@secondlayer/shared 6.0.0 → 6.1.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.
@@ -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>;
@@ -145,6 +146,8 @@ interface UsageDailyTable {
145
146
  date: string;
146
147
  api_requests: Generated<number>;
147
148
  deliveries: Generated<number>;
149
+ streams_events_returned: Generated<number>;
150
+ index_decoded_events_returned: Generated<number>;
148
151
  }
149
152
  interface UsageSnapshotsTable {
150
153
  id: Generated<string>;
@@ -273,6 +276,44 @@ interface ProcessedStripeEventsTable {
273
276
  event_type: string;
274
277
  processed_at: Generated<Date>;
275
278
  }
279
+ interface DecodedEventsTable {
280
+ cursor: string;
281
+ block_height: number;
282
+ tx_id: string;
283
+ tx_index: number;
284
+ event_index: number;
285
+ event_type: string;
286
+ microblock_hash: string | null;
287
+ canonical: Generated<boolean>;
288
+ contract_id: string | null;
289
+ sender: string | null;
290
+ recipient: string | null;
291
+ amount: string | null;
292
+ asset_identifier: string | null;
293
+ value: string | null;
294
+ memo: string | null;
295
+ source_cursor: string;
296
+ created_at: Generated<Date>;
297
+ }
298
+ interface L2DecoderCheckpointsTable {
299
+ decoder_name: string;
300
+ last_cursor: string | null;
301
+ updated_at: Generated<Date>;
302
+ }
303
+ interface ChainReorgsTable {
304
+ id: Generated<string>;
305
+ detected_at: Generated<Date>;
306
+ fork_point_height: number;
307
+ old_index_block_hash: string | null;
308
+ new_index_block_hash: string | null;
309
+ orphaned_from_height: number;
310
+ orphaned_from_event_index: number;
311
+ orphaned_to_height: number;
312
+ orphaned_to_event_index: number;
313
+ new_canonical_height: number;
314
+ new_canonical_event_index: number;
315
+ created_at: Generated<Date>;
316
+ }
276
317
  interface Database {
277
318
  blocks: BlocksTable;
278
319
  transactions: TransactionsTable;
@@ -308,6 +349,9 @@ interface Database {
308
349
  subscriptions: SubscriptionsTable;
309
350
  subscription_outbox: SubscriptionOutboxTable;
310
351
  subscription_deliveries: SubscriptionDeliveriesTable;
352
+ decoded_events: DecodedEventsTable;
353
+ l2_decoder_checkpoints: L2DecoderCheckpointsTable;
354
+ chain_reorgs: ChainReorgsTable;
311
355
  }
312
356
  type TenantStatus = "provisioning" | "active" | "limit_warning" | "paused_limit" | "suspended" | "error" | "deleted";
313
357
  interface TenantsTable {
@@ -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>;
@@ -145,6 +146,8 @@ interface UsageDailyTable {
145
146
  date: string;
146
147
  api_requests: Generated<number>;
147
148
  deliveries: Generated<number>;
149
+ streams_events_returned: Generated<number>;
150
+ index_decoded_events_returned: Generated<number>;
148
151
  }
149
152
  interface UsageSnapshotsTable {
150
153
  id: Generated<string>;
@@ -273,6 +276,44 @@ interface ProcessedStripeEventsTable {
273
276
  event_type: string;
274
277
  processed_at: Generated<Date>;
275
278
  }
279
+ interface DecodedEventsTable {
280
+ cursor: string;
281
+ block_height: number;
282
+ tx_id: string;
283
+ tx_index: number;
284
+ event_index: number;
285
+ event_type: string;
286
+ microblock_hash: string | null;
287
+ canonical: Generated<boolean>;
288
+ contract_id: string | null;
289
+ sender: string | null;
290
+ recipient: string | null;
291
+ amount: string | null;
292
+ asset_identifier: string | null;
293
+ value: string | null;
294
+ memo: string | null;
295
+ source_cursor: string;
296
+ created_at: Generated<Date>;
297
+ }
298
+ interface L2DecoderCheckpointsTable {
299
+ decoder_name: string;
300
+ last_cursor: string | null;
301
+ updated_at: Generated<Date>;
302
+ }
303
+ interface ChainReorgsTable {
304
+ id: Generated<string>;
305
+ detected_at: Generated<Date>;
306
+ fork_point_height: number;
307
+ old_index_block_hash: string | null;
308
+ new_index_block_hash: string | null;
309
+ orphaned_from_height: number;
310
+ orphaned_from_event_index: number;
311
+ orphaned_to_height: number;
312
+ orphaned_to_event_index: number;
313
+ new_canonical_height: number;
314
+ new_canonical_event_index: number;
315
+ created_at: Generated<Date>;
316
+ }
276
317
  interface Database {
277
318
  blocks: BlocksTable;
278
319
  transactions: TransactionsTable;
@@ -308,6 +349,9 @@ interface Database {
308
349
  subscriptions: SubscriptionsTable;
309
350
  subscription_outbox: SubscriptionOutboxTable;
310
351
  subscription_deliveries: SubscriptionDeliveriesTable;
352
+ decoded_events: DecodedEventsTable;
353
+ l2_decoder_checkpoints: L2DecoderCheckpointsTable;
354
+ chain_reorgs: ChainReorgsTable;
311
355
  }
312
356
  type TenantStatus = "provisioning" | "active" | "limit_warning" | "paused_limit" | "suspended" | "error" | "deleted";
313
357
  interface TenantsTable {
@@ -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>;
@@ -145,6 +146,8 @@ interface UsageDailyTable {
145
146
  date: string;
146
147
  api_requests: Generated<number>;
147
148
  deliveries: Generated<number>;
149
+ streams_events_returned: Generated<number>;
150
+ index_decoded_events_returned: Generated<number>;
148
151
  }
149
152
  interface UsageSnapshotsTable {
150
153
  id: Generated<string>;
@@ -273,6 +276,44 @@ interface ProcessedStripeEventsTable {
273
276
  event_type: string;
274
277
  processed_at: Generated<Date>;
275
278
  }
279
+ interface DecodedEventsTable {
280
+ cursor: string;
281
+ block_height: number;
282
+ tx_id: string;
283
+ tx_index: number;
284
+ event_index: number;
285
+ event_type: string;
286
+ microblock_hash: string | null;
287
+ canonical: Generated<boolean>;
288
+ contract_id: string | null;
289
+ sender: string | null;
290
+ recipient: string | null;
291
+ amount: string | null;
292
+ asset_identifier: string | null;
293
+ value: string | null;
294
+ memo: string | null;
295
+ source_cursor: string;
296
+ created_at: Generated<Date>;
297
+ }
298
+ interface L2DecoderCheckpointsTable {
299
+ decoder_name: string;
300
+ last_cursor: string | null;
301
+ updated_at: Generated<Date>;
302
+ }
303
+ interface ChainReorgsTable {
304
+ id: Generated<string>;
305
+ detected_at: Generated<Date>;
306
+ fork_point_height: number;
307
+ old_index_block_hash: string | null;
308
+ new_index_block_hash: string | null;
309
+ orphaned_from_height: number;
310
+ orphaned_from_event_index: number;
311
+ orphaned_to_height: number;
312
+ orphaned_to_event_index: number;
313
+ new_canonical_height: number;
314
+ new_canonical_event_index: number;
315
+ created_at: Generated<Date>;
316
+ }
276
317
  interface Database {
277
318
  blocks: BlocksTable;
278
319
  transactions: TransactionsTable;
@@ -308,6 +349,9 @@ interface Database {
308
349
  subscriptions: SubscriptionsTable;
309
350
  subscription_outbox: SubscriptionOutboxTable;
310
351
  subscription_deliveries: SubscriptionDeliveriesTable;
352
+ decoded_events: DecodedEventsTable;
353
+ l2_decoder_checkpoints: L2DecoderCheckpointsTable;
354
+ chain_reorgs: ChainReorgsTable;
311
355
  }
312
356
  type TenantStatus = "provisioning" | "active" | "limit_warning" | "paused_limit" | "suspended" | "error" | "deleted";
313
357
  interface TenantsTable {
@@ -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>;
@@ -145,6 +146,8 @@ interface UsageDailyTable {
145
146
  date: string;
146
147
  api_requests: Generated<number>;
147
148
  deliveries: Generated<number>;
149
+ streams_events_returned: Generated<number>;
150
+ index_decoded_events_returned: Generated<number>;
148
151
  }
149
152
  interface UsageSnapshotsTable {
150
153
  id: Generated<string>;
@@ -273,6 +276,44 @@ interface ProcessedStripeEventsTable {
273
276
  event_type: string;
274
277
  processed_at: Generated<Date>;
275
278
  }
279
+ interface DecodedEventsTable {
280
+ cursor: string;
281
+ block_height: number;
282
+ tx_id: string;
283
+ tx_index: number;
284
+ event_index: number;
285
+ event_type: string;
286
+ microblock_hash: string | null;
287
+ canonical: Generated<boolean>;
288
+ contract_id: string | null;
289
+ sender: string | null;
290
+ recipient: string | null;
291
+ amount: string | null;
292
+ asset_identifier: string | null;
293
+ value: string | null;
294
+ memo: string | null;
295
+ source_cursor: string;
296
+ created_at: Generated<Date>;
297
+ }
298
+ interface L2DecoderCheckpointsTable {
299
+ decoder_name: string;
300
+ last_cursor: string | null;
301
+ updated_at: Generated<Date>;
302
+ }
303
+ interface ChainReorgsTable {
304
+ id: Generated<string>;
305
+ detected_at: Generated<Date>;
306
+ fork_point_height: number;
307
+ old_index_block_hash: string | null;
308
+ new_index_block_hash: string | null;
309
+ orphaned_from_height: number;
310
+ orphaned_from_event_index: number;
311
+ orphaned_to_height: number;
312
+ orphaned_to_event_index: number;
313
+ new_canonical_height: number;
314
+ new_canonical_event_index: number;
315
+ created_at: Generated<Date>;
316
+ }
276
317
  interface Database {
277
318
  blocks: BlocksTable;
278
319
  transactions: TransactionsTable;
@@ -308,6 +349,9 @@ interface Database {
308
349
  subscriptions: SubscriptionsTable;
309
350
  subscription_outbox: SubscriptionOutboxTable;
310
351
  subscription_deliveries: SubscriptionDeliveriesTable;
352
+ decoded_events: DecodedEventsTable;
353
+ l2_decoder_checkpoints: L2DecoderCheckpointsTable;
354
+ chain_reorgs: ChainReorgsTable;
311
355
  }
312
356
  type TenantStatus = "provisioning" | "active" | "limit_warning" | "paused_limit" | "suspended" | "error" | "deleted";
313
357
  interface TenantsTable {
@@ -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>;
@@ -145,6 +146,8 @@ interface UsageDailyTable {
145
146
  date: string;
146
147
  api_requests: Generated<number>;
147
148
  deliveries: Generated<number>;
149
+ streams_events_returned: Generated<number>;
150
+ index_decoded_events_returned: Generated<number>;
148
151
  }
149
152
  interface UsageSnapshotsTable {
150
153
  id: Generated<string>;
@@ -273,6 +276,44 @@ interface ProcessedStripeEventsTable {
273
276
  event_type: string;
274
277
  processed_at: Generated<Date>;
275
278
  }
279
+ interface DecodedEventsTable {
280
+ cursor: string;
281
+ block_height: number;
282
+ tx_id: string;
283
+ tx_index: number;
284
+ event_index: number;
285
+ event_type: string;
286
+ microblock_hash: string | null;
287
+ canonical: Generated<boolean>;
288
+ contract_id: string | null;
289
+ sender: string | null;
290
+ recipient: string | null;
291
+ amount: string | null;
292
+ asset_identifier: string | null;
293
+ value: string | null;
294
+ memo: string | null;
295
+ source_cursor: string;
296
+ created_at: Generated<Date>;
297
+ }
298
+ interface L2DecoderCheckpointsTable {
299
+ decoder_name: string;
300
+ last_cursor: string | null;
301
+ updated_at: Generated<Date>;
302
+ }
303
+ interface ChainReorgsTable {
304
+ id: Generated<string>;
305
+ detected_at: Generated<Date>;
306
+ fork_point_height: number;
307
+ old_index_block_hash: string | null;
308
+ new_index_block_hash: string | null;
309
+ orphaned_from_height: number;
310
+ orphaned_from_event_index: number;
311
+ orphaned_to_height: number;
312
+ orphaned_to_event_index: number;
313
+ new_canonical_height: number;
314
+ new_canonical_event_index: number;
315
+ created_at: Generated<Date>;
316
+ }
276
317
  interface Database {
277
318
  blocks: BlocksTable;
278
319
  transactions: TransactionsTable;
@@ -308,6 +349,9 @@ interface Database {
308
349
  subscriptions: SubscriptionsTable;
309
350
  subscription_outbox: SubscriptionOutboxTable;
310
351
  subscription_deliveries: SubscriptionDeliveriesTable;
352
+ decoded_events: DecodedEventsTable;
353
+ l2_decoder_checkpoints: L2DecoderCheckpointsTable;
354
+ chain_reorgs: ChainReorgsTable;
311
355
  }
312
356
  type TenantStatus = "provisioning" | "active" | "limit_warning" | "paused_limit" | "suspended" | "error" | "deleted";
313
357
  interface TenantsTable {
@@ -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>;
@@ -145,6 +146,8 @@ interface UsageDailyTable {
145
146
  date: string;
146
147
  api_requests: Generated<number>;
147
148
  deliveries: Generated<number>;
149
+ streams_events_returned: Generated<number>;
150
+ index_decoded_events_returned: Generated<number>;
148
151
  }
149
152
  interface UsageSnapshotsTable {
150
153
  id: Generated<string>;
@@ -273,6 +276,44 @@ interface ProcessedStripeEventsTable {
273
276
  event_type: string;
274
277
  processed_at: Generated<Date>;
275
278
  }
279
+ interface DecodedEventsTable {
280
+ cursor: string;
281
+ block_height: number;
282
+ tx_id: string;
283
+ tx_index: number;
284
+ event_index: number;
285
+ event_type: string;
286
+ microblock_hash: string | null;
287
+ canonical: Generated<boolean>;
288
+ contract_id: string | null;
289
+ sender: string | null;
290
+ recipient: string | null;
291
+ amount: string | null;
292
+ asset_identifier: string | null;
293
+ value: string | null;
294
+ memo: string | null;
295
+ source_cursor: string;
296
+ created_at: Generated<Date>;
297
+ }
298
+ interface L2DecoderCheckpointsTable {
299
+ decoder_name: string;
300
+ last_cursor: string | null;
301
+ updated_at: Generated<Date>;
302
+ }
303
+ interface ChainReorgsTable {
304
+ id: Generated<string>;
305
+ detected_at: Generated<Date>;
306
+ fork_point_height: number;
307
+ old_index_block_hash: string | null;
308
+ new_index_block_hash: string | null;
309
+ orphaned_from_height: number;
310
+ orphaned_from_event_index: number;
311
+ orphaned_to_height: number;
312
+ orphaned_to_event_index: number;
313
+ new_canonical_height: number;
314
+ new_canonical_event_index: number;
315
+ created_at: Generated<Date>;
316
+ }
276
317
  interface Database {
277
318
  blocks: BlocksTable;
278
319
  transactions: TransactionsTable;
@@ -308,6 +349,9 @@ interface Database {
308
349
  subscriptions: SubscriptionsTable;
309
350
  subscription_outbox: SubscriptionOutboxTable;
310
351
  subscription_deliveries: SubscriptionDeliveriesTable;
352
+ decoded_events: DecodedEventsTable;
353
+ l2_decoder_checkpoints: L2DecoderCheckpointsTable;
354
+ chain_reorgs: ChainReorgsTable;
311
355
  }
312
356
  type TenantStatus = "provisioning" | "active" | "limit_warning" | "paused_limit" | "suspended" | "error" | "deleted";
313
357
  interface TenantsTable {
@@ -448,6 +492,8 @@ interface SubscriptionDeliveriesTable {
448
492
  }
449
493
  /** Increment API request counter for today. Fire-and-forget safe. */
450
494
  declare function incrementApiRequests(db: Kysely<Database>, accountId: string): Promise<void>;
495
+ declare function incrementStreamsEventsReturned(db: Kysely<Database>, accountId: string, quantity: number): Promise<void>;
496
+ declare function incrementIndexDecodedEventsReturned(db: Kysely<Database>, accountId: string, quantity: number): Promise<void>;
451
497
  interface UsageSummary {
452
498
  apiRequestsToday: number;
453
499
  deliveriesThisMonth: number;
@@ -460,4 +506,4 @@ declare function getUsage(db: Kysely<Database>, accountId: string): Promise<Usag
460
506
  * for each tenant's subgraph schemas.
461
507
  */
462
508
  declare function measureStorage(db: Kysely<Database>): Promise<void>;
463
- export { measureStorage, incrementApiRequests, getUsage, UsageSummary };
509
+ export { measureStorage, incrementStreamsEventsReturned, incrementIndexDecodedEventsReturned, incrementApiRequests, getUsage, UsageSummary };
@@ -25,6 +25,23 @@ async function incrementApiRequests(db, accountId) {
25
25
  DO UPDATE SET api_requests = usage_daily.api_requests + 1
26
26
  `.execute(db);
27
27
  }
28
+ async function incrementAccountDailyCounter(db, accountId, column, quantity) {
29
+ if (quantity <= 0)
30
+ return;
31
+ const today = new Date().toISOString().slice(0, 10);
32
+ await sql`
33
+ INSERT INTO usage_daily (account_id, tenant_id, date, api_requests, deliveries, ${sql.raw(column)})
34
+ VALUES (${accountId}, NULL, ${today}, 0, 0, ${quantity})
35
+ ON CONFLICT (account_id, date) WHERE tenant_id IS NULL
36
+ DO UPDATE SET ${sql.raw(column)} = usage_daily.${sql.raw(column)} + ${quantity}
37
+ `.execute(db);
38
+ }
39
+ async function incrementStreamsEventsReturned(db, accountId, quantity) {
40
+ await incrementAccountDailyCounter(db, accountId, "streams_events_returned", quantity);
41
+ }
42
+ async function incrementIndexDecodedEventsReturned(db, accountId, quantity) {
43
+ await incrementAccountDailyCounter(db, accountId, "index_decoded_events_returned", quantity);
44
+ }
28
45
  async function getUsage(db, accountId) {
29
46
  const today = new Date().toISOString().slice(0, 10);
30
47
  const monthStart = `${today.slice(0, 7)}-01`;
@@ -66,9 +83,11 @@ async function measureStorage(db) {
66
83
  }
67
84
  export {
68
85
  measureStorage,
86
+ incrementStreamsEventsReturned,
87
+ incrementIndexDecodedEventsReturned,
69
88
  incrementApiRequests,
70
89
  getUsage
71
90
  };
72
91
 
73
- //# debugId=D8C08A844119816364756E2164756E21
92
+ //# debugId=0A5108029A948ED964756E2164756E21
74
93
  //# sourceMappingURL=usage.js.map
@@ -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\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": "0A5108029A948ED964756E2164756E21",
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>;
@@ -144,6 +145,8 @@ interface UsageDailyTable {
144
145
  date: string;
145
146
  api_requests: Generated<number>;
146
147
  deliveries: Generated<number>;
148
+ streams_events_returned: Generated<number>;
149
+ index_decoded_events_returned: Generated<number>;
147
150
  }
148
151
  interface UsageSnapshotsTable {
149
152
  id: Generated<string>;
@@ -272,6 +275,44 @@ interface ProcessedStripeEventsTable {
272
275
  event_type: string;
273
276
  processed_at: Generated<Date>;
274
277
  }
278
+ interface DecodedEventsTable {
279
+ cursor: string;
280
+ block_height: number;
281
+ tx_id: string;
282
+ tx_index: number;
283
+ event_index: number;
284
+ event_type: string;
285
+ microblock_hash: string | null;
286
+ canonical: Generated<boolean>;
287
+ contract_id: string | null;
288
+ sender: string | null;
289
+ recipient: string | null;
290
+ amount: string | null;
291
+ asset_identifier: string | null;
292
+ value: string | null;
293
+ memo: string | null;
294
+ source_cursor: string;
295
+ created_at: Generated<Date>;
296
+ }
297
+ interface L2DecoderCheckpointsTable {
298
+ decoder_name: string;
299
+ last_cursor: string | null;
300
+ updated_at: Generated<Date>;
301
+ }
302
+ interface ChainReorgsTable {
303
+ id: Generated<string>;
304
+ detected_at: Generated<Date>;
305
+ fork_point_height: number;
306
+ old_index_block_hash: string | null;
307
+ new_index_block_hash: string | null;
308
+ orphaned_from_height: number;
309
+ orphaned_from_event_index: number;
310
+ orphaned_to_height: number;
311
+ orphaned_to_event_index: number;
312
+ new_canonical_height: number;
313
+ new_canonical_event_index: number;
314
+ created_at: Generated<Date>;
315
+ }
275
316
  interface Database {
276
317
  blocks: BlocksTable;
277
318
  transactions: TransactionsTable;
@@ -307,6 +348,9 @@ interface Database {
307
348
  subscriptions: SubscriptionsTable;
308
349
  subscription_outbox: SubscriptionOutboxTable;
309
350
  subscription_deliveries: SubscriptionDeliveriesTable;
351
+ decoded_events: DecodedEventsTable;
352
+ l2_decoder_checkpoints: L2DecoderCheckpointsTable;
353
+ chain_reorgs: ChainReorgsTable;
310
354
  }
311
355
  type TenantStatus = "provisioning" | "active" | "limit_warning" | "paused_limit" | "suspended" | "error" | "deleted";
312
356
  interface TenantsTable {
@@ -518,4 +562,4 @@ interface SubscriptionDeliveriesTable {
518
562
  }
519
563
  type SubscriptionDelivery = Selectable<SubscriptionDeliveriesTable>;
520
564
  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 };
565
+ 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 };