Add syntactic sugar for assetDataUtils (#2388)
* add syntactic sugar for assetDataUtils
This commit is contained in:
		@@ -1,6 +1,6 @@
 | 
			
		||||
export { getContractAddressesForChainOrThrow, ChainId, ContractAddresses } from '@0x/contract-addresses';
 | 
			
		||||
 | 
			
		||||
export { signatureUtils, generatePseudoRandomSalt, decodeAssetDataOrThrow } from '@0x/order-utils';
 | 
			
		||||
export { signatureUtils, generatePseudoRandomSalt, assetDataUtils } from '@0x/order-utils';
 | 
			
		||||
 | 
			
		||||
export {
 | 
			
		||||
    ExchangeEventArgs,
 | 
			
		||||
 
 | 
			
		||||
@@ -58,6 +58,15 @@ export const docGenConfigs: DocGenConfigs = {
 | 
			
		||||
        'GlobalStakeByStatus',
 | 
			
		||||
        'OwnerStakeByStatus',
 | 
			
		||||
        'StakingPoolById',
 | 
			
		||||
        'AssetData',
 | 
			
		||||
        'SingleAssetData',
 | 
			
		||||
        'ERC20AssetData',
 | 
			
		||||
        'ERC20BridgeAssetData',
 | 
			
		||||
        'ERC721AssetData',
 | 
			
		||||
        'ERC1155AssetData',
 | 
			
		||||
        'MultiAssetData',
 | 
			
		||||
        'StaticCallAssetData',
 | 
			
		||||
        'MultiAssetDataWithRecursiveDecoding',
 | 
			
		||||
    ],
 | 
			
		||||
    // Some libraries only export types. In those cases, we cannot check if the exported types are part of the
 | 
			
		||||
    // "exported public interface". Thus we add them here and skip those checks.
 | 
			
		||||
 
 | 
			
		||||
@@ -3,12 +3,12 @@
 | 
			
		||||
        "version": "10.0.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Removed `assetDataUtils`",
 | 
			
		||||
                "pr": 2373
 | 
			
		||||
                "note": "Removed from assetDataUtils: individual decoding functions and assert functions",
 | 
			
		||||
                "pr": 2388
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Exported function `decodeAssetDataOrThrow`",
 | 
			
		||||
                "pr": 2373
 | 
			
		||||
                "note": "Add ERC20Bridge support to assetDataUtils",
 | 
			
		||||
                "pr": 2388
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										165
									
								
								packages/order-utils/src/asset_data_utils.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								packages/order-utils/src/asset_data_utils.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,165 @@
 | 
			
		||||
import { IAssetDataContract } from '@0x/contract-wrappers';
 | 
			
		||||
import {
 | 
			
		||||
    AssetData,
 | 
			
		||||
    AssetProxyId,
 | 
			
		||||
    MultiAssetData,
 | 
			
		||||
    MultiAssetDataWithRecursiveDecoding,
 | 
			
		||||
    SingleAssetData,
 | 
			
		||||
} from '@0x/types';
 | 
			
		||||
import { BigNumber, hexUtils, NULL_ADDRESS } from '@0x/utils';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
const fakeProvider = { isEIP1193: true } as any;
 | 
			
		||||
const assetDataEncoder = new IAssetDataContract(NULL_ADDRESS, fakeProvider);
 | 
			
		||||
 | 
			
		||||
export const assetDataUtils = {
 | 
			
		||||
    encodeERC20AssetData(tokenAddress: string): string {
 | 
			
		||||
        return assetDataEncoder.ERC20Token(tokenAddress).getABIEncodedTransactionData();
 | 
			
		||||
    },
 | 
			
		||||
    encodeERC20BridgeAssetData(tokenAddress: string, bridgeAddress: string, bridgeData: string): string {
 | 
			
		||||
        return assetDataEncoder.ERC20Bridge(tokenAddress, bridgeAddress, bridgeData).getABIEncodedTransactionData();
 | 
			
		||||
    },
 | 
			
		||||
    encodeERC721AssetData(tokenAddress: string, tokenId: BigNumber): string {
 | 
			
		||||
        return assetDataEncoder.ERC721Token(tokenAddress, tokenId).getABIEncodedTransactionData();
 | 
			
		||||
    },
 | 
			
		||||
    encodeERC1155AssetData(
 | 
			
		||||
        tokenAddress: string,
 | 
			
		||||
        tokenIds: BigNumber[],
 | 
			
		||||
        tokenValues: BigNumber[],
 | 
			
		||||
        callbackData: string,
 | 
			
		||||
    ): string {
 | 
			
		||||
        return assetDataEncoder
 | 
			
		||||
            .ERC1155Assets(tokenAddress, tokenIds, tokenValues, callbackData)
 | 
			
		||||
            .getABIEncodedTransactionData();
 | 
			
		||||
    },
 | 
			
		||||
    encodeMultiAssetData(values: BigNumber[], nestedAssetData: string[]): string {
 | 
			
		||||
        return assetDataEncoder.MultiAsset(values, nestedAssetData).getABIEncodedTransactionData();
 | 
			
		||||
    },
 | 
			
		||||
    encodeStaticCallAssetData(
 | 
			
		||||
        staticCallTargetAddress: string,
 | 
			
		||||
        staticCallData: string,
 | 
			
		||||
        expectedReturnDataHash: string,
 | 
			
		||||
    ): string {
 | 
			
		||||
        return assetDataEncoder
 | 
			
		||||
            .StaticCall(staticCallTargetAddress, staticCallData, expectedReturnDataHash)
 | 
			
		||||
            .getABIEncodedTransactionData();
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * Decode any assetData into its corresponding assetData object
 | 
			
		||||
     * @param assetData Hex encoded assetData string to decode
 | 
			
		||||
     * @return Either a ERC20, ERC20Bridge, ERC721, ERC1155, StaticCall, or MultiAsset assetData object
 | 
			
		||||
     */
 | 
			
		||||
    decodeAssetDataOrThrow(assetData: string): AssetData {
 | 
			
		||||
        const assetProxyId = hexUtils.slice(assetData, 0, 4); // tslint:disable-line:custom-no-magic-numbers
 | 
			
		||||
        switch (assetProxyId) {
 | 
			
		||||
            case AssetProxyId.ERC20: {
 | 
			
		||||
                const tokenAddress = assetDataEncoder.getABIDecodedTransactionData<string>('ERC20Token', assetData);
 | 
			
		||||
                return {
 | 
			
		||||
                    assetProxyId,
 | 
			
		||||
                    tokenAddress,
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
            case AssetProxyId.ERC20Bridge: {
 | 
			
		||||
                const [tokenAddress, bridgeAddress, bridgeData] = assetDataEncoder.getABIDecodedTransactionData<
 | 
			
		||||
                    [string, string, string]
 | 
			
		||||
                >('ERC20Bridge', assetData);
 | 
			
		||||
                return {
 | 
			
		||||
                    assetProxyId,
 | 
			
		||||
                    tokenAddress,
 | 
			
		||||
                    bridgeAddress,
 | 
			
		||||
                    bridgeData,
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
            case AssetProxyId.ERC721: {
 | 
			
		||||
                const [tokenAddress, tokenId] = assetDataEncoder.getABIDecodedTransactionData<[string, BigNumber]>(
 | 
			
		||||
                    'ERC721Token',
 | 
			
		||||
                    assetData,
 | 
			
		||||
                );
 | 
			
		||||
                return {
 | 
			
		||||
                    assetProxyId,
 | 
			
		||||
                    tokenAddress,
 | 
			
		||||
                    tokenId,
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
            case AssetProxyId.ERC1155: {
 | 
			
		||||
                const [
 | 
			
		||||
                    tokenAddress,
 | 
			
		||||
                    tokenIds,
 | 
			
		||||
                    tokenValues,
 | 
			
		||||
                    callbackData,
 | 
			
		||||
                ] = assetDataEncoder.getABIDecodedTransactionData<[string, BigNumber[], BigNumber[], string]>(
 | 
			
		||||
                    'ERC1155Assets',
 | 
			
		||||
                    assetData,
 | 
			
		||||
                );
 | 
			
		||||
                return {
 | 
			
		||||
                    assetProxyId,
 | 
			
		||||
                    tokenAddress,
 | 
			
		||||
                    tokenIds,
 | 
			
		||||
                    tokenValues,
 | 
			
		||||
                    callbackData,
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
            case AssetProxyId.MultiAsset: {
 | 
			
		||||
                const [amounts, nestedAssetData] = assetDataEncoder.getABIDecodedTransactionData<
 | 
			
		||||
                    [BigNumber[], string[]]
 | 
			
		||||
                >('MultiAsset', assetData);
 | 
			
		||||
 | 
			
		||||
                const multiAssetData: MultiAssetData = {
 | 
			
		||||
                    assetProxyId,
 | 
			
		||||
                    amounts,
 | 
			
		||||
                    nestedAssetData,
 | 
			
		||||
                };
 | 
			
		||||
                return multiAssetData;
 | 
			
		||||
            }
 | 
			
		||||
            case AssetProxyId.StaticCall:
 | 
			
		||||
                const [callTarget, staticCallData, callResultHash] = assetDataEncoder.getABIDecodedTransactionData<
 | 
			
		||||
                    [string, string, string]
 | 
			
		||||
                >('StaticCall', assetData);
 | 
			
		||||
                return {
 | 
			
		||||
                    assetProxyId,
 | 
			
		||||
                    callTarget,
 | 
			
		||||
                    staticCallData,
 | 
			
		||||
                    callResultHash,
 | 
			
		||||
                };
 | 
			
		||||
            default:
 | 
			
		||||
                throw new Error(`Unhandled asset proxy ID: ${assetProxyId}`);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * Decodes a MultiAsset assetData hex string into its corresponding amounts and decoded nestedAssetData elements (all nested elements are flattened)
 | 
			
		||||
     * @param assetData Hex encoded assetData string to decode
 | 
			
		||||
     * @return An object containing the decoded amounts and nestedAssetData
 | 
			
		||||
     */
 | 
			
		||||
    decodeMultiAssetDataRecursively(assetData: string): MultiAssetDataWithRecursiveDecoding {
 | 
			
		||||
        const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData) as MultiAssetData; // tslint:disable-line:no-unnecessary-type-assertion
 | 
			
		||||
        if (decodedAssetData.assetProxyId !== AssetProxyId.MultiAsset) {
 | 
			
		||||
            throw new Error(`Not a MultiAssetData. Use 'decodeAssetDataOrThrow' instead`);
 | 
			
		||||
        }
 | 
			
		||||
        const amounts: any[] = [];
 | 
			
		||||
        const decodedNestedAssetData = decodedAssetData.nestedAssetData.map((nestedAssetDataElement, index) => {
 | 
			
		||||
            const decodedNestedAssetDataElement = assetDataUtils.decodeAssetDataOrThrow(nestedAssetDataElement);
 | 
			
		||||
            if (decodedNestedAssetDataElement.assetProxyId === AssetProxyId.MultiAsset) {
 | 
			
		||||
                const recursivelyDecodedAssetData = assetDataUtils.decodeMultiAssetDataRecursively(
 | 
			
		||||
                    nestedAssetDataElement,
 | 
			
		||||
                );
 | 
			
		||||
                amounts.push(
 | 
			
		||||
                    recursivelyDecodedAssetData.amounts.map(amountElement =>
 | 
			
		||||
                        amountElement.times(decodedAssetData.amounts[index]),
 | 
			
		||||
                    ),
 | 
			
		||||
                );
 | 
			
		||||
                return recursivelyDecodedAssetData.nestedAssetData;
 | 
			
		||||
            } else {
 | 
			
		||||
                amounts.push(decodedAssetData.amounts[index]);
 | 
			
		||||
                return decodedNestedAssetDataElement;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        const flattenedAmounts = _.flattenDeep(amounts);
 | 
			
		||||
        const flattenedDecodedNestedAssetData = _.flattenDeep(decodedNestedAssetData);
 | 
			
		||||
        return {
 | 
			
		||||
            assetProxyId: decodedAssetData.assetProxyId,
 | 
			
		||||
            amounts: flattenedAmounts,
 | 
			
		||||
            // tslint:disable-next-line:no-unnecessary-type-assertion
 | 
			
		||||
            nestedAssetData: flattenedDecodedNestedAssetData as SingleAssetData[],
 | 
			
		||||
        };
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
@@ -1,80 +0,0 @@
 | 
			
		||||
import { IAssetDataContract } from '@0x/contract-wrappers';
 | 
			
		||||
import { AssetData, AssetProxyId } from '@0x/types';
 | 
			
		||||
import { BigNumber, hexUtils, NULL_ADDRESS } from '@0x/utils';
 | 
			
		||||
 | 
			
		||||
const fakeProvider = { isEIP1193: true } as any;
 | 
			
		||||
const assetDataDecoder = new IAssetDataContract(NULL_ADDRESS, fakeProvider);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Decode any assetData into its corresponding assetData object
 | 
			
		||||
 * @param assetData Hex encoded assetData string to decode
 | 
			
		||||
 * @return Either a ERC20, ERC20Bridge, ERC721, ERC1155, StaticCall, or MultiAsset assetData object
 | 
			
		||||
 */
 | 
			
		||||
export function decodeAssetDataOrThrow(assetData: string): AssetData {
 | 
			
		||||
    const assetProxyId = hexUtils.slice(assetData, 0, 4); // tslint:disable-line:custom-no-magic-numbers
 | 
			
		||||
    switch (assetProxyId) {
 | 
			
		||||
        case AssetProxyId.ERC20: {
 | 
			
		||||
            const tokenAddress = assetDataDecoder.getABIDecodedTransactionData<string>('ERC20Token', assetData);
 | 
			
		||||
            return {
 | 
			
		||||
                assetProxyId,
 | 
			
		||||
                tokenAddress,
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
        case AssetProxyId.ERC20Bridge: {
 | 
			
		||||
            const [tokenAddress, bridgeAddress, bridgeData] = assetDataDecoder.getABIDecodedTransactionData<
 | 
			
		||||
                [string, string, string]
 | 
			
		||||
            >('ERC20Bridge', assetData);
 | 
			
		||||
            return {
 | 
			
		||||
                assetProxyId,
 | 
			
		||||
                tokenAddress,
 | 
			
		||||
                bridgeAddress,
 | 
			
		||||
                bridgeData,
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
        case AssetProxyId.ERC721: {
 | 
			
		||||
            const [tokenAddress, tokenId] = assetDataDecoder.getABIDecodedTransactionData<[string, BigNumber]>(
 | 
			
		||||
                'ERC721Token',
 | 
			
		||||
                assetData,
 | 
			
		||||
            );
 | 
			
		||||
            return {
 | 
			
		||||
                assetProxyId,
 | 
			
		||||
                tokenAddress,
 | 
			
		||||
                tokenId,
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
        case AssetProxyId.ERC1155: {
 | 
			
		||||
            const [tokenAddress, tokenIds, tokenValues] = assetDataDecoder.getABIDecodedTransactionData<
 | 
			
		||||
                [string, BigNumber[], BigNumber[]]
 | 
			
		||||
            >('ERC1155Assets', assetData);
 | 
			
		||||
            return {
 | 
			
		||||
                assetProxyId,
 | 
			
		||||
                tokenAddress,
 | 
			
		||||
                tokenIds,
 | 
			
		||||
                tokenValues,
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
        case AssetProxyId.MultiAsset: {
 | 
			
		||||
            const [amounts, nestedAssetData] = assetDataDecoder.getABIDecodedTransactionData<[BigNumber[], string[]]>(
 | 
			
		||||
                'MultiAsset',
 | 
			
		||||
                assetData,
 | 
			
		||||
            );
 | 
			
		||||
            return {
 | 
			
		||||
                assetProxyId,
 | 
			
		||||
                amounts,
 | 
			
		||||
                nestedAssetData,
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
        case AssetProxyId.StaticCall:
 | 
			
		||||
            const [callTarget, staticCallData, callResultHash] = assetDataDecoder.getABIDecodedTransactionData<
 | 
			
		||||
                [string, string, string]
 | 
			
		||||
            >('StaticCall', assetData);
 | 
			
		||||
            return {
 | 
			
		||||
                assetProxyId,
 | 
			
		||||
                callTarget,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                callResultHash,
 | 
			
		||||
            };
 | 
			
		||||
        default:
 | 
			
		||||
            throw new Error(`Unhandled asset proxy ID: ${assetProxyId}`);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -5,7 +5,7 @@ export { rateUtils } from './rate_utils';
 | 
			
		||||
export { sortingUtils } from './sorting_utils';
 | 
			
		||||
export { orderCalculationUtils } from './order_calculation_utils';
 | 
			
		||||
export { orderHashUtils } from './order_hash_utils';
 | 
			
		||||
export { decodeAssetDataOrThrow } from './decode_asset_data';
 | 
			
		||||
export { assetDataUtils } from './asset_data_utils';
 | 
			
		||||
 | 
			
		||||
export { eip712Utils } from './eip712_utils';
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										186
									
								
								packages/order-utils/test/asset_data_utils_test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								packages/order-utils/test/asset_data_utils_test.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,186 @@
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
 | 
			
		||||
import { AssetProxyId, ERC1155AssetData, ERC20AssetData, ERC721AssetData, MultiAssetData } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
 | 
			
		||||
import { assetDataUtils } from '../src/asset_data_utils';
 | 
			
		||||
 | 
			
		||||
import { chaiSetup } from './utils/chai_setup';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
 | 
			
		||||
const KNOWN_ERC20_ENCODING = {
 | 
			
		||||
    address: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
 | 
			
		||||
    assetData: '0xf47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48',
 | 
			
		||||
};
 | 
			
		||||
const KNOWN_ERC721_ENCODING = {
 | 
			
		||||
    address: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
 | 
			
		||||
    tokenId: new BigNumber(1),
 | 
			
		||||
    assetData:
 | 
			
		||||
        '0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001',
 | 
			
		||||
};
 | 
			
		||||
const KNOWN_ERC1155_ENCODING = {
 | 
			
		||||
    tokenAddress: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
 | 
			
		||||
    tokenIds: [new BigNumber(100), new BigNumber(1001), new BigNumber(10001)],
 | 
			
		||||
    tokenValues: [new BigNumber(200), new BigNumber(2001), new BigNumber(20001)],
 | 
			
		||||
    callbackData:
 | 
			
		||||
        '0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001',
 | 
			
		||||
    assetData:
 | 
			
		||||
        '0xa7cb5fb70000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000',
 | 
			
		||||
};
 | 
			
		||||
const KNOWN_MULTI_ASSET_ENCODING = {
 | 
			
		||||
    amounts: [new BigNumber(70), new BigNumber(1), new BigNumber(18)],
 | 
			
		||||
    nestedAssetData: [
 | 
			
		||||
        KNOWN_ERC20_ENCODING.assetData,
 | 
			
		||||
        KNOWN_ERC721_ENCODING.assetData,
 | 
			
		||||
        KNOWN_ERC1155_ENCODING.assetData,
 | 
			
		||||
    ],
 | 
			
		||||
    assetData:
 | 
			
		||||
        '0x94cfcdd7000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000204a7cb5fb70000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c4800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
describe('assetDataUtils', () => {
 | 
			
		||||
    it('should encode ERC20', () => {
 | 
			
		||||
        const assetData = assetDataUtils.encodeERC20AssetData(KNOWN_ERC20_ENCODING.address);
 | 
			
		||||
        expect(assetData).to.equal(KNOWN_ERC20_ENCODING.assetData);
 | 
			
		||||
    });
 | 
			
		||||
    it('should decode ERC20', () => {
 | 
			
		||||
        const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(
 | 
			
		||||
            KNOWN_ERC20_ENCODING.assetData,
 | 
			
		||||
        ) as ERC20AssetData; // tslint:disable-line:no-unnecessary-type-assertion
 | 
			
		||||
        expect(decodedAssetData.tokenAddress).to.equal(KNOWN_ERC20_ENCODING.address);
 | 
			
		||||
        expect(decodedAssetData.assetProxyId).to.equal(AssetProxyId.ERC20);
 | 
			
		||||
    });
 | 
			
		||||
    it('should encode ERC721', () => {
 | 
			
		||||
        const assetData = assetDataUtils.encodeERC721AssetData(
 | 
			
		||||
            KNOWN_ERC721_ENCODING.address,
 | 
			
		||||
            KNOWN_ERC721_ENCODING.tokenId,
 | 
			
		||||
        );
 | 
			
		||||
        expect(assetData).to.equal(KNOWN_ERC721_ENCODING.assetData);
 | 
			
		||||
    });
 | 
			
		||||
    it('should decode ERC721', () => {
 | 
			
		||||
        const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(
 | 
			
		||||
            KNOWN_ERC721_ENCODING.assetData,
 | 
			
		||||
        ) as ERC721AssetData; // tslint:disable-line:no-unnecessary-type-assertion
 | 
			
		||||
        expect(decodedAssetData.tokenAddress).to.equal(KNOWN_ERC721_ENCODING.address);
 | 
			
		||||
        expect(decodedAssetData.assetProxyId).to.equal(AssetProxyId.ERC721);
 | 
			
		||||
        expect(decodedAssetData.tokenId).to.be.bignumber.equal(KNOWN_ERC721_ENCODING.tokenId);
 | 
			
		||||
    });
 | 
			
		||||
    it('should encode ERC1155', () => {
 | 
			
		||||
        const assetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
            KNOWN_ERC1155_ENCODING.tokenAddress,
 | 
			
		||||
            KNOWN_ERC1155_ENCODING.tokenIds,
 | 
			
		||||
            KNOWN_ERC1155_ENCODING.tokenValues,
 | 
			
		||||
            KNOWN_ERC1155_ENCODING.callbackData,
 | 
			
		||||
        );
 | 
			
		||||
        expect(assetData).to.equal(KNOWN_ERC1155_ENCODING.assetData);
 | 
			
		||||
    });
 | 
			
		||||
    it('should decode ERC1155', () => {
 | 
			
		||||
        const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(
 | 
			
		||||
            KNOWN_ERC1155_ENCODING.assetData,
 | 
			
		||||
        ) as ERC1155AssetData; // tslint:disable-line:no-unnecessary-type-assertion
 | 
			
		||||
        expect(decodedAssetData.assetProxyId).to.be.equal(AssetProxyId.ERC1155);
 | 
			
		||||
        expect(decodedAssetData.tokenAddress).to.be.equal(KNOWN_ERC1155_ENCODING.tokenAddress);
 | 
			
		||||
        expect(decodedAssetData.tokenValues).to.be.deep.equal(KNOWN_ERC1155_ENCODING.tokenValues);
 | 
			
		||||
        expect(decodedAssetData.tokenIds).to.be.deep.equal(KNOWN_ERC1155_ENCODING.tokenIds);
 | 
			
		||||
        expect(decodedAssetData.callbackData).to.be.equal(KNOWN_ERC1155_ENCODING.callbackData);
 | 
			
		||||
    });
 | 
			
		||||
    it('should encode ERC20, ERC721 and ERC1155 multiAssetData', () => {
 | 
			
		||||
        const assetData = assetDataUtils.encodeMultiAssetData(
 | 
			
		||||
            KNOWN_MULTI_ASSET_ENCODING.amounts,
 | 
			
		||||
            KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
 | 
			
		||||
        );
 | 
			
		||||
        expect(assetData).to.equal(KNOWN_MULTI_ASSET_ENCODING.assetData);
 | 
			
		||||
    });
 | 
			
		||||
    it('should decode ERC20, ERC721 and ERC1155 multiAssetData', () => {
 | 
			
		||||
        const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(
 | 
			
		||||
            KNOWN_MULTI_ASSET_ENCODING.assetData,
 | 
			
		||||
        ) as MultiAssetData; // tslint:disable-line:no-unnecessary-type-assertion
 | 
			
		||||
        expect(decodedAssetData.assetProxyId).to.equal(AssetProxyId.MultiAsset);
 | 
			
		||||
        expect(decodedAssetData.amounts).to.deep.equal(KNOWN_MULTI_ASSET_ENCODING.amounts);
 | 
			
		||||
        expect(decodedAssetData.nestedAssetData).to.deep.equal(KNOWN_MULTI_ASSET_ENCODING.nestedAssetData);
 | 
			
		||||
    });
 | 
			
		||||
    it('should recursively decode ERC20 and ERC721 multiAssetData', () => {
 | 
			
		||||
        const decodedAssetData = assetDataUtils.decodeMultiAssetDataRecursively(KNOWN_MULTI_ASSET_ENCODING.assetData);
 | 
			
		||||
        expect(decodedAssetData.assetProxyId).to.equal(AssetProxyId.MultiAsset);
 | 
			
		||||
        expect(decodedAssetData.amounts).to.deep.equal(KNOWN_MULTI_ASSET_ENCODING.amounts);
 | 
			
		||||
        expect(decodedAssetData.nestedAssetData.length).to.equal(3);
 | 
			
		||||
        // tslint:disable-next-line:no-unnecessary-type-assertion
 | 
			
		||||
        const decodedErc20AssetData = decodedAssetData.nestedAssetData[0] as ERC20AssetData;
 | 
			
		||||
        expect(decodedErc20AssetData.tokenAddress).to.equal(KNOWN_ERC20_ENCODING.address);
 | 
			
		||||
        expect(decodedErc20AssetData.assetProxyId).to.equal(AssetProxyId.ERC20);
 | 
			
		||||
        // tslint:disable-next-line:no-unnecessary-type-assertion
 | 
			
		||||
        const decodedErc721AssetData = decodedAssetData.nestedAssetData[1] as ERC721AssetData;
 | 
			
		||||
        expect(decodedErc721AssetData.tokenAddress).to.equal(KNOWN_ERC721_ENCODING.address);
 | 
			
		||||
        expect(decodedErc721AssetData.assetProxyId).to.equal(AssetProxyId.ERC721);
 | 
			
		||||
        expect(decodedErc721AssetData.tokenId).to.be.bignumber.equal(KNOWN_ERC721_ENCODING.tokenId);
 | 
			
		||||
        // tslint:disable-next-line:no-unnecessary-type-assertion
 | 
			
		||||
        const decodedErc1155AssetData = decodedAssetData.nestedAssetData[2] as ERC1155AssetData;
 | 
			
		||||
        expect(decodedErc1155AssetData.tokenAddress).to.be.equal(KNOWN_ERC1155_ENCODING.tokenAddress);
 | 
			
		||||
        expect(decodedErc1155AssetData.tokenValues).to.be.deep.equal(KNOWN_ERC1155_ENCODING.tokenValues);
 | 
			
		||||
        expect(decodedErc1155AssetData.tokenIds).to.be.deep.equal(KNOWN_ERC1155_ENCODING.tokenIds);
 | 
			
		||||
        expect(decodedErc1155AssetData.callbackData).to.be.equal(KNOWN_ERC1155_ENCODING.callbackData);
 | 
			
		||||
    });
 | 
			
		||||
    it('should recursively decode nested assetData within multiAssetData', () => {
 | 
			
		||||
        // setup test parameters
 | 
			
		||||
        const erc20Amount = new BigNumber(1);
 | 
			
		||||
        const erc721Amount = new BigNumber(1);
 | 
			
		||||
        const erc1155Amount = new BigNumber(15);
 | 
			
		||||
        const nestedAssetsAmount = new BigNumber(2);
 | 
			
		||||
        const amounts = [erc20Amount, erc721Amount, erc1155Amount, nestedAssetsAmount];
 | 
			
		||||
        const nestedAssetData = [
 | 
			
		||||
            KNOWN_ERC20_ENCODING.assetData,
 | 
			
		||||
            KNOWN_ERC721_ENCODING.assetData,
 | 
			
		||||
            KNOWN_ERC1155_ENCODING.assetData,
 | 
			
		||||
            KNOWN_MULTI_ASSET_ENCODING.assetData,
 | 
			
		||||
        ];
 | 
			
		||||
        const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
        // execute test
 | 
			
		||||
        const decodedAssetData = assetDataUtils.decodeMultiAssetDataRecursively(assetData);
 | 
			
		||||
        // validate asset data
 | 
			
		||||
        expect(decodedAssetData.assetProxyId).to.equal(AssetProxyId.MultiAsset);
 | 
			
		||||
        const expectedAmounts = [
 | 
			
		||||
            erc20Amount,
 | 
			
		||||
            erc721Amount,
 | 
			
		||||
            erc1155Amount,
 | 
			
		||||
            KNOWN_MULTI_ASSET_ENCODING.amounts[0].times(nestedAssetsAmount),
 | 
			
		||||
            KNOWN_MULTI_ASSET_ENCODING.amounts[1].times(nestedAssetsAmount),
 | 
			
		||||
            KNOWN_MULTI_ASSET_ENCODING.amounts[2].times(nestedAssetsAmount),
 | 
			
		||||
        ];
 | 
			
		||||
        expect(decodedAssetData.amounts).to.deep.equal(expectedAmounts);
 | 
			
		||||
        const expectedNestedAssetDataLength = 6;
 | 
			
		||||
        expect(decodedAssetData.nestedAssetData.length).to.be.equal(expectedNestedAssetDataLength);
 | 
			
		||||
        // validate nested asset data (outer)
 | 
			
		||||
        let nestedAssetDataIndex = 0;
 | 
			
		||||
        // tslint:disable-next-line:no-unnecessary-type-assertion
 | 
			
		||||
        const decodedErc20AssetData1 = decodedAssetData.nestedAssetData[nestedAssetDataIndex++] as ERC20AssetData;
 | 
			
		||||
        expect(decodedErc20AssetData1.tokenAddress).to.equal(KNOWN_ERC20_ENCODING.address);
 | 
			
		||||
        expect(decodedErc20AssetData1.assetProxyId).to.equal(AssetProxyId.ERC20);
 | 
			
		||||
        // tslint:disable-next-line:no-unnecessary-type-assertion
 | 
			
		||||
        const decodedErc721AssetData1 = decodedAssetData.nestedAssetData[nestedAssetDataIndex++] as ERC721AssetData;
 | 
			
		||||
        expect(decodedErc721AssetData1.tokenAddress).to.equal(KNOWN_ERC721_ENCODING.address);
 | 
			
		||||
        expect(decodedErc721AssetData1.assetProxyId).to.equal(AssetProxyId.ERC721);
 | 
			
		||||
        // tslint:disable-next-line:no-unnecessary-type-assertion
 | 
			
		||||
        const decodedErc1155AssetData1 = decodedAssetData.nestedAssetData[nestedAssetDataIndex++] as ERC1155AssetData;
 | 
			
		||||
        expect(decodedErc1155AssetData1.tokenAddress).to.be.equal(KNOWN_ERC1155_ENCODING.tokenAddress);
 | 
			
		||||
        expect(decodedErc1155AssetData1.tokenValues).to.be.deep.equal(KNOWN_ERC1155_ENCODING.tokenValues);
 | 
			
		||||
        expect(decodedErc1155AssetData1.tokenIds).to.be.deep.equal(KNOWN_ERC1155_ENCODING.tokenIds);
 | 
			
		||||
        expect(decodedErc1155AssetData1.callbackData).to.be.equal(KNOWN_ERC1155_ENCODING.callbackData);
 | 
			
		||||
        // validate nested asset data (inner)
 | 
			
		||||
        // tslint:disable-next-line:no-unnecessary-type-assertion
 | 
			
		||||
        const decodedErc20AssetData2 = decodedAssetData.nestedAssetData[nestedAssetDataIndex++] as ERC20AssetData;
 | 
			
		||||
        expect(decodedErc20AssetData2.tokenAddress).to.equal(KNOWN_ERC20_ENCODING.address);
 | 
			
		||||
        expect(decodedErc20AssetData2.assetProxyId).to.equal(AssetProxyId.ERC20);
 | 
			
		||||
        // tslint:disable-next-line:no-unnecessary-type-assertion
 | 
			
		||||
        const decodedErc721AssetData2 = decodedAssetData.nestedAssetData[nestedAssetDataIndex++] as ERC721AssetData;
 | 
			
		||||
        expect(decodedErc721AssetData2.tokenAddress).to.equal(KNOWN_ERC721_ENCODING.address);
 | 
			
		||||
        expect(decodedErc721AssetData2.assetProxyId).to.equal(AssetProxyId.ERC721);
 | 
			
		||||
        // tslint:disable-next-line:no-unnecessary-type-assertion
 | 
			
		||||
        const decodedErc1155AssetData2 = decodedAssetData.nestedAssetData[nestedAssetDataIndex++] as ERC1155AssetData;
 | 
			
		||||
        expect(decodedErc1155AssetData2.tokenAddress).to.be.equal(KNOWN_ERC1155_ENCODING.tokenAddress);
 | 
			
		||||
        expect(decodedErc1155AssetData2.tokenValues).to.be.deep.equal(KNOWN_ERC1155_ENCODING.tokenValues);
 | 
			
		||||
        expect(decodedErc1155AssetData2.tokenIds).to.be.deep.equal(KNOWN_ERC1155_ENCODING.tokenIds);
 | 
			
		||||
        expect(decodedErc1155AssetData2.callbackData).to.be.equal(KNOWN_ERC1155_ENCODING.callbackData);
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
		Reference in New Issue
	
	Block a user