From b38aff8808db0ade04746f69bbb25b62147d17a4 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 6 Sep 2017 17:26:55 +0200 Subject: Fix log decoder to return correct types --- src/utils/abi_decoder.ts | 5 +++-- test/0x.js_test.ts | 8 +++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/utils/abi_decoder.ts b/src/utils/abi_decoder.ts index f988a5695..61c8eecd4 100644 --- a/src/utils/abi_decoder.ts +++ b/src/utils/abi_decoder.ts @@ -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; }); diff --git a/test/0x.js_test.ts b/test/0x.js_test.ts index 5182275a8..5461a7d3f 100644 --- a/test/0x.js_test.ts +++ b/test/0x.js_test.ts @@ -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); }); }); }); -- cgit v1.2.3 From 7c61b09dce6ea294013a4745895b58ad855817a0 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 6 Sep 2017 17:29:15 +0200 Subject: Add zeroEx.exchange.throwLogErrorsAsErrors --- src/contract_wrappers/exchange_wrapper.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 115bd1110..79b2ea582 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -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,20 @@ export class ExchangeWrapper extends ContractWrapper { ); return isRoundingError; } + /** + * Checks if logs contain LogError, which is emited by Exchange contract on transfer failure + * and throws an appropriate error. + * @param logsWithdecodedArgs Transaction logs as returned by `zeroEx.awaitTransactionMinedAsync` + */ + public throwLogErrorsAsErrors(logsWithdecodedArgs: LogWithDecodedArgs[]): void { + const errLog = _.find(logsWithdecodedArgs, {event: '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 { await this.stopWatchingAllEventsAsync(); delete this._exchangeContractIfExists; -- cgit v1.2.3 From a57b22a6bc20df951c70212943b018ba8039a914 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 6 Sep 2017 17:41:40 +0200 Subject: Fix overlapping async intervals issue --- src/0x.ts | 7 +++++-- src/utils/interval_utils.ts | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 src/utils/interval_utils.ts diff --git a/src/0x.ts b/src/0x.ts index bde9360c3..8709dadc9 100644 --- a/src/0x.ts +++ b/src/0x.ts @@ -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'; @@ -72,6 +73,7 @@ export class ZeroEx { public proxy: TokenTransferProxyWrapper; private _web3Wrapper: Web3Wrapper; private _abiDecoder: AbiDecoder; + private _intervalUtils: IntervalUtils; /** * Verifies that the elliptic curve signature `signature` was generated * by signing `data` with the private key corresponding to the `signerAddress` address. @@ -192,6 +194,7 @@ export class ZeroEx { const defaults = { gasPrice, }; + this._intervalUtils = new IntervalUtils(); this._web3Wrapper = new Web3Wrapper(provider, defaults); this.token = new TokenWrapper(this._web3Wrapper); this.proxy = new TokenTransferProxyWrapper(this._web3Wrapper); @@ -280,10 +283,10 @@ export class ZeroEx { txHash: string, pollingIntervalMs: number = 1000): Promise { const txReceiptPromise = new Promise( (resolve: (receipt: TransactionReceiptWithDecodedLogs) => void, reject) => { - const intervalId = setInterval(async () => { + const intervalId = this._intervalUtils.setAsyncExcludingInterval(async () => { const transactionReceipt = await this._web3Wrapper.getTransactionReceiptAsync(txHash); if (!_.isNull(transactionReceipt)) { - clearInterval(intervalId); + this._intervalUtils.clearAsyncExcludingInterval(intervalId); const logsWithDecodedArgs = _.map(transactionReceipt.logs, (log: Web3.LogEntry) => { const decodedLog = this._abiDecoder.decodeLog(log); if (_.isUndefined(decodedLog)) { diff --git a/src/utils/interval_utils.ts b/src/utils/interval_utils.ts new file mode 100644 index 000000000..23e6acc5b --- /dev/null +++ b/src/utils/interval_utils.ts @@ -0,0 +1,20 @@ +import * as _ from 'lodash'; + +export class IntervalUtils { + private mutex: {[intervalId: number]: boolean} = {}; + public setAsyncExcludingInterval(fn: () => Promise, intervalMs: number) { + const intervalId = setInterval(async () => { + if (_.isUndefined(this.mutex[intervalId])) { + return; + } else { + this.mutex[intervalId] = true; + await fn(); + delete this.mutex[intervalId]; + } + }); + return intervalId; + } + public clearAsyncExcludingInterval(intervalId: number): void { + clearInterval(intervalId); + } +} -- cgit v1.2.3 From 873aa26f63b8266078ce3cf90e3a9ae65301ae1b Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 6 Sep 2017 17:45:10 +0200 Subject: Update CHANGELOG --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62c3bbc3a..5712af40c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +v0.13.1 - _September 6, 2017_ +------------------------ + * 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) -- cgit v1.2.3 From b1feb5ac29bf2dbe424a5485eb3e48e90c08ba94 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 6 Sep 2017 17:49:51 +0200 Subject: Fix a bug in intervalUtils --- src/utils/interval_utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/interval_utils.ts b/src/utils/interval_utils.ts index 23e6acc5b..6bcf5a643 100644 --- a/src/utils/interval_utils.ts +++ b/src/utils/interval_utils.ts @@ -4,7 +4,7 @@ export class IntervalUtils { private mutex: {[intervalId: number]: boolean} = {}; public setAsyncExcludingInterval(fn: () => Promise, intervalMs: number) { const intervalId = setInterval(async () => { - if (_.isUndefined(this.mutex[intervalId])) { + if (!_.isUndefined(this.mutex[intervalId])) { return; } else { this.mutex[intervalId] = true; -- cgit v1.2.3 From 88791f732fc83bb273508ec8d4b1e87c6bea05dc Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 6 Sep 2017 18:22:28 +0200 Subject: Make intervalUtils an object instead of a class and make instance variable local --- src/0x.ts | 8 +++----- src/utils/interval_utils.ts | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/0x.ts b/src/0x.ts index 8709dadc9..5d5604780 100644 --- a/src/0x.ts +++ b/src/0x.ts @@ -13,7 +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 {intervalUtils} from './utils/interval_utils'; import {artifacts} from './artifacts'; import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper'; import {TokenRegistryWrapper} from './contract_wrappers/token_registry_wrapper'; @@ -73,7 +73,6 @@ export class ZeroEx { public proxy: TokenTransferProxyWrapper; private _web3Wrapper: Web3Wrapper; private _abiDecoder: AbiDecoder; - private _intervalUtils: IntervalUtils; /** * Verifies that the elliptic curve signature `signature` was generated * by signing `data` with the private key corresponding to the `signerAddress` address. @@ -194,7 +193,6 @@ export class ZeroEx { const defaults = { gasPrice, }; - this._intervalUtils = new IntervalUtils(); this._web3Wrapper = new Web3Wrapper(provider, defaults); this.token = new TokenWrapper(this._web3Wrapper); this.proxy = new TokenTransferProxyWrapper(this._web3Wrapper); @@ -283,10 +281,10 @@ export class ZeroEx { txHash: string, pollingIntervalMs: number = 1000): Promise { const txReceiptPromise = new Promise( (resolve: (receipt: TransactionReceiptWithDecodedLogs) => void, reject) => { - const intervalId = this._intervalUtils.setAsyncExcludingInterval(async () => { + const intervalId = intervalUtils.setAsyncExcludingInterval(async () => { const transactionReceipt = await this._web3Wrapper.getTransactionReceiptAsync(txHash); if (!_.isNull(transactionReceipt)) { - this._intervalUtils.clearAsyncExcludingInterval(intervalId); + intervalUtils.clearAsyncExcludingInterval(intervalId); const logsWithDecodedArgs = _.map(transactionReceipt.logs, (log: Web3.LogEntry) => { const decodedLog = this._abiDecoder.decodeLog(log); if (_.isUndefined(decodedLog)) { diff --git a/src/utils/interval_utils.ts b/src/utils/interval_utils.ts index 6bcf5a643..1656318e6 100644 --- a/src/utils/interval_utils.ts +++ b/src/utils/interval_utils.ts @@ -1,20 +1,20 @@ import * as _ from 'lodash'; -export class IntervalUtils { - private mutex: {[intervalId: number]: boolean} = {}; - public setAsyncExcludingInterval(fn: () => Promise, intervalMs: number) { +export const intervalUtils = { + setAsyncExcludingInterval(fn: () => Promise, intervalMs: number) { + let locked = false; const intervalId = setInterval(async () => { - if (!_.isUndefined(this.mutex[intervalId])) { + if (locked) { return; } else { - this.mutex[intervalId] = true; + locked = true; await fn(); - delete this.mutex[intervalId]; + locked = false; } }); return intervalId; - } - public clearAsyncExcludingInterval(intervalId: number): void { + }, + clearAsyncExcludingInterval(intervalId: number): void { clearInterval(intervalId); - } -} + }, +}; -- cgit v1.2.3 From 0b6e874a0d06b6360946fa2495176ee4e5e7a34e Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 6 Sep 2017 18:25:03 +0200 Subject: Fix a comment --- src/contract_wrappers/exchange_wrapper.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 79b2ea582..f4b62d8c0 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -684,8 +684,7 @@ export class ExchangeWrapper extends ContractWrapper { return isRoundingError; } /** - * Checks if logs contain LogError, which is emited by Exchange contract on transfer failure - * and throws an appropriate error. + * 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 { -- cgit v1.2.3 From 67ed341f24d48491b5365a5bb82e445c0ca51f8c Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 6 Sep 2017 18:26:17 +0200 Subject: Use LogError type --- src/contract_wrappers/exchange_wrapper.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index f4b62d8c0..47a066a8f 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -685,10 +685,10 @@ export class ExchangeWrapper extends ContractWrapper { } /** * Checks if logs contain LogError, which is emmited by Exchange contract on transaction failure. - * @param logsWithdecodedArgs Transaction logs as returned by `zeroEx.awaitTransactionMinedAsync` + * @param logsWithDecodedArgs Transaction logs as returned by `zeroEx.awaitTransactionMinedAsync` */ - public throwLogErrorsAsErrors(logsWithdecodedArgs: LogWithDecodedArgs[]): void { - const errLog = _.find(logsWithdecodedArgs, {event: 'LogError'}); + 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(); -- cgit v1.2.3 From d2dc4d18be93fd04f237bef7fe7e29e4a9447517 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 6 Sep 2017 18:27:25 +0200 Subject: Add zeroEx.exchange.throwLogErrorsAsErrors to CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5712af40c..6a61de712 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ 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) -- cgit v1.2.3