aboutsummaryrefslogtreecommitdiffstats
path: root/packages/order-watcher/src
diff options
context:
space:
mode:
authorLeonid Logvinov <logvinov.leon@gmail.com>2018-07-18 22:38:16 +0800
committerGitHub <noreply@github.com>2018-07-18 22:38:16 +0800
commit00d1622b3f087943e750f1b3f6ee6ceab7e80285 (patch)
tree44789fff181ec24846728d885ba541c23f682321 /packages/order-watcher/src
parente2fb49a8f871fd4b631bb01bb641c632b7c19435 (diff)
parenta1acf19ff3c1948214dde05a91eb3fbeac728d2c (diff)
downloaddexon-sol-tools-00d1622b3f087943e750f1b3f6ee6ceab7e80285.tar.gz
dexon-sol-tools-00d1622b3f087943e750f1b3f6ee6ceab7e80285.tar.zst
dexon-sol-tools-00d1622b3f087943e750f1b3f6ee6ceab7e80285.zip
Merge pull request #887 from 0xProject/feature/order-watcher-v2
Order watcher v2
Diffstat (limited to 'packages/order-watcher/src')
-rw-r--r--packages/order-watcher/src/artifacts.ts19
-rw-r--r--packages/order-watcher/src/compact_artifacts/DummyToken.json22
-rw-r--r--packages/order-watcher/src/compact_artifacts/ERC20Token.json49
-rw-r--r--packages/order-watcher/src/compact_artifacts/ERC721Token.json71
-rw-r--r--packages/order-watcher/src/compact_artifacts/EtherToken.json287
-rw-r--r--packages/order-watcher/src/compact_artifacts/Exchange.json543
-rw-r--r--packages/order-watcher/src/compact_artifacts/Token.json172
-rw-r--r--packages/order-watcher/src/compact_artifacts/TokenRegistry.json547
-rw-r--r--packages/order-watcher/src/compact_artifacts/TokenTransferProxy.json187
-rw-r--r--packages/order-watcher/src/compact_artifacts/WETH9.json100
-rw-r--r--packages/order-watcher/src/compact_artifacts/ZRX.json20
-rw-r--r--packages/order-watcher/src/fetchers/asset_balance_and_proxy_allowance_fetcher.ts74
-rw-r--r--packages/order-watcher/src/fetchers/order_filled_cancelled_fetcher.ts27
-rw-r--r--packages/order-watcher/src/index.ts3
-rw-r--r--packages/order-watcher/src/order_watcher/collision_resistant_abi_decoder.ts54
-rw-r--r--packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts230
-rw-r--r--packages/order-watcher/src/order_watcher/event_watcher.ts10
-rw-r--r--packages/order-watcher/src/order_watcher/expiration_watcher.ts4
-rw-r--r--packages/order-watcher/src/order_watcher/order_watcher.ts412
-rw-r--r--packages/order-watcher/src/schemas/order_watcher_partial_config_schema.ts13
-rw-r--r--packages/order-watcher/src/types.ts14
-rw-r--r--packages/order-watcher/src/utils/assert.ts12
22 files changed, 912 insertions, 1958 deletions
diff --git a/packages/order-watcher/src/artifacts.ts b/packages/order-watcher/src/artifacts.ts
index 13587984c..4732fb2b5 100644
--- a/packages/order-watcher/src/artifacts.ts
+++ b/packages/order-watcher/src/artifacts.ts
@@ -1,18 +1,13 @@
import { Artifact } from '@0xproject/types';
-import * as DummyToken from './compact_artifacts/DummyToken.json';
-import * as EtherToken from './compact_artifacts/EtherToken.json';
+import * as ERC20Token from './compact_artifacts/ERC20Token.json';
+import * as ERC721Token from './compact_artifacts/ERC721Token.json';
import * as Exchange from './compact_artifacts/Exchange.json';
-import * as Token from './compact_artifacts/Token.json';
-import * as TokenRegistry from './compact_artifacts/TokenRegistry.json';
-import * as TokenTransferProxy from './compact_artifacts/TokenTransferProxy.json';
-import * as ZRX from './compact_artifacts/ZRX.json';
+import * as WETH9 from './compact_artifacts/WETH9.json';
+
export const artifacts = {
- ZRX: (ZRX as any) as Artifact,
- DummyToken: (DummyToken as any) as Artifact,
- Token: (Token as any) as Artifact,
+ ERC20Token: (ERC20Token as any) as Artifact,
+ ERC721Token: (ERC721Token as any) as Artifact,
Exchange: (Exchange as any) as Artifact,
- EtherToken: (EtherToken as any) as Artifact,
- TokenRegistry: (TokenRegistry as any) as Artifact,
- TokenTransferProxy: (TokenTransferProxy as any) as Artifact,
+ EtherToken: (WETH9 as any) as Artifact,
};
diff --git a/packages/order-watcher/src/compact_artifacts/DummyToken.json b/packages/order-watcher/src/compact_artifacts/DummyToken.json
deleted file mode 100644
index f64a8cd3d..000000000
--- a/packages/order-watcher/src/compact_artifacts/DummyToken.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "contract_name": "DummyToken",
- "abi": [
- {
- "constant": false,
- "inputs": [
- {
- "name": "_target",
- "type": "address"
- },
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "setBalance",
- "outputs": [],
- "payable": false,
- "type": "function"
- }
- ]
-}
diff --git a/packages/order-watcher/src/compact_artifacts/ERC20Token.json b/packages/order-watcher/src/compact_artifacts/ERC20Token.json
new file mode 100644
index 000000000..8d60fa324
--- /dev/null
+++ b/packages/order-watcher/src/compact_artifacts/ERC20Token.json
@@ -0,0 +1,49 @@
+{
+ "contract_name": "ERC20Token",
+ "abi": [
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "_from",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "_to",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Transfer",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "_owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "_spender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Approval",
+ "type": "event"
+ }
+ ]
+}
diff --git a/packages/order-watcher/src/compact_artifacts/ERC721Token.json b/packages/order-watcher/src/compact_artifacts/ERC721Token.json
new file mode 100644
index 000000000..5934376d3
--- /dev/null
+++ b/packages/order-watcher/src/compact_artifacts/ERC721Token.json
@@ -0,0 +1,71 @@
+{
+ "contract_name": "ERC721Token",
+ "abi": [
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "_from",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "_to",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "_tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "Transfer",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "_owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "_approved",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "_tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "Approval",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "_owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "_operator",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "_approved",
+ "type": "bool"
+ }
+ ],
+ "name": "ApprovalForAll",
+ "type": "event"
+ }
+ ]
+}
diff --git a/packages/order-watcher/src/compact_artifacts/EtherToken.json b/packages/order-watcher/src/compact_artifacts/EtherToken.json
deleted file mode 100644
index 26cca57cd..000000000
--- a/packages/order-watcher/src/compact_artifacts/EtherToken.json
+++ /dev/null
@@ -1,287 +0,0 @@
-{
- "contract_name": "EtherToken",
- "abi": [
- {
- "constant": true,
- "inputs": [],
- "name": "name",
- "outputs": [
- {
- "name": "",
- "type": "string"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_spender",
- "type": "address"
- },
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "approve",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "totalSupply",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_from",
- "type": "address"
- },
- {
- "name": "_to",
- "type": "address"
- },
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "transferFrom",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "amount",
- "type": "uint256"
- }
- ],
- "name": "withdraw",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "decimals",
- "outputs": [
- {
- "name": "",
- "type": "uint8"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_owner",
- "type": "address"
- }
- ],
- "name": "balanceOf",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "symbol",
- "outputs": [
- {
- "name": "",
- "type": "string"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_to",
- "type": "address"
- },
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "transfer",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [],
- "name": "deposit",
- "outputs": [],
- "payable": true,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_owner",
- "type": "address"
- },
- {
- "name": "_spender",
- "type": "address"
- }
- ],
- "name": "allowance",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "payable": true,
- "type": "fallback"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "_from",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "_to",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "Transfer",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "_owner",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "_spender",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "Approval",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "_owner",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "Deposit",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "_owner",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "Withdrawal",
- "type": "event"
- }
- ],
- "networks": {
- "1": {
- "address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
- },
- "3": {
- "address": "0xc00fd9820cd2898cc4c054b7bf142de637ad129a"
- },
- "4": {
- "address": "0xc778417e063141139fce010982780140aa0cd5ab"
- },
- "42": {
- "address": "0x653e49e301e508a13237c0ddc98ae7d4cd2667a1"
- },
- "50": {
- "address": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c"
- }
- }
-}
diff --git a/packages/order-watcher/src/compact_artifacts/Exchange.json b/packages/order-watcher/src/compact_artifacts/Exchange.json
index af8db7360..4e319f7cf 100644
--- a/packages/order-watcher/src/compact_artifacts/Exchange.json
+++ b/packages/order-watcher/src/compact_artifacts/Exchange.json
@@ -2,527 +2,65 @@
"contract_name": "Exchange",
"abi": [
{
- "constant": true,
- "inputs": [
- {
- "name": "numerator",
- "type": "uint256"
- },
- {
- "name": "denominator",
- "type": "uint256"
- },
- {
- "name": "target",
- "type": "uint256"
- }
- ],
- "name": "isRoundingError",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "",
- "type": "bytes32"
- }
- ],
- "name": "filled",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "",
- "type": "bytes32"
- }
- ],
- "name": "cancelled",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "orderAddresses",
- "type": "address[5][]"
- },
- {
- "name": "orderValues",
- "type": "uint256[6][]"
- },
- {
- "name": "fillTakerTokenAmount",
- "type": "uint256"
- },
- {
- "name": "shouldThrowOnInsufficientBalanceOrAllowance",
- "type": "bool"
- },
- {
- "name": "v",
- "type": "uint8[]"
- },
- {
- "name": "r",
- "type": "bytes32[]"
- },
- {
- "name": "s",
- "type": "bytes32[]"
- }
- ],
- "name": "fillOrdersUpTo",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "orderAddresses",
- "type": "address[5]"
- },
- {
- "name": "orderValues",
- "type": "uint256[6]"
- },
- {
- "name": "cancelTakerTokenAmount",
- "type": "uint256"
- }
- ],
- "name": "cancelOrder",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "ZRX_TOKEN_CONTRACT",
- "outputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "orderAddresses",
- "type": "address[5][]"
- },
- {
- "name": "orderValues",
- "type": "uint256[6][]"
- },
- {
- "name": "fillTakerTokenAmounts",
- "type": "uint256[]"
- },
- {
- "name": "v",
- "type": "uint8[]"
- },
- {
- "name": "r",
- "type": "bytes32[]"
- },
- {
- "name": "s",
- "type": "bytes32[]"
- }
- ],
- "name": "batchFillOrKillOrders",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "orderAddresses",
- "type": "address[5]"
- },
- {
- "name": "orderValues",
- "type": "uint256[6]"
- },
- {
- "name": "fillTakerTokenAmount",
- "type": "uint256"
- },
- {
- "name": "v",
- "type": "uint8"
- },
- {
- "name": "r",
- "type": "bytes32"
- },
- {
- "name": "s",
- "type": "bytes32"
- }
- ],
- "name": "fillOrKillOrder",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "orderHash",
- "type": "bytes32"
- }
- ],
- "name": "getUnavailableTakerTokenAmount",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "signer",
- "type": "address"
- },
- {
- "name": "hash",
- "type": "bytes32"
- },
- {
- "name": "v",
- "type": "uint8"
- },
- {
- "name": "r",
- "type": "bytes32"
- },
- {
- "name": "s",
- "type": "bytes32"
- }
- ],
- "name": "isValidSignature",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "numerator",
- "type": "uint256"
- },
- {
- "name": "denominator",
- "type": "uint256"
- },
- {
- "name": "target",
- "type": "uint256"
- }
- ],
- "name": "getPartialAmount",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "TOKEN_TRANSFER_PROXY_CONTRACT",
- "outputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "orderAddresses",
- "type": "address[5][]"
- },
- {
- "name": "orderValues",
- "type": "uint256[6][]"
- },
- {
- "name": "fillTakerTokenAmounts",
- "type": "uint256[]"
- },
- {
- "name": "shouldThrowOnInsufficientBalanceOrAllowance",
- "type": "bool"
- },
- {
- "name": "v",
- "type": "uint8[]"
- },
- {
- "name": "r",
- "type": "bytes32[]"
- },
- {
- "name": "s",
- "type": "bytes32[]"
- }
- ],
- "name": "batchFillOrders",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "orderAddresses",
- "type": "address[5][]"
- },
- {
- "name": "orderValues",
- "type": "uint256[6][]"
- },
- {
- "name": "cancelTakerTokenAmounts",
- "type": "uint256[]"
- }
- ],
- "name": "batchCancelOrders",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "orderAddresses",
- "type": "address[5]"
- },
- {
- "name": "orderValues",
- "type": "uint256[6]"
- },
- {
- "name": "fillTakerTokenAmount",
- "type": "uint256"
- },
- {
- "name": "shouldThrowOnInsufficientBalanceOrAllowance",
- "type": "bool"
- },
- {
- "name": "v",
- "type": "uint8"
- },
- {
- "name": "r",
- "type": "bytes32"
- },
- {
- "name": "s",
- "type": "bytes32"
- }
- ],
- "name": "fillOrder",
- "outputs": [
- {
- "name": "filledTakerTokenAmount",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "orderAddresses",
- "type": "address[5]"
- },
- {
- "name": "orderValues",
- "type": "uint256[6]"
- }
- ],
- "name": "getOrderHash",
- "outputs": [
- {
- "name": "",
- "type": "bytes32"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "EXTERNAL_QUERY_GAS_LIMIT",
- "outputs": [
- {
- "name": "",
- "type": "uint16"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "VERSION",
- "outputs": [
- {
- "name": "",
- "type": "string"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "inputs": [
- {
- "name": "_zrxToken",
- "type": "address"
- },
- {
- "name": "_tokenTransferProxy",
- "type": "address"
- }
- ],
- "payable": false,
- "type": "constructor"
- },
- {
"anonymous": false,
"inputs": [
{
"indexed": true,
- "name": "maker",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "taker",
+ "name": "makerAddress",
"type": "address"
},
{
"indexed": true,
- "name": "feeRecipient",
+ "name": "feeRecipientAddress",
"type": "address"
},
{
"indexed": false,
- "name": "makerToken",
+ "name": "takerAddress",
"type": "address"
},
{
"indexed": false,
- "name": "takerToken",
+ "name": "senderAddress",
"type": "address"
},
{
"indexed": false,
- "name": "filledMakerTokenAmount",
+ "name": "makerAssetFilledAmount",
"type": "uint256"
},
{
"indexed": false,
- "name": "filledTakerTokenAmount",
+ "name": "takerAssetFilledAmount",
"type": "uint256"
},
{
"indexed": false,
- "name": "paidMakerFee",
+ "name": "makerFeePaid",
"type": "uint256"
},
{
"indexed": false,
- "name": "paidTakerFee",
+ "name": "takerFeePaid",
"type": "uint256"
},
{
"indexed": true,
- "name": "tokens",
+ "name": "orderHash",
"type": "bytes32"
},
{
"indexed": false,
- "name": "orderHash",
- "type": "bytes32"
+ "name": "makerAssetData",
+ "type": "bytes"
+ },
+ {
+ "indexed": false,
+ "name": "takerAssetData",
+ "type": "bytes"
}
],
- "name": "LogFill",
+ "name": "Fill",
"type": "event"
},
{
@@ -530,46 +68,36 @@
"inputs": [
{
"indexed": true,
- "name": "maker",
+ "name": "makerAddress",
"type": "address"
},
{
"indexed": true,
- "name": "feeRecipient",
+ "name": "feeRecipientAddress",
"type": "address"
},
{
"indexed": false,
- "name": "makerToken",
+ "name": "senderAddress",
"type": "address"
},
{
- "indexed": false,
- "name": "takerToken",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "cancelledMakerTokenAmount",
- "type": "uint256"
+ "indexed": true,
+ "name": "orderHash",
+ "type": "bytes32"
},
{
"indexed": false,
- "name": "cancelledTakerTokenAmount",
- "type": "uint256"
- },
- {
- "indexed": true,
- "name": "tokens",
- "type": "bytes32"
+ "name": "makerAssetData",
+ "type": "bytes"
},
{
"indexed": false,
- "name": "orderHash",
- "type": "bytes32"
+ "name": "takerAssetData",
+ "type": "bytes"
}
],
- "name": "LogCancel",
+ "name": "Cancel",
"type": "event"
},
{
@@ -577,16 +105,21 @@
"inputs": [
{
"indexed": true,
- "name": "errorId",
- "type": "uint8"
+ "name": "makerAddress",
+ "type": "address"
},
{
"indexed": true,
- "name": "orderHash",
- "type": "bytes32"
+ "name": "senderAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "orderEpoch",
+ "type": "uint256"
}
],
- "name": "LogError",
+ "name": "CancelUpTo",
"type": "event"
}
],
diff --git a/packages/order-watcher/src/compact_artifacts/Token.json b/packages/order-watcher/src/compact_artifacts/Token.json
deleted file mode 100644
index 3b5a86ae0..000000000
--- a/packages/order-watcher/src/compact_artifacts/Token.json
+++ /dev/null
@@ -1,172 +0,0 @@
-{
- "contract_name": "Token",
- "abi": [
- {
- "constant": false,
- "inputs": [
- {
- "name": "_spender",
- "type": "address"
- },
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "approve",
- "outputs": [
- {
- "name": "success",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "totalSupply",
- "outputs": [
- {
- "name": "supply",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_from",
- "type": "address"
- },
- {
- "name": "_to",
- "type": "address"
- },
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "transferFrom",
- "outputs": [
- {
- "name": "success",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_owner",
- "type": "address"
- }
- ],
- "name": "balanceOf",
- "outputs": [
- {
- "name": "balance",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_to",
- "type": "address"
- },
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "transfer",
- "outputs": [
- {
- "name": "success",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_owner",
- "type": "address"
- },
- {
- "name": "_spender",
- "type": "address"
- }
- ],
- "name": "allowance",
- "outputs": [
- {
- "name": "remaining",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "_from",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "_to",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "Transfer",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "_owner",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "_spender",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "Approval",
- "type": "event"
- }
- ]
-}
diff --git a/packages/order-watcher/src/compact_artifacts/TokenRegistry.json b/packages/order-watcher/src/compact_artifacts/TokenRegistry.json
deleted file mode 100644
index 0f583628c..000000000
--- a/packages/order-watcher/src/compact_artifacts/TokenRegistry.json
+++ /dev/null
@@ -1,547 +0,0 @@
-{
- "contract_name": "TokenRegistry",
- "abi": [
- {
- "constant": false,
- "inputs": [
- {
- "name": "_token",
- "type": "address"
- },
- {
- "name": "_index",
- "type": "uint256"
- }
- ],
- "name": "removeToken",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_name",
- "type": "string"
- }
- ],
- "name": "getTokenAddressByName",
- "outputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_symbol",
- "type": "string"
- }
- ],
- "name": "getTokenAddressBySymbol",
- "outputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_token",
- "type": "address"
- },
- {
- "name": "_swarmHash",
- "type": "bytes"
- }
- ],
- "name": "setTokenSwarmHash",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_token",
- "type": "address"
- }
- ],
- "name": "getTokenMetaData",
- "outputs": [
- {
- "name": "",
- "type": "address"
- },
- {
- "name": "",
- "type": "string"
- },
- {
- "name": "",
- "type": "string"
- },
- {
- "name": "",
- "type": "uint8"
- },
- {
- "name": "",
- "type": "bytes"
- },
- {
- "name": "",
- "type": "bytes"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "owner",
- "outputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_token",
- "type": "address"
- },
- {
- "name": "_name",
- "type": "string"
- },
- {
- "name": "_symbol",
- "type": "string"
- },
- {
- "name": "_decimals",
- "type": "uint8"
- },
- {
- "name": "_ipfsHash",
- "type": "bytes"
- },
- {
- "name": "_swarmHash",
- "type": "bytes"
- }
- ],
- "name": "addToken",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_token",
- "type": "address"
- },
- {
- "name": "_name",
- "type": "string"
- }
- ],
- "name": "setTokenName",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "name": "tokens",
- "outputs": [
- {
- "name": "token",
- "type": "address"
- },
- {
- "name": "name",
- "type": "string"
- },
- {
- "name": "symbol",
- "type": "string"
- },
- {
- "name": "decimals",
- "type": "uint8"
- },
- {
- "name": "ipfsHash",
- "type": "bytes"
- },
- {
- "name": "swarmHash",
- "type": "bytes"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "name": "tokenAddresses",
- "outputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_name",
- "type": "string"
- }
- ],
- "name": "getTokenByName",
- "outputs": [
- {
- "name": "",
- "type": "address"
- },
- {
- "name": "",
- "type": "string"
- },
- {
- "name": "",
- "type": "string"
- },
- {
- "name": "",
- "type": "uint8"
- },
- {
- "name": "",
- "type": "bytes"
- },
- {
- "name": "",
- "type": "bytes"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "getTokenAddresses",
- "outputs": [
- {
- "name": "",
- "type": "address[]"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_token",
- "type": "address"
- },
- {
- "name": "_ipfsHash",
- "type": "bytes"
- }
- ],
- "name": "setTokenIpfsHash",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_symbol",
- "type": "string"
- }
- ],
- "name": "getTokenBySymbol",
- "outputs": [
- {
- "name": "",
- "type": "address"
- },
- {
- "name": "",
- "type": "string"
- },
- {
- "name": "",
- "type": "string"
- },
- {
- "name": "",
- "type": "uint8"
- },
- {
- "name": "",
- "type": "bytes"
- },
- {
- "name": "",
- "type": "bytes"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_token",
- "type": "address"
- },
- {
- "name": "_symbol",
- "type": "string"
- }
- ],
- "name": "setTokenSymbol",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "newOwner",
- "type": "address"
- }
- ],
- "name": "transferOwnership",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "token",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "name",
- "type": "string"
- },
- {
- "indexed": false,
- "name": "symbol",
- "type": "string"
- },
- {
- "indexed": false,
- "name": "decimals",
- "type": "uint8"
- },
- {
- "indexed": false,
- "name": "ipfsHash",
- "type": "bytes"
- },
- {
- "indexed": false,
- "name": "swarmHash",
- "type": "bytes"
- }
- ],
- "name": "LogAddToken",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "token",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "name",
- "type": "string"
- },
- {
- "indexed": false,
- "name": "symbol",
- "type": "string"
- },
- {
- "indexed": false,
- "name": "decimals",
- "type": "uint8"
- },
- {
- "indexed": false,
- "name": "ipfsHash",
- "type": "bytes"
- },
- {
- "indexed": false,
- "name": "swarmHash",
- "type": "bytes"
- }
- ],
- "name": "LogRemoveToken",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "token",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "oldName",
- "type": "string"
- },
- {
- "indexed": false,
- "name": "newName",
- "type": "string"
- }
- ],
- "name": "LogTokenNameChange",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "token",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "oldSymbol",
- "type": "string"
- },
- {
- "indexed": false,
- "name": "newSymbol",
- "type": "string"
- }
- ],
- "name": "LogTokenSymbolChange",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "token",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "oldIpfsHash",
- "type": "bytes"
- },
- {
- "indexed": false,
- "name": "newIpfsHash",
- "type": "bytes"
- }
- ],
- "name": "LogTokenIpfsHashChange",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "token",
- "type": "address"
- },
- {
- "indexed": false,
- "name": "oldSwarmHash",
- "type": "bytes"
- },
- {
- "indexed": false,
- "name": "newSwarmHash",
- "type": "bytes"
- }
- ],
- "name": "LogTokenSwarmHashChange",
- "type": "event"
- }
- ],
- "networks": {
- "1": {
- "address": "0x926a74c5c36adf004c87399e65f75628b0f98d2c"
- },
- "3": {
- "address": "0x6b1a50f0bb5a7995444bd3877b22dc89c62843ed"
- },
- "4": {
- "address": "0x4e9aad8184de8833365fea970cd9149372fdf1e6"
- },
- "42": {
- "address": "0xf18e504561f4347bea557f3d4558f559dddbae7f"
- },
- "50": {
- "address": "0x0b1ba0af832d7c05fd64161e0db78e85978e8082"
- }
- }
-}
diff --git a/packages/order-watcher/src/compact_artifacts/TokenTransferProxy.json b/packages/order-watcher/src/compact_artifacts/TokenTransferProxy.json
deleted file mode 100644
index 8cf551ddb..000000000
--- a/packages/order-watcher/src/compact_artifacts/TokenTransferProxy.json
+++ /dev/null
@@ -1,187 +0,0 @@
-{
- "contract_name": "TokenTransferProxy",
- "abi": [
- {
- "constant": false,
- "inputs": [
- {
- "name": "token",
- "type": "address"
- },
- {
- "name": "from",
- "type": "address"
- },
- {
- "name": "to",
- "type": "address"
- },
- {
- "name": "value",
- "type": "uint256"
- }
- ],
- "name": "transferFrom",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "target",
- "type": "address"
- }
- ],
- "name": "addAuthorizedAddress",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "name": "authorities",
- "outputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "target",
- "type": "address"
- }
- ],
- "name": "removeAuthorizedAddress",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "owner",
- "outputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "",
- "type": "address"
- }
- ],
- "name": "authorized",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "getAuthorizedAddresses",
- "outputs": [
- {
- "name": "",
- "type": "address[]"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "newOwner",
- "type": "address"
- }
- ],
- "name": "transferOwnership",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "target",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "caller",
- "type": "address"
- }
- ],
- "name": "LogAuthorizedAddressAdded",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "target",
- "type": "address"
- },
- {
- "indexed": true,
- "name": "caller",
- "type": "address"
- }
- ],
- "name": "LogAuthorizedAddressRemoved",
- "type": "event"
- }
- ],
- "networks": {
- "1": {
- "address": "0x8da0d80f5007ef1e431dd2127178d224e32c2ef4"
- },
- "3": {
- "address": "0x4e9aad8184de8833365fea970cd9149372fdf1e6"
- },
- "4": {
- "address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d"
- },
- "42": {
- "address": "0x087eed4bc1ee3de49befbd66c662b434b15d49d4"
- },
- "50": {
- "address": "0x1dc4c1cefef38a777b15aa20260a54e584b16c48"
- }
- }
-}
diff --git a/packages/order-watcher/src/compact_artifacts/WETH9.json b/packages/order-watcher/src/compact_artifacts/WETH9.json
new file mode 100644
index 000000000..f635276a1
--- /dev/null
+++ b/packages/order-watcher/src/compact_artifacts/WETH9.json
@@ -0,0 +1,100 @@
+{
+ "contract_name": "WETH9",
+ "abi": [
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "_from",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "_to",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Transfer",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "_owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "_spender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Approval",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "_owner",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Deposit",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "_owner",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Withdrawal",
+ "type": "event"
+ }
+ ],
+ "networks": {
+ "1": {
+ "address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
+ },
+ "3": {
+ "address": "0xc00fd9820cd2898cc4c054b7bf142de637ad129a"
+ },
+ "4": {
+ "address": "0xc778417e063141139fce010982780140aa0cd5ab"
+ },
+ "42": {
+ "address": "0x653e49e301e508a13237c0ddc98ae7d4cd2667a1"
+ },
+ "50": {
+ "address": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c"
+ }
+ }
+}
diff --git a/packages/order-watcher/src/compact_artifacts/ZRX.json b/packages/order-watcher/src/compact_artifacts/ZRX.json
deleted file mode 100644
index e40b8f268..000000000
--- a/packages/order-watcher/src/compact_artifacts/ZRX.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "contract_name": "ZRX",
- "networks": {
- "1": {
- "address": "0xe41d2489571d322189246dafa5ebde1f4699f498"
- },
- "3": {
- "address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d"
- },
- "4": {
- "address": "0x00f58d6d585f84b2d7267940cede30ce2fe6eae8"
- },
- "42": {
- "address": "0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570"
- },
- "50": {
- "address": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401"
- }
- }
-}
diff --git a/packages/order-watcher/src/fetchers/asset_balance_and_proxy_allowance_fetcher.ts b/packages/order-watcher/src/fetchers/asset_balance_and_proxy_allowance_fetcher.ts
new file mode 100644
index 000000000..a1de22a5e
--- /dev/null
+++ b/packages/order-watcher/src/fetchers/asset_balance_and_proxy_allowance_fetcher.ts
@@ -0,0 +1,74 @@
+// tslint:disable:no-unnecessary-type-assertion
+import { BlockParamLiteral, ERC20TokenWrapper, ERC721TokenWrapper } from '@0xproject/contract-wrappers';
+import { AbstractBalanceAndProxyAllowanceFetcher, assetDataUtils } from '@0xproject/order-utils';
+import { AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0xproject/types';
+import { BigNumber } from '@0xproject/utils';
+
+export class AssetBalanceAndProxyAllowanceFetcher implements AbstractBalanceAndProxyAllowanceFetcher {
+ private readonly _erc20Token: ERC20TokenWrapper;
+ private readonly _erc721Token: ERC721TokenWrapper;
+ private readonly _stateLayer: BlockParamLiteral;
+ constructor(erc20Token: ERC20TokenWrapper, erc721Token: ERC721TokenWrapper, stateLayer: BlockParamLiteral) {
+ this._erc20Token = erc20Token;
+ this._erc721Token = erc721Token;
+ this._stateLayer = stateLayer;
+ }
+ public async getBalanceAsync(assetData: string, userAddress: string): Promise<BigNumber> {
+ const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
+ if (decodedAssetData.assetProxyId === AssetProxyId.ERC20) {
+ const decodedERC20AssetData = decodedAssetData as ERC20AssetData;
+ const balance = await this._erc20Token.getBalanceAsync(decodedERC20AssetData.tokenAddress, userAddress, {
+ defaultBlock: this._stateLayer,
+ });
+ return balance;
+ } else {
+ const decodedERC721AssetData = decodedAssetData as ERC721AssetData;
+ const tokenOwner = await this._erc721Token.getOwnerOfAsync(
+ decodedERC721AssetData.tokenAddress,
+ decodedERC721AssetData.tokenId,
+ {
+ defaultBlock: this._stateLayer,
+ },
+ );
+ const balance = tokenOwner === userAddress ? new BigNumber(1) : new BigNumber(0);
+ return balance;
+ }
+ }
+ public async getProxyAllowanceAsync(assetData: string, userAddress: string): Promise<BigNumber> {
+ const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
+ if (decodedAssetData.assetProxyId === AssetProxyId.ERC20) {
+ const decodedERC20AssetData = decodedAssetData as ERC20AssetData;
+ const proxyAllowance = await this._erc20Token.getProxyAllowanceAsync(
+ decodedERC20AssetData.tokenAddress,
+ userAddress,
+ {
+ defaultBlock: this._stateLayer,
+ },
+ );
+ return proxyAllowance;
+ } else {
+ const decodedERC721AssetData = decodedAssetData as ERC721AssetData;
+
+ const isApprovedForAll = await this._erc721Token.isProxyApprovedForAllAsync(
+ decodedERC721AssetData.tokenAddress,
+ userAddress,
+ {
+ defaultBlock: this._stateLayer,
+ },
+ );
+ if (isApprovedForAll) {
+ return new BigNumber(this._erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
+ } else {
+ const isApproved = await this._erc721Token.isProxyApprovedAsync(
+ decodedERC721AssetData.tokenAddress,
+ decodedERC721AssetData.tokenId,
+ {
+ defaultBlock: this._stateLayer,
+ },
+ );
+ const proxyAllowance = isApproved ? new BigNumber(1) : new BigNumber(0);
+ return proxyAllowance;
+ }
+ }
+ }
+}
diff --git a/packages/order-watcher/src/fetchers/order_filled_cancelled_fetcher.ts b/packages/order-watcher/src/fetchers/order_filled_cancelled_fetcher.ts
new file mode 100644
index 000000000..bfad1a48c
--- /dev/null
+++ b/packages/order-watcher/src/fetchers/order_filled_cancelled_fetcher.ts
@@ -0,0 +1,27 @@
+// tslint:disable:no-unnecessary-type-assertion
+import { BlockParamLiteral, ExchangeWrapper } from '@0xproject/contract-wrappers';
+import { AbstractOrderFilledCancelledFetcher } from '@0xproject/order-utils';
+import { BigNumber } from '@0xproject/utils';
+
+export class OrderFilledCancelledFetcher implements AbstractOrderFilledCancelledFetcher {
+ private readonly _exchange: ExchangeWrapper;
+ private readonly _stateLayer: BlockParamLiteral;
+ constructor(exchange: ExchangeWrapper, stateLayer: BlockParamLiteral) {
+ this._exchange = exchange;
+ this._stateLayer = stateLayer;
+ }
+ public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
+ const filledTakerAmount = this._exchange.getFilledTakerAssetAmountAsync(orderHash, {
+ defaultBlock: this._stateLayer,
+ });
+ return filledTakerAmount;
+ }
+ public async isOrderCancelledAsync(orderHash: string): Promise<boolean> {
+ const isCancelled = await this._exchange.isCancelledAsync(orderHash);
+ return isCancelled;
+ }
+ public getZRXAssetData(): string {
+ const zrxAssetData = this._exchange.getZRXAssetData();
+ return zrxAssetData;
+ }
+}
diff --git a/packages/order-watcher/src/index.ts b/packages/order-watcher/src/index.ts
index 390003b1d..5f84554c8 100644
--- a/packages/order-watcher/src/index.ts
+++ b/packages/order-watcher/src/index.ts
@@ -4,4 +4,5 @@ export { OrderStateValid, OrderStateInvalid, OrderState } from '@0xproject/types
export { OnOrderStateChangeCallback, OrderWatcherConfig } from './types';
-export { BlockParamLiteral, BlockParam, Order, Provider, SignedOrder } from '@0xproject/types';
+export { Order, SignedOrder } from '@0xproject/types';
+export { BlockParamLiteral, BlockParam, Provider } from 'ethereum-types';
diff --git a/packages/order-watcher/src/order_watcher/collision_resistant_abi_decoder.ts b/packages/order-watcher/src/order_watcher/collision_resistant_abi_decoder.ts
new file mode 100644
index 000000000..e13663c7a
--- /dev/null
+++ b/packages/order-watcher/src/order_watcher/collision_resistant_abi_decoder.ts
@@ -0,0 +1,54 @@
+import { AbiDecoder } from '@0xproject/utils';
+import { ContractAbi, DecodedLogArgs, LogEntry, LogWithDecodedArgs, RawLog } from 'ethereum-types';
+
+const TOKEN_TYPE_COLLISION = `Token can't be marked as ERC20 and ERC721 at the same time`;
+
+/**
+ * ERC20 and ERC721 have some events with different args but colliding signature.
+ * For exmaple:
+ * Transfer(_from address, _to address, _value uint256)
+ * Transfer(_from address, _to address, _tokenId uint256)
+ * Both have the signature:
+ * Transfer(address,address,uint256)
+ *
+ * In order to correctly decode those events we need to know the token type by address in advance.
+ * You can pass it by calling `this.addERC20Token(address)` or `this.addERC721Token(address)`
+ */
+export class CollisionResistanceAbiDecoder {
+ private readonly _erc20AbiDecoder: AbiDecoder;
+ private readonly _erc721AbiDecoder: AbiDecoder;
+ private readonly _restAbiDecoder: AbiDecoder;
+ private readonly _knownERC20Tokens = new Set();
+ private readonly _knownERC721Tokens = new Set();
+ constructor(erc20Abi: ContractAbi, erc721Abi: ContractAbi, abis: ContractAbi[]) {
+ this._erc20AbiDecoder = new AbiDecoder([erc20Abi]);
+ this._erc721AbiDecoder = new AbiDecoder([erc721Abi]);
+ this._restAbiDecoder = new AbiDecoder(abis);
+ }
+ public tryToDecodeLogOrNoop<ArgsType extends DecodedLogArgs>(log: LogEntry): LogWithDecodedArgs<ArgsType> | RawLog {
+ if (this._knownERC20Tokens.has(log.address)) {
+ const maybeDecodedERC20Log = this._erc20AbiDecoder.tryToDecodeLogOrNoop(log);
+ return maybeDecodedERC20Log;
+ } else if (this._knownERC721Tokens.has(log.address)) {
+ const maybeDecodedERC721Log = this._erc721AbiDecoder.tryToDecodeLogOrNoop(log);
+ return maybeDecodedERC721Log;
+ } else {
+ const maybeDecodedLog = this._restAbiDecoder.tryToDecodeLogOrNoop(log);
+ return maybeDecodedLog;
+ }
+ }
+ // Hints the ABI decoder that a particular token address is ERC20 and events from it should be decoded as ERC20 events
+ public addERC20Token(address: string): void {
+ if (this._knownERC721Tokens.has(address)) {
+ throw new Error(TOKEN_TYPE_COLLISION);
+ }
+ this._knownERC20Tokens.add(address);
+ }
+ // Hints the ABI decoder that a particular token address is ERC721 and events from it should be decoded as ERC721 events
+ public addERC721Token(address: string): void {
+ if (this._knownERC20Tokens.has(address)) {
+ throw new Error(TOKEN_TYPE_COLLISION);
+ }
+ this._knownERC721Tokens.add(address);
+ }
+}
diff --git a/packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts b/packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts
new file mode 100644
index 000000000..cc70bd5d7
--- /dev/null
+++ b/packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts
@@ -0,0 +1,230 @@
+// tslint:disable:no-unnecessary-type-assertion
+import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils';
+import { AssetProxyId, ERC20AssetData, ERC721AssetData, SignedOrder } from '@0xproject/types';
+import { BigNumber } from '@0xproject/utils';
+import * as _ from 'lodash';
+
+export interface OrderHashesByMakerAddress {
+ [makerAddress: string]: Set<string>;
+}
+
+export interface OrderHashesByERC20ByMakerAddress {
+ [makerAddress: string]: {
+ [erc20TokenAddress: string]: Set<string>;
+ };
+}
+
+export interface OrderHashesByERC721AddressByTokenIdByMakerAddress {
+ [makerAddress: string]: {
+ [erc721TokenAddress: string]: {
+ // Ideally erc721TokenId should be a BigNumber, but it's not a valid index type so we just convert it to a string before using it as an index
+ [erc721TokenId: string]: Set<string>;
+ };
+ };
+}
+
+/**
+ */
+export class DependentOrderHashesTracker {
+ private readonly _zrxTokenAddress: string;
+ // `_orderHashesByMakerAddress` is redundant and could be generated from
+ // `_orderHashesByERC20ByMakerAddress` and `_orderHashesByERC721AddressByTokenIdByMakerAddress`
+ // on the fly by merging all the entries together but it's more complex and computationally heavy.
+ // We might change that in future if we're move memory-constrained.
+ private readonly _orderHashesByMakerAddress: OrderHashesByMakerAddress = {};
+ private readonly _orderHashesByERC20ByMakerAddress: OrderHashesByERC20ByMakerAddress = {};
+ private readonly _orderHashesByERC721AddressByTokenIdByMakerAddress: OrderHashesByERC721AddressByTokenIdByMakerAddress = {};
+ constructor(zrxTokenAddress: string) {
+ this._zrxTokenAddress = zrxTokenAddress;
+ }
+ public getDependentOrderHashesByERC721ByMaker(makerAddress: string, tokenAddress: string): string[] {
+ const orderHashSets = _.values(
+ this._orderHashesByERC721AddressByTokenIdByMakerAddress[makerAddress][tokenAddress],
+ );
+ const orderHashList = _.reduce(
+ orderHashSets,
+ (accumulator, orderHashSet) => [...accumulator, ...orderHashSet],
+ [] as string[],
+ );
+ const uniqueOrderHashList = _.uniq(orderHashList);
+ return uniqueOrderHashList;
+ }
+ public getDependentOrderHashesByMaker(makerAddress: string): string[] {
+ const dependentOrderHashes = Array.from(this._orderHashesByMakerAddress[makerAddress]);
+ return dependentOrderHashes;
+ }
+ public getDependentOrderHashesByAssetDataByMaker(makerAddress: string, assetData: string): string[] {
+ const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
+ const dependentOrderHashes =
+ decodedAssetData.assetProxyId === AssetProxyId.ERC20
+ ? this._getDependentOrderHashesByERC20AssetData(makerAddress, assetData)
+ : this._getDependentOrderHashesByERC721AssetData(makerAddress, assetData);
+ return dependentOrderHashes;
+ }
+ public addToDependentOrderHashes(signedOrder: SignedOrder): void {
+ const decodedMakerAssetData = assetDataUtils.decodeAssetDataOrThrow(signedOrder.makerAssetData);
+ if (decodedMakerAssetData.assetProxyId === AssetProxyId.ERC20) {
+ this._addToERC20DependentOrderHashes(signedOrder, (decodedMakerAssetData as ERC20AssetData).tokenAddress);
+ } else {
+ this._addToERC721DependentOrderHashes(
+ signedOrder,
+ (decodedMakerAssetData as ERC721AssetData).tokenAddress,
+ (decodedMakerAssetData as ERC721AssetData).tokenId,
+ );
+ }
+ this._addToERC20DependentOrderHashes(signedOrder, this._zrxTokenAddress);
+ this._addToMakerDependentOrderHashes(signedOrder);
+ }
+ public removeFromDependentOrderHashes(signedOrder: SignedOrder): void {
+ const decodedMakerAssetData = assetDataUtils.decodeAssetDataOrThrow(signedOrder.makerAssetData);
+ if (decodedMakerAssetData.assetProxyId === AssetProxyId.ERC20) {
+ this._removeFromERC20DependentOrderhashes(
+ signedOrder,
+ (decodedMakerAssetData as ERC20AssetData).tokenAddress,
+ );
+ } else {
+ this._removeFromERC721DependentOrderhashes(
+ signedOrder,
+ (decodedMakerAssetData as ERC721AssetData).tokenAddress,
+ (decodedMakerAssetData as ERC721AssetData).tokenId,
+ );
+ }
+ this._removeFromERC20DependentOrderhashes(signedOrder, this._zrxTokenAddress);
+ this._removeFromMakerDependentOrderhashes(signedOrder);
+ }
+ private _getDependentOrderHashesByERC20AssetData(makerAddress: string, erc20AssetData: string): string[] {
+ const tokenAddress = assetDataUtils.decodeERC20AssetData(erc20AssetData).tokenAddress;
+ let dependentOrderHashes: string[] = [];
+ if (
+ !_.isUndefined(this._orderHashesByERC20ByMakerAddress[makerAddress]) &&
+ !_.isUndefined(this._orderHashesByERC20ByMakerAddress[makerAddress][tokenAddress])
+ ) {
+ dependentOrderHashes = Array.from(this._orderHashesByERC20ByMakerAddress[makerAddress][tokenAddress]);
+ }
+ return dependentOrderHashes;
+ }
+ private _getDependentOrderHashesByERC721AssetData(makerAddress: string, erc721AssetData: string): string[] {
+ const tokenAddress = assetDataUtils.decodeERC721AssetData(erc721AssetData).tokenAddress;
+ const tokenId = assetDataUtils.decodeERC721AssetData(erc721AssetData).tokenId;
+ let dependentOrderHashes: string[] = [];
+ if (
+ !_.isUndefined(this._orderHashesByERC721AddressByTokenIdByMakerAddress[makerAddress]) &&
+ !_.isUndefined(this._orderHashesByERC721AddressByTokenIdByMakerAddress[makerAddress][tokenAddress]) &&
+ !_.isUndefined(
+ this._orderHashesByERC721AddressByTokenIdByMakerAddress[makerAddress][tokenAddress][tokenId.toString()],
+ )
+ ) {
+ dependentOrderHashes = Array.from(
+ this._orderHashesByERC721AddressByTokenIdByMakerAddress[makerAddress][tokenAddress][tokenId.toString()],
+ );
+ }
+ return dependentOrderHashes;
+ }
+ private _addToERC20DependentOrderHashes(signedOrder: SignedOrder, erc20TokenAddress: string): void {
+ const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
+ if (_.isUndefined(this._orderHashesByERC20ByMakerAddress[signedOrder.makerAddress])) {
+ this._orderHashesByERC20ByMakerAddress[signedOrder.makerAddress] = {};
+ }
+ if (_.isUndefined(this._orderHashesByERC20ByMakerAddress[signedOrder.makerAddress][erc20TokenAddress])) {
+ this._orderHashesByERC20ByMakerAddress[signedOrder.makerAddress][erc20TokenAddress] = new Set();
+ }
+ this._orderHashesByERC20ByMakerAddress[signedOrder.makerAddress][erc20TokenAddress].add(orderHash);
+ }
+ private _addToERC721DependentOrderHashes(
+ signedOrder: SignedOrder,
+ erc721TokenAddress: string,
+ tokenId: BigNumber,
+ ): void {
+ const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
+ if (_.isUndefined(this._orderHashesByERC721AddressByTokenIdByMakerAddress[signedOrder.makerAddress])) {
+ this._orderHashesByERC721AddressByTokenIdByMakerAddress[signedOrder.makerAddress] = {};
+ }
+
+ if (
+ _.isUndefined(
+ this._orderHashesByERC721AddressByTokenIdByMakerAddress[signedOrder.makerAddress][erc721TokenAddress],
+ )
+ ) {
+ this._orderHashesByERC721AddressByTokenIdByMakerAddress[signedOrder.makerAddress][erc721TokenAddress] = {};
+ }
+
+ if (
+ _.isUndefined(
+ this._orderHashesByERC721AddressByTokenIdByMakerAddress[signedOrder.makerAddress][erc721TokenAddress][
+ tokenId.toString()
+ ],
+ )
+ ) {
+ this._orderHashesByERC721AddressByTokenIdByMakerAddress[signedOrder.makerAddress][erc721TokenAddress][
+ tokenId.toString()
+ ] = new Set();
+ }
+
+ this._orderHashesByERC721AddressByTokenIdByMakerAddress[signedOrder.makerAddress][erc721TokenAddress][
+ tokenId.toString()
+ ].add(orderHash);
+ }
+ private _addToMakerDependentOrderHashes(signedOrder: SignedOrder): void {
+ const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
+ if (_.isUndefined(this._orderHashesByMakerAddress[signedOrder.makerAddress])) {
+ this._orderHashesByMakerAddress[signedOrder.makerAddress] = new Set();
+ }
+ this._orderHashesByMakerAddress[signedOrder.makerAddress].add(orderHash);
+ }
+ private _removeFromERC20DependentOrderhashes(signedOrder: SignedOrder, erc20TokenAddress: string): void {
+ const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
+ this._orderHashesByERC20ByMakerAddress[signedOrder.makerAddress][erc20TokenAddress].delete(orderHash);
+
+ if (_.isEmpty(this._orderHashesByERC20ByMakerAddress[signedOrder.makerAddress][erc20TokenAddress])) {
+ delete this._orderHashesByERC20ByMakerAddress[signedOrder.makerAddress][erc20TokenAddress];
+ }
+
+ if (_.isEmpty(this._orderHashesByERC20ByMakerAddress[signedOrder.makerAddress])) {
+ delete this._orderHashesByERC20ByMakerAddress[signedOrder.makerAddress];
+ }
+ }
+ private _removeFromERC721DependentOrderhashes(
+ signedOrder: SignedOrder,
+ erc721TokenAddress: string,
+ tokenId: BigNumber,
+ ): void {
+ const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
+ this._orderHashesByERC721AddressByTokenIdByMakerAddress[signedOrder.makerAddress][erc721TokenAddress][
+ tokenId.toString()
+ ].delete(orderHash);
+
+ if (
+ _.isEmpty(
+ this._orderHashesByERC721AddressByTokenIdByMakerAddress[signedOrder.makerAddress][erc721TokenAddress][
+ tokenId.toString()
+ ],
+ )
+ ) {
+ delete this._orderHashesByERC721AddressByTokenIdByMakerAddress[signedOrder.makerAddress][
+ erc721TokenAddress
+ ][tokenId.toString()];
+ }
+
+ if (
+ _.isEmpty(
+ this._orderHashesByERC721AddressByTokenIdByMakerAddress[signedOrder.makerAddress][erc721TokenAddress],
+ )
+ ) {
+ delete this._orderHashesByERC721AddressByTokenIdByMakerAddress[signedOrder.makerAddress][
+ erc721TokenAddress
+ ];
+ }
+
+ if (_.isEmpty(this._orderHashesByERC721AddressByTokenIdByMakerAddress[signedOrder.makerAddress])) {
+ delete this._orderHashesByERC721AddressByTokenIdByMakerAddress[signedOrder.makerAddress];
+ }
+ }
+ private _removeFromMakerDependentOrderhashes(signedOrder: SignedOrder): void {
+ const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
+ this._orderHashesByMakerAddress[signedOrder.makerAddress].delete(orderHash);
+
+ if (_.isEmpty(this._orderHashesByMakerAddress[signedOrder.makerAddress])) {
+ delete this._orderHashesByMakerAddress[signedOrder.makerAddress];
+ }
+ }
+}
diff --git a/packages/order-watcher/src/order_watcher/event_watcher.ts b/packages/order-watcher/src/order_watcher/event_watcher.ts
index 8ad52989b..9509c75de 100644
--- a/packages/order-watcher/src/order_watcher/event_watcher.ts
+++ b/packages/order-watcher/src/order_watcher/event_watcher.ts
@@ -1,6 +1,6 @@
-import { BlockParamLiteral, LogEntry } from '@0xproject/types';
import { intervalUtils, logUtils } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
+import { BlockParamLiteral, LogEntry, Provider } from 'ethereum-types';
import { Block, BlockAndLogStreamer, Log } from 'ethereumjs-blockstream';
import * as _ from 'lodash';
@@ -20,21 +20,21 @@ enum LogEventState {
*/
export class EventWatcher {
private readonly _web3Wrapper: Web3Wrapper;
+ private readonly _stateLayer: BlockParamLiteral;
+ private readonly _isVerbose: boolean;
private _blockAndLogStreamerIfExists: BlockAndLogStreamer<Block, Log> | undefined;
private _blockAndLogStreamIntervalIfExists?: NodeJS.Timer;
private _onLogAddedSubscriptionToken: string | undefined;
private _onLogRemovedSubscriptionToken: string | undefined;
private readonly _pollingIntervalMs: number;
- private readonly _stateLayer: BlockParamLiteral;
- private readonly _isVerbose: boolean;
constructor(
- web3Wrapper: Web3Wrapper,
+ provider: Provider,
pollingIntervalIfExistsMs: undefined | number,
stateLayer: BlockParamLiteral,
isVerbose: boolean,
) {
this._isVerbose = isVerbose;
- this._web3Wrapper = web3Wrapper;
+ this._web3Wrapper = new Web3Wrapper(provider);
this._stateLayer = stateLayer;
this._pollingIntervalMs = _.isUndefined(pollingIntervalIfExistsMs)
? DEFAULT_EVENT_POLLING_INTERVAL_MS
diff --git a/packages/order-watcher/src/order_watcher/expiration_watcher.ts b/packages/order-watcher/src/order_watcher/expiration_watcher.ts
index c1f34d13d..6eadf14c7 100644
--- a/packages/order-watcher/src/order_watcher/expiration_watcher.ts
+++ b/packages/order-watcher/src/order_watcher/expiration_watcher.ts
@@ -68,8 +68,8 @@ export class ExpirationWatcher {
private _pruneExpiredOrders(callback: (orderHash: string) => void): void {
const currentUnixTimestampMs = utils.getCurrentUnixTimestampMs();
while (true) {
- const hasTrakedOrders = this._orderHashByExpirationRBTree.size === 0;
- if (hasTrakedOrders) {
+ const hasNoTrackedOrders = this._orderHashByExpirationRBTree.size === 0;
+ if (hasNoTrackedOrders) {
break;
}
const nextOrderHashToExpire = this._orderHashByExpirationRBTree.min();
diff --git a/packages/order-watcher/src/order_watcher/order_watcher.ts b/packages/order-watcher/src/order_watcher/order_watcher.ts
index 765747e35..2dfbd4230 100644
--- a/packages/order-watcher/src/order_watcher/order_watcher.ts
+++ b/packages/order-watcher/src/order_watcher/order_watcher.ts
@@ -1,55 +1,53 @@
+// tslint:disable:no-unnecessary-type-assertion
import {
- BalanceAndProxyAllowanceLazyStore,
ContractWrappers,
- OrderFilledCancelledLazyStore,
+ ERC20TokenApprovalEventArgs,
+ ERC20TokenEventArgs,
+ ERC20TokenEvents,
+ ERC20TokenTransferEventArgs,
+ ERC721TokenApprovalEventArgs,
+ ERC721TokenApprovalForAllEventArgs,
+ ERC721TokenEventArgs,
+ ERC721TokenEvents,
+ ERC721TokenTransferEventArgs,
+ ExchangeCancelEventArgs,
+ ExchangeCancelUpToEventArgs,
+ ExchangeEventArgs,
+ ExchangeEvents,
+ ExchangeFillEventArgs,
+ WETH9DepositEventArgs,
+ WETH9EventArgs,
+ WETH9Events,
+ WETH9WithdrawalEventArgs,
} from '@0xproject/contract-wrappers';
import { schemas } from '@0xproject/json-schemas';
-import { getOrderHashHex, OrderStateUtils } from '@0xproject/order-utils';
import {
- BlockParamLiteral,
- ExchangeContractErrs,
- LogEntryEvent,
- LogWithDecodedArgs,
- OrderState,
- Provider,
- SignedOrder,
-} from '@0xproject/types';
+ assetDataUtils,
+ BalanceAndProxyAllowanceLazyStore,
+ OrderFilledCancelledLazyStore,
+ orderHashUtils,
+ OrderStateUtils,
+} from '@0xproject/order-utils';
+import { AssetProxyId, ExchangeContractErrs, OrderState, SignedOrder } from '@0xproject/types';
import { errorUtils, intervalUtils } from '@0xproject/utils';
-import { Web3Wrapper } from '@0xproject/web3-wrapper';
+import { BlockParamLiteral, LogEntryEvent, LogWithDecodedArgs, Provider } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from '../artifacts';
-import {
- EtherTokenDepositEventArgs,
- EtherTokenEventArgs,
- EtherTokenEvents,
- EtherTokenWithdrawalEventArgs,
-} from '../generated_contract_wrappers/ether_token';
-import {
- ExchangeEventArgs,
- ExchangeEvents,
- ExchangeLogCancelEventArgs,
- ExchangeLogFillEventArgs,
-} from '../generated_contract_wrappers/exchange';
-import {
- TokenApprovalEventArgs,
- TokenEventArgs,
- TokenEvents,
- TokenTransferEventArgs,
-} from '../generated_contract_wrappers/token';
+import { AssetBalanceAndProxyAllowanceFetcher } from '../fetchers/asset_balance_and_proxy_allowance_fetcher';
+import { OrderFilledCancelledFetcher } from '../fetchers/order_filled_cancelled_fetcher';
+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';
-type ContractEventArgs = EtherTokenEventArgs | ExchangeEventArgs | TokenEventArgs;
+const MILLISECONDS_IN_A_SECOND = 1000;
-interface DependentOrderHashes {
- [makerAddress: string]: {
- [makerToken: string]: Set<string>;
- };
-}
+type ContractEventArgs = WETH9EventArgs | ExchangeEventArgs | ERC20TokenEventArgs | ERC721TokenEventArgs;
interface OrderByOrderHash {
[orderHash: string]: SignedOrder;
@@ -59,8 +57,14 @@ interface OrderStateByOrderHash {
[orderHash: string]: OrderState;
}
-// tslint:disable-next-line:custom-no-magic-numbers
-const DEFAULT_CLEANUP_JOB_INTERVAL_MS = 1000 * 60 * 60; // 1h
+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;
/**
@@ -70,69 +74,86 @@ const STATE_LAYER = BlockParamLiteral.Latest;
* the order should be deemed invalid.
*/
export class OrderWatcher {
- private readonly _contractWrappers: ContractWrappers;
+ private readonly _dependentOrderHashesTracker: DependentOrderHashesTracker;
private readonly _orderStateByOrderHashCache: OrderStateByOrderHash = {};
private readonly _orderByOrderHash: OrderByOrderHash = {};
- private readonly _dependentOrderHashes: DependentOrderHashes = {};
- private _callbackIfExists?: OnOrderStateChangeCallback;
private readonly _eventWatcher: EventWatcher;
- private readonly _web3Wrapper: Web3Wrapper;
+ private readonly _provider: Provider;
+ 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;
- constructor(provider: Provider, networkId: number, config?: OrderWatcherConfig) {
- this._web3Wrapper = new Web3Wrapper(provider);
- const artifactJSONs = _.values(artifacts);
- const abiArrays = _.map(artifactJSONs, artifact => artifact.abi);
- _.forEach(abiArrays, abi => {
- this._web3Wrapper.abiDecoder.addABI(abi);
- });
- this._contractWrappers = new ContractWrappers(provider, { networkId });
- const pollingIntervalIfExistsMs = _.isUndefined(config) ? undefined : config.eventPollingIntervalMs;
- const isVerbose = !_.isUndefined(config) && !_.isUndefined(config.isVerbose) ? config.isVerbose : false;
- this._eventWatcher = new EventWatcher(this._web3Wrapper, pollingIntervalIfExistsMs, STATE_LAYER, isVerbose);
- this._balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore(
- this._contractWrappers.token,
- STATE_LAYER,
+ private _callbackIfExists?: OnOrderStateChangeCallback;
+ constructor(
+ provider: Provider,
+ networkId: number,
+ partialConfig: Partial<OrderWatcherConfig> = DEFAULT_ORDER_WATCHER_CONFIG,
+ ) {
+ assert.isWeb3Provider('provider', provider);
+ 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.abi,
+ artifacts.ERC721Token.abi,
+ [artifacts.EtherToken.abi, artifacts.Exchange.abi],
);
- this._orderFilledCancelledLazyStore = new OrderFilledCancelledLazyStore(
- this._contractWrappers.exchange,
+ const contractWrappers = new ContractWrappers(provider, { networkId });
+ this._eventWatcher = new EventWatcher(provider, config.eventPollingIntervalMs, STATE_LAYER, config.isVerbose);
+ const balanceAndProxyAllowanceFetcher = new AssetBalanceAndProxyAllowanceFetcher(
+ contractWrappers.erc20Token,
+ contractWrappers.erc721Token,
STATE_LAYER,
);
- this._orderStateUtils = new OrderStateUtils(
- this._balanceAndProxyAllowanceLazyStore,
- this._orderFilledCancelledLazyStore,
+ this._balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore(
+ balanceAndProxyAllowanceFetcher,
);
- const orderExpirationCheckingIntervalMsIfExists = _.isUndefined(config)
- ? undefined
- : config.orderExpirationCheckingIntervalMs;
+ const orderFilledCancelledFetcher = new OrderFilledCancelledFetcher(contractWrappers.exchange, STATE_LAYER);
+ this._orderFilledCancelledLazyStore = new OrderFilledCancelledLazyStore(orderFilledCancelledFetcher);
+ this._orderStateUtils = new OrderStateUtils(balanceAndProxyAllowanceFetcher, orderFilledCancelledFetcher);
const expirationMarginIfExistsMs = _.isUndefined(config) ? undefined : config.expirationMarginMs;
this._expirationWatcher = new ExpirationWatcher(
expirationMarginIfExistsMs,
- orderExpirationCheckingIntervalMsIfExists,
+ config.orderExpirationCheckingIntervalMs,
);
- this._cleanupJobInterval =
- _.isUndefined(config) || _.isUndefined(config.cleanupJobIntervalMs)
- ? DEFAULT_CLEANUP_JOB_INTERVAL_MS
- : config.cleanupJobIntervalMs;
+ 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 addOrder(signedOrder: SignedOrder): void {
+ public async addOrderAsync(signedOrder: SignedOrder): Promise<void> {
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
- const orderHash = getOrderHashHex(signedOrder);
- assert.isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker);
- this._orderByOrderHash[orderHash] = signedOrder;
- this._addToDependentOrderHashes(signedOrder, orderHash);
- const milisecondsInASecond = 1000;
- const expirationUnixTimestampMs = signedOrder.expirationUnixTimestampSec.times(milisecondsInASecond);
+ const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
+ await assert.isValidSignatureAsync(this._provider, orderHash, signedOrder.signature, signedOrder.makerAddress);
+
+ 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 => {
+ const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
+ if (decodedAssetData.assetProxyId === AssetProxyId.ERC20) {
+ this._collisionResistantAbiDecoder.addERC20Token(decodedAssetData.tokenAddress);
+ } else if (decodedAssetData.assetProxyId === AssetProxyId.ERC721) {
+ this._collisionResistantAbiDecoder.addERC721Token(decodedAssetData.tokenAddress);
+ }
+ });
}
/**
* Removes an order from the orderWatcher
@@ -144,16 +165,10 @@ export class OrderWatcher {
if (_.isUndefined(signedOrder)) {
return; // noop
}
+ this._dependentOrderHashesTracker.removeFromDependentOrderHashes(signedOrder);
delete this._orderByOrderHash[orderHash];
- delete this._orderStateByOrderHashCache[orderHash];
- const zrxTokenAddress = this._orderFilledCancelledLazyStore.getZRXTokenAddress();
-
- this._removeFromDependentOrderHashes(signedOrder.maker, zrxTokenAddress, orderHash);
- if (zrxTokenAddress !== signedOrder.makerTokenAddress) {
- this._removeFromDependentOrderHashes(signedOrder.maker, signedOrder.makerTokenAddress, orderHash);
- }
-
this._expirationWatcher.removeOrder(orderHash);
+ delete this._orderStateByOrderHashCache[orderHash];
}
/**
* Starts an orderWatcher subscription. The callback will be called every time a watched order's
@@ -202,21 +217,27 @@ export class OrderWatcher {
const signedOrder = this._orderByOrderHash[orderHash];
this._orderFilledCancelledLazyStore.deleteFilledTakerAmount(orderHash);
- this._orderFilledCancelledLazyStore.deleteCancelledTakerAmount(orderHash);
+ this._orderFilledCancelledLazyStore.deleteIsCancelled(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);
+ this._balanceAndProxyAllowanceLazyStore.deleteBalance(signedOrder.makerAssetData, signedOrder.makerAddress);
+ this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(
+ signedOrder.makerAssetData,
+ signedOrder.makerAddress,
+ );
+ this._balanceAndProxyAllowanceLazyStore.deleteBalance(signedOrder.takerAssetData, signedOrder.takerAddress);
+ this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(
+ signedOrder.takerAssetData,
+ signedOrder.takerAddress,
+ );
- const zrxTokenAddress = this._getZRXTokenAddress();
+ const zrxAssetData = this._orderFilledCancelledLazyStore.getZRXAssetData();
if (!signedOrder.makerFee.isZero()) {
- this._balanceAndProxyAllowanceLazyStore.deleteBalance(zrxTokenAddress, signedOrder.maker);
- this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(zrxTokenAddress, signedOrder.maker);
+ this._balanceAndProxyAllowanceLazyStore.deleteBalance(zrxAssetData, signedOrder.makerAddress);
+ this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(zrxAssetData, signedOrder.makerAddress);
}
if (!signedOrder.takerFee.isZero()) {
- this._balanceAndProxyAllowanceLazyStore.deleteBalance(zrxTokenAddress, signedOrder.taker);
- this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(zrxTokenAddress, signedOrder.taker);
+ this._balanceAndProxyAllowanceLazyStore.deleteBalance(zrxAssetData, signedOrder.takerAddress);
+ this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(zrxAssetData, signedOrder.takerAddress);
}
}
private _onOrderExpired(orderHash: string): void {
@@ -239,89 +260,122 @@ export class OrderWatcher {
}
return;
}
- const log = logIfExists as LogEntryEvent; // At this moment we are sure that no error occured and log is defined.
- const maybeDecodedLog = this._web3Wrapper.abiDecoder.tryToDecodeLogOrNoop<ContractEventArgs>(log);
+ 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 = !_.isUndefined(((maybeDecodedLog as any) as LogWithDecodedArgs<ContractEventArgs>).event);
if (!isLogDecoded) {
return; // noop
}
const decodedLog = (maybeDecodedLog as any) as LogWithDecodedArgs<ContractEventArgs>;
- let makerToken: string;
- let makerAddress: string;
switch (decodedLog.event) {
- case TokenEvents.Approval: {
- // Invalidate cache
- // tslint:disable-next-line:no-unnecessary-type-assertion
- const args = decodedLog.args as TokenApprovalEventArgs;
- this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(decodedLog.address, args._owner);
- // Revalidate orders
- makerToken = decodedLog.address;
- makerAddress = args._owner;
- if (
- !_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
- !_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])
- ) {
- const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
+ case ERC20TokenEvents.Approval:
+ case ERC721TokenEvents.Approval: {
+ // ERC20 and ERC721 Transfer events have the same name so we need to distinguish them by args
+ if (!_.isUndefined(decodedLog.args._value)) {
+ // ERC20
+ // Invalidate cache
+ const args = decodedLog.args as ERC20TokenApprovalEventArgs;
+ const tokenAssetData = assetDataUtils.encodeERC20AssetData(decodedLog.address);
+ this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(tokenAssetData, args._owner);
+ // Revalidate orders
+ const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker(
+ args._owner,
+ tokenAssetData,
+ );
await this._emitRevalidateOrdersAsync(orderHashes);
+ break;
+ } else {
+ // ERC721
+ // Invalidate cache
+ const args = decodedLog.args as ERC721TokenApprovalEventArgs;
+ const tokenAssetData = assetDataUtils.encodeERC721AssetData(decodedLog.address, args._tokenId);
+ this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(tokenAssetData, args._owner);
+ // Revalidate orders
+ const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker(
+ args._owner,
+ tokenAssetData,
+ );
+ await this._emitRevalidateOrdersAsync(orderHashes);
+ break;
}
- break;
}
- case TokenEvents.Transfer: {
- // Invalidate cache
- // tslint:disable-next-line:no-unnecessary-type-assertion
- const args = decodedLog.args as TokenTransferEventArgs;
- this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._from);
- this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._to);
- // Revalidate orders
- makerToken = decodedLog.address;
- makerAddress = args._from;
- if (
- !_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
- !_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])
- ) {
- const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
+ case ERC20TokenEvents.Transfer:
+ case ERC721TokenEvents.Transfer: {
+ // ERC20 and ERC721 Transfer events have the same name so we need to distinguish them by args
+ if (!_.isUndefined(decodedLog.args._value)) {
+ // ERC20
+ // Invalidate cache
+ const args = decodedLog.args as ERC20TokenTransferEventArgs;
+ const tokenAssetData = assetDataUtils.encodeERC20AssetData(decodedLog.address);
+ this._balanceAndProxyAllowanceLazyStore.deleteBalance(tokenAssetData, args._from);
+ this._balanceAndProxyAllowanceLazyStore.deleteBalance(tokenAssetData, args._to);
+ // Revalidate orders
+ const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker(
+ args._from,
+ tokenAssetData,
+ );
await this._emitRevalidateOrdersAsync(orderHashes);
+ break;
+ } else {
+ // ERC721
+ // Invalidate cache
+ const args = decodedLog.args as ERC721TokenTransferEventArgs;
+ const tokenAssetData = assetDataUtils.encodeERC721AssetData(decodedLog.address, args._tokenId);
+ this._balanceAndProxyAllowanceLazyStore.deleteBalance(tokenAssetData, args._from);
+ this._balanceAndProxyAllowanceLazyStore.deleteBalance(tokenAssetData, args._to);
+ // Revalidate orders
+ const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker(
+ args._from,
+ tokenAssetData,
+ );
+ await this._emitRevalidateOrdersAsync(orderHashes);
+ 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);
break;
}
- case EtherTokenEvents.Deposit: {
+ case WETH9Events.Deposit: {
// Invalidate cache
- // tslint:disable-next-line:no-unnecessary-type-assertion
- const args = decodedLog.args as EtherTokenDepositEventArgs;
- this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._owner);
+ const args = decodedLog.args as WETH9DepositEventArgs;
+ const tokenAssetData = assetDataUtils.encodeERC20AssetData(decodedLog.address);
+ this._balanceAndProxyAllowanceLazyStore.deleteBalance(tokenAssetData, args._owner);
// Revalidate orders
- makerToken = decodedLog.address;
- makerAddress = args._owner;
- if (
- !_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
- !_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])
- ) {
- const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
- await this._emitRevalidateOrdersAsync(orderHashes);
- }
+ const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker(
+ args._owner,
+ tokenAssetData,
+ );
+ await this._emitRevalidateOrdersAsync(orderHashes);
break;
}
- case EtherTokenEvents.Withdrawal: {
+ case WETH9Events.Withdrawal: {
// Invalidate cache
- // tslint:disable-next-line:no-unnecessary-type-assertion
- const args = decodedLog.args as EtherTokenWithdrawalEventArgs;
- this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._owner);
+ const args = decodedLog.args as WETH9WithdrawalEventArgs;
+ const tokenAssetData = assetDataUtils.encodeERC20AssetData(decodedLog.address);
+ this._balanceAndProxyAllowanceLazyStore.deleteBalance(tokenAssetData, args._owner);
// Revalidate orders
- makerToken = decodedLog.address;
- makerAddress = args._owner;
- if (
- !_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
- !_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])
- ) {
- const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
- await this._emitRevalidateOrdersAsync(orderHashes);
- }
+ const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker(
+ args._owner,
+ tokenAssetData,
+ );
+ await this._emitRevalidateOrdersAsync(orderHashes);
break;
}
- case ExchangeEvents.LogFill: {
+ case ExchangeEvents.Fill: {
// Invalidate cache
- // tslint:disable-next-line:no-unnecessary-type-assertion
- const args = decodedLog.args as ExchangeLogFillEventArgs;
+ const args = decodedLog.args as ExchangeFillEventArgs;
this._orderFilledCancelledLazyStore.deleteFilledTakerAmount(args.orderHash);
// Revalidate orders
const orderHash = args.orderHash;
@@ -331,11 +385,10 @@ export class OrderWatcher {
}
break;
}
- case ExchangeEvents.LogCancel: {
+ case ExchangeEvents.Cancel: {
// Invalidate cache
- // tslint:disable-next-line:no-unnecessary-type-assertion
- const args = decodedLog.args as ExchangeLogCancelEventArgs;
- this._orderFilledCancelledLazyStore.deleteCancelledTakerAmount(args.orderHash);
+ const args = decodedLog.args as ExchangeCancelEventArgs;
+ this._orderFilledCancelledLazyStore.deleteIsCancelled(args.orderHash);
// Revalidate orders
const orderHash = args.orderHash;
const isOrderWatched = !_.isUndefined(this._orderByOrderHash[orderHash]);
@@ -344,8 +397,16 @@ export class OrderWatcher {
}
break;
}
- case ExchangeEvents.LogError:
- return; // noop
+ 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);
+ break;
+ }
default:
throw errorUtils.spawnSwitchErr('decodedLog.event', decodedLog.event);
@@ -356,7 +417,7 @@ export class OrderWatcher {
const signedOrder = this._orderByOrderHash[orderHash];
// 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.getOrderStateAsync(signedOrder);
+ const orderState = await this._orderStateUtils.getOpenOrderStateAsync(signedOrder);
if (_.isUndefined(this._callbackIfExists)) {
break; // Unsubscribe was called
}
@@ -369,31 +430,4 @@ export class OrderWatcher {
this._callbackIfExists(null, orderState);
}
}
- private _addToDependentOrderHashes(signedOrder: SignedOrder, orderHash: string): void {
- 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);
- const zrxTokenAddress = this._getZRXTokenAddress();
- if (_.isUndefined(this._dependentOrderHashes[signedOrder.maker][zrxTokenAddress])) {
- this._dependentOrderHashes[signedOrder.maker][zrxTokenAddress] = new Set();
- }
- this._dependentOrderHashes[signedOrder.maker][zrxTokenAddress].add(orderHash);
- }
- private _removeFromDependentOrderHashes(makerAddress: string, tokenAddress: string, orderHash: string): void {
- this._dependentOrderHashes[makerAddress][tokenAddress].delete(orderHash);
- if (this._dependentOrderHashes[makerAddress][tokenAddress].size === 0) {
- delete this._dependentOrderHashes[makerAddress][tokenAddress];
- }
- if (_.isEmpty(this._dependentOrderHashes[makerAddress])) {
- delete this._dependentOrderHashes[makerAddress];
- }
- }
- private _getZRXTokenAddress(): string {
- const zrxTokenAddress = this._orderFilledCancelledLazyStore.getZRXTokenAddress();
- return zrxTokenAddress;
- }
}
diff --git a/packages/order-watcher/src/schemas/order_watcher_partial_config_schema.ts b/packages/order-watcher/src/schemas/order_watcher_partial_config_schema.ts
new file mode 100644
index 000000000..bc7d40524
--- /dev/null
+++ b/packages/order-watcher/src/schemas/order_watcher_partial_config_schema.ts
@@ -0,0 +1,13 @@
+export const orderWatcherPartialConfigSchema = {
+ id: '/OrderWatcherPartialConfigSchema',
+ properties: {
+ stateLayer: { $ref: '/BlockParam' },
+ orderExpirationCheckingIntervalMs: { type: 'number' },
+ eventPollingIntervalMs: { type: 'number' },
+ expirationMarginMs: { type: 'number' },
+ cleanupJobIntervalMs: { type: 'number' },
+ isVerbose: { type: 'boolean' },
+ },
+ type: 'object',
+ required: [],
+};
diff --git a/packages/order-watcher/src/types.ts b/packages/order-watcher/src/types.ts
index fd71267a2..27d892985 100644
--- a/packages/order-watcher/src/types.ts
+++ b/packages/order-watcher/src/types.ts
@@ -1,4 +1,5 @@
-import { LogEntryEvent, OrderState } from '@0xproject/types';
+import { OrderState } from '@0xproject/types';
+import { LogEntryEvent } from 'ethereum-types';
export enum OrderWatcherError {
SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT',
@@ -13,13 +14,14 @@ export type EventWatcherCallback = (err: null | Error, log?: LogEntryEvent) => v
* expirationMarginMs: Amount of time before order expiry that you'd like to be notified
* of an orders expiration. Default=0.
* cleanupJobIntervalMs: How often to run a cleanup job which revalidates all the orders. Default=1hr.
+ * isVerbose: Weather the order watcher should be verbose. Default=true.
*/
export interface OrderWatcherConfig {
- orderExpirationCheckingIntervalMs?: number;
- eventPollingIntervalMs?: number;
- expirationMarginMs?: number;
- cleanupJobIntervalMs?: number;
- isVerbose?: boolean;
+ orderExpirationCheckingIntervalMs: number;
+ eventPollingIntervalMs: number;
+ expirationMarginMs: number;
+ cleanupJobIntervalMs: number;
+ isVerbose: boolean;
}
export type OnOrderStateChangeCallback = (err: Error | null, orderState?: OrderState) => void;
diff --git a/packages/order-watcher/src/utils/assert.ts b/packages/order-watcher/src/utils/assert.ts
index 4a1441474..a891a60d2 100644
--- a/packages/order-watcher/src/utils/assert.ts
+++ b/packages/order-watcher/src/utils/assert.ts
@@ -5,13 +5,19 @@ import { Schema } from '@0xproject/json-schemas';
import { ECSignature } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
// tslint:enable:no-unused-variable
+import { Provider } from 'ethereum-types';
-import { isValidSignature } from '@0xproject/order-utils';
+import { isValidSignatureAsync } from '@0xproject/order-utils';
export const assert = {
...sharedAssert,
- isValidSignature(orderHash: string, ecSignature: ECSignature, signerAddress: string): void {
- const isValid = isValidSignature(orderHash, ecSignature, signerAddress);
+ async isValidSignatureAsync(
+ provider: Provider,
+ orderHash: string,
+ signature: string,
+ signerAddress: string,
+ ): Promise<void> {
+ const isValid = await isValidSignatureAsync(provider, orderHash, signature, signerAddress);
assert.assert(isValid, `Expected order with hash '${orderHash}' to have a valid signature`);
},
};