Merge pull request #157 from 0xProject/feature/throw-for-exchange-errors
Feature/throw for exchange errors
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
# CHANGELOG
|
||||
|
||||
v0.13.1 - _September 6, 2017_
|
||||
------------------------
|
||||
* Added `zeroEx.exchange.throwLogErrorsAsErrors` method to public interface (#157)
|
||||
* Fixed an issue with overlapping async intervals in `zeroEx.awaitTransactionMinedAsync` (#157)
|
||||
* Fixed an issue with log decoder returning `BigNumber`s as `strings` (#157)
|
||||
|
||||
v0.13.0 - _September 6, 2017_
|
||||
------------------------
|
||||
* Made all the functions submitting transactions to the network to immediately return transaction hash (#151)
|
||||
|
||||
@@ -13,6 +13,7 @@ import {utils} from './utils/utils';
|
||||
import {signatureUtils} from './utils/signature_utils';
|
||||
import {assert} from './utils/assert';
|
||||
import {AbiDecoder} from './utils/abi_decoder';
|
||||
import {intervalUtils} from './utils/interval_utils';
|
||||
import {artifacts} from './artifacts';
|
||||
import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper';
|
||||
import {TokenRegistryWrapper} from './contract_wrappers/token_registry_wrapper';
|
||||
@@ -280,10 +281,10 @@ export class ZeroEx {
|
||||
txHash: string, pollingIntervalMs: number = 1000): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
const txReceiptPromise = new Promise(
|
||||
(resolve: (receipt: TransactionReceiptWithDecodedLogs) => void, reject) => {
|
||||
const intervalId = setInterval(async () => {
|
||||
const intervalId = intervalUtils.setAsyncExcludingInterval(async () => {
|
||||
const transactionReceipt = await this._web3Wrapper.getTransactionReceiptAsync(txHash);
|
||||
if (!_.isNull(transactionReceipt)) {
|
||||
clearInterval(intervalId);
|
||||
intervalUtils.clearAsyncExcludingInterval(intervalId);
|
||||
const logsWithDecodedArgs = _.map(transactionReceipt.logs, (log: Web3.LogEntry) => {
|
||||
const decodedLog = this._abiDecoder.decodeLog(log);
|
||||
if (_.isUndefined(decodedLog)) {
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
LogErrorContractEventArgs,
|
||||
LogFillContractEventArgs,
|
||||
LogCancelContractEventArgs,
|
||||
LogWithDecodedArgs,
|
||||
} from '../types';
|
||||
import {assert} from '../utils/assert';
|
||||
import {utils} from '../utils/utils';
|
||||
@@ -46,6 +47,14 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
private _exchangeLogEventEmitters: ContractEventEmitter[];
|
||||
private _orderValidationUtils: OrderValidationUtils;
|
||||
private _tokenWrapper: TokenWrapper;
|
||||
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 static _getOrderAddressesAndValues(order: Order): [OrderAddresses, OrderValues] {
|
||||
const orderAddresses: OrderAddresses = [
|
||||
order.maker,
|
||||
@@ -674,6 +683,19 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
);
|
||||
return isRoundingError;
|
||||
}
|
||||
/**
|
||||
* Checks if logs contain LogError, which is emmited by Exchange contract on transaction failure.
|
||||
* @param logsWithDecodedArgs Transaction logs as returned by `zeroEx.awaitTransactionMinedAsync`
|
||||
*/
|
||||
public throwLogErrorsAsErrors(logsWithDecodedArgs: LogWithDecodedArgs[]): void {
|
||||
const errLog = _.find(logsWithDecodedArgs, {event: ExchangeEvents.LogError});
|
||||
if (!_.isUndefined(errLog)) {
|
||||
const logArgs: LogErrorContractEventArgs = errLog.args as any;
|
||||
const errCode = logArgs.errorId.toNumber();
|
||||
const errMessage = this._exchangeContractErrCodesToMsg[errCode];
|
||||
throw new Error(errMessage);
|
||||
}
|
||||
}
|
||||
private async _invalidateContractInstancesAsync(): Promise<void> {
|
||||
await this.stopWatchingAllEventsAsync();
|
||||
delete this._exchangeContractIfExists;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import * as Web3 from 'web3';
|
||||
import * as _ from 'lodash';
|
||||
import * as BigNumber from 'bignumber.js';
|
||||
import {AbiType, DecodedLogArgs, DecodedArgs} from '../types';
|
||||
import * as SolidityCoder from 'web3/lib/solidity/coder';
|
||||
|
||||
@@ -31,9 +32,9 @@ export class AbiDecoder {
|
||||
dataIndex++;
|
||||
}
|
||||
if (param.type === 'address') {
|
||||
value = this.padZeros(new Web3().toBigNumber(value).toString(16));
|
||||
value = this.padZeros(new BigNumber(value).toString(16));
|
||||
} else if (param.type === 'uint256' || param.type === 'uint8' || param.type === 'int' ) {
|
||||
value = new Web3().toBigNumber(value).toString(10);
|
||||
value = new BigNumber(value);
|
||||
}
|
||||
decodedParams[param.name] = value;
|
||||
});
|
||||
|
||||
20
src/utils/interval_utils.ts
Normal file
20
src/utils/interval_utils.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import * as _ from 'lodash';
|
||||
|
||||
export const intervalUtils = {
|
||||
setAsyncExcludingInterval(fn: () => Promise<void>, intervalMs: number) {
|
||||
let locked = false;
|
||||
const intervalId = setInterval(async () => {
|
||||
if (locked) {
|
||||
return;
|
||||
} else {
|
||||
locked = true;
|
||||
await fn();
|
||||
locked = false;
|
||||
}
|
||||
});
|
||||
return intervalId;
|
||||
},
|
||||
clearAsyncExcludingInterval(intervalId: number): void {
|
||||
clearInterval(intervalId);
|
||||
},
|
||||
};
|
||||
@@ -226,11 +226,9 @@ describe('ZeroEx library', () => {
|
||||
const txReceiptWithDecodedLogs = await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const log = txReceiptWithDecodedLogs.logs[0] as LogWithDecodedArgs;
|
||||
expect(log.event).to.be.equal('Approval');
|
||||
expect(log.args).to.be.deep.equal({
|
||||
_owner: coinbase,
|
||||
_spender: proxyAddress,
|
||||
_value: zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS.toString(),
|
||||
});
|
||||
expect(log.args._owner).to.be.equal(coinbase);
|
||||
expect(log.args._spender).to.be.equal(proxyAddress);
|
||||
expect(log.args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user