@secondlayer/shared 6.8.1 → 6.9.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 (33) hide show
  1. package/dist/src/db/index.d.ts +25 -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 +14 -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 +761 -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 +14 -0
  11. package/dist/src/db/queries/subgraph-gaps.d.ts +14 -0
  12. package/dist/src/db/queries/subgraph-operations.d.ts +14 -0
  13. package/dist/src/db/queries/subgraphs.d.ts +36 -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 +14 -0
  17. package/dist/src/db/schema.d.ts +18 -1
  18. package/dist/src/index.d.ts +33 -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 +14 -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/0081_subgraphs_database_url_enc.ts +16 -0
  32. package/migrations/0082_contracts_registry.ts +44 -0
  33. 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;
@@ -519,6 +532,7 @@ interface Database {
519
532
  transactions: TransactionsTable;
520
533
  events: EventsTable;
521
534
  index_progress: IndexProgressTable;
535
+ contracts: ContractsTable;
522
536
  subgraphs: SubgraphsTable;
523
537
  api_keys: ApiKeysTable;
524
538
  accounts: AccountsTable;
@@ -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;
@@ -519,6 +532,7 @@ interface Database {
519
532
  transactions: TransactionsTable;
520
533
  events: EventsTable;
521
534
  index_progress: IndexProgressTable;
535
+ contracts: ContractsTable;
522
536
  subgraphs: SubgraphsTable;
523
537
  api_keys: ApiKeysTable;
524
538
  accounts: AccountsTable;
@@ -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;
@@ -519,6 +532,7 @@ interface Database {
519
532
  transactions: TransactionsTable;
520
533
  events: EventsTable;
521
534
  index_progress: IndexProgressTable;
535
+ contracts: ContractsTable;
522
536
  subgraphs: SubgraphsTable;
523
537
  api_keys: ApiKeysTable;
524
538
  accounts: AccountsTable;
@@ -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;
@@ -519,6 +533,7 @@ interface Database {
519
533
  transactions: TransactionsTable;
520
534
  events: EventsTable;
521
535
  index_progress: IndexProgressTable;
536
+ contracts: ContractsTable;
522
537
  subgraphs: SubgraphsTable;
523
538
  api_keys: ApiKeysTable;
524
539
  accounts: AccountsTable;
@@ -709,6 +724,24 @@ interface SubscriptionDeliveriesTable {
709
724
  dispatched_at: Generated<Date>;
710
725
  }
711
726
  /**
727
+ * BYO data plane helpers. A subgraph's user-owned Postgres connection string is
728
+ * stored encrypted at rest in `database_url_enc` (AES-GCM envelope). Plaintext
729
+ * only exists transiently — at deploy (to encrypt) and at pool construction (to
730
+ * connect). Never serialize it into API responses.
731
+ */
732
+ declare function encryptDatabaseUrl(url: string): Buffer;
733
+ /** Decrypt a subgraph's BYO connection string, or null when managed. */
734
+ declare function subgraphDatabaseUrl(subgraph: Subgraph): string | null;
735
+ /** True when the subgraph writes/serves from a user-owned DB. */
736
+ declare function isByoSubgraph(subgraph: Subgraph): boolean;
737
+ /**
738
+ * Resolve the Kysely instance a subgraph's data plane lives on: the user's DB
739
+ * when BYO, else the managed target DB. Pools are cached by URL in db/index.ts.
740
+ */
741
+ declare function resolveSubgraphDb(subgraph: Subgraph): Kysely<Database>;
742
+ /** Raw postgres.js client for a subgraph's data plane (DDL / serving queries). */
743
+ declare function resolveSubgraphRawClient(subgraph: Subgraph): ReturnType<typeof postgres>;
744
+ /**
712
745
  * Convert a subgraph name to its PostgreSQL schema name (legacy form).
713
746
  * Pre shared-rip every tenant DB had its own schema namespace so disambiguation
714
747
  * was implicit. Kept for oss mode (single-tenant) and legacy-row fallback.
@@ -733,6 +766,8 @@ declare function registerSubgraph(db: Kysely<Database>, data: {
733
766
  startBlock?: number
734
767
  handlerCode?: string
735
768
  sourceCode?: string
769
+ /** BYO data plane: encrypted user-DB connection string, or null = managed. */
770
+ databaseUrlEnc?: Buffer | null
736
771
  }): Promise<Subgraph>;
737
772
  declare function getSubgraph(db: Kysely<Database>, name: string, accountId?: string): Promise<Subgraph | null>;
738
773
  declare function listSubgraphs(db: Kysely<Database>, accountId?: string): Promise<Subgraph[]>;
@@ -743,4 +778,4 @@ declare function updateSubgraphHandlerPath(db: Kysely<Database>, name: string, h
743
778
  sourceCode?: string
744
779
  }): Promise<void>;
745
780
  declare function deleteSubgraph(db: Kysely<Database>, name: string, accountId?: string): Promise<Subgraph | null>;
746
- export { updateSubgraphStatus, updateSubgraphHandlerPath, registerSubgraph, recordSubgraphProcessed, pgSchemaNameFor, pgSchemaName, listSubgraphs, getSubgraph, deleteSubgraph };
781
+ export { updateSubgraphStatus, updateSubgraphHandlerPath, subgraphDatabaseUrl, resolveSubgraphRawClient, resolveSubgraphDb, registerSubgraph, recordSubgraphProcessed, pgSchemaNameFor, pgSchemaName, listSubgraphs, isByoSubgraph, getSubgraph, encryptDatabaseUrl, deleteSubgraph };