From 572a6626308b85edfc66202e238964fffdd15ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Sun, 2 Apr 2023 19:13:34 -0600 Subject: [PATCH 1/2] fix: support FTs with missing metadata but correct token data --- jest.config.js | 5 +- .../queue/job/process-token-job.ts | 10 ++- tests/process-token-job.test.ts | 77 +++++++++++++++++++ 3 files changed, 87 insertions(+), 5 deletions(-) diff --git a/jest.config.js b/jest.config.js index 591e073e..c532797d 100644 --- a/jest.config.js +++ b/jest.config.js @@ -176,10 +176,7 @@ module.exports = { transform: {}, // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation - // transformIgnorePatterns: [ - // "/node_modules/", - // "\\.pnp\\.[^\\/]+$" - // ], + transformIgnorePatterns: ["./dist/.+\\.js"] // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them // unmockedModulePathPatterns: undefined, diff --git a/src/token-processor/queue/job/process-token-job.ts b/src/token-processor/queue/job/process-token-job.ts index b3a3d784..13a14c38 100644 --- a/src/token-processor/queue/job/process-token-job.ts +++ b/src/token-processor/queue/job/process-token-job.ts @@ -114,7 +114,15 @@ export class ProcessTokenJob extends Job { let metadataLocales: DbMetadataLocaleInsertBundle[] | undefined; if (uri) { - metadataLocales = await fetchAllMetadataLocalesFromBaseUri(uri, token); + try { + metadataLocales = await fetchAllMetadataLocalesFromBaseUri(uri, token); + } catch (error) { + // If the fetch error is retryable, rethrow for job retry. If it's not but we don't have any + // data to display otherwise, rethrow so we can mark the job as failed/invalid. + if (error instanceof RetryableJobError || !(name || symbol || fDecimals || fTotalSupply)) { + throw error; + } + } } const tokenValues: DbProcessedTokenUpdateBundle = { diff --git a/tests/process-token-job.test.ts b/tests/process-token-job.test.ts index f65f2335..db54b2ce 100644 --- a/tests/process-token-job.test.ts +++ b/tests/process-token-job.test.ts @@ -112,6 +112,83 @@ describe('ProcessTokenJob', () => { expect(token?.decimals).toBe(6); expect(token?.total_supply).toBe(1997500000000n); }); + + test('keeps contract FT info if metadata fetch fails', async () => { + const agent = new MockAgent(); + agent.disableNetConnect(); + const interceptor = agent.get( + `http://${ENV.STACKS_NODE_RPC_HOST}:${ENV.STACKS_NODE_RPC_PORT}` + ); + interceptor + .intercept({ + path: '/v2/contracts/call-read/ABCD/test-ft/get-name', + method: 'POST', + }) + .reply(200, { + okay: true, + result: cvToHex(stringUtf8CV('FooToken')), + }); + interceptor + .intercept({ + path: '/v2/contracts/call-read/ABCD/test-ft/get-token-uri', + method: 'POST', + }) + .reply(200, { + okay: true, + result: cvToHex(stringUtf8CV('http://m.io/{id}.json')), + }); + interceptor + .intercept({ + path: '/v2/contracts/call-read/ABCD/test-ft/get-symbol', + method: 'POST', + }) + .reply(200, { + okay: true, + result: cvToHex(stringUtf8CV('FOO')), + }); + interceptor + .intercept({ + path: '/v2/contracts/call-read/ABCD/test-ft/get-decimals', + method: 'POST', + }) + .reply(200, { + okay: true, + result: cvToHex(uintCV(6)), + }); + interceptor + .intercept({ + path: '/v2/contracts/call-read/ABCD/test-ft/get-total-supply', + method: 'POST', + }) + .reply(200, { + okay: true, + result: cvToHex(uintCV(1997500000000)), + }); + agent + .get('http://m.io') + .intercept({ + path: '/1.json', + method: 'GET', + }) + .reply(500, { message: 'server error' }) + .persist(); + setGlobalDispatcher(agent); + + const processor = new ProcessTokenJob({ db, job: tokenJob }); + await processor.work(); + + const token = await db.getToken({ id: 1 }); + expect(token).not.toBeUndefined(); + expect(token?.name).toBe('FooToken'); + expect(token?.symbol).toBe('FOO'); + expect(token?.decimals).toBe(6); + expect(token?.total_supply).toBe(1997500000000n); + const bundle = await db.getTokenMetadataBundle({ + contractPrincipal: 'ABCD.test-ft', + tokenNumber: 1, + }); + expect(bundle?.metadataLocale).toBeUndefined(); + }); }); describe('NFT', () => { From b1c42eb32142855f3f92f35150a924bcca38cd6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Sun, 2 Apr 2023 19:28:12 -0600 Subject: [PATCH 2/2] fix: add warn log --- src/token-processor/queue/job/process-token-job.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/token-processor/queue/job/process-token-job.ts b/src/token-processor/queue/job/process-token-job.ts index 13a14c38..eedbd63a 100644 --- a/src/token-processor/queue/job/process-token-job.ts +++ b/src/token-processor/queue/job/process-token-job.ts @@ -122,6 +122,10 @@ export class ProcessTokenJob extends Job { if (error instanceof RetryableJobError || !(name || symbol || fDecimals || fTotalSupply)) { throw error; } + logger.warn( + error, + `ProcessTokenJob ${this.description()} metadata fetch failed for ${uri}, continuing with contract data` + ); } }