aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/contract-wrappers/src/fetchers/asset_balance_and_proxy_allowance_fetcher.ts132
-rw-r--r--packages/fill-scenarios/src/fill_scenarios.ts59
-rw-r--r--packages/order-utils/src/asset_data_utils.ts36
-rw-r--r--packages/order-utils/src/constants.ts107
-rw-r--r--packages/order-utils/src/exchange_transfer_simulator.ts2
-rw-r--r--packages/order-utils/src/order_state_utils.ts61
-rw-r--r--packages/order-utils/test/asset_data_utils_test.ts4
-rw-r--r--packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts67
-rw-r--r--packages/order-watcher/src/order_watcher/order_watcher.ts33
-rw-r--r--packages/pipeline/src/parsers/events/exchange_events.ts48
-rw-r--r--packages/pipeline/src/parsers/sra_orders/index.ts26
11 files changed, 247 insertions, 328 deletions
diff --git a/packages/contract-wrappers/src/fetchers/asset_balance_and_proxy_allowance_fetcher.ts b/packages/contract-wrappers/src/fetchers/asset_balance_and_proxy_allowance_fetcher.ts
index 376004f52..1ff130a48 100644
--- a/packages/contract-wrappers/src/fetchers/asset_balance_and_proxy_allowance_fetcher.ts
+++ b/packages/contract-wrappers/src/fetchers/asset_balance_and_proxy_allowance_fetcher.ts
@@ -1,6 +1,4 @@
-// tslint:disable:no-unnecessary-type-assertion
import { AbstractBalanceAndProxyAllowanceFetcher, assetDataUtils } from '@0x/order-utils';
-import { AssetProxyId, ERC20AssetData, ERC721AssetData, MultiAssetData } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { BlockParamLiteral } from 'ethereum-types';
import * as _ from 'lodash';
@@ -20,99 +18,73 @@ export class AssetBalanceAndProxyAllowanceFetcher implements AbstractBalanceAndP
public async getBalanceAsync(assetData: string, userAddress: string): Promise<BigNumber> {
const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
let balance: BigNumber | undefined;
- switch (decodedAssetData.assetProxyId) {
- case AssetProxyId.ERC20:
- const decodedERC20AssetData = decodedAssetData as ERC20AssetData;
- balance = await this._erc20Token.getBalanceAsync(decodedERC20AssetData.tokenAddress, userAddress, {
+ if (assetDataUtils.isERC20AssetData(decodedAssetData)) {
+ balance = await this._erc20Token.getBalanceAsync(decodedAssetData.tokenAddress, userAddress, {
+ defaultBlock: this._stateLayer,
+ });
+ } else if (assetDataUtils.isERC721AssetData(decodedAssetData)) {
+ const tokenOwner = await this._erc721Token.getOwnerOfAsync(
+ decodedAssetData.tokenAddress,
+ decodedAssetData.tokenId,
+ {
defaultBlock: this._stateLayer,
- });
- break;
- case AssetProxyId.ERC721:
- const decodedERC721AssetData = decodedAssetData as ERC721AssetData;
- const tokenOwner = await this._erc721Token.getOwnerOfAsync(
- decodedERC721AssetData.tokenAddress,
- decodedERC721AssetData.tokenId,
- {
- defaultBlock: this._stateLayer,
- },
- );
- balance = tokenOwner === userAddress ? new BigNumber(1) : new BigNumber(0);
- break;
- case AssetProxyId.MultiAsset:
- // The `balance` for MultiAssetData is the total units of the entire `assetData` that are held by the `userAddress`.
- for (const [
- index,
+ },
+ );
+ balance = tokenOwner === userAddress ? new BigNumber(1) : new BigNumber(0);
+ } else if (assetDataUtils.isMultiAssetData(decodedAssetData)) {
+ // The `balance` for MultiAssetData is the total units of the entire `assetData` that are held by the `userAddress`.
+ for (const [index, nestedAssetDataElement] of decodedAssetData.nestedAssetData.entries()) {
+ const nestedAmountElement = decodedAssetData.amounts[index];
+ const nestedAssetBalance = (await this.getBalanceAsync(
nestedAssetDataElement,
- ] of (decodedAssetData as MultiAssetData).nestedAssetData.entries()) {
- const nestedAmountElement = (decodedAssetData as MultiAssetData).amounts[index];
- const nestedAssetBalance = (await this.getBalanceAsync(
- nestedAssetDataElement,
- userAddress,
- )).dividedToIntegerBy(nestedAmountElement);
- if (_.isUndefined(balance) || nestedAssetBalance.lessThan(balance)) {
- balance = nestedAssetBalance;
- }
+ userAddress,
+ )).dividedToIntegerBy(nestedAmountElement);
+ if (_.isUndefined(balance) || nestedAssetBalance.lessThan(balance)) {
+ balance = nestedAssetBalance;
}
- break;
- default:
- throw new Error(`Proxy with id ${decodedAssetData.assetProxyId} not supported`);
+ }
}
return balance as BigNumber;
}
public async getProxyAllowanceAsync(assetData: string, userAddress: string): Promise<BigNumber> {
const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
let proxyAllowance: BigNumber | undefined;
- switch (decodedAssetData.assetProxyId) {
- case AssetProxyId.ERC20:
- const decodedERC20AssetData = decodedAssetData as ERC20AssetData;
- proxyAllowance = await this._erc20Token.getProxyAllowanceAsync(
- decodedERC20AssetData.tokenAddress,
- userAddress,
- {
- defaultBlock: this._stateLayer,
- },
- );
- break;
- case AssetProxyId.ERC721:
- const decodedERC721AssetData = decodedAssetData as ERC721AssetData;
- const isApprovedForAll = await this._erc721Token.isProxyApprovedForAllAsync(
- decodedERC721AssetData.tokenAddress,
- userAddress,
+ if (assetDataUtils.isERC20AssetData(decodedAssetData)) {
+ proxyAllowance = await this._erc20Token.getProxyAllowanceAsync(decodedAssetData.tokenAddress, userAddress, {
+ defaultBlock: this._stateLayer,
+ });
+ } else if (assetDataUtils.isERC721AssetData(decodedAssetData)) {
+ const isApprovedForAll = await this._erc721Token.isProxyApprovedForAllAsync(
+ decodedAssetData.tokenAddress,
+ userAddress,
+ {
+ defaultBlock: this._stateLayer,
+ },
+ );
+ if (isApprovedForAll) {
+ return new BigNumber(this._erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
+ } else {
+ const isApproved = await this._erc721Token.isProxyApprovedAsync(
+ decodedAssetData.tokenAddress,
+ decodedAssetData.tokenId,
{
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,
- },
- );
- proxyAllowance = isApproved ? new BigNumber(1) : new BigNumber(0);
- }
- break;
- case AssetProxyId.MultiAsset:
- // The `proxyAllowance` for MultiAssetData is the total units of the entire `assetData` that the proxies have been approved to spend by the `userAddress`.
- for (const [
- index,
+ proxyAllowance = isApproved ? new BigNumber(1) : new BigNumber(0);
+ }
+ } else if (assetDataUtils.isMultiAssetData(decodedAssetData)) {
+ // The `proxyAllowance` for MultiAssetData is the total units of the entire `assetData` that the proxies have been approved to spend by the `userAddress`.
+ for (const [index, nestedAssetDataElement] of decodedAssetData.nestedAssetData.entries()) {
+ const nestedAmountElement = decodedAssetData.amounts[index];
+ const nestedAssetAllowance = (await this.getProxyAllowanceAsync(
nestedAssetDataElement,
- ] of (decodedAssetData as MultiAssetData).nestedAssetData.entries()) {
- const nestedAmountElement = (decodedAssetData as MultiAssetData).amounts[index];
- const nestedAssetAllowance = (await this.getProxyAllowanceAsync(
- nestedAssetDataElement,
- userAddress,
- )).dividedToIntegerBy(nestedAmountElement);
- if (_.isUndefined(proxyAllowance) || nestedAssetAllowance.lessThan(proxyAllowance)) {
- proxyAllowance = nestedAssetAllowance;
- }
+ userAddress,
+ )).dividedToIntegerBy(nestedAmountElement);
+ if (_.isUndefined(proxyAllowance) || nestedAssetAllowance.lessThan(proxyAllowance)) {
+ proxyAllowance = nestedAssetAllowance;
}
- break;
- default:
- throw new Error(`Proxy with id ${decodedAssetData.assetProxyId} not supported`);
+ }
}
return proxyAllowance as BigNumber;
}
diff --git a/packages/fill-scenarios/src/fill_scenarios.ts b/packages/fill-scenarios/src/fill_scenarios.ts
index 2e87e60cc..ce1f7f9ff 100644
--- a/packages/fill-scenarios/src/fill_scenarios.ts
+++ b/packages/fill-scenarios/src/fill_scenarios.ts
@@ -2,14 +2,7 @@ import { DummyERC20TokenContract, DummyERC721TokenContract, ExchangeContract } f
import * as artifacts from '@0x/contract-artifacts';
import { assetDataUtils } from '@0x/order-utils';
import { orderFactory } from '@0x/order-utils/lib/src/order_factory';
-import {
- AssetProxyId,
- ERC20AssetData,
- ERC721AssetData,
- MultiAssetData,
- OrderWithoutExchangeAddress,
- SignedOrder,
-} from '@0x/types';
+import { OrderWithoutExchangeAddress, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { Provider } from 'ethereum-types';
@@ -280,42 +273,24 @@ export class FillScenarios {
amount: BigNumber,
): Promise<void> {
const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
- switch (decodedAssetData.assetProxyId) {
- case AssetProxyId.ERC20:
- await this._increaseERC20BalanceAndAllowanceAsync(
- // tslint:disable-next-line:no-unnecessary-type-assertion
- (decodedAssetData as ERC20AssetData).tokenAddress,
- userAddress,
- amount,
- );
- break;
- case AssetProxyId.ERC721:
- await this._increaseERC721BalanceAndAllowanceAsync(
- // tslint:disable-next-line:no-unnecessary-type-assertion
- (decodedAssetData as ERC721AssetData).tokenAddress,
+ if (assetDataUtils.isERC20AssetData(decodedAssetData)) {
+ await this._increaseERC20BalanceAndAllowanceAsync(decodedAssetData.tokenAddress, userAddress, amount);
+ } else if (assetDataUtils.isERC721AssetData(decodedAssetData)) {
+ await this._increaseERC721BalanceAndAllowanceAsync(
+ decodedAssetData.tokenAddress,
+ userAddress,
+ decodedAssetData.tokenId,
+ );
+ } else if (assetDataUtils.isMultiAssetData(decodedAssetData)) {
+ for (const [index, nestedAssetDataElement] of decodedAssetData.nestedAssetData.entries()) {
+ const amountsElement = decodedAssetData.amounts[index];
+ const totalAmount = amount.times(amountsElement);
+ await this._increaseBalanceAndAllowanceWithAssetDataAsync(
+ nestedAssetDataElement,
userAddress,
- // tslint:disable-next-line:no-unnecessary-type-assertion
- (decodedAssetData as ERC721AssetData).tokenId,
+ totalAmount,
);
- break;
- case AssetProxyId.MultiAsset:
- for (const [
- index,
- nestedAssetDataElement,
- // tslint:disable-next-line:no-unnecessary-type-assertion
- ] of (decodedAssetData as MultiAssetData).nestedAssetData.entries()) {
- // tslint:disable-next-line:no-unnecessary-type-assertion
- const amountsElement = (decodedAssetData as MultiAssetData).amounts[index];
- const totalAmount = amount.times(amountsElement);
- await this._increaseBalanceAndAllowanceWithAssetDataAsync(
- nestedAssetDataElement,
- userAddress,
- totalAmount,
- );
- }
- break;
- default:
- throw new Error(`Proxy with id ${decodedAssetData.assetProxyId} not supported`);
+ }
}
}
}
diff --git a/packages/order-utils/src/asset_data_utils.ts b/packages/order-utils/src/asset_data_utils.ts
index c2929d426..0526c3d00 100644
--- a/packages/order-utils/src/asset_data_utils.ts
+++ b/packages/order-utils/src/asset_data_utils.ts
@@ -7,7 +7,6 @@ import {
SingleAssetData,
} from '@0x/types';
import { AbiEncoder, BigNumber } from '@0x/utils';
-import { MethodAbi } from 'ethereum-types';
import * as _ from 'lodash';
import { constants } from './constants';
@@ -23,7 +22,7 @@ export const assetDataUtils = {
* @return The hex encoded assetData string
*/
encodeERC20AssetData(tokenAddress: string): string {
- const abiEncoder = new AbiEncoder.Method(constants.ERC20_METHOD_ABI as MethodAbi);
+ const abiEncoder = new AbiEncoder.Method(constants.ERC20_METHOD_ABI);
const args = [tokenAddress];
const assetData = abiEncoder.encode(args, encodingRules);
return assetData;
@@ -36,7 +35,7 @@ export const assetDataUtils = {
decodeERC20AssetData(assetData: string): ERC20AssetData {
assetDataUtils.assertIsERC20AssetData(assetData);
const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData);
- const abiEncoder = new AbiEncoder.Method(constants.ERC20_METHOD_ABI as MethodAbi);
+ const abiEncoder = new AbiEncoder.Method(constants.ERC20_METHOD_ABI);
const decodedAssetData = abiEncoder.decode(assetData, decodingRules);
return {
assetProxyId,
@@ -52,7 +51,7 @@ export const assetDataUtils = {
* @return The hex encoded assetData string
*/
encodeERC721AssetData(tokenAddress: string, tokenId: BigNumber): string {
- const abiEncoder = new AbiEncoder.Method(constants.ERC721_METHOD_ABI as MethodAbi);
+ const abiEncoder = new AbiEncoder.Method(constants.ERC721_METHOD_ABI);
const args = [tokenAddress, tokenId];
const assetData = abiEncoder.encode(args, encodingRules);
return assetData;
@@ -65,7 +64,7 @@ export const assetDataUtils = {
decodeERC721AssetData(assetData: string): ERC721AssetData {
assetDataUtils.assertIsERC721AssetData(assetData);
const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData);
- const abiEncoder = new AbiEncoder.Method(constants.ERC721_METHOD_ABI as MethodAbi);
+ const abiEncoder = new AbiEncoder.Method(constants.ERC721_METHOD_ABI);
const decodedAssetData = abiEncoder.decode(assetData, decodingRules);
return {
assetProxyId,
@@ -90,7 +89,7 @@ export const assetDataUtils = {
);
}
_.forEach(nestedAssetData, assetDataElement => assetDataUtils.validateAssetDataOrThrow(assetDataElement));
- const abiEncoder = new AbiEncoder.Method(constants.MULTI_ASSET_METHOD_ABI as MethodAbi);
+ const abiEncoder = new AbiEncoder.Method(constants.MULTI_ASSET_METHOD_ABI);
const args = [amounts, nestedAssetData];
const assetData = abiEncoder.encode(args, encodingRules);
return assetData;
@@ -103,7 +102,7 @@ export const assetDataUtils = {
decodeMultiAssetData(assetData: string): MultiAssetData {
assetDataUtils.assertIsMultiAssetData(assetData);
const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData);
- const abiEncoder = new AbiEncoder.Method(constants.MULTI_ASSET_METHOD_ABI as MethodAbi);
+ const abiEncoder = new AbiEncoder.Method(constants.MULTI_ASSET_METHOD_ABI);
const decodedAssetData = abiEncoder.decode(assetData, decodingRules);
// TODO(abandeali1): fix return types for `AbiEncoder.Method.decode` so that we can remove type assertion
const amounts = (decodedAssetData as any).amounts;
@@ -138,7 +137,7 @@ export const assetDataUtils = {
nestedAssetDataElement,
);
amounts.push(
- _.map(recursivelyDecodedAssetData.amounts as BigNumber[], amountElement =>
+ _.map(recursivelyDecodedAssetData.amounts, amountElement =>
amountElement.times(decodedAssetData.amounts[index]),
),
);
@@ -182,6 +181,27 @@ export const assetDataUtils = {
return assetProxyId;
},
/**
+ * Checks if the decoded asset data is valid ERC20 data
+ * @param decodedAssetData The decoded asset data to check
+ */
+ isERC20AssetData(decodedAssetData: SingleAssetData | MultiAssetData): decodedAssetData is ERC20AssetData {
+ return decodedAssetData.assetProxyId === AssetProxyId.ERC20;
+ },
+ /**
+ * Checks if the decoded asset data is valid ERC721 data
+ * @param decodedAssetData The decoded asset data to check
+ */
+ isERC721AssetData(decodedAssetData: SingleAssetData | MultiAssetData): decodedAssetData is ERC721AssetData {
+ return decodedAssetData.assetProxyId === AssetProxyId.ERC721;
+ },
+ /**
+ * Checks if the decoded asset data is valid MultiAsset data
+ * @param decodedAssetData The decoded asset data to check
+ */
+ isMultiAssetData(decodedAssetData: SingleAssetData | MultiAssetData): decodedAssetData is MultiAssetData {
+ return decodedAssetData.assetProxyId === AssetProxyId.MultiAsset;
+ },
+ /**
* Throws if the length or assetProxyId are invalid for the ERC20Proxy.
* @param assetData Hex encoded assetData string
*/
diff --git a/packages/order-utils/src/constants.ts b/packages/order-utils/src/constants.ts
index 1248a5576..a9a687719 100644
--- a/packages/order-utils/src/constants.ts
+++ b/packages/order-utils/src/constants.ts
@@ -1,4 +1,58 @@
import { BigNumber } from '@0x/utils';
+import { MethodAbi } from 'ethereum-types';
+
+const ERC20_METHOD_ABI: MethodAbi = {
+ constant: false,
+ inputs: [
+ {
+ name: 'tokenContract',
+ type: 'address',
+ },
+ ],
+ name: 'ERC20Token',
+ outputs: [],
+ payable: false,
+ stateMutability: 'nonpayable',
+ type: 'function',
+};
+
+const ERC721_METHOD_ABI: MethodAbi = {
+ constant: false,
+ inputs: [
+ {
+ name: 'tokenContract',
+ type: 'address',
+ },
+ {
+ name: 'tokenId',
+ type: 'uint256',
+ },
+ ],
+ name: 'ERC721Token',
+ outputs: [],
+ payable: false,
+ stateMutability: 'nonpayable',
+ type: 'function',
+};
+
+const MULTI_ASSET_METHOD_ABI: MethodAbi = {
+ constant: false,
+ inputs: [
+ {
+ name: 'amounts',
+ type: 'uint256[]',
+ },
+ {
+ name: 'nestedAssetData',
+ type: 'bytes[]',
+ },
+ ],
+ name: 'MultiAsset',
+ outputs: [],
+ payable: false,
+ stateMutability: 'nonpayable',
+ type: 'function',
+};
export const constants = {
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
@@ -49,54 +103,7 @@ export const constants = {
{ name: 'data', type: 'bytes' },
],
},
- ERC20_METHOD_ABI: {
- constant: false,
- inputs: [
- {
- name: 'tokenContract',
- type: 'address',
- },
- ],
- name: 'ERC20Token',
- outputs: [],
- payable: false,
- stateMutability: 'nonpayable',
- type: 'function',
- },
- ERC721_METHOD_ABI: {
- constant: false,
- inputs: [
- {
- name: 'tokenContract',
- type: 'address',
- },
- {
- name: 'tokenId',
- type: 'uint256',
- },
- ],
- name: 'ERC721Token',
- outputs: [],
- payable: false,
- stateMutability: 'nonpayable',
- type: 'function',
- },
- MULTI_ASSET_METHOD_ABI: {
- constant: false,
- inputs: [
- {
- name: 'amounts',
- type: 'uint256[]',
- },
- {
- name: 'nestedAssetData',
- type: 'bytes[]',
- },
- ],
- name: 'MultiAsset',
- outputs: [],
- payable: false,
- stateMutability: 'nonpayable',
- type: 'function',
- },
+ ERC20_METHOD_ABI,
+ ERC721_METHOD_ABI,
+ MULTI_ASSET_METHOD_ABI,
};
diff --git a/packages/order-utils/src/exchange_transfer_simulator.ts b/packages/order-utils/src/exchange_transfer_simulator.ts
index 0a948fd1f..06621fd9e 100644
--- a/packages/order-utils/src/exchange_transfer_simulator.ts
+++ b/packages/order-utils/src/exchange_transfer_simulator.ts
@@ -108,7 +108,7 @@ export class ExchangeTransferSimulator {
const amountsElement = decodedAssetData.amounts[index];
const totalAmount = amountInBaseUnits.times(amountsElement);
await this.transferFromAsync(
- nestedAssetDataElement as string,
+ nestedAssetDataElement,
from,
to,
totalAmount,
diff --git a/packages/order-utils/src/order_state_utils.ts b/packages/order-utils/src/order_state_utils.ts
index 9e3e228ba..389419587 100644
--- a/packages/order-utils/src/order_state_utils.ts
+++ b/packages/order-utils/src/order_state_utils.ts
@@ -1,14 +1,11 @@
import {
- AssetProxyId,
ExchangeContractErrs,
- MultiAssetData,
ObjectMap,
OrderRelevantState,
OrderState,
OrderStateInvalid,
OrderStateValid,
SignedOrder,
- SingleAssetData,
} from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
@@ -310,22 +307,16 @@ export class OrderStateUtils {
): Promise<ObjectMap<BigNumber>> {
const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
let balances: ObjectMap<BigNumber> = { ...initialBalances };
- switch (decodedAssetData.assetProxyId) {
- case AssetProxyId.ERC20:
- case AssetProxyId.ERC721:
- const balance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync(assetData, traderAddress);
- const tokenAddress = (decodedAssetData as SingleAssetData).tokenAddress;
- balances[tokenAddress] = _.isUndefined(initialBalances[tokenAddress])
- ? balance
- : balances[tokenAddress].add(balance);
- break;
- case AssetProxyId.MultiAsset:
- for (const assetDataElement of (decodedAssetData as MultiAssetData).nestedAssetData) {
- balances = await this._getAssetBalancesAsync(assetDataElement, traderAddress, balances);
- }
- break;
- default:
- throw new Error(`Proxy with id ${decodedAssetData.assetProxyId} not supported`);
+ if (assetDataUtils.isERC20AssetData(decodedAssetData) || assetDataUtils.isERC721AssetData(decodedAssetData)) {
+ const balance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync(assetData, traderAddress);
+ const tokenAddress = decodedAssetData.tokenAddress;
+ balances[tokenAddress] = _.isUndefined(initialBalances[tokenAddress])
+ ? balance
+ : balances[tokenAddress].add(balance);
+ } else if (assetDataUtils.isMultiAssetData(decodedAssetData)) {
+ for (const assetDataElement of decodedAssetData.nestedAssetData) {
+ balances = await this._getAssetBalancesAsync(assetDataElement, traderAddress, balances);
+ }
}
return balances;
}
@@ -336,25 +327,19 @@ export class OrderStateUtils {
): Promise<ObjectMap<BigNumber>> {
const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
let allowances: ObjectMap<BigNumber> = { ...initialAllowances };
- switch (decodedAssetData.assetProxyId) {
- case AssetProxyId.ERC20:
- case AssetProxyId.ERC721:
- const allowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync(
- assetData,
- traderAddress,
- );
- const tokenAddress = (decodedAssetData as SingleAssetData).tokenAddress;
- allowances[tokenAddress] = _.isUndefined(initialAllowances[tokenAddress])
- ? allowance
- : allowances[tokenAddress].add(allowance);
- break;
- case AssetProxyId.MultiAsset:
- for (const assetDataElement of (decodedAssetData as MultiAssetData).nestedAssetData) {
- allowances = await this._getAssetBalancesAsync(assetDataElement, traderAddress, allowances);
- }
- break;
- default:
- throw new Error(`Proxy with id ${decodedAssetData.assetProxyId} not supported`);
+ if (assetDataUtils.isERC20AssetData(decodedAssetData) || assetDataUtils.isERC721AssetData(decodedAssetData)) {
+ const allowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync(
+ assetData,
+ traderAddress,
+ );
+ const tokenAddress = decodedAssetData.tokenAddress;
+ allowances[tokenAddress] = _.isUndefined(initialAllowances[tokenAddress])
+ ? allowance
+ : allowances[tokenAddress].add(allowance);
+ } else if (assetDataUtils.isMultiAssetData(decodedAssetData)) {
+ for (const assetDataElement of decodedAssetData.nestedAssetData) {
+ allowances = await this._getAssetBalancesAsync(assetDataElement, traderAddress, allowances);
+ }
}
return allowances;
}
diff --git a/packages/order-utils/test/asset_data_utils_test.ts b/packages/order-utils/test/asset_data_utils_test.ts
index ebc5bdeac..c498c5a00 100644
--- a/packages/order-utils/test/asset_data_utils_test.ts
+++ b/packages/order-utils/test/asset_data_utils_test.ts
@@ -27,7 +27,6 @@ const KNOWN_MULTI_ASSET_ENCODING = {
'0x94cfcdd7000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000',
};
-// tslint:disable:no-unnecessary-type-assertion
describe('assetDataUtils', () => {
it('should encode ERC20', () => {
const assetData = assetDataUtils.encodeERC20AssetData(KNOWN_ERC20_ENCODING.address);
@@ -69,6 +68,7 @@ describe('assetDataUtils', () => {
expect(decodedAssetData.assetProxyId).to.equal(AssetProxyId.MultiAsset);
expect(decodedAssetData.amounts).to.deep.equal(KNOWN_MULTI_ASSET_ENCODING.amounts);
const decodedErc20AssetData = decodedAssetData.nestedAssetData[0];
+ // tslint:disable-next-line:no-unnecessary-type-assertion
const decodedErc721AssetData = decodedAssetData.nestedAssetData[1] as ERC721AssetData;
expect(decodedErc20AssetData.tokenAddress).to.equal(KNOWN_ERC20_ENCODING.address);
expect(decodedErc20AssetData.assetProxyId).to.equal(AssetProxyId.ERC20);
@@ -91,8 +91,10 @@ describe('assetDataUtils', () => {
const expectedLength = 4;
expect(decodedAssetData.nestedAssetData.length).to.be.equal(expectedLength);
const decodedErc20AssetData1 = decodedAssetData.nestedAssetData[0];
+ // tslint:disable-next-line:no-unnecessary-type-assertion
const decodedErc721AssetData1 = decodedAssetData.nestedAssetData[1] as ERC721AssetData;
const decodedErc20AssetData2 = decodedAssetData.nestedAssetData[2];
+ // tslint:disable-next-line:no-unnecessary-type-assertion
const decodedErc721AssetData2 = decodedAssetData.nestedAssetData[3] as ERC721AssetData;
expect(decodedErc20AssetData1.tokenAddress).to.equal(KNOWN_ERC20_ENCODING.address);
expect(decodedErc20AssetData1.assetProxyId).to.equal(AssetProxyId.ERC20);
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
index 12723f73e..d1085014c 100644
--- a/packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts
+++ b/packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts
@@ -1,6 +1,5 @@
-// tslint:disable:no-unnecessary-type-assertion
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
-import { AssetProxyId, ERC20AssetData, ERC721AssetData, MultiAssetData, SignedOrder } from '@0x/types';
+import { AssetProxyId, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
@@ -70,7 +69,10 @@ export class DependentOrderHashesTracker {
this._removeAssetDataFromDependentOrderHashes(signedOrder, signedOrder.makerAssetData);
// If makerToken === ZRX then we already removed it and we don't need to remove it again.
const decodedMakerAssetData = assetDataUtils.decodeAssetDataOrThrow(signedOrder.makerAssetData);
- if ((decodedMakerAssetData as ERC20AssetData).tokenAddress !== this._zrxTokenAddress) {
+ if (
+ assetDataUtils.isERC20AssetData(decodedMakerAssetData) &&
+ decodedMakerAssetData.tokenAddress !== this._zrxTokenAddress
+ ) {
this._removeFromERC20DependentOrderhashes(signedOrder, this._zrxTokenAddress);
}
this._removeFromMakerDependentOrderhashes(signedOrder);
@@ -149,24 +151,14 @@ export class DependentOrderHashesTracker {
}
private _addAssetDataToDependentOrderHashes(signedOrder: SignedOrder, assetData: string): void {
const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
- switch (decodedAssetData.assetProxyId) {
- case AssetProxyId.ERC20:
- this._addToERC20DependentOrderHashes(signedOrder, (decodedAssetData as ERC20AssetData).tokenAddress);
- break;
- case AssetProxyId.ERC721:
- this._addToERC721DependentOrderHashes(
- signedOrder,
- (decodedAssetData as ERC721AssetData).tokenAddress,
- (decodedAssetData as ERC721AssetData).tokenId,
- );
- break;
- case AssetProxyId.MultiAsset:
- _.each((decodedAssetData as MultiAssetData).nestedAssetData, nestedAssetDataElement =>
- this._addAssetDataToDependentOrderHashes(signedOrder, nestedAssetDataElement),
- );
- break;
- default:
- break;
+ if (assetDataUtils.isERC20AssetData(decodedAssetData)) {
+ this._addToERC20DependentOrderHashes(signedOrder, decodedAssetData.tokenAddress);
+ } else if (assetDataUtils.isERC721AssetData(decodedAssetData)) {
+ this._addToERC721DependentOrderHashes(signedOrder, decodedAssetData.tokenAddress, decodedAssetData.tokenId);
+ } else if (assetDataUtils.isMultiAssetData(decodedAssetData)) {
+ _.each(decodedAssetData.nestedAssetData, nestedAssetDataElement =>
+ this._addAssetDataToDependentOrderHashes(signedOrder, nestedAssetDataElement),
+ );
}
}
private _addToMakerDependentOrderHashes(signedOrder: SignedOrder): void {
@@ -234,27 +226,18 @@ export class DependentOrderHashesTracker {
}
private _removeAssetDataFromDependentOrderHashes(signedOrder: SignedOrder, assetData: string): void {
const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
- switch (decodedAssetData.assetProxyId) {
- case AssetProxyId.ERC20:
- this._removeFromERC20DependentOrderhashes(
- signedOrder,
- (decodedAssetData as ERC20AssetData).tokenAddress,
- );
- break;
- case AssetProxyId.ERC721:
- this._removeFromERC721DependentOrderhashes(
- signedOrder,
- (decodedAssetData as ERC721AssetData).tokenAddress,
- (decodedAssetData as ERC721AssetData).tokenId,
- );
- break;
- case AssetProxyId.MultiAsset:
- _.each((decodedAssetData as MultiAssetData).nestedAssetData, nestedAssetDataElement =>
- this._removeAssetDataFromDependentOrderHashes(signedOrder, nestedAssetDataElement),
- );
- break;
- default:
- break;
+ if (assetDataUtils.isERC20AssetData(decodedAssetData)) {
+ this._removeFromERC20DependentOrderhashes(signedOrder, decodedAssetData.tokenAddress);
+ } else if (assetDataUtils.isERC721AssetData(decodedAssetData)) {
+ this._removeFromERC721DependentOrderhashes(
+ signedOrder,
+ decodedAssetData.tokenAddress,
+ decodedAssetData.tokenId,
+ );
+ } else if (assetDataUtils.isMultiAssetData(decodedAssetData)) {
+ _.each(decodedAssetData.nestedAssetData, nestedAssetDataElement =>
+ this._removeAssetDataFromDependentOrderHashes(signedOrder, nestedAssetDataElement),
+ );
}
}
}
diff --git a/packages/order-watcher/src/order_watcher/order_watcher.ts b/packages/order-watcher/src/order_watcher/order_watcher.ts
index c48606555..656f21a53 100644
--- a/packages/order-watcher/src/order_watcher/order_watcher.ts
+++ b/packages/order-watcher/src/order_watcher/order_watcher.ts
@@ -32,16 +32,7 @@ import {
orderHashUtils,
OrderStateUtils,
} from '@0x/order-utils';
-import {
- AssetProxyId,
- ERC20AssetData,
- ERC721AssetData,
- ExchangeContractErrs,
- MultiAssetData,
- OrderState,
- SignedOrder,
- Stats,
-} from '@0x/types';
+import { AssetProxyId, ExchangeContractErrs, OrderState, SignedOrder, Stats } from '@0x/types';
import { errorUtils, intervalUtils } from '@0x/utils';
import { BlockParamLiteral, LogEntryEvent, LogWithDecodedArgs, Provider } from 'ethereum-types';
import * as _ from 'lodash';
@@ -240,20 +231,14 @@ export class OrderWatcher {
}
private _addAssetDataToAbiDecoder(assetData: string): void {
const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
- switch (decodedAssetData.assetProxyId) {
- case AssetProxyId.ERC20:
- this._collisionResistantAbiDecoder.addERC20Token((decodedAssetData as ERC20AssetData).tokenAddress);
- break;
- case AssetProxyId.ERC721:
- this._collisionResistantAbiDecoder.addERC721Token((decodedAssetData as ERC721AssetData).tokenAddress);
- break;
- case AssetProxyId.MultiAsset:
- _.each((decodedAssetData as MultiAssetData).nestedAssetData, nestedAssetDataElement =>
- this._addAssetDataToAbiDecoder(nestedAssetDataElement),
- );
- break;
- default:
- break;
+ 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 {
diff --git a/packages/pipeline/src/parsers/events/exchange_events.ts b/packages/pipeline/src/parsers/events/exchange_events.ts
index 8d2e7dec7..9c4a5f89a 100644
--- a/packages/pipeline/src/parsers/events/exchange_events.ts
+++ b/packages/pipeline/src/parsers/events/exchange_events.ts
@@ -1,14 +1,12 @@
import { ExchangeCancelEventArgs, ExchangeCancelUpToEventArgs, ExchangeFillEventArgs } from '@0x/contract-wrappers';
import { assetDataUtils } from '@0x/order-utils';
-import { AssetProxyId, ERC721AssetData, SingleAssetData } from '@0x/types';
+import { AssetProxyId, ERC721AssetData } from '@0x/types';
import { LogWithDecodedArgs } from 'ethereum-types';
import * as R from 'ramda';
import { ExchangeCancelEvent, ExchangeCancelUpToEvent, ExchangeFillEvent } from '../../entities';
import { bigNumbertoStringOrNull, convertAssetProxyIdToType } from '../../utils';
-// tslint:disable:no-unnecessary-type-assertion
-
/**
* Parses raw event logs for a fill event and returns an array of
* ExchangeFillEvent entities.
@@ -59,26 +57,24 @@ export function _convertToExchangeFillEvent(eventLog: LogWithDecodedArgs<Exchang
exchangeFillEvent.takerFeePaid = eventLog.args.takerFeePaid;
exchangeFillEvent.orderHash = eventLog.args.orderHash;
exchangeFillEvent.rawMakerAssetData = eventLog.args.makerAssetData;
+ // tslint:disable-next-line:no-unnecessary-type-assertion
exchangeFillEvent.makerAssetType = convertAssetProxyIdToType(makerAssetData.assetProxyId as AssetProxyId);
exchangeFillEvent.makerAssetProxyId = makerAssetData.assetProxyId;
- // HACK(abandeali1): this event schema currently does not support multiple maker/taker assets, so we store a null byte array when decoding assetData from the MultiAssetProxy
- exchangeFillEvent.makerTokenAddress =
- makerAssetData.assetProxyId === AssetProxyId.MultiAsset
- ? assetDataUtils.decodeMultiAssetDataRecursively(eventLog.args.makerAssetData).nestedAssetData[0]
- .tokenAddress
- : (makerAssetData as SingleAssetData).tokenAddress;
+ // HACK(abandeali1): this event schema currently does not support multiple maker/taker assets, so we store the first token address from the MultiAssetProxy assetData
+ exchangeFillEvent.makerTokenAddress = assetDataUtils.isMultiAssetData(makerAssetData)
+ ? assetDataUtils.decodeMultiAssetDataRecursively(eventLog.args.makerAssetData).nestedAssetData[0].tokenAddress
+ : makerAssetData.tokenAddress;
// tslint has a false positive here. Type assertion is required.
// tslint:disable-next-line:no-unnecessary-type-assertion
exchangeFillEvent.makerTokenId = bigNumbertoStringOrNull((makerAssetData as ERC721AssetData).tokenId);
exchangeFillEvent.rawTakerAssetData = eventLog.args.takerAssetData;
+ // tslint:disable-next-line:no-unnecessary-type-assertion
exchangeFillEvent.takerAssetType = convertAssetProxyIdToType(takerAssetData.assetProxyId as AssetProxyId);
exchangeFillEvent.takerAssetProxyId = takerAssetData.assetProxyId;
- // HACK(abandeali1): this event schema currently does not support multiple maker/taker assets, so we store a null byte array when decoding assetData from the MultiAssetProxy
- exchangeFillEvent.takerTokenAddress =
- takerAssetData.assetProxyId === AssetProxyId.MultiAsset
- ? assetDataUtils.decodeMultiAssetDataRecursively(eventLog.args.takerAssetData).nestedAssetData[0]
- .tokenAddress
- : (takerAssetData as SingleAssetData).tokenAddress;
+ // HACK(abandeali1): this event schema currently does not support multiple maker/taker assets, so we store the first token address from the MultiAssetProxy assetData
+ exchangeFillEvent.takerTokenAddress = assetDataUtils.isMultiAssetData(takerAssetData)
+ ? assetDataUtils.decodeMultiAssetDataRecursively(eventLog.args.takerAssetData).nestedAssetData[0].tokenAddress
+ : takerAssetData.tokenAddress;
// tslint:disable-next-line:no-unnecessary-type-assertion
exchangeFillEvent.takerTokenId = bigNumbertoStringOrNull((takerAssetData as ERC721AssetData).tokenId);
return exchangeFillEvent;
@@ -106,25 +102,23 @@ export function _convertToExchangeCancelEvent(
exchangeCancelEvent.senderAddress = eventLog.args.senderAddress;
exchangeCancelEvent.orderHash = eventLog.args.orderHash;
exchangeCancelEvent.rawMakerAssetData = eventLog.args.makerAssetData;
+ // tslint:disable-next-line:no-unnecessary-type-assertion
exchangeCancelEvent.makerAssetType = convertAssetProxyIdToType(makerAssetData.assetProxyId as AssetProxyId);
exchangeCancelEvent.makerAssetProxyId = makerAssetData.assetProxyId;
- // HACK(abandeali1): this event schema currently does not support multiple maker/taker assets, so we store a null byte array when decoding assetData from the MultiAssetProxy
- exchangeCancelEvent.makerTokenAddress =
- makerAssetData.assetProxyId === AssetProxyId.MultiAsset
- ? assetDataUtils.decodeMultiAssetDataRecursively(eventLog.args.makerAssetData).nestedAssetData[0]
- .tokenAddress
- : (makerAssetData as SingleAssetData).tokenAddress;
+ // HACK(abandeali1): this event schema currently does not support multiple maker/taker assets, so we store the first token address from the MultiAssetProxy assetData
+ exchangeCancelEvent.makerTokenAddress = assetDataUtils.isMultiAssetData(makerAssetData)
+ ? assetDataUtils.decodeMultiAssetDataRecursively(eventLog.args.makerAssetData).nestedAssetData[0].tokenAddress
+ : makerAssetData.tokenAddress;
// tslint:disable-next-line:no-unnecessary-type-assertion
exchangeCancelEvent.makerTokenId = bigNumbertoStringOrNull((makerAssetData as ERC721AssetData).tokenId);
exchangeCancelEvent.rawTakerAssetData = eventLog.args.takerAssetData;
+ // tslint:disable-next-line:no-unnecessary-type-assertion
exchangeCancelEvent.takerAssetType = convertAssetProxyIdToType(takerAssetData.assetProxyId as AssetProxyId);
exchangeCancelEvent.takerAssetProxyId = takerAssetData.assetProxyId;
- // HACK(abandeali1): this event schema currently does not support multiple maker/taker assets, so we store a null byte array when decoding assetData from the MultiAssetProxy
- exchangeCancelEvent.takerTokenAddress =
- takerAssetData.assetProxyId === AssetProxyId.MultiAsset
- ? assetDataUtils.decodeMultiAssetDataRecursively(eventLog.args.takerAssetData).nestedAssetData[0]
- .tokenAddress
- : (takerAssetData as SingleAssetData).tokenAddress;
+ // HACK(abandeali1): this event schema currently does not support multiple maker/taker assets, so we store the first token address from the MultiAssetProxy assetData
+ exchangeCancelEvent.takerTokenAddress = assetDataUtils.isMultiAssetData(takerAssetData)
+ ? assetDataUtils.decodeMultiAssetDataRecursively(eventLog.args.takerAssetData).nestedAssetData[0].tokenAddress
+ : takerAssetData.tokenAddress;
// tslint:disable-next-line:no-unnecessary-type-assertion
exchangeCancelEvent.takerTokenId = bigNumbertoStringOrNull((takerAssetData as ERC721AssetData).tokenId);
return exchangeCancelEvent;
diff --git a/packages/pipeline/src/parsers/sra_orders/index.ts b/packages/pipeline/src/parsers/sra_orders/index.ts
index 10546921d..13fe632a4 100644
--- a/packages/pipeline/src/parsers/sra_orders/index.ts
+++ b/packages/pipeline/src/parsers/sra_orders/index.ts
@@ -1,13 +1,11 @@
import { APIOrder, OrdersResponse } from '@0x/connect';
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
-import { AssetProxyId, ERC721AssetData, SingleAssetData } from '@0x/types';
+import { AssetProxyId, ERC721AssetData } from '@0x/types';
import * as R from 'ramda';
import { SraOrder } from '../../entities';
import { bigNumbertoStringOrNull, convertAssetProxyIdToType } from '../../utils';
-// tslint:disable:no-unnecessary-type-assertion
-
/**
* Parses a raw order response from an SRA endpoint and returns an array of
* SraOrder entities.
@@ -43,26 +41,24 @@ export function _convertToEntity(apiOrder: APIOrder): SraOrder {
sraOrder.signature = apiOrder.order.signature;
sraOrder.rawMakerAssetData = apiOrder.order.makerAssetData;
+ // tslint:disable-next-line:no-unnecessary-type-assertion
sraOrder.makerAssetType = convertAssetProxyIdToType(makerAssetData.assetProxyId as AssetProxyId);
sraOrder.makerAssetProxyId = makerAssetData.assetProxyId;
- // HACK(abandeali1): this event schema currently does not support multiple maker/taker assets, so we store a null byte array when decoding assetData from the MultiAssetProxy
- sraOrder.makerTokenAddress =
- makerAssetData.assetProxyId === AssetProxyId.MultiAsset
- ? assetDataUtils.decodeMultiAssetDataRecursively(apiOrder.order.makerAssetData).nestedAssetData[0]
- .tokenAddress
- : (makerAssetData as SingleAssetData).tokenAddress;
+ // HACK(abandeali1): this event schema currently does not support multiple maker/taker assets, so we store the first token address from the MultiAssetProxy assetData
+ sraOrder.makerTokenAddress = assetDataUtils.isMultiAssetData(makerAssetData)
+ ? assetDataUtils.decodeMultiAssetDataRecursively(apiOrder.order.makerAssetData).nestedAssetData[0].tokenAddress
+ : makerAssetData.tokenAddress;
// tslint has a false positive here. Type assertion is required.
// tslint:disable-next-line:no-unnecessary-type-assertion
sraOrder.makerTokenId = bigNumbertoStringOrNull((makerAssetData as ERC721AssetData).tokenId);
sraOrder.rawTakerAssetData = apiOrder.order.takerAssetData;
+ // tslint:disable-next-line:no-unnecessary-type-assertion
sraOrder.takerAssetType = convertAssetProxyIdToType(takerAssetData.assetProxyId as AssetProxyId);
sraOrder.takerAssetProxyId = takerAssetData.assetProxyId;
- // HACK(abandeali1): this event schema currently does not support multiple maker/taker assets, so we store a null byte array when decoding assetData from the MultiAssetProxy
- sraOrder.takerTokenAddress =
- takerAssetData.assetProxyId === AssetProxyId.MultiAsset
- ? assetDataUtils.decodeMultiAssetDataRecursively(apiOrder.order.takerAssetData).nestedAssetData[0]
- .tokenAddress
- : (takerAssetData as SingleAssetData).tokenAddress;
+ // HACK(abandeali1): this event schema currently does not support multiple maker/taker assets, so we store the first token address from the MultiAssetProxy assetData
+ sraOrder.takerTokenAddress = assetDataUtils.isMultiAssetData(takerAssetData)
+ ? assetDataUtils.decodeMultiAssetDataRecursively(apiOrder.order.takerAssetData).nestedAssetData[0].tokenAddress
+ : takerAssetData.tokenAddress;
// tslint:disable-next-line:no-unnecessary-type-assertion
sraOrder.takerTokenId = bigNumbertoStringOrNull((takerAssetData as ERC721AssetData).tokenId);