diff --git a/src/assets/Standards/CollectibleStandards/ERC1155/ERC1155Standard.ts b/src/assets/Standards/CollectibleStandards/ERC1155/ERC1155Standard.ts index 67a3a028086..9bee70ace4c 100644 --- a/src/assets/Standards/CollectibleStandards/ERC1155/ERC1155Standard.ts +++ b/src/assets/Standards/CollectibleStandards/ERC1155/ERC1155Standard.ts @@ -188,6 +188,10 @@ export class ERC1155Standard { image: string | undefined; }> => { const isERC1155 = await this.contractSupportsBase1155Interface(address); + + if (!isERC1155) { + throw new Error("This isn't a valid ERC1155 contract"); + } let tokenURI, image; if (tokenId) { @@ -209,14 +213,10 @@ export class ERC1155Standard { } // TODO consider querying to the metadata to get name. - if (isERC1155) { - return { - standard: ERC1155, - tokenURI, - image, - }; - } - - throw new Error("This isn't a valid ERC1155 contract"); + return { + standard: ERC1155, + tokenURI, + image, + }; }; } diff --git a/src/assets/Standards/CollectibleStandards/ERC721/ERC721Standard.test.ts b/src/assets/Standards/CollectibleStandards/ERC721/ERC721Standard.test.ts index fcdf46578b3..af3670c2170 100644 --- a/src/assets/Standards/CollectibleStandards/ERC721/ERC721Standard.test.ts +++ b/src/assets/Standards/CollectibleStandards/ERC721/ERC721Standard.test.ts @@ -10,6 +10,8 @@ const MAINNET_PROVIDER = new HttpProvider( const ERC721_GODSADDRESS = '0x6EbeAf8e8E946F0716E6533A6f2cefc83f60e8Ab'; const CRYPTO_KITTIES_ADDRESS = '0x06012c8cf97BEaD5deAe237070F9587f8E7A266d'; const ERC721_ENSADDRESS = '0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85'; +const ERC721_DECENTRALAND_ADDRESS = + '0xF87E31492Faf9A91B02Ee0dEAAd50d51d56D5d4d'; describe('ERC721Standard', () => { let erc721Standard: ERC721Standard; @@ -100,24 +102,6 @@ describe('ERC721Standard', () => { jsonrpc: '2.0', id: 4, method: 'eth_call', - params: [ - { - to: '0x6EbeAf8e8E946F0716E6533A6f2cefc83f60e8Ab', - data: '0x01ffc9a75b5e139f00000000000000000000000000000000000000000000000000000000', - }, - 'latest', - ], - }) - .reply(200, { - jsonrpc: '2.0', - id: 4, - result: - '0x0000000000000000000000000000000000000000000000000000000000000001', - }) - .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { - jsonrpc: '2.0', - id: 5, - method: 'eth_call', params: [ { to: '0x6EbeAf8e8E946F0716E6533A6f2cefc83f60e8Ab', @@ -128,13 +112,13 @@ describe('ERC721Standard', () => { }) .reply(200, { jsonrpc: '2.0', - id: 5, + id: 4, result: '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004474f445300000000000000000000000000000000000000000000000000000000', }) .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { jsonrpc: '2.0', - id: 6, + id: 5, method: 'eth_call', params: [ { @@ -146,10 +130,11 @@ describe('ERC721Standard', () => { }) .reply(200, { jsonrpc: '2.0', - id: 6, + id: 5, result: '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000e476f647320556e636861696e6564000000000000000000000000000000000000', }); + const expectedResult = { name: 'Gods Unchained', standard: 'ERC721', @@ -167,7 +152,7 @@ describe('ERC721Standard', () => { nock('https://mainnet.infura.io:443', { encodedQueryParams: true }) .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { jsonrpc: '2.0', - id: 7, + id: 6, method: 'eth_call', params: [ { @@ -179,31 +164,13 @@ describe('ERC721Standard', () => { }) .reply(200, { jsonrpc: '2.0', - id: 7, - result: - '0x0000000000000000000000000000000000000000000000000000000000000001', - }) - .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { - jsonrpc: '2.0', - id: 8, - method: 'eth_call', - params: [ - { - to: '0x6EbeAf8e8E946F0716E6533A6f2cefc83f60e8Ab', - data: '0x01ffc9a75b5e139f00000000000000000000000000000000000000000000000000000000', - }, - 'latest', - ], - }) - .reply(200, { - jsonrpc: '2.0', - id: 8, + id: 6, result: '0x0000000000000000000000000000000000000000000000000000000000000001', }) .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { jsonrpc: '2.0', - id: 9, + id: 7, method: 'eth_call', params: [ { @@ -215,13 +182,15 @@ describe('ERC721Standard', () => { }) .reply(200, { jsonrpc: '2.0', - id: 9, + id: 7, result: '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004474f445300000000000000000000000000000000000000000000000000000000', - }) + }); + + nock('https://mainnet.infura.io:443', { encodedQueryParams: true }) .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { jsonrpc: '2.0', - id: 10, + id: 8, method: 'eth_call', params: [ { @@ -233,13 +202,13 @@ describe('ERC721Standard', () => { }) .reply(200, { jsonrpc: '2.0', - id: 10, + id: 8, result: '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000e476f647320556e636861696e6564000000000000000000000000000000000000', }) .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { jsonrpc: '2.0', - id: 11, + id: 9, method: 'eth_call', params: [ { @@ -251,13 +220,13 @@ describe('ERC721Standard', () => { }) .reply(200, { jsonrpc: '2.0', - id: 11, + id: 9, result: '0x0000000000000000000000000000000000000000000000000000000000000001', }) .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { jsonrpc: '2.0', - id: 12, + id: 10, method: 'eth_call', params: [ { @@ -269,7 +238,7 @@ describe('ERC721Standard', () => { }) .reply(200, { jsonrpc: '2.0', - id: 12, + id: 10, result: '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002468747470733a2f2f6170692e676f6473756e636861696e65642e636f6d2f636172642f3400000000000000000000000000000000000000000000000000000000', }); @@ -302,25 +271,7 @@ describe('ERC721Standard', () => { nock('https://mainnet.infura.io:443', { encodedQueryParams: true }) .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { jsonrpc: '2.0', - id: 14, - method: 'eth_call', - params: [ - { - to: '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D', - data: '0x01ffc9a75b5e139f00000000000000000000000000000000000000000000000000000000', - }, - 'latest', - ], - }) - .reply(200, { - jsonrpc: '2.0', - id: 14, - result: - '0x0000000000000000000000000000000000000000000000000000000000000001', - }) - .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { - jsonrpc: '2.0', - id: 13, + id: 11, method: 'eth_call', params: [ { @@ -332,13 +283,13 @@ describe('ERC721Standard', () => { }) .reply(200, { jsonrpc: '2.0', - id: 13, + id: 11, result: '0x0000000000000000000000000000000000000000000000000000000000000001', }) .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { jsonrpc: '2.0', - id: 15, + id: 12, method: 'eth_call', params: [ { @@ -350,13 +301,13 @@ describe('ERC721Standard', () => { }) .reply(200, { jsonrpc: '2.0', - id: 15, + id: 12, result: '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000044241594300000000000000000000000000000000000000000000000000000000', }) .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { jsonrpc: '2.0', - id: 16, + id: 13, method: 'eth_call', params: [ { @@ -368,13 +319,13 @@ describe('ERC721Standard', () => { }) .reply(200, { jsonrpc: '2.0', - id: 16, + id: 13, result: '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000011426f7265644170655961636874436c7562000000000000000000000000000000', }) .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { jsonrpc: '2.0', - id: 17, + id: 14, method: 'eth_call', params: [ { @@ -386,7 +337,7 @@ describe('ERC721Standard', () => { }) .reply(200, { jsonrpc: '2.0', - id: 17, + id: 14, result: '0x0000000000000000000000000000000000000000000000000000000000000001', }); @@ -394,7 +345,7 @@ describe('ERC721Standard', () => { nock('https://mainnet.infura.io:443', { encodedQueryParams: true }) .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { jsonrpc: '2.0', - id: 18, + id: 15, method: 'eth_call', params: [ { @@ -406,7 +357,7 @@ describe('ERC721Standard', () => { }) .reply(200, { jsonrpc: '2.0', - id: 18, + id: 15, result: '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000037697066733a2f2f516d65536a53696e4870506e6d586d73704d6a776958794e367a533445397a63636172694752336a7863615774712f33000000000000000000', }); @@ -444,7 +395,7 @@ describe('ERC721Standard', () => { nock('https://mainnet.infura.io:443', { encodedQueryParams: true }) .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { jsonrpc: '2.0', - id: 19, + id: 16, method: 'eth_call', params: [ { @@ -456,27 +407,26 @@ describe('ERC721Standard', () => { }) .reply(200, { jsonrpc: '2.0', - id: 19, + id: 16, result: '0x0000000000000000000000000000000000000000000000000000000000000001', }) .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { jsonrpc: '2.0', - id: 20, + id: 17, method: 'eth_call', params: [ { to: '0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85', - data: '0x01ffc9a75b5e139f00000000000000000000000000000000000000000000000000000000', + data: '0x06fdde03', }, 'latest', ], }) .reply(200, { jsonrpc: '2.0', - id: 20, - result: - '0x0000000000000000000000000000000000000000000000000000000000000000', + id: 17, + error: { code: -32000, message: 'execution reverted' }, }); const expectedResult = { @@ -497,7 +447,7 @@ describe('ERC721Standard', () => { nock('https://mainnet.infura.io:443', { encodedQueryParams: true }) .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { jsonrpc: '2.0', - id: 21, + id: 20, method: 'eth_call', params: [ { @@ -509,9 +459,36 @@ describe('ERC721Standard', () => { }) .reply(200, { jsonrpc: '2.0', - id: 21, + id: 20, result: '0x0000000000000000000000000000000000000000000000000000000000000000', + }); + + const result = async () => { + await erc721Standard.getDetails(CRYPTO_KITTIES_ADDRESS, '4'); + }; + await expect(result).rejects.toThrow("This isn't a valid ERC721 contract"); + }); + + it('should return an object with any or all of name, tokenURI or symbol for a given contract that supports these methods even if it does not support the metadata interface', async () => { + nock('https://mainnet.infura.io:443', { encodedQueryParams: true }) + .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { + jsonrpc: '2.0', + id: 21, + method: 'eth_call', + params: [ + { + to: '0xF87E31492Faf9A91B02Ee0dEAAd50d51d56D5d4d', + data: '0x01ffc9a780ac58cd00000000000000000000000000000000000000000000000000000000', + }, + 'latest', + ], + }) + .reply(200, { + jsonrpc: '2.0', + id: 21, + result: + '0x0000000000000000000000000000000000000000000000000000000000000001', }) .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { jsonrpc: '2.0', @@ -519,8 +496,8 @@ describe('ERC721Standard', () => { method: 'eth_call', params: [ { - to: '0x06012c8cf97BEaD5deAe237070F9587f8E7A266d', - data: '0x01ffc9a75b5e139f00000000000000000000000000000000000000000000000000000000', + to: '0xF87E31492Faf9A91B02Ee0dEAAd50d51d56D5d4d', + data: '0x95d89b41', }, 'latest', ], @@ -529,12 +506,37 @@ describe('ERC721Standard', () => { jsonrpc: '2.0', id: 22, result: - '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000044c414e4400000000000000000000000000000000000000000000000000000000', + }) + .post('/v3/341eacb578dd44a1a049cbc5f6fd4035', { + jsonrpc: '2.0', + id: 23, + method: 'eth_call', + params: [ + { + to: '0xF87E31492Faf9A91B02Ee0dEAAd50d51d56D5d4d', + data: '0x06fdde03', + }, + 'latest', + ], + }) + .reply(200, { + jsonrpc: '2.0', + id: 23, + result: + '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000011446563656e7472616c616e64204c414e44000000000000000000000000000000', }); - - const result = async () => { - await erc721Standard.getDetails(CRYPTO_KITTIES_ADDRESS, '4'); + const expectedResult = { + name: 'Decentraland LAND', + standard: 'ERC721', + symbol: 'LAND', + tokenURI: undefined, }; - await expect(result).rejects.toThrow("This isn't a valid ERC721 contract"); + const details = await erc721Standard.getDetails( + ERC721_DECENTRALAND_ADDRESS, + IPFS_DEFAULT_GATEWAY_URL, + '2381976568446569244243622252022377480050', + ); + expect(details).toMatchObject(expectedResult); }); }); diff --git a/src/assets/Standards/CollectibleStandards/ERC721/ERC721Standard.ts b/src/assets/Standards/CollectibleStandards/ERC721/ERC721Standard.ts index 45324231c6b..ca4f9eebb84 100644 --- a/src/assets/Standards/CollectibleStandards/ERC721/ERC721Standard.ts +++ b/src/assets/Standards/CollectibleStandards/ERC721/ERC721Standard.ts @@ -221,46 +221,50 @@ export class ERC721Standard { name: string | undefined; image: string | undefined; }> => { - const [isERC721, supportsMetadata] = await Promise.all([ - this.contractSupportsBase721Interface(address), - this.contractSupportsMetadataInterface(address), - ]); - let tokenURI, symbol, name, image; - if (supportsMetadata) { - [symbol, name] = await Promise.all([ - this.getAssetSymbol(address), - this.getAssetName(address), - ]); + const isERC721 = await this.contractSupportsBase721Interface(address); + if (!isERC721) { + throw new Error("This isn't a valid ERC721 contract"); + } + + let tokenURI, image, symbol, name; - if (tokenId) { + // TODO upgrade to use Promise.allSettled for name/symbol when we can refactor to use es2020 in tsconfig + try { + symbol = await this.getAssetSymbol(address); + } catch { + // ignore + } + + try { + name = await this.getAssetName(address); + } catch { + // ignore + } + + if (tokenId) { + try { tokenURI = await this.getTokenURI(address, tokenId); if (tokenURI.startsWith('ipfs://')) { tokenURI = getFormattedIpfsUrl(ipfsGateway, tokenURI, true); } - try { - const response = await timeoutFetch(tokenURI); - const object = await response.json(); - image = object?.image; - if (image?.startsWith('ipfs://')) { - image = getFormattedIpfsUrl(ipfsGateway, image, true); - } - } catch { - // ignore + const response = await timeoutFetch(tokenURI); + const object = await response.json(); + image = object?.image; + if (image?.startsWith('ipfs://')) { + image = getFormattedIpfsUrl(ipfsGateway, image, true); } + } catch { + // ignore } } - if (isERC721) { - return { - standard: ERC721, - tokenURI, - symbol, - name, - image, - }; - } - - throw new Error("This isn't a valid ERC721 contract"); + return { + standard: ERC721, + tokenURI, + symbol, + name, + image, + }; }; }