Skip to content

Commit

Permalink
fix: 🐛 Support contracts throwing when asked for tokenURI
Browse files Browse the repository at this point in the history
Support the scenario where the NFT contract doesn't have a tokenURI for
an NFT already exchanged
  • Loading branch information
atoulme committed Dec 2, 2021
1 parent 2ba9630 commit 55aa44b
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 17 deletions.
5 changes: 3 additions & 2 deletions src/eth/responses.ts
Expand Up @@ -152,8 +152,9 @@ export interface NftBody {
from: string;
to: string;
index: string;
rawTokenURI: string;
tokenURI: string;
rawTokenURI: string | undefined;
tokenURI: string | undefined;
errorTokenURI: any | undefined;
metadata: any;
contract: string;
blockHash: string;
Expand Down
48 changes: 35 additions & 13 deletions src/nftwatcher.ts
Expand Up @@ -21,6 +21,7 @@ import { parseBlockTime } from './blockwatcher';
import { FormattedBlock, NftMessage } from './msgs';
import { ethers } from 'ethers';
import fetch from 'node-fetch';
import { JsonRpcError } from './eth/jsonrpc';

const abiDecoder = new ethers.utils.AbiCoder();
const maxResponseSize = 4096;
Expand Down Expand Up @@ -327,22 +328,42 @@ export class NFTWatcher implements ManagedResource {
formattedBlock: FormattedBlock,
blockTime: number
): Promise<NftMessage> {
const response = await this.ethClient.request(
ethCall(this.config.contractAddress, 'tokenURI(uint256)', [index.substr(2)], formattedBlock.number!)
);
let rawTokenURI = undefined;
let errorTokenURI;
try {
rawTokenURI = await this.ethClient.request(
ethCall(this.config.contractAddress, 'tokenURI(uint256)', [index.substr(2)], formattedBlock.number!)
);
} catch (e) {
if (e instanceof JsonRpcError) {
errorTokenURI = { code: e.code, data: e.data, decodedData: '' };
try {
// remove the first 10 characters: 0x and 4 bytes.
const decodeResults = abiDecoder.decode(['string'], '0x' + e.data.substr(10));
if (decodeResults.length == 1) {
const decoded = decodeResults[0];
errorTokenURI.decodedData = decoded;
}
} catch (abiDecodeError) {
warn(abiDecodeError);
}
}
}

let decoded = '';
let metadata: any = null;
try {
const decodeResults = abiDecoder.decode(['string'], response);
if (decodeResults.length == 1) {
decoded = decodeResults[0];
metadata = await this.fetchMetadata(decoded);
} else {
warn('Expected a string object, received %o', decodeResults);
if (rawTokenURI !== undefined) {
try {
const decodeResults = abiDecoder.decode(['string'], rawTokenURI);
if (decodeResults.length == 1) {
decoded = decodeResults[0];
metadata = await this.fetchMetadata(decoded);
} else {
warn('Expected a string object, received %o', decodeResults);
}
} catch (e) {
warn(e);
}
} catch (e) {
warn(e);
}
return {
body: {
Expand All @@ -352,7 +373,8 @@ export class NFTWatcher implements ManagedResource {
blockHash: formattedBlock.hash!,
blockNumber: formattedBlock.number!,
index: index,
rawTokenURI: response,
rawTokenURI: rawTokenURI,
errorTokenURI: errorTokenURI,
tokenURI: decoded,
metadata: metadata,
retrievalTime: this.collectRetrievalTime ? Math.floor(Date.now() / 1000) : 0,
Expand Down
17 changes: 17 additions & 0 deletions test/__snapshots__/nftwatcher.test.ts.snap
Expand Up @@ -7,6 +7,7 @@ Array [
"blockHash": "0x5499be815b61cb4676629c5366af723e55d11a859c563900c0d7b2371fc826b5",
"blockNumber": 19227319,
"contract": "0x22C1f6050E56d2876009903609a2cC3fEf83B415",
"errorTokenURI": undefined,
"from": "0x0000000000000000000000000000000000000000",
"index": "0x00000000000000000000000000000000000000000000000000000000002aa81f",
"metadata": Object {
Expand Down Expand Up @@ -60,6 +61,7 @@ Array [
"blockHash": "0x5499be815b61cb4676629c5366af723e55d11a859c563900c0d7b2371fc826b5",
"blockNumber": 19227319,
"contract": "0x22C1f6050E56d2876009903609a2cC3fEf83B415",
"errorTokenURI": undefined,
"from": "0x0000000000000000000000000000000000000000",
"index": "0x00000000000000000000000000000000000000000000000000000000002aa820",
"metadata": Object {
Expand Down Expand Up @@ -113,6 +115,7 @@ Array [
"blockHash": "0x5499be815b61cb4676629c5366af723e55d11a859c563900c0d7b2371fc826b5",
"blockNumber": 19227319,
"contract": "0x22C1f6050E56d2876009903609a2cC3fEf83B415",
"errorTokenURI": undefined,
"from": "0x0000000000000000000000000000000000000000",
"index": "0x00000000000000000000000000000000000000000000000000000000002aa821",
"metadata": Object {
Expand Down Expand Up @@ -166,6 +169,7 @@ Array [
"blockHash": "0x24d10bb06bf6b351f9046e03127d3b61841abdc35e5bcdaa8ca6f90b701d963d",
"blockNumber": 19227323,
"contract": "0x22C1f6050E56d2876009903609a2cC3fEf83B415",
"errorTokenURI": undefined,
"from": "0x0000000000000000000000000000000000000000",
"index": "0x00000000000000000000000000000000000000000000000000000000002aa822",
"metadata": Object {
Expand Down Expand Up @@ -219,6 +223,7 @@ Array [
"blockHash": "0x24d10bb06bf6b351f9046e03127d3b61841abdc35e5bcdaa8ca6f90b701d963d",
"blockNumber": 19227323,
"contract": "0x22C1f6050E56d2876009903609a2cC3fEf83B415",
"errorTokenURI": undefined,
"from": "0x0000000000000000000000000000000000000000",
"index": "0x00000000000000000000000000000000000000000000000000000000002aa823",
"metadata": Object {
Expand Down Expand Up @@ -281,6 +286,7 @@ Terms and Conditions: https://confirmed.onelink.me/mzYA/589f9ddf",
"blockHash": "0x24d10bb06bf6b351f9046e03127d3b61841abdc35e5bcdaa8ca6f90b701d963d",
"blockNumber": 19227323,
"contract": "0x22C1f6050E56d2876009903609a2cC3fEf83B415",
"errorTokenURI": undefined,
"from": "0x0000000000000000000000000000000000000000",
"index": "0x00000000000000000000000000000000000000000000000000000000002aa824",
"metadata": Object {
Expand Down Expand Up @@ -334,6 +340,7 @@ Terms and Conditions: https://confirmed.onelink.me/mzYA/589f9ddf",
"blockHash": "0x24d10bb06bf6b351f9046e03127d3b61841abdc35e5bcdaa8ca6f90b701d963d",
"blockNumber": 19227323,
"contract": "0x22C1f6050E56d2876009903609a2cC3fEf83B415",
"errorTokenURI": undefined,
"from": "0x0000000000000000000000000000000000000000",
"index": "0x00000000000000000000000000000000000000000000000000000000002aa825",
"metadata": Object {
Expand Down Expand Up @@ -392,6 +399,7 @@ Aquarium gear airdropped to players every 15 minutes! The crypto competition awa
"blockHash": "0x24d10bb06bf6b351f9046e03127d3b61841abdc35e5bcdaa8ca6f90b701d963d",
"blockNumber": 19227323,
"contract": "0x22C1f6050E56d2876009903609a2cC3fEf83B415",
"errorTokenURI": undefined,
"from": "0x0000000000000000000000000000000000000000",
"index": "0x00000000000000000000000000000000000000000000000000000000002aa826",
"metadata": Object {
Expand Down Expand Up @@ -445,6 +453,7 @@ Aquarium gear airdropped to players every 15 minutes! The crypto competition awa
"blockHash": "0x69508bf3d7a734215a6f6ea74c4bc0e019e6b8a30594b9a39088bc4bb161a56d",
"blockNumber": 19227324,
"contract": "0x22C1f6050E56d2876009903609a2cC3fEf83B415",
"errorTokenURI": undefined,
"from": "0x0000000000000000000000000000000000000000",
"index": "0x00000000000000000000000000000000000000000000000000000000002aa827",
"metadata": Object {
Expand Down Expand Up @@ -498,6 +507,7 @@ Aquarium gear airdropped to players every 15 minutes! The crypto competition awa
"blockHash": "0x69508bf3d7a734215a6f6ea74c4bc0e019e6b8a30594b9a39088bc4bb161a56d",
"blockNumber": 19227324,
"contract": "0x22C1f6050E56d2876009903609a2cC3fEf83B415",
"errorTokenURI": undefined,
"from": "0x0000000000000000000000000000000000000000",
"index": "0x00000000000000000000000000000000000000000000000000000000002aa828",
"metadata": Object {
Expand Down Expand Up @@ -551,6 +561,7 @@ Aquarium gear airdropped to players every 15 minutes! The crypto competition awa
"blockHash": "0x69508bf3d7a734215a6f6ea74c4bc0e019e6b8a30594b9a39088bc4bb161a56d",
"blockNumber": 19227324,
"contract": "0x22C1f6050E56d2876009903609a2cC3fEf83B415",
"errorTokenURI": undefined,
"from": "0x0000000000000000000000000000000000000000",
"index": "0x00000000000000000000000000000000000000000000000000000000002aa829",
"metadata": Object {
Expand Down Expand Up @@ -609,6 +620,7 @@ Aquarium gear airdropped to players every 15 minutes! The crypto competition awa
"blockHash": "0xd93aaf9039246440482d4cb3d546fae828d70e775d7a2e1dbe2733e093c30193",
"blockNumber": 19227325,
"contract": "0x22C1f6050E56d2876009903609a2cC3fEf83B415",
"errorTokenURI": undefined,
"from": "0x0000000000000000000000000000000000000000",
"index": "0x00000000000000000000000000000000000000000000000000000000002aa82a",
"metadata": Object {
Expand Down Expand Up @@ -668,6 +680,7 @@ POAP distributed directly to artist from SearchLight through secret passcode.",
"blockHash": "0xd93aaf9039246440482d4cb3d546fae828d70e775d7a2e1dbe2733e093c30193",
"blockNumber": 19227325,
"contract": "0x22C1f6050E56d2876009903609a2cC3fEf83B415",
"errorTokenURI": undefined,
"from": "0x0000000000000000000000000000000000000000",
"index": "0x00000000000000000000000000000000000000000000000000000000002aa82b",
"metadata": Object {
Expand Down Expand Up @@ -721,6 +734,7 @@ POAP distributed directly to artist from SearchLight through secret passcode.",
"blockHash": "0xbbfff3a829e108e5955c5396d52e64064867bb329a4b85b5b6ed4e8e12276dde",
"blockNumber": 19227326,
"contract": "0x22C1f6050E56d2876009903609a2cC3fEf83B415",
"errorTokenURI": undefined,
"from": "0x0000000000000000000000000000000000000000",
"index": "0x00000000000000000000000000000000000000000000000000000000002aa82c",
"metadata": Object {
Expand Down Expand Up @@ -774,6 +788,7 @@ POAP distributed directly to artist from SearchLight through secret passcode.",
"blockHash": "0x7cc10cc0d3464c0005512873f98ba4770bd656de0364c01659076bcf61ce306b",
"blockNumber": 19227327,
"contract": "0x22C1f6050E56d2876009903609a2cC3fEf83B415",
"errorTokenURI": undefined,
"from": "0x0000000000000000000000000000000000000000",
"index": "0x00000000000000000000000000000000000000000000000000000000002aa82d",
"metadata": Object {
Expand Down Expand Up @@ -827,6 +842,7 @@ POAP distributed directly to artist from SearchLight through secret passcode.",
"blockHash": "0x798e23ce6737bd08d38e00c083ca91e5dbf34ae90d7d24e024aac2a44ff24d53",
"blockNumber": 19227328,
"contract": "0x22C1f6050E56d2876009903609a2cC3fEf83B415",
"errorTokenURI": undefined,
"from": "0x0000000000000000000000000000000000000000",
"index": "0x00000000000000000000000000000000000000000000000000000000002aa82e",
"metadata": Object {
Expand Down Expand Up @@ -880,6 +896,7 @@ POAP distributed directly to artist from SearchLight through secret passcode.",
"blockHash": "0x798e23ce6737bd08d38e00c083ca91e5dbf34ae90d7d24e024aac2a44ff24d53",
"blockNumber": 19227328,
"contract": "0x22C1f6050E56d2876009903609a2cC3fEf83B415",
"errorTokenURI": undefined,
"from": "0x0000000000000000000000000000000000000000",
"index": "0x00000000000000000000000000000000000000000000000000000000002aa82f",
"metadata": Object {
Expand Down
4 changes: 2 additions & 2 deletions test/balancewatcher.test.ts
Expand Up @@ -36,7 +36,7 @@ test('balancewatcher', async () => {
checkpoint.setInitialBlockNumber(123);
const output = new TestOutput();
const contractInfoCache = new LRUCache<string, Promise<ContractInfo>>({ maxSize: 100 });
const nftWatcher = new BalanceWatcher({
const balanceWatcher = new BalanceWatcher({
checkpoint,
config: {
contractAddress: '0xe91d153e0b41518a2ce8dd3d7944fa863463a97d',
Expand All @@ -55,7 +55,7 @@ test('balancewatcher', async () => {
nodePlatform: MOCK_NODE_ADAPTER,
});

await nftWatcher.processChunk({ from: 19227319, to: 19227329 });
await balanceWatcher.processChunk({ from: 19227319, to: 19227329 });

expect(output.messages).toMatchSnapshot();
}
Expand Down

0 comments on commit 55aa44b

Please sign in to comment.