aboutsummaryrefslogtreecommitdiffstats
path: root/packages/order-utils/src/order_state_utils.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/order-utils/src/order_state_utils.ts')
-rw-r--r--packages/order-utils/src/order_state_utils.ts56
1 files changed, 56 insertions, 0 deletions
diff --git a/packages/order-utils/src/order_state_utils.ts b/packages/order-utils/src/order_state_utils.ts
index fe0d6c773..389419587 100644
--- a/packages/order-utils/src/order_state_utils.ts
+++ b/packages/order-utils/src/order_state_utils.ts
@@ -1,5 +1,6 @@
import {
ExchangeContractErrs,
+ ObjectMap,
OrderRelevantState,
OrderState,
OrderStateInvalid,
@@ -7,9 +8,11 @@ import {
SignedOrder,
} from '@0x/types';
import { BigNumber } from '@0x/utils';
+import * as _ from 'lodash';
import { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher';
import { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher';
+import { assetDataUtils } from './asset_data_utils';
import { orderHashUtils } from './order_hash';
import { OrderValidationUtils } from './order_validation_utils';
import { RemainingFillableCalculator } from './remaining_fillable_calculator';
@@ -18,7 +21,9 @@ import { utils } from './utils';
interface SidedOrderRelevantState {
isMakerSide: boolean;
traderBalance: BigNumber;
+ traderIndividualBalances: ObjectMap<BigNumber>;
traderProxyAllowance: BigNumber;
+ traderIndividualProxyAllowances: ObjectMap<BigNumber>;
traderFeeBalance: BigNumber;
traderFeeProxyAllowance: BigNumber;
filledTakerAssetAmount: BigNumber;
@@ -121,7 +126,9 @@ export class OrderStateUtils {
const sidedOrderRelevantState = {
isMakerSide: true,
traderBalance: orderRelevantState.makerBalance,
+ traderIndividualBalances: orderRelevantState.makerIndividualBalances,
traderProxyAllowance: orderRelevantState.makerProxyAllowance,
+ traderIndividualProxyAllowances: orderRelevantState.makerIndividualProxyAllowances,
traderFeeBalance: orderRelevantState.makerFeeBalance,
traderFeeProxyAllowance: orderRelevantState.makerFeeProxyAllowance,
filledTakerAssetAmount: orderRelevantState.filledTakerAssetAmount,
@@ -165,7 +172,9 @@ export class OrderStateUtils {
const orderRelevantState = {
makerBalance: sidedOrderRelevantState.traderBalance,
+ makerIndividualBalances: sidedOrderRelevantState.traderIndividualBalances,
makerProxyAllowance: sidedOrderRelevantState.traderProxyAllowance,
+ makerIndividualProxyAllowances: sidedOrderRelevantState.traderIndividualProxyAllowances,
makerFeeBalance: sidedOrderRelevantState.traderFeeBalance,
makerFeeProxyAllowance: sidedOrderRelevantState.traderFeeProxyAllowance,
filledTakerAssetAmount: sidedOrderRelevantState.filledTakerAssetAmount,
@@ -236,10 +245,12 @@ export class OrderStateUtils {
const isAssetZRX = assetData === zrxAssetData;
const traderBalance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync(assetData, traderAddress);
+ const traderIndividualBalances = await this._getAssetBalancesAsync(assetData, traderAddress);
const traderProxyAllowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync(
assetData,
traderAddress,
);
+ const traderIndividualProxyAllowances = await this._getAssetProxyAllowancesAsync(assetData, traderAddress);
const traderFeeBalance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync(
zrxAssetData,
traderAddress,
@@ -278,7 +289,9 @@ export class OrderStateUtils {
const sidedOrderRelevantState = {
isMakerSide,
traderBalance,
+ traderIndividualBalances,
traderProxyAllowance,
+ traderIndividualProxyAllowances,
traderFeeBalance,
traderFeeProxyAllowance,
filledTakerAssetAmount,
@@ -287,4 +300,47 @@ export class OrderStateUtils {
};
return sidedOrderRelevantState;
}
+ private async _getAssetBalancesAsync(
+ assetData: string,
+ traderAddress: string,
+ initialBalances: ObjectMap<BigNumber> = {},
+ ): Promise<ObjectMap<BigNumber>> {
+ const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
+ let balances: ObjectMap<BigNumber> = { ...initialBalances };
+ 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;
+ }
+ private async _getAssetProxyAllowancesAsync(
+ assetData: string,
+ traderAddress: string,
+ initialAllowances: ObjectMap<BigNumber> = {},
+ ): Promise<ObjectMap<BigNumber>> {
+ const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
+ let allowances: ObjectMap<BigNumber> = { ...initialAllowances };
+ 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;
+ }
}