diff options
Diffstat (limited to 'src/contract_wrappers')
-rw-r--r-- | src/contract_wrappers/contract_wrapper.ts | 51 | ||||
-rw-r--r-- | src/contract_wrappers/ether_token_wrapper.ts | 22 | ||||
-rw-r--r-- | src/contract_wrappers/exchange_wrapper.ts | 127 | ||||
-rw-r--r-- | src/contract_wrappers/token_registry_wrapper.ts | 22 | ||||
-rw-r--r-- | src/contract_wrappers/token_transfer_proxy_wrapper.ts | 10 | ||||
-rw-r--r-- | src/contract_wrappers/token_wrapper.ts | 67 |
6 files changed, 135 insertions, 164 deletions
diff --git a/src/contract_wrappers/contract_wrapper.ts b/src/contract_wrappers/contract_wrapper.ts index 28df82cee..ca19342f3 100644 --- a/src/contract_wrappers/contract_wrapper.ts +++ b/src/contract_wrappers/contract_wrapper.ts @@ -1,53 +1,18 @@ import * as _ from 'lodash'; -import contract = require('truffle-contract'); +import * as Web3 from 'web3'; import {Web3Wrapper} from '../web3_wrapper'; -import {ZeroExError, Artifact, ContractInstance} from '../types'; +import {ZeroExError} from '../types'; import {utils} from '../utils/utils'; export class ContractWrapper { protected _web3Wrapper: Web3Wrapper; - private _gasPrice?: BigNumber.BigNumber; - constructor(web3Wrapper: Web3Wrapper, gasPrice?: BigNumber.BigNumber) { + constructor(web3Wrapper: Web3Wrapper) { this._web3Wrapper = web3Wrapper; - this._gasPrice = gasPrice; } - protected async _instantiateContractIfExistsAsync(artifact: Artifact, address?: string): Promise<ContractInstance> { - const c = await contract(artifact); - c.defaults({ - gasPrice: this._gasPrice, - }); - const providerObj = this._web3Wrapper.getCurrentProvider(); - c.setProvider(providerObj); - - const networkIdIfExists = await this._web3Wrapper.getNetworkIdIfExistsAsync(); - const artifactNetworkConfigs = _.isUndefined(networkIdIfExists) ? - undefined : - artifact.networks[networkIdIfExists]; - let contractAddress; - if (!_.isUndefined(address)) { - contractAddress = address; - } else if (!_.isUndefined(artifactNetworkConfigs)) { - contractAddress = artifactNetworkConfigs.address.toLowerCase(); - } - - if (!_.isUndefined(contractAddress)) { - const doesContractExist = await this._web3Wrapper.doesContractExistAtAddressAsync(contractAddress); - if (!doesContractExist) { - throw new Error(ZeroExError.ContractDoesNotExist); - } - } - - try { - const contractInstance = _.isUndefined(address) ? await c.deployed() : await c.at(address); - return contractInstance; - } catch (err) { - const errMsg = `${err}`; - if (_.includes(errMsg, 'not been deployed to detected network')) { - throw new Error(ZeroExError.ContractDoesNotExist); - } else { - utils.consoleLog(`Notice: Error encountered: ${err} ${err.stack}`); - throw new Error(ZeroExError.UnhandledError); - } - } + protected async _instantiateContractIfExistsAsync<A extends Web3.ContractInstance>(artifact: Artifact, + address?: string): Promise<A> { + const contractInstance = + await this._web3Wrapper.getContractInstanceFromArtifactAsync<A>(artifact, address); + return contractInstance; } } diff --git a/src/contract_wrappers/ether_token_wrapper.ts b/src/contract_wrappers/ether_token_wrapper.ts index 3c282510f..b86309f90 100644 --- a/src/contract_wrappers/ether_token_wrapper.ts +++ b/src/contract_wrappers/ether_token_wrapper.ts @@ -4,7 +4,7 @@ import {ContractWrapper} from './contract_wrapper'; import {TokenWrapper} from './token_wrapper'; import {EtherTokenContract, ZeroExError} from '../types'; import {assert} from '../utils/assert'; -import * as EtherTokenArtifacts from '../artifacts/EtherToken.json'; +import {artifacts} from '../artifacts'; /** * This class includes all the functionality related to interacting with a wrapped Ether ERC20 token contract. @@ -13,8 +13,8 @@ import * as EtherTokenArtifacts from '../artifacts/EtherToken.json'; export class EtherTokenWrapper extends ContractWrapper { private _etherTokenContractIfExists?: EtherTokenContract; private _tokenWrapper: TokenWrapper; - constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper, gasPrice?: BigNumber.BigNumber) { - super(web3Wrapper, gasPrice); + constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper) { + super(web3Wrapper); this._tokenWrapper = tokenWrapper; } /** @@ -23,8 +23,9 @@ export class EtherTokenWrapper extends ContractWrapper { * for ETH. * @param amountInWei Amount of ETH in Wei the caller wishes to deposit. * @param depositor The hex encoded user Ethereum address that would like to make the deposit. + * @return Transaction hash. */ - public async depositAsync(amountInWei: BigNumber.BigNumber, depositor: string): Promise<void> { + public async depositAsync(amountInWei: BigNumber.BigNumber, depositor: string): Promise<string> { assert.isBigNumber('amountInWei', amountInWei); await assert.isSenderAddressAsync('depositor', depositor, this._web3Wrapper); @@ -32,18 +33,20 @@ export class EtherTokenWrapper extends ContractWrapper { assert.assert(ethBalanceInWei.gte(amountInWei), ZeroExError.InsufficientEthBalanceForDeposit); const wethContract = await this._getEtherTokenContractAsync(); - await wethContract.deposit({ + const txHash = await wethContract.deposit.sendTransactionAsync({ from: depositor, value: amountInWei, }); + return txHash; } /** * Withdraw ETH to the withdrawer's address from the wrapped ETH smart contract in exchange for the * equivalent number of wrapped ETH tokens. * @param amountInWei Amount of ETH in Wei the caller wishes to withdraw. * @param withdrawer The hex encoded user Ethereum address that would like to make the withdrawl. + * @return Transaction hash. */ - public async withdrawAsync(amountInWei: BigNumber.BigNumber, withdrawer: string): Promise<void> { + public async withdrawAsync(amountInWei: BigNumber.BigNumber, withdrawer: string): Promise<string> { assert.isBigNumber('amountInWei', amountInWei); await assert.isSenderAddressAsync('withdrawer', withdrawer, this._web3Wrapper); @@ -52,9 +55,10 @@ export class EtherTokenWrapper extends ContractWrapper { assert.assert(WETHBalanceInBaseUnits.gte(amountInWei), ZeroExError.InsufficientWEthBalanceForWithdrawal); const wethContract = await this._getEtherTokenContractAsync(); - await wethContract.withdraw(amountInWei, { + const txHash = await wethContract.withdraw.sendTransactionAsync(amountInWei, { from: withdrawer, }); + return txHash; } /** * Retrieves the Wrapped Ether token contract address @@ -71,7 +75,9 @@ export class EtherTokenWrapper extends ContractWrapper { if (!_.isUndefined(this._etherTokenContractIfExists)) { return this._etherTokenContractIfExists; } - const contractInstance = await this._instantiateContractIfExistsAsync((EtherTokenArtifacts as any)); + const contractInstance = await this._instantiateContractIfExistsAsync<EtherTokenContract>( + artifacts.EtherTokenArtifact, + ); this._etherTokenContractIfExists = contractInstance as EtherTokenContract; return this._etherTokenContractIfExists; } diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index d09df236b..115bd1110 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -21,7 +21,6 @@ import { IndexedFilterValues, CreateContractEvent, ContractEventObj, - ContractResponse, OrderCancellationRequest, OrderFillRequest, LogErrorContractEventArgs, @@ -36,21 +35,13 @@ import {ContractWrapper} from './contract_wrapper'; import {constants} from '../utils/constants'; import {TokenWrapper} from './token_wrapper'; import {decorators} from '../utils/decorators'; -import * as ExchangeArtifacts from '../artifacts/Exchange.json'; +import {artifacts} from '../artifacts'; /** * This class includes all the functionality related to calling methods and subscribing to * events of the 0x Exchange smart contract. */ export class ExchangeWrapper extends ContractWrapper { - private _exchangeContractErrCodesToMsg = { - [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 _exchangeContractIfExists?: ExchangeContract; private _exchangeLogEventEmitters: ContractEventEmitter[]; private _orderValidationUtils: OrderValidationUtils; @@ -73,8 +64,8 @@ export class ExchangeWrapper extends ContractWrapper { ]; return [orderAddresses, orderValues]; } - constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper, gasPrice?: BigNumber.BigNumber) { - super(web3Wrapper, gasPrice); + constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper) { + super(web3Wrapper); this._tokenWrapper = tokenWrapper; this._orderValidationUtils = new OrderValidationUtils(tokenWrapper, this); this._exchangeLogEventEmitters = []; @@ -91,7 +82,7 @@ export class ExchangeWrapper extends ContractWrapper { assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema); const exchangeContract = await this._getExchangeContractAsync(); - let unavailableTakerTokenAmount = await exchangeContract.getUnavailableTakerTokenAmount.call(orderHash); + let unavailableTakerTokenAmount = await exchangeContract.getUnavailableTakerTokenAmount.callAsync(orderHash); // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber unavailableTakerTokenAmount = new BigNumber(unavailableTakerTokenAmount); return unavailableTakerTokenAmount; @@ -105,7 +96,7 @@ export class ExchangeWrapper extends ContractWrapper { assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema); const exchangeContract = await this._getExchangeContractAsync(); - let fillAmountInBaseUnits = await exchangeContract.filled.call(orderHash); + let fillAmountInBaseUnits = await exchangeContract.filled.callAsync(orderHash); // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber fillAmountInBaseUnits = new BigNumber(fillAmountInBaseUnits); return fillAmountInBaseUnits; @@ -120,7 +111,7 @@ export class ExchangeWrapper extends ContractWrapper { assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema); const exchangeContract = await this._getExchangeContractAsync(); - let cancelledAmountInBaseUnits = await exchangeContract.cancelled.call(orderHash); + let cancelledAmountInBaseUnits = await exchangeContract.cancelled.callAsync(orderHash); // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber cancelledAmountInBaseUnits = new BigNumber(cancelledAmountInBaseUnits); return cancelledAmountInBaseUnits; @@ -141,12 +132,12 @@ export class ExchangeWrapper extends ContractWrapper { * @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. - * @return The amount of the order that was filled (in taker token baseUnits). + * @return Transaction hash. */ @decorators.contractCallErrorHandler public async fillOrderAsync(signedOrder: SignedOrder, fillTakerTokenAmount: BigNumber.BigNumber, shouldThrowOnInsufficientBalanceOrAllowance: boolean, - takerAddress: string): Promise<BigNumber.BigNumber> { + takerAddress: string): Promise<string> { assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); assert.isBigNumber('fillTakerTokenAmount', fillTakerTokenAmount); assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance); @@ -157,7 +148,7 @@ export class ExchangeWrapper extends ContractWrapper { const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder); - const gas = await exchangeInstance.fillOrder.estimateGas( + const gas = await exchangeInstance.fillOrder.estimateGasAsync( orderAddresses, orderValues, fillTakerTokenAmount, @@ -169,7 +160,7 @@ export class ExchangeWrapper extends ContractWrapper { from: takerAddress, }, ); - const response: ContractResponse = await exchangeInstance.fillOrder( + const txHash: string = await exchangeInstance.fillOrder.sendTransactionAsync( orderAddresses, orderValues, fillTakerTokenAmount, @@ -182,10 +173,7 @@ export class ExchangeWrapper extends ContractWrapper { gas, }, ); - this._throwErrorLogsAsErrors(response.logs); - const logFillArgs = response.logs[0].args as LogFillContractEventArgs; - const filledTakerTokenAmount = new BigNumber(logFillArgs.filledTakerTokenAmount); - return filledTakerTokenAmount; + return txHash; } /** * Sequentially and atomically fills signedOrders up to the specified takerTokenFillAmount. @@ -201,12 +189,12 @@ export class ExchangeWrapper extends ContractWrapper { * @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. - * @return The amount of the orders that was filled (in taker token baseUnits). + * @return Transaction hash. */ @decorators.contractCallErrorHandler public async fillOrdersUpToAsync(signedOrders: SignedOrder[], fillTakerTokenAmount: BigNumber.BigNumber, shouldThrowOnInsufficientBalanceOrAllowance: boolean, - takerAddress: string): Promise<BigNumber.BigNumber> { + takerAddress: string): Promise<string> { assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); const takerTokenAddresses = _.map(signedOrders, signedOrder => signedOrder.takerTokenAddress); assert.hasAtMostOneUniqueValue(takerTokenAddresses, @@ -222,7 +210,7 @@ export class ExchangeWrapper extends ContractWrapper { signedOrder, fillTakerTokenAmount, takerAddress); } if (_.isEmpty(signedOrders)) { - return new BigNumber(0); // no-op + throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem); } const orderAddressesValuesAndSignatureArray = _.map(signedOrders, signedOrder => { @@ -239,7 +227,7 @@ export class ExchangeWrapper extends ContractWrapper { ); const exchangeInstance = await this._getExchangeContractAsync(); - const gas = await exchangeInstance.fillOrdersUpTo.estimateGas( + const gas = await exchangeInstance.fillOrdersUpTo.estimateGasAsync( orderAddressesArray, orderValuesArray, fillTakerTokenAmount, @@ -251,7 +239,7 @@ export class ExchangeWrapper extends ContractWrapper { from: takerAddress, }, ); - const response: ContractResponse = await exchangeInstance.fillOrdersUpTo( + const txHash = await exchangeInstance.fillOrdersUpTo.sendTransactionAsync( orderAddressesArray, orderValuesArray, fillTakerTokenAmount, @@ -264,13 +252,7 @@ export class ExchangeWrapper extends ContractWrapper { gas, }, ); - this._throwErrorLogsAsErrors(response.logs); - let filledTakerTokenAmount = new BigNumber(0); - _.each(response.logs, log => { - filledTakerTokenAmount = filledTakerTokenAmount.plus( - (log.args as LogFillContractEventArgs).filledTakerTokenAmount); - }); - return filledTakerTokenAmount; + return txHash; } /** * Batch version of fillOrderAsync. @@ -288,11 +270,12 @@ export class ExchangeWrapper extends ContractWrapper { * @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. + * @return Transaction hash. */ @decorators.contractCallErrorHandler public async batchFillOrdersAsync(orderFillRequests: OrderFillRequest[], shouldThrowOnInsufficientBalanceOrAllowance: boolean, - takerAddress: string): Promise<void> { + takerAddress: string): Promise<string> { assert.doesConformToSchema('orderFillRequests', orderFillRequests, schemas.orderFillRequestsSchema); const exchangeContractAddresses = _.map( orderFillRequests, @@ -307,7 +290,7 @@ export class ExchangeWrapper extends ContractWrapper { orderFillRequest.signedOrder, orderFillRequest.takerTokenFillAmount, takerAddress); } if (_.isEmpty(orderFillRequests)) { - return; // no-op + throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem); } const orderAddressesValuesAmountsAndSignatureArray = _.map(orderFillRequests, orderFillRequest => { @@ -325,7 +308,7 @@ export class ExchangeWrapper extends ContractWrapper { ); const exchangeInstance = await this._getExchangeContractAsync(); - const gas = await exchangeInstance.batchFillOrders.estimateGas( + const gas = await exchangeInstance.batchFillOrders.estimateGasAsync( orderAddressesArray, orderValuesArray, fillTakerTokenAmounts, @@ -337,7 +320,7 @@ export class ExchangeWrapper extends ContractWrapper { from: takerAddress, }, ); - const response: ContractResponse = await exchangeInstance.batchFillOrders( + const txHash = await exchangeInstance.batchFillOrders.sendTransactionAsync( orderAddressesArray, orderValuesArray, fillTakerTokenAmounts, @@ -350,7 +333,7 @@ export class ExchangeWrapper extends ContractWrapper { gas, }, ); - this._throwErrorLogsAsErrors(response.logs); + return txHash; } /** * Attempts to fill a specific amount of an order. If the entire amount specified cannot be filled, @@ -360,10 +343,11 @@ export class ExchangeWrapper extends ContractWrapper { * @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. + * @return Transaction hash. */ @decorators.contractCallErrorHandler public async fillOrKillOrderAsync(signedOrder: SignedOrder, fillTakerTokenAmount: BigNumber.BigNumber, - takerAddress: string): Promise<void> { + takerAddress: string): Promise<string> { assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); assert.isBigNumber('fillTakerTokenAmount', fillTakerTokenAmount); await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); @@ -374,7 +358,7 @@ export class ExchangeWrapper extends ContractWrapper { const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder); - const gas = await exchangeInstance.fillOrKillOrder.estimateGas( + const gas = await exchangeInstance.fillOrKillOrder.estimateGasAsync( orderAddresses, orderValues, fillTakerTokenAmount, @@ -385,7 +369,7 @@ export class ExchangeWrapper extends ContractWrapper { from: takerAddress, }, ); - const response: ContractResponse = await exchangeInstance.fillOrKillOrder( + const txHash = await exchangeInstance.fillOrKillOrder.sendTransactionAsync( orderAddresses, orderValues, fillTakerTokenAmount, @@ -397,7 +381,7 @@ export class ExchangeWrapper extends ContractWrapper { gas, }, ); - this._throwErrorLogsAsErrors(response.logs); + return txHash; } /** * Batch version of fillOrKill. Allows a taker to specify a batch of orders that will either be atomically @@ -405,10 +389,11 @@ export class ExchangeWrapper extends ContractWrapper { * @param orderFillOrKillRequests An array of objects that conform to the OrderFillOrKillRequest 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. + * @return Transaction hash. */ @decorators.contractCallErrorHandler public async batchFillOrKillAsync(orderFillOrKillRequests: OrderFillOrKillRequest[], - takerAddress: string): Promise<void> { + takerAddress: string): Promise<string> { assert.doesConformToSchema('orderFillOrKillRequests', orderFillOrKillRequests, schemas.orderFillOrKillRequestsSchema); const exchangeContractAddresses = _.map( @@ -419,7 +404,7 @@ export class ExchangeWrapper extends ContractWrapper { ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress); await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); if (_.isEmpty(orderFillOrKillRequests)) { - return; // no-op + throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem); } const exchangeInstance = await this._getExchangeContractAsync(); for (const request of orderFillOrKillRequests) { @@ -441,7 +426,7 @@ export class ExchangeWrapper extends ContractWrapper { const [orderAddresses, orderValues, fillTakerTokenAmounts, vParams, rParams, sParams] = _.unzip<any>(orderAddressesValuesAndTakerTokenFillAmounts); - const gas = await exchangeInstance.batchFillOrKillOrders.estimateGas( + const gas = await exchangeInstance.batchFillOrKillOrders.estimateGasAsync( orderAddresses, orderValues, fillTakerTokenAmounts, @@ -452,7 +437,7 @@ export class ExchangeWrapper extends ContractWrapper { from: takerAddress, }, ); - const response: ContractResponse = await exchangeInstance.batchFillOrKillOrders( + const txHash = await exchangeInstance.batchFillOrKillOrders.sendTransactionAsync( orderAddresses, orderValues, fillTakerTokenAmounts, @@ -464,18 +449,18 @@ export class ExchangeWrapper extends ContractWrapper { gas, }, ); - this._throwErrorLogsAsErrors(response.logs); + 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. - * @return The amount of the order that was cancelled (in taker token baseUnits). + * @return Transaction hash. */ @decorators.contractCallErrorHandler public async cancelOrderAsync( - order: Order|SignedOrder, cancelTakerTokenAmount: BigNumber.BigNumber): Promise<BigNumber.BigNumber> { + order: Order|SignedOrder, cancelTakerTokenAmount: BigNumber.BigNumber): Promise<string> { assert.doesConformToSchema('order', order, schemas.orderSchema); assert.isBigNumber('takerTokenCancelAmount', cancelTakerTokenAmount); await assert.isSenderAddressAsync('order.maker', order.maker, this._web3Wrapper); @@ -484,7 +469,7 @@ export class ExchangeWrapper extends ContractWrapper { await this.validateCancelOrderThrowIfInvalidAsync(order, cancelTakerTokenAmount); const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order); - const gas = await exchangeInstance.cancelOrder.estimateGas( + const gas = await exchangeInstance.cancelOrder.estimateGasAsync( orderAddresses, orderValues, cancelTakerTokenAmount, @@ -492,7 +477,7 @@ export class ExchangeWrapper extends ContractWrapper { from: order.maker, }, ); - const response: ContractResponse = await exchangeInstance.cancelOrder( + const txHash = await exchangeInstance.cancelOrder.sendTransactionAsync( orderAddresses, orderValues, cancelTakerTokenAmount, @@ -501,19 +486,17 @@ export class ExchangeWrapper extends ContractWrapper { gas, }, ); - this._throwErrorLogsAsErrors(response.logs); - const logFillArgs = response.logs[0].args as LogCancelContractEventArgs; - const cancelledTakerTokenAmount = new BigNumber(logFillArgs.cancelledTakerTokenAmount); - return cancelledTakerTokenAmount; + 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. + * @return Transaction hash. */ @decorators.contractCallErrorHandler - public async batchCancelOrdersAsync(orderCancellationRequests: OrderCancellationRequest[]): Promise<void> { + public async batchCancelOrdersAsync(orderCancellationRequests: OrderCancellationRequest[]): Promise<string> { assert.doesConformToSchema('orderCancellationRequests', orderCancellationRequests, schemas.orderCancellationRequestsSchema); const exchangeContractAddresses = _.map( @@ -532,7 +515,7 @@ export class ExchangeWrapper extends ContractWrapper { ); } if (_.isEmpty(orderCancellationRequests)) { - return; // no-op + throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem); } const exchangeInstance = await this._getExchangeContractAsync(); const orderAddressesValuesAndTakerTokenCancelAmounts = _.map(orderCancellationRequests, cancellationRequest => { @@ -544,7 +527,7 @@ export class ExchangeWrapper extends ContractWrapper { // We use _.unzip<any> because _.unzip doesn't type check if values have different types :'( const [orderAddresses, orderValues, cancelTakerTokenAmounts] = _.unzip<any>(orderAddressesValuesAndTakerTokenCancelAmounts); - const gas = await exchangeInstance.batchCancelOrders.estimateGas( + const gas = await exchangeInstance.batchCancelOrders.estimateGasAsync( orderAddresses, orderValues, cancelTakerTokenAmounts, @@ -552,7 +535,7 @@ export class ExchangeWrapper extends ContractWrapper { from: maker, }, ); - const response: ContractResponse = await exchangeInstance.batchCancelOrders( + const txHash = await exchangeInstance.batchCancelOrders.sendTransactionAsync( orderAddresses, orderValues, cancelTakerTokenAmounts, @@ -561,7 +544,7 @@ export class ExchangeWrapper extends ContractWrapper { gas, }, ); - this._throwErrorLogsAsErrors(response.logs); + return txHash; } /** * Subscribe to an event type emitted by the Exchange smart contract @@ -686,7 +669,7 @@ export class ExchangeWrapper extends ContractWrapper { assert.isBigNumber('takerTokenAmount', takerTokenAmount); assert.isBigNumber('makerTokenAmount', makerTokenAmount); const exchangeInstance = await this._getExchangeContractAsync(); - const isRoundingError = await exchangeInstance.isRoundingError.call( + const isRoundingError = await exchangeInstance.isRoundingError.callAsync( fillTakerTokenAmount, takerTokenAmount, makerTokenAmount, ); return isRoundingError; @@ -703,7 +686,7 @@ export class ExchangeWrapper extends ContractWrapper { const exchangeInstance = await this._getExchangeContractAsync(); - const isValidSignature = await exchangeInstance.isValidSignature.call( + const isValidSignature = await exchangeInstance.isValidSignature.callAsync( signerAddressHex, dataHex, ecSignature.v, @@ -715,28 +698,22 @@ export class ExchangeWrapper extends ContractWrapper { private async _getOrderHashHexUsingContractCallAsync(order: Order|SignedOrder): Promise<string> { const exchangeInstance = await this._getExchangeContractAsync(); const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order); - const orderHashHex = await exchangeInstance.getOrderHash.call(orderAddresses, orderValues); + const orderHashHex = await exchangeInstance.getOrderHash.callAsync(orderAddresses, orderValues); return orderHashHex; } - private _throwErrorLogsAsErrors(logs: ContractEvent[]): void { - const errEvent = _.find(logs, {event: 'LogError'}); - if (!_.isUndefined(errEvent)) { - const errCode = (errEvent.args as LogErrorContractEventArgs).errorId.toNumber(); - const errMessage = this._exchangeContractErrCodesToMsg[errCode]; - throw new Error(errMessage); - } - } private async _getExchangeContractAsync(): Promise<ExchangeContract> { if (!_.isUndefined(this._exchangeContractIfExists)) { return this._exchangeContractIfExists; } - const contractInstance = await this._instantiateContractIfExistsAsync((ExchangeArtifacts as any)); + const contractInstance = await this._instantiateContractIfExistsAsync<ExchangeContract>( + artifacts.ExchangeArtifact, + ); this._exchangeContractIfExists = contractInstance as ExchangeContract; return this._exchangeContractIfExists; } private async _getZRXTokenAddressAsync(): Promise<string> { const exchangeInstance = await this._getExchangeContractAsync(); - const ZRXtokenAddress = await exchangeInstance.ZRX_TOKEN_CONTRACT.call(); + const ZRXtokenAddress = await exchangeInstance.ZRX_TOKEN_CONTRACT.callAsync(); return ZRXtokenAddress; } } diff --git a/src/contract_wrappers/token_registry_wrapper.ts b/src/contract_wrappers/token_registry_wrapper.ts index 822e69460..528a88e06 100644 --- a/src/contract_wrappers/token_registry_wrapper.ts +++ b/src/contract_wrappers/token_registry_wrapper.ts @@ -4,15 +4,15 @@ import {assert} from '../utils/assert'; import {Token, TokenRegistryContract, TokenMetadata} from '../types'; import {constants} from '../utils/constants'; import {ContractWrapper} from './contract_wrapper'; -import * as TokenRegistryArtifacts from '../artifacts/TokenRegistry.json'; +import {artifacts} from '../artifacts'; /** * This class includes all the functionality related to interacting with the 0x Token Registry smart contract. */ export class TokenRegistryWrapper extends ContractWrapper { private _tokenRegistryContractIfExists?: TokenRegistryContract; - constructor(web3Wrapper: Web3Wrapper, gasPrice?: BigNumber.BigNumber) { - super(web3Wrapper, gasPrice); + constructor(web3Wrapper: Web3Wrapper) { + super(web3Wrapper); } /** * Retrieves all the tokens currently listed in the Token Registry smart contract @@ -35,7 +35,7 @@ export class TokenRegistryWrapper extends ContractWrapper { */ public async getTokenAddressesAsync(): Promise<string[]> { const tokenRegistryContract = await this._getTokenRegistryContractAsync(); - const addresses = await tokenRegistryContract.getTokenAddresses.call(); + const addresses = await tokenRegistryContract.getTokenAddresses.callAsync(); return addresses; } /** @@ -46,14 +46,14 @@ export class TokenRegistryWrapper extends ContractWrapper { assert.isETHAddressHex('address', address); const tokenRegistryContract = await this._getTokenRegistryContractAsync(); - const metadata = await tokenRegistryContract.getTokenMetaData.call(address); + const metadata = await tokenRegistryContract.getTokenMetaData.callAsync(address); const token = this._createTokenFromMetadata(metadata); return token; } public async getTokenAddressBySymbolIfExistsAsync(symbol: string): Promise<string|undefined> { assert.isString('symbol', symbol); const tokenRegistryContract = await this._getTokenRegistryContractAsync(); - const addressIfExists = await tokenRegistryContract.getTokenAddressBySymbol.call(symbol); + const addressIfExists = await tokenRegistryContract.getTokenAddressBySymbol.callAsync(symbol); if (addressIfExists === constants.NULL_ADDRESS) { return undefined; } @@ -62,7 +62,7 @@ export class TokenRegistryWrapper extends ContractWrapper { public async getTokenAddressByNameIfExistsAsync(name: string): Promise<string|undefined> { assert.isString('name', name); const tokenRegistryContract = await this._getTokenRegistryContractAsync(); - const addressIfExists = await tokenRegistryContract.getTokenAddressByName.call(name); + const addressIfExists = await tokenRegistryContract.getTokenAddressByName.callAsync(name); if (addressIfExists === constants.NULL_ADDRESS) { return undefined; } @@ -71,14 +71,14 @@ export class TokenRegistryWrapper extends ContractWrapper { public async getTokenBySymbolIfExistsAsync(symbol: string): Promise<Token|undefined> { assert.isString('symbol', symbol); const tokenRegistryContract = await this._getTokenRegistryContractAsync(); - const metadata = await tokenRegistryContract.getTokenBySymbol.call(symbol); + const metadata = await tokenRegistryContract.getTokenBySymbol.callAsync(symbol); const token = this._createTokenFromMetadata(metadata); return token; } public async getTokenByNameIfExistsAsync(name: string): Promise<Token|undefined> { assert.isString('name', name); const tokenRegistryContract = await this._getTokenRegistryContractAsync(); - const metadata = await tokenRegistryContract.getTokenByName.call(name); + const metadata = await tokenRegistryContract.getTokenByName.callAsync(name); const token = this._createTokenFromMetadata(metadata); return token; } @@ -101,7 +101,9 @@ export class TokenRegistryWrapper extends ContractWrapper { if (!_.isUndefined(this._tokenRegistryContractIfExists)) { return this._tokenRegistryContractIfExists; } - const contractInstance = await this._instantiateContractIfExistsAsync((TokenRegistryArtifacts as any)); + const contractInstance = await this._instantiateContractIfExistsAsync<TokenRegistryContract>( + artifacts.TokenRegistryArtifact, + ); this._tokenRegistryContractIfExists = contractInstance as TokenRegistryContract; return this._tokenRegistryContractIfExists; } diff --git a/src/contract_wrappers/token_transfer_proxy_wrapper.ts b/src/contract_wrappers/token_transfer_proxy_wrapper.ts index da17d79ff..528d661d1 100644 --- a/src/contract_wrappers/token_transfer_proxy_wrapper.ts +++ b/src/contract_wrappers/token_transfer_proxy_wrapper.ts @@ -1,6 +1,6 @@ import * as _ from 'lodash'; import {ContractWrapper} from './contract_wrapper'; -import * as TokenTransferProxyArtifacts from '../artifacts/TokenTransferProxy.json'; +import {artifacts} from '../artifacts'; import {TokenTransferProxyContract} from '../types'; /** @@ -15,7 +15,7 @@ export class TokenTransferProxyWrapper extends ContractWrapper { */ public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> { const tokenTransferProxyContractInstance = await this._getTokenTransferProxyContractAsync(); - const isAuthorized = await tokenTransferProxyContractInstance.authorized.call(exchangeContractAddress); + const isAuthorized = await tokenTransferProxyContractInstance.authorized.callAsync(exchangeContractAddress); return isAuthorized; } /** @@ -24,7 +24,7 @@ export class TokenTransferProxyWrapper extends ContractWrapper { */ public async getAuthorizedAddressesAsync(): Promise<string[]> { const tokenTransferProxyContractInstance = await this._getTokenTransferProxyContractAsync(); - const authorizedAddresses = await tokenTransferProxyContractInstance.getAuthorizedAddresses.call(); + const authorizedAddresses = await tokenTransferProxyContractInstance.getAuthorizedAddresses.callAsync(); return authorizedAddresses; } /** @@ -44,7 +44,9 @@ export class TokenTransferProxyWrapper extends ContractWrapper { if (!_.isUndefined(this._tokenTransferProxyContractIfExists)) { return this._tokenTransferProxyContractIfExists; } - const contractInstance = await this._instantiateContractIfExistsAsync((TokenTransferProxyArtifacts as any)); + const contractInstance = await this._instantiateContractIfExistsAsync<TokenTransferProxyContract>( + artifacts.TokenTransferProxyArtifact, + ); this._tokenTransferProxyContractIfExists = contractInstance as TokenTransferProxyContract; return this._tokenTransferProxyContractIfExists; } diff --git a/src/contract_wrappers/token_wrapper.ts b/src/contract_wrappers/token_wrapper.ts index f7070f1f4..f1f967286 100644 --- a/src/contract_wrappers/token_wrapper.ts +++ b/src/contract_wrappers/token_wrapper.ts @@ -7,8 +7,7 @@ import {utils} from '../utils/utils'; import {eventUtils} from '../utils/event_utils'; import {constants} from '../utils/constants'; import {ContractWrapper} from './contract_wrapper'; -import * as TokenArtifacts from '../artifacts/Token.json'; -import * as TokenTransferProxyArtifacts from '../artifacts/TokenTransferProxy.json'; +import {artifacts} from '../artifacts'; import { TokenContract, ZeroExError, @@ -31,8 +30,8 @@ export class TokenWrapper extends ContractWrapper { public UNLIMITED_ALLOWANCE_IN_BASE_UNITS = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; private _tokenContractsByAddress: {[address: string]: TokenContract}; private _tokenLogEventEmitters: ContractEventEmitter[]; - constructor(web3Wrapper: Web3Wrapper, gasPrice?: BigNumber.BigNumber) { - super(web3Wrapper, gasPrice); + constructor(web3Wrapper: Web3Wrapper) { + super(web3Wrapper); this._tokenContractsByAddress = {}; this._tokenLogEventEmitters = []; } @@ -47,7 +46,7 @@ export class TokenWrapper extends ContractWrapper { assert.isETHAddressHex('tokenAddress', tokenAddress); const tokenContract = await this._getTokenContractAsync(tokenAddress); - let balance = await tokenContract.balanceOf.call(ownerAddress); + let balance = await tokenContract.balanceOf.callAsync(ownerAddress); // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber balance = new BigNumber(balance); return balance; @@ -60,9 +59,10 @@ export class TokenWrapper extends ContractWrapper { * for spenderAddress. * @param spenderAddress The hex encoded user Ethereum address who will be able to spend the set allowance. * @param amountInBaseUnits The allowance amount you would like to set. + * @return Transaction hash. */ public async setAllowanceAsync(tokenAddress: string, ownerAddress: string, spenderAddress: string, - amountInBaseUnits: BigNumber.BigNumber): Promise<void> { + amountInBaseUnits: BigNumber.BigNumber): Promise<string> { await assert.isSenderAddressAsync('ownerAddress', ownerAddress, this._web3Wrapper); assert.isETHAddressHex('spenderAddress', spenderAddress); assert.isETHAddressHex('tokenAddress', tokenAddress); @@ -74,10 +74,11 @@ export class TokenWrapper extends ContractWrapper { // TODO: Debug issue in testrpc and submit a PR, then remove this hack const networkIdIfExists = await this._web3Wrapper.getNetworkIdIfExistsAsync(); const gas = networkIdIfExists === constants.TESTRPC_NETWORK_ID ? ALLOWANCE_TO_ZERO_GAS_AMOUNT : undefined; - await tokenContract.approve(spenderAddress, amountInBaseUnits, { + const txHash = await tokenContract.approve.sendTransactionAsync(spenderAddress, amountInBaseUnits, { from: ownerAddress, gas, }); + return txHash; } /** * Sets the spender's allowance to an unlimited number of baseUnits on behalf of the owner address. @@ -88,12 +89,14 @@ export class TokenWrapper extends ContractWrapper { * @param ownerAddress The hex encoded user Ethereum address who would like to set an allowance * for spenderAddress. * @param spenderAddress The hex encoded user Ethereum address who will be able to spend the set allowance. + * @return Transaction hash. */ public async setUnlimitedAllowanceAsync(tokenAddress: string, ownerAddress: string, - spenderAddress: string): Promise<void> { - await this.setAllowanceAsync( + spenderAddress: string): Promise<string> { + const txHash = await this.setAllowanceAsync( tokenAddress, ownerAddress, spenderAddress, this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS, ); + return txHash; } /** * Retrieves the owners allowance in baseUnits set to the spender's address. @@ -102,12 +105,13 @@ export class TokenWrapper extends ContractWrapper { * you would like to retrieve. * @param spenderAddress The hex encoded user Ethereum address who can spend the allowance you are fetching. */ - public async getAllowanceAsync(tokenAddress: string, ownerAddress: string, spenderAddress: string) { + public async getAllowanceAsync(tokenAddress: string, ownerAddress: string, + spenderAddress: string): Promise<BigNumber.BigNumber> { assert.isETHAddressHex('ownerAddress', ownerAddress); assert.isETHAddressHex('tokenAddress', tokenAddress); const tokenContract = await this._getTokenContractAsync(tokenAddress); - let allowanceInBaseUnits = await tokenContract.allowance.call(ownerAddress, spenderAddress); + let allowanceInBaseUnits = await tokenContract.allowance.callAsync(ownerAddress, spenderAddress); // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber allowanceInBaseUnits = new BigNumber(allowanceInBaseUnits); return allowanceInBaseUnits; @@ -117,7 +121,7 @@ export class TokenWrapper extends ContractWrapper { * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed. * @param ownerAddress The hex encoded user Ethereum address whose proxy contract allowance we are retrieving. */ - public async getProxyAllowanceAsync(tokenAddress: string, ownerAddress: string) { + public async getProxyAllowanceAsync(tokenAddress: string, ownerAddress: string): Promise<BigNumber.BigNumber> { assert.isETHAddressHex('ownerAddress', ownerAddress); assert.isETHAddressHex('tokenAddress', tokenAddress); @@ -132,15 +136,17 @@ export class TokenWrapper extends ContractWrapper { * @param ownerAddress The hex encoded user Ethereum address who is setting an allowance * for the Proxy contract. * @param amountInBaseUnits The allowance amount specified in baseUnits. + * @return Transaction hash. */ public async setProxyAllowanceAsync(tokenAddress: string, ownerAddress: string, - amountInBaseUnits: BigNumber.BigNumber): Promise<void> { + amountInBaseUnits: BigNumber.BigNumber): Promise<string> { assert.isETHAddressHex('ownerAddress', ownerAddress); assert.isETHAddressHex('tokenAddress', tokenAddress); assert.isBigNumber('amountInBaseUnits', amountInBaseUnits); const proxyAddress = await this._getProxyAddressAsync(); - await this.setAllowanceAsync(tokenAddress, ownerAddress, proxyAddress, amountInBaseUnits); + const txHash = await this.setAllowanceAsync(tokenAddress, ownerAddress, proxyAddress, amountInBaseUnits); + return txHash; } /** * Sets the 0x proxy contract's allowance to a unlimited number of a tokens' baseUnits on behalf @@ -150,9 +156,13 @@ export class TokenWrapper extends ContractWrapper { * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed. * @param ownerAddress The hex encoded user Ethereum address who is setting an allowance * for the Proxy contract. + * @return Transaction hash. */ - public async setUnlimitedProxyAllowanceAsync(tokenAddress: string, ownerAddress: string): Promise<void> { - await this.setProxyAllowanceAsync(tokenAddress, ownerAddress, this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); + public async setUnlimitedProxyAllowanceAsync(tokenAddress: string, ownerAddress: string): Promise<string> { + const txHash = await this.setProxyAllowanceAsync( + tokenAddress, ownerAddress, this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS, + ); + return txHash; } /** * Transfers `amountInBaseUnits` ERC20 tokens from `fromAddress` to `toAddress`. @@ -160,9 +170,10 @@ export class TokenWrapper extends ContractWrapper { * @param fromAddress The hex encoded user Ethereum address that will send the funds. * @param toAddress The hex encoded user Ethereum address that will receive the funds. * @param amountInBaseUnits The amount (specified in baseUnits) of the token to transfer. + * @return Transaction hash. */ public async transferAsync(tokenAddress: string, fromAddress: string, toAddress: string, - amountInBaseUnits: BigNumber.BigNumber): Promise<void> { + amountInBaseUnits: BigNumber.BigNumber): Promise<string> { assert.isETHAddressHex('tokenAddress', tokenAddress); await assert.isSenderAddressAsync('fromAddress', fromAddress, this._web3Wrapper); assert.isETHAddressHex('toAddress', toAddress); @@ -175,9 +186,10 @@ export class TokenWrapper extends ContractWrapper { throw new Error(ZeroExError.InsufficientBalanceForTransfer); } - await tokenContract.transfer(toAddress, amountInBaseUnits, { + const txHash = await tokenContract.transfer.sendTransactionAsync(toAddress, amountInBaseUnits, { from: fromAddress, }); + return txHash; } /** * Transfers `amountInBaseUnits` ERC20 tokens from `fromAddress` to `toAddress`. @@ -190,10 +202,11 @@ export class TokenWrapper extends ContractWrapper { * `fromAddress` must have set an allowance to the `senderAddress` * before this call. * @param amountInBaseUnits The amount (specified in baseUnits) of the token to transfer. + * @return Transaction hash. */ public async transferFromAsync(tokenAddress: string, fromAddress: string, toAddress: string, senderAddress: string, amountInBaseUnits: BigNumber.BigNumber): - Promise<void> { + Promise<string> { assert.isETHAddressHex('tokenAddress', tokenAddress); assert.isETHAddressHex('fromAddress', fromAddress); assert.isETHAddressHex('toAddress', toAddress); @@ -212,9 +225,13 @@ export class TokenWrapper extends ContractWrapper { throw new Error(ZeroExError.InsufficientBalanceForTransfer); } - await tokenContract.transferFrom(fromAddress, toAddress, amountInBaseUnits, { - from: senderAddress, - }); + const txHash = await tokenContract.transferFrom.sendTransactionAsync( + fromAddress, toAddress, amountInBaseUnits, + { + from: senderAddress, + }, + ); + return txHash; } /** * Subscribe to an event type emitted by the Token contract. @@ -267,7 +284,9 @@ export class TokenWrapper extends ContractWrapper { if (!_.isUndefined(tokenContract)) { return tokenContract; } - const contractInstance = await this._instantiateContractIfExistsAsync((TokenArtifacts as any), tokenAddress); + const contractInstance = await this._instantiateContractIfExistsAsync<TokenContract>( + artifacts.TokenArtifact, tokenAddress, + ); tokenContract = contractInstance as TokenContract; this._tokenContractsByAddress[tokenAddress] = tokenContract; return tokenContract; @@ -276,7 +295,7 @@ export class TokenWrapper extends ContractWrapper { const networkIdIfExists = await this._web3Wrapper.getNetworkIdIfExistsAsync(); const proxyNetworkConfigsIfExists = _.isUndefined(networkIdIfExists) ? undefined : - (TokenTransferProxyArtifacts as any).networks[networkIdIfExists]; + artifacts.TokenTransferProxyArtifact.networks[networkIdIfExists]; if (_.isUndefined(proxyNetworkConfigsIfExists)) { throw new Error(ZeroExError.ContractNotDeployedOnNetwork); } |