@secondlayer/shared 6.8.1 → 6.10.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.
Files changed (36) hide show
  1. package/dist/src/db/index.d.ts +47 -1
  2. package/dist/src/db/index.js +42 -3
  3. package/dist/src/db/index.js.map +3 -3
  4. package/dist/src/db/queries/chain-reorgs.d.ts +36 -0
  5. package/dist/src/db/queries/chain-reorgs.js +41 -3
  6. package/dist/src/db/queries/chain-reorgs.js.map +3 -3
  7. package/dist/src/db/queries/contracts.d.ts +783 -0
  8. package/dist/src/db/queries/contracts.js +90 -0
  9. package/dist/src/db/queries/contracts.js.map +11 -0
  10. package/dist/src/db/queries/integrity.d.ts +36 -0
  11. package/dist/src/db/queries/subgraph-gaps.d.ts +36 -0
  12. package/dist/src/db/queries/subgraph-operations.d.ts +36 -0
  13. package/dist/src/db/queries/subgraphs.d.ts +58 -1
  14. package/dist/src/db/queries/subgraphs.js +390 -6
  15. package/dist/src/db/queries/subgraphs.js.map +9 -4
  16. package/dist/src/db/queries/subscriptions.d.ts +36 -0
  17. package/dist/src/db/schema.d.ts +40 -1
  18. package/dist/src/index.d.ts +55 -1
  19. package/dist/src/index.js +45 -4
  20. package/dist/src/index.js.map +4 -4
  21. package/dist/src/node/client.d.ts +2 -0
  22. package/dist/src/node/client.js +11 -1
  23. package/dist/src/node/client.js.map +3 -3
  24. package/dist/src/node/local-client.d.ts +36 -0
  25. package/dist/src/schemas/index.d.ts +8 -0
  26. package/dist/src/schemas/index.js +4 -2
  27. package/dist/src/schemas/index.js.map +3 -3
  28. package/dist/src/schemas/subgraphs.d.ts +8 -0
  29. package/dist/src/schemas/subgraphs.js +4 -2
  30. package/dist/src/schemas/subgraphs.js.map +3 -3
  31. package/migrations/0066_public_l2_decoded_events.ts +4 -2
  32. package/migrations/0067_product_usage_counters.ts +4 -2
  33. package/migrations/0081_subgraphs_database_url_enc.ts +16 -0
  34. package/migrations/0082_contracts_registry.ts +44 -0
  35. package/migrations/0083_burnchain_rewards.ts +63 -0
  36. package/package.json +6 -2
@@ -0,0 +1,90 @@
1
+ import { createRequire } from "node:module";
2
+ var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, {
10
+ get: all[name],
11
+ enumerable: true,
12
+ configurable: true,
13
+ set: __exportSetter.bind(all, name)
14
+ });
15
+ };
16
+
17
+ // src/db/jsonb.ts
18
+ import { sql } from "kysely";
19
+ function jsonb(value) {
20
+ const escaped = JSON.stringify(value, (_k, v) => typeof v === "bigint" ? v.toString() : v).replace(/'/g, "''");
21
+ return sql`${sql.raw(`'${escaped}'::jsonb`)}`;
22
+ }
23
+ function parseJsonb(value) {
24
+ if (typeof value === "string") {
25
+ try {
26
+ return JSON.parse(value);
27
+ } catch {
28
+ return value;
29
+ }
30
+ }
31
+ return value ?? {};
32
+ }
33
+
34
+ // src/db/queries/contracts.ts
35
+ import { sql as sql2 } from "kysely";
36
+ async function recordContractDeploy(db, row) {
37
+ await db.insertInto("contracts").values({
38
+ contract_id: row.contractId,
39
+ deployer: row.deployer,
40
+ block_height: row.blockHeight
41
+ }).onConflict((oc) => oc.column("contract_id").doNothing()).execute();
42
+ }
43
+ async function setContractAbi(db, contractId, data) {
44
+ await db.updateTable("contracts").set({
45
+ abi: data.abi == null ? null : jsonb(data.abi),
46
+ abi_status: data.status,
47
+ abi_fetched_at: new Date,
48
+ ...data.declaredTraits ? { declared_traits: data.declaredTraits } : {},
49
+ ...data.inferredStandards ? { inferred_standards: data.inferredStandards } : {}
50
+ }).where("contract_id", "=", contractId).execute();
51
+ }
52
+ async function getContract(db, contractId) {
53
+ return await db.selectFrom("contracts").selectAll().where("contract_id", "=", contractId).executeTakeFirst() ?? null;
54
+ }
55
+ async function listContractsPendingAbi(db, limit = 100) {
56
+ return db.selectFrom("contracts").selectAll().where("abi_status", "=", "pending").where("canonical", "=", true).orderBy("block_height", "asc").limit(limit).execute();
57
+ }
58
+ async function listContractsByTrait(db, trait, opts = {}) {
59
+ const conformance = opts.conformance ?? "any";
60
+ let q = db.selectFrom("contracts").selectAll().where("canonical", "=", true);
61
+ if (conformance === "declared") {
62
+ q = q.where(sql2`${sql2.ref("declared_traits")} @> ARRAY[${trait}]`);
63
+ } else if (conformance === "inferred") {
64
+ q = q.where(sql2`${sql2.ref("inferred_standards")} @> ARRAY[${trait}]`);
65
+ } else {
66
+ q = q.where(sql2`(${sql2.ref("declared_traits")} @> ARRAY[${trait}] OR ${sql2.ref("inferred_standards")} @> ARRAY[${trait}])`);
67
+ }
68
+ if (opts.afterId)
69
+ q = q.where("contract_id", ">", opts.afterId);
70
+ return q.orderBy("contract_id", "asc").limit(opts.limit ?? 100).execute();
71
+ }
72
+ async function resolveTraitContractIds(db, trait, asOfBlock) {
73
+ const rows = await db.selectFrom("contracts").select("contract_id").where("canonical", "=", true).where("block_height", "<=", asOfBlock).where(sql2`(${sql2.ref("declared_traits")} @> ARRAY[${trait}] OR ${sql2.ref("inferred_standards")} @> ARRAY[${trait}])`).execute();
74
+ return rows.map((r) => r.contract_id);
75
+ }
76
+ async function markContractsNonCanonical(db, fromBlockHeight) {
77
+ await db.updateTable("contracts").set({ canonical: false }).where("block_height", ">=", fromBlockHeight).execute();
78
+ }
79
+ export {
80
+ setContractAbi,
81
+ resolveTraitContractIds,
82
+ recordContractDeploy,
83
+ markContractsNonCanonical,
84
+ listContractsPendingAbi,
85
+ listContractsByTrait,
86
+ getContract
87
+ };
88
+
89
+ //# debugId=FF480204BC0AAD0A64756E2164756E21
90
+ //# sourceMappingURL=contracts.js.map
@@ -0,0 +1,11 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/db/jsonb.ts", "../src/db/queries/contracts.ts"],
4
+ "sourcesContent": [
5
+ "import { type RawBuilder, sql } from \"kysely\";\n\n/**\n * Safely encode a JS value as a JSONB literal for Kysely inserts/updates.\n * Kysely + postgres.js double-encodes JSON when using parameterized queries\n * with ::jsonb casts. This uses sql.raw to inline a properly escaped literal.\n *\n * Generic parameter lets callers set the RawBuilder's output type so they\n * don't need to cast at the insert site. Default is `unknown` — widen at\n * the call site when the column type is narrower, e.g. `jsonb<MyShape>(...)`.\n */\nexport function jsonb<T = unknown>(value: T): RawBuilder<T> {\n\tconst escaped = JSON.stringify(value, (_k, v) =>\n\t\ttypeof v === \"bigint\" ? v.toString() : v,\n\t).replace(/'/g, \"''\");\n\treturn sql`${sql.raw(`'${escaped}'::jsonb`)}`;\n}\n\n/**\n * Safely parse a JSONB value from the database.\n * Handles double-encoded strings where postgres.js returns a JSON string\n * instead of a parsed object.\n */\nexport function parseJsonb<T = unknown>(value: unknown): T {\n\tif (typeof value === \"string\") {\n\t\ttry {\n\t\t\treturn JSON.parse(value) as T;\n\t\t} catch {\n\t\t\treturn value as T;\n\t\t}\n\t}\n\treturn (value ?? {}) as T;\n}\n",
6
+ "import { type Kysely, sql } from \"kysely\";\nimport { jsonb } from \"../jsonb.ts\";\nimport type { Contract, Database } from \"../types.ts\";\n\n/**\n * Contract registry queries — backing for trait-based discovery. Populated from\n * contract deploys; ABI fetched async; standards inferred by static analysis.\n */\n\nexport type AbiStatus = \"pending\" | \"fetched\" | \"failed\" | \"unparseable\";\n\n/** Record a contract deploy (idempotent). ABI is fetched separately + async. */\nexport async function recordContractDeploy(\n\tdb: Kysely<Database>,\n\trow: { contractId: string; deployer: string; blockHeight: number },\n): Promise<void> {\n\tawait db\n\t\t.insertInto(\"contracts\")\n\t\t.values({\n\t\t\tcontract_id: row.contractId,\n\t\t\tdeployer: row.deployer,\n\t\t\tblock_height: row.blockHeight,\n\t\t})\n\t\t.onConflict((oc) => oc.column(\"contract_id\").doNothing())\n\t\t.execute();\n}\n\n/** Store a fetched ABI + the traits/standards derived from it. */\nexport async function setContractAbi(\n\tdb: Kysely<Database>,\n\tcontractId: string,\n\tdata: {\n\t\tabi: unknown | null;\n\t\tstatus: AbiStatus;\n\t\tdeclaredTraits?: string[];\n\t\tinferredStandards?: string[];\n\t},\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"contracts\")\n\t\t.set({\n\t\t\tabi: data.abi == null ? null : jsonb(data.abi),\n\t\t\tabi_status: data.status,\n\t\t\tabi_fetched_at: new Date(),\n\t\t\t...(data.declaredTraits ? { declared_traits: data.declaredTraits } : {}),\n\t\t\t...(data.inferredStandards\n\t\t\t\t? { inferred_standards: data.inferredStandards }\n\t\t\t\t: {}),\n\t\t})\n\t\t.where(\"contract_id\", \"=\", contractId)\n\t\t.execute();\n}\n\nexport async function getContract(\n\tdb: Kysely<Database>,\n\tcontractId: string,\n): Promise<Contract | null> {\n\treturn (\n\t\t(await db\n\t\t\t.selectFrom(\"contracts\")\n\t\t\t.selectAll()\n\t\t\t.where(\"contract_id\", \"=\", contractId)\n\t\t\t.executeTakeFirst()) ?? null\n\t);\n}\n\n/** Contracts still awaiting an ABI fetch (drives the fetch/backfill worker). */\nexport async function listContractsPendingAbi(\n\tdb: Kysely<Database>,\n\tlimit = 100,\n): Promise<Contract[]> {\n\treturn db\n\t\t.selectFrom(\"contracts\")\n\t\t.selectAll()\n\t\t.where(\"abi_status\", \"=\", \"pending\")\n\t\t.where(\"canonical\", \"=\", true)\n\t\t.orderBy(\"block_height\", \"asc\")\n\t\t.limit(limit)\n\t\t.execute();\n}\n\nexport type Conformance = \"declared\" | \"inferred\" | \"any\";\n\n/** Discovery: contracts matching a trait/standard, by conformance source. */\nexport async function listContractsByTrait(\n\tdb: Kysely<Database>,\n\ttrait: string,\n\topts: { conformance?: Conformance; limit?: number; afterId?: string } = {},\n): Promise<Contract[]> {\n\tconst conformance = opts.conformance ?? \"any\";\n\tlet q = db.selectFrom(\"contracts\").selectAll().where(\"canonical\", \"=\", true);\n\n\tif (conformance === \"declared\") {\n\t\tq = q.where(sql<boolean>`${sql.ref(\"declared_traits\")} @> ARRAY[${trait}]`);\n\t} else if (conformance === \"inferred\") {\n\t\tq = q.where(\n\t\t\tsql<boolean>`${sql.ref(\"inferred_standards\")} @> ARRAY[${trait}]`,\n\t\t);\n\t} else {\n\t\tq = q.where(\n\t\t\tsql<boolean>`(${sql.ref(\"declared_traits\")} @> ARRAY[${trait}] OR ${sql.ref(\"inferred_standards\")} @> ARRAY[${trait}])`,\n\t\t);\n\t}\n\n\tif (opts.afterId) q = q.where(\"contract_id\", \">\", opts.afterId);\n\treturn q\n\t\t.orderBy(\"contract_id\", \"asc\")\n\t\t.limit(opts.limit ?? 100)\n\t\t.execute();\n}\n\n/**\n * As-of-block trait resolution (B4): contract IDs conforming to `trait` whose\n * deploy block ≤ `asOfBlock`. Lets a trait-scoped subgraph reindex a token's\n * full history even if classification lagged its deploy.\n */\nexport async function resolveTraitContractIds(\n\tdb: Kysely<Database>,\n\ttrait: string,\n\tasOfBlock: number,\n): Promise<string[]> {\n\tconst rows = await db\n\t\t.selectFrom(\"contracts\")\n\t\t.select(\"contract_id\")\n\t\t.where(\"canonical\", \"=\", true)\n\t\t.where(\"block_height\", \"<=\", asOfBlock)\n\t\t.where(\n\t\t\tsql<boolean>`(${sql.ref(\"declared_traits\")} @> ARRAY[${trait}] OR ${sql.ref(\"inferred_standards\")} @> ARRAY[${trait}])`,\n\t\t)\n\t\t.execute();\n\treturn rows.map((r) => r.contract_id);\n}\n\n/** Reorg: flip contracts deployed at/above a reorged height to non-canonical. */\nexport async function markContractsNonCanonical(\n\tdb: Kysely<Database>,\n\tfromBlockHeight: number,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"contracts\")\n\t\t.set({ canonical: false })\n\t\t.where(\"block_height\", \">=\", fromBlockHeight)\n\t\t.execute();\n}\n"
7
+ ],
8
+ "mappings": "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",
9
+ "debugId": "FF480204BC0AAD0A64756E2164756E21",
10
+ "names": []
11
+ }
@@ -61,9 +61,22 @@ interface SubgraphsTable {
61
61
  handler_code: string | null;
62
62
  source_code: string | null;
63
63
  project_id: string | null;
64
+ database_url_enc: ColumnType<Buffer | null, Buffer | null | undefined, Buffer | null>;
64
65
  created_at: Generated<Date>;
65
66
  updated_at: Generated<Date>;
66
67
  }
68
+ interface ContractsTable {
69
+ contract_id: string;
70
+ deployer: string;
71
+ block_height: number;
72
+ canonical: Generated<boolean>;
73
+ abi: unknown | null;
74
+ declared_traits: Generated<string[]>;
75
+ inferred_standards: Generated<string[]>;
76
+ abi_status: Generated<string>;
77
+ abi_fetched_at: Date | null;
78
+ created_at: Generated<Date>;
79
+ }
67
80
  interface SubgraphGapsTable {
68
81
  id: Generated<string>;
69
82
  subgraph_id: string;
@@ -367,6 +380,26 @@ interface Pox4SignersDailyTable {
367
380
  aggregation_calls: Generated<number>;
368
381
  updated_at: Generated<Date>;
369
382
  }
383
+ interface BurnBlockRewardsTable {
384
+ cursor: string;
385
+ burn_block_height: number;
386
+ burn_block_hash: string;
387
+ reward_index: number;
388
+ recipient_btc: string;
389
+ amount_sats: string;
390
+ burn_amount: Generated<string>;
391
+ canonical: Generated<boolean>;
392
+ created_at: Generated<Date>;
393
+ }
394
+ interface BurnBlockRewardSlotsTable {
395
+ cursor: string;
396
+ burn_block_height: number;
397
+ burn_block_hash: string;
398
+ slot_index: number;
399
+ holder_btc: string;
400
+ canonical: Generated<boolean>;
401
+ created_at: Generated<Date>;
402
+ }
370
403
  type SbtcEventTopic = "completed-deposit" | "withdrawal-create" | "withdrawal-accept" | "withdrawal-reject" | "key-rotation" | "update-protocol-contract";
371
404
  interface SbtcEventsTable {
372
405
  cursor: string;
@@ -519,6 +552,7 @@ interface Database {
519
552
  transactions: TransactionsTable;
520
553
  events: EventsTable;
521
554
  index_progress: IndexProgressTable;
555
+ contracts: ContractsTable;
522
556
  subgraphs: SubgraphsTable;
523
557
  api_keys: ApiKeysTable;
524
558
  accounts: AccountsTable;
@@ -554,6 +588,8 @@ interface Database {
554
588
  pox4_calls: Pox4CallsTable;
555
589
  pox4_cycles_daily: Pox4CyclesDailyTable;
556
590
  pox4_signers_daily: Pox4SignersDailyTable;
591
+ burn_block_rewards: BurnBlockRewardsTable;
592
+ burn_block_reward_slots: BurnBlockRewardSlotsTable;
557
593
  sbtc_events: SbtcEventsTable;
558
594
  sbtc_token_events: SbtcTokenEventsTable;
559
595
  sbtc_supply_snapshots: SbtcSupplySnapshotsTable;
@@ -61,9 +61,22 @@ interface SubgraphsTable {
61
61
  handler_code: string | null;
62
62
  source_code: string | null;
63
63
  project_id: string | null;
64
+ database_url_enc: ColumnType<Buffer | null, Buffer | null | undefined, Buffer | null>;
64
65
  created_at: Generated<Date>;
65
66
  updated_at: Generated<Date>;
66
67
  }
68
+ interface ContractsTable {
69
+ contract_id: string;
70
+ deployer: string;
71
+ block_height: number;
72
+ canonical: Generated<boolean>;
73
+ abi: unknown | null;
74
+ declared_traits: Generated<string[]>;
75
+ inferred_standards: Generated<string[]>;
76
+ abi_status: Generated<string>;
77
+ abi_fetched_at: Date | null;
78
+ created_at: Generated<Date>;
79
+ }
67
80
  interface SubgraphGapsTable {
68
81
  id: Generated<string>;
69
82
  subgraph_id: string;
@@ -367,6 +380,26 @@ interface Pox4SignersDailyTable {
367
380
  aggregation_calls: Generated<number>;
368
381
  updated_at: Generated<Date>;
369
382
  }
383
+ interface BurnBlockRewardsTable {
384
+ cursor: string;
385
+ burn_block_height: number;
386
+ burn_block_hash: string;
387
+ reward_index: number;
388
+ recipient_btc: string;
389
+ amount_sats: string;
390
+ burn_amount: Generated<string>;
391
+ canonical: Generated<boolean>;
392
+ created_at: Generated<Date>;
393
+ }
394
+ interface BurnBlockRewardSlotsTable {
395
+ cursor: string;
396
+ burn_block_height: number;
397
+ burn_block_hash: string;
398
+ slot_index: number;
399
+ holder_btc: string;
400
+ canonical: Generated<boolean>;
401
+ created_at: Generated<Date>;
402
+ }
370
403
  type SbtcEventTopic = "completed-deposit" | "withdrawal-create" | "withdrawal-accept" | "withdrawal-reject" | "key-rotation" | "update-protocol-contract";
371
404
  interface SbtcEventsTable {
372
405
  cursor: string;
@@ -519,6 +552,7 @@ interface Database {
519
552
  transactions: TransactionsTable;
520
553
  events: EventsTable;
521
554
  index_progress: IndexProgressTable;
555
+ contracts: ContractsTable;
522
556
  subgraphs: SubgraphsTable;
523
557
  api_keys: ApiKeysTable;
524
558
  accounts: AccountsTable;
@@ -554,6 +588,8 @@ interface Database {
554
588
  pox4_calls: Pox4CallsTable;
555
589
  pox4_cycles_daily: Pox4CyclesDailyTable;
556
590
  pox4_signers_daily: Pox4SignersDailyTable;
591
+ burn_block_rewards: BurnBlockRewardsTable;
592
+ burn_block_reward_slots: BurnBlockRewardSlotsTable;
557
593
  sbtc_events: SbtcEventsTable;
558
594
  sbtc_token_events: SbtcTokenEventsTable;
559
595
  sbtc_supply_snapshots: SbtcSupplySnapshotsTable;
@@ -61,9 +61,22 @@ interface SubgraphsTable {
61
61
  handler_code: string | null;
62
62
  source_code: string | null;
63
63
  project_id: string | null;
64
+ database_url_enc: ColumnType<Buffer | null, Buffer | null | undefined, Buffer | null>;
64
65
  created_at: Generated<Date>;
65
66
  updated_at: Generated<Date>;
66
67
  }
68
+ interface ContractsTable {
69
+ contract_id: string;
70
+ deployer: string;
71
+ block_height: number;
72
+ canonical: Generated<boolean>;
73
+ abi: unknown | null;
74
+ declared_traits: Generated<string[]>;
75
+ inferred_standards: Generated<string[]>;
76
+ abi_status: Generated<string>;
77
+ abi_fetched_at: Date | null;
78
+ created_at: Generated<Date>;
79
+ }
67
80
  interface SubgraphGapsTable {
68
81
  id: Generated<string>;
69
82
  subgraph_id: string;
@@ -367,6 +380,26 @@ interface Pox4SignersDailyTable {
367
380
  aggregation_calls: Generated<number>;
368
381
  updated_at: Generated<Date>;
369
382
  }
383
+ interface BurnBlockRewardsTable {
384
+ cursor: string;
385
+ burn_block_height: number;
386
+ burn_block_hash: string;
387
+ reward_index: number;
388
+ recipient_btc: string;
389
+ amount_sats: string;
390
+ burn_amount: Generated<string>;
391
+ canonical: Generated<boolean>;
392
+ created_at: Generated<Date>;
393
+ }
394
+ interface BurnBlockRewardSlotsTable {
395
+ cursor: string;
396
+ burn_block_height: number;
397
+ burn_block_hash: string;
398
+ slot_index: number;
399
+ holder_btc: string;
400
+ canonical: Generated<boolean>;
401
+ created_at: Generated<Date>;
402
+ }
370
403
  type SbtcEventTopic = "completed-deposit" | "withdrawal-create" | "withdrawal-accept" | "withdrawal-reject" | "key-rotation" | "update-protocol-contract";
371
404
  interface SbtcEventsTable {
372
405
  cursor: string;
@@ -519,6 +552,7 @@ interface Database {
519
552
  transactions: TransactionsTable;
520
553
  events: EventsTable;
521
554
  index_progress: IndexProgressTable;
555
+ contracts: ContractsTable;
522
556
  subgraphs: SubgraphsTable;
523
557
  api_keys: ApiKeysTable;
524
558
  accounts: AccountsTable;
@@ -554,6 +588,8 @@ interface Database {
554
588
  pox4_calls: Pox4CallsTable;
555
589
  pox4_cycles_daily: Pox4CyclesDailyTable;
556
590
  pox4_signers_daily: Pox4SignersDailyTable;
591
+ burn_block_rewards: BurnBlockRewardsTable;
592
+ burn_block_reward_slots: BurnBlockRewardSlotsTable;
557
593
  sbtc_events: SbtcEventsTable;
558
594
  sbtc_token_events: SbtcTokenEventsTable;
559
595
  sbtc_supply_snapshots: SbtcSupplySnapshotsTable;
@@ -1,4 +1,5 @@
1
1
  import { Kysely } from "kysely";
2
+ import postgres from "postgres";
2
3
  import { ColumnType, Generated, Selectable } from "kysely";
3
4
  interface BlocksTable {
4
5
  height: number;
@@ -61,9 +62,22 @@ interface SubgraphsTable {
61
62
  handler_code: string | null;
62
63
  source_code: string | null;
63
64
  project_id: string | null;
65
+ database_url_enc: ColumnType<Buffer | null, Buffer | null | undefined, Buffer | null>;
64
66
  created_at: Generated<Date>;
65
67
  updated_at: Generated<Date>;
66
68
  }
69
+ interface ContractsTable {
70
+ contract_id: string;
71
+ deployer: string;
72
+ block_height: number;
73
+ canonical: Generated<boolean>;
74
+ abi: unknown | null;
75
+ declared_traits: Generated<string[]>;
76
+ inferred_standards: Generated<string[]>;
77
+ abi_status: Generated<string>;
78
+ abi_fetched_at: Date | null;
79
+ created_at: Generated<Date>;
80
+ }
67
81
  interface SubgraphGapsTable {
68
82
  id: Generated<string>;
69
83
  subgraph_id: string;
@@ -367,6 +381,26 @@ interface Pox4SignersDailyTable {
367
381
  aggregation_calls: Generated<number>;
368
382
  updated_at: Generated<Date>;
369
383
  }
384
+ interface BurnBlockRewardsTable {
385
+ cursor: string;
386
+ burn_block_height: number;
387
+ burn_block_hash: string;
388
+ reward_index: number;
389
+ recipient_btc: string;
390
+ amount_sats: string;
391
+ burn_amount: Generated<string>;
392
+ canonical: Generated<boolean>;
393
+ created_at: Generated<Date>;
394
+ }
395
+ interface BurnBlockRewardSlotsTable {
396
+ cursor: string;
397
+ burn_block_height: number;
398
+ burn_block_hash: string;
399
+ slot_index: number;
400
+ holder_btc: string;
401
+ canonical: Generated<boolean>;
402
+ created_at: Generated<Date>;
403
+ }
370
404
  type SbtcEventTopic = "completed-deposit" | "withdrawal-create" | "withdrawal-accept" | "withdrawal-reject" | "key-rotation" | "update-protocol-contract";
371
405
  interface SbtcEventsTable {
372
406
  cursor: string;
@@ -519,6 +553,7 @@ interface Database {
519
553
  transactions: TransactionsTable;
520
554
  events: EventsTable;
521
555
  index_progress: IndexProgressTable;
556
+ contracts: ContractsTable;
522
557
  subgraphs: SubgraphsTable;
523
558
  api_keys: ApiKeysTable;
524
559
  accounts: AccountsTable;
@@ -554,6 +589,8 @@ interface Database {
554
589
  pox4_calls: Pox4CallsTable;
555
590
  pox4_cycles_daily: Pox4CyclesDailyTable;
556
591
  pox4_signers_daily: Pox4SignersDailyTable;
592
+ burn_block_rewards: BurnBlockRewardsTable;
593
+ burn_block_reward_slots: BurnBlockRewardSlotsTable;
557
594
  sbtc_events: SbtcEventsTable;
558
595
  sbtc_token_events: SbtcTokenEventsTable;
559
596
  sbtc_supply_snapshots: SbtcSupplySnapshotsTable;
@@ -709,6 +746,24 @@ interface SubscriptionDeliveriesTable {
709
746
  dispatched_at: Generated<Date>;
710
747
  }
711
748
  /**
749
+ * BYO data plane helpers. A subgraph's user-owned Postgres connection string is
750
+ * stored encrypted at rest in `database_url_enc` (AES-GCM envelope). Plaintext
751
+ * only exists transiently — at deploy (to encrypt) and at pool construction (to
752
+ * connect). Never serialize it into API responses.
753
+ */
754
+ declare function encryptDatabaseUrl(url: string): Buffer;
755
+ /** Decrypt a subgraph's BYO connection string, or null when managed. */
756
+ declare function subgraphDatabaseUrl(subgraph: Subgraph): string | null;
757
+ /** True when the subgraph writes/serves from a user-owned DB. */
758
+ declare function isByoSubgraph(subgraph: Subgraph): boolean;
759
+ /**
760
+ * Resolve the Kysely instance a subgraph's data plane lives on: the user's DB
761
+ * when BYO, else the managed target DB. Pools are cached by URL in db/index.ts.
762
+ */
763
+ declare function resolveSubgraphDb(subgraph: Subgraph): Kysely<Database>;
764
+ /** Raw postgres.js client for a subgraph's data plane (DDL / serving queries). */
765
+ declare function resolveSubgraphRawClient(subgraph: Subgraph): ReturnType<typeof postgres>;
766
+ /**
712
767
  * Convert a subgraph name to its PostgreSQL schema name (legacy form).
713
768
  * Pre shared-rip every tenant DB had its own schema namespace so disambiguation
714
769
  * was implicit. Kept for oss mode (single-tenant) and legacy-row fallback.
@@ -733,6 +788,8 @@ declare function registerSubgraph(db: Kysely<Database>, data: {
733
788
  startBlock?: number
734
789
  handlerCode?: string
735
790
  sourceCode?: string
791
+ /** BYO data plane: encrypted user-DB connection string, or null = managed. */
792
+ databaseUrlEnc?: Buffer | null
736
793
  }): Promise<Subgraph>;
737
794
  declare function getSubgraph(db: Kysely<Database>, name: string, accountId?: string): Promise<Subgraph | null>;
738
795
  declare function listSubgraphs(db: Kysely<Database>, accountId?: string): Promise<Subgraph[]>;
@@ -743,4 +800,4 @@ declare function updateSubgraphHandlerPath(db: Kysely<Database>, name: string, h
743
800
  sourceCode?: string
744
801
  }): Promise<void>;
745
802
  declare function deleteSubgraph(db: Kysely<Database>, name: string, accountId?: string): Promise<Subgraph | null>;
746
- export { updateSubgraphStatus, updateSubgraphHandlerPath, registerSubgraph, recordSubgraphProcessed, pgSchemaNameFor, pgSchemaName, listSubgraphs, getSubgraph, deleteSubgraph };
803
+ export { updateSubgraphStatus, updateSubgraphHandlerPath, subgraphDatabaseUrl, resolveSubgraphRawClient, resolveSubgraphDb, registerSubgraph, recordSubgraphProcessed, pgSchemaNameFor, pgSchemaName, listSubgraphs, isByoSubgraph, getSubgraph, encryptDatabaseUrl, deleteSubgraph };