aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeonid <logvinov.leon@gmail.com>2017-05-26 18:41:51 +0800
committerGitHub <noreply@github.com>2017-05-26 18:41:51 +0800
commitf338c68f126cba0f1b49c2928f276158b64d8ee7 (patch)
tree2d90199df90974be6a596eace3503281889c29f4
parentf7b8378a6eb4b4c6c3461ff677723869c67a4753 (diff)
parent3195741ebcfc95f4622aebcdc23fc5b8630efe39 (diff)
downloaddexon-sol-tools-f338c68f126cba0f1b49c2928f276158b64d8ee7.tar
dexon-sol-tools-f338c68f126cba0f1b49c2928f276158b64d8ee7.tar.gz
dexon-sol-tools-f338c68f126cba0f1b49c2928f276158b64d8ee7.tar.bz2
dexon-sol-tools-f338c68f126cba0f1b49c2928f276158b64d8ee7.tar.lz
dexon-sol-tools-f338c68f126cba0f1b49c2928f276158b64d8ee7.tar.xz
dexon-sol-tools-f338c68f126cba0f1b49c2928f276158b64d8ee7.tar.zst
dexon-sol-tools-f338c68f126cba0f1b49c2928f276158b64d8ee7.zip
Merge pull request #13 from 0xProject/getOrderHash
Port getOrderHash and write tests for it
-rw-r--r--package.json2
-rw-r--r--src/ts/0x.js.ts56
-rw-r--r--src/ts/globals.d.ts5
-rw-r--r--src/ts/types.ts17
-rw-r--r--src/ts/utils/constants.ts3
-rw-r--r--test/0x.js.ts38
6 files changed, 120 insertions, 1 deletions
diff --git a/package.json b/package.json
index 557d6eeff..e6281afae 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/src/ts/0x.js.ts b/src/ts/0x.js.ts
index ead1f56df..ba922d3db 100644
--- a/src/ts/0x.js.ts
+++ b/src/ts/0x.js.ts
@@ -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
@@ -17,6 +21,48 @@ const MAX_DIGITS_IN_UNSIGNED_256_INT = 78;
export class ZeroEx {
/**
+ * Computes the orderHash given the order parameters and returns it as a hex encoded string.
+ */
+ public static getOrderHashHex(exchangeContractAddr: string, makerAddr: string, takerAddr: string,
+ tokenMAddress: string, tokenTAddress: string, feeRecipient: string,
+ valueM: BigNumber.BigNumber, valueT: BigNumber.BigNumber,
+ makerFee: BigNumber.BigNumber, takerFee: BigNumber.BigNumber,
+ expiration: BigNumber.BigNumber, salt: BigNumber.BigNumber): string {
+ takerAddr = _.isEmpty(takerAddr) ? constants.NULL_ADDRESS : takerAddr ;
+ assert.isETHAddressHex('exchangeContractAddr', exchangeContractAddr);
+ assert.isETHAddressHex('makerAddr', makerAddr);
+ assert.isETHAddressHex('takerAddr', takerAddr);
+ assert.isETHAddressHex('tokenMAddress', tokenMAddress);
+ assert.isETHAddressHex('tokenTAddress', tokenTAddress);
+ assert.isETHAddressHex('feeRecipient', feeRecipient);
+ assert.isBigNumber('valueM', valueM);
+ assert.isBigNumber('valueT', valueT);
+ 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: tokenMAddress, type: SolidityTypes.address},
+ {value: tokenTAddress, type: SolidityTypes.address},
+ {value: feeRecipient, type: SolidityTypes.address},
+ {value: this.bigNumberToBN(valueM), type: SolidityTypes.uint256},
+ {value: this.bigNumberToBN(valueT), type: SolidityTypes.uint256},
+ {value: this.bigNumberToBN(makerFee), type: SolidityTypes.uint256},
+ {value: this.bigNumberToBN(takerFee), type: SolidityTypes.uint256},
+ {value: this.bigNumberToBN(expiration), type: SolidityTypes.uint256},
+ {value: this.bigNumberToBN(salt), type: SolidityTypes.uint256},
+ ];
+ const types = _.map(orderParts, o => o.type);
+ const values = _.map(orderParts, o => o.value);
+ const hashBuff = ethABI.soliditySHA3(types, values);
+ const hashHex = ethUtil.bufferToHex(hashBuff);
+ return hashHex;
+ }
+ /**
* Verifies that the elliptic curve signature `signature` was generated
* by signing `data` with the private key corresponding to the `signerAddressHex` address.
*/
@@ -83,4 +129,14 @@ export class ZeroEx {
const baseUnitAmount = amount.times(unit);
return baseUnitAmount;
}
+
+ /**
+ * Converts BigNumber instance to BN
+ * The only we convert to BN is to remain compatible with `ethABI. soliditySHA3 ` that
+ * expects values of Solidity type `uint` to be of type `BN`.
+ * We do not use BN anywhere else in the codebase.
+ */
+ private static bigNumberToBN(value: BigNumber.BigNumber) {
+ return new BN(value.toString(), 10);
+ }
}
diff --git a/src/ts/globals.d.ts b/src/ts/globals.d.ts
index 796812c87..99baf593f 100644
--- a/src/ts/globals.d.ts
+++ b/src/ts/globals.d.ts
@@ -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;
+}
diff --git a/src/ts/types.ts b/src/ts/types.ts
new file mode 100644
index 000000000..04902cca6
--- /dev/null
+++ b/src/ts/types.ts
@@ -0,0 +1,17 @@
+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',
+]);
+export type SolidityTypes = keyof typeof SolidityTypes;
diff --git a/src/ts/utils/constants.ts b/src/ts/utils/constants.ts
new file mode 100644
index 000000000..60af7b674
--- /dev/null
+++ b/src/ts/utils/constants.ts
@@ -0,0 +1,3 @@
+export const constants = {
+ NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
+}
diff --git a/test/0x.js.ts b/test/0x.js.ts
index a913fd6b5..d5b2015fb 100644
--- a/test/0x.js.ts
+++ b/test/0x.js.ts
@@ -3,12 +3,50 @@ 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', () => {
+ const ORDER_HASH = '0x103a5e97dab5dbeb8f385636f86a7d1e458a7ccbe1bd194727f0b2f85ab116c7';
+ it('defaults takerAddress to NULL address', () => {
+ const orderHash = ZeroEx.getOrderHashHex(
+ 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(ORDER_HASH);
+ });
+ it('calculates the order hash', () => {
+ const orderHash = ZeroEx.getOrderHashHex(
+ 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(ORDER_HASH);
+ });
+ });
describe('#isValidSignature', () => {
// This test data was borrowed from the JSON RPC documentation
// Source: https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign