Minimize unnecessary type assertions
This commit is contained in:
@@ -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]),
|
||||
),
|
||||
);
|
||||
@@ -181,6 +180,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
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user