diff --git a/src/pg/pg-store.ts b/src/pg/pg-store.ts index 5fd601aa..ff663ec1 100644 --- a/src/pg/pg-store.ts +++ b/src/pg/pg-store.ts @@ -87,6 +87,12 @@ export class PgStore extends BasePgStore { async updateInscriptions(payload: Payload): Promise { let updatedBlockHeightMin = Infinity; await this.sqlWriteTransaction(async sql => { + // Check where we're at in terms of ingestion, e.g. block height and max blessed inscription + // number. This will let us determine if we should skip ingesting this block or throw an error + // if a gap is detected. + let blessedNumber = (await this.getMaxInscriptionNumber()) ?? -1; + const currentBlockHeight = await this.getChainTipBlockHeight(); + for (const rollbackEvent of payload.rollback) { // TODO: Optimize rollbacks just as we optimized applys. const event = rollbackEvent as BitcoinEvent; @@ -118,6 +124,12 @@ export class PgStore extends BasePgStore { for (const applyEvent of payload.apply) { const event = applyEvent as BitcoinEvent; const block_height = event.block_identifier.index; + if (block_height <= currentBlockHeight && block_height !== 767430) { + logger.info( + `PgStore skipping ingestion for previously seen block ${block_height}, current chain tip is at ${currentBlockHeight}` + ); + return; + } const block_hash = normalizedHexString(event.block_identifier.hash); const writes: DbRevealInsert[] = []; for (const tx of event.transactions) { @@ -125,6 +137,11 @@ export class PgStore extends BasePgStore { for (const operation of tx.metadata.ordinal_operations) { if (operation.inscription_revealed) { const reveal = operation.inscription_revealed; + if (blessedNumber + 1 !== reveal.inscription_number) + throw Error( + `PgStore inscription gap detected: Attempting to insert #${reveal.inscription_number} (${block_height}) but current max is #${blessedNumber}` + ); + blessedNumber = reveal.inscription_number; const satoshi = new OrdinalSatoshi(reveal.ordinal_number); const satpoint = parseSatPoint(reveal.satpoint_post_inscription); const recursive_refs = getInscriptionRecursion(reveal.content_bytes); @@ -237,15 +254,8 @@ export class PgStore extends BasePgStore { } }); await this.refreshMaterializedView('chain_tip'); - // Skip expensive view refreshes if we're not streaming live blocks. - if (payload.chainhook.is_streaming_blocks) { - // We'll issue materialized view refreshes in parallel. We will not wait for them to finish so - // we can respond to the chainhook node with a `200` HTTP code as soon as possible. - const views = [this.normalizeInscriptionCount({ min_block_height: updatedBlockHeightMin })]; - const viewRefresh = Promise.allSettled(views); - // Only wait for these on tests. - if (isTestEnv) await viewRefresh; - } + if (updatedBlockHeightMin !== Infinity) + await this.normalizeInscriptionCount({ min_block_height: updatedBlockHeightMin }); } async getChainTipBlockHeight(): Promise { @@ -403,8 +413,10 @@ export class PgStore extends BasePgStore { } ${filters?.to_sat_ordinal ? sql`AND i.sat_ordinal <= ${filters.to_sat_ordinal}` : sql``} ${filters?.number?.length ? sql`AND i.number IN ${sql(filters.number)}` : sql``} - ${filters?.from_number ? sql`AND i.number >= ${filters.from_number}` : sql``} - ${filters?.to_number ? sql`AND i.number <= ${filters.to_number}` : sql``} + ${ + filters?.from_number !== undefined ? sql`AND i.number >= ${filters.from_number}` : sql`` + } + ${filters?.to_number !== undefined ? sql`AND i.number <= ${filters.to_number}` : sql``} ${filters?.address?.length ? sql`AND cur.address IN ${sql(filters.address)}` : sql``} ${filters?.mime_type?.length ? sql`AND i.mime_type IN ${sql(filters.mime_type)}` : sql``} ${filters?.output ? sql`AND cur_l.output = ${filters.output}` : sql``} @@ -648,7 +660,6 @@ export class PgStore extends BasePgStore { SET updated_at = NOW() WHERE genesis_id IN ${sql([...transferGenesisIds])} `; - await this.backfillOrphanLocations(); await this.updateInscriptionLocationPointers(locations); await this.counts.applyInscriptions(inscriptions); } @@ -825,21 +836,6 @@ export class PgStore extends BasePgStore { }); } - private async backfillOrphanLocations(): Promise { - await this.sqlWriteTransaction(async sql => { - await sql` - UPDATE locations AS l - SET inscription_id = (SELECT id FROM inscriptions WHERE genesis_id = l.genesis_id) - WHERE l.inscription_id IS NULL - `; - await sql` - UPDATE inscription_recursions AS l - SET ref_inscription_id = (SELECT id FROM inscriptions WHERE genesis_id = l.ref_inscription_genesis_id) - WHERE l.ref_inscription_id IS NULL - `; - }); - } - private async recalculateCurrentLocationPointerFromLocationRollBack(args: { location: DbLocation; }): Promise { diff --git a/tests/brc20.test.ts b/tests/brc20.test.ts index fa206798..12c8cfb2 100644 --- a/tests/brc20.test.ts +++ b/tests/brc20.test.ts @@ -36,7 +36,7 @@ describe('BRC-20', () => { tick: 'PEPE', max: '250000', }, - number: 5, + number: 0, tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', address: address, }) @@ -61,7 +61,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '10000', }, - number: 6, + number: 1, tx_id: '3b55f624eaa4f8de6c42e0c490176b67123a83094384f658611faf7bfb85dd0f', address: address, }) @@ -86,7 +86,7 @@ describe('BRC-20', () => { const content = Buffer.from(JSON.stringify(json), 'utf-8'); const insert: DbInscriptionInsert = { genesis_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - number: 1, + number: 0, mime_type: 'application/json', content_type: 'application/json', content_length: content.length, @@ -113,7 +113,7 @@ describe('BRC-20', () => { ); const insert: DbInscriptionInsert = { genesis_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - number: 1, + number: 0, mime_type: 'foo/bar', content_type: 'foo/bar;x=1', content_length: content.length, @@ -141,7 +141,7 @@ describe('BRC-20', () => { ); const insert: DbInscriptionInsert = { genesis_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - number: 1, + number: 0, mime_type: 'application/json', content_type: 'application/json', content_length: content.length, @@ -487,7 +487,7 @@ describe('BRC-20', () => { tick: 'PEPE', max: '21000000', }, - number: 5, + number: 0, tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', }) @@ -507,7 +507,7 @@ describe('BRC-20', () => { block_height: 775617, decimals: 18, id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - number: 5, + number: 0, mint_limit: null, max_supply: '21000000.000000000000000000', ticker: 'PEPE', @@ -538,7 +538,7 @@ describe('BRC-20', () => { tick: 'PEPE', max: '21000000', }, - number: 5, + number: 0, tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', }) @@ -563,7 +563,7 @@ describe('BRC-20', () => { tick: 'PEPE', max: '19000000', }, - number: 6, + number: 1, tx_id: '3f8067a6e9b45308b5a090c2987feeb2d08cbaf814ef2ffabad7c381b62f5f7e', address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', }) @@ -585,7 +585,7 @@ describe('BRC-20', () => { id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', max_supply: '21000000.000000000000000000', mint_limit: null, - number: 5, + number: 0, ticker: 'PEPE', tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', deploy_timestamp: 1677803510000, @@ -614,7 +614,7 @@ describe('BRC-20', () => { tick: 'PEPE', max: '21000000', }, - number: 5, + number: 0, tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', }) @@ -639,7 +639,7 @@ describe('BRC-20', () => { tick: 'pepe', max: '19000000', }, - number: 6, + number: 1, tx_id: '3f8067a6e9b45308b5a090c2987feeb2d08cbaf814ef2ffabad7c381b62f5f7e', address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', }) @@ -661,7 +661,7 @@ describe('BRC-20', () => { id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', max_supply: '21000000.000000000000000000', mint_limit: null, - number: 5, + number: 0, ticker: 'PEPE', tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', deploy_timestamp: 1677803510000, @@ -684,7 +684,7 @@ describe('BRC-20', () => { id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', max_supply: '21000000.000000000000000000', mint_limit: null, - number: 5, + number: 0, ticker: 'PEPE', tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', deploy_timestamp: 1677803510000, @@ -716,7 +716,7 @@ describe('BRC-20', () => { tick: 'PEPE', max: '21000000', }, - number: 5, + number: 0, tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', address: address, }) @@ -741,7 +741,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '250000', }, - number: 6, + number: 1, tx_id: '8aec77f855549d98cb9fb5f35e02a03f9a2354fd05a5f89fc610b32c3b01f99f', address: address, }) @@ -784,7 +784,7 @@ describe('BRC-20', () => { tick: 'pepe', amt: '100000', }, - number: 7, + number: 2, tx_id: '7a1adbc3e93ddf8d7c4e0ba75aa11c98c431521dd850be8b955feedb716d8bec', address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', }) @@ -842,7 +842,7 @@ describe('BRC-20', () => { tick: 'PEPE', max: '21000000', }, - number: 5, + number: 0, tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', address: address, }) @@ -867,7 +867,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '250000', }, - number: 6, + number: 1, tx_id: '8aec77f855549d98cb9fb5f35e02a03f9a2354fd05a5f89fc610b32c3b01f99f', address: address, }) @@ -893,7 +893,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '250000', }, - number: 6, + number: 1, tx_id: '8aec77f855549d98cb9fb5f35e02a03f9a2354fd05a5f89fc610b32c3b01f99f', address: address, }) @@ -938,7 +938,7 @@ describe('BRC-20', () => { max: '21000000', dec: '1', }, - number: 5, + number: 0, tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', address: address, }) @@ -963,7 +963,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '250000.000', // Invalid decimal count }, - number: 6, + number: 1, tx_id: '8aec77f855549d98cb9fb5f35e02a03f9a2354fd05a5f89fc610b32c3b01f99f', address: address, }) @@ -1002,7 +1002,7 @@ describe('BRC-20', () => { max: '2500', dec: '1', }, - number: 5, + number: 0, tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', address: address, }) @@ -1027,7 +1027,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '1000', }, - number: 6, + number: 1, tx_id: '3b55f624eaa4f8de6c42e0c490176b67123a83094384f658611faf7bfb85dd0f', address: address, }) @@ -1043,7 +1043,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '1000', }, - number: 7, + number: 2, tx_id: '7e09bda2cba34bca648cca6d79a074940d39b6137150d3a3edcf80c0e01419a5', address: address, }) @@ -1059,7 +1059,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '5000000000', // Exceeds supply }, - number: 8, + number: 3, tx_id: '8aec77f855549d98cb9fb5f35e02a03f9a2354fd05a5f89fc610b32c3b01f99f', address: address, }) @@ -1102,7 +1102,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '1000', }, - number: 9, + number: 4, tx_id: 'bf7a3e1a0647ca88f6539119b2defaec302683704ea270b3302e709597643548', address: address, }) @@ -1139,7 +1139,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '1000', }, - number: 6, + number: 0, tx_id: '3b55f624eaa4f8de6c42e0c490176b67123a83094384f658611faf7bfb85dd0f', address: address, }) @@ -1179,7 +1179,7 @@ describe('BRC-20', () => { dec: '1', lim: '100', }, - number: 5, + number: 0, tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', address: address, }) @@ -1204,7 +1204,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '1000', // Greater than limit }, - number: 6, + number: 1, tx_id: '3b55f624eaa4f8de6c42e0c490176b67123a83094384f658611faf7bfb85dd0f', address: address, }) @@ -1245,7 +1245,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '2000', }, - number: 7, + number: 2, tx_id: 'eee52b22397ea4a4aefe6a39931315e93a157091f5a994216c0aa9c8c6fef47a', address: address, }) @@ -1299,7 +1299,7 @@ describe('BRC-20', () => { tick: 'TEST', // Not found amt: '2000', }, - number: 7, + number: 2, tx_id: 'eee52b22397ea4a4aefe6a39931315e93a157091f5a994216c0aa9c8c6fef47a', address: address, }) @@ -1345,7 +1345,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '5000000000', // More than was minted }, - number: 7, + number: 2, tx_id: 'eee52b22397ea4a4aefe6a39931315e93a157091f5a994216c0aa9c8c6fef47a', address: address, }) @@ -1391,7 +1391,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '9000', }, - number: 7, + number: 2, tx_id: 'eee52b22397ea4a4aefe6a39931315e93a157091f5a994216c0aa9c8c6fef47a', address: address, }) @@ -1407,7 +1407,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '2000', // Will exceed available balance }, - number: 8, + number: 3, tx_id: '7edaa48337a94da327b6262830505f116775a32db5ad4ad46e87ecea33f21bac', address: address, }) @@ -1454,7 +1454,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '9000', }, - number: 7, + number: 2, tx_id: 'eee52b22397ea4a4aefe6a39931315e93a157091f5a994216c0aa9c8c6fef47a', address: address, }) @@ -1552,7 +1552,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '9000', }, - number: 7, + number: 2, tx_id: 'eee52b22397ea4a4aefe6a39931315e93a157091f5a994216c0aa9c8c6fef47a', address: address, }) @@ -1620,7 +1620,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '9000', }, - number: 7, + number: 2, tx_id: 'eee52b22397ea4a4aefe6a39931315e93a157091f5a994216c0aa9c8c6fef47a', address: address, }) @@ -1689,7 +1689,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '9000', }, - number: 7, + number: 2, tx_id: 'eee52b22397ea4a4aefe6a39931315e93a157091f5a994216c0aa9c8c6fef47a', address: address, }) @@ -1799,7 +1799,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '20', }, - number: 10, + number: 2, tx_id: '825a25b64b5d99ca30e04e53cc9a3020412e1054eb2a7523eb075ddd6d983205', address: address, }) @@ -1858,7 +1858,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '20', }, - number: 11, + number: 3, tx_id: '09a812f72275892b4858880cf3821004a6e8885817159b340639afe9952ac053', address: address2, }) @@ -1932,7 +1932,7 @@ describe('BRC-20', () => { tick: 'PEPE', max: '21000000', }, - number: 5, + number: 0, tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', }) @@ -1947,7 +1947,7 @@ describe('BRC-20', () => { expect(response.json()).toStrictEqual({ token: { id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - number: 5, + number: 0, block_height: 775617, tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', @@ -1968,7 +1968,7 @@ describe('BRC-20', () => { }); test('tokens filter by ticker prefix', async () => { - const inscriptionNumbers = incrementing(1); + const inscriptionNumbers = incrementing(0); const blockHeights = incrementing(775600); let transferHash = randomHash(); @@ -2076,7 +2076,7 @@ describe('BRC-20', () => { test('tokens using order_by tx_count', async () => { // Setup - const inscriptionNumbers = incrementing(1); + const inscriptionNumbers = incrementing(0); const blockHeights = incrementing(775600); const addressA = 'bc1q6uwuet65rm6xvlz7ztw2gvdmmay5uaycu03mqz'; const addressB = 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'; @@ -2317,7 +2317,7 @@ describe('BRC-20', () => { describe('/brc-20/activity', () => { test('activity for token transfers', async () => { // Setup - const inscriptionNumbers = incrementing(1); + const inscriptionNumbers = incrementing(0); const blockHeights = incrementing(775600); const addressA = 'bc1q6uwuet65rm6xvlz7ztw2gvdmmay5uaycu03mqz'; const addressB = 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'; @@ -2573,7 +2573,7 @@ describe('BRC-20', () => { // Step 7: B transfer_send the transfer to C // Setup - const inscriptionNumbers = incrementing(1); + const inscriptionNumbers = incrementing(0); const blockHeights = incrementing(775600); const addressA = 'bc1q6uwuet65rm6xvlz7ztw2gvdmmay5uaycu03mqz'; const addressB = 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'; @@ -3026,7 +3026,7 @@ describe('BRC-20', () => { }); test('activity for multiple token creation', async () => { - const inscriptionNumbers = incrementing(1); + const inscriptionNumbers = incrementing(0); const blockHeights = incrementing(775600); const addressA = 'bc1q6uwuet65rm6xvlz7ztw2gvdmmay5uaycu03mqz'; @@ -3179,7 +3179,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '2000', }, - number: 999, + number: 2, tx_id: '633648e0e1ddcab8dea0496a561f2b08c486ae619b5634d7bb55d7f0cd32ef16', address: 'bc1qp9jgp9qtlhgvwjnxclj6kav6nr2fq09c206pyl', }) @@ -3225,7 +3225,7 @@ describe('BRC-20', () => { tick: 'PEPE', max: '250000', }, - number: 5, + number: 0, tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', address: 'bc1qp9jgp9qtlhgvwjnxclj6kav6nr2fq09c206pyl', }) @@ -3276,7 +3276,7 @@ describe('BRC-20', () => { tick: 'PEPE', amt: '9000', }, - number: 7, + number: 2, tx_id: 'eee52b22397ea4a4aefe6a39931315e93a157091f5a994216c0aa9c8c6fef47a', address: address, }) @@ -3322,7 +3322,7 @@ describe('BRC-20', () => { tick: '🔥', max: '1000', }, - number: 50, + number: 3, tx_id: '8354e85e87fa2df8b3a06ec0b9d395559b95174530cb19447fc4df5f6d4ca84d', address: address, }) @@ -3346,7 +3346,7 @@ describe('BRC-20', () => { tick: '🔥', amt: '500', }, - number: 60, + number: 4, tx_id: '81f4ee2c247c5f5c0d3a6753fef706df410ea61c2aa6d370003b98beb041b887', address: address, }) @@ -3371,7 +3371,7 @@ describe('BRC-20', () => { tick: '🔥', amt: '100', }, - number: 90, + number: 5, tx_id: 'c1c7f1d5c10a30605a8a5285ca3465a4f75758ed9b7f201e5ef62727e179966f', address: address, }) diff --git a/tests/cache.test.ts b/tests/cache.test.ts index 6d7de35e..eda268f3 100644 --- a/tests/cache.test.ts +++ b/tests/cache.test.ts @@ -27,7 +27,7 @@ describe('ETag cache', () => { content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 2805, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, @@ -54,7 +54,7 @@ describe('ETag cache', () => { // Check on numbered id too const nResponse = await fastify.inject({ method: 'GET', - url: '/ordinals/v1/inscriptions/7', + url: '/ordinals/v1/inscriptions/0', }); expect(nResponse.statusCode).toBe(200); expect(nResponse.headers.etag).not.toBeUndefined(); @@ -70,7 +70,7 @@ describe('ETag cache', () => { expect(cached.statusCode).toBe(304); const nCached = await fastify.inject({ method: 'GET', - url: '/ordinals/v1/inscriptions/7', + url: '/ordinals/v1/inscriptions/0', headers: { 'if-none-match': etag1 }, }); expect(nCached.statusCode).toBe(304); @@ -79,7 +79,7 @@ describe('ETag cache', () => { await db.updateInscriptions( new TestChainhookPayloadBuilder() .apply() - .block({ height: 775700, timestamp: 1678122360 }) + .block({ height: 775618, timestamp: 1678122360 }) .transaction({ hash: '0xbdda0d240132bab2af7f797d1507beb1acab6ad43e2c0ef7f96291aea5cc3444', }) @@ -106,7 +106,7 @@ describe('ETag cache', () => { expect(cached2.statusCode).toBe(200); const nCached2 = await fastify.inject({ method: 'GET', - url: '/ordinals/v1/inscriptions/7', + url: '/ordinals/v1/inscriptions/0', headers: { 'if-none-match': etag1 }, }); expect(nCached2.statusCode).toBe(200); @@ -116,7 +116,7 @@ describe('ETag cache', () => { await db.updateInscriptions( new TestChainhookPayloadBuilder() .apply() - .block({ height: 775690, timestamp: 1678122360 }) + .block({ height: 775619, timestamp: 1678122360 }) .transaction({ hash: 'bebb1357c97d2348eb8ef24e1d8639ff79c8847bf12999ca7fef463489b40f0f', }) @@ -143,7 +143,7 @@ describe('ETag cache', () => { expect(cached3.statusCode).toBe(200); const nCached3 = await fastify.inject({ method: 'GET', - url: '/ordinals/v1/inscriptions/7', + url: '/ordinals/v1/inscriptions/0', headers: { 'if-none-match': etag2 }, }); expect(nCached3.statusCode).toBe(200); @@ -158,7 +158,7 @@ describe('ETag cache', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -176,13 +176,13 @@ describe('ETag cache', () => { await db.updateInscriptions(block1); const block2 = new TestChainhookPayloadBuilder() .apply() - .block({ height: 775617 }) + .block({ height: 778576 }) .transaction({ hash: '0x00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d' }) .inscriptionRevealed({ content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 2, + inscription_number: 1, inscription_fee: 2805, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, @@ -219,7 +219,7 @@ describe('ETag cache', () => { // New location const block3 = new TestChainhookPayloadBuilder() .apply() - .block({ height: 775618 }) + .block({ height: 778577 }) .transaction({ hash: 'ae9d273a10e899f0d2cad47ee2b0e77ab8a9addd9dd5bb5e4b03d6971c060d52' }) .inscriptionTransferred({ inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', @@ -242,39 +242,6 @@ describe('ETag cache', () => { headers: { 'if-none-match': etag }, }); expect(cached2.statusCode).toBe(200); - const etag2 = cached2.headers.etag; - - // Upsert genesis location - const block4 = new TestChainhookPayloadBuilder() - .apply() - .block({ height: 778575 }) - .transaction({ hash: '0x9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201' }) - .inscriptionRevealed({ - content_bytes: '0x48656C6C6F', - content_type: 'text/plain', - content_length: 5, - inscription_number: 7, - inscription_fee: 705, - inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', - inscription_output_value: 10000, - inscriber_address: 'bc1pscktlmn99gyzlvymvrezh6vwd0l4kg06tg5rvssw0czg8873gz5sdkteqj', - ordinal_number: 257418248345364, - ordinal_block_height: 650000, - ordinal_offset: 0, - satpoint_post_inscription: - '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201:0:0', - inscription_input_index: 0, - transfers_pre_inscription: 0, - tx_index: 0, - }) - .build(); - await db.updateInscriptions(block4); - const cached3 = await fastify.inject({ - method: 'GET', - url: '/ordinals/v1/inscriptions', - headers: { 'if-none-match': etag2 }, - }); - expect(cached3.statusCode).toBe(200); }); test('inscriptions stats per block cache control', async () => { @@ -286,7 +253,7 @@ describe('ETag cache', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -323,13 +290,13 @@ describe('ETag cache', () => { // New block const block2 = new TestChainhookPayloadBuilder() .apply() - .block({ height: 778577, hash: randomHash() }) + .block({ height: 778576, hash: randomHash() }) .transaction({ hash: '0x00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d' }) .inscriptionRevealed({ content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 2, + inscription_number: 1, inscription_fee: 2805, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, @@ -364,7 +331,7 @@ describe('ETag cache', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -401,13 +368,13 @@ describe('ETag cache', () => { // New block const block2 = new TestChainhookPayloadBuilder() .apply() - .block({ height: 778577, hash: randomHash() }) + .block({ height: 778576, hash: randomHash() }) .transaction({ hash: '0x00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d' }) .inscriptionRevealed({ content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 2, + inscription_number: 1, inscription_fee: 2805, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, diff --git a/tests/inscriptions.test.ts b/tests/inscriptions.test.ts index 6767fc0b..e101ac17 100644 --- a/tests/inscriptions.test.ts +++ b/tests/inscriptions.test.ts @@ -39,7 +39,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 188, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -59,7 +59,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '0x00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1676913207, }) @@ -70,7 +70,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 7, + inscription_number: 1, inscription_fee: 2805, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, @@ -90,14 +90,14 @@ describe('/inscriptions', () => { address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', genesis_address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', genesis_block_hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', - genesis_block_height: 775617, + genesis_block_height: 778576, content_length: 5, mime_type: 'image/png', content_type: 'image/png', genesis_fee: '2805', id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', offset: '0', - number: 7, + number: 1, value: '10000', tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', sat_ordinal: '257418248345364', @@ -124,7 +124,7 @@ describe('/inscriptions', () => { // By inscription number const response2 = await fastify.inject({ method: 'GET', - url: '/ordinals/v1/inscriptions/7', + url: '/ordinals/v1/inscriptions/1', }); expect(response2.statusCode).toBe(200); expect(response2.json()).toStrictEqual(expected); @@ -146,7 +146,7 @@ describe('/inscriptions', () => { content_bytes: `0x${Buffer.from('World').toString('hex')}`, content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 188, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -167,7 +167,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 189, + inscription_number: 1, inscription_fee: 2805, inscription_id: 'f351d86c6e6cae3c64e297e7463095732f216875bcc1f3c03f950a492bb25421i0', inscription_output_value: 10000, @@ -187,7 +187,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '0x00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1676913207, }) @@ -204,7 +204,7 @@ describe('/inscriptions', () => { ).toString('hex')}`, content_type: 'image/png', content_length: 5, - inscription_number: 7, + inscription_number: 2, inscription_fee: 2805, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, @@ -224,14 +224,14 @@ describe('/inscriptions', () => { address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', genesis_address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', genesis_block_hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', - genesis_block_height: 775617, + genesis_block_height: 778576, content_length: 5, mime_type: 'image/png', content_type: 'image/png', genesis_fee: '2805', id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', offset: '0', - number: 7, + number: 2, value: '10000', tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', sat_ordinal: '257418248345364', @@ -261,53 +261,10 @@ describe('/inscriptions', () => { // By inscription number const response2 = await fastify.inject({ method: 'GET', - url: '/ordinals/v1/inscriptions/7', + url: '/ordinals/v1/inscriptions/2', }); expect(response2.statusCode).toBe(200); expect(response2.json()).toStrictEqual(expected); - - // Backfill new inscription - await db.updateInscriptions( - new TestChainhookPayloadBuilder() - .apply() - .block({ - height: 778600, - hash: '000000000000000000043b10697970720b44c79f6ca2dd604cc83cc015e0c459', - timestamp: 1676913207, - }) - .transaction({ - hash: 'b4b27b9a15f928b95a8ce4b418946553b7b313a345254cd9b23d79489175fa5a', - }) - .inscriptionRevealed({ - content_bytes: `0x${Buffer.from('World').toString('hex')}`, - content_type: 'text/plain;charset=utf-8', - content_length: 5, - inscription_number: 200, - inscription_fee: 705, - inscription_id: 'b4b27b9a15f928b95a8ce4b418946553b7b313a345254cd9b23d79489175fa5ai0', - inscription_output_value: 10000, - inscriber_address: 'bc1pscktlmn99gyzlvymvrezh6vwd0l4kg06tg5rvssw0czg8873gz5sdkteqj', - ordinal_number: 257418248345364, - ordinal_block_height: 650000, - ordinal_offset: 0, - satpoint_post_inscription: - 'b4b27b9a15f928b95a8ce4b418946553b7b313a345254cd9b23d79489175fa5a:0:0', - tx_index: 0, - inscription_input_index: 0, - transfers_pre_inscription: 0, - }) - .build() - ); - const response3 = await fastify.inject({ - method: 'GET', - url: '/ordinals/v1/inscriptions/38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - }); - expect(response3.statusCode).toBe(200); - expect(response3.json().recursion_refs).toStrictEqual([ - '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', - 'f351d86c6e6cae3c64e297e7463095732f216875bcc1f3c03f950a492bb25421i0', - 'b4b27b9a15f928b95a8ce4b418946553b7b313a345254cd9b23d79489175fa5ai0', - ]); }); test('shows inscription with null genesis address', async () => { @@ -326,7 +283,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 2805, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, @@ -353,7 +310,7 @@ describe('/inscriptions', () => { genesis_fee: '2805', id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', offset: '0', - number: 7, + number: 0, value: '10000', tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', sat_ordinal: '257418248345364', @@ -380,7 +337,7 @@ describe('/inscriptions', () => { // By inscription number const response2 = await fastify.inject({ method: 'GET', - url: '/ordinals/v1/inscriptions/7', + url: '/ordinals/v1/inscriptions/0', }); expect(response2.statusCode).toBe(200); expect(response2.json()).toStrictEqual(expected); @@ -479,7 +436,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 2805, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, @@ -535,7 +492,7 @@ describe('/inscriptions', () => { genesis_fee: '2805', id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', offset: '0', - number: 7, + number: 0, value: '9000', tx_id: 'bdda0d240132bab2af7f797d1507beb1acab6ad43e2c0ef7f96291aea5cc3444', sat_ordinal: '257418248345364', @@ -590,7 +547,7 @@ describe('/inscriptions', () => { genesis_fee: '2805', id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', offset: '0', - number: 7, + number: 0, tx_id: 'e3af144354367de58c675e987febcb49f17d6c19e645728b833fe95408feab85', value: '8000', sat_ordinal: '257418248345364', @@ -607,127 +564,6 @@ describe('/inscriptions', () => { }); }); - test('shows correct inscription data after an unordered transfer', async () => { - await db.updateInscriptions( - new TestChainhookPayloadBuilder() - .apply() - .block({ - height: 775617, - hash: '0x00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', - timestamp: 1676913207, - }) - .transaction({ - hash: '0x38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', - }) - .inscriptionRevealed({ - content_bytes: '0x48656C6C6F', - content_type: 'image/png', - content_length: 5, - inscription_number: 7, - inscription_fee: 2805, - inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - inscription_output_value: 9000, - inscriber_address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', - ordinal_number: 257418248345364, - ordinal_block_height: 51483, - ordinal_offset: 0, - satpoint_post_inscription: - '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc:0:0', - inscription_input_index: 0, - transfers_pre_inscription: 0, - tx_index: 0, - }) - .build() - ); - - const response1 = await fastify.inject({ - method: 'GET', - url: '/ordinals/v1/inscriptions/38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - }); - expect(response1.statusCode).toBe(200); - expect(response1.json()).toStrictEqual({ - address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', - genesis_address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', - genesis_block_hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', - genesis_block_height: 775617, - content_length: 5, - mime_type: 'image/png', - content_type: 'image/png', - genesis_fee: '2805', - id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - offset: '0', - number: 7, - value: '9000', - tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', - sat_ordinal: '257418248345364', - sat_coinbase_height: 51483, - output: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc:0', - location: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc:0:0', - sat_rarity: 'common', - timestamp: 1676913207000, - genesis_timestamp: 1676913207000, - genesis_tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', - curse_type: null, - recursive: false, - recursion_refs: null, - }); - - // Insert real genesis - await db.updateInscriptions( - new TestChainhookPayloadBuilder() - .apply() - .block({ height: 775610, timestamp: 1678122360 }) - .transaction({ - hash: '0xbdda0d240132bab2af7f797d1507beb1acab6ad43e2c0ef7f96291aea5cc3444', - }) - .inscriptionTransferred({ - inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - destination: { - type: 'transferred', - value: 'bc1p3xqwzmddceqrd6x9yxplqzkl5vucta2gqm5szpkmpuvcvgs7g8psjf8htd', - }, - satpoint_pre_transfer: - '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc:0:0', - satpoint_post_transfer: - 'bdda0d240132bab2af7f797d1507beb1acab6ad43e2c0ef7f96291aea5cc3444:0:0', - post_transfer_output_value: 9000, - tx_index: 0, - }) - .build() - ); - const response = await fastify.inject({ - method: 'GET', - url: '/ordinals/v1/inscriptions/38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - }); - expect(response.statusCode).toBe(200); - expect(response.json()).toStrictEqual({ - address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', - genesis_address: 'bc1p3xqwzmddceqrd6x9yxplqzkl5vucta2gqm5szpkmpuvcvgs7g8psjf8htd', - genesis_block_hash: '163de66dc9c0949905bfe8e148bde04600223cf88d19f26fdbeba1d6e6fa0f88', - genesis_block_height: 775610, - content_length: 5, - mime_type: 'image/png', - content_type: 'image/png', - genesis_fee: '2805', - id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - offset: '0', - number: 7, - value: '9000', - tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', - sat_ordinal: '257418248345364', - sat_coinbase_height: 51483, - output: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc:0', - location: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc:0:0', - sat_rarity: 'common', - timestamp: 1676913207000, - genesis_timestamp: 1678122360000, - genesis_tx_id: 'bdda0d240132bab2af7f797d1507beb1acab6ad43e2c0ef7f96291aea5cc3444', - curse_type: null, - recursive: false, - recursion_refs: null, - }); - }); - test('shows correct data when multiple transfers happen in the same block', async () => { await db.updateInscriptions( new TestChainhookPayloadBuilder() @@ -744,7 +580,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 2805, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 9000, @@ -815,7 +651,7 @@ describe('/inscriptions', () => { genesis_fee: '2805', id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', offset: '0', - number: 7, + number: 0, value: '8000', tx_id: 'bdda0d240132bab2af7f797d1507beb1acab6ad43e2c0ef7f96291aea5cc3444', sat_ordinal: '257418248345364', @@ -995,7 +831,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 2805, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, @@ -1158,7 +994,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 2805, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, @@ -1179,7 +1015,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 8, + inscription_number: 1, inscription_fee: 2805, inscription_id: '7ac73ecd01b9da4a7eab904655416dbfe8e03f193e091761b5a63ad0963570cdi0', inscription_output_value: 10000, @@ -1259,7 +1095,7 @@ describe('/inscriptions', () => { expect(json2.results).toStrictEqual([ { id: '7ac73ecd01b9da4a7eab904655416dbfe8e03f193e091761b5a63ad0963570cdi0', - number: 8, + number: 1, from: { address: 'bc1ptrehxtus25xx8jp5pchljxg2aps7mdemc4264zzzsdcvs6q25hhsf3rrph', block_hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', @@ -1285,7 +1121,7 @@ describe('/inscriptions', () => { }, { id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - number: 7, + number: 0, from: { address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', block_hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', @@ -1362,7 +1198,7 @@ describe('/inscriptions', () => { expect(json3.results).toStrictEqual([ { id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - number: 7, + number: 0, from: { address: 'bc1pkx5me775s748lzchytzdsw4f0lq04wssxnyk27g8fn3gee8zhjjqsn9tfp', block_hash: '000000000000000000044b12039abd3112963959d9fd7510ac503ea84dc17002', @@ -1388,7 +1224,7 @@ describe('/inscriptions', () => { }, { id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - number: 7, + number: 0, from: { address: 'bc1p3xqwzmddceqrd6x9yxplqzkl5vucta2gqm5szpkmpuvcvgs7g8psjf8htd', block_hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7bbbb', @@ -1433,7 +1269,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -1453,7 +1289,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1676913207, }) @@ -1490,53 +1326,53 @@ describe('/inscriptions', () => { expect(responseJson1.total).toBe(2); expect(responseJson1.results).toStrictEqual([ { - address: 'bc1pscktlmn99gyzlvymvrezh6vwd0l4kg06tg5rvssw0czg8873gz5sdkteqj', - genesis_address: 'bc1pscktlmn99gyzlvymvrezh6vwd0l4kg06tg5rvssw0czg8873gz5sdkteqj', + address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', + genesis_address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', genesis_block_hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', - genesis_block_height: 778575, + genesis_block_height: 778576, content_length: 5, - mime_type: 'text/plain', - content_type: 'text/plain;charset=utf-8', - genesis_fee: '705', - id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', + mime_type: 'image/png', + content_type: 'image/png', + genesis_fee: '2805', + id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', offset: '0', - number: 7, + number: 1, value: '10000', sat_ordinal: '257418248345364', + tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', sat_coinbase_height: 51483, - output: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201:0', - location: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201:0:0', + output: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc:0', + location: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc:0:0', sat_rarity: 'common', - tx_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201', timestamp: 1676913207000, genesis_timestamp: 1676913207000, - genesis_tx_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201', + genesis_tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', curse_type: null, recursive: false, recursion_refs: null, }, { - address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', - genesis_address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', + address: 'bc1pscktlmn99gyzlvymvrezh6vwd0l4kg06tg5rvssw0czg8873gz5sdkteqj', + genesis_address: 'bc1pscktlmn99gyzlvymvrezh6vwd0l4kg06tg5rvssw0czg8873gz5sdkteqj', genesis_block_hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', - genesis_block_height: 775617, + genesis_block_height: 778575, content_length: 5, - mime_type: 'image/png', - content_type: 'image/png', - genesis_fee: '2805', - id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', + mime_type: 'text/plain', + content_type: 'text/plain;charset=utf-8', + genesis_fee: '705', + id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', offset: '0', - number: 1, + number: 0, value: '10000', sat_ordinal: '257418248345364', - tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', sat_coinbase_height: 51483, - output: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc:0', - location: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc:0:0', + output: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201:0', + location: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201:0:0', sat_rarity: 'common', + tx_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201', timestamp: 1676913207000, genesis_timestamp: 1676913207000, - genesis_tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', + genesis_tx_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201', curse_type: null, recursive: false, recursion_refs: null, @@ -1561,7 +1397,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -1581,7 +1417,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1676913207, }) @@ -1627,7 +1463,7 @@ describe('/inscriptions', () => { genesis_fee: '705', id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', offset: '0', - number: 7, + number: 0, value: '10000', sat_ordinal: '257418248345364', sat_coinbase_height: 51483, @@ -1655,7 +1491,7 @@ describe('/inscriptions', () => { address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', genesis_address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', genesis_block_hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', - genesis_block_height: 775617, + genesis_block_height: 778576, content_length: 5, mime_type: 'image/png', content_type: 'image/png', @@ -1686,8 +1522,8 @@ describe('/inscriptions', () => { expect(response3.statusCode).toBe(200); const responseJson3 = response3.json(); expect(responseJson3.total).toBe(2); - expect(responseJson3.results[0]).toStrictEqual(result1); - expect(responseJson3.results[1]).toStrictEqual(result2); + expect(responseJson3.results[0]).toStrictEqual(result2); + expect(responseJson3.results[1]).toStrictEqual(result1); }); test('index filtered by sat rarity', async () => { @@ -1706,7 +1542,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -1726,7 +1562,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1676913207, }) @@ -1797,7 +1633,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -1817,7 +1653,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1676913207, }) @@ -1892,7 +1728,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -1912,7 +1748,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1676913207, }) @@ -1923,7 +1759,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 50, + inscription_number: 1, inscription_fee: 2805, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, @@ -1942,25 +1778,25 @@ describe('/inscriptions', () => { const response1 = await fastify.inject({ method: 'GET', - url: '/ordinals/v1/inscriptions?number=7', + url: '/ordinals/v1/inscriptions?number=0', }); expect(response1.statusCode).toBe(200); const responseJson1 = response1.json(); expect(responseJson1.total).toBe(1); - expect(responseJson1.results[0].number).toBe(7); + expect(responseJson1.results[0].number).toBe(0); const response2 = await fastify.inject({ method: 'GET', - url: '/ordinals/v1/inscriptions?number=50', + url: '/ordinals/v1/inscriptions?number=1', }); expect(response2.statusCode).toBe(200); const responseJson2 = response2.json(); expect(responseJson2.total).toBe(1); - expect(responseJson2.results[0].number).toBe(50); + expect(responseJson2.results[0].number).toBe(1); const response3 = await fastify.inject({ method: 'GET', - url: '/ordinals/v1/inscriptions?number=7&number=50', + url: '/ordinals/v1/inscriptions?number=0&number=1', }); expect(response3.statusCode).toBe(200); const responseJson3 = response3.json(); @@ -1983,7 +1819,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -2003,7 +1839,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1676913207, }) @@ -2033,17 +1869,17 @@ describe('/inscriptions', () => { const response1 = await fastify.inject({ method: 'GET', - url: '/ordinals/v1/inscriptions?genesis_block=775617', + url: '/ordinals/v1/inscriptions?genesis_block=778576', }); expect(response1.statusCode).toBe(200); const responseJson1 = response1.json(); expect(responseJson1.total).toBe(1); expect(responseJson1.results.length).toBe(1); - expect(responseJson1.results[0].genesis_block_height).toBe(775617); + expect(responseJson1.results[0].genesis_block_height).toBe(778576); const response2 = await fastify.inject({ method: 'GET', - url: '/ordinals/v1/inscriptions?from_genesis_block_height=778000', + url: '/ordinals/v1/inscriptions?to_genesis_block_height=778575', }); expect(response2.statusCode).toBe(200); const responseJson2 = response2.json(); @@ -2053,19 +1889,19 @@ describe('/inscriptions', () => { const response3 = await fastify.inject({ method: 'GET', - url: '/ordinals/v1/inscriptions?to_genesis_block_height=778000', + url: '/ordinals/v1/inscriptions?from_genesis_block_height=778576', }); expect(response3.statusCode).toBe(200); const responseJson3 = response3.json(); expect(responseJson3.total).toBe(1); expect(responseJson3.results.length).toBe(1); - expect(responseJson3.results[0].genesis_block_height).toBe(775617); + expect(responseJson3.results[0].genesis_block_height).toBe(778576); await db.updateInscriptions( new TestChainhookPayloadBuilder() .apply() .block({ - height: 778580, + height: 778577, hash: '000000000000000000003ac2d5b588bc97a5479d25e403cffd90bd60c9680cfc', timestamp: 1676913207, }) @@ -2076,7 +1912,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 70, + inscription_number: 2, inscription_fee: 705, inscription_id: '25b372de3de0cb6fcc52c89a8bc3fb78eec596521ba20de16e53c1585be7c3fci0', inscription_output_value: 10000, @@ -2094,13 +1930,13 @@ describe('/inscriptions', () => { ); const response4 = await fastify.inject({ method: 'GET', - url: '/ordinals/v1/inscriptions?from_genesis_block_height=778000&to_genesis_block_height=779000', + url: '/ordinals/v1/inscriptions?from_genesis_block_height=778575&to_genesis_block_height=778576', }); expect(response4.statusCode).toBe(200); const responseJson4 = response4.json(); expect(responseJson4.total).toBe(2); expect(responseJson4.results.length).toBe(2); - expect(responseJson4.results[0].genesis_block_height).toBe(778580); + expect(responseJson4.results[0].genesis_block_height).toBe(778576); expect(responseJson4.results[1].genesis_block_height).toBe(778575); }); @@ -2120,7 +1956,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -2140,7 +1976,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1676913207, }) @@ -2197,7 +2033,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -2217,7 +2053,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1675312161, }) @@ -2282,7 +2118,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -2302,7 +2138,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1675312161, }) @@ -2367,7 +2203,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -2387,7 +2223,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1675312161, }) @@ -2452,7 +2288,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -2472,7 +2308,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1675312161, }) @@ -2483,7 +2319,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 50, + inscription_number: 1, inscription_fee: 2805, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, @@ -2502,22 +2338,22 @@ describe('/inscriptions', () => { const response2 = await fastify.inject({ method: 'GET', - url: '/ordinals/v1/inscriptions?from_number=10', + url: '/ordinals/v1/inscriptions?from_number=1', }); expect(response2.statusCode).toBe(200); const responseJson2 = response2.json(); expect(responseJson2.total).toBe(1); - expect(responseJson2.results[0].number).toBe(50); + expect(responseJson2.results[0].number).toBe(1); const response3 = await fastify.inject({ method: 'GET', - url: '/ordinals/v1/inscriptions?to_number=10', + url: '/ordinals/v1/inscriptions?to_number=0', }); expect(response3.statusCode).toBe(200); const responseJson3 = response3.json(); expect(responseJson3.total).toBe(1); expect(responseJson3.results.length).toBe(1); - expect(responseJson3.results[0].number).toBe(7); + expect(responseJson3.results[0].number).toBe(0); }); test('index filtered by output', async () => { @@ -2536,7 +2372,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -2556,7 +2392,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1675312161, }) @@ -2601,7 +2437,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -2633,7 +2469,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1675312161, }) @@ -2700,7 +2536,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775618, + height: 778577, hash: '000000000000000000032ef6c45a69c0496456b3cae84ee9f2899f636d03c5ac', timestamp: 1675312161, }) @@ -2757,7 +2593,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .rollback() .block({ - height: 775618, + height: 778577, hash: '000000000000000000032ef6c45a69c0496456b3cae84ee9f2899f636d03c5ac', timestamp: 1675312161, }) @@ -2802,7 +2638,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -2822,7 +2658,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1675312161, }) @@ -2893,7 +2729,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -2913,14 +2749,14 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1675312161, }) .transaction({ hash: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', }) - .inscriptionRevealed({ + .cursedInscriptionRevealed({ content_bytes: `0x${Buffer.from( 'Hello /content/9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0' ).toString('hex')}`, @@ -2939,6 +2775,7 @@ describe('/inscriptions', () => { inscription_input_index: 0, transfers_pre_inscription: 0, tx_index: 0, + curse_type: 'test', }) .build() ); @@ -2984,7 +2821,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -3003,7 +2840,7 @@ describe('/inscriptions', () => { const genesis2 = new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1675312161, }) @@ -3082,7 +2919,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -3102,7 +2939,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1676913207, }) @@ -3113,7 +2950,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 8, + inscription_number: 1, inscription_fee: 705, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, @@ -3133,7 +2970,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 778583, + height: 778577, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1676913207, }) @@ -3144,7 +2981,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 9, + inscription_number: 2, inscription_fee: 2805, inscription_id: '567c7605439dfdc3a289d13fd2132237852f4a56e784b9364ba94499d5f9baf1i0', inscription_output_value: 10000, @@ -3168,9 +3005,9 @@ describe('/inscriptions', () => { expect(response1.statusCode).toBe(200); const responseJson1 = response1.json(); expect(responseJson1.total).toBe(3); - expect(responseJson1.results[0].number).toStrictEqual(7); - expect(responseJson1.results[1].number).toStrictEqual(8); - expect(responseJson1.results[2].number).toStrictEqual(9); + expect(responseJson1.results[0].number).toStrictEqual(0); + expect(responseJson1.results[1].number).toStrictEqual(1); + expect(responseJson1.results[2].number).toStrictEqual(2); const response2 = await fastify.inject({ method: 'GET', @@ -3179,9 +3016,9 @@ describe('/inscriptions', () => { expect(response2.statusCode).toBe(200); const responseJson2 = response2.json(); expect(responseJson2.total).toBe(3); - expect(responseJson2.results[0].number).toStrictEqual(9); - expect(responseJson2.results[1].number).toStrictEqual(8); - expect(responseJson2.results[2].number).toStrictEqual(7); + expect(responseJson2.results[0].number).toStrictEqual(2); + expect(responseJson2.results[1].number).toStrictEqual(1); + expect(responseJson2.results[2].number).toStrictEqual(0); }); test('index ordered by sat rarity', async () => { @@ -3200,7 +3037,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -3220,7 +3057,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1676913207, }) @@ -3231,7 +3068,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 8, + inscription_number: 1, inscription_fee: 705, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, @@ -3251,7 +3088,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 778583, + height: 778577, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1676913207, }) @@ -3262,7 +3099,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 9, + inscription_number: 2, inscription_fee: 2805, inscription_id: '567c7605439dfdc3a289d13fd2132237852f4a56e784b9364ba94499d5f9baf1i0', inscription_output_value: 10000, @@ -3318,7 +3155,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -3338,7 +3175,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1676913207, }) @@ -3349,7 +3186,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 8, + inscription_number: 1, inscription_fee: 705, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, @@ -3369,7 +3206,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 778583, + height: 778577, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1676913207, }) @@ -3380,7 +3217,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 9, + inscription_number: 2, inscription_fee: 2805, inscription_id: '567c7605439dfdc3a289d13fd2132237852f4a56e784b9364ba94499d5f9baf1i0', inscription_output_value: 10000, @@ -3436,7 +3273,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 705, inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, @@ -3456,7 +3293,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 778576, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1676913207, }) @@ -3467,7 +3304,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 8, + inscription_number: 1, inscription_fee: 705, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, @@ -3487,7 +3324,7 @@ describe('/inscriptions', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 778583, + height: 778577, hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1676913207, }) @@ -3498,7 +3335,7 @@ describe('/inscriptions', () => { content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 9, + inscription_number: 2, inscription_fee: 2805, inscription_id: '567c7605439dfdc3a289d13fd2132237852f4a56e784b9364ba94499d5f9baf1i0', inscription_output_value: 10000, @@ -3522,9 +3359,9 @@ describe('/inscriptions', () => { expect(response1.statusCode).toBe(200); const responseJson1 = response1.json(); expect(responseJson1.total).toBe(3); - expect(responseJson1.results[0].genesis_block_height).toStrictEqual(775617); - expect(responseJson1.results[1].genesis_block_height).toStrictEqual(778575); - expect(responseJson1.results[2].genesis_block_height).toStrictEqual(778583); + expect(responseJson1.results[0].genesis_block_height).toStrictEqual(778575); + expect(responseJson1.results[1].genesis_block_height).toStrictEqual(778576); + expect(responseJson1.results[2].genesis_block_height).toStrictEqual(778577); const response2 = await fastify.inject({ method: 'GET', @@ -3533,56 +3370,9 @@ describe('/inscriptions', () => { expect(response2.statusCode).toBe(200); const responseJson2 = response2.json(); expect(responseJson2.total).toBe(3); - expect(responseJson2.results[0].genesis_block_height).toStrictEqual(778583); - expect(responseJson2.results[1].genesis_block_height).toStrictEqual(778575); - expect(responseJson2.results[2].genesis_block_height).toStrictEqual(775617); - - // Same genesis block items should be sorted by number - await db.updateInscriptions( - new TestChainhookPayloadBuilder() - .apply() - .block({ - height: 778583, - hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', - timestamp: 1676913207, - }) - .transaction({ - hash: '907f66261909f40e6b892b7ac574fd9e8661262c83b48be7488194b66523abbd', - }) - .inscriptionRevealed({ - content_bytes: '0x48656C6C6F', - content_type: 'image/png', - content_length: 5, - inscription_number: 43, - inscription_fee: 2805, - inscription_id: '907f66261909f40e6b892b7ac574fd9e8661262c83b48be7488194b66523abbdi0', - inscription_output_value: 10000, - inscriber_address: 'bc1pxq6t85qp57aw8yf8eh9t7vsgd9zm5a8372rdll5jzrmc3cxqdpmqfucdry', - ordinal_number: 0, - ordinal_block_height: 0, - ordinal_offset: 0, - satpoint_post_inscription: - '907f66261909f40e6b892b7ac574fd9e8661262c83b48be7488194b66523abbd:0:0', - inscription_input_index: 0, - transfers_pre_inscription: 0, - tx_index: 0, - }) - .build() - ); - - const response3 = await fastify.inject({ - method: 'GET', - url: '/ordinals/v1/inscriptions?order_by=genesis_block_height&order=desc', - }); - expect(response3.statusCode).toBe(200); - const responseJson3 = response3.json(); - expect(responseJson3.total).toBe(4); - expect(responseJson3.results[0].genesis_block_height).toStrictEqual(778583); - expect(responseJson3.results[0].number).toStrictEqual(43); - expect(responseJson3.results[1].genesis_block_height).toStrictEqual(778583); - expect(responseJson3.results[1].number).toStrictEqual(9); - expect(responseJson3.results[2].genesis_block_height).toStrictEqual(778575); - expect(responseJson3.results[3].genesis_block_height).toStrictEqual(775617); + expect(responseJson2.results[0].genesis_block_height).toStrictEqual(778577); + expect(responseJson2.results[1].genesis_block_height).toStrictEqual(778576); + expect(responseJson2.results[2].genesis_block_height).toStrictEqual(778575); }); }); }); diff --git a/tests/sats.test.ts b/tests/sats.test.ts index 479fee4c..af39a376 100644 --- a/tests/sats.test.ts +++ b/tests/sats.test.ts @@ -48,7 +48,7 @@ describe('/sats', () => { content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 2805, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, @@ -105,7 +105,7 @@ describe('/sats', () => { new TestChainhookPayloadBuilder() .apply() .block({ - height: 775617, + height: 775618, hash: '000000000000000000002a244dc7dfcf8ab85e42d182531c27197fc125086f19', timestamp: 1676913207, }) @@ -147,7 +147,7 @@ describe('/sats', () => { content_type: 'image/png', genesis_address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', genesis_block_hash: '000000000000000000002a244dc7dfcf8ab85e42d182531c27197fc125086f19', - genesis_block_height: 775617, + genesis_block_height: 775618, genesis_fee: '2805', genesis_timestamp: 1676913207000, genesis_tx_id: 'b9cd9489fe30b81d007f753663d12766f1368721a87f4c69056c8215caa57993', diff --git a/tests/server.test.ts b/tests/server.test.ts index f0785521..5a334af9 100644 --- a/tests/server.test.ts +++ b/tests/server.test.ts @@ -35,7 +35,7 @@ describe('EventServer', () => { content_bytes: '0x303030303030303030303030', content_type: 'text/plain;charset=utf-8', content_length: 12, - inscription_number: 100, + inscription_number: 0, inscription_fee: 3425, inscription_output_value: 10000, inscription_id: '0268dd9743c862d80ab02cb1d0228036cfe172522850eb96be60cfee14b31fb8i0', @@ -54,7 +54,7 @@ describe('EventServer', () => { const payload1 = new TestChainhookPayloadBuilder() .apply() .block({ - height: 107, + height: 767430, hash: '0x163de66dc9c0949905bfe8e148bde04600223cf88d19f26fdbeba1d6e6fa0f88', timestamp: 1676913207, }) @@ -89,7 +89,7 @@ describe('EventServer', () => { expect(inscr.genesis_block_hash).toBe( '163de66dc9c0949905bfe8e148bde04600223cf88d19f26fdbeba1d6e6fa0f88' ); - expect(inscr.genesis_block_height).toBe('107'); + expect(inscr.genesis_block_height).toBe('767430'); expect(inscr.genesis_fee).toBe('3425'); expect(inscr.genesis_id).toBe( '0268dd9743c862d80ab02cb1d0228036cfe172522850eb96be60cfee14b31fb8i0' @@ -99,7 +99,7 @@ describe('EventServer', () => { '0268dd9743c862d80ab02cb1d0228036cfe172522850eb96be60cfee14b31fb8' ); expect(inscr.mime_type).toBe('text/plain'); - expect(inscr.number).toBe('100'); + expect(inscr.number).toBe('0'); expect(inscr.offset).toBe('0'); expect(inscr.output).toBe( '0268dd9743c862d80ab02cb1d0228036cfe172522850eb96be60cfee14b31fb8:0' @@ -152,7 +152,7 @@ describe('EventServer', () => { content_bytes: '0x48656C6C6F', content_type: 'image/png', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 2805, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, @@ -232,7 +232,7 @@ describe('EventServer', () => { '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc' ); expect(inscr.mime_type).toBe('image/png'); - expect(inscr.number).toBe('7'); + expect(inscr.number).toBe('0'); expect(inscr.offset).toBe('5000'); expect(inscr.output).toBe( '0268dd9743c862d80ab02cb1d0228036cfe172522850eb96be60cfee14b31fb8:0' @@ -269,186 +269,255 @@ describe('EventServer', () => { expect(c2[0].count).toBe(1); }); - test('saves transfer without genesis and fills the gap later', async () => { - // Insert transfers with no genesis + test('multiple inscription pointers on the same block are compared correctly', async () => { + const address = 'bc1q92zytmqgczsrg4xuhpc2asz6h4h7ke5hagw8k6'; + const address2 = 'bc1qtpm0fsaawxjsthfdrxhmrzunnpjx0g9hncgvp7'; await db.updateInscriptions( new TestChainhookPayloadBuilder() .apply() .block({ - height: 775620, - hash: '0x00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', - timestamp: 1676913207, + height: 808382, + hash: '00000000000000000002b14f0c5dde0b2fc74d022e860696bd64f1f652756674', }) .transaction({ - hash: '0x38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', - }) - .inscriptionTransferred({ - inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - destination: { - type: 'transferred', - value: 'bc1qcf3dgqgvylmd5ayl4njm4ephqfdazy93ssu28j', - }, - satpoint_pre_transfer: - '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc:0:0', - satpoint_post_transfer: - '9e2414153b1893f799477f7e1a00a52fafc235de72fd215cb3321f253c4464ac:0:0', - post_transfer_output_value: 9000, - tx_index: 0, + hash: '6046f17804eb8396285567a20c09598ae1273b6f744b23700ba95593c380ce02', }) - .build() - ); - await db.updateInscriptions( - new TestChainhookPayloadBuilder() - .apply() - .block({ - height: 775621, - hash: '00000000000000000003dd4738355bedb73796de9b1099e59ff7adc235e967a6', - timestamp: 1676913207, + .inscriptionRevealed({ + content_bytes: '0x48656C6C6F', + content_type: 'image/png', + content_length: 5, + inscription_number: 0, + inscription_fee: 2805, + inscription_id: '6046f17804eb8396285567a20c09598ae1273b6f744b23700ba95593c380ce02i0', + inscription_output_value: 10000, + inscriber_address: address, + ordinal_number: 5, + ordinal_block_height: 0, + ordinal_offset: 0, + satpoint_post_inscription: + '6046f17804eb8396285567a20c09598ae1273b6f744b23700ba95593c380ce02:0:0', + inscription_input_index: 0, + transfers_pre_inscription: 0, + tx_index: 995, }) .transaction({ - hash: '2fa1640d61f04a699833f0f6a884f543c835fc60f0fd4da8627ebb857acdce84', + hash: '7edaa48337a94da327b6262830505f116775a32db5ad4ad46e87ecea33f21bac', }) .inscriptionTransferred({ - inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - destination: { - type: 'transferred', - value: 'bc1qcf3dgqgvylmd5ayl4njm4ephqfdazy93ssu28j', - }, + inscription_id: '6046f17804eb8396285567a20c09598ae1273b6f744b23700ba95593c380ce02i0', + destination: { type: 'transferred', value: address2 }, satpoint_pre_transfer: - '9e2414153b1893f799477f7e1a00a52fafc235de72fd215cb3321f253c4464ac:0:0', + '6046f17804eb8396285567a20c09598ae1273b6f744b23700ba95593c380ce02:0:0', satpoint_post_transfer: - '2fa1640d61f04a699833f0f6a884f543c835fc60f0fd4da8627ebb857acdce84:0:0', - post_transfer_output_value: 8000, - tx_index: 0, + '7edaa48337a94da327b6262830505f116775a32db5ad4ad46e87ecea33f21bac:0:0', + post_transfer_output_value: null, + tx_index: 1019, // '1019' is less than '995' when compared as a string }) .build() ); - // Locations should exist with null FKs - const results1 = await db.sql` - SELECT * FROM locations - WHERE genesis_id = '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0' - `; - expect(results1.count).toBe(2); - expect(results1[0].inscription_id).toBeNull(); - expect(results1[1].inscription_id).toBeNull(); - const api1 = await fastify.inject({ - method: 'GET', - url: '/ordinals/v1/inscriptions/38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - }); - expect(api1.statusCode).toBe(404); - const api2 = await fastify.inject({ + const response = await fastify.inject({ method: 'GET', - url: '/ordinals/v1/inscriptions/38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0/transfers', + url: `/ordinals/inscriptions/6046f17804eb8396285567a20c09598ae1273b6f744b23700ba95593c380ce02i0`, }); - expect(api2.json().total).toBe(0); + expect(response.statusCode).toBe(200); + const json = response.json(); + expect(json.genesis_address).toBe(address); + }); + }); - // Insert genesis and make sure locations are normalized. + describe('gap detection', () => { + test('server rejects payload with first inscription gap', async () => { await db.updateInscriptions( new TestChainhookPayloadBuilder() .apply() .block({ - height: 775618, + height: 778575, hash: '0x00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', timestamp: 1676913207, }) .transaction({ - hash: '0x38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', + hash: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201', }) .inscriptionRevealed({ content_bytes: '0x48656C6C6F', - content_type: 'image/png', + content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, - inscription_fee: 2805, - inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', + inscription_number: 0, + inscription_fee: 705, + inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, - inscriber_address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', - ordinal_number: 5, - ordinal_block_height: 0, + inscriber_address: 'bc1pscktlmn99gyzlvymvrezh6vwd0l4kg06tg5rvssw0czg8873gz5sdkteqj', + ordinal_number: 257418248345364, + ordinal_block_height: 650000, ordinal_offset: 0, satpoint_post_inscription: - '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc:0:0', + '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201:0:0', inscription_input_index: 0, transfers_pre_inscription: 0, tx_index: 0, }) .build() ); - // Locations should exist with all FKs filled in - const results2 = await db.sql` - SELECT * FROM locations - WHERE genesis_id = '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0' - `; - expect(results2.count).toBe(3); - expect(results2[0].inscription_id).not.toBeNull(); - expect(results2[1].inscription_id).not.toBeNull(); - expect(results2[2].inscription_id).not.toBeNull(); - const api3 = await fastify.inject({ - method: 'GET', - url: '/ordinals/v1/inscriptions/38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', - }); - expect(api3.statusCode).toBe(200); - expect(api3.json().genesis_block_height).toBe(775618); - const api4 = await fastify.inject({ - method: 'GET', - url: '/ordinals/v1/inscriptions/38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0/transfers', - }); - expect(api4.json().total).toBe(3); + const errorPayload = new TestChainhookPayloadBuilder() + .apply() + .block({ + height: 778576, + hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', + timestamp: 1676913207, + }) + .transaction({ + hash: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', + }) + .inscriptionRevealed({ + content_bytes: '0x48656C6C6F', + content_type: 'text/plain;charset=utf-8', + content_length: 5, + inscription_number: 5, // Gap at 5 + inscription_fee: 705, + inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', + inscription_output_value: 10000, + inscriber_address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', + ordinal_number: 1050000000000000, + ordinal_block_height: 650000, + ordinal_offset: 0, + satpoint_post_inscription: + '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc:0:0', + inscription_input_index: 0, + transfers_pre_inscription: 0, + tx_index: 0, + }) + .build(); + await expect(db.updateInscriptions(errorPayload)).rejects.toThrowError( + /inscription gap detected/ + ); }); - test('multiple inscription pointers on the same block are compared correctly', async () => { - const address = 'bc1q92zytmqgczsrg4xuhpc2asz6h4h7ke5hagw8k6'; - const address2 = 'bc1qtpm0fsaawxjsthfdrxhmrzunnpjx0g9hncgvp7'; + test('server rejects payload with intermediate inscription gap', async () => { await db.updateInscriptions( new TestChainhookPayloadBuilder() .apply() .block({ - height: 808382, - hash: '00000000000000000002b14f0c5dde0b2fc74d022e860696bd64f1f652756674', + height: 778575, + hash: '0x00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', + timestamp: 1676913207, }) .transaction({ - hash: '6046f17804eb8396285567a20c09598ae1273b6f744b23700ba95593c380ce02', + hash: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201', }) .inscriptionRevealed({ content_bytes: '0x48656C6C6F', - content_type: 'image/png', + content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 33224825, - inscription_fee: 2805, - inscription_id: '6046f17804eb8396285567a20c09598ae1273b6f744b23700ba95593c380ce02i0', + inscription_number: 0, + inscription_fee: 705, + inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', inscription_output_value: 10000, - inscriber_address: address, - ordinal_number: 5, - ordinal_block_height: 0, + inscriber_address: 'bc1pscktlmn99gyzlvymvrezh6vwd0l4kg06tg5rvssw0czg8873gz5sdkteqj', + ordinal_number: 257418248345364, + ordinal_block_height: 650000, ordinal_offset: 0, satpoint_post_inscription: - '6046f17804eb8396285567a20c09598ae1273b6f744b23700ba95593c380ce02:0:0', + '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201:0:0', inscription_input_index: 0, transfers_pre_inscription: 0, - tx_index: 995, - }) - .transaction({ - hash: '7edaa48337a94da327b6262830505f116775a32db5ad4ad46e87ecea33f21bac', - }) - .inscriptionTransferred({ - inscription_id: '6046f17804eb8396285567a20c09598ae1273b6f744b23700ba95593c380ce02i0', - destination: { type: 'transferred', value: address2 }, - satpoint_pre_transfer: - '6046f17804eb8396285567a20c09598ae1273b6f744b23700ba95593c380ce02:0:0', - satpoint_post_transfer: - '7edaa48337a94da327b6262830505f116775a32db5ad4ad46e87ecea33f21bac:0:0', - post_transfer_output_value: null, - tx_index: 1019, // '1019' is less than '995' when compared as a string + tx_index: 0, }) .build() ); - const response = await fastify.inject({ - method: 'GET', - url: `/ordinals/inscriptions/6046f17804eb8396285567a20c09598ae1273b6f744b23700ba95593c380ce02i0`, + const errorPayload = new TestChainhookPayloadBuilder() + .apply() + .block({ + height: 778576, + hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', + timestamp: 1676913207, + }) + .transaction({ + hash: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', + }) + .inscriptionRevealed({ + content_bytes: '0x48656C6C6F', + content_type: 'text/plain;charset=utf-8', + content_length: 5, + inscription_number: 1, + inscription_fee: 705, + inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', + inscription_output_value: 10000, + inscriber_address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', + ordinal_number: 1050000000000000, + ordinal_block_height: 650000, + ordinal_offset: 0, + satpoint_post_inscription: + '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc:0:0', + inscription_input_index: 0, + transfers_pre_inscription: 0, + tx_index: 0, + }) + .transaction({ + hash: '6891d374a17ba85f6b5514f2f7edc301c1c860284dff5a5c6e88ab3a20fcd8a5', + }) + .inscriptionRevealed({ + content_bytes: '0x48656C6C6F', + content_type: 'text/plain;charset=utf-8', + content_length: 5, + inscription_number: 4, // Gap + inscription_fee: 705, + inscription_id: '6891d374a17ba85f6b5514f2f7edc301c1c860284dff5a5c6e88ab3a20fcd8a5o0', + inscription_output_value: 10000, + inscriber_address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', + ordinal_number: 1050000000000000, + ordinal_block_height: 650000, + ordinal_offset: 0, + satpoint_post_inscription: + '6891d374a17ba85f6b5514f2f7edc301c1c860284dff5a5c6e88ab3a20fcd8a5:0:0', + inscription_input_index: 0, + transfers_pre_inscription: 0, + tx_index: 0, + }) + .build(); + await expect(db.updateInscriptions(errorPayload)).rejects.toThrowError( + /inscription gap detected/ + ); + }); + + test('server ignores past blocks', async () => { + const payload = new TestChainhookPayloadBuilder() + .apply() + .block({ + height: 778575, + hash: '0x00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', + timestamp: 1676913207, + }) + .transaction({ + hash: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201', + }) + .inscriptionRevealed({ + content_bytes: '0x48656C6C6F', + content_type: 'text/plain;charset=utf-8', + content_length: 5, + inscription_number: 0, + inscription_fee: 705, + inscription_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', + inscription_output_value: 10000, + inscriber_address: 'bc1pscktlmn99gyzlvymvrezh6vwd0l4kg06tg5rvssw0czg8873gz5sdkteqj', + ordinal_number: 257418248345364, + ordinal_block_height: 650000, + ordinal_offset: 0, + satpoint_post_inscription: + '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201:0:0', + inscription_input_index: 0, + transfers_pre_inscription: 0, + tx_index: 0, + }) + .build(); + await db.updateInscriptions(payload); + + const response = await server['fastify'].inject({ + method: 'POST', + url: `/chainhook/${PREDICATE_UUID}`, + headers: { authorization: `Bearer ${ENV.CHAINHOOK_NODE_AUTH_TOKEN}` }, + payload: payload, }); expect(response.statusCode).toBe(200); - const json = response.json(); - expect(json.genesis_address).toBe(address); }); }); }); diff --git a/tests/stats.test.ts b/tests/stats.test.ts index 90097703..34b83c91 100644 --- a/tests/stats.test.ts +++ b/tests/stats.test.ts @@ -64,34 +64,11 @@ describe('/stats', () => { }; test('returns stats when processing blocks in order', async () => { - await db.updateInscriptions(testRevealApply(778_000)); - await db.updateInscriptions(testRevealApply(778_000)); - await db.updateInscriptions(testRevealApply(778_001)); - await db.updateInscriptions(testRevealApply(778_002)); - await db.updateInscriptions(testRevealApply(778_005)); - await db.updateInscriptions(testRevealApply(778_005)); - await db.updateInscriptions(testRevealApply(778_010)); - await db.updateInscriptions(testRevealApply(778_010)); - await db.updateInscriptions(testRevealApply(778_010)); - - const response = await fastify.inject({ - method: 'GET', - url: '/ordinals/v1/stats/inscriptions', - }); - expect(response.statusCode).toBe(200); - expect(response.json()).toStrictEqual(EXPECTED); - }); - - test('returns stats when processing blocks out-of-order', async () => { - await db.updateInscriptions(testRevealApply(778_001)); - await db.updateInscriptions(testRevealApply(778_010)); - await db.updateInscriptions(testRevealApply(778_000)); - await db.updateInscriptions(testRevealApply(778_000)); - await db.updateInscriptions(testRevealApply(778_005)); - await db.updateInscriptions(testRevealApply(778_010)); - await db.updateInscriptions(testRevealApply(778_002)); - await db.updateInscriptions(testRevealApply(778_010)); - await db.updateInscriptions(testRevealApply(778_005)); + await db.updateInscriptions(testRevealApply(778_000, [0, 1])); + await db.updateInscriptions(testRevealApply(778_001, [2])); + await db.updateInscriptions(testRevealApply(778_002, [3])); + await db.updateInscriptions(testRevealApply(778_005, [4, 5])); + await db.updateInscriptions(testRevealApply(778_010, [6, 7, 8])); const response = await fastify.inject({ method: 'GET', @@ -102,20 +79,16 @@ describe('/stats', () => { }); test('returns stats when processing rollbacks', async () => { - const payloadApply = testRevealApply(778_004); + const payloadApply = testRevealApply(778_004, [4]); const payloadRollback = { ...payloadApply, apply: [], rollback: payloadApply.apply }; - await db.updateInscriptions(testRevealApply(778_001)); - await db.updateInscriptions(testRevealApply(778_010)); - await db.updateInscriptions(testRevealApply(778_000)); + await db.updateInscriptions(testRevealApply(778_000, [0, 1])); + await db.updateInscriptions(testRevealApply(778_001, [2])); + await db.updateInscriptions(testRevealApply(778_002, [3])); await db.updateInscriptions(payloadApply); - await db.updateInscriptions(testRevealApply(778_005)); - await db.updateInscriptions(testRevealApply(778_000)); await db.updateInscriptions(payloadRollback); - await db.updateInscriptions(testRevealApply(778_010)); - await db.updateInscriptions(testRevealApply(778_002)); - await db.updateInscriptions(testRevealApply(778_010)); - await db.updateInscriptions(testRevealApply(778_005)); + await db.updateInscriptions(testRevealApply(778_005, [4, 5])); + await db.updateInscriptions(testRevealApply(778_010, [6, 7, 8])); const response = await fastify.inject({ method: 'GET', @@ -127,12 +100,11 @@ describe('/stats', () => { }); test('range filters', async () => { - await db.updateInscriptions(testRevealApply(778_000)); - await db.updateInscriptions(testRevealApply(778_001)); - await db.updateInscriptions(testRevealApply(778_002)); - await db.updateInscriptions(testRevealApply(778_005)); - await db.updateInscriptions(testRevealApply(778_005)); - await db.updateInscriptions(testRevealApply(778_010)); + await db.updateInscriptions(testRevealApply(778_000, [0])); + await db.updateInscriptions(testRevealApply(778_001, [1])); + await db.updateInscriptions(testRevealApply(778_002, [2])); + await db.updateInscriptions(testRevealApply(778_005, [3, 4])); + await db.updateInscriptions(testRevealApply(778_010, [5])); const responseFrom = await fastify.inject({ method: 'GET', @@ -222,34 +194,35 @@ describe('/stats', () => { }); }); -function testRevealApply(blockHeight: number) { - const randomHex = randomHash(); - return new TestChainhookPayloadBuilder() - .apply() - .block({ - height: blockHeight, - hash: '0x00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', - timestamp: 1676913207, - }) - .transaction({ - hash: `0x${randomHex}`, - }) - .inscriptionRevealed({ - content_bytes: '0x48656C6C6F', - content_type: 'image/png', - content_length: 5, - inscription_number: Math.floor(Math.random() * 100000), - inscription_fee: 2805, - inscription_id: `${randomHex}i0`, - inscription_output_value: 10000, - inscriber_address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', - ordinal_number: Math.floor(Math.random() * 1000000), - ordinal_block_height: Math.floor(Math.random() * 777000), - ordinal_offset: 0, - satpoint_post_inscription: `${randomHex}:0:0`, - inscription_input_index: 0, - transfers_pre_inscription: 0, - tx_index: 0, - }) - .build(); +function testRevealApply(blockHeight: number, numbers: number[]) { + const block = new TestChainhookPayloadBuilder().apply().block({ + height: blockHeight, + hash: '0x00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', + timestamp: 1676913207, + }); + for (const number of numbers) { + const randomHex = randomHash(); + block + .transaction({ + hash: `0x${randomHex}`, + }) + .inscriptionRevealed({ + content_bytes: '0x48656C6C6F', + content_type: 'image/png', + content_length: 5, + inscription_number: number, + inscription_fee: 2805, + inscription_id: `${randomHex}i0`, + inscription_output_value: 10000, + inscriber_address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', + ordinal_number: Math.floor(Math.random() * 1000000), + ordinal_block_height: Math.floor(Math.random() * 777000), + ordinal_offset: 0, + satpoint_post_inscription: `${randomHex}:0:0`, + inscription_input_index: 0, + transfers_pre_inscription: 0, + tx_index: 0, + }); + } + return block.build(); } diff --git a/tests/status.test.ts b/tests/status.test.ts index 87b845be..bf043697 100644 --- a/tests/status.test.ts +++ b/tests/status.test.ts @@ -41,7 +41,7 @@ describe('Status', () => { content_bytes: '0x48656C6C6F', content_type: 'text/plain;charset=utf-8', content_length: 5, - inscription_number: 7, + inscription_number: 0, inscription_fee: 2805, inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', inscription_output_value: 10000, @@ -90,7 +90,7 @@ describe('Status', () => { server_version: 'ordinals-api v0.0.1 (test:123456)', status: 'ready', block_height: 791975, - max_inscription_number: 7, + max_inscription_number: 0, max_cursed_inscription_number: -2, }); });