aboutsummaryrefslogtreecommitdiffstats
path: root/src/mempool/order_state_watcher.ts
diff options
context:
space:
mode:
authorFabio Berger <me@fabioberger.com>2017-11-09 08:01:57 +0800
committerFabio Berger <me@fabioberger.com>2017-11-09 08:01:57 +0800
commit6007609f7132d5f919c8e9de04ae6c652ce38980 (patch)
tree1b539c0e448be17693006d67c7025403dad637ce /src/mempool/order_state_watcher.ts
parent5a6ed252c400b0442045354b35a06162f3d1b89e (diff)
downloaddexon-0x-contracts-6007609f7132d5f919c8e9de04ae6c652ce38980.tar
dexon-0x-contracts-6007609f7132d5f919c8e9de04ae6c652ce38980.tar.gz
dexon-0x-contracts-6007609f7132d5f919c8e9de04ae6c652ce38980.tar.bz2
dexon-0x-contracts-6007609f7132d5f919c8e9de04ae6c652ce38980.tar.lz
dexon-0x-contracts-6007609f7132d5f919c8e9de04ae6c652ce38980.tar.xz
dexon-0x-contracts-6007609f7132d5f919c8e9de04ae6c652ce38980.tar.zst
dexon-0x-contracts-6007609f7132d5f919c8e9de04ae6c652ce38980.zip
Look for relevant events in the decodedLogs and emit orderState events for orders impacted by the blockchain state changes
Diffstat (limited to 'src/mempool/order_state_watcher.ts')
-rw-r--r--src/mempool/order_state_watcher.ts89
1 files changed, 81 insertions, 8 deletions
diff --git a/src/mempool/order_state_watcher.ts b/src/mempool/order_state_watcher.ts
index 3da48005d..436f86554 100644
--- a/src/mempool/order_state_watcher.ts
+++ b/src/mempool/order_state_watcher.ts
@@ -3,6 +3,7 @@ import {schemas} from '0x-json-schemas';
import {ZeroEx} from '../';
import {EventWatcher} from './event_watcher';
import {assert} from '../utils/assert';
+import {utils} from '../utils/utils';
import {artifacts} from '../artifacts';
import {AbiDecoder} from '../utils/abi_decoder';
import {OrderStateUtils} from '../utils/order_state_utils';
@@ -14,11 +15,24 @@ import {
BlockParamLiteral,
LogWithDecodedArgs,
OnOrderStateChangeCallback,
+ ExchangeEvents,
+ TokenEvents,
} from '../types';
import {Web3Wrapper} from '../web3_wrapper';
+interface DependentOrderHashes {
+ [makerAddress: string]: {
+ [makerToken: string]: Set<string>,
+ };
+}
+
+interface OrderByOrderHash {
+ [orderHash: string]: SignedOrder;
+}
+
export class OrderStateWatcher {
- private _orders = new Map<string, SignedOrder>();
+ private _orders: OrderByOrderHash;
+ private _dependentOrderHashes: DependentOrderHashes;
private _web3Wrapper: Web3Wrapper;
private _callbackAsync?: OnOrderStateChangeCallback;
private _eventWatcher: EventWatcher;
@@ -28,6 +42,8 @@ export class OrderStateWatcher {
web3Wrapper: Web3Wrapper, abiDecoder: AbiDecoder, orderStateUtils: OrderStateUtils,
mempoolPollingIntervalMs?: number) {
this._web3Wrapper = web3Wrapper;
+ this._orders = {};
+ this._dependentOrderHashes = {};
this._eventWatcher = new EventWatcher(
this._web3Wrapper, mempoolPollingIntervalMs,
);
@@ -37,12 +53,18 @@ export class OrderStateWatcher {
public addOrder(signedOrder: SignedOrder): void {
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- this._orders.set(orderHash, signedOrder);
+ this._orders[orderHash] = signedOrder;
+ this.addToDependentOrderHashes(signedOrder, orderHash);
}
public removeOrder(signedOrder: SignedOrder): void {
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
+ if (_.isUndefined(this._dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress])) {
+ return; // noop if user tries to remove order that wasn't added
+ }
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
- this._orders.delete(orderHash);
+ delete this._orders[orderHash];
+ this._dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress].delete(orderHash);
+ // We currently do not remove the maker/makerToken keys from the mapping when all orderHashes removed
}
public subscribe(callback: OnOrderStateChangeCallback): void {
assert.isFunction('callback', callback);
@@ -55,17 +77,59 @@ export class OrderStateWatcher {
}
private async _onMempoolEventCallbackAsync(log: LogEvent): Promise<void> {
const maybeDecodedLog = this._abiDecoder.tryToDecodeLogOrNoop(log);
- if (!_.isUndefined((maybeDecodedLog as LogWithDecodedArgs<any>).event)) {
- await this._revalidateOrdersAsync();
+ const isDecodedLog = !_.isUndefined((maybeDecodedLog as LogWithDecodedArgs<any>).event);
+ if (!isDecodedLog) {
+ return; // noop
+ }
+ const decodedLog = maybeDecodedLog as LogWithDecodedArgs<any>;
+ let makerToken: string;
+ let makerAddress: string;
+ let orderHashesSet: Set<string>;
+ switch (decodedLog.event) {
+ case TokenEvents.Approval:
+ makerToken = decodedLog.address;
+ makerAddress = decodedLog.args._owner;
+ orderHashesSet = _.get(this._dependentOrderHashes, [makerAddress, makerToken]);
+ if (!_.isUndefined(orderHashesSet)) {
+ const orderHashes = Array.from(orderHashesSet);
+ await this._emitRevalidateOrdersAsync(orderHashes);
+ }
+ break;
+
+ case TokenEvents.Transfer:
+ makerToken = decodedLog.address;
+ makerAddress = decodedLog.args._from;
+ orderHashesSet = _.get(this._dependentOrderHashes, [makerAddress, makerToken]);
+ if (!_.isUndefined(orderHashesSet)) {
+ const orderHashes = Array.from(orderHashesSet);
+ await this._emitRevalidateOrdersAsync(orderHashes);
+ }
+ break;
+
+ case ExchangeEvents.LogFill:
+ case ExchangeEvents.LogCancel:
+ const orderHash = decodedLog.args.orderHash;
+ const isOrderWatched = !_.isUndefined(this._orders[orderHash]);
+ if (isOrderWatched) {
+ await this._emitRevalidateOrdersAsync([orderHash]);
+ }
+ break;
+
+ case ExchangeEvents.LogError:
+ return; // noop
+
+ default:
+ throw utils.spawnSwitchErr('decodedLog.event', decodedLog.event);
}
}
- private async _revalidateOrdersAsync(): Promise<void> {
+ private async _emitRevalidateOrdersAsync(orderHashes: string[]): Promise<void> {
+ // TODO: Make defaultBlock a passed in option
const methodOpts = {
defaultBlock: BlockParamLiteral.Pending,
};
- const orderHashes = Array.from(this._orders.keys());
+
for (const orderHash of orderHashes) {
- const signedOrder = this._orders.get(orderHash) as SignedOrder;
+ const signedOrder = this._orders[orderHash] as SignedOrder;
const orderState = await this._orderStateUtils.getOrderStateAsync(signedOrder, methodOpts);
if (!_.isUndefined(this._callbackAsync)) {
await this._callbackAsync(orderState);
@@ -74,4 +138,13 @@ export class OrderStateWatcher {
}
}
}
+ private addToDependentOrderHashes(signedOrder: SignedOrder, orderHash: string) {
+ if (_.isUndefined(this._dependentOrderHashes[signedOrder.maker])) {
+ this._dependentOrderHashes[signedOrder.maker] = {};
+ }
+ if (_.isUndefined(this._dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress])) {
+ this._dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress] = new Set();
+ }
+ this._dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress].add(orderHash);
+ }
}