From 377ebb028c694ddf30a4450c457fd4dc6f27aabb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Wed, 1 Mar 2023 22:48:20 -0600 Subject: [PATCH] feat: filter by sat ordinal range --- src/api/routes/inscriptions.ts | 9 +++++ src/pg/pg-store.ts | 10 +++++ tests/inscriptions.test.ts | 73 ++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) diff --git a/src/api/routes/inscriptions.ts b/src/api/routes/inscriptions.ts index 0ebfe1ad..9c24253a 100644 --- a/src/api/routes/inscriptions.ts +++ b/src/api/routes/inscriptions.ts @@ -24,6 +24,7 @@ import { BlockParam, BlockHeightParam, TimestampParam, + OrdinalParam, } from '../types'; import { handleChainTipCache, handleInscriptionCache } from '../util/cache'; import { @@ -47,6 +48,10 @@ function inscriptionIdParam(param: string | number) { return InscriptionIdParamCType.Check(param) ? { genesis_id: param } : { number: param }; } +function bigIntParam(param: number | undefined) { + return param ? BigInt(param) : undefined; +} + const IndexRoutes: FastifyPluginCallback, Server, TypeBoxTypeProvider> = ( fastify, options, @@ -66,6 +71,8 @@ const IndexRoutes: FastifyPluginCallback, Server, TypeBoxTy to_genesis_block_height: Type.Optional(BlockHeightParam), from_genesis_timestamp: Type.Optional(TimestampParam), to_genesis_timestamp: Type.Optional(TimestampParam), + from_sat_ordinal: Type.Optional(OrdinalParam), + to_sat_ordinal: Type.Optional(OrdinalParam), output: Type.Optional(OutputParam), address: Type.Optional(AddressParam), mime_type: Type.Optional(MimeTypesParam), @@ -92,6 +99,8 @@ const IndexRoutes: FastifyPluginCallback, Server, TypeBoxTy ...blockParam(request.query.to_genesis_block_height, 'to_genesis_block'), from_genesis_timestamp: request.query.from_genesis_timestamp, to_genesis_timestamp: request.query.to_genesis_timestamp, + from_sat_ordinal: bigIntParam(request.query.from_sat_ordinal), + to_sat_ordinal: bigIntParam(request.query.to_sat_ordinal), output: request.query.output, address: request.query.address, mime_type: request.query.mime_type, diff --git a/src/pg/pg-store.ts b/src/pg/pg-store.ts index d11df3cf..0a0a485e 100644 --- a/src/pg/pg-store.ts +++ b/src/pg/pg-store.ts @@ -168,6 +168,8 @@ export class PgStore extends BasePgStore { output?: string; sat_rarity?: SatoshiRarity[]; sat_ordinal?: bigint; + from_sat_ordinal?: bigint; + to_sat_ordinal?: bigint; order_by?: OrderBy; order?: Order; limit: number; @@ -229,6 +231,14 @@ export class PgStore extends BasePgStore { ? this.sql`AND gen.timestamp <= to_timestamp(${args.to_genesis_timestamp})` : this.sql`` } + ${ + args.from_sat_ordinal + ? this.sql`AND loc.sat_ordinal >= ${args.from_sat_ordinal}` + : this.sql`` + } + ${ + args.to_sat_ordinal ? this.sql`AND loc.sat_ordinal <= ${args.to_sat_ordinal}` : this.sql`` + } ${args.address ? this.sql`AND loc.address = ${args.address}` : this.sql``} ${ args.mime_type?.length diff --git a/tests/inscriptions.test.ts b/tests/inscriptions.test.ts index 8e37f16e..581dc0c0 100644 --- a/tests/inscriptions.test.ts +++ b/tests/inscriptions.test.ts @@ -513,6 +513,79 @@ describe('/inscriptions', () => { expect(responseJson3.results[0].genesis_timestamp).toBe(1675312161000); }); + test('index filtered by sat ordinal range', async () => { + await db.insertInscriptionGenesis({ + inscription: { + genesis_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201i0', + mime_type: 'text/plain', + content_type: 'text/plain;charset=utf-8', + content_length: 5, + number: 7, + content: '0x48656C6C6F', + fee: 705n, + }, + location: { + inscription_id: 0, + block_height: 778575, + block_hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', + tx_id: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201', + address: 'bc1pscktlmn99gyzlvymvrezh6vwd0l4kg06tg5rvssw0czg8873gz5sdkteqj', + output: '9f4a9b73b0713c5da01c0a47f97c6c001af9028d6bdd9e264dfacbc4e6790201:0', + offset: 0n, + value: 10000n, + timestamp: 1677731361, + sat_ordinal: 257418248345364n, + sat_rarity: 'common', + genesis: true, + current: true, + }, + }); + await db.insertInscriptionGenesis({ + inscription: { + genesis_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0', + mime_type: 'image/png', + content_type: 'image/png', + content_length: 5, + number: 7, + content: '0x48656C6C6F', + fee: 2805n, + }, + location: { + inscription_id: 0, + block_height: 775617, + block_hash: '00000000000000000002a90330a99f67e3f01eb2ce070b45930581e82fb7a91d', + tx_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc', + address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td', + output: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dc:0', + offset: 0n, + value: 10000n, + timestamp: 1675312161, + sat_ordinal: 1000000000000n, + sat_rarity: 'epic', + genesis: true, + current: true, + }, + }); + + const response2 = await fastify.inject({ + method: 'GET', + url: '/ordinals/v1/inscriptions?from_sat_ordinal=1000400000000', + }); + expect(response2.statusCode).toBe(200); + const responseJson2 = response2.json(); + expect(responseJson2.total).toBe(1); + expect(responseJson2.results[0].sat_ordinal).toBe('257418248345364'); + + const response3 = await fastify.inject({ + method: 'GET', + url: '/ordinals/v1/inscriptions?to_sat_ordinal=1000400000000', + }); + expect(response3.statusCode).toBe(200); + const responseJson3 = response3.json(); + expect(responseJson3.total).toBe(1); + expect(responseJson3.results[0].sat_ordinal).toBe('1000000000000'); + }); + test('index filtered by output', async () => { await db.insertInscriptionGenesis({ inscription: {