From b85b1d3903a336d5691e05387140fcc1e8a41f16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Fri, 30 Aug 2024 14:59:23 -0600 Subject: [PATCH] fix: handle updated chain tip on rollbacks correctly (#261) * fix: rollbacks * test: status --- src/api/util/helpers.ts | 4 +-- src/pg/chainhook/chainhook-pg-store.ts | 6 +++- tests/api/nft.test.ts | 5 +++ tests/api/status.test.ts | 14 +++++++-- tests/chainhook/chainhook-observer.test.ts | 36 ---------------------- 5 files changed, 22 insertions(+), 43 deletions(-) diff --git a/src/api/util/helpers.ts b/src/api/util/helpers.ts index 11aa60b8..a6d3cf9f 100644 --- a/src/api/util/helpers.ts +++ b/src/api/util/helpers.ts @@ -32,9 +32,7 @@ export function parseMetadataLocaleBundle( if (locale.properties.length > 0) { const mergedProperties: MetadataPropertiesType = {}; for (const property of locale.properties) { - if (property.value) { - mergedProperties[property.name] = property.value as MetadataValueType; - } + mergedProperties[property.name] = property.value as MetadataValueType; } response.properties = mergedProperties; } diff --git a/src/pg/chainhook/chainhook-pg-store.ts b/src/pg/chainhook/chainhook-pg-store.ts index 9b7a1de1..86cb5087 100644 --- a/src/pg/chainhook/chainhook-pg-store.ts +++ b/src/pg/chainhook/chainhook-pg-store.ts @@ -39,6 +39,10 @@ export class ChainhookPgStore extends BasePgStoreModule { } finished in ${time.getElapsedSeconds()}s` ); } + if (payload.rollback.length) { + const earliestRolledBack = Math.min(...payload.rollback.map(r => r.block_identifier.index)); + await this.updateChainTipBlockHeight(earliestRolledBack - 1); + } for (const block of payload.apply) { if (block.block_identifier.index <= (await this.getLastIngestedBlockHeight())) { logger.info( @@ -114,7 +118,7 @@ export class ChainhookPgStore extends BasePgStoreModule { } async updateChainTipBlockHeight(blockHeight: number): Promise { - await this.sql`UPDATE chain_tip SET block_height = GREATEST(${blockHeight}, block_height)`; + await this.sql`UPDATE chain_tip SET block_height = ${blockHeight}`; } private async getLastIngestedBlockHeight(): Promise { diff --git a/tests/api/nft.test.ts b/tests/api/nft.test.ts index 15cdda3f..2f36d91f 100644 --- a/tests/api/nft.test.ts +++ b/tests/api/nft.test.ts @@ -221,6 +221,10 @@ describe('NFT routes', () => { name: 'prop3', value: true, }, + { + name: 'prop4', + value: false, + }, ], }, ], @@ -256,6 +260,7 @@ describe('NFT routes', () => { prop1: 'ABC', prop2: 1, prop3: true, + prop4: false, }, }, }); diff --git a/tests/api/status.test.ts b/tests/api/status.test.ts index 9f2b24de..7d5d031a 100644 --- a/tests/api/status.test.ts +++ b/tests/api/status.test.ts @@ -44,9 +44,13 @@ describe('Status routes', () => { db, 'SP2SYHR84SDJJDK8M09HFS4KBFXPPCX9H7RZ9YVTS.hello-world', DbSipNumber.sip009, - 1n + 4n ); await db.chainhook.updateChainTipBlockHeight(100); + await db.sql`UPDATE jobs SET status = 'failed' WHERE id = 2`; + await db.sql`UPDATE jobs SET status = 'invalid' WHERE id = 3`; + await db.sql`UPDATE jobs SET status = 'queued' WHERE id = 4`; + await db.sql`UPDATE jobs SET status = 'done' WHERE id = 5`; const response = await fastify.inject({ method: 'GET', url: '/metadata/v1/' }); const json = response.json(); @@ -57,13 +61,17 @@ describe('Status routes', () => { block_height: 100, }, job_queue: { - pending: 2, + pending: 1, + failed: 1, + invalid: 1, + queued: 1, + done: 1, }, token_contracts: { 'sip-009': 1, }, tokens: { - nft: 1, + nft: 4, }, }); }); diff --git a/tests/chainhook/chainhook-observer.test.ts b/tests/chainhook/chainhook-observer.test.ts index cfbe820f..024a8752 100644 --- a/tests/chainhook/chainhook-observer.test.ts +++ b/tests/chainhook/chainhook-observer.test.ts @@ -59,42 +59,6 @@ describe('Chainhook observer', () => { await expect(db.getChainTipBlockHeight()).resolves.toBe(101); }); - test('keeps only the highest chain tip value', async () => { - await db.chainhook.processPayload( - new TestChainhookPayloadBuilder() - .apply() - .block({ height: 100 }) - .transaction({ hash: '0x01', sender: 'SP1K1A1PMGW2ZJCNF46NWZWHG8TS1D23EGH1KNK60' }) - .contractDeploy('SP1K1A1PMGW2ZJCNF46NWZWHG8TS1D23EGH1KNK60.friedger-pool-nft', { - maps: [], - functions: [], - variables: [], - fungible_tokens: [], - non_fungible_tokens: [], - }) - .build() - ); - await expect(db.getChainTipBlockHeight()).resolves.toBe(100); - - await db.chainhook.processPayload( - new TestChainhookPayloadBuilder() - .apply() - .block({ height: 65 }) - .transaction({ hash: '0x01', sender: 'SP1K1A1PMGW2ZJCNF46NWZWHG8TS1D23EGH1KNK60' }) - .event({ - type: 'SmartContractEvent', - position: { index: 0 }, - data: { - contract_identifier: 'SP1K1A1PMGW2ZJCNF46NWZWHG8TS1D23EGH1KNK60.friedger-pool-nft', - topic: 'print', - raw_value: cvToHex(stringUtf8CV('test')), - }, - }) - .build() - ); - await expect(db.getChainTipBlockHeight()).resolves.toBe(100); - }); - test('enqueues dynamic tokens for refresh with standard interval', async () => { const address = 'SP1K1A1PMGW2ZJCNF46NWZWHG8TS1D23EGH1KNK60'; const contractId = `${address}.friedger-pool-nft`;