Move SignTypedData to utils package
This commit is contained in:
parent
07926ded6e
commit
2a82ff48c0
@ -14,3 +14,15 @@ export const constants = {
|
|||||||
INFINITE_TIMESTAMP_SEC: new BigNumber(2524604400), // Close to infinite
|
INFINITE_TIMESTAMP_SEC: new BigNumber(2524604400), // Close to infinite
|
||||||
ZERO_AMOUNT: new BigNumber(0),
|
ZERO_AMOUNT: new BigNumber(0),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const EIP712_DOMAIN_NAME = '0x Protocol';
|
||||||
|
export const EIP712_DOMAIN_VERSION = '2';
|
||||||
|
|
||||||
|
export const EIP712_DOMAIN_SCHEMA = {
|
||||||
|
name: 'EIP712Domain',
|
||||||
|
parameters: [
|
||||||
|
{ name: 'name', type: 'string' },
|
||||||
|
{ name: 'version', type: 'string ' },
|
||||||
|
{ name: 'verifyingContract', type: 'address' },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
@ -1,109 +0,0 @@
|
|||||||
import ethUtil = require('ethereumjs-util');
|
|
||||||
import * as _ from 'lodash';
|
|
||||||
|
|
||||||
import { crypto } from './crypto';
|
|
||||||
import { EIP712Schema, EIP712Types } from './types';
|
|
||||||
|
|
||||||
const EIP191_PREFIX = '\x19\x01';
|
|
||||||
const EIP712_VALUE_LENGTH = 32;
|
|
||||||
export const EIP712_DOMAIN_NAME = '0x Protocol';
|
|
||||||
export const EIP712_DOMAIN_VERSION = '2';
|
|
||||||
|
|
||||||
export const EIP712_DOMAIN_SCHEMA: EIP712Schema = {
|
|
||||||
name: 'EIP712Domain',
|
|
||||||
parameters: [
|
|
||||||
{ name: 'name', type: EIP712Types.String },
|
|
||||||
{ name: 'version', type: EIP712Types.String },
|
|
||||||
{ name: 'verifyingContract', type: EIP712Types.Address },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const eip712Utils = {
|
|
||||||
/**
|
|
||||||
* Compiles the EIP712Schema and returns the hash of the schema.
|
|
||||||
* @param schema The EIP712 schema.
|
|
||||||
* @return The hash of the compiled schema
|
|
||||||
*/
|
|
||||||
compileSchema(schema: EIP712Schema): Buffer {
|
|
||||||
const eip712Schema = eip712Utils._encodeType(schema);
|
|
||||||
const eip712SchemaHashBuffer = crypto.solSHA3([eip712Schema]);
|
|
||||||
return eip712SchemaHashBuffer;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Merges the EIP712 hash of a struct with the DomainSeparator for 0x v2.
|
|
||||||
* @param hashStruct the EIP712 hash of a struct
|
|
||||||
* @param contractAddress the exchange contract address
|
|
||||||
* @return The hash of an EIP712 message with domain separator prefixed
|
|
||||||
*/
|
|
||||||
createEIP712Message(hashStruct: Buffer, contractAddress: string): Buffer {
|
|
||||||
const domainSeparatorHashBuffer = eip712Utils._getDomainSeparatorHashBuffer(contractAddress);
|
|
||||||
const messageBuff = crypto.solSHA3([EIP191_PREFIX, domainSeparatorHashBuffer, hashStruct]);
|
|
||||||
return messageBuff;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Pad an address to 32 bytes
|
|
||||||
* @param address Address to pad
|
|
||||||
* @return padded address
|
|
||||||
*/
|
|
||||||
pad32Address(address: string): Buffer {
|
|
||||||
const addressBuffer = ethUtil.toBuffer(address);
|
|
||||||
const addressPadded = eip712Utils.pad32Buffer(addressBuffer);
|
|
||||||
return addressPadded;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Pad an buffer to 32 bytes
|
|
||||||
* @param buffer Address to pad
|
|
||||||
* @return padded buffer
|
|
||||||
*/
|
|
||||||
pad32Buffer(buffer: Buffer): Buffer {
|
|
||||||
const bufferPadded = ethUtil.setLengthLeft(buffer, EIP712_VALUE_LENGTH);
|
|
||||||
return bufferPadded;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Hash together a EIP712 schema with the corresponding data
|
|
||||||
* @param schema EIP712-compliant schema
|
|
||||||
* @param data Data the complies to the schema
|
|
||||||
* @return A buffer containing the SHA256 hash of the schema and encoded data
|
|
||||||
*/
|
|
||||||
structHash(schema: EIP712Schema, data: { [key: string]: any }): Buffer {
|
|
||||||
const encodedData = eip712Utils._encodeData(schema, data);
|
|
||||||
const schemaHash = eip712Utils.compileSchema(schema);
|
|
||||||
const hashBuffer = crypto.solSHA3([schemaHash, ...encodedData]);
|
|
||||||
return hashBuffer;
|
|
||||||
},
|
|
||||||
_getDomainSeparatorSchemaBuffer(): Buffer {
|
|
||||||
return eip712Utils.compileSchema(EIP712_DOMAIN_SCHEMA);
|
|
||||||
},
|
|
||||||
_getDomainSeparatorHashBuffer(exchangeAddress: string): Buffer {
|
|
||||||
const domainSeparatorSchemaBuffer = eip712Utils._getDomainSeparatorSchemaBuffer();
|
|
||||||
const encodedData = eip712Utils._encodeData(EIP712_DOMAIN_SCHEMA, {
|
|
||||||
name: EIP712_DOMAIN_NAME,
|
|
||||||
version: EIP712_DOMAIN_VERSION,
|
|
||||||
verifyingContract: exchangeAddress,
|
|
||||||
});
|
|
||||||
const domainSeparatorHashBuff2 = crypto.solSHA3([domainSeparatorSchemaBuffer, ...encodedData]);
|
|
||||||
return domainSeparatorHashBuff2;
|
|
||||||
},
|
|
||||||
_encodeType(schema: EIP712Schema): string {
|
|
||||||
const namedTypes = _.map(schema.parameters, ({ name, type }) => `${type} ${name}`);
|
|
||||||
const namedTypesJoined = namedTypes.join(',');
|
|
||||||
const encodedType = `${schema.name}(${namedTypesJoined})`;
|
|
||||||
return encodedType;
|
|
||||||
},
|
|
||||||
_encodeData(schema: EIP712Schema, data: { [key: string]: any }): any {
|
|
||||||
const encodedValues = [];
|
|
||||||
for (const parameter of schema.parameters) {
|
|
||||||
const value = data[parameter.name];
|
|
||||||
if (parameter.type === EIP712Types.String || parameter.type === EIP712Types.Bytes) {
|
|
||||||
encodedValues.push(crypto.solSHA3([ethUtil.toBuffer(value)]));
|
|
||||||
} else if (parameter.type === EIP712Types.Uint256) {
|
|
||||||
encodedValues.push(value);
|
|
||||||
} else if (parameter.type === EIP712Types.Address) {
|
|
||||||
encodedValues.push(eip712Utils.pad32Address(value));
|
|
||||||
} else {
|
|
||||||
throw new Error(`Unable to encode ${parameter.type}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return encodedValues;
|
|
||||||
},
|
|
||||||
};
|
|
@ -2,7 +2,6 @@ export { orderHashUtils } from './order_hash';
|
|||||||
export { signatureUtils } from './signature_utils';
|
export { signatureUtils } from './signature_utils';
|
||||||
export { generatePseudoRandomSalt } from './salt';
|
export { generatePseudoRandomSalt } from './salt';
|
||||||
export { assetDataUtils } from './asset_data_utils';
|
export { assetDataUtils } from './asset_data_utils';
|
||||||
export { eip712Utils } from './eip712_utils';
|
|
||||||
export { marketUtils } from './market_utils';
|
export { marketUtils } from './market_utils';
|
||||||
export { rateUtils } from './rate_utils';
|
export { rateUtils } from './rate_utils';
|
||||||
export { sortingUtils } from './sorting_utils';
|
export { sortingUtils } from './sorting_utils';
|
||||||
@ -36,9 +35,6 @@ export {
|
|||||||
} from '@0xproject/types';
|
} from '@0xproject/types';
|
||||||
export {
|
export {
|
||||||
OrderError,
|
OrderError,
|
||||||
EIP712Parameter,
|
|
||||||
EIP712Schema,
|
|
||||||
EIP712Types,
|
|
||||||
TradeSide,
|
TradeSide,
|
||||||
TransferType,
|
TransferType,
|
||||||
FindFeeOrdersThatCoverFeesForTargetOrdersOpts,
|
FindFeeOrdersThatCoverFeesForTargetOrdersOpts,
|
||||||
|
@ -1,28 +1,28 @@
|
|||||||
import { schemas, SchemaValidator } from '@0xproject/json-schemas';
|
import { schemas, SchemaValidator } from '@0xproject/json-schemas';
|
||||||
import { Order, SignedOrder } from '@0xproject/types';
|
import { Order, SignedOrder } from '@0xproject/types';
|
||||||
|
import { signTypedDataUtils } from '@0xproject/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { assert } from './assert';
|
import { assert } from './assert';
|
||||||
import { eip712Utils } from './eip712_utils';
|
import { EIP712_DOMAIN_NAME, EIP712_DOMAIN_SCHEMA, EIP712_DOMAIN_VERSION } from './constants';
|
||||||
import { EIP712Schema, EIP712Types } from './types';
|
|
||||||
|
|
||||||
const INVALID_TAKER_FORMAT = 'instance.takerAddress is not of a type(s) string';
|
const INVALID_TAKER_FORMAT = 'instance.takerAddress is not of a type(s) string';
|
||||||
|
|
||||||
export const EIP712_ORDER_SCHEMA: EIP712Schema = {
|
export const EIP712_ORDER_SCHEMA = {
|
||||||
name: 'Order',
|
name: 'Order',
|
||||||
parameters: [
|
parameters: [
|
||||||
{ name: 'makerAddress', type: EIP712Types.Address },
|
{ name: 'makerAddress', type: 'address' },
|
||||||
{ name: 'takerAddress', type: EIP712Types.Address },
|
{ name: 'takerAddress', type: 'address' },
|
||||||
{ name: 'feeRecipientAddress', type: EIP712Types.Address },
|
{ name: 'feeRecipientAddress', type: 'address' },
|
||||||
{ name: 'senderAddress', type: EIP712Types.Address },
|
{ name: 'senderAddress', type: 'address' },
|
||||||
{ name: 'makerAssetAmount', type: EIP712Types.Uint256 },
|
{ name: 'makerAssetAmount', type: 'uint256' },
|
||||||
{ name: 'takerAssetAmount', type: EIP712Types.Uint256 },
|
{ name: 'takerAssetAmount', type: 'uint256' },
|
||||||
{ name: 'makerFee', type: EIP712Types.Uint256 },
|
{ name: 'makerFee', type: 'uint256' },
|
||||||
{ name: 'takerFee', type: EIP712Types.Uint256 },
|
{ name: 'takerFee', type: 'uint256' },
|
||||||
{ name: 'expirationTimeSeconds', type: EIP712Types.Uint256 },
|
{ name: 'expirationTimeSeconds', type: 'uint256' },
|
||||||
{ name: 'salt', type: EIP712Types.Uint256 },
|
{ name: 'salt', type: 'uint256' },
|
||||||
{ name: 'makerAssetData', type: EIP712Types.Bytes },
|
{ name: 'makerAssetData', type: 'bytes' },
|
||||||
{ name: 'takerAssetData', type: EIP712Types.Bytes },
|
{ name: 'takerAssetData', type: 'bytes' },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -69,11 +69,23 @@ export const orderHashUtils = {
|
|||||||
* @return The resulting orderHash from hashing the supplied order as a Buffer
|
* @return The resulting orderHash from hashing the supplied order as a Buffer
|
||||||
*/
|
*/
|
||||||
getOrderHashBuffer(order: SignedOrder | Order): Buffer {
|
getOrderHashBuffer(order: SignedOrder | Order): Buffer {
|
||||||
const orderParamsHashBuff = eip712Utils.structHash(EIP712_ORDER_SCHEMA, order);
|
const normalizedOrder = _.mapValues(order, value => {
|
||||||
const orderHashBuff = eip712Utils.createEIP712Message(orderParamsHashBuff, order.exchangeAddress);
|
return _.isObject(value) ? value.toString() : value;
|
||||||
|
});
|
||||||
|
const typedData = {
|
||||||
|
types: {
|
||||||
|
EIP712Domain: EIP712_DOMAIN_SCHEMA.parameters,
|
||||||
|
Order: EIP712_ORDER_SCHEMA.parameters,
|
||||||
|
},
|
||||||
|
domain: {
|
||||||
|
name: EIP712_DOMAIN_NAME,
|
||||||
|
version: EIP712_DOMAIN_VERSION,
|
||||||
|
verifyingContract: order.exchangeAddress,
|
||||||
|
},
|
||||||
|
message: normalizedOrder,
|
||||||
|
primaryType: EIP712_ORDER_SCHEMA.name,
|
||||||
|
};
|
||||||
|
const orderHashBuff = signTypedDataUtils.signTypedDataHash(typedData);
|
||||||
return orderHashBuff;
|
return orderHashBuff;
|
||||||
},
|
},
|
||||||
_getOrderSchemaBuffer(): Buffer {
|
|
||||||
return eip712Utils.compileSchema(EIP712_ORDER_SCHEMA);
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,7 @@ import * as _ from 'lodash';
|
|||||||
|
|
||||||
import { artifacts } from './artifacts';
|
import { artifacts } from './artifacts';
|
||||||
import { assert } from './assert';
|
import { assert } from './assert';
|
||||||
import { EIP712_DOMAIN_NAME, EIP712_DOMAIN_SCHEMA, EIP712_DOMAIN_VERSION } from './eip712_utils';
|
import { EIP712_DOMAIN_NAME, EIP712_DOMAIN_SCHEMA, EIP712_DOMAIN_VERSION } from './constants';
|
||||||
import { ExchangeContract } from './generated_contract_wrappers/exchange';
|
import { ExchangeContract } from './generated_contract_wrappers/exchange';
|
||||||
import { IValidatorContract } from './generated_contract_wrappers/i_validator';
|
import { IValidatorContract } from './generated_contract_wrappers/i_validator';
|
||||||
import { IWalletContract } from './generated_contract_wrappers/i_wallet';
|
import { IWalletContract } from './generated_contract_wrappers/i_wallet';
|
||||||
|
@ -14,24 +14,6 @@ export enum TransferType {
|
|||||||
Fee = 'fee',
|
Fee = 'fee',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EIP712Parameter {
|
|
||||||
name: string;
|
|
||||||
type: EIP712Types;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface EIP712Schema {
|
|
||||||
name: string;
|
|
||||||
parameters: EIP712Parameter[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum EIP712Types {
|
|
||||||
Address = 'address',
|
|
||||||
Bytes = 'bytes',
|
|
||||||
Bytes32 = 'bytes32',
|
|
||||||
String = 'string',
|
|
||||||
Uint256 = 'uint256',
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CreateOrderOpts {
|
export interface CreateOrderOpts {
|
||||||
takerAddress?: string;
|
takerAddress?: string;
|
||||||
senderAddress?: string;
|
senderAddress?: string;
|
||||||
|
@ -9,3 +9,4 @@ export { abiUtils } from './abi_utils';
|
|||||||
export { NULL_BYTES } from './constants';
|
export { NULL_BYTES } from './constants';
|
||||||
export { errorUtils } from './error_utils';
|
export { errorUtils } from './error_utils';
|
||||||
export { fetchAsync } from './fetch_async';
|
export { fetchAsync } from './fetch_async';
|
||||||
|
export { signTypedDataUtils } from './sign_typed_data_utils';
|
||||||
|
81
packages/utils/src/sign_typed_data_utils.ts
Normal file
81
packages/utils/src/sign_typed_data_utils.ts
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const signTypedDataUtils = {
|
||||||
|
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)) {
|
||||||
|
if (!found.includes(dep)) {
|
||||||
|
found.push(dep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
},
|
||||||
|
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 = '';
|
||||||
|
for (const dep of deps) {
|
||||||
|
result += `${dep}(${types[dep].map(({ name, type }) => `${type} ${name}`).join(',')})`;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
encodeData(primaryType: string, data: any, types: EIP712Types): string {
|
||||||
|
const encodedTypes = ['bytes32'];
|
||||||
|
const encodedValues = [signTypedDataUtils.typeHash(primaryType, types)];
|
||||||
|
for (const field of types[primaryType]) {
|
||||||
|
let value = data[field.name];
|
||||||
|
if (field.type === 'string' || field.type === 'bytes') {
|
||||||
|
value = ethUtil.sha3(value);
|
||||||
|
encodedTypes.push('bytes32');
|
||||||
|
encodedValues.push(value);
|
||||||
|
} else if (types[field.type] !== undefined) {
|
||||||
|
encodedTypes.push('bytes32');
|
||||||
|
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');
|
||||||
|
} else {
|
||||||
|
encodedTypes.push(field.type);
|
||||||
|
encodedValues.push(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ethers.utils.defaultAbiCoder.encode(encodedTypes, encodedValues);
|
||||||
|
},
|
||||||
|
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),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
};
|
107
packages/utils/test/sign_typed_data_utils_test.ts
Normal file
107
packages/utils/test/sign_typed_data_utils_test.ts
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
import * as chai from 'chai';
|
||||||
|
import 'mocha';
|
||||||
|
|
||||||
|
import { signTypedDataUtils } from '../src/sign_typed_data_utils';
|
||||||
|
|
||||||
|
const expect = chai.expect;
|
||||||
|
|
||||||
|
describe('signTypedDataUtils', () => {
|
||||||
|
describe('signTypedDataHash', () => {
|
||||||
|
const signTypedDataHashHex = '0x55eaa6ec02f3224d30873577e9ddd069a288c16d6fb407210eecbc501fa76692';
|
||||||
|
const signTypedData = {
|
||||||
|
types: {
|
||||||
|
EIP712Domain: [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'version',
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'verifyingContract',
|
||||||
|
type: 'address',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Order: [
|
||||||
|
{
|
||||||
|
name: 'makerAddress',
|
||||||
|
type: 'address',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'takerAddress',
|
||||||
|
type: 'address',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'feeRecipientAddress',
|
||||||
|
type: 'address',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'senderAddress',
|
||||||
|
type: 'address',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'makerAssetAmount',
|
||||||
|
type: 'uint256',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'takerAssetAmount',
|
||||||
|
type: 'uint256',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'makerFee',
|
||||||
|
type: 'uint256',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'takerFee',
|
||||||
|
type: 'uint256',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'expirationTimeSeconds',
|
||||||
|
type: 'uint256',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'salt',
|
||||||
|
type: 'uint256',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'makerAssetData',
|
||||||
|
type: 'bytes',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'takerAssetData',
|
||||||
|
type: 'bytes',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
domain: {
|
||||||
|
name: '0x Protocol',
|
||||||
|
version: '2',
|
||||||
|
verifyingContract: '0x0000000000000000000000000000000000000000',
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
makerAddress: '0x0000000000000000000000000000000000000000',
|
||||||
|
takerAddress: '0x0000000000000000000000000000000000000000',
|
||||||
|
makerAssetAmount: '1000000000000000000',
|
||||||
|
takerAssetAmount: '1000000000000000000',
|
||||||
|
expirationTimeSeconds: '12345',
|
||||||
|
makerFee: '0',
|
||||||
|
takerFee: '0',
|
||||||
|
feeRecipientAddress: '0x0000000000000000000000000000000000000000',
|
||||||
|
senderAddress: '0x0000000000000000000000000000000000000000',
|
||||||
|
salt: '12345',
|
||||||
|
makerAssetData: '0x0000000000000000000000000000000000000000',
|
||||||
|
takerAssetData: '0x0000000000000000000000000000000000000000',
|
||||||
|
exchangeAddress: '0x0000000000000000000000000000000000000000',
|
||||||
|
},
|
||||||
|
primaryType: 'Order',
|
||||||
|
};
|
||||||
|
it.only('creates a known hash of the sign typed data', () => {
|
||||||
|
const hash = signTypedDataUtils.signTypedDataHash(signTypedData).toString('hex');
|
||||||
|
const hashHex = `0x${hash}`;
|
||||||
|
expect(hashHex).to.be.eq(signTypedDataHashHex);
|
||||||
|
console.log(hash);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user