diff options
Diffstat (limited to 'packages/0x.js')
-rw-r--r-- | packages/0x.js/src/order_watcher/order_state_watcher.ts | 48 | ||||
-rw-r--r-- | packages/0x.js/src/types.ts | 2 | ||||
-rw-r--r-- | packages/0x.js/test/exchange_wrapper_test.ts | 2 | ||||
-rw-r--r-- | packages/0x.js/test/token_wrapper_test.ts | 2 |
4 files changed, 49 insertions, 5 deletions
diff --git a/packages/0x.js/src/order_watcher/order_state_watcher.ts b/packages/0x.js/src/order_watcher/order_state_watcher.ts index 8c21c1678..1ce111708 100644 --- a/packages/0x.js/src/order_watcher/order_state_watcher.ts +++ b/packages/0x.js/src/order_watcher/order_state_watcher.ts @@ -50,6 +50,8 @@ interface OrderStateByOrderHash { [orderHash: string]: OrderState; } +const DEFAULT_CLEANUP_JOB_INTERVAL_MS = 1000 * 60 * 60; // 1h + /** * This class includes all the functionality related to watching a set of orders * for potential changes in order validity/fillability. The orderWatcher notifies @@ -68,6 +70,8 @@ export class OrderStateWatcher { private _orderStateUtils: OrderStateUtils; private _orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore; private _balanceAndProxyAllowanceLazyStore: BalanceAndProxyAllowanceLazyStore; + private _cleanupJobInterval: number; + private _cleanupJobIntervalIdIfExists?: NodeJS.Timer; constructor( web3Wrapper: Web3Wrapper, abiDecoder: AbiDecoder, token: TokenWrapper, exchange: ExchangeWrapper, config?: OrderStateWatcherConfig, @@ -92,6 +96,9 @@ export class OrderStateWatcher { this._expirationWatcher = new ExpirationWatcher( expirationMarginIfExistsMs, orderExpirationCheckingIntervalMsIfExists, ); + this._cleanupJobInterval = _.isUndefined(config) || _.isUndefined(config.cleanupJobIntervalMs) ? + DEFAULT_CLEANUP_JOB_INTERVAL_MS : + config.cleanupJobIntervalMs; } /** * Add an order to the orderStateWatcher. Before the order is added, it's @@ -139,12 +146,15 @@ export class OrderStateWatcher { this._callbackIfExists = callback; this._eventWatcher.subscribe(this._onEventWatcherCallbackAsync.bind(this)); this._expirationWatcher.subscribe(this._onOrderExpired.bind(this)); + this._cleanupJobIntervalIdIfExists = intervalUtils.setAsyncExcludingInterval( + this._cleanupAsync.bind(this), this._cleanupJobInterval, + ); } /** * Ends an orderStateWatcher subscription. */ public unsubscribe(): void { - if (_.isUndefined(this._callbackIfExists)) { + if (_.isUndefined(this._callbackIfExists) || _.isUndefined(this._cleanupJobIntervalIdIfExists)) { throw new Error(ZeroExError.SubscriptionNotFound); } this._balanceAndProxyAllowanceLazyStore.deleteAll(); @@ -152,6 +162,34 @@ export class OrderStateWatcher { delete this._callbackIfExists; this._eventWatcher.unsubscribe(); this._expirationWatcher.unsubscribe(); + intervalUtils.clearAsyncExcludingInterval(this._cleanupJobIntervalIdIfExists); + } + private async _cleanupAsync(): Promise<void> { + for (const orderHash of _.keys(this._orderByOrderHash)) { + this._cleanupOrderRelatedState(orderHash); + await this._emitRevalidateOrdersAsync([orderHash]); + } + } + private _cleanupOrderRelatedState(orderHash: string): void { + const signedOrder = this._orderByOrderHash[orderHash]; + + this._orderFilledCancelledLazyStore.deleteFilledTakerAmount(orderHash); + this._orderFilledCancelledLazyStore.deleteCancelledTakerAmount(orderHash); + + this._balanceAndProxyAllowanceLazyStore.deleteBalance(signedOrder.makerTokenAddress, signedOrder.maker); + this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(signedOrder.makerTokenAddress, signedOrder.maker); + this._balanceAndProxyAllowanceLazyStore.deleteBalance(signedOrder.takerTokenAddress, signedOrder.taker); + this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(signedOrder.takerTokenAddress, signedOrder.taker); + + const zrxTokenAddress = this._getZRXTokenAddress(); + if (!signedOrder.makerFee.isZero()) { + this._balanceAndProxyAllowanceLazyStore.deleteBalance(zrxTokenAddress, signedOrder.maker); + this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(zrxTokenAddress, signedOrder.maker); + } + if (!signedOrder.takerFee.isZero()) { + this._balanceAndProxyAllowanceLazyStore.deleteBalance(zrxTokenAddress, signedOrder.taker); + this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(zrxTokenAddress, signedOrder.taker); + } } private _onOrderExpired(orderHash: string): void { const orderState: OrderState = { @@ -266,8 +304,7 @@ export class OrderStateWatcher { this._dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress] = new Set(); } this._dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress].add(orderHash); - const exchange = (this._orderFilledCancelledLazyStore as any).exchange as ExchangeWrapper; - const zrxTokenAddress = exchange.getZRXTokenAddress(); + const zrxTokenAddress = this._getZRXTokenAddress(); if (_.isUndefined(this._dependentOrderHashes[signedOrder.maker][zrxTokenAddress])) { this._dependentOrderHashes[signedOrder.maker][zrxTokenAddress] = new Set(); } @@ -282,4 +319,9 @@ export class OrderStateWatcher { delete this._dependentOrderHashes[makerAddress]; } } + private _getZRXTokenAddress(): string { + const exchange = (this._orderFilledCancelledLazyStore as any).exchange as ExchangeWrapper; + const zrxTokenAddress = exchange.getZRXTokenAddress(); + return zrxTokenAddress; + } } diff --git a/packages/0x.js/src/types.ts b/packages/0x.js/src/types.ts index 3949c17c5..5363b02ff 100644 --- a/packages/0x.js/src/types.ts +++ b/packages/0x.js/src/types.ts @@ -407,11 +407,13 @@ export interface JSONRPCPayload { * eventPollingIntervalMs: How often to poll the Ethereum node for new events. Defaults: 200 * expirationMarginMs: Amount of time before order expiry that you'd like to be notified * of an orders expiration. Defaults: 0 + * cleanupJobIntervalMs: How often to run a cleanup job which revalidates all the orders. Defaults: 1h */ export interface OrderStateWatcherConfig { orderExpirationCheckingIntervalMs?: number; eventPollingIntervalMs?: number; expirationMarginMs?: number; + cleanupJobIntervalMs?: number; } /* diff --git a/packages/0x.js/test/exchange_wrapper_test.ts b/packages/0x.js/test/exchange_wrapper_test.ts index f6c823cc4..14559c706 100644 --- a/packages/0x.js/test/exchange_wrapper_test.ts +++ b/packages/0x.js/test/exchange_wrapper_test.ts @@ -680,7 +680,7 @@ describe('ExchangeWrapper', () => { await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelTakerAmountInBaseUnits); })().catch(done); }); - it('Outstanding subscriptions are cancelled when zeroEx.setProviderAsync called', (done: DoneCallback) => { + it('Outstanding subscriptions are cancelled when zeroEx.setProvider called', (done: DoneCallback) => { (async () => { const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<LogFillContractEventArgs>) => { diff --git a/packages/0x.js/test/token_wrapper_test.ts b/packages/0x.js/test/token_wrapper_test.ts index cc61c2324..c853fe0c2 100644 --- a/packages/0x.js/test/token_wrapper_test.ts +++ b/packages/0x.js/test/token_wrapper_test.ts @@ -398,7 +398,7 @@ describe('TokenWrapper', () => { await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount); })().catch(done); }); - it('Outstanding subscriptions are cancelled when zeroEx.setProviderAsync called', (done: DoneCallback) => { + it('Outstanding subscriptions are cancelled when zeroEx.setProvider called', (done: DoneCallback) => { (async () => { const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => { done(new Error('Expected this subscription to have been cancelled')); |