Refactor subscription to return zeroExSignature object

This commit is contained in:
Leonid Logvinov
2017-06-13 15:52:50 +02:00
parent a045eb7bbb
commit 6ad1900ada
5 changed files with 51 additions and 28 deletions

View File

@@ -14,6 +14,7 @@ import {
SignedOrder,
ContractEvent,
ExchangeEvents,
ZeroExEvent,
SubscriptionOpts,
IndexFilterValues,
CreateContractEvent,
@@ -47,7 +48,7 @@ export class ExchangeWrapper extends ContractWrapper {
[ExchangeContractErrCodes.ERROR_FILL_BALANCE_ALLOWANCE]: ExchangeContractErrs.FILL_BALANCE_ALLOWANCE_ERROR,
};
private _exchangeContractIfExists?: ExchangeContract;
private _exchangeLogEventObjs: ContractEventObj[];
private _exchangeLogEventObjs: ZeroExEvent[];
private _tokenWrapper: TokenWrapper;
private static _getOrderAddressesAndValues(order: Order): [OrderAddresses, OrderValues] {
const orderAddresses: OrderAddresses = [
@@ -73,7 +74,7 @@ export class ExchangeWrapper extends ContractWrapper {
this._exchangeLogEventObjs = [];
}
public async invalidateContractInstanceAsync(): Promise<void> {
await this._stopWatchingExchangeLogEventsAsync();
await this.stopWatchingAllEventsAsync();
delete this._exchangeContractIfExists;
}
/**
@@ -517,11 +518,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 ZeroExEvent object
*/
public async subscribeAsync(eventName: ExchangeEvents, subscriptionOpts: SubscriptionOpts,
indexFilterValues: IndexFilterValues, callback: EventCallback):
Promise<void> {
indexFilterValues: IndexFilterValues):
Promise<ZeroExEvent> {
const exchangeContract = await this._getExchangeContractAsync();
let createLogEvent: CreateContractEvent;
switch (eventName) {
@@ -535,13 +536,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 zeroExEvent = this._wrapEventAsZeroExEvent(logEventObj);
this._exchangeLogEventObjs.push(zeroExEvent);
return zeroExEvent;
}
/**
* Returns the ethereum address of the current exchange contract
@@ -552,6 +553,23 @@ 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._exchangeLogEventObjs, logEventObj => logEventObj.stopWatchingAsync());
await Promise.all(stopWatchingPromises);
this._exchangeLogEventObjs = [];
}
private _wrapEventAsZeroExEvent(event: ContractEventObj): ZeroExEvent {
const zeroExEvent = {
watch: event.watch,
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> {

View File

@@ -22,4 +22,5 @@ export {
OrderCancellationRequest,
OrderFillRequest,
DoneCallback,
ZeroExEvent,
} from './types';

View File

@@ -275,3 +275,8 @@ export interface ContractInstance {
export interface Artifact {
networks: {[networkId: number]: any};
}
export interface ZeroExEvent {
watch: (eventCallback: EventCallback) => void;
stopWatchingAsync: () => Promise<void>;
}

View File

@@ -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 {

View File

@@ -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();