diff options
author | Fabio Berger <me@fabioberger.com> | 2018-01-30 20:21:01 +0800 |
---|---|---|
committer | Fabio Berger <me@fabioberger.com> | 2018-01-30 20:21:01 +0800 |
commit | 93a5b3f457c1211676296840c285759007a55500 (patch) | |
tree | d1682b657c207f447748e08550095bafc79b6997 /packages/0x.js/src/contract_wrappers/exchange_wrapper.ts | |
parent | 4242176d291f54212797de9f5df80b1346724ebb (diff) | |
download | dexon-0x-contracts-93a5b3f457c1211676296840c285759007a55500.tar dexon-0x-contracts-93a5b3f457c1211676296840c285759007a55500.tar.gz dexon-0x-contracts-93a5b3f457c1211676296840c285759007a55500.tar.bz2 dexon-0x-contracts-93a5b3f457c1211676296840c285759007a55500.tar.lz dexon-0x-contracts-93a5b3f457c1211676296840c285759007a55500.tar.xz dexon-0x-contracts-93a5b3f457c1211676296840c285759007a55500.tar.zst dexon-0x-contracts-93a5b3f457c1211676296840c285759007a55500.zip |
Fix prettier
Diffstat (limited to 'packages/0x.js/src/contract_wrappers/exchange_wrapper.ts')
-rw-r--r-- | packages/0x.js/src/contract_wrappers/exchange_wrapper.ts | 1718 |
1 files changed, 859 insertions, 859 deletions
diff --git a/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts b/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts index 2b6117729..668893d45 100644 --- a/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts +++ b/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts @@ -6,27 +6,27 @@ import * as Web3 from 'web3'; import { artifacts } from '../artifacts'; import { - BlockParamLiteral, - BlockRange, - DecodedLogArgs, - ECSignature, - EventCallback, - ExchangeContractErrCodes, - ExchangeContractErrs, - ExchangeContractEventArgs, - ExchangeEvents, - IndexedFilterValues, - LogErrorContractEventArgs, - LogWithDecodedArgs, - MethodOpts, - Order, - OrderAddresses, - OrderCancellationRequest, - OrderFillRequest, - OrderTransactionOpts, - OrderValues, - SignedOrder, - ValidateOrderFillableOpts, + BlockParamLiteral, + BlockRange, + DecodedLogArgs, + ECSignature, + EventCallback, + ExchangeContractErrCodes, + ExchangeContractErrs, + ExchangeContractEventArgs, + ExchangeEvents, + IndexedFilterValues, + LogErrorContractEventArgs, + LogWithDecodedArgs, + MethodOpts, + Order, + OrderAddresses, + OrderCancellationRequest, + OrderFillRequest, + OrderTransactionOpts, + OrderValues, + SignedOrder, + ValidateOrderFillableOpts, } from '../types'; import { AbiDecoder } from '../utils/abi_decoder'; import { assert } from '../utils/assert'; @@ -42,7 +42,7 @@ import { TokenWrapper } from './token_wrapper'; const SHOULD_VALIDATE_BY_DEFAULT = true; interface ExchangeContractErrCodesToMsgs { - [exchangeContractErrCodes: number]: string; + [exchangeContractErrCodes: number]: string; } /** @@ -50,864 +50,864 @@ interface ExchangeContractErrCodesToMsgs { * events of the 0x Exchange smart contract. */ export class ExchangeWrapper extends ContractWrapper { - private _exchangeContractIfExists?: ExchangeContract; - private _orderValidationUtils: OrderValidationUtils; - private _tokenWrapper: TokenWrapper; - private _exchangeContractErrCodesToMsg: ExchangeContractErrCodesToMsgs = { - [ExchangeContractErrCodes.ERROR_FILL_EXPIRED]: ExchangeContractErrs.OrderFillExpired, - [ExchangeContractErrCodes.ERROR_CANCEL_EXPIRED]: ExchangeContractErrs.OrderFillExpired, - [ExchangeContractErrCodes.ERROR_FILL_NO_VALUE]: ExchangeContractErrs.OrderRemainingFillAmountZero, - [ExchangeContractErrCodes.ERROR_CANCEL_NO_VALUE]: ExchangeContractErrs.OrderRemainingFillAmountZero, - [ExchangeContractErrCodes.ERROR_FILL_TRUNCATION]: ExchangeContractErrs.OrderFillRoundingError, - [ExchangeContractErrCodes.ERROR_FILL_BALANCE_ALLOWANCE]: ExchangeContractErrs.FillBalanceAllowanceError, - }; - private _contractAddressIfExists?: string; - private _zrxContractAddressIfExists?: string; - private static _getOrderAddressesAndValues(order: Order): [OrderAddresses, OrderValues] { - const orderAddresses: OrderAddresses = [ - order.maker, - order.taker, - order.makerTokenAddress, - order.takerTokenAddress, - order.feeRecipient, - ]; - const orderValues: OrderValues = [ - order.makerTokenAmount, - order.takerTokenAmount, - order.makerFee, - order.takerFee, - order.expirationUnixTimestampSec, - order.salt, - ]; - return [orderAddresses, orderValues]; - } - constructor( - web3Wrapper: Web3Wrapper, - networkId: number, - abiDecoder: AbiDecoder, - tokenWrapper: TokenWrapper, - contractAddressIfExists?: string, - zrxContractAddressIfExists?: string, - ) { - super(web3Wrapper, networkId, abiDecoder); - this._tokenWrapper = tokenWrapper; - this._orderValidationUtils = new OrderValidationUtils(this); - this._contractAddressIfExists = contractAddressIfExists; - this._zrxContractAddressIfExists = zrxContractAddressIfExists; - } - /** - * Returns the unavailable takerAmount of an order. Unavailable amount is defined as the total - * amount that has been filled or cancelled. The remaining takerAmount can be calculated by - * subtracting the unavailable amount from the total order takerAmount. - * @param orderHash The hex encoded orderHash for which you would like to retrieve the - * unavailable takerAmount. - * @param methodOpts Optional arguments this method accepts. - * @return The amount of the order (in taker tokens) that has either been filled or cancelled. - */ - public async getUnavailableTakerAmountAsync(orderHash: string, methodOpts?: MethodOpts): Promise<BigNumber> { - assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema); + private _exchangeContractIfExists?: ExchangeContract; + private _orderValidationUtils: OrderValidationUtils; + private _tokenWrapper: TokenWrapper; + private _exchangeContractErrCodesToMsg: ExchangeContractErrCodesToMsgs = { + [ExchangeContractErrCodes.ERROR_FILL_EXPIRED]: ExchangeContractErrs.OrderFillExpired, + [ExchangeContractErrCodes.ERROR_CANCEL_EXPIRED]: ExchangeContractErrs.OrderFillExpired, + [ExchangeContractErrCodes.ERROR_FILL_NO_VALUE]: ExchangeContractErrs.OrderRemainingFillAmountZero, + [ExchangeContractErrCodes.ERROR_CANCEL_NO_VALUE]: ExchangeContractErrs.OrderRemainingFillAmountZero, + [ExchangeContractErrCodes.ERROR_FILL_TRUNCATION]: ExchangeContractErrs.OrderFillRoundingError, + [ExchangeContractErrCodes.ERROR_FILL_BALANCE_ALLOWANCE]: ExchangeContractErrs.FillBalanceAllowanceError, + }; + private _contractAddressIfExists?: string; + private _zrxContractAddressIfExists?: string; + private static _getOrderAddressesAndValues(order: Order): [OrderAddresses, OrderValues] { + const orderAddresses: OrderAddresses = [ + order.maker, + order.taker, + order.makerTokenAddress, + order.takerTokenAddress, + order.feeRecipient, + ]; + const orderValues: OrderValues = [ + order.makerTokenAmount, + order.takerTokenAmount, + order.makerFee, + order.takerFee, + order.expirationUnixTimestampSec, + order.salt, + ]; + return [orderAddresses, orderValues]; + } + constructor( + web3Wrapper: Web3Wrapper, + networkId: number, + abiDecoder: AbiDecoder, + tokenWrapper: TokenWrapper, + contractAddressIfExists?: string, + zrxContractAddressIfExists?: string, + ) { + super(web3Wrapper, networkId, abiDecoder); + this._tokenWrapper = tokenWrapper; + this._orderValidationUtils = new OrderValidationUtils(this); + this._contractAddressIfExists = contractAddressIfExists; + this._zrxContractAddressIfExists = zrxContractAddressIfExists; + } + /** + * Returns the unavailable takerAmount of an order. Unavailable amount is defined as the total + * amount that has been filled or cancelled. The remaining takerAmount can be calculated by + * subtracting the unavailable amount from the total order takerAmount. + * @param orderHash The hex encoded orderHash for which you would like to retrieve the + * unavailable takerAmount. + * @param methodOpts Optional arguments this method accepts. + * @return The amount of the order (in taker tokens) that has either been filled or cancelled. + */ + public async getUnavailableTakerAmountAsync(orderHash: string, methodOpts?: MethodOpts): Promise<BigNumber> { + assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema); - const exchangeContract = await this._getExchangeContractAsync(); - const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock; - let unavailableTakerTokenAmount = await exchangeContract.getUnavailableTakerTokenAmount.callAsync( - orderHash, - defaultBlock, - ); - // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber - unavailableTakerTokenAmount = new BigNumber(unavailableTakerTokenAmount); - return unavailableTakerTokenAmount; - } - /** - * Retrieve the takerAmount of an order that has already been filled. - * @param orderHash The hex encoded orderHash for which you would like to retrieve the filled takerAmount. - * @param methodOpts Optional arguments this method accepts. - * @return The amount of the order (in taker tokens) that has already been filled. - */ - public async getFilledTakerAmountAsync(orderHash: string, methodOpts?: MethodOpts): Promise<BigNumber> { - assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema); + const exchangeContract = await this._getExchangeContractAsync(); + const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock; + let unavailableTakerTokenAmount = await exchangeContract.getUnavailableTakerTokenAmount.callAsync( + orderHash, + defaultBlock, + ); + // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber + unavailableTakerTokenAmount = new BigNumber(unavailableTakerTokenAmount); + return unavailableTakerTokenAmount; + } + /** + * Retrieve the takerAmount of an order that has already been filled. + * @param orderHash The hex encoded orderHash for which you would like to retrieve the filled takerAmount. + * @param methodOpts Optional arguments this method accepts. + * @return The amount of the order (in taker tokens) that has already been filled. + */ + public async getFilledTakerAmountAsync(orderHash: string, methodOpts?: MethodOpts): Promise<BigNumber> { + assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema); - const exchangeContract = await this._getExchangeContractAsync(); - const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock; - let fillAmountInBaseUnits = await exchangeContract.filled.callAsync(orderHash, defaultBlock); - // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber - fillAmountInBaseUnits = new BigNumber(fillAmountInBaseUnits); - return fillAmountInBaseUnits; - } - /** - * Retrieve the takerAmount of an order that has been cancelled. - * @param orderHash The hex encoded orderHash for which you would like to retrieve the - * cancelled takerAmount. - * @param methodOpts Optional arguments this method accepts. - * @return The amount of the order (in taker tokens) that has been cancelled. - */ - public async getCancelledTakerAmountAsync(orderHash: string, methodOpts?: MethodOpts): Promise<BigNumber> { - assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema); + const exchangeContract = await this._getExchangeContractAsync(); + const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock; + let fillAmountInBaseUnits = await exchangeContract.filled.callAsync(orderHash, defaultBlock); + // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber + fillAmountInBaseUnits = new BigNumber(fillAmountInBaseUnits); + return fillAmountInBaseUnits; + } + /** + * Retrieve the takerAmount of an order that has been cancelled. + * @param orderHash The hex encoded orderHash for which you would like to retrieve the + * cancelled takerAmount. + * @param methodOpts Optional arguments this method accepts. + * @return The amount of the order (in taker tokens) that has been cancelled. + */ + public async getCancelledTakerAmountAsync(orderHash: string, methodOpts?: MethodOpts): Promise<BigNumber> { + assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema); - const exchangeContract = await this._getExchangeContractAsync(); - const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock; - let cancelledAmountInBaseUnits = await exchangeContract.cancelled.callAsync(orderHash, defaultBlock); - // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber - cancelledAmountInBaseUnits = new BigNumber(cancelledAmountInBaseUnits); - return cancelledAmountInBaseUnits; - } - /** - * Fills a signed order with an amount denominated in baseUnits of the taker token. - * Since the order in which transactions are included in the next block is indeterminate, race-conditions - * could arise where a users balance or allowance changes before the fillOrder executes. Because of this, - * we allow you to specify `shouldThrowOnInsufficientBalanceOrAllowance`. - * If false, the smart contract will not throw if the parties - * do not have sufficient balances/allowances, preserving gas costs. Setting it to true forgoes this check - * and causes the smart contract to throw (using all the gas supplied) instead. - * @param signedOrder An object that conforms to the SignedOrder interface. - * @param fillTakerTokenAmount The amount of the order (in taker tokens baseUnits) that - * you wish to fill. - * @param shouldThrowOnInsufficientBalanceOrAllowance Whether or not you wish for the contract call to throw - * if upon execution the tokens cannot be transferred. - * @param takerAddress The user Ethereum address who would like to fill this order. - * Must be available via the supplied Web3.Provider - * passed to 0x.js. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async fillOrderAsync( - signedOrder: SignedOrder, - fillTakerTokenAmount: BigNumber, - shouldThrowOnInsufficientBalanceOrAllowance: boolean, - takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, - ): Promise<string> { - assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); - assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount); - assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); + const exchangeContract = await this._getExchangeContractAsync(); + const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock; + let cancelledAmountInBaseUnits = await exchangeContract.cancelled.callAsync(orderHash, defaultBlock); + // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber + cancelledAmountInBaseUnits = new BigNumber(cancelledAmountInBaseUnits); + return cancelledAmountInBaseUnits; + } + /** + * Fills a signed order with an amount denominated in baseUnits of the taker token. + * Since the order in which transactions are included in the next block is indeterminate, race-conditions + * could arise where a users balance or allowance changes before the fillOrder executes. Because of this, + * we allow you to specify `shouldThrowOnInsufficientBalanceOrAllowance`. + * If false, the smart contract will not throw if the parties + * do not have sufficient balances/allowances, preserving gas costs. Setting it to true forgoes this check + * and causes the smart contract to throw (using all the gas supplied) instead. + * @param signedOrder An object that conforms to the SignedOrder interface. + * @param fillTakerTokenAmount The amount of the order (in taker tokens baseUnits) that + * you wish to fill. + * @param shouldThrowOnInsufficientBalanceOrAllowance Whether or not you wish for the contract call to throw + * if upon execution the tokens cannot be transferred. + * @param takerAddress The user Ethereum address who would like to fill this order. + * Must be available via the supplied Web3.Provider + * passed to 0x.js. + * @param orderTransactionOpts Optional arguments this method accepts. + * @return Transaction hash. + */ + @decorators.asyncZeroExErrorHandler + public async fillOrderAsync( + signedOrder: SignedOrder, + fillTakerTokenAmount: BigNumber, + shouldThrowOnInsufficientBalanceOrAllowance: boolean, + takerAddress: string, + orderTransactionOpts: OrderTransactionOpts = {}, + ): Promise<string> { + assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); + assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount); + assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance); + await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - const exchangeInstance = await this._getExchangeContractAsync(); - const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) - ? SHOULD_VALIDATE_BY_DEFAULT - : orderTransactionOpts.shouldValidate; - if (shouldValidate) { - const zrxTokenAddress = this.getZRXTokenAddress(); - const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); - await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync( - exchangeTradeEmulator, - signedOrder, - fillTakerTokenAmount, - takerAddress, - zrxTokenAddress, - ); - } + const exchangeInstance = await this._getExchangeContractAsync(); + const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) + ? SHOULD_VALIDATE_BY_DEFAULT + : orderTransactionOpts.shouldValidate; + if (shouldValidate) { + const zrxTokenAddress = this.getZRXTokenAddress(); + const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); + await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync( + exchangeTradeEmulator, + signedOrder, + fillTakerTokenAmount, + takerAddress, + zrxTokenAddress, + ); + } - const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder); + const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder); - const txHash: string = await exchangeInstance.fillOrder.sendTransactionAsync( - orderAddresses, - orderValues, - fillTakerTokenAmount, - shouldThrowOnInsufficientBalanceOrAllowance, - signedOrder.ecSignature.v, - signedOrder.ecSignature.r, - signedOrder.ecSignature.s, - { - from: takerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - }, - ); - return txHash; - } - /** - * Sequentially and atomically fills signedOrders up to the specified takerTokenFillAmount. - * If the fill amount is reached - it succeeds and does not fill the rest of the orders. - * If fill amount is not reached - it fills as much of the fill amount as possible and succeeds. - * @param signedOrders The array of signedOrders that you would like to fill until - * takerTokenFillAmount is reached. - * @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill. - * @param shouldThrowOnInsufficientBalanceOrAllowance Whether or not you wish for the contract call to throw if - * upon execution any of the tokens cannot be transferred. - * If set to false, the call will continue to fill subsequent - * signedOrders even when some cannot be filled. - * @param takerAddress The user Ethereum address who would like to fill these - * orders. Must be available via the supplied Web3.Provider - * passed to 0x.js. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async fillOrdersUpToAsync( - signedOrders: SignedOrder[], - fillTakerTokenAmount: BigNumber, - shouldThrowOnInsufficientBalanceOrAllowance: boolean, - takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, - ): Promise<string> { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - const takerTokenAddresses = _.map(signedOrders, signedOrder => signedOrder.takerTokenAddress); - assert.hasAtMostOneUniqueValue( - takerTokenAddresses, - ExchangeContractErrs.MultipleTakerTokensInFillUpToDisallowed, - ); - const exchangeContractAddresses = _.map(signedOrders, signedOrder => signedOrder.exchangeContractAddress); - assert.hasAtMostOneUniqueValue( - exchangeContractAddresses, - ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress, - ); - assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount); - assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); + const txHash: string = await exchangeInstance.fillOrder.sendTransactionAsync( + orderAddresses, + orderValues, + fillTakerTokenAmount, + shouldThrowOnInsufficientBalanceOrAllowance, + signedOrder.ecSignature.v, + signedOrder.ecSignature.r, + signedOrder.ecSignature.s, + { + from: takerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }, + ); + return txHash; + } + /** + * Sequentially and atomically fills signedOrders up to the specified takerTokenFillAmount. + * If the fill amount is reached - it succeeds and does not fill the rest of the orders. + * If fill amount is not reached - it fills as much of the fill amount as possible and succeeds. + * @param signedOrders The array of signedOrders that you would like to fill until + * takerTokenFillAmount is reached. + * @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill. + * @param shouldThrowOnInsufficientBalanceOrAllowance Whether or not you wish for the contract call to throw if + * upon execution any of the tokens cannot be transferred. + * If set to false, the call will continue to fill subsequent + * signedOrders even when some cannot be filled. + * @param takerAddress The user Ethereum address who would like to fill these + * orders. Must be available via the supplied Web3.Provider + * passed to 0x.js. + * @param orderTransactionOpts Optional arguments this method accepts. + * @return Transaction hash. + */ + @decorators.asyncZeroExErrorHandler + public async fillOrdersUpToAsync( + signedOrders: SignedOrder[], + fillTakerTokenAmount: BigNumber, + shouldThrowOnInsufficientBalanceOrAllowance: boolean, + takerAddress: string, + orderTransactionOpts: OrderTransactionOpts = {}, + ): Promise<string> { + assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); + const takerTokenAddresses = _.map(signedOrders, signedOrder => signedOrder.takerTokenAddress); + assert.hasAtMostOneUniqueValue( + takerTokenAddresses, + ExchangeContractErrs.MultipleTakerTokensInFillUpToDisallowed, + ); + const exchangeContractAddresses = _.map(signedOrders, signedOrder => signedOrder.exchangeContractAddress); + assert.hasAtMostOneUniqueValue( + exchangeContractAddresses, + ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress, + ); + assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount); + assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance); + await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) - ? SHOULD_VALIDATE_BY_DEFAULT - : orderTransactionOpts.shouldValidate; - if (shouldValidate) { - let filledTakerTokenAmount = new BigNumber(0); - const zrxTokenAddress = this.getZRXTokenAddress(); - const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); - for (const signedOrder of signedOrders) { - const singleFilledTakerTokenAmount = await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync( - exchangeTradeEmulator, - signedOrder, - fillTakerTokenAmount.minus(filledTakerTokenAmount), - takerAddress, - zrxTokenAddress, - ); - filledTakerTokenAmount = filledTakerTokenAmount.plus(singleFilledTakerTokenAmount); - } - } + const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) + ? SHOULD_VALIDATE_BY_DEFAULT + : orderTransactionOpts.shouldValidate; + if (shouldValidate) { + let filledTakerTokenAmount = new BigNumber(0); + const zrxTokenAddress = this.getZRXTokenAddress(); + const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); + for (const signedOrder of signedOrders) { + const singleFilledTakerTokenAmount = await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync( + exchangeTradeEmulator, + signedOrder, + fillTakerTokenAmount.minus(filledTakerTokenAmount), + takerAddress, + zrxTokenAddress, + ); + filledTakerTokenAmount = filledTakerTokenAmount.plus(singleFilledTakerTokenAmount); + } + } - if (_.isEmpty(signedOrders)) { - throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem); - } + if (_.isEmpty(signedOrders)) { + throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem); + } - const orderAddressesValuesAndSignatureArray = _.map(signedOrders, signedOrder => { - return [ - ...ExchangeWrapper._getOrderAddressesAndValues(signedOrder), - signedOrder.ecSignature.v, - signedOrder.ecSignature.r, - signedOrder.ecSignature.s, - ]; - }); - // We use _.unzip<any> because _.unzip doesn't type check if values have different types :'( - const [orderAddressesArray, orderValuesArray, vArray, rArray, sArray] = _.unzip<any>( - orderAddressesValuesAndSignatureArray, - ); + const orderAddressesValuesAndSignatureArray = _.map(signedOrders, signedOrder => { + return [ + ...ExchangeWrapper._getOrderAddressesAndValues(signedOrder), + signedOrder.ecSignature.v, + signedOrder.ecSignature.r, + signedOrder.ecSignature.s, + ]; + }); + // We use _.unzip<any> because _.unzip doesn't type check if values have different types :'( + const [orderAddressesArray, orderValuesArray, vArray, rArray, sArray] = _.unzip<any>( + orderAddressesValuesAndSignatureArray, + ); - const exchangeInstance = await this._getExchangeContractAsync(); - const txHash = await exchangeInstance.fillOrdersUpTo.sendTransactionAsync( - orderAddressesArray, - orderValuesArray, - fillTakerTokenAmount, - shouldThrowOnInsufficientBalanceOrAllowance, - vArray, - rArray, - sArray, - { - from: takerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - }, - ); - return txHash; - } - /** - * Batch version of fillOrderAsync. - * Executes multiple fills atomically in a single transaction. - * If shouldThrowOnInsufficientBalanceOrAllowance is set to false, it will continue filling subsequent orders even - * when earlier ones fail. - * When shouldThrowOnInsufficientBalanceOrAllowance is set to true, if any fill fails, the entire batch fails. - * @param orderFillRequests An array of objects that conform to the - * OrderFillRequest interface. - * @param shouldThrowOnInsufficientBalanceOrAllowance Whether or not you wish for the contract call to throw - * if upon execution any of the tokens cannot be - * transferred. If set to false, the call will continue to - * fill subsequent signedOrders even when some - * cannot be filled. - * @param takerAddress The user Ethereum address who would like to fill - * these orders. Must be available via the supplied - * Web3.Provider passed to 0x.js. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async batchFillOrdersAsync( - orderFillRequests: OrderFillRequest[], - shouldThrowOnInsufficientBalanceOrAllowance: boolean, - takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, - ): Promise<string> { - assert.doesConformToSchema('orderFillRequests', orderFillRequests, schemas.orderFillRequestsSchema); - const exchangeContractAddresses = _.map( - orderFillRequests, - orderFillRequest => orderFillRequest.signedOrder.exchangeContractAddress, - ); - assert.hasAtMostOneUniqueValue( - exchangeContractAddresses, - ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress, - ); - assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) - ? SHOULD_VALIDATE_BY_DEFAULT - : orderTransactionOpts.shouldValidate; - if (shouldValidate) { - const zrxTokenAddress = this.getZRXTokenAddress(); - const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); - for (const orderFillRequest of orderFillRequests) { - await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync( - exchangeTradeEmulator, - orderFillRequest.signedOrder, - orderFillRequest.takerTokenFillAmount, - takerAddress, - zrxTokenAddress, - ); - } - } - if (_.isEmpty(orderFillRequests)) { - throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem); - } + const exchangeInstance = await this._getExchangeContractAsync(); + const txHash = await exchangeInstance.fillOrdersUpTo.sendTransactionAsync( + orderAddressesArray, + orderValuesArray, + fillTakerTokenAmount, + shouldThrowOnInsufficientBalanceOrAllowance, + vArray, + rArray, + sArray, + { + from: takerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }, + ); + return txHash; + } + /** + * Batch version of fillOrderAsync. + * Executes multiple fills atomically in a single transaction. + * If shouldThrowOnInsufficientBalanceOrAllowance is set to false, it will continue filling subsequent orders even + * when earlier ones fail. + * When shouldThrowOnInsufficientBalanceOrAllowance is set to true, if any fill fails, the entire batch fails. + * @param orderFillRequests An array of objects that conform to the + * OrderFillRequest interface. + * @param shouldThrowOnInsufficientBalanceOrAllowance Whether or not you wish for the contract call to throw + * if upon execution any of the tokens cannot be + * transferred. If set to false, the call will continue to + * fill subsequent signedOrders even when some + * cannot be filled. + * @param takerAddress The user Ethereum address who would like to fill + * these orders. Must be available via the supplied + * Web3.Provider passed to 0x.js. + * @param orderTransactionOpts Optional arguments this method accepts. + * @return Transaction hash. + */ + @decorators.asyncZeroExErrorHandler + public async batchFillOrdersAsync( + orderFillRequests: OrderFillRequest[], + shouldThrowOnInsufficientBalanceOrAllowance: boolean, + takerAddress: string, + orderTransactionOpts: OrderTransactionOpts = {}, + ): Promise<string> { + assert.doesConformToSchema('orderFillRequests', orderFillRequests, schemas.orderFillRequestsSchema); + const exchangeContractAddresses = _.map( + orderFillRequests, + orderFillRequest => orderFillRequest.signedOrder.exchangeContractAddress, + ); + assert.hasAtMostOneUniqueValue( + exchangeContractAddresses, + ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress, + ); + assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance); + await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); + const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) + ? SHOULD_VALIDATE_BY_DEFAULT + : orderTransactionOpts.shouldValidate; + if (shouldValidate) { + const zrxTokenAddress = this.getZRXTokenAddress(); + const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); + for (const orderFillRequest of orderFillRequests) { + await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync( + exchangeTradeEmulator, + orderFillRequest.signedOrder, + orderFillRequest.takerTokenFillAmount, + takerAddress, + zrxTokenAddress, + ); + } + } + if (_.isEmpty(orderFillRequests)) { + throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem); + } - const orderAddressesValuesAmountsAndSignatureArray = _.map(orderFillRequests, orderFillRequest => { - return [ - ...ExchangeWrapper._getOrderAddressesAndValues(orderFillRequest.signedOrder), - orderFillRequest.takerTokenFillAmount, - orderFillRequest.signedOrder.ecSignature.v, - orderFillRequest.signedOrder.ecSignature.r, - orderFillRequest.signedOrder.ecSignature.s, - ]; - }); - // We use _.unzip<any> because _.unzip doesn't type check if values have different types :'( - const [orderAddressesArray, orderValuesArray, fillTakerTokenAmounts, vArray, rArray, sArray] = _.unzip<any>( - orderAddressesValuesAmountsAndSignatureArray, - ); + const orderAddressesValuesAmountsAndSignatureArray = _.map(orderFillRequests, orderFillRequest => { + return [ + ...ExchangeWrapper._getOrderAddressesAndValues(orderFillRequest.signedOrder), + orderFillRequest.takerTokenFillAmount, + orderFillRequest.signedOrder.ecSignature.v, + orderFillRequest.signedOrder.ecSignature.r, + orderFillRequest.signedOrder.ecSignature.s, + ]; + }); + // We use _.unzip<any> because _.unzip doesn't type check if values have different types :'( + const [orderAddressesArray, orderValuesArray, fillTakerTokenAmounts, vArray, rArray, sArray] = _.unzip<any>( + orderAddressesValuesAmountsAndSignatureArray, + ); - const exchangeInstance = await this._getExchangeContractAsync(); - const txHash = await exchangeInstance.batchFillOrders.sendTransactionAsync( - orderAddressesArray, - orderValuesArray, - fillTakerTokenAmounts, - shouldThrowOnInsufficientBalanceOrAllowance, - vArray, - rArray, - sArray, - { - from: takerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - }, - ); - return txHash; - } - /** - * Attempts to fill a specific amount of an order. If the entire amount specified cannot be filled, - * the fill order is abandoned. - * @param signedOrder An object that conforms to the SignedOrder interface. The - * signedOrder you wish to fill. - * @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill. - * @param takerAddress The user Ethereum address who would like to fill this order. - * Must be available via the supplied Web3.Provider passed to 0x.js. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async fillOrKillOrderAsync( - signedOrder: SignedOrder, - fillTakerTokenAmount: BigNumber, - takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, - ): Promise<string> { - assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); - assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); + const exchangeInstance = await this._getExchangeContractAsync(); + const txHash = await exchangeInstance.batchFillOrders.sendTransactionAsync( + orderAddressesArray, + orderValuesArray, + fillTakerTokenAmounts, + shouldThrowOnInsufficientBalanceOrAllowance, + vArray, + rArray, + sArray, + { + from: takerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }, + ); + return txHash; + } + /** + * Attempts to fill a specific amount of an order. If the entire amount specified cannot be filled, + * the fill order is abandoned. + * @param signedOrder An object that conforms to the SignedOrder interface. The + * signedOrder you wish to fill. + * @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill. + * @param takerAddress The user Ethereum address who would like to fill this order. + * Must be available via the supplied Web3.Provider passed to 0x.js. + * @param orderTransactionOpts Optional arguments this method accepts. + * @return Transaction hash. + */ + @decorators.asyncZeroExErrorHandler + public async fillOrKillOrderAsync( + signedOrder: SignedOrder, + fillTakerTokenAmount: BigNumber, + takerAddress: string, + orderTransactionOpts: OrderTransactionOpts = {}, + ): Promise<string> { + assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); + assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount); + await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - const exchangeInstance = await this._getExchangeContractAsync(); + const exchangeInstance = await this._getExchangeContractAsync(); - const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) - ? SHOULD_VALIDATE_BY_DEFAULT - : orderTransactionOpts.shouldValidate; - if (shouldValidate) { - const zrxTokenAddress = this.getZRXTokenAddress(); - const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); - await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync( - exchangeTradeEmulator, - signedOrder, - fillTakerTokenAmount, - takerAddress, - zrxTokenAddress, - ); - } + const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) + ? SHOULD_VALIDATE_BY_DEFAULT + : orderTransactionOpts.shouldValidate; + if (shouldValidate) { + const zrxTokenAddress = this.getZRXTokenAddress(); + const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); + await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync( + exchangeTradeEmulator, + signedOrder, + fillTakerTokenAmount, + takerAddress, + zrxTokenAddress, + ); + } - const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder); - const txHash = await exchangeInstance.fillOrKillOrder.sendTransactionAsync( - orderAddresses, - orderValues, - fillTakerTokenAmount, - signedOrder.ecSignature.v, - signedOrder.ecSignature.r, - signedOrder.ecSignature.s, - { - from: takerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - }, - ); - return txHash; - } - /** - * Batch version of fillOrKill. Allows a taker to specify a batch of orders that will either be atomically - * filled (each to the specified fillAmount) or aborted. - * @param orderFillRequests An array of objects that conform to the OrderFillRequest interface. - * @param takerAddress The user Ethereum address who would like to fill there orders. - * Must be available via the supplied Web3.Provider passed to 0x.js. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async batchFillOrKillAsync( - orderFillRequests: OrderFillRequest[], - takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = {}, - ): Promise<string> { - assert.doesConformToSchema('orderFillRequests', orderFillRequests, schemas.orderFillRequestsSchema); - const exchangeContractAddresses = _.map( - orderFillRequests, - orderFillRequest => orderFillRequest.signedOrder.exchangeContractAddress, - ); - assert.hasAtMostOneUniqueValue( - exchangeContractAddresses, - ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress, - ); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - if (_.isEmpty(orderFillRequests)) { - throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem); - } - const exchangeInstance = await this._getExchangeContractAsync(); + const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder); + const txHash = await exchangeInstance.fillOrKillOrder.sendTransactionAsync( + orderAddresses, + orderValues, + fillTakerTokenAmount, + signedOrder.ecSignature.v, + signedOrder.ecSignature.r, + signedOrder.ecSignature.s, + { + from: takerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }, + ); + return txHash; + } + /** + * Batch version of fillOrKill. Allows a taker to specify a batch of orders that will either be atomically + * filled (each to the specified fillAmount) or aborted. + * @param orderFillRequests An array of objects that conform to the OrderFillRequest interface. + * @param takerAddress The user Ethereum address who would like to fill there orders. + * Must be available via the supplied Web3.Provider passed to 0x.js. + * @param orderTransactionOpts Optional arguments this method accepts. + * @return Transaction hash. + */ + @decorators.asyncZeroExErrorHandler + public async batchFillOrKillAsync( + orderFillRequests: OrderFillRequest[], + takerAddress: string, + orderTransactionOpts: OrderTransactionOpts = {}, + ): Promise<string> { + assert.doesConformToSchema('orderFillRequests', orderFillRequests, schemas.orderFillRequestsSchema); + const exchangeContractAddresses = _.map( + orderFillRequests, + orderFillRequest => orderFillRequest.signedOrder.exchangeContractAddress, + ); + assert.hasAtMostOneUniqueValue( + exchangeContractAddresses, + ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress, + ); + await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); + if (_.isEmpty(orderFillRequests)) { + throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem); + } + const exchangeInstance = await this._getExchangeContractAsync(); - const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) - ? SHOULD_VALIDATE_BY_DEFAULT - : orderTransactionOpts.shouldValidate; - if (shouldValidate) { - const zrxTokenAddress = this.getZRXTokenAddress(); - const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); - for (const orderFillRequest of orderFillRequests) { - await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync( - exchangeTradeEmulator, - orderFillRequest.signedOrder, - orderFillRequest.takerTokenFillAmount, - takerAddress, - zrxTokenAddress, - ); - } - } + const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) + ? SHOULD_VALIDATE_BY_DEFAULT + : orderTransactionOpts.shouldValidate; + if (shouldValidate) { + const zrxTokenAddress = this.getZRXTokenAddress(); + const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); + for (const orderFillRequest of orderFillRequests) { + await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync( + exchangeTradeEmulator, + orderFillRequest.signedOrder, + orderFillRequest.takerTokenFillAmount, + takerAddress, + zrxTokenAddress, + ); + } + } - const orderAddressesValuesAndTakerTokenFillAmounts = _.map(orderFillRequests, request => { - return [ - ...ExchangeWrapper._getOrderAddressesAndValues(request.signedOrder), - request.takerTokenFillAmount, - request.signedOrder.ecSignature.v, - request.signedOrder.ecSignature.r, - request.signedOrder.ecSignature.s, - ]; - }); + const orderAddressesValuesAndTakerTokenFillAmounts = _.map(orderFillRequests, request => { + return [ + ...ExchangeWrapper._getOrderAddressesAndValues(request.signedOrder), + request.takerTokenFillAmount, + request.signedOrder.ecSignature.v, + request.signedOrder.ecSignature.r, + request.signedOrder.ecSignature.s, + ]; + }); - // We use _.unzip<any> because _.unzip doesn't type check if values have different types :'( - const [orderAddresses, orderValues, fillTakerTokenAmounts, vParams, rParams, sParams] = _.unzip<any>( - orderAddressesValuesAndTakerTokenFillAmounts, - ); - const txHash = await exchangeInstance.batchFillOrKillOrders.sendTransactionAsync( - orderAddresses, - orderValues, - fillTakerTokenAmounts, - vParams, - rParams, - sParams, - { - from: takerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - }, - ); - return txHash; - } - /** - * Cancel a given fill amount of an order. Cancellations are cumulative. - * @param order An object that conforms to the Order or SignedOrder interface. - * The order you would like to cancel. - * @param cancelTakerTokenAmount The amount (specified in taker tokens) that you would like to cancel. - * @param transactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async cancelOrderAsync( - order: Order | SignedOrder, - cancelTakerTokenAmount: BigNumber, - orderTransactionOpts: OrderTransactionOpts = {}, - ): Promise<string> { - assert.doesConformToSchema('order', order, schemas.orderSchema); - assert.isValidBaseUnitAmount('takerTokenCancelAmount', cancelTakerTokenAmount); - await assert.isSenderAddressAsync('order.maker', order.maker, this._web3Wrapper); + // We use _.unzip<any> because _.unzip doesn't type check if values have different types :'( + const [orderAddresses, orderValues, fillTakerTokenAmounts, vParams, rParams, sParams] = _.unzip<any>( + orderAddressesValuesAndTakerTokenFillAmounts, + ); + const txHash = await exchangeInstance.batchFillOrKillOrders.sendTransactionAsync( + orderAddresses, + orderValues, + fillTakerTokenAmounts, + vParams, + rParams, + sParams, + { + from: takerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }, + ); + return txHash; + } + /** + * Cancel a given fill amount of an order. Cancellations are cumulative. + * @param order An object that conforms to the Order or SignedOrder interface. + * The order you would like to cancel. + * @param cancelTakerTokenAmount The amount (specified in taker tokens) that you would like to cancel. + * @param transactionOpts Optional arguments this method accepts. + * @return Transaction hash. + */ + @decorators.asyncZeroExErrorHandler + public async cancelOrderAsync( + order: Order | SignedOrder, + cancelTakerTokenAmount: BigNumber, + orderTransactionOpts: OrderTransactionOpts = {}, + ): Promise<string> { + assert.doesConformToSchema('order', order, schemas.orderSchema); + assert.isValidBaseUnitAmount('takerTokenCancelAmount', cancelTakerTokenAmount); + await assert.isSenderAddressAsync('order.maker', order.maker, this._web3Wrapper); - const exchangeInstance = await this._getExchangeContractAsync(); + const exchangeInstance = await this._getExchangeContractAsync(); - const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) - ? SHOULD_VALIDATE_BY_DEFAULT - : orderTransactionOpts.shouldValidate; - if (shouldValidate) { - const orderHash = utils.getOrderHashHex(order); - const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash); - OrderValidationUtils.validateCancelOrderThrowIfInvalid( - order, - cancelTakerTokenAmount, - unavailableTakerTokenAmount, - ); - } + const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) + ? SHOULD_VALIDATE_BY_DEFAULT + : orderTransactionOpts.shouldValidate; + if (shouldValidate) { + const orderHash = utils.getOrderHashHex(order); + const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash); + OrderValidationUtils.validateCancelOrderThrowIfInvalid( + order, + cancelTakerTokenAmount, + unavailableTakerTokenAmount, + ); + } - const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order); - const txHash = await exchangeInstance.cancelOrder.sendTransactionAsync( - orderAddresses, - orderValues, - cancelTakerTokenAmount, - { - from: order.maker, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - }, - ); - return txHash; - } - /** - * Batch version of cancelOrderAsync. Atomically cancels multiple orders in a single transaction. - * All orders must be from the same maker. - * @param orderCancellationRequests An array of objects that conform to the OrderCancellationRequest - * interface. - * @param transactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async batchCancelOrdersAsync( - orderCancellationRequests: OrderCancellationRequest[], - orderTransactionOpts: OrderTransactionOpts = {}, - ): Promise<string> { - assert.doesConformToSchema( - 'orderCancellationRequests', - orderCancellationRequests, - schemas.orderCancellationRequestsSchema, - ); - const exchangeContractAddresses = _.map( - orderCancellationRequests, - orderCancellationRequest => orderCancellationRequest.order.exchangeContractAddress, - ); - assert.hasAtMostOneUniqueValue( - exchangeContractAddresses, - ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress, - ); - const makers = _.map(orderCancellationRequests, cancellationRequest => cancellationRequest.order.maker); - assert.hasAtMostOneUniqueValue(makers, ExchangeContractErrs.MultipleMakersInSingleCancelBatchDisallowed); - const maker = makers[0]; - await assert.isSenderAddressAsync('maker', maker, this._web3Wrapper); - const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) - ? SHOULD_VALIDATE_BY_DEFAULT - : orderTransactionOpts.shouldValidate; - if (shouldValidate) { - for (const orderCancellationRequest of orderCancellationRequests) { - const orderHash = utils.getOrderHashHex(orderCancellationRequest.order); - const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash); - OrderValidationUtils.validateCancelOrderThrowIfInvalid( - orderCancellationRequest.order, - orderCancellationRequest.takerTokenCancelAmount, - unavailableTakerTokenAmount, - ); - } - } - if (_.isEmpty(orderCancellationRequests)) { - throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem); - } - const exchangeInstance = await this._getExchangeContractAsync(); - const orderAddressesValuesAndTakerTokenCancelAmounts = _.map(orderCancellationRequests, cancellationRequest => { - return [ - ...ExchangeWrapper._getOrderAddressesAndValues(cancellationRequest.order), - cancellationRequest.takerTokenCancelAmount, - ]; - }); - // We use _.unzip<any> because _.unzip doesn't type check if values have different types :'( - const [orderAddresses, orderValues, cancelTakerTokenAmounts] = _.unzip<any>( - orderAddressesValuesAndTakerTokenCancelAmounts, - ); - const txHash = await exchangeInstance.batchCancelOrders.sendTransactionAsync( - orderAddresses, - orderValues, - cancelTakerTokenAmounts, - { - from: maker, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - }, - ); - return txHash; - } - /** - * Subscribe to an event type emitted by the Exchange contract. - * @param eventName The exchange contract event you would like to subscribe to. - * @param indexFilterValues An object where the keys are indexed args returned by the event and - * the value is the value you are interested in. E.g `{maker: aUserAddressHex}` - * @param callback Callback that gets called when a log is added/removed - * @return Subscription token used later to unsubscribe - */ - public subscribe<ArgsType extends ExchangeContractEventArgs>( - eventName: ExchangeEvents, - indexFilterValues: IndexedFilterValues, - callback: EventCallback<ArgsType>, - ): string { - assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents); - assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); - assert.isFunction('callback', callback); - const exchangeContractAddress = this.getContractAddress(); - const subscriptionToken = this._subscribe<ArgsType>( - exchangeContractAddress, - eventName, - indexFilterValues, - artifacts.ExchangeArtifact.abi, - callback, - ); - return subscriptionToken; - } - /** - * Cancel a subscription - * @param subscriptionToken Subscription token returned by `subscribe()` - */ - public unsubscribe(subscriptionToken: string): void { - this._unsubscribe(subscriptionToken); - } - /** - * Cancels all existing subscriptions - */ - public unsubscribeAll(): void { - super.unsubscribeAll(); - } - /** - * Gets historical logs without creating a subscription - * @param eventName The exchange contract event you would like to subscribe to. - * @param blockRange Block range to get logs from. - * @param indexFilterValues An object where the keys are indexed args returned by the event and - * the value is the value you are interested in. E.g `{_from: aUserAddressHex}` - * @return Array of logs that match the parameters - */ - public async getLogsAsync<ArgsType extends ExchangeContractEventArgs>( - eventName: ExchangeEvents, - blockRange: BlockRange, - indexFilterValues: IndexedFilterValues, - ): Promise<Array<LogWithDecodedArgs<ArgsType>>> { - assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents); - assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema); - assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); - const exchangeContractAddress = this.getContractAddress(); - const logs = await this._getLogsAsync<ArgsType>( - exchangeContractAddress, - eventName, - blockRange, - indexFilterValues, - artifacts.ExchangeArtifact.abi, - ); - return logs; - } - /** - * Retrieves the Ethereum address of the Exchange contract deployed on the network - * that the user-passed web3 provider is connected to. - * @returns The Ethereum address of the Exchange contract being used. - */ - public getContractAddress(): string { - const contractAddress = this._getContractAddress(artifacts.ExchangeArtifact, this._contractAddressIfExists); - return contractAddress; - } - /** - * Checks if order is still fillable and throws an error otherwise. Useful for orderbook - * pruning where you want to remove stale orders without knowing who the taker will be. - * @param signedOrder An object that conforms to the SignedOrder interface. The - * signedOrder you wish to validate. - * @param opts An object that conforms to the ValidateOrderFillableOpts - * interface. Allows specifying a specific fillTakerTokenAmount - * to validate for. - */ - public async validateOrderFillableOrThrowAsync( - signedOrder: SignedOrder, - opts?: ValidateOrderFillableOpts, - ): Promise<void> { - assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); - const zrxTokenAddress = this.getZRXTokenAddress(); - const expectedFillTakerTokenAmount = !_.isUndefined(opts) ? opts.expectedFillTakerTokenAmount : undefined; - const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); - await this._orderValidationUtils.validateOrderFillableOrThrowAsync( - exchangeTradeEmulator, - signedOrder, - zrxTokenAddress, - expectedFillTakerTokenAmount, - ); - } - /** - * Checks if order fill will succeed and throws an error otherwise. - * @param signedOrder An object that conforms to the SignedOrder interface. The - * signedOrder you wish to fill. - * @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill. - * @param takerAddress The user Ethereum address who would like to fill this order. - * Must be available via the supplied Web3.Provider passed to 0x.js. - */ - public async validateFillOrderThrowIfInvalidAsync( - signedOrder: SignedOrder, - fillTakerTokenAmount: BigNumber, - takerAddress: string, - ): Promise<void> { - assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); - assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - const zrxTokenAddress = this.getZRXTokenAddress(); - const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); - await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync( - exchangeTradeEmulator, - signedOrder, - fillTakerTokenAmount, - takerAddress, - zrxTokenAddress, - ); - } - /** - * Checks if cancelling a given order will succeed and throws an informative error if it won't. - * @param order An object that conforms to the Order or SignedOrder interface. - * The order you would like to cancel. - * @param cancelTakerTokenAmount The amount (specified in taker tokens) that you would like to cancel. - */ - public async validateCancelOrderThrowIfInvalidAsync( - order: Order, - cancelTakerTokenAmount: BigNumber, - ): Promise<void> { - assert.doesConformToSchema('order', order, schemas.orderSchema); - assert.isValidBaseUnitAmount('cancelTakerTokenAmount', cancelTakerTokenAmount); - const orderHash = utils.getOrderHashHex(order); - const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash); - OrderValidationUtils.validateCancelOrderThrowIfInvalid( - order, - cancelTakerTokenAmount, - unavailableTakerTokenAmount, - ); - } - /** - * Checks if calling fillOrKill on a given order will succeed and throws an informative error if it won't. - * @param signedOrder An object that conforms to the SignedOrder interface. The - * signedOrder you wish to fill. - * @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill. - * @param takerAddress The user Ethereum address who would like to fill this order. - * Must be available via the supplied Web3.Provider passed to 0x.js. - */ - public async validateFillOrKillOrderThrowIfInvalidAsync( - signedOrder: SignedOrder, - fillTakerTokenAmount: BigNumber, - takerAddress: string, - ): Promise<void> { - assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); - assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - const zrxTokenAddress = this.getZRXTokenAddress(); - const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); - await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync( - exchangeTradeEmulator, - signedOrder, - fillTakerTokenAmount, - takerAddress, - zrxTokenAddress, - ); - } - /** - * Checks if rounding error will be > 0.1% when computing makerTokenAmount by doing: - * `(fillTakerTokenAmount * makerTokenAmount) / takerTokenAmount`. - * 0x Protocol does not accept any trades that result in large rounding errors. This means that tokens with few or - * no decimals can only be filled in quantities and ratios that avoid large rounding errors. - * @param fillTakerTokenAmount The amount of the order (in taker tokens baseUnits) that you wish to fill. - * @param takerTokenAmount The order size on the taker side - * @param makerTokenAmount The order size on the maker side - */ - public async isRoundingErrorAsync( - fillTakerTokenAmount: BigNumber, - takerTokenAmount: BigNumber, - makerTokenAmount: BigNumber, - ): Promise<boolean> { - assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount); - assert.isValidBaseUnitAmount('takerTokenAmount', takerTokenAmount); - assert.isValidBaseUnitAmount('makerTokenAmount', makerTokenAmount); - const exchangeInstance = await this._getExchangeContractAsync(); - const isRoundingError = await exchangeInstance.isRoundingError.callAsync( - fillTakerTokenAmount, - takerTokenAmount, - makerTokenAmount, - ); - return isRoundingError; - } - /** - * Checks if logs contain LogError, which is emmited by Exchange contract on transaction failure. - * @param logs Transaction logs as returned by `zeroEx.awaitTransactionMinedAsync` - */ - public throwLogErrorsAsErrors(logs: Array<LogWithDecodedArgs<DecodedLogArgs> | Web3.LogEntry>): void { - const errLog = _.find(logs, { - event: ExchangeEvents.LogError, - }) as LogWithDecodedArgs<LogErrorContractEventArgs> | undefined; - if (!_.isUndefined(errLog)) { - const logArgs = errLog.args; - const errCode = logArgs.errorId.toNumber(); - const errMessage = this._exchangeContractErrCodesToMsg[errCode]; - throw new Error(errMessage); - } - } - /** - * Returns the ZRX token address used by the exchange contract. - * @return Address of ZRX token - */ - public getZRXTokenAddress(): string { - const contractAddress = this._getContractAddress(artifacts.ZRXArtifact, this._zrxContractAddressIfExists); - return contractAddress; - } - private _invalidateContractInstances(): void { - this.unsubscribeAll(); - delete this._exchangeContractIfExists; - } - private async _isValidSignatureUsingContractCallAsync( - dataHex: string, - ecSignature: ECSignature, - signerAddressHex: string, - ): Promise<boolean> { - assert.isHexString('dataHex', dataHex); - assert.doesConformToSchema('ecSignature', ecSignature, schemas.ecSignatureSchema); - assert.isETHAddressHex('signerAddressHex', signerAddressHex); + const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order); + const txHash = await exchangeInstance.cancelOrder.sendTransactionAsync( + orderAddresses, + orderValues, + cancelTakerTokenAmount, + { + from: order.maker, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }, + ); + return txHash; + } + /** + * Batch version of cancelOrderAsync. Atomically cancels multiple orders in a single transaction. + * All orders must be from the same maker. + * @param orderCancellationRequests An array of objects that conform to the OrderCancellationRequest + * interface. + * @param transactionOpts Optional arguments this method accepts. + * @return Transaction hash. + */ + @decorators.asyncZeroExErrorHandler + public async batchCancelOrdersAsync( + orderCancellationRequests: OrderCancellationRequest[], + orderTransactionOpts: OrderTransactionOpts = {}, + ): Promise<string> { + assert.doesConformToSchema( + 'orderCancellationRequests', + orderCancellationRequests, + schemas.orderCancellationRequestsSchema, + ); + const exchangeContractAddresses = _.map( + orderCancellationRequests, + orderCancellationRequest => orderCancellationRequest.order.exchangeContractAddress, + ); + assert.hasAtMostOneUniqueValue( + exchangeContractAddresses, + ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress, + ); + const makers = _.map(orderCancellationRequests, cancellationRequest => cancellationRequest.order.maker); + assert.hasAtMostOneUniqueValue(makers, ExchangeContractErrs.MultipleMakersInSingleCancelBatchDisallowed); + const maker = makers[0]; + await assert.isSenderAddressAsync('maker', maker, this._web3Wrapper); + const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) + ? SHOULD_VALIDATE_BY_DEFAULT + : orderTransactionOpts.shouldValidate; + if (shouldValidate) { + for (const orderCancellationRequest of orderCancellationRequests) { + const orderHash = utils.getOrderHashHex(orderCancellationRequest.order); + const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash); + OrderValidationUtils.validateCancelOrderThrowIfInvalid( + orderCancellationRequest.order, + orderCancellationRequest.takerTokenCancelAmount, + unavailableTakerTokenAmount, + ); + } + } + if (_.isEmpty(orderCancellationRequests)) { + throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem); + } + const exchangeInstance = await this._getExchangeContractAsync(); + const orderAddressesValuesAndTakerTokenCancelAmounts = _.map(orderCancellationRequests, cancellationRequest => { + return [ + ...ExchangeWrapper._getOrderAddressesAndValues(cancellationRequest.order), + cancellationRequest.takerTokenCancelAmount, + ]; + }); + // We use _.unzip<any> because _.unzip doesn't type check if values have different types :'( + const [orderAddresses, orderValues, cancelTakerTokenAmounts] = _.unzip<any>( + orderAddressesValuesAndTakerTokenCancelAmounts, + ); + const txHash = await exchangeInstance.batchCancelOrders.sendTransactionAsync( + orderAddresses, + orderValues, + cancelTakerTokenAmounts, + { + from: maker, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + }, + ); + return txHash; + } + /** + * Subscribe to an event type emitted by the Exchange contract. + * @param eventName The exchange contract event you would like to subscribe to. + * @param indexFilterValues An object where the keys are indexed args returned by the event and + * the value is the value you are interested in. E.g `{maker: aUserAddressHex}` + * @param callback Callback that gets called when a log is added/removed + * @return Subscription token used later to unsubscribe + */ + public subscribe<ArgsType extends ExchangeContractEventArgs>( + eventName: ExchangeEvents, + indexFilterValues: IndexedFilterValues, + callback: EventCallback<ArgsType>, + ): string { + assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents); + assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); + assert.isFunction('callback', callback); + const exchangeContractAddress = this.getContractAddress(); + const subscriptionToken = this._subscribe<ArgsType>( + exchangeContractAddress, + eventName, + indexFilterValues, + artifacts.ExchangeArtifact.abi, + callback, + ); + return subscriptionToken; + } + /** + * Cancel a subscription + * @param subscriptionToken Subscription token returned by `subscribe()` + */ + public unsubscribe(subscriptionToken: string): void { + this._unsubscribe(subscriptionToken); + } + /** + * Cancels all existing subscriptions + */ + public unsubscribeAll(): void { + super.unsubscribeAll(); + } + /** + * Gets historical logs without creating a subscription + * @param eventName The exchange contract event you would like to subscribe to. + * @param blockRange Block range to get logs from. + * @param indexFilterValues An object where the keys are indexed args returned by the event and + * the value is the value you are interested in. E.g `{_from: aUserAddressHex}` + * @return Array of logs that match the parameters + */ + public async getLogsAsync<ArgsType extends ExchangeContractEventArgs>( + eventName: ExchangeEvents, + blockRange: BlockRange, + indexFilterValues: IndexedFilterValues, + ): Promise<Array<LogWithDecodedArgs<ArgsType>>> { + assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents); + assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema); + assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); + const exchangeContractAddress = this.getContractAddress(); + const logs = await this._getLogsAsync<ArgsType>( + exchangeContractAddress, + eventName, + blockRange, + indexFilterValues, + artifacts.ExchangeArtifact.abi, + ); + return logs; + } + /** + * Retrieves the Ethereum address of the Exchange contract deployed on the network + * that the user-passed web3 provider is connected to. + * @returns The Ethereum address of the Exchange contract being used. + */ + public getContractAddress(): string { + const contractAddress = this._getContractAddress(artifacts.ExchangeArtifact, this._contractAddressIfExists); + return contractAddress; + } + /** + * Checks if order is still fillable and throws an error otherwise. Useful for orderbook + * pruning where you want to remove stale orders without knowing who the taker will be. + * @param signedOrder An object that conforms to the SignedOrder interface. The + * signedOrder you wish to validate. + * @param opts An object that conforms to the ValidateOrderFillableOpts + * interface. Allows specifying a specific fillTakerTokenAmount + * to validate for. + */ + public async validateOrderFillableOrThrowAsync( + signedOrder: SignedOrder, + opts?: ValidateOrderFillableOpts, + ): Promise<void> { + assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); + const zrxTokenAddress = this.getZRXTokenAddress(); + const expectedFillTakerTokenAmount = !_.isUndefined(opts) ? opts.expectedFillTakerTokenAmount : undefined; + const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); + await this._orderValidationUtils.validateOrderFillableOrThrowAsync( + exchangeTradeEmulator, + signedOrder, + zrxTokenAddress, + expectedFillTakerTokenAmount, + ); + } + /** + * Checks if order fill will succeed and throws an error otherwise. + * @param signedOrder An object that conforms to the SignedOrder interface. The + * signedOrder you wish to fill. + * @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill. + * @param takerAddress The user Ethereum address who would like to fill this order. + * Must be available via the supplied Web3.Provider passed to 0x.js. + */ + public async validateFillOrderThrowIfInvalidAsync( + signedOrder: SignedOrder, + fillTakerTokenAmount: BigNumber, + takerAddress: string, + ): Promise<void> { + assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); + assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount); + await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); + const zrxTokenAddress = this.getZRXTokenAddress(); + const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); + await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync( + exchangeTradeEmulator, + signedOrder, + fillTakerTokenAmount, + takerAddress, + zrxTokenAddress, + ); + } + /** + * Checks if cancelling a given order will succeed and throws an informative error if it won't. + * @param order An object that conforms to the Order or SignedOrder interface. + * The order you would like to cancel. + * @param cancelTakerTokenAmount The amount (specified in taker tokens) that you would like to cancel. + */ + public async validateCancelOrderThrowIfInvalidAsync( + order: Order, + cancelTakerTokenAmount: BigNumber, + ): Promise<void> { + assert.doesConformToSchema('order', order, schemas.orderSchema); + assert.isValidBaseUnitAmount('cancelTakerTokenAmount', cancelTakerTokenAmount); + const orderHash = utils.getOrderHashHex(order); + const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash); + OrderValidationUtils.validateCancelOrderThrowIfInvalid( + order, + cancelTakerTokenAmount, + unavailableTakerTokenAmount, + ); + } + /** + * Checks if calling fillOrKill on a given order will succeed and throws an informative error if it won't. + * @param signedOrder An object that conforms to the SignedOrder interface. The + * signedOrder you wish to fill. + * @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill. + * @param takerAddress The user Ethereum address who would like to fill this order. + * Must be available via the supplied Web3.Provider passed to 0x.js. + */ + public async validateFillOrKillOrderThrowIfInvalidAsync( + signedOrder: SignedOrder, + fillTakerTokenAmount: BigNumber, + takerAddress: string, + ): Promise<void> { + assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); + assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount); + await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); + const zrxTokenAddress = this.getZRXTokenAddress(); + const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); + await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync( + exchangeTradeEmulator, + signedOrder, + fillTakerTokenAmount, + takerAddress, + zrxTokenAddress, + ); + } + /** + * Checks if rounding error will be > 0.1% when computing makerTokenAmount by doing: + * `(fillTakerTokenAmount * makerTokenAmount) / takerTokenAmount`. + * 0x Protocol does not accept any trades that result in large rounding errors. This means that tokens with few or + * no decimals can only be filled in quantities and ratios that avoid large rounding errors. + * @param fillTakerTokenAmount The amount of the order (in taker tokens baseUnits) that you wish to fill. + * @param takerTokenAmount The order size on the taker side + * @param makerTokenAmount The order size on the maker side + */ + public async isRoundingErrorAsync( + fillTakerTokenAmount: BigNumber, + takerTokenAmount: BigNumber, + makerTokenAmount: BigNumber, + ): Promise<boolean> { + assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount); + assert.isValidBaseUnitAmount('takerTokenAmount', takerTokenAmount); + assert.isValidBaseUnitAmount('makerTokenAmount', makerTokenAmount); + const exchangeInstance = await this._getExchangeContractAsync(); + const isRoundingError = await exchangeInstance.isRoundingError.callAsync( + fillTakerTokenAmount, + takerTokenAmount, + makerTokenAmount, + ); + return isRoundingError; + } + /** + * Checks if logs contain LogError, which is emmited by Exchange contract on transaction failure. + * @param logs Transaction logs as returned by `zeroEx.awaitTransactionMinedAsync` + */ + public throwLogErrorsAsErrors(logs: Array<LogWithDecodedArgs<DecodedLogArgs> | Web3.LogEntry>): void { + const errLog = _.find(logs, { + event: ExchangeEvents.LogError, + }) as LogWithDecodedArgs<LogErrorContractEventArgs> | undefined; + if (!_.isUndefined(errLog)) { + const logArgs = errLog.args; + const errCode = logArgs.errorId.toNumber(); + const errMessage = this._exchangeContractErrCodesToMsg[errCode]; + throw new Error(errMessage); + } + } + /** + * Returns the ZRX token address used by the exchange contract. + * @return Address of ZRX token + */ + public getZRXTokenAddress(): string { + const contractAddress = this._getContractAddress(artifacts.ZRXArtifact, this._zrxContractAddressIfExists); + return contractAddress; + } + private _invalidateContractInstances(): void { + this.unsubscribeAll(); + delete this._exchangeContractIfExists; + } + private async _isValidSignatureUsingContractCallAsync( + dataHex: string, + ecSignature: ECSignature, + signerAddressHex: string, + ): Promise<boolean> { + assert.isHexString('dataHex', dataHex); + assert.doesConformToSchema('ecSignature', ecSignature, schemas.ecSignatureSchema); + assert.isETHAddressHex('signerAddressHex', signerAddressHex); - const exchangeInstance = await this._getExchangeContractAsync(); + const exchangeInstance = await this._getExchangeContractAsync(); - const isValidSignature = await exchangeInstance.isValidSignature.callAsync( - signerAddressHex, - dataHex, - ecSignature.v, - ecSignature.r, - ecSignature.s, - ); - return isValidSignature; - } - private async _getOrderHashHexUsingContractCallAsync(order: Order | SignedOrder): Promise<string> { - const exchangeInstance = await this._getExchangeContractAsync(); - const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order); - const orderHashHex = await exchangeInstance.getOrderHash.callAsync(orderAddresses, orderValues); - return orderHashHex; - } - private async _getExchangeContractAsync(): Promise<ExchangeContract> { - if (!_.isUndefined(this._exchangeContractIfExists)) { - return this._exchangeContractIfExists; - } - const web3ContractInstance = await this._instantiateContractIfExistsAsync( - artifacts.ExchangeArtifact, - this._contractAddressIfExists, - ); - const contractInstance = new ExchangeContract(web3ContractInstance, this._web3Wrapper.getContractDefaults()); - this._exchangeContractIfExists = contractInstance; - return this._exchangeContractIfExists; - } - private async _getTokenTransferProxyAddressAsync(): Promise<string> { - const exchangeInstance = await this._getExchangeContractAsync(); - const tokenTransferProxyAddress = await exchangeInstance.TOKEN_TRANSFER_PROXY_CONTRACT.callAsync(); - const tokenTransferProxyAddressLowerCase = tokenTransferProxyAddress.toLowerCase(); - return tokenTransferProxyAddressLowerCase; - } + const isValidSignature = await exchangeInstance.isValidSignature.callAsync( + signerAddressHex, + dataHex, + ecSignature.v, + ecSignature.r, + ecSignature.s, + ); + return isValidSignature; + } + private async _getOrderHashHexUsingContractCallAsync(order: Order | SignedOrder): Promise<string> { + const exchangeInstance = await this._getExchangeContractAsync(); + const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order); + const orderHashHex = await exchangeInstance.getOrderHash.callAsync(orderAddresses, orderValues); + return orderHashHex; + } + private async _getExchangeContractAsync(): Promise<ExchangeContract> { + if (!_.isUndefined(this._exchangeContractIfExists)) { + return this._exchangeContractIfExists; + } + const web3ContractInstance = await this._instantiateContractIfExistsAsync( + artifacts.ExchangeArtifact, + this._contractAddressIfExists, + ); + const contractInstance = new ExchangeContract(web3ContractInstance, this._web3Wrapper.getContractDefaults()); + this._exchangeContractIfExists = contractInstance; + return this._exchangeContractIfExists; + } + private async _getTokenTransferProxyAddressAsync(): Promise<string> { + const exchangeInstance = await this._getExchangeContractAsync(); + const tokenTransferProxyAddress = await exchangeInstance.TOKEN_TRANSFER_PROXY_CONTRACT.callAsync(); + const tokenTransferProxyAddressLowerCase = tokenTransferProxyAddress.toLowerCase(); + return tokenTransferProxyAddressLowerCase; + } } // tslint:disable:max-file-line-count |