aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmir Bandeali <abandeali1@gmail.com>2019-01-03 06:08:21 +0800
committerAmir Bandeali <abandeali1@gmail.com>2019-01-08 02:31:11 +0800
commit0fba0b1a1bbe1192802ebcf4b88437b94d6a1c18 (patch)
tree8eda6776f15138b21d0844fc37d09ac64ae38a62
parentdf4f3d9eacd370b56913f6b85ab7aa705cbed8fe (diff)
downloaddexon-0x-contracts-0fba0b1a1bbe1192802ebcf4b88437b94d6a1c18.tar.gz
dexon-0x-contracts-0fba0b1a1bbe1192802ebcf4b88437b94d6a1c18.tar.zst
dexon-0x-contracts-0fba0b1a1bbe1192802ebcf4b88437b94d6a1c18.zip
feat: Add balance and allowance checks for MultiAssetProxy
-rw-r--r--packages/contract-wrappers/src/fetchers/asset_balance_and_proxy_allowance_fetcher.ts132
1 files changed, 87 insertions, 45 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 d10cffe57..376004f52 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,8 +1,9 @@
// tslint:disable:no-unnecessary-type-assertion
import { AbstractBalanceAndProxyAllowanceFetcher, assetDataUtils } from '@0x/order-utils';
-import { AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0x/types';
+import { AssetProxyId, ERC20AssetData, ERC721AssetData, MultiAssetData } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { BlockParamLiteral } from 'ethereum-types';
+import * as _ from 'lodash';
import { ERC20TokenWrapper } from '../contract_wrappers/erc20_token_wrapper';
import { ERC721TokenWrapper } from '../contract_wrappers/erc721_token_wrapper';
@@ -18,60 +19,101 @@ export class AssetBalanceAndProxyAllowanceFetcher implements AbstractBalanceAndP
}
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,
- {
+ let balance: BigNumber | undefined;
+ switch (decodedAssetData.assetProxyId) {
+ case AssetProxyId.ERC20:
+ const decodedERC20AssetData = decodedAssetData as ERC20AssetData;
+ balance = await this._erc20Token.getBalanceAsync(decodedERC20AssetData.tokenAddress, userAddress, {
defaultBlock: this._stateLayer,
- },
- );
- const balance = tokenOwner === userAddress ? new BigNumber(1) : new BigNumber(0);
- return balance;
+ });
+ 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,
+ 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;
+ }
+ }
+ 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);
- 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(
+ 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,
- decodedERC721AssetData.tokenId,
+ userAddress,
{
defaultBlock: this._stateLayer,
},
);
- const proxyAllowance = isApproved ? new BigNumber(1) : new BigNumber(0);
- return proxyAllowance;
- }
+ 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,
+ 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;
+ }
+ }
+ break;
+ default:
+ throw new Error(`Proxy with id ${decodedAssetData.assetProxyId} not supported`);
}
+ return proxyAllowance as BigNumber;
}
}