Merge branch 'master' into implementFirstExchangeMethod

# Conflicts:
#	package.json
#	src/ts/0x.js.ts
#	src/ts/globals.d.ts
#	src/ts/types.ts
This commit is contained in:
Fabio Berger 2017-05-26 13:29:19 +02:00
commit 9f16316567
6 changed files with 110 additions and 1 deletions

View File

@ -59,6 +59,7 @@
"dependencies": { "dependencies": {
"bignumber.js": "^4.0.2", "bignumber.js": "^4.0.2",
"es6-promisify": "^5.0.0", "es6-promisify": "^5.0.0",
"ethereumjs-abi": "^0.6.4",
"ethereumjs-util": "^5.1.1", "ethereumjs-util": "^5.1.1",
"jsonschema": "^1.1.1", "jsonschema": "^1.1.1",
"lodash": "^4.17.4", "lodash": "^4.17.4",

View File

@ -1,18 +1,64 @@
import * as BigNumber from 'bignumber.js'; import * as BigNumber from 'bignumber.js';
import * as BN from 'bn.js';
import * as ethUtil from 'ethereumjs-util'; import * as ethUtil from 'ethereumjs-util';
import * as Web3 from 'web3'; import * as Web3 from 'web3';
import * as ethABI from 'ethereumjs-abi';
import * as _ from 'lodash';
import {constants} from './utils/constants';
import {assert} from './utils/assert'; import {assert} from './utils/assert';
import {Web3Wrapper} from './web3_wrapper'; import {Web3Wrapper} from './web3_wrapper';
import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper'; import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper';
import contract = require('truffle-contract'); import contract = require('truffle-contract');
import {ECSignatureSchema} from './schemas/ec_signature_schema'; import {ECSignatureSchema} from './schemas/ec_signature_schema';
import {ECSignature} from './types'; import {SolidityTypes, ECSignature} from './types';
const MAX_DIGITS_IN_UNSIGNED_256_INT = 78; const MAX_DIGITS_IN_UNSIGNED_256_INT = 78;
export class ZeroEx { export class ZeroEx {
public web3Wrapper: Web3Wrapper; public web3Wrapper: Web3Wrapper;
public exchange: ExchangeWrapper; public exchange: ExchangeWrapper;
/**
* 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 * Verifies that the elliptic curve signature `signature` was generated
* by signing `data` with the private key corresponding to the `signerAddressHex` address. * by signing `data` with the private key corresponding to the `signerAddressHex` address.
@ -80,6 +126,15 @@ export class ZeroEx {
const baseUnitAmount = amount.times(unit); const baseUnitAmount = amount.times(unit);
return baseUnitAmount; 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);
}
constructor(web3: Web3) { constructor(web3: Web3) {
this.web3Wrapper = new Web3Wrapper(web3); this.web3Wrapper = new Web3Wrapper(web3);
this.exchange = new ExchangeWrapper(this.web3Wrapper); this.exchange = new ExchangeWrapper(this.web3Wrapper);

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

@ -1,4 +1,5 @@
declare module 'chai-bignumber'; declare module 'chai-bignumber';
declare module 'bn.js';
declare interface Schema { declare interface Schema {
id: string; id: string;
@ -51,3 +52,7 @@ declare function promisify(original: any, settings?: any): ((...arg: any[]) => P
declare module 'es6-promisify' { declare module 'es6-promisify' {
export = promisify; export = promisify;
} }
declare module 'ethereumjs-abi' {
const soliditySHA3: (argTypes: string[], args: any[]) => Buffer;
}

View File

@ -1,4 +1,5 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as BigNumber from 'bignumber.js';
// Utility function to create a K:V from a list of strings // 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 // Adapted from: https://basarat.gitbooks.io/typescript/content/docs/types/literal-types.html
@ -28,3 +29,9 @@ export interface ECSignature {
export interface ExchangeContract { export interface ExchangeContract {
isValidSignature: any; isValidSignature: any;
} }
export const SolidityTypes = strEnum([
'address',
'uint256',
]);
export type SolidityTypes = keyof typeof SolidityTypes;

View File

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

View File

@ -3,12 +3,50 @@ import * as chai from 'chai';
import 'mocha'; import 'mocha';
import * as BigNumber from 'bignumber.js'; import * as BigNumber from 'bignumber.js';
import ChaiBigNumber = require('chai-bignumber'); import ChaiBigNumber = require('chai-bignumber');
import {constants} from '../src/ts/utils/constants';
// Use BigNumber chai add-on // Use BigNumber chai add-on
chai.use(ChaiBigNumber()); chai.use(ChaiBigNumber());
const expect = chai.expect; const expect = chai.expect;
describe('ZeroEx library', () => { 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', () => { describe('#isValidSignature', () => {
// This test data was borrowed from the JSON RPC documentation // This test data was borrowed from the JSON RPC documentation
// Source: https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign // Source: https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign