@secondlayer/shared 11.6.1 → 11.7.1
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.
- package/dist/src/archive/range-digest.d.ts +46 -27
- package/dist/src/archive/semantic-digest-builder.d.ts +46 -27
- package/dist/src/coverage/index.d.ts +46 -27
- package/dist/src/db/index.d.ts +57 -39
- package/dist/src/db/index.js +5 -4
- package/dist/src/db/index.js.map +3 -3
- package/dist/src/db/queries/chain-reorgs.d.ts +46 -27
- package/dist/src/db/queries/chain-reorgs.js +5 -4
- package/dist/src/db/queries/chain-reorgs.js.map +3 -3
- package/dist/src/db/queries/contracts.d.ts +46 -27
- package/dist/src/db/queries/instance.d.ts +46 -27
- package/dist/src/db/queries/integrity.d.ts +47 -28
- package/dist/src/db/queries/integrity.js +4 -3
- package/dist/src/db/queries/integrity.js.map +3 -3
- package/dist/src/db/queries/subgraph-gaps.d.ts +46 -27
- package/dist/src/db/queries/subgraph-operations.d.ts +46 -27
- package/dist/src/db/queries/subgraphs.d.ts +47 -33
- package/dist/src/db/queries/subgraphs.js +1 -10
- package/dist/src/db/queries/subgraphs.js.map +3 -3
- package/dist/src/db/queries/sync-scope.d.ts +46 -27
- package/dist/src/db/queries/webhooks.d.ts +46 -27
- package/dist/src/db/schema.d.ts +53 -36
- package/dist/src/index-http.d.ts +23 -0
- package/dist/src/index-http.js +9 -2
- package/dist/src/index-http.js.map +3 -3
- package/dist/src/index.d.ts +86 -42
- package/dist/src/index.js +58 -6
- package/dist/src/index.js.map +5 -5
- package/dist/src/node/local-client.d.ts +67 -28
- package/dist/src/node/local-client.js +41 -2
- package/dist/src/node/local-client.js.map +5 -4
- package/dist/src/schemas/index.d.ts +23 -1
- package/dist/src/schemas/index.js +38 -1
- package/dist/src/schemas/index.js.map +3 -3
- package/dist/src/schemas/webhooks.d.ts +23 -1
- package/dist/src/schemas/webhooks.js +38 -1
- package/dist/src/schemas/webhooks.js.map +3 -3
- package/dist/src/streams-rows/index.d.ts +43 -1
- package/dist/src/streams-rows/index.js +14 -3
- package/dist/src/streams-rows/index.js.map +3 -3
- package/dist/src/types.d.ts +12 -1
- package/migrations/0131_vm_events.ts +81 -0
- package/migrations/0132_vm_events_type_ordinal_idx.ts +21 -0
- package/migrations/0133_vm_events_fk_cascade.ts +47 -0
- package/migrations/0134_waitlists.ts +64 -0
- package/migrations/0135_drop_hosted_play_and_meters.ts +58 -0
- package/package.json +2 -2
|
@@ -93,14 +93,15 @@ async function computeContiguousTip(db, fromHeight) {
|
|
|
93
93
|
return Number(rows[0]?.tip ?? fromHeight);
|
|
94
94
|
}
|
|
95
95
|
async function findBrokenLinks(db, opts = {}) {
|
|
96
|
-
const windowSize = opts.window
|
|
96
|
+
const windowSize = opts.window === undefined ? 1e4 : opts.window;
|
|
97
97
|
const limitClause = opts.limit ? sql`LIMIT ${opts.limit}` : sql``;
|
|
98
|
+
const windowClause = windowSize === null ? sql`` : sql`AND height > (SELECT MAX(height) - ${windowSize} FROM blocks WHERE canonical = true)`;
|
|
98
99
|
const { rows } = await sql`
|
|
99
100
|
WITH recent AS (
|
|
100
101
|
SELECT height, hash, parent_hash
|
|
101
102
|
FROM blocks
|
|
102
103
|
WHERE canonical = true
|
|
103
|
-
|
|
104
|
+
${windowClause}
|
|
104
105
|
)
|
|
105
106
|
SELECT b.height, b.hash, p.hash AS expected_parent, b.parent_hash AS stored_parent
|
|
106
107
|
FROM recent b
|
|
@@ -124,5 +125,5 @@ export {
|
|
|
124
125
|
checkChainDataIntegrity
|
|
125
126
|
};
|
|
126
127
|
|
|
127
|
-
//# debugId=
|
|
128
|
+
//# debugId=956E0AF2AC54818A64756E2164756E21
|
|
128
129
|
//# sourceMappingURL=integrity.js.map
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/db/queries/integrity.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import { type Kysely, sql } from \"kysely\";\nimport type { Database } from \"../types.ts\";\n\nexport interface Gap {\n\tgapStart: number;\n\tgapEnd: number;\n\tsize: number;\n}\n\nexport async function findGaps(\n\tdb: Kysely<Database>,\n\tlimit?: number,\n): Promise<Gap[]> {\n\tconst limitClause = limit ? sql`LIMIT ${limit}` : sql``;\n\tconst { rows } = await sql<{\n\t\tgap_start: string;\n\t\tgap_end: string;\n\t\tsize: string;\n\t}>`\n SELECT gap_start, gap_end, gap_end - gap_start + 1 AS size\n FROM (\n SELECT height + 1 AS gap_start, next_height - 1 AS gap_end\n FROM (\n SELECT height, LEAD(height) OVER (ORDER BY height) AS next_height\n FROM blocks WHERE canonical = true\n ) sub\n WHERE next_height - height > 1\n ) gaps\n ORDER BY gap_start\n ${limitClause}\n `.execute(db);\n\n\treturn rows.map((r) => ({\n\t\tgapStart: Number(r.gap_start),\n\t\tgapEnd: Number(r.gap_end),\n\t\tsize: Number(r.size),\n\t}));\n}\n\nexport async function countMissingBlocks(\n\tdb: Kysely<Database>,\n): Promise<number> {\n\tconst { rows } = await sql<{ total: string }>`\n SELECT COALESCE(SUM(next_height - height - 1), 0) AS total\n FROM (\n SELECT height, LEAD(height) OVER (ORDER BY height) AS next_height\n FROM blocks WHERE canonical = true\n ) sub\n WHERE next_height - height > 1\n `.execute(db);\n\n\treturn Number(rows[0]?.total ?? 0);\n}\n\nexport interface ChainDataIntegrity {\n\tok: boolean;\n\tmaxHeight: number;\n\tsampleHeight: number | null;\n\tsampleBlocks: number;\n\treason: string | null;\n}\n\n/**\n * Cheap sanity check that the `blocks` table actually holds the history its tip\n * implies. Catches a wrong/empty Postgres volume — e.g. a container recreated\n * against a fresh volume — being silently served: if the tip is high but a\n * window of blocks well below it is missing, the data isn't what the tip claims.\n *\n * Below `checkFloor` we can't distinguish a fresh install from an empty volume,\n * so we report ok — a genuinely new DB legitimately has little history. Two\n * indexed lookups, safe to run on every startup / health poll.\n */\nexport async function checkChainDataIntegrity(\n\tdb: Kysely<Database>,\n\topts?: { checkFloor?: number; lookback?: number },\n): Promise<ChainDataIntegrity> {\n\tconst checkFloor = opts?.checkFloor ?? 1_000_000;\n\tconst lookback = opts?.lookback ?? 500_000;\n\n\tconst { rows: tipRows } = await sql<{ max: string | null }>`\n\t\tSELECT MAX(height) AS max FROM blocks WHERE canonical = true\n\t`.execute(db);\n\tconst maxHeight = Number(tipRows[0]?.max ?? 0);\n\n\tif (maxHeight < checkFloor) {\n\t\treturn {\n\t\t\tok: true,\n\t\t\tmaxHeight,\n\t\t\tsampleHeight: null,\n\t\t\tsampleBlocks: 0,\n\t\t\treason: null,\n\t\t};\n\t}\n\n\tconst sampleHeight = maxHeight - lookback;\n\tconst { rows: sampleRows } = await sql<{ n: string }>`\n\t\tSELECT count(*) AS n FROM blocks\n\t\tWHERE canonical = true AND height >= ${sampleHeight} AND height < ${sampleHeight + 1000}\n\t`.execute(db);\n\tconst sampleBlocks = Number(sampleRows[0]?.n ?? 0);\n\n\treturn {\n\t\tok: sampleBlocks > 0,\n\t\tmaxHeight,\n\t\tsampleHeight,\n\t\tsampleBlocks,\n\t\treason:\n\t\t\tsampleBlocks > 0\n\t\t\t\t? null\n\t\t\t\t: `tip is ${maxHeight} but no canonical blocks near ${sampleHeight} — wrong or empty volume?`,\n\t};\n}\n\nexport async function computeContiguousTip(\n\tdb: Kysely<Database>,\n\tfromHeight: number,\n): Promise<number> {\n\tconst { rows } = await sql<{ tip: string }>`\n SELECT COALESCE(MAX(height), ${fromHeight}) AS tip\n FROM (\n SELECT height, height - ROW_NUMBER() OVER (ORDER BY height) AS grp\n FROM blocks WHERE canonical = true AND height >= ${fromHeight}\n ) sub\n WHERE grp = (\n SELECT height - ROW_NUMBER() OVER (ORDER BY height)\n FROM blocks WHERE canonical = true AND height = ${fromHeight}\n )\n `.execute(db);\n\n\treturn Number(rows[0]?.tip ?? fromHeight);\n}\n\nexport type BrokenLink = {\n\theight: number;\n\thash: string;\n\texpectedParent: string;\n\tstoredParent: string;\n};\n\n/**\n * Canonical heights whose block does not descend from the canonical block\n * below it.\n *\n * `findGaps` asks \"is every height present?\", which a chain sitting on a losing\n * fork answers yes to. On 2026-07-30 a reorg at 8,663,166 was resolved the\n * wrong way: we adopted a block that mainnet orphaned, its true successors were\n * swept non-canonical, and later blocks were inserted canonical on top. Every\n * height existed. Nothing was \"missing\". The chain simply did not join up, and\n * no check asked that question — so we served a broken chain for seventeen\n * hours and only noticed because subgraphs stopped moving.\n *\n * Scoped to a recent window by default: an unlinked height is an active-repair\n * concern, and scanning eight million rows every cycle is not.\n */\nexport async function findBrokenLinks(\n\tdb: Kysely<Database>,\n\topts: { window?: number; limit?: number } = {},\n): Promise<BrokenLink[]> {\n\tconst windowSize = opts.window
|
|
5
|
+
"import { type Kysely, sql } from \"kysely\";\nimport type { Database } from \"../types.ts\";\n\nexport interface Gap {\n\tgapStart: number;\n\tgapEnd: number;\n\tsize: number;\n}\n\nexport async function findGaps(\n\tdb: Kysely<Database>,\n\tlimit?: number,\n): Promise<Gap[]> {\n\tconst limitClause = limit ? sql`LIMIT ${limit}` : sql``;\n\tconst { rows } = await sql<{\n\t\tgap_start: string;\n\t\tgap_end: string;\n\t\tsize: string;\n\t}>`\n SELECT gap_start, gap_end, gap_end - gap_start + 1 AS size\n FROM (\n SELECT height + 1 AS gap_start, next_height - 1 AS gap_end\n FROM (\n SELECT height, LEAD(height) OVER (ORDER BY height) AS next_height\n FROM blocks WHERE canonical = true\n ) sub\n WHERE next_height - height > 1\n ) gaps\n ORDER BY gap_start\n ${limitClause}\n `.execute(db);\n\n\treturn rows.map((r) => ({\n\t\tgapStart: Number(r.gap_start),\n\t\tgapEnd: Number(r.gap_end),\n\t\tsize: Number(r.size),\n\t}));\n}\n\nexport async function countMissingBlocks(\n\tdb: Kysely<Database>,\n): Promise<number> {\n\tconst { rows } = await sql<{ total: string }>`\n SELECT COALESCE(SUM(next_height - height - 1), 0) AS total\n FROM (\n SELECT height, LEAD(height) OVER (ORDER BY height) AS next_height\n FROM blocks WHERE canonical = true\n ) sub\n WHERE next_height - height > 1\n `.execute(db);\n\n\treturn Number(rows[0]?.total ?? 0);\n}\n\nexport interface ChainDataIntegrity {\n\tok: boolean;\n\tmaxHeight: number;\n\tsampleHeight: number | null;\n\tsampleBlocks: number;\n\treason: string | null;\n}\n\n/**\n * Cheap sanity check that the `blocks` table actually holds the history its tip\n * implies. Catches a wrong/empty Postgres volume — e.g. a container recreated\n * against a fresh volume — being silently served: if the tip is high but a\n * window of blocks well below it is missing, the data isn't what the tip claims.\n *\n * Below `checkFloor` we can't distinguish a fresh install from an empty volume,\n * so we report ok — a genuinely new DB legitimately has little history. Two\n * indexed lookups, safe to run on every startup / health poll.\n */\nexport async function checkChainDataIntegrity(\n\tdb: Kysely<Database>,\n\topts?: { checkFloor?: number; lookback?: number },\n): Promise<ChainDataIntegrity> {\n\tconst checkFloor = opts?.checkFloor ?? 1_000_000;\n\tconst lookback = opts?.lookback ?? 500_000;\n\n\tconst { rows: tipRows } = await sql<{ max: string | null }>`\n\t\tSELECT MAX(height) AS max FROM blocks WHERE canonical = true\n\t`.execute(db);\n\tconst maxHeight = Number(tipRows[0]?.max ?? 0);\n\n\tif (maxHeight < checkFloor) {\n\t\treturn {\n\t\t\tok: true,\n\t\t\tmaxHeight,\n\t\t\tsampleHeight: null,\n\t\t\tsampleBlocks: 0,\n\t\t\treason: null,\n\t\t};\n\t}\n\n\tconst sampleHeight = maxHeight - lookback;\n\tconst { rows: sampleRows } = await sql<{ n: string }>`\n\t\tSELECT count(*) AS n FROM blocks\n\t\tWHERE canonical = true AND height >= ${sampleHeight} AND height < ${sampleHeight + 1000}\n\t`.execute(db);\n\tconst sampleBlocks = Number(sampleRows[0]?.n ?? 0);\n\n\treturn {\n\t\tok: sampleBlocks > 0,\n\t\tmaxHeight,\n\t\tsampleHeight,\n\t\tsampleBlocks,\n\t\treason:\n\t\t\tsampleBlocks > 0\n\t\t\t\t? null\n\t\t\t\t: `tip is ${maxHeight} but no canonical blocks near ${sampleHeight} — wrong or empty volume?`,\n\t};\n}\n\nexport async function computeContiguousTip(\n\tdb: Kysely<Database>,\n\tfromHeight: number,\n): Promise<number> {\n\tconst { rows } = await sql<{ tip: string }>`\n SELECT COALESCE(MAX(height), ${fromHeight}) AS tip\n FROM (\n SELECT height, height - ROW_NUMBER() OVER (ORDER BY height) AS grp\n FROM blocks WHERE canonical = true AND height >= ${fromHeight}\n ) sub\n WHERE grp = (\n SELECT height - ROW_NUMBER() OVER (ORDER BY height)\n FROM blocks WHERE canonical = true AND height = ${fromHeight}\n )\n `.execute(db);\n\n\treturn Number(rows[0]?.tip ?? fromHeight);\n}\n\nexport type BrokenLink = {\n\theight: number;\n\thash: string;\n\texpectedParent: string;\n\tstoredParent: string;\n};\n\n/**\n * Canonical heights whose block does not descend from the canonical block\n * below it.\n *\n * `findGaps` asks \"is every height present?\", which a chain sitting on a losing\n * fork answers yes to. On 2026-07-30 a reorg at 8,663,166 was resolved the\n * wrong way: we adopted a block that mainnet orphaned, its true successors were\n * swept non-canonical, and later blocks were inserted canonical on top. Every\n * height existed. Nothing was \"missing\". The chain simply did not join up, and\n * no check asked that question — so we served a broken chain for seventeen\n * hours and only noticed because subgraphs stopped moving.\n *\n * Scoped to a recent window by default: an unlinked height is an active-repair\n * concern, and scanning eight million rows every cycle is not.\n */\nexport async function findBrokenLinks(\n\tdb: Kysely<Database>,\n\t/** Heights below the tip to scan; `null` scans the whole chain. */\n\topts: { window?: number | null; limit?: number } = {},\n): Promise<BrokenLink[]> {\n\tconst windowSize = opts.window === undefined ? 10_000 : opts.window;\n\tconst limitClause = opts.limit ? sql`LIMIT ${opts.limit}` : sql``;\n\tconst windowClause =\n\t\twindowSize === null\n\t\t\t? sql``\n\t\t\t: sql`AND height > (SELECT MAX(height) - ${windowSize} FROM blocks WHERE canonical = true)`;\n\tconst { rows } = await sql<{\n\t\theight: string | number;\n\t\thash: string;\n\t\texpected_parent: string;\n\t\tstored_parent: string;\n\t}>`\n\t\tWITH recent AS (\n\t\t\tSELECT height, hash, parent_hash\n\t\t\tFROM blocks\n\t\t\tWHERE canonical = true\n\t\t\t\t${windowClause}\n\t\t)\n\t\tSELECT b.height, b.hash, p.hash AS expected_parent, b.parent_hash AS stored_parent\n\t\tFROM recent b\n\t\tJOIN recent p ON p.height = b.height - 1\n\t\tWHERE b.parent_hash <> p.hash\n\t\tORDER BY b.height\n\t\t${limitClause}\n\t`.execute(db);\n\treturn rows.map((r) => ({\n\t\theight: Number(r.height),\n\t\thash: r.hash,\n\t\texpectedParent: r.expected_parent,\n\t\tstoredParent: r.stored_parent,\n\t}));\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AASA,eAAsB,QAAQ,CAC7B,IACA,OACiB;AAAA,EACjB,MAAM,cAAc,QAAQ,YAAY,UAAU;AAAA,EAClD,QAAQ,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAelB;AAAA,IACF,QAAQ,EAAE;AAAA,EAEb,OAAO,KAAK,IAAI,CAAC,OAAO;AAAA,IACvB,UAAU,OAAO,EAAE,SAAS;AAAA,IAC5B,QAAQ,OAAO,EAAE,OAAO;AAAA,IACxB,MAAM,OAAO,EAAE,IAAI;AAAA,EACpB,EAAE;AAAA;AAGH,eAAsB,kBAAkB,CACvC,IACkB;AAAA,EAClB,QAAQ,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOpB,QAAQ,EAAE;AAAA,EAEb,OAAO,OAAO,KAAK,IAAI,SAAS,CAAC;AAAA;AAqBlC,eAAsB,uBAAuB,CAC5C,IACA,MAC8B;AAAA,EAC9B,MAAM,aAAa,MAAM,cAAc;AAAA,EACvC,MAAM,WAAW,MAAM,YAAY;AAAA,EAEnC,QAAQ,MAAM,YAAY,MAAM;AAAA;AAAA,GAE9B,QAAQ,EAAE;AAAA,EACZ,MAAM,YAAY,OAAO,QAAQ,IAAI,OAAO,CAAC;AAAA,EAE7C,IAAI,YAAY,YAAY;AAAA,IAC3B,OAAO;AAAA,MACN,IAAI;AAAA,MACJ;AAAA,MACA,cAAc;AAAA,MACd,cAAc;AAAA,MACd,QAAQ;AAAA,IACT;AAAA,EACD;AAAA,EAEA,MAAM,eAAe,YAAY;AAAA,EACjC,QAAQ,MAAM,eAAe,MAAM;AAAA;AAAA,yCAEK,6BAA6B,eAAe;AAAA,GAClF,QAAQ,EAAE;AAAA,EACZ,MAAM,eAAe,OAAO,WAAW,IAAI,KAAK,CAAC;AAAA,EAEjD,OAAO;AAAA,IACN,IAAI,eAAe;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA,QACC,eAAe,IACZ,OACA,UAAU,0CAA0C;AAAA,EACzD;AAAA;AAGD,eAAsB,oBAAoB,CACzC,IACA,YACkB;AAAA,EAClB,QAAQ,SAAS,MAAM;AAAA,mCACW;AAAA;AAAA;AAAA,yDAGsB;AAAA;AAAA;AAAA;AAAA,wDAID;AAAA;AAAA,IAEpD,QAAQ,EAAE;AAAA,EAEb,OAAO,OAAO,KAAK,IAAI,OAAO,UAAU;AAAA;AAyBzC,eAAsB,eAAe,CACpC,
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AASA,eAAsB,QAAQ,CAC7B,IACA,OACiB;AAAA,EACjB,MAAM,cAAc,QAAQ,YAAY,UAAU;AAAA,EAClD,QAAQ,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAelB;AAAA,IACF,QAAQ,EAAE;AAAA,EAEb,OAAO,KAAK,IAAI,CAAC,OAAO;AAAA,IACvB,UAAU,OAAO,EAAE,SAAS;AAAA,IAC5B,QAAQ,OAAO,EAAE,OAAO;AAAA,IACxB,MAAM,OAAO,EAAE,IAAI;AAAA,EACpB,EAAE;AAAA;AAGH,eAAsB,kBAAkB,CACvC,IACkB;AAAA,EAClB,QAAQ,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOpB,QAAQ,EAAE;AAAA,EAEb,OAAO,OAAO,KAAK,IAAI,SAAS,CAAC;AAAA;AAqBlC,eAAsB,uBAAuB,CAC5C,IACA,MAC8B;AAAA,EAC9B,MAAM,aAAa,MAAM,cAAc;AAAA,EACvC,MAAM,WAAW,MAAM,YAAY;AAAA,EAEnC,QAAQ,MAAM,YAAY,MAAM;AAAA;AAAA,GAE9B,QAAQ,EAAE;AAAA,EACZ,MAAM,YAAY,OAAO,QAAQ,IAAI,OAAO,CAAC;AAAA,EAE7C,IAAI,YAAY,YAAY;AAAA,IAC3B,OAAO;AAAA,MACN,IAAI;AAAA,MACJ;AAAA,MACA,cAAc;AAAA,MACd,cAAc;AAAA,MACd,QAAQ;AAAA,IACT;AAAA,EACD;AAAA,EAEA,MAAM,eAAe,YAAY;AAAA,EACjC,QAAQ,MAAM,eAAe,MAAM;AAAA;AAAA,yCAEK,6BAA6B,eAAe;AAAA,GAClF,QAAQ,EAAE;AAAA,EACZ,MAAM,eAAe,OAAO,WAAW,IAAI,KAAK,CAAC;AAAA,EAEjD,OAAO;AAAA,IACN,IAAI,eAAe;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA,QACC,eAAe,IACZ,OACA,UAAU,0CAA0C;AAAA,EACzD;AAAA;AAGD,eAAsB,oBAAoB,CACzC,IACA,YACkB;AAAA,EAClB,QAAQ,SAAS,MAAM;AAAA,mCACW;AAAA;AAAA;AAAA,yDAGsB;AAAA;AAAA;AAAA;AAAA,wDAID;AAAA;AAAA,IAEpD,QAAQ,EAAE;AAAA,EAEb,OAAO,OAAO,KAAK,IAAI,OAAO,UAAU;AAAA;AAyBzC,eAAsB,eAAe,CACpC,IAEA,OAAmD,CAAC,GAC5B;AAAA,EACxB,MAAM,aAAa,KAAK,WAAW,YAAY,MAAS,KAAK;AAAA,EAC7D,MAAM,cAAc,KAAK,QAAQ,YAAY,KAAK,UAAU;AAAA,EAC5D,MAAM,eACL,eAAe,OACZ,QACA,yCAAyC;AAAA,EAC7C,QAAQ,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,MAUlB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOF;AAAA,GACD,QAAQ,EAAE;AAAA,EACZ,OAAO,KAAK,IAAI,CAAC,OAAO;AAAA,IACvB,QAAQ,OAAO,EAAE,MAAM;AAAA,IACvB,MAAM,EAAE;AAAA,IACR,gBAAgB,EAAE;AAAA,IAClB,cAAc,EAAE;AAAA,EACjB,EAAE;AAAA;",
|
|
8
|
+
"debugId": "956E0AF2AC54818A64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -83,6 +83,27 @@ interface EventsArchiveTable {
|
|
|
83
83
|
orphaned_block_hash: string | null;
|
|
84
84
|
archived_at: Generated<Date>;
|
|
85
85
|
}
|
|
86
|
+
interface VmEventsTable {
|
|
87
|
+
id: Generated<string>;
|
|
88
|
+
tx_id: string;
|
|
89
|
+
block_height: number;
|
|
90
|
+
ordinal: number;
|
|
91
|
+
type: string;
|
|
92
|
+
data: unknown;
|
|
93
|
+
created_at: Generated<Date>;
|
|
94
|
+
}
|
|
95
|
+
interface VmEventsArchiveTable {
|
|
96
|
+
archive_id: Generated<string>;
|
|
97
|
+
id: string;
|
|
98
|
+
tx_id: string;
|
|
99
|
+
block_height: number;
|
|
100
|
+
ordinal: number;
|
|
101
|
+
type: string;
|
|
102
|
+
data: unknown;
|
|
103
|
+
created_at: Date;
|
|
104
|
+
orphaned_block_hash: string | null;
|
|
105
|
+
archived_at: Generated<Date>;
|
|
106
|
+
}
|
|
86
107
|
interface DeadLetterEventsTable {
|
|
87
108
|
id: Generated<string>;
|
|
88
109
|
block_height: number;
|
|
@@ -263,21 +284,6 @@ interface MagicLinksTable {
|
|
|
263
284
|
failed_attempts: Generated<number>;
|
|
264
285
|
created_at: Generated<Date>;
|
|
265
286
|
}
|
|
266
|
-
/** One-shot hashed tokens that attach a play ghost to an email at claim. */
|
|
267
|
-
interface ClaimTokensTable {
|
|
268
|
-
id: Generated<string>;
|
|
269
|
-
account_id: string;
|
|
270
|
-
token_hash: string;
|
|
271
|
-
created_at: Generated<Date>;
|
|
272
|
-
expires_at: Date;
|
|
273
|
-
used_at: Date | null;
|
|
274
|
-
}
|
|
275
|
-
/** 3 play provisions per IP per UTC day. PK (ip_hash, day); `count` caps at 3. */
|
|
276
|
-
interface PlayProvisionsTable {
|
|
277
|
-
ip_hash: string;
|
|
278
|
-
day: string;
|
|
279
|
-
count: Generated<number>;
|
|
280
|
-
}
|
|
281
287
|
interface SubgraphProcessingStatsTable {
|
|
282
288
|
id: Generated<string>;
|
|
283
289
|
subgraph_name: string;
|
|
@@ -725,8 +731,10 @@ interface Database {
|
|
|
725
731
|
blocks: BlocksTable;
|
|
726
732
|
transactions: TransactionsTable;
|
|
727
733
|
events: EventsTable;
|
|
734
|
+
vm_events: VmEventsTable;
|
|
728
735
|
transactions_archive: TransactionsArchiveTable;
|
|
729
736
|
events_archive: EventsArchiveTable;
|
|
737
|
+
vm_events_archive: VmEventsArchiveTable;
|
|
730
738
|
dead_letter_events: DeadLetterEventsTable;
|
|
731
739
|
mempool_transactions: MempoolTransactionsTable;
|
|
732
740
|
index_progress: IndexProgressTable;
|
|
@@ -737,8 +745,6 @@ interface Database {
|
|
|
737
745
|
accounts: AccountsTable;
|
|
738
746
|
sessions: SessionsTable;
|
|
739
747
|
magic_links: MagicLinksTable;
|
|
740
|
-
claim_tokens: ClaimTokensTable;
|
|
741
|
-
play_provisions: PlayProvisionsTable;
|
|
742
748
|
subgraph_health_snapshots: SubgraphHealthSnapshotsTable;
|
|
743
749
|
subgraph_processing_stats: SubgraphProcessingStatsTable;
|
|
744
750
|
subgraph_gaps: SubgraphGapsTable;
|
|
@@ -747,7 +753,6 @@ interface Database {
|
|
|
747
753
|
processed_stripe_events: ProcessedStripeEventsTable;
|
|
748
754
|
account_spend_caps: AccountSpendCapsTable;
|
|
749
755
|
account_credits: AccountCreditsTable;
|
|
750
|
-
hosted_meter_days: HostedMeterDaysTable;
|
|
751
756
|
webhooks: WebhooksTable;
|
|
752
757
|
webhook_outbox: WebhookOutboxTable;
|
|
753
758
|
webhook_deliveries: WebhookDeliveriesTable;
|
|
@@ -778,6 +783,8 @@ interface Database {
|
|
|
778
783
|
coverage_segments: CoverageSegmentsTable;
|
|
779
784
|
stage_failures: StageFailuresTable;
|
|
780
785
|
archive_fetches: ArchiveFetchesTable;
|
|
786
|
+
waitlists: WaitlistsTable;
|
|
787
|
+
waitlist_signups: WaitlistSignupsTable;
|
|
781
788
|
}
|
|
782
789
|
interface ServiceHeartbeatsTable {
|
|
783
790
|
name: string;
|
|
@@ -806,15 +813,6 @@ interface AccountCreditsTable {
|
|
|
806
813
|
refill_last_at: Date | null;
|
|
807
814
|
updated_at: Generated<Date>;
|
|
808
815
|
}
|
|
809
|
-
/** Daily idempotency ledger for hosted subgraph running + storage meters. */
|
|
810
|
-
interface HostedMeterDaysTable {
|
|
811
|
-
day: string;
|
|
812
|
-
account_id: string;
|
|
813
|
-
subgraph_name: string;
|
|
814
|
-
kind: string;
|
|
815
|
-
usd_micros: string | number | bigint;
|
|
816
|
-
billed_at: Generated<Date>;
|
|
817
|
-
}
|
|
818
816
|
/**
|
|
819
817
|
* Archive fetch charge log (design-f089 gate). Append-only: one row per
|
|
820
818
|
* priced attempt to fetch a partition object. `usd_micros` is 0 for
|
|
@@ -917,6 +915,27 @@ interface TriggerEvaluatorStateTable {
|
|
|
917
915
|
last_settlement_scan_at: ColumnType<Date | null, Date | null | undefined, Date | null>;
|
|
918
916
|
updated_at: Generated<Date>;
|
|
919
917
|
}
|
|
918
|
+
/** A public waitlist page: what it is for and whether it takes signups. */
|
|
919
|
+
interface WaitlistsTable {
|
|
920
|
+
slug: string;
|
|
921
|
+
title: string;
|
|
922
|
+
description: string;
|
|
923
|
+
url: string;
|
|
924
|
+
opened_at: Generated<Date>;
|
|
925
|
+
/** Null while the list is open. */
|
|
926
|
+
closed_at: Date | null;
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* One signup per (list, contact, token). `answers` holds the list's own
|
|
930
|
+
* questions, validated per list by the API before insert.
|
|
931
|
+
*/
|
|
932
|
+
interface WaitlistSignupsTable {
|
|
933
|
+
id: Generated<string>;
|
|
934
|
+
list: string;
|
|
935
|
+
contact: string;
|
|
936
|
+
answers: Record<string, unknown>;
|
|
937
|
+
created_at: Generated<Date>;
|
|
938
|
+
}
|
|
920
939
|
interface GapRange {
|
|
921
940
|
start: number;
|
|
922
941
|
end: number;
|
|
@@ -83,6 +83,27 @@ interface EventsArchiveTable {
|
|
|
83
83
|
orphaned_block_hash: string | null;
|
|
84
84
|
archived_at: Generated<Date>;
|
|
85
85
|
}
|
|
86
|
+
interface VmEventsTable {
|
|
87
|
+
id: Generated<string>;
|
|
88
|
+
tx_id: string;
|
|
89
|
+
block_height: number;
|
|
90
|
+
ordinal: number;
|
|
91
|
+
type: string;
|
|
92
|
+
data: unknown;
|
|
93
|
+
created_at: Generated<Date>;
|
|
94
|
+
}
|
|
95
|
+
interface VmEventsArchiveTable {
|
|
96
|
+
archive_id: Generated<string>;
|
|
97
|
+
id: string;
|
|
98
|
+
tx_id: string;
|
|
99
|
+
block_height: number;
|
|
100
|
+
ordinal: number;
|
|
101
|
+
type: string;
|
|
102
|
+
data: unknown;
|
|
103
|
+
created_at: Date;
|
|
104
|
+
orphaned_block_hash: string | null;
|
|
105
|
+
archived_at: Generated<Date>;
|
|
106
|
+
}
|
|
86
107
|
interface DeadLetterEventsTable {
|
|
87
108
|
id: Generated<string>;
|
|
88
109
|
block_height: number;
|
|
@@ -263,21 +284,6 @@ interface MagicLinksTable {
|
|
|
263
284
|
failed_attempts: Generated<number>;
|
|
264
285
|
created_at: Generated<Date>;
|
|
265
286
|
}
|
|
266
|
-
/** One-shot hashed tokens that attach a play ghost to an email at claim. */
|
|
267
|
-
interface ClaimTokensTable {
|
|
268
|
-
id: Generated<string>;
|
|
269
|
-
account_id: string;
|
|
270
|
-
token_hash: string;
|
|
271
|
-
created_at: Generated<Date>;
|
|
272
|
-
expires_at: Date;
|
|
273
|
-
used_at: Date | null;
|
|
274
|
-
}
|
|
275
|
-
/** 3 play provisions per IP per UTC day. PK (ip_hash, day); `count` caps at 3. */
|
|
276
|
-
interface PlayProvisionsTable {
|
|
277
|
-
ip_hash: string;
|
|
278
|
-
day: string;
|
|
279
|
-
count: Generated<number>;
|
|
280
|
-
}
|
|
281
287
|
interface SubgraphProcessingStatsTable {
|
|
282
288
|
id: Generated<string>;
|
|
283
289
|
subgraph_name: string;
|
|
@@ -725,8 +731,10 @@ interface Database {
|
|
|
725
731
|
blocks: BlocksTable;
|
|
726
732
|
transactions: TransactionsTable;
|
|
727
733
|
events: EventsTable;
|
|
734
|
+
vm_events: VmEventsTable;
|
|
728
735
|
transactions_archive: TransactionsArchiveTable;
|
|
729
736
|
events_archive: EventsArchiveTable;
|
|
737
|
+
vm_events_archive: VmEventsArchiveTable;
|
|
730
738
|
dead_letter_events: DeadLetterEventsTable;
|
|
731
739
|
mempool_transactions: MempoolTransactionsTable;
|
|
732
740
|
index_progress: IndexProgressTable;
|
|
@@ -737,8 +745,6 @@ interface Database {
|
|
|
737
745
|
accounts: AccountsTable;
|
|
738
746
|
sessions: SessionsTable;
|
|
739
747
|
magic_links: MagicLinksTable;
|
|
740
|
-
claim_tokens: ClaimTokensTable;
|
|
741
|
-
play_provisions: PlayProvisionsTable;
|
|
742
748
|
subgraph_health_snapshots: SubgraphHealthSnapshotsTable;
|
|
743
749
|
subgraph_processing_stats: SubgraphProcessingStatsTable;
|
|
744
750
|
subgraph_gaps: SubgraphGapsTable;
|
|
@@ -747,7 +753,6 @@ interface Database {
|
|
|
747
753
|
processed_stripe_events: ProcessedStripeEventsTable;
|
|
748
754
|
account_spend_caps: AccountSpendCapsTable;
|
|
749
755
|
account_credits: AccountCreditsTable;
|
|
750
|
-
hosted_meter_days: HostedMeterDaysTable;
|
|
751
756
|
webhooks: WebhooksTable;
|
|
752
757
|
webhook_outbox: WebhookOutboxTable;
|
|
753
758
|
webhook_deliveries: WebhookDeliveriesTable;
|
|
@@ -778,6 +783,8 @@ interface Database {
|
|
|
778
783
|
coverage_segments: CoverageSegmentsTable;
|
|
779
784
|
stage_failures: StageFailuresTable;
|
|
780
785
|
archive_fetches: ArchiveFetchesTable;
|
|
786
|
+
waitlists: WaitlistsTable;
|
|
787
|
+
waitlist_signups: WaitlistSignupsTable;
|
|
781
788
|
}
|
|
782
789
|
interface ServiceHeartbeatsTable {
|
|
783
790
|
name: string;
|
|
@@ -806,15 +813,6 @@ interface AccountCreditsTable {
|
|
|
806
813
|
refill_last_at: Date | null;
|
|
807
814
|
updated_at: Generated<Date>;
|
|
808
815
|
}
|
|
809
|
-
/** Daily idempotency ledger for hosted subgraph running + storage meters. */
|
|
810
|
-
interface HostedMeterDaysTable {
|
|
811
|
-
day: string;
|
|
812
|
-
account_id: string;
|
|
813
|
-
subgraph_name: string;
|
|
814
|
-
kind: string;
|
|
815
|
-
usd_micros: string | number | bigint;
|
|
816
|
-
billed_at: Generated<Date>;
|
|
817
|
-
}
|
|
818
816
|
/**
|
|
819
817
|
* Archive fetch charge log (design-f089 gate). Append-only: one row per
|
|
820
818
|
* priced attempt to fetch a partition object. `usd_micros` is 0 for
|
|
@@ -918,6 +916,27 @@ interface TriggerEvaluatorStateTable {
|
|
|
918
916
|
last_settlement_scan_at: ColumnType<Date | null, Date | null | undefined, Date | null>;
|
|
919
917
|
updated_at: Generated<Date>;
|
|
920
918
|
}
|
|
919
|
+
/** A public waitlist page: what it is for and whether it takes signups. */
|
|
920
|
+
interface WaitlistsTable {
|
|
921
|
+
slug: string;
|
|
922
|
+
title: string;
|
|
923
|
+
description: string;
|
|
924
|
+
url: string;
|
|
925
|
+
opened_at: Generated<Date>;
|
|
926
|
+
/** Null while the list is open. */
|
|
927
|
+
closed_at: Date | null;
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* One signup per (list, contact, token). `answers` holds the list's own
|
|
931
|
+
* questions, validated per list by the API before insert.
|
|
932
|
+
*/
|
|
933
|
+
interface WaitlistSignupsTable {
|
|
934
|
+
id: Generated<string>;
|
|
935
|
+
list: string;
|
|
936
|
+
contact: string;
|
|
937
|
+
answers: Record<string, unknown>;
|
|
938
|
+
created_at: Generated<Date>;
|
|
939
|
+
}
|
|
921
940
|
declare function isActiveSubgraphOperationConflict(err: unknown): boolean;
|
|
922
941
|
declare function createSubgraphOperation(db: Kysely<Database>, data: {
|
|
923
942
|
subgraphId: string
|
|
@@ -83,6 +83,27 @@ interface EventsArchiveTable {
|
|
|
83
83
|
orphaned_block_hash: string | null;
|
|
84
84
|
archived_at: Generated<Date>;
|
|
85
85
|
}
|
|
86
|
+
interface VmEventsTable {
|
|
87
|
+
id: Generated<string>;
|
|
88
|
+
tx_id: string;
|
|
89
|
+
block_height: number;
|
|
90
|
+
ordinal: number;
|
|
91
|
+
type: string;
|
|
92
|
+
data: unknown;
|
|
93
|
+
created_at: Generated<Date>;
|
|
94
|
+
}
|
|
95
|
+
interface VmEventsArchiveTable {
|
|
96
|
+
archive_id: Generated<string>;
|
|
97
|
+
id: string;
|
|
98
|
+
tx_id: string;
|
|
99
|
+
block_height: number;
|
|
100
|
+
ordinal: number;
|
|
101
|
+
type: string;
|
|
102
|
+
data: unknown;
|
|
103
|
+
created_at: Date;
|
|
104
|
+
orphaned_block_hash: string | null;
|
|
105
|
+
archived_at: Generated<Date>;
|
|
106
|
+
}
|
|
86
107
|
interface DeadLetterEventsTable {
|
|
87
108
|
id: Generated<string>;
|
|
88
109
|
block_height: number;
|
|
@@ -263,21 +284,6 @@ interface MagicLinksTable {
|
|
|
263
284
|
failed_attempts: Generated<number>;
|
|
264
285
|
created_at: Generated<Date>;
|
|
265
286
|
}
|
|
266
|
-
/** One-shot hashed tokens that attach a play ghost to an email at claim. */
|
|
267
|
-
interface ClaimTokensTable {
|
|
268
|
-
id: Generated<string>;
|
|
269
|
-
account_id: string;
|
|
270
|
-
token_hash: string;
|
|
271
|
-
created_at: Generated<Date>;
|
|
272
|
-
expires_at: Date;
|
|
273
|
-
used_at: Date | null;
|
|
274
|
-
}
|
|
275
|
-
/** 3 play provisions per IP per UTC day. PK (ip_hash, day); `count` caps at 3. */
|
|
276
|
-
interface PlayProvisionsTable {
|
|
277
|
-
ip_hash: string;
|
|
278
|
-
day: string;
|
|
279
|
-
count: Generated<number>;
|
|
280
|
-
}
|
|
281
287
|
interface SubgraphProcessingStatsTable {
|
|
282
288
|
id: Generated<string>;
|
|
283
289
|
subgraph_name: string;
|
|
@@ -725,8 +731,10 @@ interface Database {
|
|
|
725
731
|
blocks: BlocksTable;
|
|
726
732
|
transactions: TransactionsTable;
|
|
727
733
|
events: EventsTable;
|
|
734
|
+
vm_events: VmEventsTable;
|
|
728
735
|
transactions_archive: TransactionsArchiveTable;
|
|
729
736
|
events_archive: EventsArchiveTable;
|
|
737
|
+
vm_events_archive: VmEventsArchiveTable;
|
|
730
738
|
dead_letter_events: DeadLetterEventsTable;
|
|
731
739
|
mempool_transactions: MempoolTransactionsTable;
|
|
732
740
|
index_progress: IndexProgressTable;
|
|
@@ -737,8 +745,6 @@ interface Database {
|
|
|
737
745
|
accounts: AccountsTable;
|
|
738
746
|
sessions: SessionsTable;
|
|
739
747
|
magic_links: MagicLinksTable;
|
|
740
|
-
claim_tokens: ClaimTokensTable;
|
|
741
|
-
play_provisions: PlayProvisionsTable;
|
|
742
748
|
subgraph_health_snapshots: SubgraphHealthSnapshotsTable;
|
|
743
749
|
subgraph_processing_stats: SubgraphProcessingStatsTable;
|
|
744
750
|
subgraph_gaps: SubgraphGapsTable;
|
|
@@ -747,7 +753,6 @@ interface Database {
|
|
|
747
753
|
processed_stripe_events: ProcessedStripeEventsTable;
|
|
748
754
|
account_spend_caps: AccountSpendCapsTable;
|
|
749
755
|
account_credits: AccountCreditsTable;
|
|
750
|
-
hosted_meter_days: HostedMeterDaysTable;
|
|
751
756
|
webhooks: WebhooksTable;
|
|
752
757
|
webhook_outbox: WebhookOutboxTable;
|
|
753
758
|
webhook_deliveries: WebhookDeliveriesTable;
|
|
@@ -778,6 +783,8 @@ interface Database {
|
|
|
778
783
|
coverage_segments: CoverageSegmentsTable;
|
|
779
784
|
stage_failures: StageFailuresTable;
|
|
780
785
|
archive_fetches: ArchiveFetchesTable;
|
|
786
|
+
waitlists: WaitlistsTable;
|
|
787
|
+
waitlist_signups: WaitlistSignupsTable;
|
|
781
788
|
}
|
|
782
789
|
interface ServiceHeartbeatsTable {
|
|
783
790
|
name: string;
|
|
@@ -806,15 +813,6 @@ interface AccountCreditsTable {
|
|
|
806
813
|
refill_last_at: Date | null;
|
|
807
814
|
updated_at: Generated<Date>;
|
|
808
815
|
}
|
|
809
|
-
/** Daily idempotency ledger for hosted subgraph running + storage meters. */
|
|
810
|
-
interface HostedMeterDaysTable {
|
|
811
|
-
day: string;
|
|
812
|
-
account_id: string;
|
|
813
|
-
subgraph_name: string;
|
|
814
|
-
kind: string;
|
|
815
|
-
usd_micros: string | number | bigint;
|
|
816
|
-
billed_at: Generated<Date>;
|
|
817
|
-
}
|
|
818
816
|
/**
|
|
819
817
|
* Archive fetch charge log (design-f089 gate). Append-only: one row per
|
|
820
818
|
* priced attempt to fetch a partition object. `usd_micros` is 0 for
|
|
@@ -918,6 +916,27 @@ interface TriggerEvaluatorStateTable {
|
|
|
918
916
|
last_settlement_scan_at: ColumnType<Date | null, Date | null | undefined, Date | null>;
|
|
919
917
|
updated_at: Generated<Date>;
|
|
920
918
|
}
|
|
919
|
+
/** A public waitlist page: what it is for and whether it takes signups. */
|
|
920
|
+
interface WaitlistsTable {
|
|
921
|
+
slug: string;
|
|
922
|
+
title: string;
|
|
923
|
+
description: string;
|
|
924
|
+
url: string;
|
|
925
|
+
opened_at: Generated<Date>;
|
|
926
|
+
/** Null while the list is open. */
|
|
927
|
+
closed_at: Date | null;
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* One signup per (list, contact, token). `answers` holds the list's own
|
|
931
|
+
* questions, validated per list by the API before insert.
|
|
932
|
+
*/
|
|
933
|
+
interface WaitlistSignupsTable {
|
|
934
|
+
id: Generated<string>;
|
|
935
|
+
list: string;
|
|
936
|
+
contact: string;
|
|
937
|
+
answers: Record<string, unknown>;
|
|
938
|
+
created_at: Generated<Date>;
|
|
939
|
+
}
|
|
921
940
|
/**
|
|
922
941
|
* Convert a subgraph name to its PostgreSQL schema name (legacy form).
|
|
923
942
|
* Pre shared-rip every tenant DB had its own schema namespace so disambiguation
|
|
@@ -949,11 +968,6 @@ declare function registerSubgraph(db: Kysely<Database>, data: {
|
|
|
949
968
|
declare function getSubgraph(db: Kysely<Database>, name: string, accountId?: string): Promise<Subgraph | null>;
|
|
950
969
|
declare function listSubgraphs(db: Kysely<Database>, accountId?: string): Promise<Subgraph[]>;
|
|
951
970
|
declare function updateSubgraphStatus(db: Kysely<Database>, name: string, status: string, lastProcessedBlock?: number): Promise<void>;
|
|
952
|
-
/** Account-scoped pause. Only active/reindexing rows flip; name-only
|
|
953
|
-
* {@link updateSubgraphStatus} is unsafe on platform (name, account_id). */
|
|
954
|
-
declare function pauseSubgraph(db: Kysely<Database>, name: string, accountId: string): Promise<void>;
|
|
955
|
-
/** Resume every paused subgraph for an account (claim / Stripe top-up). */
|
|
956
|
-
declare function resumePausedSubgraphs(db: Kysely<Database>, accountId: string): Promise<number>;
|
|
957
971
|
/** Live-walk ERROR write (f069): a block whose handlers ALL failed
|
|
958
972
|
* (`processed === 0 && errors > 0`, `block-processor.ts`'s `applyProgress`)
|
|
959
973
|
* is stamped 'error' and its height is recorded as processed, same as
|
|
@@ -1029,4 +1043,4 @@ declare function recordLiveProgress(db: Kysely<Database>, name: string, lastProc
|
|
|
1029
1043
|
* forward write between the rewind and the fork block's reprocess. Do not
|
|
1030
1044
|
* call this from the live catch-up path. */
|
|
1031
1045
|
declare function rewindLiveProgress(db: Kysely<Database>, name: string, lastProcessedBlock: number): Promise<void>;
|
|
1032
|
-
export { updateSubgraphStatus, updateSubgraphHandlerPath, updateSubgraphExpiry, rewindLiveProgress,
|
|
1046
|
+
export { updateSubgraphStatus, updateSubgraphHandlerPath, updateSubgraphExpiry, rewindLiveProgress, registerSubgraph, recordSubgraphProcessed, recordLiveProgress, recordLiveError, pgSchemaNameFor, pgSchemaName, localSubgraphAccountId, listSubgraphs, getSubgraph, deleteSubgraph };
|
|
@@ -139,13 +139,6 @@ async function updateSubgraphStatus(db, name, status, lastProcessedBlock) {
|
|
|
139
139
|
updated_at: new Date
|
|
140
140
|
}).where("name", "=", name).execute();
|
|
141
141
|
}
|
|
142
|
-
async function pauseSubgraph(db, name, accountId) {
|
|
143
|
-
await db.updateTable("subgraphs").set({ status: "paused", updated_at: new Date }).where("name", "=", name).where("account_id", "=", accountId).where("status", "in", ["active", "reindexing"]).execute();
|
|
144
|
-
}
|
|
145
|
-
async function resumePausedSubgraphs(db, accountId) {
|
|
146
|
-
const res = await db.updateTable("subgraphs").set({ status: "active", updated_at: new Date }).where("account_id", "=", accountId).where("status", "=", "paused").executeTakeFirst();
|
|
147
|
-
return Number(res.numUpdatedRows ?? 0);
|
|
148
|
-
}
|
|
149
142
|
async function recordLiveError(db, name, blockHeight) {
|
|
150
143
|
const result = await db.updateTable("subgraphs").set({
|
|
151
144
|
status: "error",
|
|
@@ -208,19 +201,17 @@ export {
|
|
|
208
201
|
updateSubgraphHandlerPath,
|
|
209
202
|
updateSubgraphExpiry,
|
|
210
203
|
rewindLiveProgress,
|
|
211
|
-
resumePausedSubgraphs,
|
|
212
204
|
registerSubgraph,
|
|
213
205
|
recordSubgraphProcessed,
|
|
214
206
|
recordLiveProgress,
|
|
215
207
|
recordLiveError,
|
|
216
208
|
pgSchemaNameFor,
|
|
217
209
|
pgSchemaName,
|
|
218
|
-
pauseSubgraph,
|
|
219
210
|
localSubgraphAccountId,
|
|
220
211
|
listSubgraphs,
|
|
221
212
|
getSubgraph,
|
|
222
213
|
deleteSubgraph
|
|
223
214
|
};
|
|
224
215
|
|
|
225
|
-
//# debugId=
|
|
216
|
+
//# debugId=EEA4A11D75AFDFDE64756E2164756E21
|
|
226
217
|
//# sourceMappingURL=subgraphs.js.map
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"/**\n * Instance modes for the Secondlayer platform.\n *\n * - `oss`: self-hosted, single-tenant. No auth middleware, no platform routes\n * (projects, admin). Everything runs against a single `DATABASE_URL`.\n * Intended for `docker compose up`.\n *\n * - `platform`: the metered archive deployment. Magic-link auth, API keys,\n * accounts, credits, and metered `/v1` reads (Index + Streams + subgraphs)\n * against a single shared DB. No paid tier ladder — one metered `free`\n * tier plus first-party internal service credentials.\n */\n\nexport type InstanceMode = \"oss\" | \"platform\";\n\n/** What the operator wrote in the env — `archive` is the honest name for the\n * metered public-archive deployment and aliases `platform` behaviorally. */\nexport type DeclaredInstanceMode = InstanceMode | \"archive\";\n\nconst VALID_MODES: readonly DeclaredInstanceMode[] = [\n\t\"oss\",\n\t\"platform\",\n\t\"archive\",\n];\n\nfunction declaredMode(): DeclaredInstanceMode {\n\tconst raw = process.env.INSTANCE_MODE?.trim().toLowerCase();\n\tif (raw && (VALID_MODES as readonly string[]).includes(raw)) {\n\t\treturn raw as DeclaredInstanceMode;\n\t}\n\treturn \"oss\";\n}\n\n/**\n * Resolve the active instance mode from `process.env.INSTANCE_MODE`.\n * Defaults to `\"oss\"` — the safest default for self-hosters who deploy\n * without setting the variable. `archive` normalizes to `platform` here so\n * every behavioral branch stays a two-way choice; use\n * `getDeclaredInstanceMode()` for display surfaces.\n */\nexport function getInstanceMode(): InstanceMode {\n\tconst declared = declaredMode();\n\treturn declared === \"archive\" ? \"platform\" : declared;\n}\n\n/** The mode as declared in the env, for status/identity surfaces. */\nexport function getDeclaredInstanceMode(): DeclaredInstanceMode {\n\treturn declaredMode();\n}\n\n/**\n * True when public reads are credit-metered (the free window, retention, and\n * credits gates arm). Platform/archive deployments meter by default;\n * self-host never does unless the operator explicitly sets\n * `METERED_READS=true`. `METERED_READS=false` disarms a metered deployment.\n */\nexport function isMeteredReads(): boolean {\n\tconst override = process.env.METERED_READS?.trim().toLowerCase();\n\tif (override === \"true\") return true;\n\tif (override === \"false\") return false;\n\treturn getInstanceMode() === \"platform\";\n}\n\n/** True when the active mode is `\"platform\"` (shared multi-tenant). */\nexport function isPlatformMode(): boolean {\n\treturn getInstanceMode() === \"platform\";\n}\n\n/** True when the active mode is `\"oss\"` (self-hosted). */\nexport function isOssMode(): boolean {\n\treturn getInstanceMode() === \"oss\";\n}\n",
|
|
6
6
|
"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",
|
|
7
|
-
"import { type Kysely, sql } from \"kysely\";\nimport { isPlatformMode } from \"../../mode.ts\";\nimport { jsonb } from \"../jsonb.ts\";\nimport type { Database, Subgraph } from \"../types.ts\";\n\n/**\n * Convert a subgraph name to its PostgreSQL schema name (legacy form).\n * Pre shared-rip every tenant DB had its own schema namespace so disambiguation\n * was implicit. Kept for oss mode (single-tenant) and legacy-row fallback.\n * Platform-mode deploys use `pgSchemaNameFor(accountId, name)`.\n */\nexport function pgSchemaName(subgraphName: string): string {\n\tconst safeName = subgraphName.replace(/-/g, \"_\");\n\treturn `subgraph_${safeName}`;\n}\n\n/** OSS writes empty account_id — name is the local unique key. */\nexport function localSubgraphAccountId(accountId?: string): string {\n\tif (!isPlatformMode()) return \"\";\n\treturn accountId ?? \"\";\n}\n\n/**\n * Account-scoped schema name. Matches migration 0028's rename pattern:\n * subgraph_{first8charsOfAccountId, dashes-as-underscores}_{name}\n * Empty accountId falls back to legacy form (oss mode).\n */\nexport function pgSchemaNameFor(\n\taccountId: string,\n\tsubgraphName: string,\n): string {\n\tif (!accountId) return pgSchemaName(subgraphName);\n\tconst accountPrefix = accountId.slice(0, 8).replace(/-/g, \"_\");\n\tconst safeName = subgraphName.replace(/-/g, \"_\");\n\treturn `subgraph_${accountPrefix}_${safeName}`;\n}\n\nexport async function registerSubgraph(\n\tdb: Kysely<Database>,\n\tdata: {\n\t\tname: string;\n\t\tversion: string;\n\t\tdefinition: Record<string, unknown>;\n\t\tschemaHash: string;\n\t\thandlerPath: string;\n\t\tapiKeyId?: string;\n\t\taccountId?: string;\n\t\tschemaName?: string;\n\t\tstartBlock?: number;\n\t\thandlerCode?: string;\n\t\tsourceCode?: string;\n\t},\n): Promise<Subgraph> {\n\tconst accountId = localSubgraphAccountId(data.accountId);\n\tconst values = {\n\t\tname: data.name,\n\t\tversion: data.version,\n\t\tdefinition: jsonb<Record<string, unknown>>(data.definition),\n\t\tschema_hash: data.schemaHash,\n\t\thandler_path: data.handlerPath,\n\t\taccount_id: accountId,\n\t\thandler_code: data.handlerCode ?? null,\n\t\tsource_code: data.sourceCode ?? null,\n\t\tschema_name: data.schemaName ?? null,\n\t\tstart_block: data.startBlock ?? 0,\n\t};\n\tconst updateSet = {\n\t\tversion: data.version,\n\t\tdefinition: jsonb<Record<string, unknown>>(data.definition),\n\t\tschema_hash: data.schemaHash,\n\t\thandler_path: data.handlerPath,\n\t\thandler_code: data.handlerCode ?? null,\n\t\tsource_code: data.sourceCode ?? null,\n\t\tschema_name: data.schemaName ?? null,\n\t\tstart_block: data.startBlock ?? 0,\n\t\tupdated_at: new Date(),\n\t};\n\n\t// OSS: name is unique. Upsert by name so leftover rows with a non-empty\n\t// account_id (pre-local-namespace deploys) don't insert a second row.\n\tif (!isPlatformMode()) {\n\t\tconst existing = await db\n\t\t\t.selectFrom(\"subgraphs\")\n\t\t\t.select(\"id\")\n\t\t\t.where(\"name\", \"=\", data.name)\n\t\t\t.executeTakeFirst();\n\t\tif (existing) {\n\t\t\treturn await db\n\t\t\t\t.updateTable(\"subgraphs\")\n\t\t\t\t.set({ ...updateSet, account_id: \"\" })\n\t\t\t\t.where(\"id\", \"=\", existing.id)\n\t\t\t\t.returningAll()\n\t\t\t\t.executeTakeFirstOrThrow();\n\t\t}\n\t\treturn await db\n\t\t\t.insertInto(\"subgraphs\")\n\t\t\t.values(values)\n\t\t\t.returningAll()\n\t\t\t.executeTakeFirstOrThrow();\n\t}\n\n\treturn await db\n\t\t.insertInto(\"subgraphs\")\n\t\t.values(values)\n\t\t.onConflict((oc) =>\n\t\t\toc.columns([\"name\", \"account_id\"]).doUpdateSet(updateSet),\n\t\t)\n\t\t.returningAll()\n\t\t.executeTakeFirstOrThrow();\n}\n\nexport async function getSubgraph(\n\tdb: Kysely<Database>,\n\tname: string,\n\taccountId?: string,\n): Promise<Subgraph | null> {\n\tlet query = db.selectFrom(\"subgraphs\").selectAll().where(\"name\", \"=\", name);\n\n\tif (isPlatformMode() && accountId !== undefined) {\n\t\tquery = query.where(\"account_id\", \"=\", accountId);\n\t}\n\n\treturn (await query.executeTakeFirst()) ?? null;\n}\n\nexport async function listSubgraphs(\n\tdb: Kysely<Database>,\n\taccountId?: string,\n): Promise<Subgraph[]> {\n\tlet query = db.selectFrom(\"subgraphs\").selectAll();\n\tif (isPlatformMode() && accountId !== undefined) {\n\t\tquery = query.where(\"account_id\", \"=\", accountId);\n\t}\n\treturn query.execute();\n}\n\nexport async function updateSubgraphStatus(\n\tdb: Kysely<Database>,\n\tname: string,\n\tstatus: string,\n\tlastProcessedBlock?: number,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\tstatus,\n\t\t\t...(lastProcessedBlock !== undefined\n\t\t\t\t? { last_processed_block: lastProcessedBlock }\n\t\t\t\t: {}),\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n\n/** Account-scoped pause. Only active/reindexing rows flip; name-only\n * {@link updateSubgraphStatus} is unsafe on platform (name, account_id). */\nexport async function pauseSubgraph(\n\tdb: Kysely<Database>,\n\tname: string,\n\taccountId: string,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({ status: \"paused\", updated_at: new Date() })\n\t\t.where(\"name\", \"=\", name)\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"status\", \"in\", [\"active\", \"reindexing\"])\n\t\t.execute();\n}\n\n/** Resume every paused subgraph for an account (claim / Stripe top-up). */\nexport async function resumePausedSubgraphs(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<number> {\n\tconst res = await db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({ status: \"active\", updated_at: new Date() })\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"status\", \"=\", \"paused\")\n\t\t.executeTakeFirst();\n\treturn Number(res.numUpdatedRows ?? 0);\n}\n\n/** Live-walk ERROR write (f069): a block whose handlers ALL failed\n * (`processed === 0 && errors > 0`, `block-processor.ts`'s `applyProgress`)\n * is stamped 'error' and its height is recorded as processed, same as\n * `updateSubgraphStatus(db, name, \"error\", blockHeight)` — except the\n * cursor half of that write now goes through the same conditional `<`\n * guard as {@link recordLiveProgress}. Marking a subgraph 'error' is not\n * itself replay-sensitive, but it shares the `last_processed_block` column\n * with the replay guard: an unconditional write here could regress the\n * cursor a racing (successful) writer already advanced past, which is\n * exactly the regress-then-re-walk loop this guard exists to close. In\n * practice `ctx.rollbackTo` (`runner.ts`) means an all-failed block never\n * flushes writes, so a lost race here is always a silent no-op, never a\n * case that needs `CursorRaceLostError`-style tx abort. Returns whether\n * the write applied. Live path only — reindex/backfill's error stamping\n * goes through {@link updateSubgraphStatus} unconditionally, as before. */\nexport async function recordLiveError(\n\tdb: Kysely<Database>,\n\tname: string,\n\tblockHeight: number,\n): Promise<boolean> {\n\tconst result = await db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\tstatus: \"error\",\n\t\t\tlast_processed_block: blockHeight,\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.where(\"last_processed_block\", \"<\", blockHeight)\n\t\t.executeTakeFirst();\n\treturn Number(result.numUpdatedRows ?? 0n) > 0;\n}\n\nexport async function recordSubgraphProcessed(\n\tdb: Kysely<Database>,\n\tname: string,\n\tprocessed: number,\n\terrors: number,\n\tlastError?: string,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\ttotal_processed: sql`total_processed + ${processed}`,\n\t\t\ttotal_errors: sql`total_errors + ${errors}`,\n\t\t\t...(lastError\n\t\t\t\t? { last_error: lastError, last_error_at: new Date() }\n\t\t\t\t: {}),\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n\nexport async function updateSubgraphHandlerPath(\n\tdb: Kysely<Database>,\n\tname: string,\n\thandlerPath: string,\n\topts?: { handlerCode?: string; sourceCode?: string },\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\thandler_path: handlerPath,\n\t\t\t...(opts?.handlerCode != null ? { handler_code: opts.handlerCode } : {}),\n\t\t\t...(opts?.sourceCode != null ? { source_code: opts.sourceCode } : {}),\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n\nexport async function deleteSubgraph(\n\tdb: Kysely<Database>,\n\tname: string,\n\taccountId?: string,\n): Promise<Subgraph | null> {\n\tconst subgraph = await getSubgraph(db, name, accountId);\n\tif (!subgraph) return null;\n\n\t// Use stored schema_name if available, otherwise compute\n\tconst schemaName = subgraph.schema_name ?? pgSchemaName(name);\n\n\t// Cascade to webhooks: a webhook pointing at a deleted\n\t// subgraph + table will throw `relation does not exist` on every\n\t// subsequent emission. Pause active subs and purge any pending outbox\n\t// rows so receivers don't get phantom replays. We don't delete the\n\t// webhooks themselves — operators may want to repoint them at a\n\t// resurrected subgraph; we just stop them firing.\n\tawait db\n\t\t.updateTable(\"webhooks\")\n\t\t.set({\n\t\t\tstatus: \"paused\",\n\t\t\tlast_error: `Subgraph \"${name}\" deleted; webhook auto-paused.`,\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"subgraph_name\", \"=\", name)\n\t\t.execute();\n\tawait db\n\t\t.deleteFrom(\"webhook_outbox\")\n\t\t.where(\"status\", \"=\", \"pending\")\n\t\t.where(\"webhook_id\", \"in\", (qb) =>\n\t\t\tqb.selectFrom(\"webhooks\").select(\"id\").where(\"subgraph_name\", \"=\", name),\n\t\t)\n\t\t.execute();\n\n\t// Drop the subgraph's schema (CASCADE drops all tables within).\n\tawait sql`DROP SCHEMA IF EXISTS ${sql.raw(`\"${schemaName}\"`)} CASCADE`.execute(\n\t\tdb,\n\t);\n\n\t// Remove from registry\n\tawait db.deleteFrom(\"subgraphs\").where(\"id\", \"=\", subgraph.id).execute();\n\n\treturn subgraph;\n}\n\n/** Set or clear a paid subgraph's expiry (NULL = no expiry, e.g. on claim). */\nexport async function updateSubgraphExpiry(\n\tdb: Kysely<Database>,\n\tname: string,\n\taccountId: string,\n\texpiresAt: Date | null,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({ expires_at: expiresAt })\n\t\t.where(\"name\", \"=\", name)\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.execute();\n}\n\n/** Live-walk progress write: advances the cursor and PROMOTES toward\n * 'active' (deploying/error → active keeps reorg eligibility, reorg.ts gates\n * on it) but never overwrites an explicit 'reindexing' park — unconditional\n * status stamping let catch-up flap a parked subgraph back into its own path\n * per block, fighting the queued reindex op.\n *\n * `last_processed_block` is now written CONDITIONALLY — `WHERE\n * last_processed_block < lastProcessedBlock`, mirroring\n * `advanceOperationCursor`'s (`subgraph-operations.ts`) comparison shape —\n * and returns whether THIS call actually advanced it. This used to be\n * unconditional by design, on the premise that the only two writers able to\n * advance/rewind a given subgraph's cursor concurrently (the catch-up walk\n * and the reorg handler) serialize on an in-process per-subgraph lock +\n * reorg epoch guard (`packages/subgraphs/src/runtime/catchup.ts`,\n * `subgraphBlockLockHeld` / `reorgEpoch`; f057). That guard is in-process\n * only. The f068 investigation\n * (`docs/internal/audits/asset-holdings-unreproducible-balances-f068.md`)\n * found a cross-process sequence it does not cover: a catch-up leader that\n * loses its advisory-lock connection mid-walk keeps writing (leadership is\n * checked only at walk entry, not per-iteration) while a new leader takes\n * over and walks the same range — both commit increments for overlapping\n * heights, and every regressed cursor write from the laggard re-triggers a\n * full re-walk, growing per-height application without bound. The\n * conditional advance here (paired with the fast-path replay guard armed on\n * the live path in `block-processor.ts`) is now the cross-process\n * guarantee: a block at/below the current cursor can never re-advance it,\n * so a laggard's commits can no longer regress-then-retrigger.\n *\n * This conditionality is why the reorg rewind can no longer go through this\n * function — a rewind's whole point is to move the cursor *backward*, which\n * the `<` guard would silently refuse. Reorg mode calls\n * {@link rewindLiveProgress} instead, which keeps the old unconditional\n * semantics and is safe specifically because the reorg path takes a\n * transaction-scoped advisory lock (`reorg.ts`) other writers can't cross. */\nexport async function recordLiveProgress(\n\tdb: Kysely<Database>,\n\tname: string,\n\tlastProcessedBlock: number,\n): Promise<boolean> {\n\tconst result = await db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\tlast_processed_block: lastProcessedBlock,\n\t\t\tstatus: sql`CASE WHEN status = 'reindexing' THEN status ELSE 'active' END`,\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.where(\"last_processed_block\", \"<\", lastProcessedBlock)\n\t\t.executeTakeFirst();\n\treturn Number(result.numUpdatedRows ?? 0n) > 0;\n}\n\n/** Reorg-rewind progress write: the OLD unconditional `recordLiveProgress`\n * semantics, verbatim — moves `last_processed_block` to the fork height\n * regardless of its current value, because that is by definition a\n * backward move the conditional `<` guard in `recordLiveProgress` would\n * refuse. Same status-promotion CASE (never unparks an explicit\n * 'reindexing').\n *\n * Callers: exclusively the subgraph-reorg path\n * (`packages/subgraphs/src/runtime/reorg.ts`, via `block-processor.ts`'s\n * `reorgRewind` mode), which is safe from the cross-process race this\n * function reintroduces because it holds a transaction-scoped Postgres\n * advisory lock (`pg_advisory_xact_lock`) for the whole\n * delete+reprocess+rewind sequence — no other writer can interleave a\n * forward write between the rewind and the fork block's reprocess. Do not\n * call this from the live catch-up path. */\nexport async function rewindLiveProgress(\n\tdb: Kysely<Database>,\n\tname: string,\n\tlastProcessedBlock: number,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\tlast_processed_block: lastProcessedBlock,\n\t\t\tstatus: sql`CASE WHEN status = 'reindexing' THEN status ELSE 'active' END`,\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n"
|
|
7
|
+
"import { type Kysely, sql } from \"kysely\";\nimport { isPlatformMode } from \"../../mode.ts\";\nimport { jsonb } from \"../jsonb.ts\";\nimport type { Database, Subgraph } from \"../types.ts\";\n\n/**\n * Convert a subgraph name to its PostgreSQL schema name (legacy form).\n * Pre shared-rip every tenant DB had its own schema namespace so disambiguation\n * was implicit. Kept for oss mode (single-tenant) and legacy-row fallback.\n * Platform-mode deploys use `pgSchemaNameFor(accountId, name)`.\n */\nexport function pgSchemaName(subgraphName: string): string {\n\tconst safeName = subgraphName.replace(/-/g, \"_\");\n\treturn `subgraph_${safeName}`;\n}\n\n/** OSS writes empty account_id — name is the local unique key. */\nexport function localSubgraphAccountId(accountId?: string): string {\n\tif (!isPlatformMode()) return \"\";\n\treturn accountId ?? \"\";\n}\n\n/**\n * Account-scoped schema name. Matches migration 0028's rename pattern:\n * subgraph_{first8charsOfAccountId, dashes-as-underscores}_{name}\n * Empty accountId falls back to legacy form (oss mode).\n */\nexport function pgSchemaNameFor(\n\taccountId: string,\n\tsubgraphName: string,\n): string {\n\tif (!accountId) return pgSchemaName(subgraphName);\n\tconst accountPrefix = accountId.slice(0, 8).replace(/-/g, \"_\");\n\tconst safeName = subgraphName.replace(/-/g, \"_\");\n\treturn `subgraph_${accountPrefix}_${safeName}`;\n}\n\nexport async function registerSubgraph(\n\tdb: Kysely<Database>,\n\tdata: {\n\t\tname: string;\n\t\tversion: string;\n\t\tdefinition: Record<string, unknown>;\n\t\tschemaHash: string;\n\t\thandlerPath: string;\n\t\tapiKeyId?: string;\n\t\taccountId?: string;\n\t\tschemaName?: string;\n\t\tstartBlock?: number;\n\t\thandlerCode?: string;\n\t\tsourceCode?: string;\n\t},\n): Promise<Subgraph> {\n\tconst accountId = localSubgraphAccountId(data.accountId);\n\tconst values = {\n\t\tname: data.name,\n\t\tversion: data.version,\n\t\tdefinition: jsonb<Record<string, unknown>>(data.definition),\n\t\tschema_hash: data.schemaHash,\n\t\thandler_path: data.handlerPath,\n\t\taccount_id: accountId,\n\t\thandler_code: data.handlerCode ?? null,\n\t\tsource_code: data.sourceCode ?? null,\n\t\tschema_name: data.schemaName ?? null,\n\t\tstart_block: data.startBlock ?? 0,\n\t};\n\tconst updateSet = {\n\t\tversion: data.version,\n\t\tdefinition: jsonb<Record<string, unknown>>(data.definition),\n\t\tschema_hash: data.schemaHash,\n\t\thandler_path: data.handlerPath,\n\t\thandler_code: data.handlerCode ?? null,\n\t\tsource_code: data.sourceCode ?? null,\n\t\tschema_name: data.schemaName ?? null,\n\t\tstart_block: data.startBlock ?? 0,\n\t\tupdated_at: new Date(),\n\t};\n\n\t// OSS: name is unique. Upsert by name so leftover rows with a non-empty\n\t// account_id (pre-local-namespace deploys) don't insert a second row.\n\tif (!isPlatformMode()) {\n\t\tconst existing = await db\n\t\t\t.selectFrom(\"subgraphs\")\n\t\t\t.select(\"id\")\n\t\t\t.where(\"name\", \"=\", data.name)\n\t\t\t.executeTakeFirst();\n\t\tif (existing) {\n\t\t\treturn await db\n\t\t\t\t.updateTable(\"subgraphs\")\n\t\t\t\t.set({ ...updateSet, account_id: \"\" })\n\t\t\t\t.where(\"id\", \"=\", existing.id)\n\t\t\t\t.returningAll()\n\t\t\t\t.executeTakeFirstOrThrow();\n\t\t}\n\t\treturn await db\n\t\t\t.insertInto(\"subgraphs\")\n\t\t\t.values(values)\n\t\t\t.returningAll()\n\t\t\t.executeTakeFirstOrThrow();\n\t}\n\n\treturn await db\n\t\t.insertInto(\"subgraphs\")\n\t\t.values(values)\n\t\t.onConflict((oc) =>\n\t\t\toc.columns([\"name\", \"account_id\"]).doUpdateSet(updateSet),\n\t\t)\n\t\t.returningAll()\n\t\t.executeTakeFirstOrThrow();\n}\n\nexport async function getSubgraph(\n\tdb: Kysely<Database>,\n\tname: string,\n\taccountId?: string,\n): Promise<Subgraph | null> {\n\tlet query = db.selectFrom(\"subgraphs\").selectAll().where(\"name\", \"=\", name);\n\n\tif (isPlatformMode() && accountId !== undefined) {\n\t\tquery = query.where(\"account_id\", \"=\", accountId);\n\t}\n\n\treturn (await query.executeTakeFirst()) ?? null;\n}\n\nexport async function listSubgraphs(\n\tdb: Kysely<Database>,\n\taccountId?: string,\n): Promise<Subgraph[]> {\n\tlet query = db.selectFrom(\"subgraphs\").selectAll();\n\tif (isPlatformMode() && accountId !== undefined) {\n\t\tquery = query.where(\"account_id\", \"=\", accountId);\n\t}\n\treturn query.execute();\n}\n\nexport async function updateSubgraphStatus(\n\tdb: Kysely<Database>,\n\tname: string,\n\tstatus: string,\n\tlastProcessedBlock?: number,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\tstatus,\n\t\t\t...(lastProcessedBlock !== undefined\n\t\t\t\t? { last_processed_block: lastProcessedBlock }\n\t\t\t\t: {}),\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n\n/** Live-walk ERROR write (f069): a block whose handlers ALL failed\n * (`processed === 0 && errors > 0`, `block-processor.ts`'s `applyProgress`)\n * is stamped 'error' and its height is recorded as processed, same as\n * `updateSubgraphStatus(db, name, \"error\", blockHeight)` — except the\n * cursor half of that write now goes through the same conditional `<`\n * guard as {@link recordLiveProgress}. Marking a subgraph 'error' is not\n * itself replay-sensitive, but it shares the `last_processed_block` column\n * with the replay guard: an unconditional write here could regress the\n * cursor a racing (successful) writer already advanced past, which is\n * exactly the regress-then-re-walk loop this guard exists to close. In\n * practice `ctx.rollbackTo` (`runner.ts`) means an all-failed block never\n * flushes writes, so a lost race here is always a silent no-op, never a\n * case that needs `CursorRaceLostError`-style tx abort. Returns whether\n * the write applied. Live path only — reindex/backfill's error stamping\n * goes through {@link updateSubgraphStatus} unconditionally, as before. */\nexport async function recordLiveError(\n\tdb: Kysely<Database>,\n\tname: string,\n\tblockHeight: number,\n): Promise<boolean> {\n\tconst result = await db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\tstatus: \"error\",\n\t\t\tlast_processed_block: blockHeight,\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.where(\"last_processed_block\", \"<\", blockHeight)\n\t\t.executeTakeFirst();\n\treturn Number(result.numUpdatedRows ?? 0n) > 0;\n}\n\nexport async function recordSubgraphProcessed(\n\tdb: Kysely<Database>,\n\tname: string,\n\tprocessed: number,\n\terrors: number,\n\tlastError?: string,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\ttotal_processed: sql`total_processed + ${processed}`,\n\t\t\ttotal_errors: sql`total_errors + ${errors}`,\n\t\t\t...(lastError\n\t\t\t\t? { last_error: lastError, last_error_at: new Date() }\n\t\t\t\t: {}),\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n\nexport async function updateSubgraphHandlerPath(\n\tdb: Kysely<Database>,\n\tname: string,\n\thandlerPath: string,\n\topts?: { handlerCode?: string; sourceCode?: string },\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\thandler_path: handlerPath,\n\t\t\t...(opts?.handlerCode != null ? { handler_code: opts.handlerCode } : {}),\n\t\t\t...(opts?.sourceCode != null ? { source_code: opts.sourceCode } : {}),\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n\nexport async function deleteSubgraph(\n\tdb: Kysely<Database>,\n\tname: string,\n\taccountId?: string,\n): Promise<Subgraph | null> {\n\tconst subgraph = await getSubgraph(db, name, accountId);\n\tif (!subgraph) return null;\n\n\t// Use stored schema_name if available, otherwise compute\n\tconst schemaName = subgraph.schema_name ?? pgSchemaName(name);\n\n\t// Cascade to webhooks: a webhook pointing at a deleted\n\t// subgraph + table will throw `relation does not exist` on every\n\t// subsequent emission. Pause active subs and purge any pending outbox\n\t// rows so receivers don't get phantom replays. We don't delete the\n\t// webhooks themselves — operators may want to repoint them at a\n\t// resurrected subgraph; we just stop them firing.\n\tawait db\n\t\t.updateTable(\"webhooks\")\n\t\t.set({\n\t\t\tstatus: \"paused\",\n\t\t\tlast_error: `Subgraph \"${name}\" deleted; webhook auto-paused.`,\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"subgraph_name\", \"=\", name)\n\t\t.execute();\n\tawait db\n\t\t.deleteFrom(\"webhook_outbox\")\n\t\t.where(\"status\", \"=\", \"pending\")\n\t\t.where(\"webhook_id\", \"in\", (qb) =>\n\t\t\tqb.selectFrom(\"webhooks\").select(\"id\").where(\"subgraph_name\", \"=\", name),\n\t\t)\n\t\t.execute();\n\n\t// Drop the subgraph's schema (CASCADE drops all tables within).\n\tawait sql`DROP SCHEMA IF EXISTS ${sql.raw(`\"${schemaName}\"`)} CASCADE`.execute(\n\t\tdb,\n\t);\n\n\t// Remove from registry\n\tawait db.deleteFrom(\"subgraphs\").where(\"id\", \"=\", subgraph.id).execute();\n\n\treturn subgraph;\n}\n\n/** Set or clear a paid subgraph's expiry (NULL = no expiry, e.g. on claim). */\nexport async function updateSubgraphExpiry(\n\tdb: Kysely<Database>,\n\tname: string,\n\taccountId: string,\n\texpiresAt: Date | null,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({ expires_at: expiresAt })\n\t\t.where(\"name\", \"=\", name)\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.execute();\n}\n\n/** Live-walk progress write: advances the cursor and PROMOTES toward\n * 'active' (deploying/error → active keeps reorg eligibility, reorg.ts gates\n * on it) but never overwrites an explicit 'reindexing' park — unconditional\n * status stamping let catch-up flap a parked subgraph back into its own path\n * per block, fighting the queued reindex op.\n *\n * `last_processed_block` is now written CONDITIONALLY — `WHERE\n * last_processed_block < lastProcessedBlock`, mirroring\n * `advanceOperationCursor`'s (`subgraph-operations.ts`) comparison shape —\n * and returns whether THIS call actually advanced it. This used to be\n * unconditional by design, on the premise that the only two writers able to\n * advance/rewind a given subgraph's cursor concurrently (the catch-up walk\n * and the reorg handler) serialize on an in-process per-subgraph lock +\n * reorg epoch guard (`packages/subgraphs/src/runtime/catchup.ts`,\n * `subgraphBlockLockHeld` / `reorgEpoch`; f057). That guard is in-process\n * only. The f068 investigation\n * (`docs/internal/audits/asset-holdings-unreproducible-balances-f068.md`)\n * found a cross-process sequence it does not cover: a catch-up leader that\n * loses its advisory-lock connection mid-walk keeps writing (leadership is\n * checked only at walk entry, not per-iteration) while a new leader takes\n * over and walks the same range — both commit increments for overlapping\n * heights, and every regressed cursor write from the laggard re-triggers a\n * full re-walk, growing per-height application without bound. The\n * conditional advance here (paired with the fast-path replay guard armed on\n * the live path in `block-processor.ts`) is now the cross-process\n * guarantee: a block at/below the current cursor can never re-advance it,\n * so a laggard's commits can no longer regress-then-retrigger.\n *\n * This conditionality is why the reorg rewind can no longer go through this\n * function — a rewind's whole point is to move the cursor *backward*, which\n * the `<` guard would silently refuse. Reorg mode calls\n * {@link rewindLiveProgress} instead, which keeps the old unconditional\n * semantics and is safe specifically because the reorg path takes a\n * transaction-scoped advisory lock (`reorg.ts`) other writers can't cross. */\nexport async function recordLiveProgress(\n\tdb: Kysely<Database>,\n\tname: string,\n\tlastProcessedBlock: number,\n): Promise<boolean> {\n\tconst result = await db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\tlast_processed_block: lastProcessedBlock,\n\t\t\tstatus: sql`CASE WHEN status = 'reindexing' THEN status ELSE 'active' END`,\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.where(\"last_processed_block\", \"<\", lastProcessedBlock)\n\t\t.executeTakeFirst();\n\treturn Number(result.numUpdatedRows ?? 0n) > 0;\n}\n\n/** Reorg-rewind progress write: the OLD unconditional `recordLiveProgress`\n * semantics, verbatim — moves `last_processed_block` to the fork height\n * regardless of its current value, because that is by definition a\n * backward move the conditional `<` guard in `recordLiveProgress` would\n * refuse. Same status-promotion CASE (never unparks an explicit\n * 'reindexing').\n *\n * Callers: exclusively the subgraph-reorg path\n * (`packages/subgraphs/src/runtime/reorg.ts`, via `block-processor.ts`'s\n * `reorgRewind` mode), which is safe from the cross-process race this\n * function reintroduces because it holds a transaction-scoped Postgres\n * advisory lock (`pg_advisory_xact_lock`) for the whole\n * delete+reprocess+rewind sequence — no other writer can interleave a\n * forward write between the rewind and the fork block's reprocess. Do not\n * call this from the live catch-up path. */\nexport async function rewindLiveProgress(\n\tdb: Kysely<Database>,\n\tname: string,\n\tlastProcessedBlock: number,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\tlast_processed_block: lastProcessedBlock,\n\t\t\tstatus: sql`CASE WHEN status = 'reindexing' THEN status ELSE 'active' END`,\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n"
|
|
8
8
|
],
|
|
9
|
-
"mappings": "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
|
|
10
|
-
"debugId": "
|
|
9
|
+
"mappings": "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",
|
|
10
|
+
"debugId": "EEA4A11D75AFDFDE64756E2164756E21",
|
|
11
11
|
"names": []
|
|
12
12
|
}
|