ERC1155 Asset Data tests + types

This commit is contained in:
Greg Hysen
2019-03-05 08:52:33 -08:00
parent 55c4fc9aca
commit 5704afc54c
5 changed files with 122 additions and 21 deletions

View File

@@ -1,4 +1,13 @@
[
{
"version": "7.1.0",
"changes": [
{
"note": "Added `encodeERC721AssetData` and `decodeERC721AssetData`",
"pr": 1661
}
]
},
{
"timestamp": 1551479279,
"version": "7.0.2",

View File

@@ -2,6 +2,9 @@ import {
AssetProxyId,
ERC20AssetData,
ERC721AssetData,
ERC1155AssetData,
ERC1155AssetDataAbi,
ERC1155AssetDataNoProxyId,
MultiAssetData,
MultiAssetDataWithRecursiveDecoding,
SingleAssetData,
@@ -73,6 +76,46 @@ export const assetDataUtils = {
tokenId: (decodedAssetData as any).tokenId,
};
},
/**
* Encodes a set of ERC1155 assets into an assetData string, usable in the makerAssetData or
* takerAssetData fields of a 0x order.
* @param tokenAddress The token address of the ERC1155 contract
* @param tokenIds The Id's of the ERC1155 tokens to transfer
* @param tokenValues The values of each respective token Id to transfer
* @param callbackData The data forwarded to a receiver, if receiver is a contract.
* @return The hex encoded assetData string
*/
encodeERC1155AssetData(
tokenAddress: string,
tokenIds: BigNumber[],
tokenValues: BigNumber[],
callbackData: string,
): string {
const abiEncoder = AbiEncoder.createMethod('ERC1155Token', ERC1155AssetDataAbi);
const args = [tokenAddress, tokenIds, tokenValues, callbackData];
const assetData = abiEncoder.encode(args, encodingRules);
return assetData;
},
/**
* Decodes an ERC1155 assetData hex string into it's corresponding ERC1155 components.
* @param assetData Hex encoded assetData string to decode
* @return An object containing the decoded tokenAddress, tokenIds, tokenValues, callbackData & assetProxyId
*/
decodeERC1155AssetData(assetData: string): ERC1155AssetData {
const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData);
if (assetProxyId !== AssetProxyId.ERC1155) {
throw new Error(`Invalid assetProxyId. Expected '${AssetProxyId.ERC1155}', got '${assetProxyId}'`);
}
const abiEncoder = AbiEncoder.createMethod('ERC1155Token', ERC1155AssetDataAbi);
const decodedAssetData = abiEncoder.decode(assetData, decodingRules) as ERC1155AssetDataNoProxyId;
return {
assetProxyId,
tokenAddress: decodedAssetData.tokenAddress,
tokenIds: decodedAssetData.tokenIds,
tokenValues: decodedAssetData.tokenValues,
callbackData: decodedAssetData.callbackData,
};
},
/**
* Encodes assetData for multiple AssetProxies into a single hex encoded assetData string, usable in the makerAssetData or
* takerAssetData fields in a 0x order.
@@ -94,23 +137,6 @@ export const assetDataUtils = {
const assetData = abiEncoder.encode(args, encodingRules);
return assetData;
},
/**
* Encodes assetData for multiple AssetProxies into a single hex encoded assetData string, usable in the makerAssetData or
* takerAssetData fields in a 0x order.
* @return The hex encoded assetData string
*/
encodeERC1155AssetData(
tokenAddress: string,
tokenIds: BigNumber[],
tokenValues: BigNumber[],
callbackData: string,
): string {
const abiEncoder = AbiEncoder.createMethod('ERC1155Token', ['address', 'uint256[]', 'uint256[]', 'bytes']);
const args = [tokenAddress, tokenIds, tokenValues, callbackData];
const assetData = abiEncoder.encode(args, encodingRules);
return assetData;
},
/**
* Decodes a MultiAsset assetData hex string into it's corresponding amounts and nestedAssetData
* @param assetData Hex encoded assetData string to decode
@@ -212,6 +238,13 @@ export const assetDataUtils = {
isERC721AssetData(decodedAssetData: SingleAssetData | MultiAssetData): decodedAssetData is ERC721AssetData {
return decodedAssetData.assetProxyId === AssetProxyId.ERC721;
},
/**
* Checks if the decoded asset data is valid ERC1155 data
* @param decodedAssetData The decoded asset data to check
*/
isERC1155AssetData(decodedAssetData: SingleAssetData | MultiAssetData): decodedAssetData is ERC1155AssetData {
return decodedAssetData.assetProxyId === AssetProxyId.ERC1155;
},
/**
* Checks if the decoded asset data is valid MultiAsset data
* @param decodedAssetData The decoded asset data to check
@@ -219,9 +252,6 @@ export const assetDataUtils = {
isMultiAssetData(decodedAssetData: SingleAssetData | MultiAssetData): decodedAssetData is MultiAssetData {
return decodedAssetData.assetProxyId === AssetProxyId.MultiAsset;
},
isER1155AssetData(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
@@ -264,6 +294,14 @@ export const assetDataUtils = {
);
}
},
/**
* Throws if the assetData is not ERC1155.
* @param assetData Hex encoded assetData string
*/
assertIsERC1155AssetData(assetData: string): void {
// If the asset data is correctly decoded then it is valid.
assetDataUtils.decodeERC1155AssetData(assetData);
},
/**
* Throws if the length or assetProxyId are invalid for the MultiAssetProxy.
* @param assetData Hex encoded assetData string
@@ -298,6 +336,9 @@ export const assetDataUtils = {
case AssetProxyId.ERC721:
assetDataUtils.assertIsERC721AssetData(assetData);
break;
case AssetProxyId.ERC1155:
assetDataUtils.assertIsERC1155AssetData(assetData);
break;
case AssetProxyId.MultiAsset:
assetDataUtils.assertIsMultiAssetData(assetData);
break;
@@ -308,7 +349,7 @@ export const assetDataUtils = {
/**
* Decode any assetData into it's corresponding assetData object
* @param assetData Hex encoded assetData string to decode
* @return Either a ERC20 or ERC721 assetData object
* @return Either a ERC20, ERC721, ERC1155, or MultiAsset assetData object
*/
decodeAssetDataOrThrow(assetData: string): SingleAssetData | MultiAssetData {
const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData);
@@ -319,6 +360,9 @@ export const assetDataUtils = {
case AssetProxyId.ERC721:
const erc721AssetData = assetDataUtils.decodeERC721AssetData(assetData);
return erc721AssetData;
case AssetProxyId.ERC1155:
const erc1155AssetData = assetDataUtils.decodeERC1155AssetData(assetData);
return erc1155AssetData;
case AssetProxyId.MultiAsset:
const multiAssetData = assetDataUtils.decodeMultiAssetData(assetData);
return multiAssetData;

View File

@@ -20,6 +20,14 @@ const KNOWN_ERC721_ENCODING = {
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:
'0x9645780d0000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000',
};
const KNOWN_MULTI_ASSET_ENCODING = {
amounts: [new BigNumber(1), new BigNumber(1)],
nestedAssetData: [KNOWN_ERC20_ENCODING.assetData, KNOWN_ERC721_ENCODING.assetData],
@@ -50,6 +58,23 @@ describe('assetDataUtils', () => {
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.decodeERC1155AssetData(KNOWN_ERC1155_ENCODING.assetData);
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 and ERC721 multiAssetData', () => {
const assetData = assetDataUtils.encodeMultiAssetData(
KNOWN_MULTI_ASSET_ENCODING.amounts,

View File

@@ -1,4 +1,13 @@
[
{
"version": "2.2.3",
"changes": [
{
"note": "Added `ERC1155AssetData`, `ERC1155AssetDataNoProxyId`, and `ERC1155AssetDataAbi`",
"pr": 1661
}
]
},
{
"version": "2.2.2",
"changes": [

View File

@@ -185,6 +185,20 @@ export interface ERC1155AssetData {
callbackData: string;
}
export interface ERC1155AssetDataNoProxyId {
tokenAddress: string,
tokenValues: BigNumber[],
tokenIds: BigNumber[],
callbackData: string
};
export const ERC1155AssetDataAbi = [
{name: 'tokenAddress', type: 'address'},
{name: 'tokenIds', type: 'uint256[]'},
{name: 'tokenValues', type: 'uint256[]'},
{name: 'callbackData', type: 'bytes'},
];
export type SingleAssetData = ERC20AssetData | ERC721AssetData | ERC1155AssetData;
export interface MultiAssetData {