diff options
Diffstat (limited to 'packages/utils')
-rw-r--r-- | packages/utils/src/sign_typed_data_utils.ts | 60 | ||||
-rw-r--r-- | packages/utils/test/sign_typed_data_utils_test.ts | 45 |
2 files changed, 65 insertions, 40 deletions
diff --git a/packages/utils/src/sign_typed_data_utils.ts b/packages/utils/src/sign_typed_data_utils.ts index 902d8530c..b72fd099b 100644 --- a/packages/utils/src/sign_typed_data_utils.ts +++ b/packages/utils/src/sign_typed_data_utils.ts @@ -1,29 +1,30 @@ import * as ethUtil from 'ethereumjs-util'; import * as ethers from 'ethers'; -export interface EIP712Parameter { - name: string; - type: string; -} - -export interface EIP712Types { - [key: string]: EIP712Parameter[]; -} -export interface EIP712TypedData { - types: EIP712Types; - domain: any; - message: any; - primaryType: string; -} +import { EIP712TypedData, EIP712Types } from '@0xproject/types'; export const signTypedDataUtils = { - findDependencies(primaryType: string, types: EIP712Types, found: string[] = []): string[] { + /** + * Computes the Sign Typed Data hash + * @param typedData An object that conforms to the EIP712TypedData interface + * @return A Buffer containing the hash of the sign typed data. + */ + signTypedDataHash(typedData: EIP712TypedData): Buffer { + return ethUtil.sha3( + Buffer.concat([ + Buffer.from('1901', 'hex'), + signTypedDataUtils._structHash('EIP712Domain', typedData.domain, typedData.types), + signTypedDataUtils._structHash(typedData.primaryType, typedData.message, typedData.types), + ]), + ); + }, + _findDependencies(primaryType: string, types: EIP712Types, found: string[] = []): string[] { if (found.includes(primaryType) || types[primaryType] === undefined) { return found; } found.push(primaryType); for (const field of types[primaryType]) { - for (const dep of signTypedDataUtils.findDependencies(field.type, types, found)) { + for (const dep of signTypedDataUtils._findDependencies(field.type, types, found)) { if (!found.includes(dep)) { found.push(dep); } @@ -31,8 +32,8 @@ export const signTypedDataUtils = { } return found; }, - encodeType(primaryType: string, types: EIP712Types): string { - let deps = signTypedDataUtils.findDependencies(primaryType, types); + _encodeType(primaryType: string, types: EIP712Types): string { + let deps = signTypedDataUtils._findDependencies(primaryType, types); deps = deps.filter(d => d !== primaryType); deps = [primaryType].concat(deps.sort()); let result = ''; @@ -41,9 +42,9 @@ export const signTypedDataUtils = { } return result; }, - encodeData(primaryType: string, data: any, types: EIP712Types): string { + _encodeData(primaryType: string, data: any, types: EIP712Types): string { const encodedTypes = ['bytes32']; - const encodedValues = [signTypedDataUtils.typeHash(primaryType, types)]; + const encodedValues = [signTypedDataUtils._typeHash(primaryType, types)]; for (const field of types[primaryType]) { let value = data[field.name]; if (field.type === 'string' || field.type === 'bytes') { @@ -52,7 +53,7 @@ export const signTypedDataUtils = { encodedValues.push(value); } else if (types[field.type] !== undefined) { encodedTypes.push('bytes32'); - value = ethUtil.sha3(signTypedDataUtils.encodeData(field.type, value, types)); + value = ethUtil.sha3(signTypedDataUtils._encodeData(field.type, value, types)); encodedValues.push(value); } else if (field.type.lastIndexOf(']') === field.type.length - 1) { throw new Error('Arrays currently unimplemented in encodeData'); @@ -63,19 +64,10 @@ export const signTypedDataUtils = { } return ethers.utils.defaultAbiCoder.encode(encodedTypes, encodedValues); }, - typeHash(primaryType: string, types: EIP712Types): Buffer { - return ethUtil.sha3(signTypedDataUtils.encodeType(primaryType, types)); + _typeHash(primaryType: string, types: EIP712Types): Buffer { + return ethUtil.sha3(signTypedDataUtils._encodeType(primaryType, types)); }, - structHash(primaryType: string, data: any, types: EIP712Types): Buffer { - return ethUtil.sha3(signTypedDataUtils.encodeData(primaryType, data, types)); - }, - signTypedDataHash(typedData: EIP712TypedData): Buffer { - return ethUtil.sha3( - Buffer.concat([ - Buffer.from('1901', 'hex'), - signTypedDataUtils.structHash('EIP712Domain', typedData.domain, typedData.types), - signTypedDataUtils.structHash(typedData.primaryType, typedData.message, typedData.types), - ]), - ); + _structHash(primaryType: string, data: any, types: EIP712Types): Buffer { + return ethUtil.sha3(signTypedDataUtils._encodeData(primaryType, data, types)); }, }; diff --git a/packages/utils/test/sign_typed_data_utils_test.ts b/packages/utils/test/sign_typed_data_utils_test.ts index b21ffefa0..e1cb4f6e1 100644 --- a/packages/utils/test/sign_typed_data_utils_test.ts +++ b/packages/utils/test/sign_typed_data_utils_test.ts @@ -7,8 +7,37 @@ const expect = chai.expect; describe('signTypedDataUtils', () => { describe('signTypedDataHash', () => { - const signTypedDataHashHex = '0x55eaa6ec02f3224d30873577e9ddd069a288c16d6fb407210eecbc501fa76692'; - const signTypedData = { + const simpleSignTypedDataHashHex = '0xb460d69ca60383293877cd765c0f97bd832d66bca720f7e32222ce1118832493'; + const simpleSignTypedData = { + types: { + EIP712Domain: [ + { + name: 'name', + type: 'string', + }, + ], + Test: [ + { + name: 'testAddress', + type: 'address', + }, + { + name: 'testNumber', + type: 'uint256', + }, + ], + }, + domain: { + name: 'Test', + }, + message: { + testAddress: '0x0000000000000000000000000000000000000000', + testNumber: '12345', + }, + primaryType: 'Test', + }; + const orderSignTypedDataHashHex = '0x55eaa6ec02f3224d30873577e9ddd069a288c16d6fb407210eecbc501fa76692'; + const orderSignTypedData = { types: { EIP712Domain: [ { @@ -97,11 +126,15 @@ describe('signTypedDataUtils', () => { }, primaryType: 'Order', }; - it.only('creates a known hash of the sign typed data', () => { - const hash = signTypedDataUtils.signTypedDataHash(signTypedData).toString('hex'); + it('creates a hash of the test sign typed data', () => { + const hash = signTypedDataUtils.signTypedDataHash(simpleSignTypedData).toString('hex'); + const hashHex = `0x${hash}`; + expect(hashHex).to.be.eq(simpleSignTypedDataHashHex); + }); + it('creates a hash of the order sign typed data', () => { + const hash = signTypedDataUtils.signTypedDataHash(orderSignTypedData).toString('hex'); const hashHex = `0x${hash}`; - expect(hashHex).to.be.eq(signTypedDataHashHex); - console.log(hash); + expect(hashHex).to.be.eq(orderSignTypedDataHashHex); }); }); }); |