diff options
author | Fabio Berger <me@fabioberger.com> | 2017-11-11 03:13:15 +0800 |
---|---|---|
committer | Fabio Berger <me@fabioberger.com> | 2017-11-11 03:13:15 +0800 |
commit | 4262ac3c8966468b343c6467e0e9da85ef25be05 (patch) | |
tree | bf57b46afd2967b72fc3cd6d5d11d8efa82fb3af | |
parent | 76b66872d8f797ee3b0efe0fa2ca914cf44ee46c (diff) | |
download | dexon-0x-contracts-4262ac3c8966468b343c6467e0e9da85ef25be05.tar.gz dexon-0x-contracts-4262ac3c8966468b343c6467e0e9da85ef25be05.tar.zst dexon-0x-contracts-4262ac3c8966468b343c6467e0e9da85ef25be05.zip |
Fix unhandled promise rejection error on subscriptions
-rw-r--r-- | src/contract_wrappers/contract_wrapper.ts | 25 | ||||
-rw-r--r-- | src/types.ts | 4 | ||||
-rw-r--r-- | test/exchange_wrapper_test.ts | 23 | ||||
-rw-r--r-- | test/token_wrapper_test.ts | 10 |
4 files changed, 38 insertions, 24 deletions
diff --git a/src/contract_wrappers/contract_wrapper.ts b/src/contract_wrappers/contract_wrapper.ts index 19dccc6f2..a02465982 100644 --- a/src/contract_wrappers/contract_wrapper.ts +++ b/src/contract_wrappers/contract_wrapper.ts @@ -50,10 +50,14 @@ export class ContractWrapper { this._filterCallbacks[filterToken] = callback; return filterToken; } - protected _unsubscribe(filterToken: string): void { + protected _unsubscribe(filterToken: string, err?: Error): void { if (_.isUndefined(this._filters[filterToken])) { throw new Error(ZeroExError.SubscriptionNotFound); } + if (!_.isUndefined(err)) { + const callback = this._filterCallbacks[filterToken]; + callback(err, undefined); + } delete this._filters[filterToken]; delete this._filterCallbacks[filterToken]; if (_.isEmpty(this._filters)) { @@ -90,7 +94,7 @@ export class ContractWrapper { ...decodedLog, removed, }; - this._filterCallbacks[filterToken](logEvent); + this._filterCallbacks[filterToken](null, logEvent); } }); } @@ -122,11 +126,18 @@ export class ContractWrapper { delete this._blockAndLogStreamer; } private async _reconcileBlockAsync(): Promise<void> { - const latestBlock = await this._web3Wrapper.getBlockAsync(BlockParamLiteral.Latest); - // We need to coerce to Block type cause Web3.Block includes types for mempool blocks - if (!_.isUndefined(this._blockAndLogStreamer)) { - // If we clear the interval while fetching the block - this._blockAndLogStreamer will be undefined - this._blockAndLogStreamer.reconcileNewBlock(latestBlock as any as Block); + try { + const latestBlock = await this._web3Wrapper.getBlockAsync(BlockParamLiteral.Latest); + // We need to coerce to Block type cause Web3.Block includes types for mempool blocks + if (!_.isUndefined(this._blockAndLogStreamer)) { + // If we clear the interval while fetching the block - this._blockAndLogStreamer will be undefined + this._blockAndLogStreamer.reconcileNewBlock(latestBlock as any as Block); + } + } catch (err) { + const filterTokens = _.keys(this._filterCallbacks); + _.each(filterTokens, filterToken => { + this._unsubscribe(filterToken, err); + }); } } } diff --git a/src/types.ts b/src/types.ts index a9eac56d8..af3c36736 100644 --- a/src/types.ts +++ b/src/types.ts @@ -41,8 +41,8 @@ export type OrderValues = [BigNumber, BigNumber, BigNumber, export interface LogEvent<ArgsType> extends LogWithDecodedArgs<ArgsType> { removed: boolean; } -export type EventCallbackAsync<ArgsType> = (log: LogEvent<ArgsType>) => Promise<void>; -export type EventCallbackSync<ArgsType> = (log: LogEvent<ArgsType>) => void; +export type EventCallbackAsync<ArgsType> = (err: null|Error, log?: LogEvent<ArgsType>) => Promise<void>; +export type EventCallbackSync<ArgsType> = (err: null|Error, log?: LogEvent<ArgsType>) => void; export type EventCallback<ArgsType> = EventCallbackSync<ArgsType>|EventCallbackAsync<ArgsType>; export interface ExchangeContract extends Web3.ContractInstance { isValidSignature: { diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 7c76499d5..654f626c6 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -304,11 +304,11 @@ describe('ExchangeWrapper', () => { orderFillBatch = [ { signedOrder, - takerTokenFillAmount: takerTokenFillAmount, + takerTokenFillAmount, }, { signedOrder: anotherSignedOrder, - takerTokenFillAmount: takerTokenFillAmount, + takerTokenFillAmount, }, ]; }); @@ -647,7 +647,7 @@ describe('ExchangeWrapper', () => { // Source: https://github.com/mochajs/mocha/issues/2407 it('Should receive the LogFill event when an order is filled', (done: DoneCallback) => { (async () => { - const callback = (logEvent: LogEvent<LogFillContractEventArgs>) => { + const callback = (err: Error, logEvent: LogEvent<LogFillContractEventArgs>) => { expect(logEvent.event).to.be.equal(ExchangeEvents.LogFill); done(); }; @@ -655,13 +655,14 @@ describe('ExchangeWrapper', () => { ExchangeEvents.LogFill, indexFilterValues, callback, ); await zeroEx.exchange.fillOrderAsync( - signedOrder, takerTokenFillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, + signedOrder, takerTokenFillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, + takerAddress, ); })().catch(done); }); it('Should receive the LogCancel event when an order is cancelled', (done: DoneCallback) => { (async () => { - const callback = (logEvent: LogEvent<LogCancelContractEventArgs>) => { + const callback = (err: Error, logEvent: LogEvent<LogCancelContractEventArgs>) => { expect(logEvent.event).to.be.equal(ExchangeEvents.LogCancel); done(); }; @@ -673,7 +674,7 @@ describe('ExchangeWrapper', () => { }); it('Outstanding subscriptions are cancelled when zeroEx.setProviderAsync called', (done: DoneCallback) => { (async () => { - const callbackNeverToBeCalled = (logEvent: LogEvent<LogFillContractEventArgs>) => { + const callbackNeverToBeCalled = (err: Error, logEvent: LogEvent<LogFillContractEventArgs>) => { done(new Error('Expected this subscription to have been cancelled')); }; await zeroEx.exchange.subscribeAsync( @@ -683,7 +684,7 @@ describe('ExchangeWrapper', () => { const newProvider = web3Factory.getRpcProvider(); await zeroEx.setProviderAsync(newProvider); - const callback = (logEvent: LogEvent<LogFillContractEventArgs>) => { + const callback = (err: Error, logEvent: LogEvent<LogFillContractEventArgs>) => { expect(logEvent.event).to.be.equal(ExchangeEvents.LogFill); done(); }; @@ -691,13 +692,14 @@ describe('ExchangeWrapper', () => { ExchangeEvents.LogFill, indexFilterValues, callback, ); await zeroEx.exchange.fillOrderAsync( - signedOrder, takerTokenFillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, + signedOrder, takerTokenFillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, + takerAddress, ); })().catch(done); }); it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => { (async () => { - const callbackNeverToBeCalled = (logEvent: LogEvent<LogFillContractEventArgs>) => { + const callbackNeverToBeCalled = (err: Error, logEvent: LogEvent<LogFillContractEventArgs>) => { done(new Error('Expected this subscription to have been cancelled')); }; const subscriptionToken = await zeroEx.exchange.subscribeAsync( @@ -705,7 +707,8 @@ describe('ExchangeWrapper', () => { ); zeroEx.exchange.unsubscribe(subscriptionToken); await zeroEx.exchange.fillOrderAsync( - signedOrder, takerTokenFillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, + signedOrder, takerTokenFillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, + takerAddress, ); done(); })().catch(done); diff --git a/test/token_wrapper_test.ts b/test/token_wrapper_test.ts index b35fa43f9..b244e3a92 100644 --- a/test/token_wrapper_test.ts +++ b/test/token_wrapper_test.ts @@ -358,7 +358,7 @@ describe('TokenWrapper', () => { // Source: https://github.com/mochajs/mocha/issues/2407 it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => { (async () => { - const callback = (logEvent: LogEvent<TransferContractEventArgs>) => { + const callback = (err: Error, logEvent: LogEvent<TransferContractEventArgs>) => { expect(logEvent).to.not.be.undefined(); const args = logEvent.args; expect(args._from).to.be.equal(coinbase); @@ -373,7 +373,7 @@ describe('TokenWrapper', () => { }); it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => { (async () => { - const callback = (logEvent: LogEvent<ApprovalContractEventArgs>) => { + const callback = (err: Error, logEvent: LogEvent<ApprovalContractEventArgs>) => { expect(logEvent).to.not.be.undefined(); const args = logEvent.args; expect(args._owner).to.be.equal(coinbase); @@ -388,13 +388,13 @@ describe('TokenWrapper', () => { }); it('Outstanding subscriptions are cancelled when zeroEx.setProviderAsync called', (done: DoneCallback) => { (async () => { - const callbackNeverToBeCalled = (logEvent: LogEvent<TransferContractEventArgs>) => { + const callbackNeverToBeCalled = (err: Error, logEvent: LogEvent<TransferContractEventArgs>) => { done(new Error('Expected this subscription to have been cancelled')); }; zeroEx.token.subscribe( tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled, ); - const callbackToBeCalled = (logEvent: LogEvent<TransferContractEventArgs>) => { + const callbackToBeCalled = (err: Error, logEvent: LogEvent<TransferContractEventArgs>) => { done(); }; const newProvider = web3Factory.getRpcProvider(); @@ -407,7 +407,7 @@ describe('TokenWrapper', () => { }); it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => { (async () => { - const callbackNeverToBeCalled = (logEvent: LogEvent<TokenContractEventArgs>) => { + const callbackNeverToBeCalled = (err: Error, logEvent: LogEvent<TokenContractEventArgs>) => { done(new Error('Expected this subscription to have been cancelled')); }; const subscriptionToken = zeroEx.token.subscribe( |