From bc8fc534332b5ea82f881bdd3a75773384714f4d Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 25 May 2017 19:47:11 +0200 Subject: Add initial exchange contract function, set up web3Wrapper, added types and utils --- src/ts/0x.js.ts | 22 +++++---- src/ts/contract_wrappers/contract_wrapper.ts | 51 ++++++++++++++++++++ src/ts/contract_wrappers/exchange_wrapper.ts | 37 +++++++++++++++ src/ts/globals.d.ts | 28 +++++++++++ src/ts/types.ts | 30 ++++++++++++ src/ts/utils/assert.ts | 21 ++++---- src/ts/utils/utils.ts | 7 +++ src/ts/web3_wrapper.ts | 71 ++++++++++++++++++++++++++++ 8 files changed, 249 insertions(+), 18 deletions(-) create mode 100644 src/ts/contract_wrappers/contract_wrapper.ts create mode 100644 src/ts/contract_wrappers/exchange_wrapper.ts create mode 100644 src/ts/types.ts create mode 100644 src/ts/utils/utils.ts create mode 100644 src/ts/web3_wrapper.ts (limited to 'src/ts') diff --git a/src/ts/0x.js.ts b/src/ts/0x.js.ts index ead1f56df..7025f8804 100644 --- a/src/ts/0x.js.ts +++ b/src/ts/0x.js.ts @@ -1,21 +1,21 @@ import * as BigNumber from 'bignumber.js'; import * as ethUtil from 'ethereumjs-util'; import * as _ from 'lodash'; +import Web3 from 'web3'; import {assert} from './utils/assert'; +import {utils} from './utils/utils'; +import {ZeroExError} from './types'; +import {Web3Wrapper} from './web3_wrapper'; +import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper'; +import contract = require('truffle-contract'); import {ECSignatureSchema} from './schemas/ec_signature_schema'; - -/** - * Elliptic Curve signature - */ -export interface ECSignature { - v: number; - r: string; - s: string; -} +import {ECSignature} from './types'; const MAX_DIGITS_IN_UNSIGNED_256_INT = 78; export class ZeroEx { + public web3Wrapper: Web3Wrapper; + public exchange: ContractInstance; /** * Verifies that the elliptic curve signature `signature` was generated * by signing `data` with the private key corresponding to the `signerAddressHex` address. @@ -83,4 +83,8 @@ export class ZeroEx { const baseUnitAmount = amount.times(unit); return baseUnitAmount; } + constructor(web3: Web3) { + this.web3Wrapper = new Web3Wrapper(web3); + this.exchange = new ExchangeWrapper(this.web3Wrapper); + } } diff --git a/src/ts/contract_wrappers/contract_wrapper.ts b/src/ts/contract_wrappers/contract_wrapper.ts new file mode 100644 index 000000000..72bfffe95 --- /dev/null +++ b/src/ts/contract_wrappers/contract_wrapper.ts @@ -0,0 +1,51 @@ +import * as _ from 'lodash'; +import {Web3Wrapper} from '../web3_wrapper'; +import {ZeroExError} from '../types'; +import {utils} from '../utils/utils'; + +export class ContractWrapper { + public web3Wrapper: Web3Wrapper; + constructor(web3Wrapper: Web3Wrapper) { + this.web3Wrapper = web3Wrapper; + } + // this.exchange = await this.instantiateContractIfExistsAsync(ExchangeArtifacts); + protected async instantiateContractIfExistsAsync(artifact: Artifact, address?: string): Promise { + const c = await contract(artifact); + const providerObj = this.web3Wrapper.getCurrentProvider(); + c.setProvider(providerObj); + + const networkId = await this.web3Wrapper.getNetworkIdIfExistsAsync(); + const artifactNetworkConfigs = _.isUndefined(networkId) ? undefined : artifact.networks[networkId]; + let contractAddress; + if (!_.isUndefined(address)) { + contractAddress = address; + } else if (!_.isUndefined(artifactNetworkConfigs)) { + contractAddress = artifactNetworkConfigs.address; + } + + if (!_.isUndefined(contractAddress)) { + const doesContractExist = await this.web3Wrapper.doesContractExistAtAddressAsync(contractAddress); + if (!doesContractExist) { + throw new Error(ZeroExError.CONTRACT_DOES_NOT_EXIST); + } + } + + try { + let contractInstance; + if (_.isUndefined(address)) { + contractInstance = await c.deployed(); + } else { + contractInstance = await c.at(address); + } + return contractInstance; + } catch (err) { + const errMsg = `${err}`; + utils.consoleLog(`Notice: Error encountered: ${err} ${err.stack}`); + if (_.includes(errMsg, 'not been deployed to detected network')) { + throw new Error(ZeroExError.CONTRACT_DOES_NOT_EXIST); + } else { + throw new Error(ZeroExError.UNHANDLED_ERROR); + } + } + } +} diff --git a/src/ts/contract_wrappers/exchange_wrapper.ts b/src/ts/contract_wrappers/exchange_wrapper.ts new file mode 100644 index 000000000..502a1089b --- /dev/null +++ b/src/ts/contract_wrappers/exchange_wrapper.ts @@ -0,0 +1,37 @@ +import * as _ from 'lodash'; +import {Web3Wrapper} from '../web3_wrapper'; +import {ECSignature, ZeroExError, ExchangeContract} from '../types'; +import {assert} from '../utils/assert'; +import {ContractWrapper} from './contract_wrapper'; +import * as ExchangeArtifacts from '../artifacts/Exchange.json'; +import {ECSignatureSchema} from '../schemas/ec_signature_schema'; + +export class ExchangeWrapper extends ContractWrapper { + constructor(web3Wrapper: Web3Wrapper) { + super(web3Wrapper); + } + public async isValidSignatureAsync(maker: string, ecSignature: ECSignature, dataHex: string) { + assert.isString('maker', maker); + assert.doesConformToSchema('ecSignature', ecSignature, ECSignatureSchema); + assert.isHexString('dataHex', dataHex); + + const senderAddressIfExists = this.web3Wrapper.getSenderAddressIfExistsAsync(); + assert.assert(!_.isUndefined(senderAddressIfExists), ZeroExError.USER_HAS_NO_ASSOCIATED_ADDRESSES); + + // TODO: remove any here + const contractInstance = await this.instantiateContractIfExistsAsync((ExchangeArtifacts as any)); + const exchangeInstance = contractInstance as ExchangeContract; + + const isValidSignature = await exchangeInstance.isValidSignature.call( + maker, + dataHex, + ecSignature.v, + ecSignature.r, + ecSignature.s, + { + from: senderAddressIfExists, + }, + ); + return isValidSignature; + } +} diff --git a/src/ts/globals.d.ts b/src/ts/globals.d.ts index 796812c87..04328509a 100644 --- a/src/ts/globals.d.ts +++ b/src/ts/globals.d.ts @@ -15,6 +15,13 @@ declare namespace Chai { } /* tslint:enable */ +declare module '*.json' { + const json: any; + /* tslint:disable */ + export default json; + /* tslint:enable */ +} + declare module 'ethereumjs-util' { const toBuffer: (dataHex: string) => Buffer; const hashPersonalMessage: (msg: Buffer) => Buffer; @@ -23,3 +30,24 @@ declare module 'ethereumjs-util' { const pubToAddress: (pubKey: string) => Buffer; const isValidAddress: (address: string) => boolean; } + +// truffle-contract declarations +declare interface ContractInstance {} +declare interface ContractFactory { + setProvider: (providerObj: any) => void; + deployed: () => ContractInstance; + at: (address: string) => ContractInstance; +} +declare interface Artifact { + networks: {[networkId: number]: any}; +} +declare function contract(artifacts: Artifact): ContractFactory; +declare module 'truffle-contract' { + export = contract; +} + +// es6-promisify declarations +declare function promisify(original: any, settings?: any): ((...arg: any[]) => Promise); +declare module 'es6-promisify' { + export = promisify; +} diff --git a/src/ts/types.ts b/src/ts/types.ts new file mode 100644 index 000000000..01380af02 --- /dev/null +++ b/src/ts/types.ts @@ -0,0 +1,30 @@ +import * as _ from 'lodash'; + +// 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 ZeroExError = strEnum([ + 'CONTRACT_DOES_NOT_EXIST', + 'UNHANDLED_ERROR', + 'USER_HAS_NO_ASSOCIATED_ADDRESSES', +]); +export type ZeroExError = keyof typeof ZeroExError; + +/** + * Elliptic Curve signature + */ +export interface ECSignature { + v: number; + r: string; + s: string; +} + +export interface ExchangeContract { + isValidSignature: any; +} diff --git a/src/ts/utils/assert.ts b/src/ts/utils/assert.ts index 2f52c6a3b..15d3031ff 100644 --- a/src/ts/utils/assert.ts +++ b/src/ts/utils/assert.ts @@ -1,30 +1,33 @@ import * as _ from 'lodash'; import * as BigNumber from 'bignumber.js'; -import Web3 = require('web3'); +import Web3 from 'web3'; import {SchemaValidator} from './schema_validator'; const HEX_REGEX = /^0x[0-9A-F]*$/i; export const assert = { - isBigNumber(variableName: string, value: BigNumber.BigNumber) { + isBigNumber(variableName: string, value: BigNumber.BigNumber): void { const isBigNumber = _.isObject(value) && value.isBigNumber; this.assert(isBigNumber, this.typeAssertionMessage(variableName, 'BigNumber', value)); }, - isString(variableName: string, value: string) { + isUndefined(value: any, variableName?: string): void { + this.assert(_.isUndefined(value), this.typeAssertionMessage(variableName, 'undefined', value)); + }, + isString(variableName: string, value: string): void { this.assert(_.isString(value), this.typeAssertionMessage(variableName, 'string', value)); }, - isHexString(variableName: string, value: string) { + isHexString(variableName: string, value: string): void { this.assert(_.isString(value) && HEX_REGEX.test(value), this.typeAssertionMessage(variableName, 'HexString', value)); }, - isETHAddressHex(variableName: string, value: string) { + isETHAddressHex(variableName: string, value: string): void { const web3 = new Web3(); this.assert(web3.isAddress(value), this.typeAssertionMessage(variableName, 'ETHAddressHex', value)); }, - isNumber(variableName: string, value: number) { + isNumber(variableName: string, value: number): void { this.assert(_.isFinite(value), this.typeAssertionMessage(variableName, 'number', value)); }, - doesConformToSchema(variableName: string, value: object, schema: Schema) { + doesConformToSchema(variableName: string, value: object, schema: Schema): void { const schemaValidator = new SchemaValidator(); const validationResult = schemaValidator.validate(value, schema); const hasValidationErrors = validationResult.errors.length > 0; @@ -33,12 +36,12 @@ Encountered: ${JSON.stringify(value, null, '\t')} Validation errors: ${validationResult.errors.join(', ')}`; this.assert(!hasValidationErrors, msg); }, - assert(condition: boolean, message: string) { + assert(condition: boolean, message: string): void { if (!condition) { throw new Error(message); } }, - typeAssertionMessage(variableName: string, type: string, value: any) { + typeAssertionMessage(variableName: string, type: string, value: any): string { return `Expected ${variableName} to be of type ${type}, encountered: ${value}`; }, }; diff --git a/src/ts/utils/utils.ts b/src/ts/utils/utils.ts new file mode 100644 index 000000000..893f82ca3 --- /dev/null +++ b/src/ts/utils/utils.ts @@ -0,0 +1,7 @@ +export const utils = { + consoleLog(message: string) { + /* tslint:disable */ + console.log(message); + /* tslint:enable */ + }, +}; diff --git a/src/ts/web3_wrapper.ts b/src/ts/web3_wrapper.ts new file mode 100644 index 000000000..92781687e --- /dev/null +++ b/src/ts/web3_wrapper.ts @@ -0,0 +1,71 @@ +import * as _ from 'lodash'; +import Web3 from 'web3'; +import * as BigNumber from 'bignumber.js'; +import promisify = require('es6-promisify'); + +export class Web3Wrapper { + private web3: Web3; + constructor(web3: Web3) { + this.web3 = new Web3(); + this.web3.setProvider(web3.currentProvider); + } + public isAddress(address: string): boolean { + return this.web3.isAddress(address); + } + public async getSenderAddressIfExistsAsync(): Promise { + const defaultAccount = this.web3.eth.defaultAccount; + if (!_.isUndefined(defaultAccount)) { + return defaultAccount; + } + const firstAccount = await this.getFirstAddressIfExistsAsync(); + return firstAccount; + } + public async getFirstAddressIfExistsAsync(): Promise { + const addresses = await promisify(this.web3.eth.getAccounts)(); + if (_.isEmpty(addresses)) { + return ''; + } + return (addresses as string[])[0]; + } + public async getNodeVersionAsync(): Promise { + const nodeVersion = await promisify(this.web3.version.getNode)(); + return nodeVersion; + } + public getCurrentProvider(): Web3.Provider { + return this.web3.currentProvider; + } + public async getNetworkIdIfExistsAsync() { + try { + const networkId = await this.getNetworkAsync(); + return Number(networkId); + } catch (err) { + return undefined; + } + } + public async getBalanceInEthAsync(owner: string): Promise { + const balanceInWei = await promisify(this.web3.eth.getBalance)(owner); + const balanceEth = this.web3.fromWei(balanceInWei, 'ether'); + return balanceEth; + } + public async doesContractExistAtAddressAsync(address: string): Promise { + const code = await promisify(this.web3.eth.getCode)(address); + // Regex matches 0x0, 0x00, 0x in order to accomodate poorly implemented clients + const zeroHexAddressRegex = /^0[xX][0]*$/; + const didFindCode = _.isNull(code.match(zeroHexAddressRegex)); + return didFindCode; + } + // Note: since `sign` is overloaded to be both a sync and async method, it doesn't play nice + // with our callAsync method. We therefore handle it here as a special case. + public async signTransactionAsync(address: string, message: string): Promise { + const signData = await promisify(this.web3.eth.sign)(address, message); + return signData; + } + public async getBlockTimestampAsync(blockHash: string): Promise { + const {timestamp} = await promisify(this.web3.eth.getBlock)(blockHash); + return timestamp; + } + private async getNetworkAsync() { + const networkId = await promisify(this.web3.version.getNetwork)(); + return networkId; + } +} -- cgit v1.2.3 From b9892c0d49076e4a32fdf33d5dc94e1d22cd2725 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 25 May 2017 20:11:48 +0200 Subject: Remove unused imports --- src/ts/0x.js.ts | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/ts') diff --git a/src/ts/0x.js.ts b/src/ts/0x.js.ts index 7025f8804..6d682fc4c 100644 --- a/src/ts/0x.js.ts +++ b/src/ts/0x.js.ts @@ -1,10 +1,7 @@ import * as BigNumber from 'bignumber.js'; import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; import Web3 from 'web3'; import {assert} from './utils/assert'; -import {utils} from './utils/utils'; -import {ZeroExError} from './types'; import {Web3Wrapper} from './web3_wrapper'; import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper'; import contract = require('truffle-contract'); -- cgit v1.2.3 From 8e35923d6e2c6ed5347a34e7147067906f8c2fe5 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 25 May 2017 20:12:13 +0200 Subject: Fix exchange type --- src/ts/0x.js.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/ts') diff --git a/src/ts/0x.js.ts b/src/ts/0x.js.ts index 6d682fc4c..7ea32b87a 100644 --- a/src/ts/0x.js.ts +++ b/src/ts/0x.js.ts @@ -12,7 +12,7 @@ const MAX_DIGITS_IN_UNSIGNED_256_INT = 78; export class ZeroEx { public web3Wrapper: Web3Wrapper; - public exchange: ContractInstance; + public exchange: ExchangeWrapper; /** * Verifies that the elliptic curve signature `signature` was generated * by signing `data` with the private key corresponding to the `signerAddressHex` address. -- cgit v1.2.3 From f75595c6cd2a3edebca37d7d0063538116844074 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 25 May 2017 20:12:55 +0200 Subject: Change the order of params in isValidSignatureAsync to be consistent --- src/ts/contract_wrappers/exchange_wrapper.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/ts') diff --git a/src/ts/contract_wrappers/exchange_wrapper.ts b/src/ts/contract_wrappers/exchange_wrapper.ts index 502a1089b..5a576a7fa 100644 --- a/src/ts/contract_wrappers/exchange_wrapper.ts +++ b/src/ts/contract_wrappers/exchange_wrapper.ts @@ -3,17 +3,17 @@ import {Web3Wrapper} from '../web3_wrapper'; import {ECSignature, ZeroExError, ExchangeContract} from '../types'; import {assert} from '../utils/assert'; import {ContractWrapper} from './contract_wrapper'; -import * as ExchangeArtifacts from '../artifacts/Exchange.json'; +import * as ExchangeArtifacts from '../../artifacts/Exchange.json'; import {ECSignatureSchema} from '../schemas/ec_signature_schema'; export class ExchangeWrapper extends ContractWrapper { constructor(web3Wrapper: Web3Wrapper) { super(web3Wrapper); } - public async isValidSignatureAsync(maker: string, ecSignature: ECSignature, dataHex: string) { - assert.isString('maker', maker); - assert.doesConformToSchema('ecSignature', ecSignature, ECSignatureSchema); + public async isValidSignatureAsync(dataHex: string, ecSignature: ECSignature, maker: string) { assert.isHexString('dataHex', dataHex); + assert.doesConformToSchema('ecSignature', ecSignature, ECSignatureSchema); + assert.isString('maker', maker); const senderAddressIfExists = this.web3Wrapper.getSenderAddressIfExistsAsync(); assert.assert(!_.isUndefined(senderAddressIfExists), ZeroExError.USER_HAS_NO_ASSOCIATED_ADDRESSES); -- cgit v1.2.3 From 8c61af28db02129fb1d79930b32cea0ab8b55954 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 26 May 2017 12:57:37 +0200 Subject: Fix web3 imports --- src/ts/0x.js.ts | 2 +- src/ts/utils/assert.ts | 2 +- src/ts/web3_wrapper.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/ts') diff --git a/src/ts/0x.js.ts b/src/ts/0x.js.ts index 7ea32b87a..78abff681 100644 --- a/src/ts/0x.js.ts +++ b/src/ts/0x.js.ts @@ -1,6 +1,6 @@ import * as BigNumber from 'bignumber.js'; import * as ethUtil from 'ethereumjs-util'; -import Web3 from 'web3'; +import Web3 = require('web3'); import {assert} from './utils/assert'; import {Web3Wrapper} from './web3_wrapper'; import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper'; diff --git a/src/ts/utils/assert.ts b/src/ts/utils/assert.ts index 15d3031ff..809acb875 100644 --- a/src/ts/utils/assert.ts +++ b/src/ts/utils/assert.ts @@ -1,6 +1,6 @@ import * as _ from 'lodash'; import * as BigNumber from 'bignumber.js'; -import Web3 from 'web3'; +import Web3 = require('web3'); import {SchemaValidator} from './schema_validator'; const HEX_REGEX = /^0x[0-9A-F]*$/i; diff --git a/src/ts/web3_wrapper.ts b/src/ts/web3_wrapper.ts index 92781687e..0c44ef514 100644 --- a/src/ts/web3_wrapper.ts +++ b/src/ts/web3_wrapper.ts @@ -1,5 +1,5 @@ import * as _ from 'lodash'; -import Web3 from 'web3'; +import Web3 = require('web3'); import * as BigNumber from 'bignumber.js'; import promisify = require('es6-promisify'); -- cgit v1.2.3 From e1e50bba3d08a96d4cb5a9314c255e5d5c19d51a Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 26 May 2017 13:24:05 +0200 Subject: Fix web3 imports again --- src/ts/0x.js.ts | 2 +- src/ts/utils/assert.ts | 2 +- src/ts/web3_wrapper.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/ts') diff --git a/src/ts/0x.js.ts b/src/ts/0x.js.ts index 78abff681..cc3c43e79 100644 --- a/src/ts/0x.js.ts +++ b/src/ts/0x.js.ts @@ -1,6 +1,6 @@ import * as BigNumber from 'bignumber.js'; import * as ethUtil from 'ethereumjs-util'; -import Web3 = require('web3'); +import * as Web3 from 'web3'; import {assert} from './utils/assert'; import {Web3Wrapper} from './web3_wrapper'; import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper'; diff --git a/src/ts/utils/assert.ts b/src/ts/utils/assert.ts index 809acb875..1baf572d1 100644 --- a/src/ts/utils/assert.ts +++ b/src/ts/utils/assert.ts @@ -1,6 +1,6 @@ import * as _ from 'lodash'; import * as BigNumber from 'bignumber.js'; -import Web3 = require('web3'); +import * as Web3 from 'web3'; import {SchemaValidator} from './schema_validator'; const HEX_REGEX = /^0x[0-9A-F]*$/i; diff --git a/src/ts/web3_wrapper.ts b/src/ts/web3_wrapper.ts index 0c44ef514..ec3be994f 100644 --- a/src/ts/web3_wrapper.ts +++ b/src/ts/web3_wrapper.ts @@ -1,5 +1,5 @@ import * as _ from 'lodash'; -import Web3 = require('web3'); +import * as Web3 from 'web3'; import * as BigNumber from 'bignumber.js'; import promisify = require('es6-promisify'); -- cgit v1.2.3 From c5cc388a596cc01522ae7bfc182ca3841a4b7ba9 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 26 May 2017 15:08:44 +0200 Subject: Remove unused bignum import --- src/ts/types.ts | 1 - 1 file changed, 1 deletion(-) (limited to 'src/ts') diff --git a/src/ts/types.ts b/src/ts/types.ts index 04123782e..4da03a4d3 100644 --- a/src/ts/types.ts +++ b/src/ts/types.ts @@ -1,5 +1,4 @@ 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 -- cgit v1.2.3 From e545ade857501fae7ccc9ad27da6ab3803a5ffd8 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 26 May 2017 17:09:34 +0200 Subject: Spacing and import re-order --- src/ts/0x.js.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/ts') diff --git a/src/ts/0x.js.ts b/src/ts/0x.js.ts index 7c6557b5b..8496a0989 100644 --- a/src/ts/0x.js.ts +++ b/src/ts/0x.js.ts @@ -1,14 +1,14 @@ import * as BigNumber from 'bignumber.js'; import * as BN from 'bn.js'; import * as ethUtil from 'ethereumjs-util'; +import contract = require('truffle-contract'); import * as Web3 from 'web3'; +import {Web3Wrapper} from './web3_wrapper'; import * as ethABI from 'ethereumjs-abi'; import * as _ from 'lodash'; import {constants} from './utils/constants'; import {assert} from './utils/assert'; -import {Web3Wrapper} from './web3_wrapper'; import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper'; -import contract = require('truffle-contract'); import {ECSignatureSchema} from './schemas/ec_signature_schema'; import {SolidityTypes, ECSignature} from './types'; @@ -71,7 +71,8 @@ export class ZeroEx { const dataBuff = ethUtil.toBuffer(dataHex); const msgHashBuff = ethUtil.hashPersonalMessage(dataBuff); try { - const pubKey = ethUtil.ecrecover(msgHashBuff, + const pubKey = ethUtil.ecrecover( + msgHashBuff, signature.v, ethUtil.toBuffer(signature.r), ethUtil.toBuffer(signature.s)); -- cgit v1.2.3 From 123cfb7c00bcfba0a24e2ac4593834b134a76806 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 26 May 2017 17:09:47 +0200 Subject: Add missing require --- src/ts/contract_wrappers/contract_wrapper.ts | 1 + 1 file changed, 1 insertion(+) (limited to 'src/ts') diff --git a/src/ts/contract_wrappers/contract_wrapper.ts b/src/ts/contract_wrappers/contract_wrapper.ts index 72bfffe95..aeb52b0e1 100644 --- a/src/ts/contract_wrappers/contract_wrapper.ts +++ b/src/ts/contract_wrappers/contract_wrapper.ts @@ -1,4 +1,5 @@ import * as _ from 'lodash'; +import contract = require('truffle-contract'); import {Web3Wrapper} from '../web3_wrapper'; import {ZeroExError} from '../types'; import {utils} from '../utils/utils'; -- cgit v1.2.3 From 5a6df03b64630b4ccfe1a211a113413b9f1d4e5c Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 26 May 2017 17:10:02 +0200 Subject: cleanup isValidSignature method --- src/ts/contract_wrappers/exchange_wrapper.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/ts') diff --git a/src/ts/contract_wrappers/exchange_wrapper.ts b/src/ts/contract_wrappers/exchange_wrapper.ts index 5a576a7fa..b02390eba 100644 --- a/src/ts/contract_wrappers/exchange_wrapper.ts +++ b/src/ts/contract_wrappers/exchange_wrapper.ts @@ -10,20 +10,21 @@ export class ExchangeWrapper extends ContractWrapper { constructor(web3Wrapper: Web3Wrapper) { super(web3Wrapper); } - public async isValidSignatureAsync(dataHex: string, ecSignature: ECSignature, maker: string) { + public async isValidSignatureAsync(dataHex: string, ecSignature: ECSignature, + signerAddressHex: string): Promise { assert.isHexString('dataHex', dataHex); assert.doesConformToSchema('ecSignature', ecSignature, ECSignatureSchema); - assert.isString('maker', maker); + assert.isETHAddressHex('signerAddressHex', signerAddressHex); - const senderAddressIfExists = this.web3Wrapper.getSenderAddressIfExistsAsync(); + const senderAddressIfExists = await this.web3Wrapper.getSenderAddressIfExistsAsync(); assert.assert(!_.isUndefined(senderAddressIfExists), ZeroExError.USER_HAS_NO_ASSOCIATED_ADDRESSES); - // TODO: remove any here + // TODO: remove `any` here const contractInstance = await this.instantiateContractIfExistsAsync((ExchangeArtifacts as any)); const exchangeInstance = contractInstance as ExchangeContract; const isValidSignature = await exchangeInstance.isValidSignature.call( - maker, + signerAddressHex, dataHex, ecSignature.v, ecSignature.r, -- cgit v1.2.3 From f4bf9fc423c4bb7f2027cdd5700de56f8f4bff96 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 26 May 2017 17:10:12 +0200 Subject: Add missing semi-colon --- src/ts/utils/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/ts') diff --git a/src/ts/utils/constants.ts b/src/ts/utils/constants.ts index 60af7b674..ec2fe744a 100644 --- a/src/ts/utils/constants.ts +++ b/src/ts/utils/constants.ts @@ -1,3 +1,3 @@ export const constants = { NULL_ADDRESS: '0x0000000000000000000000000000000000000000', -} +}; -- cgit v1.2.3 From 555bac19cb90a83d5a0025e53341f76ff39c4373 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 26 May 2017 17:12:22 +0200 Subject: Setup blockchain snapshotting before/after every test, implemented unit tests for exchangeWrapper.isValidSignature --- src/ts/globals.d.ts | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/ts') diff --git a/src/ts/globals.d.ts b/src/ts/globals.d.ts index 30225d0d8..dee957f2f 100644 --- a/src/ts/globals.d.ts +++ b/src/ts/globals.d.ts @@ -1,5 +1,8 @@ declare module 'chai-bignumber'; declare module 'bn.js'; +declare module 'request-promise-native'; +declare module 'web3-provider-engine'; +declare module 'web3-provider-engine/subproviders/rpc'; declare interface Schema { id: string; @@ -12,6 +15,7 @@ declare interface Schema { declare namespace Chai { interface Assertion { bignumber: Assertion; + eventually: Assertion; } } /* tslint:enable */ @@ -30,6 +34,7 @@ declare module 'ethereumjs-util' { const ecrecover: (msgHashBuff: Buffer, v: number, r: Buffer, s: Buffer) => string; const pubToAddress: (pubKey: string) => Buffer; const isValidAddress: (address: string) => boolean; + const bufferToInt: (buffer: Buffer) => number; } // truffle-contract declarations -- cgit v1.2.3 From 57b820c7467102b299e602aaa94e043ee0bd4690 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 26 May 2017 17:40:23 +0200 Subject: import re-order --- src/ts/0x.js.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/ts') diff --git a/src/ts/0x.js.ts b/src/ts/0x.js.ts index 8496a0989..bd4978c96 100644 --- a/src/ts/0x.js.ts +++ b/src/ts/0x.js.ts @@ -1,11 +1,11 @@ +import * as _ from 'lodash'; import * as BigNumber from 'bignumber.js'; import * as BN from 'bn.js'; import * as ethUtil from 'ethereumjs-util'; import contract = require('truffle-contract'); import * as Web3 from 'web3'; -import {Web3Wrapper} from './web3_wrapper'; import * as ethABI from 'ethereumjs-abi'; -import * as _ from 'lodash'; +import {Web3Wrapper} from './web3_wrapper'; import {constants} from './utils/constants'; import {assert} from './utils/assert'; import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper'; -- cgit v1.2.3 From a4ec739ce685989dde01c38cf45f4c21026f3c20 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 26 May 2017 17:40:35 +0200 Subject: remove comment --- src/ts/contract_wrappers/contract_wrapper.ts | 1 - 1 file changed, 1 deletion(-) (limited to 'src/ts') diff --git a/src/ts/contract_wrappers/contract_wrapper.ts b/src/ts/contract_wrappers/contract_wrapper.ts index aeb52b0e1..c3495fa21 100644 --- a/src/ts/contract_wrappers/contract_wrapper.ts +++ b/src/ts/contract_wrappers/contract_wrapper.ts @@ -9,7 +9,6 @@ export class ContractWrapper { constructor(web3Wrapper: Web3Wrapper) { this.web3Wrapper = web3Wrapper; } - // this.exchange = await this.instantiateContractIfExistsAsync(ExchangeArtifacts); protected async instantiateContractIfExistsAsync(artifact: Artifact, address?: string): Promise { const c = await contract(artifact); const providerObj = this.web3Wrapper.getCurrentProvider(); -- cgit v1.2.3 From 066c7ff0aa5c2cd657ae40b72bf1268119a86255 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 26 May 2017 17:40:51 +0200 Subject: rename networkId to networkIdIfExists --- src/ts/contract_wrappers/contract_wrapper.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/ts') diff --git a/src/ts/contract_wrappers/contract_wrapper.ts b/src/ts/contract_wrappers/contract_wrapper.ts index c3495fa21..ee1c6c90d 100644 --- a/src/ts/contract_wrappers/contract_wrapper.ts +++ b/src/ts/contract_wrappers/contract_wrapper.ts @@ -14,8 +14,10 @@ export class ContractWrapper { const providerObj = this.web3Wrapper.getCurrentProvider(); c.setProvider(providerObj); - const networkId = await this.web3Wrapper.getNetworkIdIfExistsAsync(); - const artifactNetworkConfigs = _.isUndefined(networkId) ? undefined : artifact.networks[networkId]; + const networkIdIfExists = await this.web3Wrapper.getNetworkIdIfExistsAsync(); + const artifactNetworkConfigs = _.isUndefined(networkIdIfExists) ? + undefined : + artifact.networks[networkIdIfExists]; let contractAddress; if (!_.isUndefined(address)) { contractAddress = address; -- cgit v1.2.3 From 79249f5e8a37e139c9297a94479f269bf61514af Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 26 May 2017 17:41:08 +0200 Subject: move console log into UNHANDLED_ERROR clause --- src/ts/contract_wrappers/contract_wrapper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/ts') diff --git a/src/ts/contract_wrappers/contract_wrapper.ts b/src/ts/contract_wrappers/contract_wrapper.ts index ee1c6c90d..225cb960f 100644 --- a/src/ts/contract_wrappers/contract_wrapper.ts +++ b/src/ts/contract_wrappers/contract_wrapper.ts @@ -42,10 +42,10 @@ export class ContractWrapper { return contractInstance; } catch (err) { const errMsg = `${err}`; - utils.consoleLog(`Notice: Error encountered: ${err} ${err.stack}`); if (_.includes(errMsg, 'not been deployed to detected network')) { throw new Error(ZeroExError.CONTRACT_DOES_NOT_EXIST); } else { + utils.consoleLog(`Notice: Error encountered: ${err} ${err.stack}`); throw new Error(ZeroExError.UNHANDLED_ERROR); } } -- cgit v1.2.3 From a6da9cd07389b317624ad00a3cb73b75820687e1 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 26 May 2017 17:47:00 +0200 Subject: Add missing return types --- src/ts/utils/utils.ts | 2 +- src/ts/web3_wrapper.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/ts') diff --git a/src/ts/utils/utils.ts b/src/ts/utils/utils.ts index 893f82ca3..04ac36b54 100644 --- a/src/ts/utils/utils.ts +++ b/src/ts/utils/utils.ts @@ -1,5 +1,5 @@ export const utils = { - consoleLog(message: string) { + consoleLog(message: string): void { /* tslint:disable */ console.log(message); /* tslint:enable */ diff --git a/src/ts/web3_wrapper.ts b/src/ts/web3_wrapper.ts index ec3be994f..969c2c040 100644 --- a/src/ts/web3_wrapper.ts +++ b/src/ts/web3_wrapper.ts @@ -34,7 +34,7 @@ export class Web3Wrapper { public getCurrentProvider(): Web3.Provider { return this.web3.currentProvider; } - public async getNetworkIdIfExistsAsync() { + public async getNetworkIdIfExistsAsync(): Promise { try { const networkId = await this.getNetworkAsync(); return Number(networkId); @@ -64,7 +64,7 @@ export class Web3Wrapper { const {timestamp} = await promisify(this.web3.eth.getBlock)(blockHash); return timestamp; } - private async getNetworkAsync() { + private async getNetworkAsync(): Promise { const networkId = await promisify(this.web3.version.getNetwork)(); return networkId; } -- cgit v1.2.3 From 0aabade166be563753bed3bb9ffb64f8a02e0ee8 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 26 May 2017 17:49:16 +0200 Subject: return undefined if not address found --- src/ts/web3_wrapper.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/ts') diff --git a/src/ts/web3_wrapper.ts b/src/ts/web3_wrapper.ts index 969c2c040..2f082c9ac 100644 --- a/src/ts/web3_wrapper.ts +++ b/src/ts/web3_wrapper.ts @@ -12,7 +12,7 @@ export class Web3Wrapper { public isAddress(address: string): boolean { return this.web3.isAddress(address); } - public async getSenderAddressIfExistsAsync(): Promise { + public async getSenderAddressIfExistsAsync(): Promise { const defaultAccount = this.web3.eth.defaultAccount; if (!_.isUndefined(defaultAccount)) { return defaultAccount; @@ -20,10 +20,10 @@ export class Web3Wrapper { const firstAccount = await this.getFirstAddressIfExistsAsync(); return firstAccount; } - public async getFirstAddressIfExistsAsync(): Promise { + public async getFirstAddressIfExistsAsync(): Promise { const addresses = await promisify(this.web3.eth.getAccounts)(); if (_.isEmpty(addresses)) { - return ''; + return undefined; } return (addresses as string[])[0]; } -- cgit v1.2.3 From b65ca931f24b69bf72c2b56e5b70269de710f5d5 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 26 May 2017 17:51:07 +0200 Subject: remove outdated comment --- src/ts/web3_wrapper.ts | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/ts') diff --git a/src/ts/web3_wrapper.ts b/src/ts/web3_wrapper.ts index 2f082c9ac..24938e396 100644 --- a/src/ts/web3_wrapper.ts +++ b/src/ts/web3_wrapper.ts @@ -54,8 +54,6 @@ export class Web3Wrapper { const didFindCode = _.isNull(code.match(zeroHexAddressRegex)); return didFindCode; } - // Note: since `sign` is overloaded to be both a sync and async method, it doesn't play nice - // with our callAsync method. We therefore handle it here as a special case. public async signTransactionAsync(address: string, message: string): Promise { const signData = await promisify(this.web3.eth.sign)(address, message); return signData; -- cgit v1.2.3 From 75c67f3ce3d762f84f44e669f949adab351c6cad Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 26 May 2017 17:51:16 +0200 Subject: Simplify zero address regex --- src/ts/web3_wrapper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/ts') diff --git a/src/ts/web3_wrapper.ts b/src/ts/web3_wrapper.ts index 24938e396..97d04db8c 100644 --- a/src/ts/web3_wrapper.ts +++ b/src/ts/web3_wrapper.ts @@ -50,7 +50,7 @@ export class Web3Wrapper { public async doesContractExistAtAddressAsync(address: string): Promise { const code = await promisify(this.web3.eth.getCode)(address); // Regex matches 0x0, 0x00, 0x in order to accomodate poorly implemented clients - const zeroHexAddressRegex = /^0[xX][0]*$/; + const zeroHexAddressRegex = /^0x0*$/i; const didFindCode = _.isNull(code.match(zeroHexAddressRegex)); return didFindCode; } -- cgit v1.2.3 From 90db58bb2adfd09ee672420f625f906e761d722e Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 26 May 2017 18:20:34 +0200 Subject: remove todo --- src/ts/contract_wrappers/exchange_wrapper.ts | 1 - 1 file changed, 1 deletion(-) (limited to 'src/ts') diff --git a/src/ts/contract_wrappers/exchange_wrapper.ts b/src/ts/contract_wrappers/exchange_wrapper.ts index b02390eba..38043dd55 100644 --- a/src/ts/contract_wrappers/exchange_wrapper.ts +++ b/src/ts/contract_wrappers/exchange_wrapper.ts @@ -19,7 +19,6 @@ export class ExchangeWrapper extends ContractWrapper { const senderAddressIfExists = await this.web3Wrapper.getSenderAddressIfExistsAsync(); assert.assert(!_.isUndefined(senderAddressIfExists), ZeroExError.USER_HAS_NO_ASSOCIATED_ADDRESSES); - // TODO: remove `any` here const contractInstance = await this.instantiateContractIfExistsAsync((ExchangeArtifacts as any)); const exchangeInstance = contractInstance as ExchangeContract; -- cgit v1.2.3 From 7e96b45ea0c51ca5589640018172a91a35596148 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 26 May 2017 18:25:17 +0200 Subject: Make zero address regex stricter --- src/ts/web3_wrapper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/ts') diff --git a/src/ts/web3_wrapper.ts b/src/ts/web3_wrapper.ts index 97d04db8c..3b460e4da 100644 --- a/src/ts/web3_wrapper.ts +++ b/src/ts/web3_wrapper.ts @@ -50,7 +50,7 @@ export class Web3Wrapper { public async doesContractExistAtAddressAsync(address: string): Promise { const code = await promisify(this.web3.eth.getCode)(address); // Regex matches 0x0, 0x00, 0x in order to accomodate poorly implemented clients - const zeroHexAddressRegex = /^0x0*$/i; + const zeroHexAddressRegex = /^0x0\{0,40\}$/i; const didFindCode = _.isNull(code.match(zeroHexAddressRegex)); return didFindCode; } -- cgit v1.2.3 From a34d083cad3a07965bcb1687dd6534a30d79b7d0 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 26 May 2017 18:35:35 +0200 Subject: Refactor to ternary --- src/ts/contract_wrappers/contract_wrapper.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src/ts') diff --git a/src/ts/contract_wrappers/contract_wrapper.ts b/src/ts/contract_wrappers/contract_wrapper.ts index 225cb960f..9f4cd8039 100644 --- a/src/ts/contract_wrappers/contract_wrapper.ts +++ b/src/ts/contract_wrappers/contract_wrapper.ts @@ -33,12 +33,7 @@ export class ContractWrapper { } try { - let contractInstance; - if (_.isUndefined(address)) { - contractInstance = await c.deployed(); - } else { - contractInstance = await c.at(address); - } + const contractInstance = _.isUndefined(address) ? await c.deployed() : await c.at(address); return contractInstance; } catch (err) { const errMsg = `${err}`; -- cgit v1.2.3