@secondlayer/shared 6.0.0 → 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/db/queries/usage.ts"],
4
4
  "sourcesContent": [
5
- "import { type Kysely, sql } from \"kysely\";\nimport type { Database } from \"../types.ts\";\n\n/** Increment API request counter for today. Fire-and-forget safe. */\nexport async function incrementApiRequests(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<void> {\n\tconst today = new Date().toISOString().slice(0, 10);\n\tawait sql`\n\t\tINSERT INTO usage_daily (account_id, tenant_id, date, api_requests, deliveries)\n\t\tVALUES (${accountId}, NULL, ${today}, 1, 0)\n\t\tON CONFLICT (account_id, date) WHERE tenant_id IS NULL\n\t\tDO UPDATE SET api_requests = usage_daily.api_requests + 1\n\t`.execute(db);\n}\n\nexport interface UsageSummary {\n\tapiRequestsToday: number;\n\tdeliveriesThisMonth: number;\n\tstorageBytes: number;\n}\n\n/** Get current usage for an account. */\nexport async function getUsage(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<UsageSummary> {\n\tconst today = new Date().toISOString().slice(0, 10);\n\tconst monthStart = `${today.slice(0, 7)}-01`; // YYYY-MM-01\n\n\t// Today's API requests\n\tconst dailyRow = await db\n\t\t.selectFrom(\"usage_daily\")\n\t\t.select(\"api_requests\")\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"date\", \"=\", today)\n\t\t.executeTakeFirst();\n\n\t// This month's deliveries\n\tconst monthlyRow = await db\n\t\t.selectFrom(\"usage_daily\")\n\t\t.select(sql<number>`COALESCE(SUM(deliveries), 0)`.as(\"total\"))\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"date\", \">=\", monthStart)\n\t\t.executeTakeFirst();\n\n\t// Latest storage snapshot\n\tconst storageRow = await db\n\t\t.selectFrom(\"usage_snapshots\")\n\t\t.select(\"storage_bytes\")\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.orderBy(\"measured_at\", \"desc\")\n\t\t.limit(1)\n\t\t.executeTakeFirst();\n\n\treturn {\n\t\tapiRequestsToday: dailyRow?.api_requests ?? 0,\n\t\tdeliveriesThisMonth: Number(monthlyRow?.total ?? 0),\n\t\tstorageBytes: Number(storageRow?.storage_bytes ?? 0),\n\t};\n}\n\n/**\n * Measure storage for all accounts by querying pg_total_relation_size\n * for each tenant's subgraph schemas.\n */\nexport async function measureStorage(db: Kysely<Database>): Promise<void> {\n\t// Get all accounts with subgraphs\n\tconst accountSubgraphs = await db\n\t\t.selectFrom(\"subgraphs\")\n\t\t.select([\"account_id\", \"schema_name\"])\n\t\t.where(\"schema_name\", \"is not\", null)\n\t\t.execute();\n\n\t// Group schemas by account\n\tconst byAccount = new Map<string, string[]>();\n\tfor (const row of accountSubgraphs) {\n\t\tconst schemas = byAccount.get(row.account_id) ?? [];\n\t\tif (row.schema_name) schemas.push(row.schema_name);\n\t\tbyAccount.set(row.account_id, schemas);\n\t}\n\n\tfor (const [accountId, schemas] of byAccount) {\n\t\tlet totalBytes = 0;\n\t\tfor (const schema of schemas) {\n\t\t\ttry {\n\t\t\t\tconst result = await sql<{ size: string }>`\n SELECT COALESCE(SUM(pg_total_relation_size(quote_ident(schemaname) || '.' || quote_ident(tablename))), 0)::text as size\n FROM pg_tables WHERE schemaname = ${schema}\n `.execute(db);\n\t\t\t\tconst row = result.rows[0] as { size?: string } | undefined;\n\t\t\t\ttotalBytes += Number(row?.size ?? 0);\n\t\t\t} catch {\n\t\t\t\t// Schema may not exist\n\t\t\t}\n\t\t}\n\n\t\tawait db\n\t\t\t.insertInto(\"usage_snapshots\")\n\t\t\t.values({\n\t\t\t\taccount_id: accountId,\n\t\t\t\tstorage_bytes: totalBytes,\n\t\t\t})\n\t\t\t.execute();\n\t}\n}\n"
5
+ "import { type Kysely, sql } from \"kysely\";\nimport type { Database } from \"../types.ts\";\n\n/** Increment API request counter for today. Fire-and-forget safe. */\nexport async function incrementApiRequests(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<void> {\n\tconst today = new Date().toISOString().slice(0, 10);\n\tawait sql`\n\t\tINSERT INTO usage_daily (account_id, tenant_id, date, api_requests, deliveries)\n\t\tVALUES (${accountId}, NULL, ${today}, 1, 0)\n\t\tON CONFLICT (account_id, date) WHERE tenant_id IS NULL\n\t\tDO UPDATE SET api_requests = usage_daily.api_requests + 1\n\t`.execute(db);\n}\n\nasync function incrementAccountDailyCounter(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tcolumn: \"streams_events_returned\" | \"index_decoded_events_returned\",\n\tquantity: number,\n): Promise<void> {\n\tif (quantity <= 0) return;\n\tconst today = new Date().toISOString().slice(0, 10);\n\tawait sql`\n\t\tINSERT INTO usage_daily (account_id, tenant_id, date, api_requests, deliveries, ${sql.raw(column)})\n\t\tVALUES (${accountId}, NULL, ${today}, 0, 0, ${quantity})\n\t\tON CONFLICT (account_id, date) WHERE tenant_id IS NULL\n\t\tDO UPDATE SET ${sql.raw(column)} = usage_daily.${sql.raw(column)} + ${quantity}\n\t`.execute(db);\n}\n\nexport async function incrementStreamsEventsReturned(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tquantity: number,\n): Promise<void> {\n\tawait incrementAccountDailyCounter(\n\t\tdb,\n\t\taccountId,\n\t\t\"streams_events_returned\",\n\t\tquantity,\n\t);\n}\n\nexport async function incrementIndexDecodedEventsReturned(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tquantity: number,\n): Promise<void> {\n\tawait incrementAccountDailyCounter(\n\t\tdb,\n\t\taccountId,\n\t\t\"index_decoded_events_returned\",\n\t\tquantity,\n\t);\n}\n\nexport interface UsageSummary {\n\tapiRequestsToday: number;\n\tdeliveriesThisMonth: number;\n\tstorageBytes: number;\n}\n\n/** Get current usage for an account. */\nexport async function getUsage(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<UsageSummary> {\n\tconst today = new Date().toISOString().slice(0, 10);\n\tconst monthStart = `${today.slice(0, 7)}-01`; // YYYY-MM-01\n\n\t// Today's API requests\n\tconst dailyRow = await db\n\t\t.selectFrom(\"usage_daily\")\n\t\t.select(\"api_requests\")\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"date\", \"=\", today)\n\t\t.executeTakeFirst();\n\n\t// This month's deliveries\n\tconst monthlyRow = await db\n\t\t.selectFrom(\"usage_daily\")\n\t\t.select(sql<number>`COALESCE(SUM(deliveries), 0)`.as(\"total\"))\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"date\", \">=\", monthStart)\n\t\t.executeTakeFirst();\n\n\t// Latest storage snapshot\n\tconst storageRow = await db\n\t\t.selectFrom(\"usage_snapshots\")\n\t\t.select(\"storage_bytes\")\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.orderBy(\"measured_at\", \"desc\")\n\t\t.limit(1)\n\t\t.executeTakeFirst();\n\n\treturn {\n\t\tapiRequestsToday: dailyRow?.api_requests ?? 0,\n\t\tdeliveriesThisMonth: Number(monthlyRow?.total ?? 0),\n\t\tstorageBytes: Number(storageRow?.storage_bytes ?? 0),\n\t};\n}\n\nexport interface ProductUsageBreakdown {\n\tstreamsEventsToday: number;\n\tstreamsEventsThisMonth: number;\n\tindexDecodedEventsToday: number;\n\tindexDecodedEventsThisMonth: number;\n}\n\n/** Get per-product event counts (today + this month) for an account. */\nexport async function getProductUsage(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<ProductUsageBreakdown> {\n\tconst today = new Date().toISOString().slice(0, 10);\n\tconst monthStart = `${today.slice(0, 7)}-01`;\n\n\tconst dailyRow = await db\n\t\t.selectFrom(\"usage_daily\")\n\t\t.select([\"streams_events_returned\", \"index_decoded_events_returned\"])\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"date\", \"=\", today)\n\t\t.executeTakeFirst();\n\n\tconst monthlyRow = await db\n\t\t.selectFrom(\"usage_daily\")\n\t\t.select([\n\t\t\tsql<number>`COALESCE(SUM(streams_events_returned), 0)`.as(\n\t\t\t\t\"streams_total\",\n\t\t\t),\n\t\t\tsql<number>`COALESCE(SUM(index_decoded_events_returned), 0)`.as(\n\t\t\t\t\"index_total\",\n\t\t\t),\n\t\t])\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"date\", \">=\", monthStart)\n\t\t.executeTakeFirst();\n\n\treturn {\n\t\tstreamsEventsToday: Number(dailyRow?.streams_events_returned ?? 0),\n\t\tstreamsEventsThisMonth: Number(monthlyRow?.streams_total ?? 0),\n\t\tindexDecodedEventsToday: Number(\n\t\t\tdailyRow?.index_decoded_events_returned ?? 0,\n\t\t),\n\t\tindexDecodedEventsThisMonth: Number(monthlyRow?.index_total ?? 0),\n\t};\n}\n\n/**\n * Measure storage for all accounts by querying pg_total_relation_size\n * for each tenant's subgraph schemas.\n */\nexport async function measureStorage(db: Kysely<Database>): Promise<void> {\n\t// Get all accounts with subgraphs\n\tconst accountSubgraphs = await db\n\t\t.selectFrom(\"subgraphs\")\n\t\t.select([\"account_id\", \"schema_name\"])\n\t\t.where(\"schema_name\", \"is not\", null)\n\t\t.execute();\n\n\t// Group schemas by account\n\tconst byAccount = new Map<string, string[]>();\n\tfor (const row of accountSubgraphs) {\n\t\tconst schemas = byAccount.get(row.account_id) ?? [];\n\t\tif (row.schema_name) schemas.push(row.schema_name);\n\t\tbyAccount.set(row.account_id, schemas);\n\t}\n\n\tfor (const [accountId, schemas] of byAccount) {\n\t\tlet totalBytes = 0;\n\t\tfor (const schema of schemas) {\n\t\t\ttry {\n\t\t\t\tconst result = await sql<{ size: string }>`\n SELECT COALESCE(SUM(pg_total_relation_size(quote_ident(schemaname) || '.' || quote_ident(tablename))), 0)::text as size\n FROM pg_tables WHERE schemaname = ${schema}\n `.execute(db);\n\t\t\t\tconst row = result.rows[0] as { size?: string } | undefined;\n\t\t\t\ttotalBytes += Number(row?.size ?? 0);\n\t\t\t} catch {\n\t\t\t\t// Schema may not exist\n\t\t\t}\n\t\t}\n\n\t\tawait db\n\t\t\t.insertInto(\"usage_snapshots\")\n\t\t\t.values({\n\t\t\t\taccount_id: accountId,\n\t\t\t\tstorage_bytes: totalBytes,\n\t\t\t})\n\t\t\t.execute();\n\t}\n}\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;AAAA;AAIA,eAAsB,oBAAoB,CACzC,IACA,WACgB;AAAA,EAChB,MAAM,QAAQ,IAAI,KAAK,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAAA,EAClD,MAAM;AAAA;AAAA,YAEK,oBAAoB;AAAA;AAAA;AAAA,GAG7B,QAAQ,EAAE;AAAA;AAUb,eAAsB,QAAQ,CAC7B,IACA,WACwB;AAAA,EACxB,MAAM,QAAQ,IAAI,KAAK,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAAA,EAClD,MAAM,aAAa,GAAG,MAAM,MAAM,GAAG,CAAC;AAAA,EAGtC,MAAM,WAAW,MAAM,GACrB,WAAW,aAAa,EACxB,OAAO,cAAc,EACrB,MAAM,cAAc,KAAK,SAAS,EAClC,MAAM,QAAQ,KAAK,KAAK,EACxB,iBAAiB;AAAA,EAGnB,MAAM,aAAa,MAAM,GACvB,WAAW,aAAa,EACxB,OAAO,kCAA0C,GAAG,OAAO,CAAC,EAC5D,MAAM,cAAc,KAAK,SAAS,EAClC,MAAM,QAAQ,MAAM,UAAU,EAC9B,iBAAiB;AAAA,EAGnB,MAAM,aAAa,MAAM,GACvB,WAAW,iBAAiB,EAC5B,OAAO,eAAe,EACtB,MAAM,cAAc,KAAK,SAAS,EAClC,QAAQ,eAAe,MAAM,EAC7B,MAAM,CAAC,EACP,iBAAiB;AAAA,EAEnB,OAAO;AAAA,IACN,kBAAkB,UAAU,gBAAgB;AAAA,IAC5C,qBAAqB,OAAO,YAAY,SAAS,CAAC;AAAA,IAClD,cAAc,OAAO,YAAY,iBAAiB,CAAC;AAAA,EACpD;AAAA;AAOD,eAAsB,cAAc,CAAC,IAAqC;AAAA,EAEzE,MAAM,mBAAmB,MAAM,GAC7B,WAAW,WAAW,EACtB,OAAO,CAAC,cAAc,aAAa,CAAC,EACpC,MAAM,eAAe,UAAU,IAAI,EACnC,QAAQ;AAAA,EAGV,MAAM,YAAY,IAAI;AAAA,EACtB,WAAW,OAAO,kBAAkB;AAAA,IACnC,MAAM,UAAU,UAAU,IAAI,IAAI,UAAU,KAAK,CAAC;AAAA,IAClD,IAAI,IAAI;AAAA,MAAa,QAAQ,KAAK,IAAI,WAAW;AAAA,IACjD,UAAU,IAAI,IAAI,YAAY,OAAO;AAAA,EACtC;AAAA,EAEA,YAAY,WAAW,YAAY,WAAW;AAAA,IAC7C,IAAI,aAAa;AAAA,IACjB,WAAW,UAAU,SAAS;AAAA,MAC7B,IAAI;AAAA,QACH,MAAM,SAAS,MAAM;AAAA;AAAA,8CAEqB;AAAA,UACpC,QAAQ,EAAE;AAAA,QAChB,MAAM,MAAM,OAAO,KAAK;AAAA,QACxB,cAAc,OAAO,KAAK,QAAQ,CAAC;AAAA,QAClC,MAAM;AAAA,IAGT;AAAA,IAEA,MAAM,GACJ,WAAW,iBAAiB,EAC5B,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,eAAe;AAAA,IAChB,CAAC,EACA,QAAQ;AAAA,EACX;AAAA;",
8
- "debugId": "D8C08A844119816364756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "4876492CE8C84D6164756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -4,6 +4,7 @@ interface BlocksTable {
4
4
  hash: string;
5
5
  parent_hash: string;
6
6
  burn_block_height: number;
7
+ burn_block_hash: ColumnType<string | null, string | null | undefined, string | null>;
7
8
  timestamp: number;
8
9
  canonical: Generated<boolean>;
9
10
  created_at: Generated<Date>;
@@ -102,6 +103,8 @@ interface ApiKeysTable {
102
103
  rate_limit: Generated<number>;
103
104
  ip_address: string;
104
105
  account_id: string;
106
+ product: Generated<"account" | "streams" | "index">;
107
+ tier: "free" | "build" | "scale" | "enterprise" | null;
105
108
  last_used_at: Date | null;
106
109
  revoked_at: Date | null;
107
110
  created_at: Generated<Date>;
@@ -144,6 +147,8 @@ interface UsageDailyTable {
144
147
  date: string;
145
148
  api_requests: Generated<number>;
146
149
  deliveries: Generated<number>;
150
+ streams_events_returned: Generated<number>;
151
+ index_decoded_events_returned: Generated<number>;
147
152
  }
148
153
  interface UsageSnapshotsTable {
149
154
  id: Generated<string>;
@@ -272,6 +277,44 @@ interface ProcessedStripeEventsTable {
272
277
  event_type: string;
273
278
  processed_at: Generated<Date>;
274
279
  }
280
+ interface DecodedEventsTable {
281
+ cursor: string;
282
+ block_height: number;
283
+ tx_id: string;
284
+ tx_index: number;
285
+ event_index: number;
286
+ event_type: string;
287
+ microblock_hash: string | null;
288
+ canonical: Generated<boolean>;
289
+ contract_id: string | null;
290
+ sender: string | null;
291
+ recipient: string | null;
292
+ amount: string | null;
293
+ asset_identifier: string | null;
294
+ value: string | null;
295
+ memo: string | null;
296
+ source_cursor: string;
297
+ created_at: Generated<Date>;
298
+ }
299
+ interface L2DecoderCheckpointsTable {
300
+ decoder_name: string;
301
+ last_cursor: string | null;
302
+ updated_at: Generated<Date>;
303
+ }
304
+ interface ChainReorgsTable {
305
+ id: Generated<string>;
306
+ detected_at: Generated<Date>;
307
+ fork_point_height: number;
308
+ old_index_block_hash: string | null;
309
+ new_index_block_hash: string | null;
310
+ orphaned_from_height: number;
311
+ orphaned_from_event_index: number;
312
+ orphaned_to_height: number;
313
+ orphaned_to_event_index: number;
314
+ new_canonical_height: number;
315
+ new_canonical_event_index: number;
316
+ created_at: Generated<Date>;
317
+ }
275
318
  interface Database {
276
319
  blocks: BlocksTable;
277
320
  transactions: TransactionsTable;
@@ -307,6 +350,9 @@ interface Database {
307
350
  subscriptions: SubscriptionsTable;
308
351
  subscription_outbox: SubscriptionOutboxTable;
309
352
  subscription_deliveries: SubscriptionDeliveriesTable;
353
+ decoded_events: DecodedEventsTable;
354
+ l2_decoder_checkpoints: L2DecoderCheckpointsTable;
355
+ chain_reorgs: ChainReorgsTable;
310
356
  }
311
357
  type TenantStatus = "provisioning" | "active" | "limit_warning" | "paused_limit" | "suspended" | "error" | "deleted";
312
358
  interface TenantsTable {
@@ -518,4 +564,4 @@ interface SubscriptionDeliveriesTable {
518
564
  }
519
565
  type SubscriptionDelivery = Selectable<SubscriptionDeliveriesTable>;
520
566
  type InsertSubscriptionDelivery = Insertable<SubscriptionDeliveriesTable>;
521
- export { WaitlistTable, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateTenantUsageMonthly, UpdateTenantComputeAddon, UpdateTenant, UpdateSubscriptionOutbox, UpdateSubscription, UpdateSubgraphOperation, UpdateSubgraph, UpdateProject, UpdateIndexProgress, UpdateEvent, UpdateChatSession, UpdateBlock, UpdateApiKey, UpdateAccountSpendCap, TransactionsTable, Transaction, TenantsTable, TenantUsageMonthlyTable, TenantUsageMonthly, TenantStatus, TenantComputeAddonsTable, TenantComputeAddon, Tenant, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, SubscriptionsTable, SubscriptionStatus, SubscriptionRuntime, SubscriptionOutboxTable, SubscriptionOutbox, SubscriptionFormat, SubscriptionDelivery, SubscriptionDeliveriesTable, Subscription, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphProcessingStatsTable, SubgraphOperationsTable, SubgraphOperationStatus, SubgraphOperationKind, SubgraphOperation, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGap, Subgraph, SessionsTable, Session, ProvisioningAuditStatus, ProvisioningAuditLogTable, ProvisioningAuditLog, ProvisioningAuditEvent, ProjectsTable, Project, ProcessedStripeEventsTable, OutboxStatus, MagicLinksTable, MagicLink, InsertTransaction, InsertTenantUsageMonthly, InsertTenantComputeAddon, InsertTenant, InsertTeamMember, InsertTeamInvitation, InsertSubscriptionOutbox, InsertSubscriptionDelivery, InsertSubscription, InsertSubgraphUsageDaily, InsertSubgraphOperation, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertSession, InsertProvisioningAuditLog, InsertProject, InsertMagicLink, InsertIndexProgress, InsertEvent, InsertChatSession, InsertChatMessage, InsertBlock, InsertApiKey, InsertAccountSpendCap, InsertAccountInsight, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, EventsTable, Event, Database, ChatSessionsTable, ChatSession, ChatMessagesTable, ChatMessage, BlocksTable, Block, ApiKeysTable, ApiKey, AccountsTable, AccountSpendCapsTable, AccountSpendCap, AccountInsightsTable, AccountInsight, AccountAgentRunsTable, AccountAgentRun, Account };
567
+ export { WaitlistTable, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateTenantUsageMonthly, UpdateTenantComputeAddon, UpdateTenant, UpdateSubscriptionOutbox, UpdateSubscription, UpdateSubgraphOperation, UpdateSubgraph, UpdateProject, UpdateIndexProgress, UpdateEvent, UpdateChatSession, UpdateBlock, UpdateApiKey, UpdateAccountSpendCap, TransactionsTable, Transaction, TenantsTable, TenantUsageMonthlyTable, TenantUsageMonthly, TenantStatus, TenantComputeAddonsTable, TenantComputeAddon, Tenant, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, SubscriptionsTable, SubscriptionStatus, SubscriptionRuntime, SubscriptionOutboxTable, SubscriptionOutbox, SubscriptionFormat, SubscriptionDelivery, SubscriptionDeliveriesTable, Subscription, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphProcessingStatsTable, SubgraphOperationsTable, SubgraphOperationStatus, SubgraphOperationKind, SubgraphOperation, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGap, Subgraph, SessionsTable, Session, ProvisioningAuditStatus, ProvisioningAuditLogTable, ProvisioningAuditLog, ProvisioningAuditEvent, ProjectsTable, Project, ProcessedStripeEventsTable, OutboxStatus, MagicLinksTable, MagicLink, L2DecoderCheckpointsTable, InsertTransaction, InsertTenantUsageMonthly, InsertTenantComputeAddon, InsertTenant, InsertTeamMember, InsertTeamInvitation, InsertSubscriptionOutbox, InsertSubscriptionDelivery, InsertSubscription, InsertSubgraphUsageDaily, InsertSubgraphOperation, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertSession, InsertProvisioningAuditLog, InsertProject, InsertMagicLink, InsertIndexProgress, InsertEvent, InsertChatSession, InsertChatMessage, InsertBlock, InsertApiKey, InsertAccountSpendCap, InsertAccountInsight, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, EventsTable, Event, DecodedEventsTable, Database, ChatSessionsTable, ChatSession, ChatMessagesTable, ChatMessage, ChainReorgsTable, BlocksTable, Block, ApiKeysTable, ApiKey, AccountsTable, AccountSpendCapsTable, AccountSpendCap, AccountInsightsTable, AccountInsight, AccountAgentRunsTable, AccountAgentRun, Account };
@@ -4,6 +4,7 @@ interface BlocksTable {
4
4
  hash: string;
5
5
  parent_hash: string;
6
6
  burn_block_height: number;
7
+ burn_block_hash: ColumnType<string | null, string | null | undefined, string | null>;
7
8
  timestamp: number;
8
9
  canonical: Generated<boolean>;
9
10
  created_at: Generated<Date>;
@@ -102,6 +103,8 @@ interface ApiKeysTable {
102
103
  rate_limit: Generated<number>;
103
104
  ip_address: string;
104
105
  account_id: string;
106
+ product: Generated<"account" | "streams" | "index">;
107
+ tier: "free" | "build" | "scale" | "enterprise" | null;
105
108
  last_used_at: Date | null;
106
109
  revoked_at: Date | null;
107
110
  created_at: Generated<Date>;
@@ -144,6 +147,8 @@ interface UsageDailyTable {
144
147
  date: string;
145
148
  api_requests: Generated<number>;
146
149
  deliveries: Generated<number>;
150
+ streams_events_returned: Generated<number>;
151
+ index_decoded_events_returned: Generated<number>;
147
152
  }
148
153
  interface UsageSnapshotsTable {
149
154
  id: Generated<string>;
@@ -272,6 +277,44 @@ interface ProcessedStripeEventsTable {
272
277
  event_type: string;
273
278
  processed_at: Generated<Date>;
274
279
  }
280
+ interface DecodedEventsTable {
281
+ cursor: string;
282
+ block_height: number;
283
+ tx_id: string;
284
+ tx_index: number;
285
+ event_index: number;
286
+ event_type: string;
287
+ microblock_hash: string | null;
288
+ canonical: Generated<boolean>;
289
+ contract_id: string | null;
290
+ sender: string | null;
291
+ recipient: string | null;
292
+ amount: string | null;
293
+ asset_identifier: string | null;
294
+ value: string | null;
295
+ memo: string | null;
296
+ source_cursor: string;
297
+ created_at: Generated<Date>;
298
+ }
299
+ interface L2DecoderCheckpointsTable {
300
+ decoder_name: string;
301
+ last_cursor: string | null;
302
+ updated_at: Generated<Date>;
303
+ }
304
+ interface ChainReorgsTable {
305
+ id: Generated<string>;
306
+ detected_at: Generated<Date>;
307
+ fork_point_height: number;
308
+ old_index_block_hash: string | null;
309
+ new_index_block_hash: string | null;
310
+ orphaned_from_height: number;
311
+ orphaned_from_event_index: number;
312
+ orphaned_to_height: number;
313
+ orphaned_to_event_index: number;
314
+ new_canonical_height: number;
315
+ new_canonical_event_index: number;
316
+ created_at: Generated<Date>;
317
+ }
275
318
  interface Database {
276
319
  blocks: BlocksTable;
277
320
  transactions: TransactionsTable;
@@ -307,6 +350,9 @@ interface Database {
307
350
  subscriptions: SubscriptionsTable;
308
351
  subscription_outbox: SubscriptionOutboxTable;
309
352
  subscription_deliveries: SubscriptionDeliveriesTable;
353
+ decoded_events: DecodedEventsTable;
354
+ l2_decoder_checkpoints: L2DecoderCheckpointsTable;
355
+ chain_reorgs: ChainReorgsTable;
310
356
  }
311
357
  type TenantStatus = "provisioning" | "active" | "limit_warning" | "paused_limit" | "suspended" | "error" | "deleted";
312
358
  interface TenantsTable {
@@ -1128,4 +1174,4 @@ declare function createSignatureHeader(payload: string, secret: string, timestam
1128
1174
  * Returns true if valid, false otherwise
1129
1175
  */
1130
1176
  declare function verifySignatureHeader(payload: string, header: string, secret: string, toleranceSeconds?: number): boolean;
1131
- export { validateSubscriptionFilterForTable, sql, parseJsonb, logger, jsonb, getTargetDb, getSourceDb, getRawClient, getErrorMessage, getEnv, getDb, generateSubgraphSpec, generateSubgraphOpenApi, generateSubgraphMarkdown, generateSubgraphAgentSchema, formatSubscriptionSchemaErrors, exports_hmac as crypto, closeDb, WaitlistTable, VersionConflictError, ValidationError, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateTenantUsageMonthly, UpdateTenantComputeAddon, UpdateTenant, UpdateSubscriptionRequestSchema, UpdateSubscriptionRequest, UpdateSubscriptionOutbox, UpdateSubscription, UpdateSubgraphOperation, UpdateSubgraph, UpdateProject, UpdateProfileRequestSchema, UpdateProfileRequest, UpdateIndexProgress, UpdateEvent, UpdateChatSession, UpdateBlock, UpdateApiKey, UpdateAccountSpendCap, TransactionsTable, Transaction, TenantsTable, TenantUsageMonthlyTable, TenantUsageMonthly, TenantSuspendedError, TenantStatus, TenantComputeAddonsTable, TenantComputeAddon, Tenant, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, SubscriptionsTable, SubscriptionSummary, SubscriptionStatusSchema, SubscriptionStatus, SubscriptionSchemaTables, SubscriptionSchemaTable, SubscriptionSchemaColumn, SubscriptionRuntimeSchema, SubscriptionRuntime, SubscriptionOutboxTable, SubscriptionOutbox, SubscriptionFormatSchema, SubscriptionFormat, SubscriptionFilterSchema, SubscriptionFilterPrimitiveSchema, SubscriptionFilterPrimitive, SubscriptionFilterOperatorSchema, SubscriptionFilterOperator, SubscriptionFilterClauseSchema, SubscriptionFilterClause, SubscriptionFilter, SubscriptionDetail, SubscriptionDelivery, SubscriptionDeliveriesTable, Subscription, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphSyncInfo, SubgraphSummary, SubgraphSpecOptions, SubgraphSpecFormat, SubgraphResourceWarning, SubgraphQueryParams, SubgraphProcessingStatsTable, SubgraphOperationsTable, SubgraphOperationStatus, SubgraphOperationKind, SubgraphOperation, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGapsResponse, SubgraphGapRange, SubgraphGapEntry, SubgraphGap, SubgraphDetail, SubgraphAgentSchema, Subgraph, StxTransferFilterSchema, StxTransferFilter, StxMintFilterSchema, StxMintFilter, StxLockFilterSchema, StxLockFilter, StxBurnFilterSchema, StxBurnFilter, SessionsTable, Session, SecondLayerError, SUBSCRIPTION_STATUSES, SUBSCRIPTION_RUNTIMES, SUBSCRIPTION_FORMATS, SUBSCRIPTION_FILTER_OPERATORS, RotateSecretResponse, ReplaySubscriptionRequestSchema, ReplaySubscriptionRequest, ReplayResult, ReindexResponse, RateLimitError, ProvisioningAuditStatus, ProvisioningAuditLogTable, ProvisioningAuditLog, ProvisioningAuditEvent, ProjectsTable, Project, ProcessedStripeEventsTable, PrintEventFilterSchema, PrintEventFilter, ParsedUpdateSubscriptionRequest, ParsedReplaySubscriptionRequest, ParsedCreateSubscriptionRequest, OutboxStatus, NotFoundError, NftTransferFilterSchema, NftTransferFilter, NftMintFilterSchema, NftMintFilter, NftBurnFilterSchema, NftBurnFilter, MagicLinksTable, MagicLink, KeyRotatedError, InsertTransaction, InsertTenantUsageMonthly, InsertTenantComputeAddon, InsertTenant, InsertTeamMember, InsertTeamInvitation, InsertSubscriptionOutbox, InsertSubscriptionDelivery, InsertSubscription, InsertSubgraphUsageDaily, InsertSubgraphOperation, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertSession, InsertProvisioningAuditLog, InsertProject, InsertMagicLink, InsertIndexProgress, InsertEvent, InsertChatSession, InsertChatMessage, InsertBlock, InsertApiKey, InsertAccountSpendCap, InsertAccountInsight, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, FtTransferFilterSchema, FtTransferFilter, FtMintFilterSchema, FtMintFilter, FtBurnFilterSchema, FtBurnFilter, ForbiddenError, EventsTable, EventFilterSchema, EventFilter, Event, ErrorCodes, ErrorCode, Env, DeploySubgraphResponse, DeploySubgraphRequestSchema, DeploySubgraphRequest, DeliveryRow, DeadRow, DatabaseError, Database, CreateSubscriptionResponse, CreateSubscriptionRequestSchema, CreateSubscriptionRequest, ContractDeployFilterSchema, ContractDeployFilter, ContractCallFilterSchema, ContractCallFilter, ChatSessionsTable, ChatSession, ChatMessagesTable, ChatMessage, CODE_TO_STATUS, BlocksTable, Block, AuthorizationError, AuthenticationError, ApiKeysTable, ApiKey, AccountsTable, AccountSpendCapsTable, AccountSpendCap, AccountInsightsTable, AccountInsight, AccountAgentRunsTable, AccountAgentRun, Account };
1177
+ export { validateSubscriptionFilterForTable, sql, parseJsonb, logger, jsonb, getTargetDb, getSourceDb, getRawClient, getErrorMessage, getEnv, getDb, generateSubgraphSpec, generateSubgraphOpenApi, generateSubgraphMarkdown, generateSubgraphAgentSchema, formatSubscriptionSchemaErrors, exports_hmac as crypto, closeDb, WaitlistTable, VersionConflictError, ValidationError, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateTenantUsageMonthly, UpdateTenantComputeAddon, UpdateTenant, UpdateSubscriptionRequestSchema, UpdateSubscriptionRequest, UpdateSubscriptionOutbox, UpdateSubscription, UpdateSubgraphOperation, UpdateSubgraph, UpdateProject, UpdateProfileRequestSchema, UpdateProfileRequest, UpdateIndexProgress, UpdateEvent, UpdateChatSession, UpdateBlock, UpdateApiKey, UpdateAccountSpendCap, TransactionsTable, Transaction, TenantsTable, TenantUsageMonthlyTable, TenantUsageMonthly, TenantSuspendedError, TenantStatus, TenantComputeAddonsTable, TenantComputeAddon, Tenant, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, SubscriptionsTable, SubscriptionSummary, SubscriptionStatusSchema, SubscriptionStatus, SubscriptionSchemaTables, SubscriptionSchemaTable, SubscriptionSchemaColumn, SubscriptionRuntimeSchema, SubscriptionRuntime, SubscriptionOutboxTable, SubscriptionOutbox, SubscriptionFormatSchema, SubscriptionFormat, SubscriptionFilterSchema, SubscriptionFilterPrimitiveSchema, SubscriptionFilterPrimitive, SubscriptionFilterOperatorSchema, SubscriptionFilterOperator, SubscriptionFilterClauseSchema, SubscriptionFilterClause, SubscriptionFilter, SubscriptionDetail, SubscriptionDelivery, SubscriptionDeliveriesTable, Subscription, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphSyncInfo, SubgraphSummary, SubgraphSpecOptions, SubgraphSpecFormat, SubgraphResourceWarning, SubgraphQueryParams, SubgraphProcessingStatsTable, SubgraphOperationsTable, SubgraphOperationStatus, SubgraphOperationKind, SubgraphOperation, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGapsResponse, SubgraphGapRange, SubgraphGapEntry, SubgraphGap, SubgraphDetail, SubgraphAgentSchema, Subgraph, StxTransferFilterSchema, StxTransferFilter, StxMintFilterSchema, StxMintFilter, StxLockFilterSchema, StxLockFilter, StxBurnFilterSchema, StxBurnFilter, SessionsTable, Session, SecondLayerError, SUBSCRIPTION_STATUSES, SUBSCRIPTION_RUNTIMES, SUBSCRIPTION_FORMATS, SUBSCRIPTION_FILTER_OPERATORS, RotateSecretResponse, ReplaySubscriptionRequestSchema, ReplaySubscriptionRequest, ReplayResult, ReindexResponse, RateLimitError, ProvisioningAuditStatus, ProvisioningAuditLogTable, ProvisioningAuditLog, ProvisioningAuditEvent, ProjectsTable, Project, ProcessedStripeEventsTable, PrintEventFilterSchema, PrintEventFilter, ParsedUpdateSubscriptionRequest, ParsedReplaySubscriptionRequest, ParsedCreateSubscriptionRequest, OutboxStatus, NotFoundError, NftTransferFilterSchema, NftTransferFilter, NftMintFilterSchema, NftMintFilter, NftBurnFilterSchema, NftBurnFilter, MagicLinksTable, MagicLink, L2DecoderCheckpointsTable, KeyRotatedError, InsertTransaction, InsertTenantUsageMonthly, InsertTenantComputeAddon, InsertTenant, InsertTeamMember, InsertTeamInvitation, InsertSubscriptionOutbox, InsertSubscriptionDelivery, InsertSubscription, InsertSubgraphUsageDaily, InsertSubgraphOperation, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertSession, InsertProvisioningAuditLog, InsertProject, InsertMagicLink, InsertIndexProgress, InsertEvent, InsertChatSession, InsertChatMessage, InsertBlock, InsertApiKey, InsertAccountSpendCap, InsertAccountInsight, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, FtTransferFilterSchema, FtTransferFilter, FtMintFilterSchema, FtMintFilter, FtBurnFilterSchema, FtBurnFilter, ForbiddenError, EventsTable, EventFilterSchema, EventFilter, Event, ErrorCodes, ErrorCode, Env, DeploySubgraphResponse, DeploySubgraphRequestSchema, DeploySubgraphRequest, DeliveryRow, DecodedEventsTable, DeadRow, DatabaseError, Database, CreateSubscriptionResponse, CreateSubscriptionRequestSchema, CreateSubscriptionRequest, ContractDeployFilterSchema, ContractDeployFilter, ContractCallFilterSchema, ContractCallFilter, ChatSessionsTable, ChatSession, ChatMessagesTable, ChatMessage, ChainReorgsTable, CODE_TO_STATUS, BlocksTable, Block, AuthorizationError, AuthenticationError, ApiKeysTable, ApiKey, AccountsTable, AccountSpendCapsTable, AccountSpendCap, AccountInsightsTable, AccountInsight, AccountAgentRunsTable, AccountAgentRun, Account };
@@ -5,6 +5,7 @@ interface BlocksTable {
5
5
  hash: string;
6
6
  parent_hash: string;
7
7
  burn_block_height: number;
8
+ burn_block_hash: ColumnType<string | null, string | null | undefined, string | null>;
8
9
  timestamp: number;
9
10
  canonical: Generated<boolean>;
10
11
  created_at: Generated<Date>;
@@ -103,6 +104,8 @@ interface ApiKeysTable {
103
104
  rate_limit: Generated<number>;
104
105
  ip_address: string;
105
106
  account_id: string;
107
+ product: Generated<"account" | "streams" | "index">;
108
+ tier: "free" | "build" | "scale" | "enterprise" | null;
106
109
  last_used_at: Date | null;
107
110
  revoked_at: Date | null;
108
111
  created_at: Generated<Date>;
@@ -145,6 +148,8 @@ interface UsageDailyTable {
145
148
  date: string;
146
149
  api_requests: Generated<number>;
147
150
  deliveries: Generated<number>;
151
+ streams_events_returned: Generated<number>;
152
+ index_decoded_events_returned: Generated<number>;
148
153
  }
149
154
  interface UsageSnapshotsTable {
150
155
  id: Generated<string>;
@@ -273,6 +278,44 @@ interface ProcessedStripeEventsTable {
273
278
  event_type: string;
274
279
  processed_at: Generated<Date>;
275
280
  }
281
+ interface DecodedEventsTable {
282
+ cursor: string;
283
+ block_height: number;
284
+ tx_id: string;
285
+ tx_index: number;
286
+ event_index: number;
287
+ event_type: string;
288
+ microblock_hash: string | null;
289
+ canonical: Generated<boolean>;
290
+ contract_id: string | null;
291
+ sender: string | null;
292
+ recipient: string | null;
293
+ amount: string | null;
294
+ asset_identifier: string | null;
295
+ value: string | null;
296
+ memo: string | null;
297
+ source_cursor: string;
298
+ created_at: Generated<Date>;
299
+ }
300
+ interface L2DecoderCheckpointsTable {
301
+ decoder_name: string;
302
+ last_cursor: string | null;
303
+ updated_at: Generated<Date>;
304
+ }
305
+ interface ChainReorgsTable {
306
+ id: Generated<string>;
307
+ detected_at: Generated<Date>;
308
+ fork_point_height: number;
309
+ old_index_block_hash: string | null;
310
+ new_index_block_hash: string | null;
311
+ orphaned_from_height: number;
312
+ orphaned_from_event_index: number;
313
+ orphaned_to_height: number;
314
+ orphaned_to_event_index: number;
315
+ new_canonical_height: number;
316
+ new_canonical_event_index: number;
317
+ created_at: Generated<Date>;
318
+ }
276
319
  interface Database {
277
320
  blocks: BlocksTable;
278
321
  transactions: TransactionsTable;
@@ -308,6 +351,9 @@ interface Database {
308
351
  subscriptions: SubscriptionsTable;
309
352
  subscription_outbox: SubscriptionOutboxTable;
310
353
  subscription_deliveries: SubscriptionDeliveriesTable;
354
+ decoded_events: DecodedEventsTable;
355
+ l2_decoder_checkpoints: L2DecoderCheckpointsTable;
356
+ chain_reorgs: ChainReorgsTable;
311
357
  }
312
358
  type TenantStatus = "provisioning" | "active" | "limit_warning" | "paused_limit" | "suspended" | "error" | "deleted";
313
359
  interface TenantsTable {
@@ -1,9 +1,10 @@
1
- import { Generated, Insertable, Selectable } from "kysely";
1
+ import { ColumnType, Generated, Insertable, Selectable } from "kysely";
2
2
  interface BlocksTable {
3
3
  height: number;
4
4
  hash: string;
5
5
  parent_hash: string;
6
6
  burn_block_height: number;
7
+ burn_block_hash: ColumnType<string | null, string | null | undefined, string | null>;
7
8
  timestamp: number;
8
9
  canonical: Generated<boolean>;
9
10
  created_at: Generated<Date>;
@@ -0,0 +1,50 @@
1
+ import { type Kysely, sql } from "kysely";
2
+
3
+ // biome-ignore lint/suspicious/noExplicitAny: migration DDL is intentionally schema-dynamic
4
+ export async function up(db: Kysely<any>): Promise<void> {
5
+ await db.schema
6
+ .createTable("decoded_events")
7
+ .addColumn("cursor", "text", (c) => c.primaryKey())
8
+ .addColumn("block_height", "bigint", (c) => c.notNull())
9
+ .addColumn("tx_id", "text", (c) => c.notNull())
10
+ .addColumn("tx_index", "integer", (c) => c.notNull())
11
+ .addColumn("event_index", "integer", (c) => c.notNull())
12
+ .addColumn("event_type", "text", (c) => c.notNull())
13
+ .addColumn("decoded_payload", "jsonb", (c) => c.notNull())
14
+ .addColumn("source_cursor", "text", (c) => c.notNull())
15
+ .addColumn("created_at", "timestamp", (c) =>
16
+ c.notNull().defaultTo(sql`now()`),
17
+ )
18
+ .execute();
19
+
20
+ await db.schema
21
+ .createIndex("decoded_events_block_height_idx")
22
+ .on("decoded_events")
23
+ .column("block_height")
24
+ .execute();
25
+ await db.schema
26
+ .createIndex("decoded_events_event_type_idx")
27
+ .on("decoded_events")
28
+ .column("event_type")
29
+ .execute();
30
+ await db.schema
31
+ .createIndex("decoded_events_tx_id_event_index_idx")
32
+ .on("decoded_events")
33
+ .columns(["tx_id", "event_index"])
34
+ .execute();
35
+
36
+ await db.schema
37
+ .createTable("l2_decoder_checkpoints")
38
+ .addColumn("decoder_name", "text", (c) => c.primaryKey())
39
+ .addColumn("last_cursor", "text")
40
+ .addColumn("updated_at", "timestamp", (c) =>
41
+ c.notNull().defaultTo(sql`now()`),
42
+ )
43
+ .execute();
44
+ }
45
+
46
+ // biome-ignore lint/suspicious/noExplicitAny: migration DDL is intentionally schema-dynamic
47
+ export async function down(db: Kysely<any>): Promise<void> {
48
+ await db.schema.dropTable("l2_decoder_checkpoints").ifExists().execute();
49
+ await db.schema.dropTable("decoded_events").ifExists().execute();
50
+ }
@@ -0,0 +1,83 @@
1
+ import { type Kysely, sql } from "kysely";
2
+
3
+ export async function up(db: Kysely<unknown>): Promise<void> {
4
+ await sql`
5
+ ALTER TABLE decoded_events
6
+ ADD COLUMN microblock_hash TEXT,
7
+ ADD COLUMN canonical BOOLEAN NOT NULL DEFAULT true,
8
+ ADD COLUMN contract_id TEXT,
9
+ ADD COLUMN sender TEXT,
10
+ ADD COLUMN recipient TEXT,
11
+ ADD COLUMN amount TEXT,
12
+ ADD COLUMN asset_identifier TEXT,
13
+ ADD COLUMN value TEXT,
14
+ ADD COLUMN memo TEXT
15
+ `.execute(db);
16
+
17
+ await sql`
18
+ UPDATE decoded_events
19
+ SET
20
+ contract_id = decoded_payload->>'contract_id',
21
+ sender = decoded_payload->>'sender',
22
+ recipient = decoded_payload->>'recipient',
23
+ amount = decoded_payload->>'amount',
24
+ asset_identifier = decoded_payload->>'asset_identifier'
25
+ WHERE event_type = 'ft_transfer'
26
+ `.execute(db);
27
+
28
+ await sql`ALTER TABLE decoded_events DROP COLUMN decoded_payload`.execute(db);
29
+
30
+ await sql`
31
+ CREATE INDEX decoded_events_contract_height_event_idx
32
+ ON decoded_events (contract_id, block_height, event_index)
33
+ `.execute(db);
34
+ await sql`
35
+ CREATE INDEX decoded_events_sender_height_event_idx
36
+ ON decoded_events (sender, block_height, event_index)
37
+ `.execute(db);
38
+ await sql`
39
+ CREATE INDEX decoded_events_recipient_height_event_idx
40
+ ON decoded_events (recipient, block_height, event_index)
41
+ `.execute(db);
42
+ }
43
+
44
+ export async function down(db: Kysely<unknown>): Promise<void> {
45
+ await sql`DROP INDEX IF EXISTS decoded_events_recipient_height_event_idx`.execute(
46
+ db,
47
+ );
48
+ await sql`DROP INDEX IF EXISTS decoded_events_sender_height_event_idx`.execute(
49
+ db,
50
+ );
51
+ await sql`DROP INDEX IF EXISTS decoded_events_contract_height_event_idx`.execute(
52
+ db,
53
+ );
54
+
55
+ await sql`ALTER TABLE decoded_events ADD COLUMN decoded_payload JSONB`.execute(
56
+ db,
57
+ );
58
+ await sql`
59
+ UPDATE decoded_events
60
+ SET decoded_payload = jsonb_strip_nulls(jsonb_build_object(
61
+ 'contract_id', contract_id,
62
+ 'sender', sender,
63
+ 'recipient', recipient,
64
+ 'amount', amount,
65
+ 'asset_identifier', asset_identifier,
66
+ 'value', value,
67
+ 'memo', memo
68
+ ))
69
+ `.execute(db);
70
+ await sql`
71
+ ALTER TABLE decoded_events
72
+ ALTER COLUMN decoded_payload SET NOT NULL,
73
+ DROP COLUMN memo,
74
+ DROP COLUMN value,
75
+ DROP COLUMN asset_identifier,
76
+ DROP COLUMN amount,
77
+ DROP COLUMN recipient,
78
+ DROP COLUMN sender,
79
+ DROP COLUMN contract_id,
80
+ DROP COLUMN canonical,
81
+ DROP COLUMN microblock_hash
82
+ `.execute(db);
83
+ }
@@ -0,0 +1,18 @@
1
+ import { type Kysely, sql } from "kysely";
2
+
3
+ export async function up(db: Kysely<unknown>): Promise<void> {
4
+ await sql`SET lock_timeout = '30s'`.execute(db);
5
+ await sql`
6
+ ALTER TABLE usage_daily
7
+ ADD COLUMN IF NOT EXISTS streams_events_returned integer NOT NULL DEFAULT 0,
8
+ ADD COLUMN IF NOT EXISTS index_decoded_events_returned integer NOT NULL DEFAULT 0
9
+ `.execute(db);
10
+ }
11
+
12
+ export async function down(db: Kysely<unknown>): Promise<void> {
13
+ await sql`
14
+ ALTER TABLE usage_daily
15
+ DROP COLUMN IF EXISTS index_decoded_events_returned,
16
+ DROP COLUMN IF EXISTS streams_events_returned
17
+ `.execute(db);
18
+ }
@@ -0,0 +1,48 @@
1
+ import { type Kysely, sql } from "kysely";
2
+
3
+ export async function up(db: Kysely<unknown>): Promise<void> {
4
+ await sql`SET lock_timeout = '30s'`.execute(db);
5
+ await sql`
6
+ ALTER TABLE blocks
7
+ ADD COLUMN IF NOT EXISTS burn_block_hash text
8
+ `.execute(db);
9
+
10
+ await sql`
11
+ CREATE TABLE IF NOT EXISTS chain_reorgs (
12
+ id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
13
+ detected_at timestamptz NOT NULL DEFAULT now(),
14
+ fork_point_height bigint NOT NULL,
15
+ old_index_block_hash text,
16
+ new_index_block_hash text,
17
+ orphaned_from_height bigint NOT NULL,
18
+ orphaned_from_event_index integer NOT NULL,
19
+ orphaned_to_height bigint NOT NULL,
20
+ orphaned_to_event_index integer NOT NULL,
21
+ new_canonical_height bigint NOT NULL,
22
+ new_canonical_event_index integer NOT NULL,
23
+ created_at timestamptz NOT NULL DEFAULT now()
24
+ )
25
+ `.execute(db);
26
+
27
+ await sql`
28
+ CREATE INDEX IF NOT EXISTS chain_reorgs_detected_at_idx
29
+ ON chain_reorgs (detected_at)
30
+ `.execute(db);
31
+ await sql`
32
+ CREATE INDEX IF NOT EXISTS chain_reorgs_orphaned_range_idx
33
+ ON chain_reorgs (
34
+ orphaned_from_height,
35
+ orphaned_from_event_index,
36
+ orphaned_to_height,
37
+ orphaned_to_event_index
38
+ )
39
+ `.execute(db);
40
+ }
41
+
42
+ export async function down(db: Kysely<unknown>): Promise<void> {
43
+ await sql`DROP TABLE IF EXISTS chain_reorgs`.execute(db);
44
+ await sql`
45
+ ALTER TABLE blocks
46
+ DROP COLUMN IF EXISTS burn_block_hash
47
+ `.execute(db);
48
+ }
@@ -0,0 +1,43 @@
1
+ import { type Kysely, sql } from "kysely";
2
+
3
+ export async function up(db: Kysely<unknown>): Promise<void> {
4
+ await sql`SET lock_timeout = '30s'`.execute(db);
5
+
6
+ await sql`
7
+ ALTER TABLE api_keys
8
+ ADD COLUMN IF NOT EXISTS product text NOT NULL DEFAULT 'account',
9
+ ADD COLUMN IF NOT EXISTS tier text
10
+ `.execute(db);
11
+
12
+ await sql`
13
+ ALTER TABLE api_keys
14
+ ADD CONSTRAINT api_keys_product_check
15
+ CHECK (product IN ('account', 'streams', 'index'))
16
+ `.execute(db);
17
+
18
+ await sql`
19
+ ALTER TABLE api_keys
20
+ ADD CONSTRAINT api_keys_tier_check
21
+ CHECK (tier IS NULL OR tier IN ('free', 'build', 'scale', 'enterprise'))
22
+ `.execute(db);
23
+
24
+ await sql`
25
+ CREATE INDEX IF NOT EXISTS api_keys_product_status_idx
26
+ ON api_keys (product, status)
27
+ WHERE status = 'active'
28
+ `.execute(db);
29
+ }
30
+
31
+ export async function down(db: Kysely<unknown>): Promise<void> {
32
+ await sql`DROP INDEX IF EXISTS api_keys_product_status_idx`.execute(db);
33
+ await sql`
34
+ ALTER TABLE api_keys
35
+ DROP CONSTRAINT IF EXISTS api_keys_product_check,
36
+ DROP CONSTRAINT IF EXISTS api_keys_tier_check
37
+ `.execute(db);
38
+ await sql`
39
+ ALTER TABLE api_keys
40
+ DROP COLUMN IF EXISTS product,
41
+ DROP COLUMN IF EXISTS tier
42
+ `.execute(db);
43
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@secondlayer/shared",
3
- "version": "6.0.0",
3
+ "version": "6.2.0",
4
4
  "type": "module",
5
5
  "main": "./dist/src/index.js",
6
6
  "types": "./dist/src/index.d.ts",
@@ -25,6 +25,10 @@
25
25
  "types": "./dist/src/db/queries/usage.d.ts",
26
26
  "import": "./dist/src/db/queries/usage.js"
27
27
  },
28
+ "./db/queries/chain-reorgs": {
29
+ "types": "./dist/src/db/queries/chain-reorgs.d.ts",
30
+ "import": "./dist/src/db/queries/chain-reorgs.js"
31
+ },
28
32
  "./db/queries/subgraphs": {
29
33
  "types": "./dist/src/db/queries/subgraphs.d.ts",
30
34
  "import": "./dist/src/db/queries/subgraphs.js"