From 96ac17250ac5ad525b61fe228b942a44125ddb52 Mon Sep 17 00:00:00 2001 From: Rafael Cardenas Date: Mon, 29 Jul 2024 16:25:37 -0600 Subject: [PATCH 1/2] feat: ingest missing ordhook fields --- docker/docker-compose.dev.postgres.yml | 1 - migrations/1676395230930_inscriptions.ts | 13 ++++++++++++ src/api/schemas.ts | 10 +++++++++ src/api/util/helpers.ts | 2 ++ src/pg/block-cache.ts | 4 ++++ src/pg/types.ts | 8 ++++++++ tests/api/inscriptions.test.ts | 26 ++++++++++++++++++++++++ tests/api/sats.test.ts | 4 ++++ 8 files changed, 67 insertions(+), 1 deletion(-) diff --git a/docker/docker-compose.dev.postgres.yml b/docker/docker-compose.dev.postgres.yml index 9f4be693..4eb09649 100644 --- a/docker/docker-compose.dev.postgres.yml +++ b/docker/docker-compose.dev.postgres.yml @@ -1,4 +1,3 @@ -version: '3.7' services: postgres: image: "postgres:15" diff --git a/migrations/1676395230930_inscriptions.ts b/migrations/1676395230930_inscriptions.ts index 3205872b..cbb66d07 100644 --- a/migrations/1676395230930_inscriptions.ts +++ b/migrations/1676395230930_inscriptions.ts @@ -59,12 +59,25 @@ export function up(pgm: MigrationBuilder): void { type: 'boolean', default: false, }, + input_index: { + type: 'bigint', + notNull: true, + }, + pointer: { + type: 'bigint', + }, metadata: { type: 'text', }, + metaprotocol: { + type: 'text', + }, parent: { type: 'text', }, + delegate: { + type: 'text', + }, timestamp: { type: 'timestamptz', notNull: true, diff --git a/src/api/schemas.ts b/src/api/schemas.ts index d8b6f88c..c16527d3 100644 --- a/src/api/schemas.ts +++ b/src/api/schemas.ts @@ -331,7 +331,17 @@ export const InscriptionResponse = Type.Object( examples: ['1463d48e9248159084929294f64bda04487503d30ce7ab58365df1dc6fd58218i0'], }) ), + delegate: Nullable( + Type.String({ + examples: ['1463d48e9248159084929294f64bda04487503d30ce7ab58365df1dc6fd58218i0'], + }) + ), metadata: Nullable(Type.Any()), + meta_protocol: Nullable( + Type.String({ + examples: ['brc20'], + }) + ), }, { title: 'Inscription Response' } ); diff --git a/src/api/util/helpers.ts b/src/api/util/helpers.ts index 5d3d38da..685f58d4 100644 --- a/src/api/util/helpers.ts +++ b/src/api/util/helpers.ts @@ -57,6 +57,8 @@ export function parseDbInscriptions( recursion_refs: i.recursion_refs?.split(',') ?? null, parent: i.parent, metadata: i.metadata ? JSON.parse(i.metadata) : null, + delegate: i.delegate ?? null, + meta_protocol: i.metaprotocol ?? null, })); } export function parseDbInscription(item: DbFullyLocatedInscriptionResult): InscriptionResponseType { diff --git a/src/pg/block-cache.ts b/src/pg/block-cache.ts index 128dcba7..d0852519 100644 --- a/src/pg/block-cache.ts +++ b/src/pg/block-cache.ts @@ -71,6 +71,10 @@ export class BlockCache { recursive: recursive_refs.length > 0, metadata: reveal.metadata ? JSON.stringify(reveal.metadata) : null, parent: reveal.parent, + delegate: reveal.delegate, + input_index: reveal.inscription_input_index, + pointer: reveal.inscription_pointer, + metaprotocol: reveal.metaprotocol, timestamp: this.timestamp, }); this.revealedNumbers.push(reveal.inscription_number.jubilee); diff --git a/src/pg/types.ts b/src/pg/types.ts index 46e66e1e..e72e7db9 100644 --- a/src/pg/types.ts +++ b/src/pg/types.ts @@ -25,6 +25,10 @@ export type DbInscriptionInsert = { recursive: boolean; metadata: string | null; parent: string | null; + input_index: number; + pointer: number | null; + metaprotocol: string | null; + delegate: string | null; timestamp: number; }; @@ -102,6 +106,10 @@ export type DbFullyLocatedInscriptionResult = { recursion_refs: string | null; parent: string | null; metadata: string | null; + input_index: number; + pointer: number | null; + metaprotocol: string | null; + delegate: string | null; }; export enum DbLocationTransferType { diff --git a/tests/api/inscriptions.test.ts b/tests/api/inscriptions.test.ts index dc541cc3..b7fc5f52 100644 --- a/tests/api/inscriptions.test.ts +++ b/tests/api/inscriptions.test.ts @@ -126,6 +126,8 @@ describe('/inscriptions', () => { recursion_refs: null, parent: null, metadata: null, + meta_protocol: null, + delegate: null, }; // By inscription id @@ -284,6 +286,8 @@ describe('/inscriptions', () => { ], parent: null, metadata: null, + meta_protocol: null, + delegate: null, }; // By inscription id @@ -489,6 +493,8 @@ describe('/inscriptions', () => { recursion_refs: null, parent: null, metadata: null, + meta_protocol: null, + delegate: null, }; // By inscription id @@ -573,6 +579,8 @@ describe('/inscriptions', () => { recursion_refs: null, parent: null, metadata: null, + meta_protocol: null, + delegate: null, }; // By inscription id @@ -686,6 +694,8 @@ describe('/inscriptions', () => { recursion_refs: null, parent: null, metadata: null, + meta_protocol: null, + delegate: null, }); // Transfer 2 @@ -743,6 +753,8 @@ describe('/inscriptions', () => { recursion_refs: null, parent: null, metadata: null, + meta_protocol: null, + delegate: null, }); }); @@ -855,6 +867,8 @@ describe('/inscriptions', () => { recursion_refs: null, parent: null, metadata: null, + meta_protocol: null, + delegate: null, }); }); @@ -952,6 +966,8 @@ describe('/inscriptions', () => { recursion_refs: null, parent: null, metadata: null, + meta_protocol: null, + delegate: null, }); // Transfer 2 @@ -1009,6 +1025,8 @@ describe('/inscriptions', () => { recursion_refs: null, parent: null, metadata: null, + meta_protocol: null, + delegate: null, }); }); }); @@ -1656,6 +1674,8 @@ describe('/inscriptions', () => { recursion_refs: null, parent: null, metadata: null, + meta_protocol: null, + delegate: null, }, { address: 'bc1pscktlmn99gyzlvymvrezh6vwd0l4kg06tg5rvssw0czg8873gz5sdkteqj', @@ -1684,6 +1704,8 @@ describe('/inscriptions', () => { recursion_refs: null, parent: null, metadata: null, + meta_protocol: null, + delegate: null, }, ]); }); @@ -1799,6 +1821,8 @@ describe('/inscriptions', () => { recursion_refs: null, parent: null, metadata: null, + meta_protocol: null, + delegate: null, }; expect(responseJson1.results[0]).toStrictEqual(result1); @@ -1836,6 +1860,8 @@ describe('/inscriptions', () => { recursion_refs: null, parent: null, metadata: null, + meta_protocol: null, + delegate: null, }; expect(responseJson2.results[0]).toStrictEqual(result2); diff --git a/tests/api/sats.test.ts b/tests/api/sats.test.ts index 5b12bb2e..914e25fb 100644 --- a/tests/api/sats.test.ts +++ b/tests/api/sats.test.ts @@ -186,6 +186,8 @@ describe('/sats', () => { recursion_refs: null, parent: null, metadata: null, + meta_protocol: null, + delegate: null, }, { address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', @@ -215,6 +217,8 @@ describe('/sats', () => { recursion_refs: null, parent: null, metadata: null, + meta_protocol: null, + delegate: null, }, ]); From 27b394154bd07c7ddda8aa2b804127355be65de5 Mon Sep 17 00:00:00 2001 From: Rafael Cardenas Date: Mon, 29 Jul 2024 16:46:26 -0600 Subject: [PATCH 2/2] fix: display delegate content --- src/pg/pg-store.ts | 19 +++-- tests/api/inscriptions.test.ts | 131 +++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+), 5 deletions(-) diff --git a/src/pg/pg-store.ts b/src/pg/pg-store.ts index 494a0998..7a739ec7 100644 --- a/src/pg/pg-store.ts +++ b/src/pg/pg-store.ts @@ -447,13 +447,22 @@ export class PgStore extends BasePgStore { args: InscriptionIdentifier ): Promise { const result = await this.sql` + WITH content_id AS ( + SELECT + CASE + WHEN delegate IS NOT NULL THEN delegate + ELSE genesis_id + END AS genesis_id + FROM inscriptions + WHERE ${ + 'genesis_id' in args + ? this.sql`genesis_id = ${args.genesis_id}` + : this.sql`number = ${args.number}` + } + ) SELECT content, content_type, content_length FROM inscriptions - WHERE ${ - 'genesis_id' in args - ? this.sql`genesis_id = ${args.genesis_id}` - : this.sql`number = ${args.number}` - } + WHERE genesis_id = (SELECT genesis_id FROM content_id) `; if (result.count > 0) { return result[0]; diff --git a/tests/api/inscriptions.test.ts b/tests/api/inscriptions.test.ts index b7fc5f52..648a6406 100644 --- a/tests/api/inscriptions.test.ts +++ b/tests/api/inscriptions.test.ts @@ -1029,6 +1029,137 @@ describe('/inscriptions', () => { delegate: null, }); }); + + test('shows inscription content', async () => { + await db.updateInscriptions( + new TestChainhookPayloadBuilder() + .apply() + .block({ + height: 775617, + hash: '0x00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', + timestamp: 1676913207, + }) + .transaction({ + hash: '0x38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', + }) + .inscriptionRevealed({ + content_bytes: '0x48656C6C6F', // Hello + content_type: 'text/plain', + content_length: 5, + inscription_number: { classic: 0, jubilee: 0 }, + inscription_fee: 2805, + inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', + inscription_output_value: 10000, + inscriber_address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', + ordinal_number: 257418248345364, + ordinal_block_height: 51483, + ordinal_offset: 0, + satpoint_post_inscription: + '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc:0:0', + curse_type: { tag: 66 }, + inscription_input_index: 0, + transfers_pre_inscription: 0, + tx_index: 0, + inscription_pointer: null, + delegate: null, + metaprotocol: null, + metadata: null, + parent: null, + }) + .build() + ); + const response = await fastify.inject({ + method: 'GET', + url: '/ordinals/v1/inscriptions/38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0/content', + }); + expect(response.statusCode).toBe(200); + expect(response.headers['content-length']).toBe('5'); + expect(response.body).toBe('Hello'); + }); + + test('shows delegate inscription content', async () => { + await db.updateInscriptions( + new TestChainhookPayloadBuilder() + .apply() + .block({ + height: 775617, + hash: '0x00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', + timestamp: 1676913207, + }) + .transaction({ + hash: '0x38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', + }) + .inscriptionRevealed({ + content_bytes: '0x48656C6C6F', // Hello + content_type: 'text/plain', + content_length: 5, + inscription_number: { classic: 0, jubilee: 0 }, + inscription_fee: 2805, + inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', + inscription_output_value: 10000, + inscriber_address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', + ordinal_number: 257418248345364, + ordinal_block_height: 51483, + ordinal_offset: 0, + satpoint_post_inscription: + '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc:0:0', + curse_type: { tag: 66 }, + inscription_input_index: 0, + transfers_pre_inscription: 0, + tx_index: 0, + inscription_pointer: null, + delegate: null, + metaprotocol: null, + metadata: null, + parent: null, + }) + .build() + ); + await db.updateInscriptions( + new TestChainhookPayloadBuilder() + .apply() + .block({ + height: 775618, + hash: '0x00000000000000000000ceb7a81bf3696de0b2260078942f3ab36a7127aff296', + timestamp: 1676913207, + }) + .transaction({ + hash: '0x42174ecc8a245841035793390bb53d63b3c2acb61366446f601b09e73b94b656', + }) + .inscriptionRevealed({ + content_bytes: '', + content_type: 'text/plain', + content_length: 0, + inscription_number: { classic: 1, jubilee: 1 }, + inscription_fee: 2805, + inscription_id: '42174ecc8a245841035793390bb53d63b3c2acb61366446f601b09e73b94b656i0', + inscription_output_value: 10000, + inscriber_address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', + ordinal_number: 257418248345364, + ordinal_block_height: 51483, + ordinal_offset: 0, + satpoint_post_inscription: + '42174ecc8a245841035793390bb53d63b3c2acb61366446f601b09e73b94b656:0:0', + curse_type: { tag: 66 }, + inscription_input_index: 0, + transfers_pre_inscription: 0, + tx_index: 0, + inscription_pointer: null, + delegate: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', + metaprotocol: null, + metadata: null, + parent: null, + }) + .build() + ); + const response = await fastify.inject({ + method: 'GET', + url: '/ordinals/v1/inscriptions/42174ecc8a245841035793390bb53d63b3c2acb61366446f601b09e73b94b656i0/content', + }); + expect(response.statusCode).toBe(200); + expect(response.headers['content-length']).toBe('5'); + expect(response.body).toBe('Hello'); + }); }); describe('transfers', () => {