diff options
author | Leonid <logvinov.leon@gmail.com> | 2017-06-14 00:08:30 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-14 00:08:30 +0800 |
commit | 2a56ab084631ed56718820beccc4df05590d0a6e (patch) | |
tree | 4744a89c36f28f6e679418805289456e7b03c941 | |
parent | 52dc6b77104792852eb7cdffb4a088b35b46f2be (diff) | |
parent | ac8116bbe4a615fd70cb4ae22713ca36db3ee963 (diff) | |
download | dexon-0x-contracts-2a56ab084631ed56718820beccc4df05590d0a6e.tar.gz dexon-0x-contracts-2a56ab084631ed56718820beccc4df05590d0a6e.tar.zst dexon-0x-contracts-2a56ab084631ed56718820beccc4df05590d0a6e.zip |
Merge pull request #64 from 0xProject/events
Refactor events API
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | src/contract_wrappers/exchange_wrapper.ts | 47 | ||||
-rw-r--r-- | src/index.ts | 1 | ||||
-rw-r--r-- | src/types.ts | 5 | ||||
-rw-r--r-- | src/utils/utils.ts | 4 | ||||
-rw-r--r-- | test/exchange_wrapper_test.ts | 46 |
6 files changed, 74 insertions, 31 deletions
diff --git a/package.json b/package.json index f3f7a9bb8..4b4a4ec57 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@0xproject/0x.js", - "version": "0.2.3", + "version": "0.3.0", "description": "A javascript library for interacting with the 0x protocol", "keywords": [ "0x.js", diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 74b8d25c1..14d633d66 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -14,11 +14,11 @@ import { SignedOrder, ContractEvent, ExchangeEvents, + EventEmitter, SubscriptionOpts, IndexFilterValues, CreateContractEvent, ContractEventObj, - EventCallback, ContractResponse, OrderCancellationRequest, OrderFillRequest, @@ -47,7 +47,7 @@ export class ExchangeWrapper extends ContractWrapper { [ExchangeContractErrCodes.ERROR_FILL_BALANCE_ALLOWANCE]: ExchangeContractErrs.FILL_BALANCE_ALLOWANCE_ERROR, }; private _exchangeContractIfExists?: ExchangeContract; - private _exchangeLogEventObjs: ContractEventObj[]; + private _exchangeLogEventEmitters: EventEmitter[]; private _tokenWrapper: TokenWrapper; private static _getOrderAddressesAndValues(order: Order): [OrderAddresses, OrderValues] { const orderAddresses: OrderAddresses = [ @@ -70,10 +70,10 @@ export class ExchangeWrapper extends ContractWrapper { constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper) { super(web3Wrapper); this._tokenWrapper = tokenWrapper; - this._exchangeLogEventObjs = []; + this._exchangeLogEventEmitters = []; } public async invalidateContractInstanceAsync(): Promise<void> { - await this._stopWatchingExchangeLogEventsAsync(); + await this.stopWatchingAllEventsAsync(); delete this._exchangeContractIfExists; } /** @@ -517,11 +517,11 @@ export class ExchangeWrapper extends ContractWrapper { * @param subscriptionOpts Subscriptions options that let you configure the subscription. * @param indexFilterValues A JS 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 The callback that will be called everytime a matching event is found. + * @return EventEmitter object */ public async subscribeAsync(eventName: ExchangeEvents, subscriptionOpts: SubscriptionOpts, - indexFilterValues: IndexFilterValues, callback: EventCallback): - Promise<void> { + indexFilterValues: IndexFilterValues): + Promise<EventEmitter> { const exchangeContract = await this._getExchangeContractAsync(); let createLogEvent: CreateContractEvent; switch (eventName) { @@ -535,13 +535,13 @@ export class ExchangeWrapper extends ContractWrapper { createLogEvent = exchangeContract.LogCancel; break; default: - utils.spawnSwitchErr('ExchangeEvents', eventName); - return; + throw utils.spawnSwitchErr('ExchangeEvents', eventName); } const logEventObj: ContractEventObj = createLogEvent(indexFilterValues, subscriptionOpts); - logEventObj.watch(callback); - this._exchangeLogEventObjs.push(logEventObj); + const eventEmitter = this._wrapEventEmitter(logEventObj); + this._exchangeLogEventEmitters.push(eventEmitter); + return eventEmitter; } /** * Returns the ethereum address of the current exchange contract @@ -552,6 +552,24 @@ export class ExchangeWrapper extends ContractWrapper { const exchangeContract = await this._getExchangeContractAsync(); return exchangeContract.address; } + /** + * Stops watching for all exchange events + */ + public async stopWatchingAllEventsAsync(): Promise<void> { + const stopWatchingPromises = _.map(this._exchangeLogEventEmitters, + logEventObj => logEventObj.stopWatchingAsync()); + await Promise.all(stopWatchingPromises); + this._exchangeLogEventEmitters = []; + } + private _wrapEventEmitter(event: ContractEventObj): EventEmitter { + const zeroExEvent = { + watch: event.watch.bind(event), + stopWatchingAsync: async () => { + await promisify(event.stopWatching, event)(); + }, + }; + return zeroExEvent; + } private async _isValidSignatureUsingContractCallAsync(dataHex: string, ecSignature: ECSignature, signerAddressHex: string): Promise<boolean> { assert.isHexString('dataHex', dataHex); @@ -580,13 +598,6 @@ export class ExchangeWrapper extends ContractWrapper { const orderHashHex = await exchangeInstance.getOrderHash.call(orderAddresses, orderValues); return orderHashHex; } - private async _stopWatchingExchangeLogEventsAsync() { - const stopWatchingPromises = _.map(this._exchangeLogEventObjs, logEventObj => { - return promisify(logEventObj.stopWatching, logEventObj)(); - }); - await Promise.all(stopWatchingPromises); - this._exchangeLogEventObjs = []; - } private async _validateFillOrderAndThrowIfInvalidAsync(signedOrder: SignedOrder, fillTakerAmount: BigNumber.BigNumber, senderAddress: string): Promise<void> { diff --git a/src/index.ts b/src/index.ts index 16e48862b..b2963aca7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -22,4 +22,5 @@ export { OrderCancellationRequest, OrderFillRequest, DoneCallback, + EventEmitter, } from './types'; diff --git a/src/types.ts b/src/types.ts index 1b70d950b..2197fbfc3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -275,3 +275,8 @@ export interface ContractInstance { export interface Artifact { networks: {[networkId: number]: any}; } + +export interface EventEmitter { + watch: (eventCallback: EventCallback) => void; + stopWatchingAsync: () => Promise<void>; +} diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 5786bab07..bad5b6498 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -22,11 +22,11 @@ export const utils = { isParityNode(nodeVersion: string): boolean { return _.includes(nodeVersion, 'Parity'); }, - isValidOrderHash(orderHashHex: string) { + isValidOrderHash(orderHashHex: string): boolean { const isValid = /^0x[0-9A-F]{64}$/i.test(orderHashHex); return isValid; }, - spawnSwitchErr(name: string, value: any) { + spawnSwitchErr(name: string, value: any): Error { return new Error(`Unexpected switch value: ${value} encountered for ${name}`); }, getOrderHashHex(order: Order|SignedOrder, exchangeContractAddr: string): string { diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index f9cf9651f..6d927e218 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -619,7 +619,7 @@ describe('ExchangeWrapper', () => { ); }); afterEach(async () => { - await (zeroEx.exchange as any)._stopWatchingExchangeLogEventsAsync(); + await zeroEx.exchange.stopWatchingAllEventsAsync(); }); // Hack: Mocha does not allow a test to be both async and have a `done` callback // Since we need to await the receipt of the event in the `subscribeAsync` callback, @@ -632,8 +632,9 @@ describe('ExchangeWrapper', () => { fromBlock: 0, toBlock: 'latest', }; - await zeroEx.exchange.subscribeAsync(ExchangeEvents.LogFill, subscriptionOpts, - indexFilterValues, (err: Error, event: ContractEvent) => { + const zeroExEvent = await zeroEx.exchange.subscribeAsync(ExchangeEvents.LogFill, subscriptionOpts, + indexFilterValues); + zeroExEvent.watch((err: Error, event: ContractEvent) => { expect(err).to.be.null(); expect(event).to.not.be.undefined(); done(); @@ -650,12 +651,13 @@ describe('ExchangeWrapper', () => { fromBlock: 0, toBlock: 'latest', }; - await zeroEx.exchange.subscribeAsync(ExchangeEvents.LogCancel, subscriptionOpts, - indexFilterValues, (err: Error, event: ContractEvent) => { + const zeroExEvent = await zeroEx.exchange.subscribeAsync(ExchangeEvents.LogCancel, subscriptionOpts, + indexFilterValues); + zeroExEvent.watch((err: Error, event: ContractEvent) => { expect(err).to.be.null(); expect(event).to.not.be.undefined(); done(); - }); + }); const cancelTakerAmountInBaseUnits = new BigNumber(1); await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelTakerAmountInBaseUnits); })(); @@ -666,16 +668,20 @@ describe('ExchangeWrapper', () => { fromBlock: 0, toBlock: 'latest', }; - await zeroEx.exchange.subscribeAsync(ExchangeEvents.LogFill, subscriptionOpts, - indexFilterValues, (err: Error, event: ContractEvent) => { + const eventSubscriptionToBeCancelled = await zeroEx.exchange.subscribeAsync( + ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues, + ); + eventSubscriptionToBeCancelled.watch((err: Error, event: ContractEvent) => { done(new Error('Expected this subscription to have been cancelled')); }); const newProvider = web3Factory.getRpcProvider(); await zeroEx.setProviderAsync(newProvider); - await zeroEx.exchange.subscribeAsync(ExchangeEvents.LogFill, subscriptionOpts, - indexFilterValues, (err: Error, event: ContractEvent) => { + const eventSubscriptionToStay = await zeroEx.exchange.subscribeAsync( + ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues, + ); + eventSubscriptionToStay.watch((err: Error, event: ContractEvent) => { expect(err).to.be.null(); expect(event).to.not.be.undefined(); done(); @@ -687,6 +693,26 @@ describe('ExchangeWrapper', () => { ); })(); }); + it('Should stop watch for events when stopWatchingAsync called on the eventEmitter', (done: DoneCallback) => { + (async () => { + const subscriptionOpts: SubscriptionOpts = { + fromBlock: 0, + toBlock: 'latest', + }; + const eventSubscriptionToBeStopped = await zeroEx.exchange.subscribeAsync( + ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues, + ); + eventSubscriptionToBeStopped.watch((err: Error, event: ContractEvent) => { + done(new Error('Expected this subscription to have been stopped')); + }); + await eventSubscriptionToBeStopped.stopWatchingAsync(); + const fillTakerAmountInBaseUnits = new BigNumber(1); + await zeroEx.exchange.fillOrderAsync( + signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, takerAddress, + ); + done(); + })(); + }); }); describe('#getOrderHashHexUsingContractCallAsync', () => { let makerTokenAddress: string; |