diff options
Diffstat (limited to 'packages/contracts/util')
-rw-r--r-- | packages/contracts/util/artifacts.ts | 52 | ||||
-rw-r--r-- | packages/contracts/util/balances.ts | 40 | ||||
-rw-r--r-- | packages/contracts/util/constants.ts | 14 | ||||
-rw-r--r-- | packages/contracts/util/crypto.ts | 46 | ||||
-rw-r--r-- | packages/contracts/util/exchange_wrapper.ts | 358 | ||||
-rw-r--r-- | packages/contracts/util/formatters.ts | 206 | ||||
-rw-r--r-- | packages/contracts/util/multi_sig_wrapper.ts | 60 | ||||
-rw-r--r-- | packages/contracts/util/order.ts | 188 | ||||
-rw-r--r-- | packages/contracts/util/order_factory.ts | 40 | ||||
-rw-r--r-- | packages/contracts/util/token_registry_wrapper.ts | 104 | ||||
-rw-r--r-- | packages/contracts/util/types.ts | 150 |
11 files changed, 629 insertions, 629 deletions
diff --git a/packages/contracts/util/artifacts.ts b/packages/contracts/util/artifacts.ts index ab9518d41..ecb18cbce 100644 --- a/packages/contracts/util/artifacts.ts +++ b/packages/contracts/util/artifacts.ts @@ -1,28 +1,28 @@ export class Artifacts { - public Migrations: any; - public TokenTransferProxy: any; - public TokenRegistry: any; - public MultiSigWalletWithTimeLock: any; - public Exchange: any; - public ZRXToken: any; - public DummyToken: any; - public DummyTokenV2: any; - public EtherToken: any; - public MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress: any; - public MaliciousToken: any; - constructor(artifacts: any) { - this.Migrations = artifacts.require('Migrations'); - this.TokenTransferProxy = artifacts.require('TokenTransferProxy'); - this.TokenRegistry = artifacts.require('TokenRegistry'); - this.MultiSigWalletWithTimeLock = artifacts.require('MultiSigWalletWithTimeLock'); - this.Exchange = artifacts.require('Exchange'); - this.ZRXToken = artifacts.require('ZRXToken'); - this.DummyToken = artifacts.require('DummyToken'); - this.DummyTokenV2 = artifacts.require('DummyToken_v2'); - this.EtherToken = artifacts.require('WETH9'); - this.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress = artifacts.require( - 'MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', - ); - this.MaliciousToken = artifacts.require('MaliciousToken'); - } + public Migrations: any; + public TokenTransferProxy: any; + public TokenRegistry: any; + public MultiSigWalletWithTimeLock: any; + public Exchange: any; + public ZRXToken: any; + public DummyToken: any; + public DummyTokenV2: any; + public EtherToken: any; + public MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress: any; + public MaliciousToken: any; + constructor(artifacts: any) { + this.Migrations = artifacts.require('Migrations'); + this.TokenTransferProxy = artifacts.require('TokenTransferProxy'); + this.TokenRegistry = artifacts.require('TokenRegistry'); + this.MultiSigWalletWithTimeLock = artifacts.require('MultiSigWalletWithTimeLock'); + this.Exchange = artifacts.require('Exchange'); + this.ZRXToken = artifacts.require('ZRXToken'); + this.DummyToken = artifacts.require('DummyToken'); + this.DummyTokenV2 = artifacts.require('DummyToken_v2'); + this.EtherToken = artifacts.require('WETH9'); + this.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress = artifacts.require( + 'MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', + ); + this.MaliciousToken = artifacts.require('MaliciousToken'); + } } diff --git a/packages/contracts/util/balances.ts b/packages/contracts/util/balances.ts index f8c103670..6a1659ab1 100644 --- a/packages/contracts/util/balances.ts +++ b/packages/contracts/util/balances.ts @@ -4,24 +4,24 @@ import * as _ from 'lodash'; import { BalancesByOwner, ContractInstance } from './types'; export class Balances { - private _tokenContractInstances: ContractInstance[]; - private _ownerAddresses: string[]; - constructor(tokenContractInstances: ContractInstance[], ownerAddresses: string[]) { - this._tokenContractInstances = tokenContractInstances; - this._ownerAddresses = ownerAddresses; - } - public async getAsync(): Promise<BalancesByOwner> { - const balancesByOwner: BalancesByOwner = {}; - for (const tokenContractInstance of this._tokenContractInstances) { - for (const ownerAddress of this._ownerAddresses) { - let balance = await tokenContractInstance.balanceOf(ownerAddress); - balance = new BigNumber(balance); - if (_.isUndefined(balancesByOwner[ownerAddress])) { - balancesByOwner[ownerAddress] = {}; - } - balancesByOwner[ownerAddress][tokenContractInstance.address] = balance; - } - } - return balancesByOwner; - } + private _tokenContractInstances: ContractInstance[]; + private _ownerAddresses: string[]; + constructor(tokenContractInstances: ContractInstance[], ownerAddresses: string[]) { + this._tokenContractInstances = tokenContractInstances; + this._ownerAddresses = ownerAddresses; + } + public async getAsync(): Promise<BalancesByOwner> { + const balancesByOwner: BalancesByOwner = {}; + for (const tokenContractInstance of this._tokenContractInstances) { + for (const ownerAddress of this._ownerAddresses) { + let balance = await tokenContractInstance.balanceOf(ownerAddress); + balance = new BigNumber(balance); + if (_.isUndefined(balancesByOwner[ownerAddress])) { + balancesByOwner[ownerAddress] = {}; + } + balancesByOwner[ownerAddress][tokenContractInstance.address] = balance; + } + } + return balancesByOwner; + } } diff --git a/packages/contracts/util/constants.ts b/packages/contracts/util/constants.ts index 85fd31be3..e61b2f802 100644 --- a/packages/contracts/util/constants.ts +++ b/packages/contracts/util/constants.ts @@ -1,9 +1,9 @@ export const constants = { - NULL_BYTES: '0x', - INVALID_OPCODE: 'invalid opcode', - REVERT: 'revert', - TESTRPC_NETWORK_ID: 50, - MAX_ETHERTOKEN_WITHDRAW_GAS: 43000, - MAX_TOKEN_TRANSFERFROM_GAS: 80000, - MAX_TOKEN_APPROVE_GAS: 60000, + NULL_BYTES: '0x', + INVALID_OPCODE: 'invalid opcode', + REVERT: 'revert', + TESTRPC_NETWORK_ID: 50, + MAX_ETHERTOKEN_WITHDRAW_GAS: 43000, + MAX_TOKEN_TRANSFERFROM_GAS: 80000, + MAX_TOKEN_APPROVE_GAS: 60000, }; diff --git a/packages/contracts/util/crypto.ts b/packages/contracts/util/crypto.ts index 29bbf206a..9173df643 100644 --- a/packages/contracts/util/crypto.ts +++ b/packages/contracts/util/crypto.ts @@ -4,7 +4,7 @@ import ethUtil = require('ethereumjs-util'); import * as _ from 'lodash'; export const crypto = { - /* + /* * We convert types from JS to Solidity as follows: * BigNumber -> uint256 * number -> uint8 @@ -12,26 +12,26 @@ export const crypto = { * boolean -> bool * valid Ethereum address -> address */ - solSHA3(args: any[]): Buffer { - const argTypes: string[] = []; - _.each(args, (arg, i) => { - const isNumber = _.isFinite(arg); - if (isNumber) { - argTypes.push('uint8'); - } else if (arg.isBigNumber) { - argTypes.push('uint256'); - args[i] = new BN(arg.toString(10), 10); - } else if (ethUtil.isValidAddress(arg)) { - argTypes.push('address'); - } else if (_.isString(arg)) { - argTypes.push('string'); - } else if (_.isBoolean(arg)) { - argTypes.push('bool'); - } else { - throw new Error(`Unable to guess arg type: ${arg}`); - } - }); - const hash = ABI.soliditySHA3(argTypes, args); - return hash; - }, + solSHA3(args: any[]): Buffer { + const argTypes: string[] = []; + _.each(args, (arg, i) => { + const isNumber = _.isFinite(arg); + if (isNumber) { + argTypes.push('uint8'); + } else if (arg.isBigNumber) { + argTypes.push('uint256'); + args[i] = new BN(arg.toString(10), 10); + } else if (ethUtil.isValidAddress(arg)) { + argTypes.push('address'); + } else if (_.isString(arg)) { + argTypes.push('string'); + } else if (_.isBoolean(arg)) { + argTypes.push('bool'); + } else { + throw new Error(`Unable to guess arg type: ${arg}`); + } + }); + const hash = ABI.soliditySHA3(argTypes, args); + return hash; + }, }; diff --git a/packages/contracts/util/exchange_wrapper.ts b/packages/contracts/util/exchange_wrapper.ts index 3a3c44aae..ca79f92c4 100644 --- a/packages/contracts/util/exchange_wrapper.ts +++ b/packages/contracts/util/exchange_wrapper.ts @@ -6,186 +6,186 @@ import { Order } from './order'; import { ContractInstance } from './types'; export class ExchangeWrapper { - private _exchange: ContractInstance; - constructor(exchangeContractInstance: ContractInstance) { - this._exchange = exchangeContractInstance; - } - public async fillOrderAsync( - order: Order, - from: string, - opts: { - fillTakerTokenAmount?: BigNumber; - shouldThrowOnInsufficientBalanceOrAllowance?: boolean; - } = {}, - ) { - const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance; - const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmount); - const tx = await this._exchange.fillOrder( - params.orderAddresses, - params.orderValues, - params.fillTakerTokenAmount, - params.shouldThrowOnInsufficientBalanceOrAllowance, - params.v, - params.r, - params.s, - { from }, - ); - _.each(tx.logs, log => wrapLogBigNumbers(log)); - return tx; - } - public async cancelOrderAsync(order: Order, from: string, opts: { cancelTakerTokenAmount?: BigNumber } = {}) { - const params = order.createCancel(opts.cancelTakerTokenAmount); - const tx = await this._exchange.cancelOrder( - params.orderAddresses, - params.orderValues, - params.cancelTakerTokenAmount, - { from }, - ); - _.each(tx.logs, log => wrapLogBigNumbers(log)); - return tx; - } - public async fillOrKillOrderAsync(order: Order, from: string, opts: { fillTakerTokenAmount?: BigNumber } = {}) { - const shouldThrowOnInsufficientBalanceOrAllowance = true; - const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmount); - const tx = await this._exchange.fillOrKillOrder( - params.orderAddresses, - params.orderValues, - params.fillTakerTokenAmount, - params.v, - params.r, - params.s, - { from }, - ); - _.each(tx.logs, log => wrapLogBigNumbers(log)); - return tx; - } - public async batchFillOrdersAsync( - orders: Order[], - from: string, - opts: { - fillTakerTokenAmounts?: BigNumber[]; - shouldThrowOnInsufficientBalanceOrAllowance?: boolean; - } = {}, - ) { - const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance; - const params = formatters.createBatchFill( - orders, - shouldThrowOnInsufficientBalanceOrAllowance, - opts.fillTakerTokenAmounts, - ); - const tx = await this._exchange.batchFillOrders( - params.orderAddresses, - params.orderValues, - params.fillTakerTokenAmounts, - params.shouldThrowOnInsufficientBalanceOrAllowance, - params.v, - params.r, - params.s, - { from }, - ); - _.each(tx.logs, log => wrapLogBigNumbers(log)); - return tx; - } - public async batchFillOrKillOrdersAsync( - orders: Order[], - from: string, - opts: { fillTakerTokenAmounts?: BigNumber[] } = {}, - ) { - const params = formatters.createBatchFill(orders, undefined, opts.fillTakerTokenAmounts); - const tx = await this._exchange.batchFillOrKillOrders( - params.orderAddresses, - params.orderValues, - params.fillTakerTokenAmounts, - params.v, - params.r, - params.s, - { from }, - ); - _.each(tx.logs, log => wrapLogBigNumbers(log)); - return tx; - } - public async fillOrdersUpToAsync( - orders: Order[], - from: string, - opts: { - fillTakerTokenAmount?: BigNumber; - shouldThrowOnInsufficientBalanceOrAllowance?: boolean; - } = {}, - ) { - const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance; - const params = formatters.createFillUpTo( - orders, - shouldThrowOnInsufficientBalanceOrAllowance, - opts.fillTakerTokenAmount, - ); - const tx = await this._exchange.fillOrdersUpTo( - params.orderAddresses, - params.orderValues, - params.fillTakerTokenAmount, - params.shouldThrowOnInsufficientBalanceOrAllowance, - params.v, - params.r, - params.s, - { from }, - ); - _.each(tx.logs, log => wrapLogBigNumbers(log)); - return tx; - } - public async batchCancelOrdersAsync( - orders: Order[], - from: string, - opts: { cancelTakerTokenAmounts?: BigNumber[] } = {}, - ) { - const params = formatters.createBatchCancel(orders, opts.cancelTakerTokenAmounts); - const tx = await this._exchange.batchCancelOrders( - params.orderAddresses, - params.orderValues, - params.cancelTakerTokenAmounts, - { from }, - ); - _.each(tx.logs, log => wrapLogBigNumbers(log)); - return tx; - } - public async getOrderHashAsync(order: Order): Promise<string> { - const shouldThrowOnInsufficientBalanceOrAllowance = false; - const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance); - const orderHash = await this._exchange.getOrderHash(params.orderAddresses, params.orderValues); - return orderHash; - } - public async isValidSignatureAsync(order: Order): Promise<boolean> { - const isValidSignature = await this._exchange.isValidSignature( - order.params.maker, - order.params.orderHashHex, - order.params.v, - order.params.r, - order.params.s, - ); - return isValidSignature; - } - public async isRoundingErrorAsync( - numerator: BigNumber, - denominator: BigNumber, - target: BigNumber, - ): Promise<boolean> { - const isRoundingError = await this._exchange.isRoundingError(numerator, denominator, target); - return isRoundingError; - } - public async getPartialAmountAsync( - numerator: BigNumber, - denominator: BigNumber, - target: BigNumber, - ): Promise<BigNumber> { - const partialAmount = new BigNumber(await this._exchange.getPartialAmount(numerator, denominator, target)); - return partialAmount; - } + private _exchange: ContractInstance; + constructor(exchangeContractInstance: ContractInstance) { + this._exchange = exchangeContractInstance; + } + public async fillOrderAsync( + order: Order, + from: string, + opts: { + fillTakerTokenAmount?: BigNumber; + shouldThrowOnInsufficientBalanceOrAllowance?: boolean; + } = {}, + ) { + const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance; + const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmount); + const tx = await this._exchange.fillOrder( + params.orderAddresses, + params.orderValues, + params.fillTakerTokenAmount, + params.shouldThrowOnInsufficientBalanceOrAllowance, + params.v, + params.r, + params.s, + { from }, + ); + _.each(tx.logs, log => wrapLogBigNumbers(log)); + return tx; + } + public async cancelOrderAsync(order: Order, from: string, opts: { cancelTakerTokenAmount?: BigNumber } = {}) { + const params = order.createCancel(opts.cancelTakerTokenAmount); + const tx = await this._exchange.cancelOrder( + params.orderAddresses, + params.orderValues, + params.cancelTakerTokenAmount, + { from }, + ); + _.each(tx.logs, log => wrapLogBigNumbers(log)); + return tx; + } + public async fillOrKillOrderAsync(order: Order, from: string, opts: { fillTakerTokenAmount?: BigNumber } = {}) { + const shouldThrowOnInsufficientBalanceOrAllowance = true; + const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmount); + const tx = await this._exchange.fillOrKillOrder( + params.orderAddresses, + params.orderValues, + params.fillTakerTokenAmount, + params.v, + params.r, + params.s, + { from }, + ); + _.each(tx.logs, log => wrapLogBigNumbers(log)); + return tx; + } + public async batchFillOrdersAsync( + orders: Order[], + from: string, + opts: { + fillTakerTokenAmounts?: BigNumber[]; + shouldThrowOnInsufficientBalanceOrAllowance?: boolean; + } = {}, + ) { + const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance; + const params = formatters.createBatchFill( + orders, + shouldThrowOnInsufficientBalanceOrAllowance, + opts.fillTakerTokenAmounts, + ); + const tx = await this._exchange.batchFillOrders( + params.orderAddresses, + params.orderValues, + params.fillTakerTokenAmounts, + params.shouldThrowOnInsufficientBalanceOrAllowance, + params.v, + params.r, + params.s, + { from }, + ); + _.each(tx.logs, log => wrapLogBigNumbers(log)); + return tx; + } + public async batchFillOrKillOrdersAsync( + orders: Order[], + from: string, + opts: { fillTakerTokenAmounts?: BigNumber[] } = {}, + ) { + const params = formatters.createBatchFill(orders, undefined, opts.fillTakerTokenAmounts); + const tx = await this._exchange.batchFillOrKillOrders( + params.orderAddresses, + params.orderValues, + params.fillTakerTokenAmounts, + params.v, + params.r, + params.s, + { from }, + ); + _.each(tx.logs, log => wrapLogBigNumbers(log)); + return tx; + } + public async fillOrdersUpToAsync( + orders: Order[], + from: string, + opts: { + fillTakerTokenAmount?: BigNumber; + shouldThrowOnInsufficientBalanceOrAllowance?: boolean; + } = {}, + ) { + const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance; + const params = formatters.createFillUpTo( + orders, + shouldThrowOnInsufficientBalanceOrAllowance, + opts.fillTakerTokenAmount, + ); + const tx = await this._exchange.fillOrdersUpTo( + params.orderAddresses, + params.orderValues, + params.fillTakerTokenAmount, + params.shouldThrowOnInsufficientBalanceOrAllowance, + params.v, + params.r, + params.s, + { from }, + ); + _.each(tx.logs, log => wrapLogBigNumbers(log)); + return tx; + } + public async batchCancelOrdersAsync( + orders: Order[], + from: string, + opts: { cancelTakerTokenAmounts?: BigNumber[] } = {}, + ) { + const params = formatters.createBatchCancel(orders, opts.cancelTakerTokenAmounts); + const tx = await this._exchange.batchCancelOrders( + params.orderAddresses, + params.orderValues, + params.cancelTakerTokenAmounts, + { from }, + ); + _.each(tx.logs, log => wrapLogBigNumbers(log)); + return tx; + } + public async getOrderHashAsync(order: Order): Promise<string> { + const shouldThrowOnInsufficientBalanceOrAllowance = false; + const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance); + const orderHash = await this._exchange.getOrderHash(params.orderAddresses, params.orderValues); + return orderHash; + } + public async isValidSignatureAsync(order: Order): Promise<boolean> { + const isValidSignature = await this._exchange.isValidSignature( + order.params.maker, + order.params.orderHashHex, + order.params.v, + order.params.r, + order.params.s, + ); + return isValidSignature; + } + public async isRoundingErrorAsync( + numerator: BigNumber, + denominator: BigNumber, + target: BigNumber, + ): Promise<boolean> { + const isRoundingError = await this._exchange.isRoundingError(numerator, denominator, target); + return isRoundingError; + } + public async getPartialAmountAsync( + numerator: BigNumber, + denominator: BigNumber, + target: BigNumber, + ): Promise<BigNumber> { + const partialAmount = new BigNumber(await this._exchange.getPartialAmount(numerator, denominator, target)); + return partialAmount; + } } function wrapLogBigNumbers(log: any): any { - const argNames = _.keys(log.args); - for (const argName of argNames) { - const isWeb3BigNumber = _.startsWith(log.args[argName].constructor.toString(), 'function BigNumber('); - if (isWeb3BigNumber) { - log.args[argName] = new BigNumber(log.args[argName]); - } - } + const argNames = _.keys(log.args); + for (const argName of argNames) { + const isWeb3BigNumber = _.startsWith(log.args[argName].constructor.toString(), 'function BigNumber('); + if (isWeb3BigNumber) { + log.args[argName] = new BigNumber(log.args[argName]); + } + } } diff --git a/packages/contracts/util/formatters.ts b/packages/contracts/util/formatters.ts index c452b8e79..0d0ef6df4 100644 --- a/packages/contracts/util/formatters.ts +++ b/packages/contracts/util/formatters.ts @@ -5,107 +5,107 @@ import { Order } from './order'; import { BatchCancelOrders, BatchFillOrders, FillOrdersUpTo } from './types'; export const formatters = { - createBatchFill( - orders: Order[], - shouldThrowOnInsufficientBalanceOrAllowance: boolean, - fillTakerTokenAmounts: BigNumber[] = [], - ) { - const batchFill: BatchFillOrders = { - orderAddresses: [], - orderValues: [], - fillTakerTokenAmounts, - shouldThrowOnInsufficientBalanceOrAllowance, - v: [], - r: [], - s: [], - }; - _.forEach(orders, order => { - batchFill.orderAddresses.push([ - order.params.maker, - order.params.taker, - order.params.makerToken, - order.params.takerToken, - order.params.feeRecipient, - ]); - batchFill.orderValues.push([ - order.params.makerTokenAmount, - order.params.takerTokenAmount, - order.params.makerFee, - order.params.takerFee, - order.params.expirationTimestampInSec, - order.params.salt, - ]); - batchFill.v.push(order.params.v); - batchFill.r.push(order.params.r); - batchFill.s.push(order.params.s); - if (fillTakerTokenAmounts.length < orders.length) { - batchFill.fillTakerTokenAmounts.push(order.params.takerTokenAmount); - } - }); - return batchFill; - }, - createFillUpTo( - orders: Order[], - shouldThrowOnInsufficientBalanceOrAllowance: boolean, - fillTakerTokenAmount: BigNumber, - ) { - const fillUpTo: FillOrdersUpTo = { - orderAddresses: [], - orderValues: [], - fillTakerTokenAmount, - shouldThrowOnInsufficientBalanceOrAllowance, - v: [], - r: [], - s: [], - }; - orders.forEach(order => { - fillUpTo.orderAddresses.push([ - order.params.maker, - order.params.taker, - order.params.makerToken, - order.params.takerToken, - order.params.feeRecipient, - ]); - fillUpTo.orderValues.push([ - order.params.makerTokenAmount, - order.params.takerTokenAmount, - order.params.makerFee, - order.params.takerFee, - order.params.expirationTimestampInSec, - order.params.salt, - ]); - fillUpTo.v.push(order.params.v); - fillUpTo.r.push(order.params.r); - fillUpTo.s.push(order.params.s); - }); - return fillUpTo; - }, - createBatchCancel(orders: Order[], cancelTakerTokenAmounts: BigNumber[] = []) { - const batchCancel: BatchCancelOrders = { - orderAddresses: [], - orderValues: [], - cancelTakerTokenAmounts, - }; - orders.forEach(order => { - batchCancel.orderAddresses.push([ - order.params.maker, - order.params.taker, - order.params.makerToken, - order.params.takerToken, - order.params.feeRecipient, - ]); - batchCancel.orderValues.push([ - order.params.makerTokenAmount, - order.params.takerTokenAmount, - order.params.makerFee, - order.params.takerFee, - order.params.expirationTimestampInSec, - order.params.salt, - ]); - if (cancelTakerTokenAmounts.length < orders.length) { - batchCancel.cancelTakerTokenAmounts.push(order.params.takerTokenAmount); - } - }); - return batchCancel; - }, + createBatchFill( + orders: Order[], + shouldThrowOnInsufficientBalanceOrAllowance: boolean, + fillTakerTokenAmounts: BigNumber[] = [], + ) { + const batchFill: BatchFillOrders = { + orderAddresses: [], + orderValues: [], + fillTakerTokenAmounts, + shouldThrowOnInsufficientBalanceOrAllowance, + v: [], + r: [], + s: [], + }; + _.forEach(orders, order => { + batchFill.orderAddresses.push([ + order.params.maker, + order.params.taker, + order.params.makerToken, + order.params.takerToken, + order.params.feeRecipient, + ]); + batchFill.orderValues.push([ + order.params.makerTokenAmount, + order.params.takerTokenAmount, + order.params.makerFee, + order.params.takerFee, + order.params.expirationTimestampInSec, + order.params.salt, + ]); + batchFill.v.push(order.params.v); + batchFill.r.push(order.params.r); + batchFill.s.push(order.params.s); + if (fillTakerTokenAmounts.length < orders.length) { + batchFill.fillTakerTokenAmounts.push(order.params.takerTokenAmount); + } + }); + return batchFill; + }, + createFillUpTo( + orders: Order[], + shouldThrowOnInsufficientBalanceOrAllowance: boolean, + fillTakerTokenAmount: BigNumber, + ) { + const fillUpTo: FillOrdersUpTo = { + orderAddresses: [], + orderValues: [], + fillTakerTokenAmount, + shouldThrowOnInsufficientBalanceOrAllowance, + v: [], + r: [], + s: [], + }; + orders.forEach(order => { + fillUpTo.orderAddresses.push([ + order.params.maker, + order.params.taker, + order.params.makerToken, + order.params.takerToken, + order.params.feeRecipient, + ]); + fillUpTo.orderValues.push([ + order.params.makerTokenAmount, + order.params.takerTokenAmount, + order.params.makerFee, + order.params.takerFee, + order.params.expirationTimestampInSec, + order.params.salt, + ]); + fillUpTo.v.push(order.params.v); + fillUpTo.r.push(order.params.r); + fillUpTo.s.push(order.params.s); + }); + return fillUpTo; + }, + createBatchCancel(orders: Order[], cancelTakerTokenAmounts: BigNumber[] = []) { + const batchCancel: BatchCancelOrders = { + orderAddresses: [], + orderValues: [], + cancelTakerTokenAmounts, + }; + orders.forEach(order => { + batchCancel.orderAddresses.push([ + order.params.maker, + order.params.taker, + order.params.makerToken, + order.params.takerToken, + order.params.feeRecipient, + ]); + batchCancel.orderValues.push([ + order.params.makerTokenAmount, + order.params.takerTokenAmount, + order.params.makerFee, + order.params.takerFee, + order.params.expirationTimestampInSec, + order.params.salt, + ]); + if (cancelTakerTokenAmounts.length < orders.length) { + batchCancel.cancelTakerTokenAmounts.push(order.params.takerTokenAmount); + } + }); + return batchCancel; + }, }; diff --git a/packages/contracts/util/multi_sig_wrapper.ts b/packages/contracts/util/multi_sig_wrapper.ts index ca9f07ce5..0e2e671ec 100644 --- a/packages/contracts/util/multi_sig_wrapper.ts +++ b/packages/contracts/util/multi_sig_wrapper.ts @@ -6,34 +6,34 @@ import * as Web3 from 'web3'; import { ContractInstance, TransactionDataParams } from './types'; export class MultiSigWrapper { - private _multiSig: ContractInstance; - public static encodeFnArgs(name: string, abi: Web3.AbiDefinition[], args: any[]) { - const abiEntity = _.find(abi, { name }) as Web3.MethodAbi; - if (_.isUndefined(abiEntity)) { - throw new Error(`Did not find abi entry for name: ${name}`); - } - const types = _.map(abiEntity.inputs, input => input.type); - const funcSig = ethUtil.bufferToHex(ABI.methodID(name, types)); - const argsData = _.map(args, arg => { - const target = _.isBoolean(arg) ? +arg : arg; - const targetBuff = ethUtil.toBuffer(target); - return ethUtil.setLengthLeft(targetBuff, 32).toString('hex'); - }); - return funcSig + argsData.join(''); - } - constructor(multiSigContractInstance: ContractInstance) { - this._multiSig = multiSigContractInstance; - } - public async submitTransactionAsync( - destination: string, - from: string, - dataParams: TransactionDataParams, - value: number = 0, - ) { - const { name, abi, args = [] } = dataParams; - const encoded = MultiSigWrapper.encodeFnArgs(name, abi, args); - return this._multiSig.submitTransaction(destination, value, encoded, { - from, - }); - } + private _multiSig: ContractInstance; + public static encodeFnArgs(name: string, abi: Web3.AbiDefinition[], args: any[]) { + const abiEntity = _.find(abi, { name }) as Web3.MethodAbi; + if (_.isUndefined(abiEntity)) { + throw new Error(`Did not find abi entry for name: ${name}`); + } + const types = _.map(abiEntity.inputs, input => input.type); + const funcSig = ethUtil.bufferToHex(ABI.methodID(name, types)); + const argsData = _.map(args, arg => { + const target = _.isBoolean(arg) ? +arg : arg; + const targetBuff = ethUtil.toBuffer(target); + return ethUtil.setLengthLeft(targetBuff, 32).toString('hex'); + }); + return funcSig + argsData.join(''); + } + constructor(multiSigContractInstance: ContractInstance) { + this._multiSig = multiSigContractInstance; + } + public async submitTransactionAsync( + destination: string, + from: string, + dataParams: TransactionDataParams, + value: number = 0, + ) { + const { name, abi, args = [] } = dataParams; + const encoded = MultiSigWrapper.encodeFnArgs(name, abi, args); + return this._multiSig.submitTransaction(destination, value, encoded, { + from, + }); + } } diff --git a/packages/contracts/util/order.ts b/packages/contracts/util/order.ts index 31194c03e..e202d485b 100644 --- a/packages/contracts/util/order.ts +++ b/packages/contracts/util/order.ts @@ -11,98 +11,98 @@ import { OrderParams } from './types'; const web3: Web3 = (global as any).web3; export class Order { - public params: OrderParams; - constructor(params: OrderParams) { - this.params = params; - } - public isValidSignature() { - const { v, r, s } = this.params; - if (_.isUndefined(v) || _.isUndefined(r) || _.isUndefined(s)) { - throw new Error('Cannot call isValidSignature on unsigned order'); - } - const orderHash = this._getOrderHash(); - const msgHash = ethUtil.hashPersonalMessage(ethUtil.toBuffer(orderHash)); - try { - const pubKey = ethUtil.ecrecover(msgHash, v, ethUtil.toBuffer(r), ethUtil.toBuffer(s)); - const recoveredAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey)); - return recoveredAddress === this.params.maker; - } catch (err) { - return false; - } - } - public async signAsync() { - const orderHash = this._getOrderHash(); - const signature = await promisify<string>(web3.eth.sign)(this.params.maker, orderHash); - const { v, r, s } = ethUtil.fromRpcSig(signature); - this.params = _.assign(this.params, { - orderHashHex: orderHash, - v, - r: ethUtil.bufferToHex(r), - s: ethUtil.bufferToHex(s), - }); - } - public createFill(shouldThrowOnInsufficientBalanceOrAllowance?: boolean, fillTakerTokenAmount?: BigNumber) { - const fill = { - orderAddresses: [ - this.params.maker, - this.params.taker, - this.params.makerToken, - this.params.takerToken, - this.params.feeRecipient, - ], - orderValues: [ - this.params.makerTokenAmount, - this.params.takerTokenAmount, - this.params.makerFee, - this.params.takerFee, - this.params.expirationTimestampInSec, - this.params.salt, - ], - fillTakerTokenAmount: fillTakerTokenAmount || this.params.takerTokenAmount, - shouldThrowOnInsufficientBalanceOrAllowance: !!shouldThrowOnInsufficientBalanceOrAllowance, - v: this.params.v, - r: this.params.r, - s: this.params.s, - }; - return fill; - } - public createCancel(cancelTakerTokenAmount?: BigNumber) { - const cancel = { - orderAddresses: [ - this.params.maker, - this.params.taker, - this.params.makerToken, - this.params.takerToken, - this.params.feeRecipient, - ], - orderValues: [ - this.params.makerTokenAmount, - this.params.takerTokenAmount, - this.params.makerFee, - this.params.takerFee, - this.params.expirationTimestampInSec, - this.params.salt, - ], - cancelTakerTokenAmount: cancelTakerTokenAmount || this.params.takerTokenAmount, - }; - return cancel; - } - private _getOrderHash(): string { - const orderHash = crypto.solSHA3([ - this.params.exchangeContractAddress, - this.params.maker, - this.params.taker, - this.params.makerToken, - this.params.takerToken, - this.params.feeRecipient, - this.params.makerTokenAmount, - this.params.takerTokenAmount, - this.params.makerFee, - this.params.takerFee, - this.params.expirationTimestampInSec, - this.params.salt, - ]); - const orderHashHex = ethUtil.bufferToHex(orderHash); - return orderHashHex; - } + public params: OrderParams; + constructor(params: OrderParams) { + this.params = params; + } + public isValidSignature() { + const { v, r, s } = this.params; + if (_.isUndefined(v) || _.isUndefined(r) || _.isUndefined(s)) { + throw new Error('Cannot call isValidSignature on unsigned order'); + } + const orderHash = this._getOrderHash(); + const msgHash = ethUtil.hashPersonalMessage(ethUtil.toBuffer(orderHash)); + try { + const pubKey = ethUtil.ecrecover(msgHash, v, ethUtil.toBuffer(r), ethUtil.toBuffer(s)); + const recoveredAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey)); + return recoveredAddress === this.params.maker; + } catch (err) { + return false; + } + } + public async signAsync() { + const orderHash = this._getOrderHash(); + const signature = await promisify<string>(web3.eth.sign)(this.params.maker, orderHash); + const { v, r, s } = ethUtil.fromRpcSig(signature); + this.params = _.assign(this.params, { + orderHashHex: orderHash, + v, + r: ethUtil.bufferToHex(r), + s: ethUtil.bufferToHex(s), + }); + } + public createFill(shouldThrowOnInsufficientBalanceOrAllowance?: boolean, fillTakerTokenAmount?: BigNumber) { + const fill = { + orderAddresses: [ + this.params.maker, + this.params.taker, + this.params.makerToken, + this.params.takerToken, + this.params.feeRecipient, + ], + orderValues: [ + this.params.makerTokenAmount, + this.params.takerTokenAmount, + this.params.makerFee, + this.params.takerFee, + this.params.expirationTimestampInSec, + this.params.salt, + ], + fillTakerTokenAmount: fillTakerTokenAmount || this.params.takerTokenAmount, + shouldThrowOnInsufficientBalanceOrAllowance: !!shouldThrowOnInsufficientBalanceOrAllowance, + v: this.params.v, + r: this.params.r, + s: this.params.s, + }; + return fill; + } + public createCancel(cancelTakerTokenAmount?: BigNumber) { + const cancel = { + orderAddresses: [ + this.params.maker, + this.params.taker, + this.params.makerToken, + this.params.takerToken, + this.params.feeRecipient, + ], + orderValues: [ + this.params.makerTokenAmount, + this.params.takerTokenAmount, + this.params.makerFee, + this.params.takerFee, + this.params.expirationTimestampInSec, + this.params.salt, + ], + cancelTakerTokenAmount: cancelTakerTokenAmount || this.params.takerTokenAmount, + }; + return cancel; + } + private _getOrderHash(): string { + const orderHash = crypto.solSHA3([ + this.params.exchangeContractAddress, + this.params.maker, + this.params.taker, + this.params.makerToken, + this.params.takerToken, + this.params.feeRecipient, + this.params.makerTokenAmount, + this.params.takerTokenAmount, + this.params.makerFee, + this.params.takerFee, + this.params.expirationTimestampInSec, + this.params.salt, + ]); + const orderHashHex = ethUtil.bufferToHex(orderHash); + return orderHashHex; + } } diff --git a/packages/contracts/util/order_factory.ts b/packages/contracts/util/order_factory.ts index 55034655b..a45877de0 100644 --- a/packages/contracts/util/order_factory.ts +++ b/packages/contracts/util/order_factory.ts @@ -6,24 +6,24 @@ import { Order } from './order'; import { DefaultOrderParams, OptionalOrderParams, OrderParams } from './types'; export class OrderFactory { - private _defaultOrderParams: DefaultOrderParams; - constructor(defaultOrderParams: DefaultOrderParams) { - this._defaultOrderParams = defaultOrderParams; - } - public async newSignedOrderAsync(customOrderParams: OptionalOrderParams = {}) { - const randomExpiration = new BigNumber(Math.floor((Date.now() + Math.random() * 100000000000) / 1000)); - const orderParams: OrderParams = _.assign( - {}, - { - expirationTimestampInSec: randomExpiration, - salt: ZeroEx.generatePseudoRandomSalt(), - taker: ZeroEx.NULL_ADDRESS, - }, - this._defaultOrderParams, - customOrderParams, - ); - const order = new Order(orderParams); - await order.signAsync(); - return order; - } + private _defaultOrderParams: DefaultOrderParams; + constructor(defaultOrderParams: DefaultOrderParams) { + this._defaultOrderParams = defaultOrderParams; + } + public async newSignedOrderAsync(customOrderParams: OptionalOrderParams = {}) { + const randomExpiration = new BigNumber(Math.floor((Date.now() + Math.random() * 100000000000) / 1000)); + const orderParams: OrderParams = _.assign( + {}, + { + expirationTimestampInSec: randomExpiration, + salt: ZeroEx.generatePseudoRandomSalt(), + taker: ZeroEx.NULL_ADDRESS, + }, + this._defaultOrderParams, + customOrderParams, + ); + const order = new Order(orderParams); + await order.signAsync(); + return order; + } } diff --git a/packages/contracts/util/token_registry_wrapper.ts b/packages/contracts/util/token_registry_wrapper.ts index d1983db7c..07a577dea 100644 --- a/packages/contracts/util/token_registry_wrapper.ts +++ b/packages/contracts/util/token_registry_wrapper.ts @@ -1,56 +1,56 @@ import { ContractInstance, Token } from './types'; export class TokenRegWrapper { - private _tokenReg: ContractInstance; - constructor(tokenRegContractInstance: ContractInstance) { - this._tokenReg = tokenRegContractInstance; - } - public addTokenAsync(token: Token, from: string) { - const tx = this._tokenReg.addToken( - token.address, - token.name, - token.symbol, - token.decimals, - token.ipfsHash, - token.swarmHash, - { from }, - ); - return tx; - } - public async getTokenMetaDataAsync(tokenAddress: string) { - const data = await this._tokenReg.getTokenMetaData(tokenAddress); - const token: Token = { - address: data[0], - name: data[1], - symbol: data[2], - decimals: data[3].toNumber(), - ipfsHash: data[4], - swarmHash: data[5], - }; - return token; - } - public async getTokenByNameAsync(tokenName: string) { - const data = await this._tokenReg.getTokenByName(tokenName); - const token: Token = { - address: data[0], - name: data[1], - symbol: data[2], - decimals: data[3].toNumber(), - ipfsHash: data[4], - swarmHash: data[5], - }; - return token; - } - public async getTokenBySymbolAsync(tokenSymbol: string) { - const data = await this._tokenReg.getTokenBySymbol(tokenSymbol); - const token: Token = { - address: data[0], - name: data[1], - symbol: data[2], - decimals: data[3].toNumber(), - ipfsHash: data[4], - swarmHash: data[5], - }; - return token; - } + private _tokenReg: ContractInstance; + constructor(tokenRegContractInstance: ContractInstance) { + this._tokenReg = tokenRegContractInstance; + } + public addTokenAsync(token: Token, from: string) { + const tx = this._tokenReg.addToken( + token.address, + token.name, + token.symbol, + token.decimals, + token.ipfsHash, + token.swarmHash, + { from }, + ); + return tx; + } + public async getTokenMetaDataAsync(tokenAddress: string) { + const data = await this._tokenReg.getTokenMetaData(tokenAddress); + const token: Token = { + address: data[0], + name: data[1], + symbol: data[2], + decimals: data[3].toNumber(), + ipfsHash: data[4], + swarmHash: data[5], + }; + return token; + } + public async getTokenByNameAsync(tokenName: string) { + const data = await this._tokenReg.getTokenByName(tokenName); + const token: Token = { + address: data[0], + name: data[1], + symbol: data[2], + decimals: data[3].toNumber(), + ipfsHash: data[4], + swarmHash: data[5], + }; + return token; + } + public async getTokenBySymbolAsync(tokenSymbol: string) { + const data = await this._tokenReg.getTokenBySymbol(tokenSymbol); + const token: Token = { + address: data[0], + name: data[1], + symbol: data[2], + decimals: data[3].toNumber(), + ipfsHash: data[4], + swarmHash: data[5], + }; + return token; + } } diff --git a/packages/contracts/util/types.ts b/packages/contracts/util/types.ts index 675f3f17d..e511ca9f4 100644 --- a/packages/contracts/util/types.ts +++ b/packages/contracts/util/types.ts @@ -2,118 +2,118 @@ import { BigNumber } from '@0xproject/utils'; import * as Web3 from 'web3'; export interface BalancesByOwner { - [ownerAddress: string]: { - [tokenAddress: string]: BigNumber; - }; + [ownerAddress: string]: { + [tokenAddress: string]: BigNumber; + }; } export interface BatchFillOrders { - orderAddresses: string[][]; - orderValues: BigNumber[][]; - fillTakerTokenAmounts: BigNumber[]; - shouldThrowOnInsufficientBalanceOrAllowance: boolean; - v: number[]; - r: string[]; - s: string[]; + orderAddresses: string[][]; + orderValues: BigNumber[][]; + fillTakerTokenAmounts: BigNumber[]; + shouldThrowOnInsufficientBalanceOrAllowance: boolean; + v: number[]; + r: string[]; + s: string[]; } export interface FillOrdersUpTo { - orderAddresses: string[][]; - orderValues: BigNumber[][]; - fillTakerTokenAmount: BigNumber; - shouldThrowOnInsufficientBalanceOrAllowance: boolean; - v: number[]; - r: string[]; - s: string[]; + orderAddresses: string[][]; + orderValues: BigNumber[][]; + fillTakerTokenAmount: BigNumber; + shouldThrowOnInsufficientBalanceOrAllowance: boolean; + v: number[]; + r: string[]; + s: string[]; } export interface BatchCancelOrders { - orderAddresses: string[][]; - orderValues: BigNumber[][]; - cancelTakerTokenAmounts: BigNumber[]; + orderAddresses: string[][]; + orderValues: BigNumber[][]; + cancelTakerTokenAmounts: BigNumber[]; } export interface DefaultOrderParams { - exchangeContractAddress: string; - maker: string; - feeRecipient: string; - makerToken: string; - takerToken: string; - makerTokenAmount: BigNumber; - takerTokenAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; + exchangeContractAddress: string; + maker: string; + feeRecipient: string; + makerToken: string; + takerToken: string; + makerTokenAmount: BigNumber; + takerTokenAmount: BigNumber; + makerFee: BigNumber; + takerFee: BigNumber; } export interface OptionalOrderParams { - exchangeContractAddress?: string; - maker?: string; - taker?: string; - feeRecipient?: string; - makerToken?: string; - takerToken?: string; - makerTokenAmount?: BigNumber; - takerTokenAmount?: BigNumber; - makerFee?: BigNumber; - takerFee?: BigNumber; - expirationTimestampInSec?: BigNumber; + exchangeContractAddress?: string; + maker?: string; + taker?: string; + feeRecipient?: string; + makerToken?: string; + takerToken?: string; + makerTokenAmount?: BigNumber; + takerTokenAmount?: BigNumber; + makerFee?: BigNumber; + takerFee?: BigNumber; + expirationTimestampInSec?: BigNumber; } export interface OrderParams { - exchangeContractAddress: string; - maker: string; - taker: string; - feeRecipient: string; - makerToken: string; - takerToken: string; - makerTokenAmount: BigNumber; - takerTokenAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimestampInSec: BigNumber; - salt: BigNumber; - orderHashHex?: string; - v?: number; - r?: string; - s?: string; + exchangeContractAddress: string; + maker: string; + taker: string; + feeRecipient: string; + makerToken: string; + takerToken: string; + makerTokenAmount: BigNumber; + takerTokenAmount: BigNumber; + makerFee: BigNumber; + takerFee: BigNumber; + expirationTimestampInSec: BigNumber; + salt: BigNumber; + orderHashHex?: string; + v?: number; + r?: string; + s?: string; } export interface TransactionDataParams { - name: string; - abi: Web3.AbiDefinition[]; - args: any[]; + name: string; + abi: Web3.AbiDefinition[]; + args: any[]; } export interface MultiSigConfig { - owners: string[]; - confirmationsRequired: number; - secondsRequired: number; + owners: string[]; + confirmationsRequired: number; + secondsRequired: number; } export interface MultiSigConfigByNetwork { - [networkName: string]: MultiSigConfig; + [networkName: string]: MultiSigConfig; } export interface Token { - address?: string; - name: string; - symbol: string; - decimals: number; - ipfsHash: string; - swarmHash: string; + address?: string; + name: string; + symbol: string; + decimals: number; + ipfsHash: string; + swarmHash: string; } export interface TokenInfoByNetwork { - development: Token[]; - live: Token[]; + development: Token[]; + live: Token[]; } // Named type aliases to improve readability export type ContractInstance = any; export enum ExchangeContractErrs { - ERROR_ORDER_EXPIRED, - ERROR_ORDER_FULLY_FILLED_OR_CANCELLED, - ERROR_ROUNDING_ERROR_TOO_LARGE, - ERROR_INSUFFICIENT_BALANCE_OR_ALLOWANCE, + ERROR_ORDER_EXPIRED, + ERROR_ORDER_FULLY_FILLED_OR_CANCELLED, + ERROR_ROUNDING_ERROR_TOO_LARGE, + ERROR_INSUFFICIENT_BALANCE_OR_ALLOWANCE, } |