Port getOrderHash

This commit is contained in:
Leonid Logvinov 2017-05-25 17:24:29 +02:00
parent f7b8378a6e
commit f2f39d9eb2
No known key found for this signature in database
GPG Key ID: 0DD294BFDE8C95D4
6 changed files with 107 additions and 1 deletions

View File

@ -35,7 +35,6 @@
"@types/chai": "^3.5.2",
"@types/mocha": "^2.2.41",
"@types/node": "^7.0.22",
"@types/lodash": "^4.14.64",
"awesome-typescript-loader": "^3.1.3",
"bignumber.js": "^4.0.2",
"chai": "^3.5.0",
@ -55,6 +54,7 @@
},
"dependencies": {
"bignumber.js": "^4.0.2",
"ethereumjs-abi": "^0.6.4",
"ethereumjs-util": "^5.1.1",
"jsonschema": "^1.1.1",
"lodash": "^4.17.4",

View File

@ -1,8 +1,12 @@
import * as BigNumber from 'bignumber.js';
import * as BN from 'bn.js';
import * as ethUtil from 'ethereumjs-util';
import * as ethABI from 'ethereumjs-abi';
import * as _ from 'lodash';
import {constants} from './utils/constants';
import {assert} from './utils/assert';
import {ECSignatureSchema} from './schemas/ec_signature_schema';
import {SolidityTypes} from './types';
/**
* Elliptic Curve signature
@ -16,6 +20,42 @@ export interface ECSignature {
const MAX_DIGITS_IN_UNSIGNED_256_INT = 78;
export class ZeroEx {
public static getOrderHash(exchangeContractAddr: string, makerAddr: string, takerAddr: string,
depositTokenAddr: string, receiveTokenAddr: string, feeRecipient: string,
depositAmt: BigNumber.BigNumber, receiveAmt: BigNumber.BigNumber,
makerFee: BigNumber.BigNumber, takerFee: BigNumber.BigNumber,
expiration: BigNumber.BigNumber, salt: BigNumber.BigNumber): string {
takerAddr = takerAddr !== '' ? takerAddr : constants.NULL_ADDRESS;
assert.isETHAddressHex('exchangeContractAddr', exchangeContractAddr);
assert.isETHAddressHex('makerAddr', makerAddr);
assert.isETHAddressHex('takerAddr', takerAddr);
assert.isETHAddressHex('depositTokenAddr', depositTokenAddr);
assert.isETHAddressHex('receiveTokenAddr', receiveTokenAddr);
assert.isETHAddressHex('feeRecipient', feeRecipient);
assert.isBigNumber('depositAmt', depositAmt);
assert.isBigNumber('receiveAmt', receiveAmt);
assert.isBigNumber('makerFee', makerFee);
assert.isBigNumber('takerFee', takerFee);
assert.isBigNumber('expiration', expiration);
assert.isBigNumber('salt', salt);
const orderParts = [
{value: exchangeContractAddr, type: SolidityTypes.address},
{value: makerAddr, type: SolidityTypes.address},
{value: takerAddr, type: SolidityTypes.address},
{value: depositTokenAddr, type: SolidityTypes.address},
{value: receiveTokenAddr, type: SolidityTypes.address},
{value: feeRecipient, type: SolidityTypes.address},
{value: new BN(depositAmt.toString(), 10), type: SolidityTypes.uint256},
{value: new BN(receiveAmt.toString(), 10), type: SolidityTypes.uint256},
{value: new BN(makerFee.toString(), 10), type: SolidityTypes.uint256},
{value: new BN(takerFee.toString(), 10), type: SolidityTypes.uint256},
{value: new BN(expiration.toString(), 10), type: SolidityTypes.uint256},
{value: new BN(salt.toString(), 10), type: SolidityTypes.uint256},
];
const hashBuff = ethABI.soliditySHA3(_.map(orderParts, 'type'), _.map(orderParts, 'value'));
const buffHashHex = ethUtil.bufferToHex(hashBuff);
return buffHashHex;
}
/**
* Verifies that the elliptic curve signature `signature` was generated
* by signing `data` with the private key corresponding to the `signerAddressHex` address.

5
src/ts/globals.d.ts vendored
View File

@ -1,4 +1,5 @@
declare module 'chai-bignumber';
declare module 'bn.js';
declare interface Schema {
id: string;
@ -23,3 +24,7 @@ declare module 'ethereumjs-util' {
const pubToAddress: (pubKey: string) => Buffer;
const isValidAddress: (address: string) => boolean;
}
declare module 'ethereumjs-abi' {
const soliditySHA3: (argTypes: string[], args: any) => Buffer;
}

21
src/ts/types.ts Normal file
View File

@ -0,0 +1,21 @@
import * as _ from 'lodash';
import * as BigNumber from 'bignumber.js';
// Utility function to create a K:V from a list of strings
// Adapted from: https://basarat.gitbooks.io/typescript/content/docs/types/literal-types.html
function strEnum(values: string[]): {[key: string]: string} {
return _.reduce(values, (result, key) => {
result[key] = key;
return result;
}, Object.create(null));
}
export const SolidityTypes = strEnum([
'address',
'uint256',
'uint8',
'string',
'bool',
]);
export type SolidityTypes = keyof typeof SolidityTypes;

View File

@ -0,0 +1,3 @@
export const constants = {
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
}

View File

@ -3,12 +3,49 @@ import * as chai from 'chai';
import 'mocha';
import * as BigNumber from 'bignumber.js';
import ChaiBigNumber = require('chai-bignumber');
import {constants} from '../src/ts/utils/constants';
// Use BigNumber chai add-on
chai.use(ChaiBigNumber());
const expect = chai.expect;
describe('ZeroEx library', () => {
describe('#getOrderHash', () => {
it('defaults takerAddress to NULL address', () => {
const orderHash = ZeroEx.getOrderHash(
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
'',
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
new BigNumber(0),
new BigNumber(0),
new BigNumber(0),
new BigNumber(0),
new BigNumber(0),
new BigNumber(0),
);
expect(orderHash).to.be.equal('0x103a5e97dab5dbeb8f385636f86a7d1e458a7ccbe1bd194727f0b2f85ab116c7');
});
it('calculates the order hash', () => {
const orderHash = ZeroEx.getOrderHash(
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
new BigNumber(0),
new BigNumber(0),
new BigNumber(0),
new BigNumber(0),
new BigNumber(0),
new BigNumber(0),
);
expect(orderHash).to.be.equal('0x103a5e97dab5dbeb8f385636f86a7d1e458a7ccbe1bd194727f0b2f85ab116c7');
});
});
describe('#isValidSignature', () => {
// This test data was borrowed from the JSON RPC documentation
// Source: https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign