Removed the order-watcher files that were accidentally added

This commit is contained in:
Jan-Gerrit Harms
2019-08-16 14:02:32 +02:00
parent aa3524c3b2
commit b2592d1cc2
3 changed files with 0 additions and 1157 deletions

View File

@@ -1,607 +0,0 @@
[
{
"version": "4.0.18",
"changes": [
{
"note": "Pass `signedOrder.exchangeAddress` to `signatureUtils.isValidSignatureAsync` when adding an order to watcher.",
"pr": 2017
}
]
},
{
"timestamp": 1565296576,
"version": "4.0.17",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1564604963,
"version": "4.0.16",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1563957393,
"version": "4.0.15",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1563193019,
"version": "4.0.14",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1563047529,
"version": "4.0.13",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1563006338,
"version": "4.0.12",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1558712885,
"version": "4.0.11",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1557961111,
"version": "4.0.10",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "4.0.9",
"changes": [
{
"note": "Dependencies updated"
}
],
"timestamp": 1557799313
},
{
"version": "4.0.7",
"changes": [
{
"note": "Fix race-condition bug due to async callback modifying shared state",
"pr": 1789
},
{
"note": "Fix bug where WETH deposit/withdrawal events would not trigger an order state update",
"pr": 1809
}
],
"timestamp": 1557507213
},
{
"version": "4.0.6",
"changes": [
{
"note": "Dependencies updated"
}
],
"timestamp": 1554997931
},
{
"timestamp": 1553183790,
"version": "4.0.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "4.0.4",
"changes": [
{
"note": "Update websocket from ^1.0.25 to ^1.0.26",
"pr": 1685
},
{
"note": "Fix issue where ERC721 Approval events could cause a lookup on undefined object",
"pr": 1692
},
{
"note": "Fix race-condition bugs due to async event callbacks modifying shared state",
"pr": 1718
},
{
"note": "Run Web3ProviderEngine without excess block polling",
"pr": 1695
}
],
"timestamp": 1553091633
},
{
"timestamp": 1551479279,
"version": "4.0.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1551299797,
"version": "4.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1551220833,
"version": "4.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "4.0.0",
"changes": [
{
"note": "Add support for EIP1193 providers & Web3.js providers >= 1.0-beta.38",
"pr": 1627
},
{
"note": "Update provider params to type SupportedProvider which outlines all supported providers",
"pr": 1627
}
],
"timestamp": 1551130135
},
{
"timestamp": 1549733923,
"version": "3.0.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "3.0.3",
"changes": [
{
"note": "Dependencies updated"
}
],
"timestamp": 1549547375
},
{
"timestamp": 1549504360,
"version": "3.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1549452781,
"version": "3.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "3.0.0",
"changes": [
{
"note": "Upgrade the bignumber.js to v8.0.2",
"pr": 1517
}
],
"timestamp": 1549373905
},
{
"timestamp": 1547747677,
"version": "2.4.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1547561734,
"version": "2.4.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1547225310,
"version": "2.4.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "2.4.0",
"changes": [
{
"note": "Add support for `MultiAssetProxy`",
"pr": 1363
}
],
"timestamp": 1547040760
},
{
"version": "2.3.0",
"changes": [
{
"note": "Added a WebSocket interface to OrderWatcher so that it can be used by a client written in any language",
"pr": 1427
}
]
},
{
"version": "2.2.8",
"changes": [
{
"note": "Dependencies updated"
}
],
"timestamp": 1544739608
},
{
"version": "2.2.7",
"changes": [
{
"note": "Dependencies updated"
}
],
"timestamp": 1544570656
},
{
"timestamp": 1543401373,
"version": "2.2.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1542821676,
"version": "2.2.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "2.2.4",
"changes": [
{
"note": "Fix the bug when order watcher was throwing an error on order removal when maker token was ZRX",
"pr": 1259
}
],
"timestamp": 1542208198
},
{
"version": "2.2.3",
"changes": [
{
"note": "Start jsonRpcRequestId at 1, not 0 as 0 breaks the web3.js websocket RPC provider",
"pr": 1227
},
{
"note": "Fix the bug when order watcher was trying to convert undefined to an object in case of CancelUpTo event"
}
],
"timestamp": 1542134075
},
{
"timestamp": 1542028948,
"version": "2.2.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "2.2.1",
"changes": [
{
"note": "Dependencies updated"
}
],
"timestamp": 1541740904
},
{
"version": "2.2.0",
"changes": [
{
"note": "Added getStats function and returns a Stats object",
"pr": 1118
},
{
"note": "Updated to use new modularized artifacts and the latest version of @0xproject/contract-wrappers. Constructor has a new optional `contractAddresses` parameter.",
"pr": 1105
}
],
"timestamp": 1539871071
},
{
"version": "2.1.1",
"changes": [
{
"note": "Dependencies updated"
}
],
"timestamp": 1538693146
},
{
"version": "2.1.0",
"changes": [
{
"note": "Export ExpirationWatcher",
"pr": 1097
}
],
"timestamp": 1538157789
},
{
"version": "2.0.0",
"changes": [
{
"note": "Fixes dropped events issue by fetching logs by blockHash instead of blockNumber. Support for fetching by blockHash was added in Geth > v1.8.13 and Parity > v2.1.0. Infura works too.",
"pr": 1080
},
{
"note": "Fix misunderstanding about blockstream interface callbacks and pass the raw JSON RPC responses to it",
"pr": 1080
},
{
"note": "Add `transactionHash` to `OrderState` emitted by `OrderWatcher` subscriptions if the order's state change originated from a transaction.",
"pr": 1087
}
],
"timestamp": 1537907159
},
{
"version": "1.0.5",
"changes": [
{
"note": "Dependencies updated"
}
],
"timestamp": 1537875740
},
{
"version": "1.0.4",
"changes": [
{
"note": "Dependencies updated"
}
],
"timestamp": 1537541580
},
{
"version": "1.0.3",
"changes": [
{
"note": "Drastically reduce the bundle size by removing unused parts of included contract artifacts."
}
],
"timestamp": 1537369748
},
{
"version": "1.0.2",
"changes": [
{
"note": "Add ZRX & WETH mainnet contract addresses into the included artifacts"
}
],
"timestamp": 1537265493
},
{
"timestamp": 1536142250,
"version": "1.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.0.1-rc.5",
"changes": [
{
"note": "Fix missing `BlockParamLiteral` type import issue"
}
],
"timestamp": 1535377027
},
{
"version": "1.0.1-rc.4",
"changes": [
{
"note": "Export types: `ExchangeContractErrs`, `OrderRelevantState`, `JSONRPCRequestPayload`, `JSONRPCErrorCallback` and `JSONRPCResponsePayload`",
"pr": 924
},
{
"note": "Remove exporting types: `BlockParamLiteral`, `BlockParam`, `Order`",
"pr": 924
}
],
"timestamp": 1535133899
},
{
"version": "1.0.1-rc.3",
"changes": [
{
"note": "Dependencies updated"
}
],
"timestamp": 1534210131
},
{
"version": "1.0.1-rc.2",
"changes": [
{
"note": "Fixed bug caused by importing non-existent dep"
}
],
"timestamp": 1532619515
},
{
"version": "1.0.1-rc.1",
"changes": [
{
"note": "Dependencies updated"
}
],
"timestamp": 1532605697
},
{
"timestamp": 1532357734,
"version": "1.0.0",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1532043000,
"version": "1.0.0-rc.1",
"changes": [
{
"note": "Add support for ERC721 event watching and Exchange V2 events",
"pr": 887
}
]
},
{
"timestamp": 1531919263,
"version": "0.0.8",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "0.0.7",
"changes": [
{
"note": "Switch out simple getLogs polling with ethereumjs-blockstream",
"pr": 825
},
{
"note": "Do not stop subscription if error is encountered",
"pr": 825
},
{
"note": "Fixed a bug that caused the incorrect block to be fetched via JSON-RPC within Blockstream",
"pr": 875
},
{
"note": "Remove stateLayer config from OrderWatcher. It now always operates on the latest block",
"pr": 875
}
],
"timestamp": 1531149657
},
{
"timestamp": 1529397769,
"version": "0.0.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1527617805,
"version": "0.0.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1527617227,
"version": "0.0.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1527616612,
"version": "0.0.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1527008794,
"version": "0.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1527008794,
"version": "0.0.1",
"changes": [
{
"note": "Moved OrderWatcher out of 0x.js package",
"pr": 579
}
]
}
]

View File

@@ -1,520 +0,0 @@
// tslint:disable:no-unnecessary-type-assertion
import { ContractAddresses } from '@0x/contract-addresses';
import * as artifacts from '@0x/contract-artifacts';
import {
AssetBalanceAndProxyAllowanceFetcher,
ContractWrappers,
ERC20TokenApprovalEventArgs,
ERC20TokenEventArgs,
ERC20TokenEvents,
ERC20TokenTransferEventArgs,
ERC721TokenApprovalEventArgs,
ERC721TokenApprovalForAllEventArgs,
ERC721TokenEventArgs,
ERC721TokenEvents,
ERC721TokenTransferEventArgs,
ExchangeCancelEventArgs,
ExchangeCancelUpToEventArgs,
ExchangeEventArgs,
ExchangeEvents,
ExchangeFillEventArgs,
OrderFilledCancelledFetcher,
WETH9DepositEventArgs,
WETH9EventArgs,
WETH9Events,
WETH9WithdrawalEventArgs,
} from '@0x/contract-wrappers';
import { schemas } from '@0x/json-schemas';
import {
assetDataUtils,
BalanceAndProxyAllowanceLazyStore,
OrderFilledCancelledLazyStore,
orderHashUtils,
OrderStateUtils,
} from '@0x/order-utils';
import { AssetProxyId, ExchangeContractErrs, OrderState, SignedOrder, Stats } from '@0x/types';
import { errorUtils, intervalUtils, providerUtils } from '@0x/utils';
import {
BlockParamLiteral,
LogEntryEvent,
LogWithDecodedArgs,
SupportedProvider,
ZeroExProvider,
} from 'ethereum-types';
import * as _ from 'lodash';
import { Lock } from 'semaphore-async-await';
import { orderWatcherPartialConfigSchema } from '../schemas/order_watcher_partial_config_schema';
import { OnOrderStateChangeCallback, OrderWatcherConfig, OrderWatcherError } from '../types';
import { assert } from '../utils/assert';
import { CollisionResistanceAbiDecoder } from './collision_resistant_abi_decoder';
import { DependentOrderHashesTracker } from './dependent_order_hashes_tracker';
import { EventWatcher } from './event_watcher';
import { ExpirationWatcher } from './expiration_watcher';
const MILLISECONDS_IN_A_SECOND = 1000;
type ContractEventArgs = WETH9EventArgs | ExchangeEventArgs | ERC20TokenEventArgs | ERC721TokenEventArgs;
interface OrderByOrderHash {
[orderHash: string]: SignedOrder;
}
interface OrderStateByOrderHash {
[orderHash: string]: OrderState;
}
const DEFAULT_ORDER_WATCHER_CONFIG: OrderWatcherConfig = {
orderExpirationCheckingIntervalMs: 50,
eventPollingIntervalMs: 200,
expirationMarginMs: 0,
// tslint:disable-next-line:custom-no-magic-numbers
cleanupJobIntervalMs: 1000 * 60 * 60, // 1h
isVerbose: true,
};
const STATE_LAYER = BlockParamLiteral.Latest;
/**
* This class includes all the functionality related to watching a set of orders
* for potential changes in order validity/fillability. The orderWatcher notifies
* the subscriber of these changes so that a final decision can be made on whether
* the order should be deemed invalid.
*/
export class OrderWatcher {
private readonly _dependentOrderHashesTracker: DependentOrderHashesTracker;
private readonly _orderStateByOrderHashCache: OrderStateByOrderHash = {};
private readonly _orderByOrderHash: OrderByOrderHash = {};
private readonly _lock = new Lock();
private readonly _eventWatcher: EventWatcher;
private readonly _provider: ZeroExProvider;
private readonly _collisionResistantAbiDecoder: CollisionResistanceAbiDecoder;
private readonly _expirationWatcher: ExpirationWatcher;
private readonly _orderStateUtils: OrderStateUtils;
private readonly _orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore;
private readonly _balanceAndProxyAllowanceLazyStore: BalanceAndProxyAllowanceLazyStore;
private readonly _cleanupJobInterval: number;
private _cleanupJobIntervalIdIfExists?: NodeJS.Timer;
private _callbackIfExists?: OnOrderStateChangeCallback;
/**
* Instantiate a new OrderWatcher
* @param supportedProvider Web3 provider to use for JSON RPC calls
* @param networkId NetworkId to watch orders on
* @param contractAddresses Optional contract addresses. Defaults to known
* addresses based on networkId.
* @param partialConfig Optional configurations
*/
constructor(
supportedProvider: SupportedProvider,
networkId: number,
contractAddresses?: ContractAddresses,
partialConfig: Partial<OrderWatcherConfig> = DEFAULT_ORDER_WATCHER_CONFIG,
) {
const provider = providerUtils.standardizeOrThrow(supportedProvider);
assert.isNumber('networkId', networkId);
assert.doesConformToSchema('partialConfig', partialConfig, orderWatcherPartialConfigSchema);
const config = {
...DEFAULT_ORDER_WATCHER_CONFIG,
...partialConfig,
};
this._provider = provider;
this._collisionResistantAbiDecoder = new CollisionResistanceAbiDecoder(
artifacts.ERC20Token.compilerOutput.abi,
artifacts.ERC721Token.compilerOutput.abi,
[artifacts.WETH9.compilerOutput.abi, artifacts.Exchange.compilerOutput.abi],
);
const contractWrappers = new ContractWrappers(provider, {
networkId,
// Note(albrow): We let the contract-wrappers package handle
// default values for contractAddresses.
contractAddresses,
});
this._eventWatcher = new EventWatcher(provider, config.eventPollingIntervalMs, config.isVerbose);
const balanceAndProxyAllowanceFetcher = new AssetBalanceAndProxyAllowanceFetcher(
contractWrappers.erc20Token,
contractWrappers.erc721Token,
STATE_LAYER,
);
this._balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore(
balanceAndProxyAllowanceFetcher,
);
const orderFilledCancelledFetcher = new OrderFilledCancelledFetcher(contractWrappers.exchange, STATE_LAYER);
this._orderFilledCancelledLazyStore = new OrderFilledCancelledLazyStore(orderFilledCancelledFetcher);
this._orderStateUtils = new OrderStateUtils(balanceAndProxyAllowanceFetcher, orderFilledCancelledFetcher);
const expirationMarginIfExistsMs = config === undefined ? undefined : config.expirationMarginMs;
this._expirationWatcher = new ExpirationWatcher(
expirationMarginIfExistsMs,
config.orderExpirationCheckingIntervalMs,
);
this._cleanupJobInterval = config.cleanupJobIntervalMs;
const zrxTokenAddress = assetDataUtils.decodeERC20AssetData(orderFilledCancelledFetcher.getZRXAssetData())
.tokenAddress;
this._dependentOrderHashesTracker = new DependentOrderHashesTracker(zrxTokenAddress);
}
/**
* Add an order to the orderWatcher. Before the order is added, it's
* signature is verified.
* @param signedOrder The order you wish to start watching.
*/
public async addOrderAsync(signedOrder: SignedOrder): Promise<void> {
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
await assert.isValidSignatureAsync(
this._provider,
orderHash,
signedOrder.signature,
signedOrder.makerAddress,
signedOrder.exchangeAddress,
);
const expirationUnixTimestampMs = signedOrder.expirationTimeSeconds.times(MILLISECONDS_IN_A_SECOND);
this._expirationWatcher.addOrder(orderHash, expirationUnixTimestampMs);
this._orderByOrderHash[orderHash] = signedOrder;
this._dependentOrderHashesTracker.addToDependentOrderHashes(signedOrder);
const orderAssetDatas = [signedOrder.makerAssetData, signedOrder.takerAssetData];
_.each(orderAssetDatas, assetData => this._addAssetDataToAbiDecoder(assetData));
}
/**
* Removes an order from the orderWatcher
* @param orderHash The orderHash of the order you wish to stop watching.
*/
public removeOrder(orderHash: string): void {
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
const signedOrder = this._orderByOrderHash[orderHash];
if (signedOrder === undefined) {
return; // noop
}
this._dependentOrderHashesTracker.removeFromDependentOrderHashes(signedOrder);
delete this._orderByOrderHash[orderHash];
this._expirationWatcher.removeOrder(orderHash);
delete this._orderStateByOrderHashCache[orderHash];
}
/**
* Starts an orderWatcher subscription. The callback will be called every time a watched order's
* backing blockchain state has changed. This is a call-to-action for the caller to re-validate the order.
* @param callback Receives the orderHash of the order that should be re-validated, together
* with all the order-relevant blockchain state needed to re-validate the order.
*/
public subscribe(callback: OnOrderStateChangeCallback): void {
assert.isFunction('callback', callback);
if (this._callbackIfExists !== undefined) {
throw new Error(OrderWatcherError.SubscriptionAlreadyPresent);
}
this._callbackIfExists = callback;
this._eventWatcher.subscribe(
this._addLockToCallbackAsync.bind(this, this._onEventWatcherCallbackAsync.bind(this)),
);
this._expirationWatcher.subscribe(this._addLockToCallbackAsync.bind(this, this._onOrderExpired.bind(this)));
this._cleanupJobIntervalIdIfExists = intervalUtils.setAsyncExcludingInterval(
this._addLockToCallbackAsync.bind(this, this._cleanupAsync.bind(this)),
this._cleanupJobInterval,
(err: Error) => {
this.unsubscribe();
callback(err);
},
);
}
/**
* Ends an orderWatcher subscription.
*/
public unsubscribe(): void {
if (this._callbackIfExists === undefined || this._cleanupJobIntervalIdIfExists === undefined) {
throw new Error(OrderWatcherError.SubscriptionNotFound);
}
this._balanceAndProxyAllowanceLazyStore.deleteAll();
this._orderFilledCancelledLazyStore.deleteAll();
delete this._callbackIfExists;
this._eventWatcher.unsubscribe();
this._expirationWatcher.unsubscribe();
intervalUtils.clearAsyncExcludingInterval(this._cleanupJobIntervalIdIfExists);
}
/**
* Gets statistics of the OrderWatcher Instance.
*/
public getStats(): Stats {
return {
orderCount: _.size(this._orderByOrderHash),
};
}
private async _addLockToCallbackAsync(cbAsync: any, ...params: any[]): Promise<void> {
await this._lock.acquire();
try {
await cbAsync(...params);
await this._lock.release();
} catch (err) {
// Make sure to releasee the lock if an error is thrown
await this._lock.release();
throw err;
}
}
private async _cleanupAsync(): Promise<void> {
for (const orderHash of _.keys(this._orderByOrderHash)) {
this._cleanupOrderRelatedState(orderHash);
await this._emitRevalidateOrdersAsync([orderHash]);
}
}
private _addAssetDataToAbiDecoder(assetData: string): void {
const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
if (assetDataUtils.isERC20AssetData(decodedAssetData)) {
this._collisionResistantAbiDecoder.addERC20Token(decodedAssetData.tokenAddress);
} else if (assetDataUtils.isERC721AssetData(decodedAssetData)) {
this._collisionResistantAbiDecoder.addERC721Token(decodedAssetData.tokenAddress);
} else if (assetDataUtils.isMultiAssetData(decodedAssetData)) {
_.each(decodedAssetData.nestedAssetData, nestedAssetDataElement =>
this._addAssetDataToAbiDecoder(nestedAssetDataElement),
);
}
}
private _deleteLazyStoreBalance(assetData: string, userAddress: string): void {
const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData);
switch (assetProxyId) {
case AssetProxyId.ERC20:
case AssetProxyId.ERC721:
this._balanceAndProxyAllowanceLazyStore.deleteBalance(assetData, userAddress);
break;
case AssetProxyId.MultiAsset:
const decodedAssetData = assetDataUtils.decodeMultiAssetData(assetData);
_.each(decodedAssetData.nestedAssetData, nestedAssetDataElement =>
this._deleteLazyStoreBalance(nestedAssetDataElement, userAddress),
);
break;
default:
break;
}
}
private _deleteLazyStoreProxyAllowance(assetData: string, userAddress: string): void {
const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData);
switch (assetProxyId) {
case AssetProxyId.ERC20:
case AssetProxyId.ERC721:
this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(assetData, userAddress);
break;
case AssetProxyId.MultiAsset:
const decodedAssetData = assetDataUtils.decodeMultiAssetData(assetData);
_.each(decodedAssetData.nestedAssetData, nestedAssetDataElement =>
this._deleteLazyStoreProxyAllowance(nestedAssetDataElement, userAddress),
);
break;
default:
break;
}
}
private _cleanupOrderRelatedState(orderHash: string): void {
const signedOrder = this._orderByOrderHash[orderHash];
this._orderFilledCancelledLazyStore.deleteFilledTakerAmount(orderHash);
this._orderFilledCancelledLazyStore.deleteIsCancelled(orderHash);
this._deleteLazyStoreBalance(signedOrder.makerAssetData, signedOrder.makerAddress);
this._deleteLazyStoreProxyAllowance(signedOrder.makerAssetData, signedOrder.makerAddress);
this._deleteLazyStoreBalance(signedOrder.takerAssetData, signedOrder.takerAddress);
this._deleteLazyStoreProxyAllowance(signedOrder.takerAssetData, signedOrder.takerAddress);
const zrxAssetData = this._orderFilledCancelledLazyStore.getZRXAssetData();
if (!signedOrder.makerFee.isZero()) {
this._deleteLazyStoreBalance(zrxAssetData, signedOrder.makerAddress);
this._deleteLazyStoreProxyAllowance(zrxAssetData, signedOrder.makerAddress);
}
if (!signedOrder.takerFee.isZero()) {
this._deleteLazyStoreBalance(zrxAssetData, signedOrder.takerAddress);
this._deleteLazyStoreProxyAllowance(zrxAssetData, signedOrder.takerAddress);
}
}
private _onOrderExpired(orderHash: string): void {
const orderState: OrderState = {
isValid: false,
orderHash,
error: ExchangeContractErrs.OrderFillExpired,
};
if (this._orderByOrderHash[orderHash] !== undefined) {
this.removeOrder(orderHash);
if (this._callbackIfExists !== undefined) {
this._callbackIfExists(null, orderState);
}
}
}
private async _onEventWatcherCallbackAsync(err: Error | null, logIfExists?: LogEntryEvent): Promise<void> {
if (err !== null) {
if (this._callbackIfExists !== undefined) {
this._callbackIfExists(err);
}
return;
}
const maybeDecodedLog = this._collisionResistantAbiDecoder.tryToDecodeLogOrNoop<ContractEventArgs>(
// At this moment we are sure that no error occured and log is defined.
logIfExists as LogEntryEvent,
);
const isLogDecoded = ((maybeDecodedLog as any) as LogWithDecodedArgs<ContractEventArgs>).event !== undefined;
if (!isLogDecoded) {
return; // noop
}
const decodedLog = (maybeDecodedLog as any) as LogWithDecodedArgs<ContractEventArgs>;
const transactionHash = decodedLog.transactionHash;
switch (decodedLog.event) {
case ERC20TokenEvents.Approval:
case ERC721TokenEvents.Approval: {
// ERC20 and ERC721 Transfer events have the same name so we need to distinguish them by args
if (decodedLog.args._value !== undefined) {
// ERC20
// Invalidate cache
const args = decodedLog.args as ERC20TokenApprovalEventArgs;
const tokenAssetData = assetDataUtils.encodeERC20AssetData(decodedLog.address);
this._deleteLazyStoreProxyAllowance(tokenAssetData, args._owner);
// Revalidate orders
const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker(
args._owner,
tokenAssetData,
);
await this._emitRevalidateOrdersAsync(orderHashes, transactionHash);
break;
} else {
// ERC721
// Invalidate cache
const args = decodedLog.args as ERC721TokenApprovalEventArgs;
const tokenAssetData = assetDataUtils.encodeERC721AssetData(decodedLog.address, args._tokenId);
this._deleteLazyStoreProxyAllowance(tokenAssetData, args._owner);
// Revalidate orders
const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker(
args._owner,
tokenAssetData,
);
await this._emitRevalidateOrdersAsync(orderHashes, transactionHash);
break;
}
}
case ERC20TokenEvents.Transfer:
case ERC721TokenEvents.Transfer: {
// ERC20 and ERC721 Transfer events have the same name so we need to distinguish them by args
if (decodedLog.args._value !== undefined) {
// ERC20
// Invalidate cache
const args = decodedLog.args as ERC20TokenTransferEventArgs;
const tokenAssetData = assetDataUtils.encodeERC20AssetData(decodedLog.address);
this._deleteLazyStoreBalance(tokenAssetData, args._from);
this._deleteLazyStoreBalance(tokenAssetData, args._to);
// Revalidate orders
const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker(
args._from,
tokenAssetData,
);
await this._emitRevalidateOrdersAsync(orderHashes, transactionHash);
break;
} else {
// ERC721
// Invalidate cache
const args = decodedLog.args as ERC721TokenTransferEventArgs;
const tokenAssetData = assetDataUtils.encodeERC721AssetData(decodedLog.address, args._tokenId);
this._deleteLazyStoreBalance(tokenAssetData, args._from);
this._deleteLazyStoreBalance(tokenAssetData, args._to);
// Revalidate orders
const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker(
args._from,
tokenAssetData,
);
await this._emitRevalidateOrdersAsync(orderHashes, transactionHash);
break;
}
}
case ERC721TokenEvents.ApprovalForAll: {
// Invalidate cache
const args = decodedLog.args as ERC721TokenApprovalForAllEventArgs;
const tokenAddress = decodedLog.address;
this._balanceAndProxyAllowanceLazyStore.deleteAllERC721ProxyAllowance(tokenAddress, args._owner);
// Revalidate orders
const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByERC721ByMaker(
args._owner,
tokenAddress,
);
await this._emitRevalidateOrdersAsync(orderHashes, transactionHash);
break;
}
case WETH9Events.Deposit: {
// Invalidate cache
const args = decodedLog.args as WETH9DepositEventArgs;
const tokenAssetData = assetDataUtils.encodeERC20AssetData(decodedLog.address);
this._deleteLazyStoreBalance(tokenAssetData, args._owner);
// Revalidate orders
const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker(
args._owner,
tokenAssetData,
);
await this._emitRevalidateOrdersAsync(orderHashes, transactionHash);
break;
}
case WETH9Events.Withdrawal: {
// Invalidate cache
const args = decodedLog.args as WETH9WithdrawalEventArgs;
const tokenAssetData = assetDataUtils.encodeERC20AssetData(decodedLog.address);
this._deleteLazyStoreBalance(tokenAssetData, args._owner);
// Revalidate orders
const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker(
args._owner,
tokenAssetData,
);
await this._emitRevalidateOrdersAsync(orderHashes, transactionHash);
break;
}
case ExchangeEvents.Fill: {
// Invalidate cache
const args = decodedLog.args as ExchangeFillEventArgs;
this._orderFilledCancelledLazyStore.deleteFilledTakerAmount(args.orderHash);
// Revalidate orders
const orderHash = args.orderHash;
const isOrderWatched = this._orderByOrderHash[orderHash] !== undefined;
if (isOrderWatched) {
await this._emitRevalidateOrdersAsync([orderHash], transactionHash);
}
break;
}
case ExchangeEvents.Cancel: {
// Invalidate cache
const args = decodedLog.args as ExchangeCancelEventArgs;
this._orderFilledCancelledLazyStore.deleteIsCancelled(args.orderHash);
// Revalidate orders
const orderHash = args.orderHash;
const isOrderWatched = this._orderByOrderHash[orderHash] !== undefined;
if (isOrderWatched) {
await this._emitRevalidateOrdersAsync([orderHash], transactionHash);
}
break;
}
case ExchangeEvents.CancelUpTo: {
// TODO(logvinov): Do it smarter and actually look at the salt and order epoch
// Invalidate cache
const args = decodedLog.args as ExchangeCancelUpToEventArgs;
this._orderFilledCancelledLazyStore.deleteAllIsCancelled();
// Revalidate orders
const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByMaker(args.makerAddress);
await this._emitRevalidateOrdersAsync(orderHashes, transactionHash);
break;
}
default:
throw errorUtils.spawnSwitchErr('decodedLog.event', decodedLog.event);
}
}
private async _emitRevalidateOrdersAsync(orderHashes: string[], transactionHash?: string): Promise<void> {
for (const orderHash of orderHashes) {
const signedOrder = this._orderByOrderHash[orderHash];
if (signedOrder === undefined) {
continue;
}
// Most of these calls will never reach the network because the data is fetched from stores
// and only updated when cache is invalidated
const orderState = await this._orderStateUtils.getOpenOrderStateAsync(signedOrder, transactionHash);
if (this._callbackIfExists === undefined) {
break; // Unsubscribe was called
}
if (_.isEqual(orderState, this._orderStateByOrderHashCache[orderHash])) {
// Actual order state didn't change
continue;
} else {
this._orderStateByOrderHashCache[orderHash] = orderState;
}
this._callbackIfExists(null, orderState);
}
}
} // tslint:disable:max-file-line-count

View File

@@ -1,30 +0,0 @@
import { assert as sharedAssert } from '@0x/assert';
// HACK: We need those two unused imports because they're actually used by sharedAssert which gets injected here
// tslint:disable:no-unused-variable
import { Schema } from '@0x/json-schemas';
import { ECSignature } from '@0x/types';
import { BigNumber } from '@0x/utils';
// tslint:enable:no-unused-variable
import { SupportedProvider } from 'ethereum-types';
import { signatureUtils } from '@0x/order-utils';
export const assert = {
...sharedAssert,
async isValidSignatureAsync(
supportedProvider: SupportedProvider,
orderHash: string,
signature: string,
signerAddress: string,
exchangeAddress?: string,
): Promise<void> {
const isValid = await signatureUtils.isValidSignatureAsync(
supportedProvider,
orderHash,
signature,
signerAddress,
exchangeAddress,
);
assert.assert(isValid, `Expected order with hash '${orderHash}' to have a valid signature`);
},
};