eip712.js 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. const ethSigUtil = require('eth-sig-util');
  2. const keccak256 = require('keccak256');
  3. const EIP712Domain = [
  4. { name: 'name', type: 'string' },
  5. { name: 'version', type: 'string' },
  6. { name: 'chainId', type: 'uint256' },
  7. { name: 'verifyingContract', type: 'address' },
  8. { name: 'salt', type: 'bytes32' },
  9. ];
  10. const Permit = [
  11. { name: 'owner', type: 'address' },
  12. { name: 'spender', type: 'address' },
  13. { name: 'value', type: 'uint256' },
  14. { name: 'nonce', type: 'uint256' },
  15. { name: 'deadline', type: 'uint256' },
  16. ];
  17. function bufferToHexString(buffer) {
  18. return '0x' + buffer.toString('hex');
  19. }
  20. function hexStringToBuffer(hexstr) {
  21. return Buffer.from(hexstr.replace(/^0x/, ''), 'hex');
  22. }
  23. async function getDomain(contract) {
  24. const { fields, name, version, chainId, verifyingContract, salt, extensions } = await contract.eip712Domain();
  25. if (extensions.length > 0) {
  26. throw Error('Extensions not implemented');
  27. }
  28. const domain = { name, version, chainId, verifyingContract, salt };
  29. for (const [i, { name }] of EIP712Domain.entries()) {
  30. if (!(fields & (1 << i))) {
  31. delete domain[name];
  32. }
  33. }
  34. return domain;
  35. }
  36. function domainType(domain) {
  37. return EIP712Domain.filter(({ name }) => domain[name] !== undefined);
  38. }
  39. function domainSeparator(domain) {
  40. return bufferToHexString(
  41. ethSigUtil.TypedDataUtils.hashStruct('EIP712Domain', domain, { EIP712Domain: domainType(domain) }),
  42. );
  43. }
  44. function hashTypedData(domain, structHash) {
  45. return bufferToHexString(
  46. keccak256(Buffer.concat(['0x1901', domainSeparator(domain), structHash].map(str => hexStringToBuffer(str)))),
  47. );
  48. }
  49. module.exports = {
  50. Permit,
  51. getDomain,
  52. domainType,
  53. domainSeparator,
  54. hashTypedData,
  55. };