Update AssetProxyUtils
This commit is contained in:
		
				
					committed by
					
						
						Amir Bandeali
					
				
			
			
				
	
			
			
			
						parent
						
							b7b0185baf
						
					
				
				
					commit
					08d22d2f3c
				
			@@ -1,8 +1,7 @@
 | 
				
			|||||||
import { AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0xproject/types';
 | 
					import { AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0xproject/types';
 | 
				
			||||||
import { BigNumber, NULL_BYTES } from '@0xproject/utils';
 | 
					import { BigNumber } from '@0xproject/utils';
 | 
				
			||||||
import BN = require('bn.js');
 | 
					import BN = require('bn.js');
 | 
				
			||||||
import ethUtil = require('ethereumjs-util');
 | 
					import ethUtil = require('ethereumjs-util');
 | 
				
			||||||
import * as _ from 'lodash';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const ERC20_ASSET_DATA_BYTE_LENGTH = 36;
 | 
					const ERC20_ASSET_DATA_BYTE_LENGTH = 36;
 | 
				
			||||||
const ERC721_ASSET_DATA_MINIMUM_BYTE_LENGTH = 53;
 | 
					const ERC721_ASSET_DATA_MINIMUM_BYTE_LENGTH = 53;
 | 
				
			||||||
@@ -11,6 +10,13 @@ const ERC721_ASSET_DATA_TOKEN_ID_OFFSET = 20;
 | 
				
			|||||||
const ERC721_ASSET_DATA_RECEIVER_DATA_LENGTH_OFFSET = 52;
 | 
					const ERC721_ASSET_DATA_RECEIVER_DATA_LENGTH_OFFSET = 52;
 | 
				
			||||||
const ERC721_ASSET_DATA_RECEIVER_DATA_OFFSET = 84;
 | 
					const ERC721_ASSET_DATA_RECEIVER_DATA_OFFSET = 84;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: Push upstream to DefinitelyTyped
 | 
				
			||||||
 | 
					interface EthAbi {
 | 
				
			||||||
 | 
					    simpleEncode(signature: string, ...args: any[]): Buffer;
 | 
				
			||||||
 | 
					    rawDecode(signature: string[], data: Buffer): any[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const ethAbi = require('ethereumjs-abi') as EthAbi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const assetProxyUtils = {
 | 
					export const assetProxyUtils = {
 | 
				
			||||||
    encodeAssetProxyId(assetProxyId: AssetProxyId): Buffer {
 | 
					    encodeAssetProxyId(assetProxyId: AssetProxyId): Buffer {
 | 
				
			||||||
        return ethUtil.toBuffer(assetProxyId);
 | 
					        return ethUtil.toBuffer(assetProxyId);
 | 
				
			||||||
@@ -55,123 +61,68 @@ export const assetProxyUtils = {
 | 
				
			|||||||
        return value;
 | 
					        return value;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    encodeERC20AssetData(tokenAddress: string): string {
 | 
					    encodeERC20AssetData(tokenAddress: string): string {
 | 
				
			||||||
        const encodedAssetProxyId = assetProxyUtils.encodeAssetProxyId(AssetProxyId.ERC20);
 | 
					        return ethUtil.bufferToHex(ethAbi.simpleEncode(
 | 
				
			||||||
        const encodedAddress = assetProxyUtils.encodeAddress(tokenAddress);
 | 
					            'ERC20Token(address)',
 | 
				
			||||||
        const encodedAssetData = Buffer.concat([encodedAssetProxyId, encodedAddress]);
 | 
					            tokenAddress,
 | 
				
			||||||
        const encodedAssetDataHex = ethUtil.bufferToHex(encodedAssetData);
 | 
					        ));
 | 
				
			||||||
        return encodedAssetDataHex;
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    decodeERC20AssetData(proxyData: string): ERC20AssetData {
 | 
					    decodeERC20AssetData(assetData: string): ERC20AssetData {
 | 
				
			||||||
        const encodedAssetData = ethUtil.toBuffer(proxyData);
 | 
					        const data = ethUtil.toBuffer(assetData);
 | 
				
			||||||
        if (encodedAssetData.byteLength !== ERC20_ASSET_DATA_BYTE_LENGTH) {
 | 
					        if (data.byteLength < ERC20_ASSET_DATA_BYTE_LENGTH) {
 | 
				
			||||||
            throw new Error(
 | 
					            throw new Error(
 | 
				
			||||||
                `Could not decode ERC20 Proxy Data. Expected length of encoded data to be ${ERC20_ASSET_DATA_BYTE_LENGTH}. Got ${
 | 
					                `Could not decode ERC20 Proxy Data. Expected length of encoded data to be at least ${ERC20_ASSET_DATA_BYTE_LENGTH}. Got ${data.byteLength}`,
 | 
				
			||||||
                    encodedAssetData.byteLength
 | 
					 | 
				
			||||||
                }`,
 | 
					 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        const encodedAssetProxyId = encodedAssetData.slice(0, 4);
 | 
					        const assetProxyId = ethUtil.bufferToHex(data.slice(0, 4));
 | 
				
			||||||
        const assetProxyId = assetProxyUtils.decodeAssetProxyId(encodedAssetProxyId);
 | 
					 | 
				
			||||||
        if (assetProxyId !== AssetProxyId.ERC20) {
 | 
					        if (assetProxyId !== AssetProxyId.ERC20) {
 | 
				
			||||||
            throw new Error(
 | 
					            throw new Error(
 | 
				
			||||||
                `Could not decode ERC20 Proxy Data. Expected Asset Proxy Id to be ERC20 (${
 | 
					                `Could not decode ERC20 Proxy Data. Expected Asset Proxy Id to be ERC20 (${AssetProxyId.ERC20}), but got ${assetProxyId}`,
 | 
				
			||||||
                    AssetProxyId.ERC20
 | 
					 | 
				
			||||||
                }), but got ${assetProxyId}`,
 | 
					 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        const encodedTokenAddress = encodedAssetData.slice(16, 20);
 | 
					        const [tokenAddress] = ethAbi.rawDecode(['address'], data.slice(4));
 | 
				
			||||||
        const tokenAddress = assetProxyUtils.decodeAddress(encodedTokenAddress);
 | 
					        return {
 | 
				
			||||||
        const erc20AssetData = {
 | 
					 | 
				
			||||||
            assetProxyId,
 | 
					            assetProxyId,
 | 
				
			||||||
            tokenAddress,
 | 
					            tokenAddress: ethUtil.addHexPrefix(tokenAddress),
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        return erc20AssetData;
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    encodeERC721AssetData(tokenAddress: string, tokenId: BigNumber, receiverData?: string): string {
 | 
					    encodeERC721AssetData(tokenAddress: string, tokenId: BigNumber, receiverData?: string): string {
 | 
				
			||||||
        const encodedAssetProxyId = assetProxyUtils.encodeAssetProxyId(AssetProxyId.ERC721);
 | 
					        // TODO: Pass `tokendId` as a BigNumber.
 | 
				
			||||||
        const encodedAddress = assetProxyUtils.encodeAddress(tokenAddress);
 | 
					        return ethUtil.bufferToHex(ethAbi.simpleEncode(
 | 
				
			||||||
        const encodedTokenId = assetProxyUtils.encodeUint256(tokenId);
 | 
					            'ERC721Token(address,uint256,bytes)',
 | 
				
			||||||
        let encodedAssetData = Buffer.concat([encodedAddress, encodedTokenId]);
 | 
					            tokenAddress,
 | 
				
			||||||
        if (!_.isUndefined(receiverData)) {
 | 
					            tokenId.toString(16),
 | 
				
			||||||
            const encodedReceiverData = ethUtil.toBuffer(receiverData);
 | 
					            ethUtil.toBuffer(receiverData || '0x'),
 | 
				
			||||||
            const receiverDataLength = new BigNumber(encodedReceiverData.byteLength);
 | 
					        ));
 | 
				
			||||||
            const encodedReceiverDataLength = assetProxyUtils.encodeUint256(receiverDataLength);
 | 
					 | 
				
			||||||
            encodedAssetData = Buffer.concat([encodedAssetData, encodedReceiverDataLength, encodedReceiverData]);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        encodedAssetData = Buffer.concat([encodedAssetProxyId, encodedAssetData]);
 | 
					 | 
				
			||||||
        const encodedAssetDataHex = ethUtil.bufferToHex(encodedAssetData);
 | 
					 | 
				
			||||||
        return encodedAssetDataHex;
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    decodeERC721AssetData(assetData: string): ERC721AssetData {
 | 
					    decodeERC721AssetData(assetData: string): ERC721AssetData {
 | 
				
			||||||
 | 
					        const data = ethUtil.toBuffer(assetData);
 | 
				
			||||||
        const encodedAssetData = ethUtil.toBuffer(assetData);
 | 
					        if (data.byteLength < ERC721_ASSET_DATA_MINIMUM_BYTE_LENGTH) {
 | 
				
			||||||
        if (encodedAssetData.byteLength < ERC721_ASSET_DATA_MINIMUM_BYTE_LENGTH) {
 | 
					 | 
				
			||||||
            throw new Error(
 | 
					            throw new Error(
 | 
				
			||||||
                `Could not decode ERC20 Proxy Data. Expected length of encoded data to be at least ${ERC721_ASSET_DATA_MINIMUM_BYTE_LENGTH}. Got ${
 | 
					                `Could not decode ERC721 Asset Data. Expected length of encoded data to be at least ${ERC721_ASSET_DATA_MINIMUM_BYTE_LENGTH}. Got ${data.byteLength}`,
 | 
				
			||||||
                    encodedAssetData.byteLength
 | 
					 | 
				
			||||||
                }`,
 | 
					 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        const assetProxyId = ethUtil.bufferToHex(data.slice(0, 4));
 | 
				
			||||||
        console.log(rawDecode);
 | 
					 | 
				
			||||||
        //const result = ethAbi.rawDecode(['address', 'uint256', 'bytes'], encodedAssetData.slice(4));
 | 
					 | 
				
			||||||
        //console.log(result);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const encodedTokenAddress = encodedAssetData.slice(
 | 
					 | 
				
			||||||
            ASSET_DATA_ADDRESS_OFFSET,
 | 
					 | 
				
			||||||
            ERC721_ASSET_DATA_TOKEN_ID_OFFSET,
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        const encodedAssetProxyId = encodedAssetData.slice(0, 4);
 | 
					 | 
				
			||||||
        const assetProxyId = assetProxyUtils.decodeAssetProxyId(encodedAssetProxyId);
 | 
					 | 
				
			||||||
        if (assetProxyId !== AssetProxyId.ERC721) {
 | 
					        if (assetProxyId !== AssetProxyId.ERC721) {
 | 
				
			||||||
            throw new Error(
 | 
					            throw new Error(
 | 
				
			||||||
                `Could not decode ERC721 Proxy Data. Expected Asset Proxy Id to be ERC721 (${
 | 
					                `Could not decode ERC721 Asset Data. Expected Asset Proxy Id to be ERC721 (${AssetProxyId.ERC721}), but got ${assetProxyId}`,
 | 
				
			||||||
                    AssetProxyId.ERC721
 | 
					 | 
				
			||||||
                }), but got ${assetProxyId}`,
 | 
					 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        const tokenAddress = assetProxyUtils.decodeAddress(encodedTokenAddress);
 | 
					        const [tokenAddress, tokenId, receiverData] = ethAbi.rawDecode(
 | 
				
			||||||
        const encodedTokenId = encodedAssetData.slice(
 | 
					            ['address', 'uint256', 'bytes'],
 | 
				
			||||||
            ERC721_ASSET_DATA_TOKEN_ID_OFFSET,
 | 
					            data.slice(4),
 | 
				
			||||||
            ERC721_ASSET_DATA_RECEIVER_DATA_LENGTH_OFFSET,
 | 
					 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        const tokenId = assetProxyUtils.decodeUint256(encodedTokenId);
 | 
					        return {
 | 
				
			||||||
        let receiverData = NULL_BYTES;
 | 
					 | 
				
			||||||
        const lengthUpToReceiverDataLength = ERC721_ASSET_DATA_RECEIVER_DATA_LENGTH_OFFSET + 1;
 | 
					 | 
				
			||||||
        if (encodedAssetData.byteLength > lengthUpToReceiverDataLength) {
 | 
					 | 
				
			||||||
            const encodedReceiverDataLength = encodedAssetData.slice(
 | 
					 | 
				
			||||||
                ERC721_ASSET_DATA_RECEIVER_DATA_LENGTH_OFFSET,
 | 
					 | 
				
			||||||
                ERC721_ASSET_DATA_RECEIVER_DATA_OFFSET,
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
            const receiverDataLength = assetProxyUtils.decodeUint256(encodedReceiverDataLength);
 | 
					 | 
				
			||||||
            const lengthUpToReceiverData = ERC721_ASSET_DATA_RECEIVER_DATA_OFFSET + 1;
 | 
					 | 
				
			||||||
            const expectedReceiverDataLength = new BigNumber(encodedAssetData.byteLength - lengthUpToReceiverData);
 | 
					 | 
				
			||||||
            if (!receiverDataLength.equals(expectedReceiverDataLength)) {
 | 
					 | 
				
			||||||
                throw new Error(
 | 
					 | 
				
			||||||
                    `Data length (${receiverDataLength}) does not match actual length of data (${expectedReceiverDataLength})`,
 | 
					 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            const encodedReceiverData = encodedAssetData.slice(
 | 
					 | 
				
			||||||
                ERC721_ASSET_DATA_RECEIVER_DATA_OFFSET,
 | 
					 | 
				
			||||||
                receiverDataLength.add(ERC721_ASSET_DATA_RECEIVER_DATA_OFFSET).toNumber(),
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
            receiverData = ethUtil.bufferToHex(encodedReceiverData);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        const erc721AssetData: ERC721AssetData = {
 | 
					 | 
				
			||||||
            assetProxyId,
 | 
					            assetProxyId,
 | 
				
			||||||
            tokenAddress,
 | 
					            tokenAddress: ethUtil.addHexPrefix(tokenAddress),
 | 
				
			||||||
            tokenId,
 | 
					            tokenId: new BigNumber(tokenId.toString()),
 | 
				
			||||||
            receiverData,
 | 
					            receiverData: ethUtil.bufferToHex(receiverData),
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        return erc721AssetData;
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    decodeAssetDataId(assetData: string): AssetProxyId {
 | 
					    decodeAssetDataId(assetData: string): AssetProxyId {
 | 
				
			||||||
        const encodedAssetData = ethUtil.toBuffer(assetData);
 | 
					        const encodedAssetData = ethUtil.toBuffer(assetData);
 | 
				
			||||||
        if (encodedAssetData.byteLength < 4) {
 | 
					        if (encodedAssetData.byteLength < 4) {
 | 
				
			||||||
            throw new Error(
 | 
					            throw new Error(
 | 
				
			||||||
                `Could not decode Proxy Data. Expected length of encoded data to be at least 4. Got ${
 | 
					                `Could not decode Proxy Data. Expected length of encoded data to be at least 4. Got ${encodedAssetData.byteLength}`,
 | 
				
			||||||
                    encodedAssetData.byteLength
 | 
					 | 
				
			||||||
                }`,
 | 
					 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        const encodedAssetProxyId = encodedAssetData.slice(0, 4);
 | 
					        const encodedAssetProxyId = encodedAssetData.slice(0, 4);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user