@secondlayer/shared 6.0.0 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/db/index.d.ts +45 -1
- package/dist/src/db/queries/account-spend-caps.d.ts +44 -0
- package/dist/src/db/queries/account-usage.d.ts +44 -0
- package/dist/src/db/queries/accounts.d.ts +44 -0
- package/dist/src/db/queries/chain-reorgs.d.ts +532 -0
- package/dist/src/db/queries/chain-reorgs.js +322 -0
- package/dist/src/db/queries/chain-reorgs.js.map +14 -0
- package/dist/src/db/queries/integrity.d.ts +44 -0
- package/dist/src/db/queries/projects.d.ts +44 -0
- package/dist/src/db/queries/provisioning-audit.d.ts +44 -0
- package/dist/src/db/queries/subgraph-gaps.d.ts +44 -0
- package/dist/src/db/queries/subgraph-operations.d.ts +44 -0
- package/dist/src/db/queries/subgraphs.d.ts +44 -0
- package/dist/src/db/queries/subscriptions.d.ts +44 -0
- package/dist/src/db/queries/tenant-compute-addons.d.ts +44 -0
- package/dist/src/db/queries/tenants.d.ts +44 -0
- package/dist/src/db/queries/usage.d.ts +47 -1
- package/dist/src/db/queries/usage.js +20 -1
- package/dist/src/db/queries/usage.js.map +3 -3
- package/dist/src/db/schema.d.ts +45 -1
- package/dist/src/index.d.ts +45 -1
- package/dist/src/node/local-client.d.ts +44 -0
- package/dist/src/types.d.ts +2 -1
- package/migrations/0065_l2_decoded_events.ts +50 -0
- package/migrations/0066_public_l2_decoded_events.ts +83 -0
- package/migrations/0067_product_usage_counters.ts +18 -0
- package/migrations/0068_chain_reorgs_and_burn_block_hash.ts +48 -0
- package/package.json +5 -1
|
@@ -0,0 +1,322 @@
|
|
|
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/env.ts
|
|
18
|
+
import { z } from "zod/v4";
|
|
19
|
+
var networksSchema = z.string().transform((val) => {
|
|
20
|
+
const networks = val.split(",").map((n) => n.trim()).filter(Boolean);
|
|
21
|
+
const valid = ["mainnet", "testnet"];
|
|
22
|
+
for (const n of networks) {
|
|
23
|
+
if (!valid.includes(n)) {
|
|
24
|
+
throw new Error(`Invalid network: ${n}. Must be one of: ${valid.join(", ")}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return networks;
|
|
28
|
+
});
|
|
29
|
+
var envSchema = z.object({
|
|
30
|
+
DATABASE_URL: z.preprocess((val) => typeof val === "string" && val.length === 0 ? undefined : val, z.string().url().optional()),
|
|
31
|
+
SOURCE_DATABASE_URL: z.preprocess((val) => typeof val === "string" && val.length === 0 ? undefined : val, z.string().url().optional()),
|
|
32
|
+
TARGET_DATABASE_URL: z.preprocess((val) => typeof val === "string" && val.length === 0 ? undefined : val, z.string().url().optional()),
|
|
33
|
+
NETWORK: z.enum(["mainnet", "testnet"]).optional(),
|
|
34
|
+
NETWORKS: networksSchema.optional(),
|
|
35
|
+
LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).default("info"),
|
|
36
|
+
NODE_ENV: z.enum(["development", "production", "test"]).default("development")
|
|
37
|
+
});
|
|
38
|
+
var cachedEnv = null;
|
|
39
|
+
function getEnv() {
|
|
40
|
+
if (cachedEnv) {
|
|
41
|
+
return cachedEnv;
|
|
42
|
+
}
|
|
43
|
+
const result = envSchema.safeParse(process.env);
|
|
44
|
+
if (!result.success) {
|
|
45
|
+
console.error("❌ Invalid environment configuration:");
|
|
46
|
+
console.error(z.treeifyError(result.error));
|
|
47
|
+
throw new Error("Invalid environment configuration");
|
|
48
|
+
}
|
|
49
|
+
let enabledNetworks;
|
|
50
|
+
if (result.data.NETWORKS && result.data.NETWORKS.length > 0) {
|
|
51
|
+
enabledNetworks = result.data.NETWORKS;
|
|
52
|
+
} else if (result.data.NETWORK) {
|
|
53
|
+
enabledNetworks = [result.data.NETWORK];
|
|
54
|
+
} else {
|
|
55
|
+
enabledNetworks = ["mainnet"];
|
|
56
|
+
}
|
|
57
|
+
cachedEnv = { ...result.data, enabledNetworks };
|
|
58
|
+
return cachedEnv;
|
|
59
|
+
}
|
|
60
|
+
// src/logger.ts
|
|
61
|
+
var LOG_LEVELS = {
|
|
62
|
+
debug: 0,
|
|
63
|
+
info: 1,
|
|
64
|
+
warn: 2,
|
|
65
|
+
error: 3
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
class Logger {
|
|
69
|
+
_level;
|
|
70
|
+
_isProduction;
|
|
71
|
+
_initialized = false;
|
|
72
|
+
init() {
|
|
73
|
+
if (this._initialized)
|
|
74
|
+
return;
|
|
75
|
+
this._initialized = true;
|
|
76
|
+
try {
|
|
77
|
+
const env = getEnv();
|
|
78
|
+
this._level = env.LOG_LEVEL;
|
|
79
|
+
this._isProduction = env.NODE_ENV === "production";
|
|
80
|
+
} catch {
|
|
81
|
+
this._level = "info";
|
|
82
|
+
this._isProduction = false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
get level() {
|
|
86
|
+
this.init();
|
|
87
|
+
return this._level;
|
|
88
|
+
}
|
|
89
|
+
get isProduction() {
|
|
90
|
+
this.init();
|
|
91
|
+
return this._isProduction;
|
|
92
|
+
}
|
|
93
|
+
shouldLog(level) {
|
|
94
|
+
return LOG_LEVELS[level] >= LOG_LEVELS[this.level];
|
|
95
|
+
}
|
|
96
|
+
formatMessage(level, message, meta) {
|
|
97
|
+
const timestamp = new Date().toISOString();
|
|
98
|
+
if (this.isProduction) {
|
|
99
|
+
return JSON.stringify({
|
|
100
|
+
timestamp,
|
|
101
|
+
level,
|
|
102
|
+
message,
|
|
103
|
+
...meta
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
const metaStr = meta ? ` ${JSON.stringify(meta)}` : "";
|
|
107
|
+
return `[${timestamp}] ${level.toUpperCase()}: ${message}${metaStr}`;
|
|
108
|
+
}
|
|
109
|
+
debug(message, meta) {
|
|
110
|
+
if (this.shouldLog("debug")) {
|
|
111
|
+
console.debug(this.formatMessage("debug", message, meta));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
info(message, meta) {
|
|
115
|
+
if (this.shouldLog("info")) {
|
|
116
|
+
console.info(this.formatMessage("info", message, meta));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
warn(message, meta) {
|
|
120
|
+
if (this.shouldLog("warn")) {
|
|
121
|
+
console.warn(this.formatMessage("warn", message, meta));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
error(message, meta) {
|
|
125
|
+
if (this.shouldLog("error")) {
|
|
126
|
+
console.error(this.formatMessage("error", message, meta));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
var logger = new Logger;
|
|
131
|
+
|
|
132
|
+
// src/db/jsonb.ts
|
|
133
|
+
import { sql } from "kysely";
|
|
134
|
+
function jsonb(value) {
|
|
135
|
+
const escaped = JSON.stringify(value, (_k, v) => typeof v === "bigint" ? v.toString() : v).replace(/'/g, "''");
|
|
136
|
+
return sql`${sql.raw(`'${escaped}'::jsonb`)}`;
|
|
137
|
+
}
|
|
138
|
+
function parseJsonb(value) {
|
|
139
|
+
if (typeof value === "string") {
|
|
140
|
+
try {
|
|
141
|
+
return JSON.parse(value);
|
|
142
|
+
} catch {
|
|
143
|
+
return value;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return value ?? {};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// src/db/index.ts
|
|
150
|
+
import { Kysely } from "kysely";
|
|
151
|
+
import { PostgresJSDialect } from "kysely-postgres-js";
|
|
152
|
+
import postgres from "postgres";
|
|
153
|
+
import { sql as sql2 } from "kysely";
|
|
154
|
+
var DEFAULT_URL = "postgres://postgres:postgres@localhost:5432/secondlayer_dev";
|
|
155
|
+
var pools = new Map;
|
|
156
|
+
function resolveSourceUrl() {
|
|
157
|
+
return process.env.SOURCE_DATABASE_URL || process.env.DATABASE_URL || DEFAULT_URL;
|
|
158
|
+
}
|
|
159
|
+
function resolveTargetUrl() {
|
|
160
|
+
return process.env.TARGET_DATABASE_URL || process.env.DATABASE_URL || DEFAULT_URL;
|
|
161
|
+
}
|
|
162
|
+
function getOrCreatePool(url) {
|
|
163
|
+
const existing = pools.get(url);
|
|
164
|
+
if (existing)
|
|
165
|
+
return existing;
|
|
166
|
+
const host = (() => {
|
|
167
|
+
try {
|
|
168
|
+
return new URL(url).hostname;
|
|
169
|
+
} catch {
|
|
170
|
+
return "";
|
|
171
|
+
}
|
|
172
|
+
})();
|
|
173
|
+
const isLocal = host === "localhost" || host === "127.0.0.1" || !host.includes(".");
|
|
174
|
+
const poolMax = Number.parseInt(process.env.DATABASE_POOL_MAX ?? "20", 10);
|
|
175
|
+
const rawClient = postgres(url, {
|
|
176
|
+
max: poolMax,
|
|
177
|
+
ssl: isLocal ? undefined : {
|
|
178
|
+
rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== "0"
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
const db = new Kysely({
|
|
182
|
+
dialect: new PostgresJSDialect({ postgres: rawClient }),
|
|
183
|
+
log: (event) => {
|
|
184
|
+
if (event.level !== "error")
|
|
185
|
+
return;
|
|
186
|
+
const err = event.error;
|
|
187
|
+
if (err?.code !== "42P10")
|
|
188
|
+
return;
|
|
189
|
+
logger.warn("db.on_conflict_constraint_missing", {
|
|
190
|
+
code: err.code,
|
|
191
|
+
message: err.message,
|
|
192
|
+
sql: event.query.sql,
|
|
193
|
+
params: event.query.parameters
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
const entry = { db, rawClient };
|
|
198
|
+
pools.set(url, entry);
|
|
199
|
+
return entry;
|
|
200
|
+
}
|
|
201
|
+
function getSourceDb() {
|
|
202
|
+
return getOrCreatePool(resolveSourceUrl()).db;
|
|
203
|
+
}
|
|
204
|
+
function getTargetDb() {
|
|
205
|
+
return getOrCreatePool(resolveTargetUrl()).db;
|
|
206
|
+
}
|
|
207
|
+
function getDb(connectionString) {
|
|
208
|
+
if (connectionString)
|
|
209
|
+
return getOrCreatePool(connectionString).db;
|
|
210
|
+
return getTargetDb();
|
|
211
|
+
}
|
|
212
|
+
function getRawClient(role = "target") {
|
|
213
|
+
const url = role === "source" ? resolveSourceUrl() : resolveTargetUrl();
|
|
214
|
+
return getOrCreatePool(url).rawClient;
|
|
215
|
+
}
|
|
216
|
+
async function closeDb() {
|
|
217
|
+
for (const entry of pools.values()) {
|
|
218
|
+
await entry.db.destroy();
|
|
219
|
+
await entry.rawClient.end();
|
|
220
|
+
}
|
|
221
|
+
pools.clear();
|
|
222
|
+
}
|
|
223
|
+
// src/db/queries/chain-reorgs.ts
|
|
224
|
+
function encodeChainReorgCursor(cursor) {
|
|
225
|
+
return `${cursor.block_height}:${cursor.event_index}`;
|
|
226
|
+
}
|
|
227
|
+
function normalizeRow(row) {
|
|
228
|
+
const detectedAt = row.detected_at instanceof Date ? row.detected_at.toISOString() : new Date(row.detected_at).toISOString();
|
|
229
|
+
return {
|
|
230
|
+
id: row.id,
|
|
231
|
+
detected_at: detectedAt,
|
|
232
|
+
fork_point_height: Number(row.fork_point_height),
|
|
233
|
+
old_index_block_hash: row.old_index_block_hash,
|
|
234
|
+
new_index_block_hash: row.new_index_block_hash,
|
|
235
|
+
orphaned_range: {
|
|
236
|
+
from: encodeChainReorgCursor({
|
|
237
|
+
block_height: Number(row.orphaned_from_height),
|
|
238
|
+
event_index: Number(row.orphaned_from_event_index)
|
|
239
|
+
}),
|
|
240
|
+
to: encodeChainReorgCursor({
|
|
241
|
+
block_height: Number(row.orphaned_to_height),
|
|
242
|
+
event_index: Number(row.orphaned_to_event_index)
|
|
243
|
+
})
|
|
244
|
+
},
|
|
245
|
+
new_canonical_tip: encodeChainReorgCursor({
|
|
246
|
+
block_height: Number(row.new_canonical_height),
|
|
247
|
+
event_index: Number(row.new_canonical_event_index)
|
|
248
|
+
})
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
async function insertChainReorg(params) {
|
|
252
|
+
const db = params.db ?? getSourceDb();
|
|
253
|
+
const row = await db.insertInto("chain_reorgs").values({
|
|
254
|
+
fork_point_height: params.forkPointHeight,
|
|
255
|
+
old_index_block_hash: params.oldIndexBlockHash ?? null,
|
|
256
|
+
new_index_block_hash: params.newIndexBlockHash ?? null,
|
|
257
|
+
orphaned_from_height: params.orphanedFrom.block_height,
|
|
258
|
+
orphaned_from_event_index: params.orphanedFrom.event_index,
|
|
259
|
+
orphaned_to_height: params.orphanedTo.block_height,
|
|
260
|
+
orphaned_to_event_index: params.orphanedTo.event_index,
|
|
261
|
+
new_canonical_height: params.newCanonicalTip.block_height,
|
|
262
|
+
new_canonical_event_index: params.newCanonicalTip.event_index
|
|
263
|
+
}).returningAll().executeTakeFirstOrThrow();
|
|
264
|
+
return normalizeRow(row);
|
|
265
|
+
}
|
|
266
|
+
async function readChainReorgsSince(params) {
|
|
267
|
+
const db = params.db ?? getSourceDb();
|
|
268
|
+
const limit = Math.min(1000, Math.max(1, params.limit));
|
|
269
|
+
const result = params.since instanceof Date ? await sql2`
|
|
270
|
+
SELECT *
|
|
271
|
+
FROM chain_reorgs
|
|
272
|
+
WHERE detected_at > ${params.since}
|
|
273
|
+
ORDER BY detected_at ASC, id ASC
|
|
274
|
+
LIMIT ${limit}
|
|
275
|
+
`.execute(db) : await sql2`
|
|
276
|
+
SELECT *
|
|
277
|
+
FROM chain_reorgs
|
|
278
|
+
WHERE
|
|
279
|
+
orphaned_to_height > ${params.since.block_height}
|
|
280
|
+
OR (
|
|
281
|
+
orphaned_to_height = ${params.since.block_height}
|
|
282
|
+
AND orphaned_to_event_index >= ${params.since.event_index}
|
|
283
|
+
)
|
|
284
|
+
ORDER BY detected_at ASC, id ASC
|
|
285
|
+
LIMIT ${limit}
|
|
286
|
+
`.execute(db);
|
|
287
|
+
return result.rows.map(normalizeRow);
|
|
288
|
+
}
|
|
289
|
+
async function readChainReorgsForRange(params) {
|
|
290
|
+
const db = params.db ?? getSourceDb();
|
|
291
|
+
const { from, to } = params;
|
|
292
|
+
const { rows } = await sql2`
|
|
293
|
+
SELECT *
|
|
294
|
+
FROM chain_reorgs
|
|
295
|
+
WHERE
|
|
296
|
+
(
|
|
297
|
+
orphaned_from_height < ${to.block_height}
|
|
298
|
+
OR (
|
|
299
|
+
orphaned_from_height = ${to.block_height}
|
|
300
|
+
AND orphaned_from_event_index <= ${to.event_index}
|
|
301
|
+
)
|
|
302
|
+
)
|
|
303
|
+
AND (
|
|
304
|
+
orphaned_to_height > ${from.block_height}
|
|
305
|
+
OR (
|
|
306
|
+
orphaned_to_height = ${from.block_height}
|
|
307
|
+
AND orphaned_to_event_index >= ${from.event_index}
|
|
308
|
+
)
|
|
309
|
+
)
|
|
310
|
+
ORDER BY detected_at ASC, id ASC
|
|
311
|
+
`.execute(db);
|
|
312
|
+
return rows.map(normalizeRow);
|
|
313
|
+
}
|
|
314
|
+
export {
|
|
315
|
+
readChainReorgsSince,
|
|
316
|
+
readChainReorgsForRange,
|
|
317
|
+
insertChainReorg,
|
|
318
|
+
encodeChainReorgCursor
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
//# debugId=0D1CBECB9E7B5B3664756E2164756E21
|
|
322
|
+
//# sourceMappingURL=chain-reorgs.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/env.ts", "../src/logger.ts", "../src/db/jsonb.ts", "../src/db/index.ts", "../src/db/queries/chain-reorgs.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { z } from \"zod/v4\";\n\n// Parse comma-separated networks\nconst networksSchema = z.string().transform((val) => {\n\tconst networks = val\n\t\t.split(\",\")\n\t\t.map((n) => n.trim())\n\t\t.filter(Boolean);\n\tconst valid = [\"mainnet\", \"testnet\"];\n\tfor (const n of networks) {\n\t\tif (!valid.includes(n)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid network: ${n}. Must be one of: ${valid.join(\", \")}`,\n\t\t\t);\n\t\t}\n\t}\n\treturn networks as (\"mainnet\" | \"testnet\")[];\n});\n\ninterface EnvSchemaOutput {\n\tDATABASE_URL?: string;\n\t/**\n\t * Shared indexer DB (blocks/txs/events). Falls back to DATABASE_URL.\n\t * Set this alongside TARGET_DATABASE_URL to enable dual-DB mode.\n\t */\n\tSOURCE_DATABASE_URL?: string;\n\t/**\n\t * Tenant DB (subgraph schemas + subgraphs table). Falls back to DATABASE_URL.\n\t * Set this alongside SOURCE_DATABASE_URL to enable dual-DB mode.\n\t */\n\tTARGET_DATABASE_URL?: string;\n\tNETWORK?: \"mainnet\" | \"testnet\";\n\tNETWORKS?: (\"mainnet\" | \"testnet\")[];\n\tLOG_LEVEL: \"debug\" | \"info\" | \"warn\" | \"error\";\n\tNODE_ENV: \"development\" | \"production\" | \"test\";\n}\n\n// Cast needed: z.preprocess / z.default create different _input vs _output types\n// that z.ZodType<T> can't represent without explicit input type param\nconst envSchema: z.ZodType<EnvSchemaOutput> = z.object({\n\tDATABASE_URL: z.preprocess(\n\t\t(val) => (typeof val === \"string\" && val.length === 0 ? undefined : val),\n\t\tz.string().url().optional(),\n\t),\n\tSOURCE_DATABASE_URL: z.preprocess(\n\t\t(val) => (typeof val === \"string\" && val.length === 0 ? undefined : val),\n\t\tz.string().url().optional(),\n\t),\n\tTARGET_DATABASE_URL: z.preprocess(\n\t\t(val) => (typeof val === \"string\" && val.length === 0 ? undefined : val),\n\t\tz.string().url().optional(),\n\t),\n\tNETWORK: z.enum([\"mainnet\", \"testnet\"]).optional(),\n\tNETWORKS: networksSchema.optional(),\n\tLOG_LEVEL: z.enum([\"debug\", \"info\", \"warn\", \"error\"]).default(\"info\"),\n\tNODE_ENV: z\n\t\t.enum([\"development\", \"production\", \"test\"])\n\t\t.default(\"development\"),\n}) as unknown as z.ZodType<EnvSchemaOutput>;\n\nexport type Env = EnvSchemaOutput & {\n\tenabledNetworks: (\"mainnet\" | \"testnet\")[];\n};\n\nlet cachedEnv: Env | null = null;\n\nexport function getEnv(): Env {\n\tif (cachedEnv) {\n\t\treturn cachedEnv;\n\t}\n\n\tconst result = envSchema.safeParse(process.env);\n\n\tif (!result.success) {\n\t\tconsole.error(\"❌ Invalid environment configuration:\");\n\t\tconsole.error(z.treeifyError(result.error));\n\t\tthrow new Error(\"Invalid environment configuration\");\n\t}\n\n\t// Compute enabled networks from NETWORKS or NETWORK\n\tlet enabledNetworks: (\"mainnet\" | \"testnet\")[];\n\tif (result.data.NETWORKS && result.data.NETWORKS.length > 0) {\n\t\tenabledNetworks = result.data.NETWORKS;\n\t} else if (result.data.NETWORK) {\n\t\tenabledNetworks = [result.data.NETWORK];\n\t} else {\n\t\tenabledNetworks = [\"mainnet\"]; // Default\n\t}\n\n\tcachedEnv = { ...result.data, enabledNetworks };\n\treturn cachedEnv;\n}\n\n// Export for testing\nexport { envSchema };\n",
|
|
6
|
+
"import { getEnv } from \"./env.ts\";\n\ntype LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n\tdebug: 0,\n\tinfo: 1,\n\twarn: 2,\n\terror: 3,\n};\n\nclass Logger {\n\tprivate _level?: LogLevel;\n\tprivate _isProduction?: boolean;\n\tprivate _initialized = false;\n\n\tprivate init() {\n\t\tif (this._initialized) return;\n\t\tthis._initialized = true;\n\t\ttry {\n\t\t\tconst env = getEnv();\n\t\t\tthis._level = env.LOG_LEVEL;\n\t\t\tthis._isProduction = env.NODE_ENV === \"production\";\n\t\t} catch {\n\t\t\t// Fallback when env is unavailable (e.g. tests without DATABASE_URL)\n\t\t\tthis._level = \"info\";\n\t\t\tthis._isProduction = false;\n\t\t}\n\t}\n\n\tprivate get level(): LogLevel {\n\t\tthis.init();\n\t\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\t\treturn this._level!;\n\t}\n\n\tprivate get isProduction(): boolean {\n\t\tthis.init();\n\t\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\t\treturn this._isProduction!;\n\t}\n\n\tprivate shouldLog(level: LogLevel): boolean {\n\t\treturn LOG_LEVELS[level] >= LOG_LEVELS[this.level];\n\t}\n\n\tprivate formatMessage(\n\t\tlevel: LogLevel,\n\t\tmessage: string,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety\n\t\tmeta?: Record<string, any>,\n\t) {\n\t\tconst timestamp = new Date().toISOString();\n\n\t\tif (this.isProduction) {\n\t\t\t// JSON output for production\n\t\t\treturn JSON.stringify({\n\t\t\t\ttimestamp,\n\t\t\t\tlevel,\n\t\t\t\tmessage,\n\t\t\t\t...meta,\n\t\t\t});\n\t\t}\n\n\t\t// Human-readable output for development\n\t\tconst metaStr = meta ? ` ${JSON.stringify(meta)}` : \"\";\n\t\treturn `[${timestamp}] ${level.toUpperCase()}: ${message}${metaStr}`;\n\t}\n\n\t// biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety\n\tdebug(message: string, meta?: Record<string, any>): void {\n\t\tif (this.shouldLog(\"debug\")) {\n\t\t\tconsole.debug(this.formatMessage(\"debug\", message, meta));\n\t\t}\n\t}\n\n\t// biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety\n\tinfo(message: string, meta?: Record<string, any>): void {\n\t\tif (this.shouldLog(\"info\")) {\n\t\t\tconsole.info(this.formatMessage(\"info\", message, meta));\n\t\t}\n\t}\n\n\t// biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety\n\twarn(message: string, meta?: Record<string, any>): void {\n\t\tif (this.shouldLog(\"warn\")) {\n\t\t\tconsole.warn(this.formatMessage(\"warn\", message, meta));\n\t\t}\n\t}\n\n\t// biome-ignore lint/suspicious/noExplicitAny: interop boundary or dynamic-shape value where typing adds friction without runtime safety\n\terror(message: string, meta?: Record<string, any>): void {\n\t\tif (this.shouldLog(\"error\")) {\n\t\t\tconsole.error(this.formatMessage(\"error\", message, meta));\n\t\t}\n\t}\n}\n\n// Export singleton instance\nexport const logger: Logger = new Logger();\n",
|
|
7
|
+
"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",
|
|
8
|
+
"import { Kysely } from \"kysely\";\nimport { PostgresJSDialect } from \"kysely-postgres-js\";\nimport postgres from \"postgres\";\nimport { logger } from \"../logger.ts\";\nimport type { Database } from \"./types.ts\";\n\nconst DEFAULT_URL =\n\t\"postgres://postgres:postgres@localhost:5432/secondlayer_dev\";\n\ninterface PoolEntry {\n\tdb: Kysely<Database>;\n\trawClient: ReturnType<typeof postgres>;\n}\n\n/**\n * Cache of Kysely + raw postgres.js pools keyed by resolved URL.\n * Two getters resolving to the same URL share one entry (single pool) —\n * this is the single-DB backward-compat contract: when only `DATABASE_URL`\n * is set, `getSourceDb() === getTargetDb()` (zero regression vs. pre-dual-DB).\n */\nconst pools = new Map<string, PoolEntry>();\n\nfunction resolveSourceUrl(): string {\n\treturn (\n\t\tprocess.env.SOURCE_DATABASE_URL || process.env.DATABASE_URL || DEFAULT_URL\n\t);\n}\n\nfunction resolveTargetUrl(): string {\n\treturn (\n\t\tprocess.env.TARGET_DATABASE_URL || process.env.DATABASE_URL || DEFAULT_URL\n\t);\n}\n\nfunction getOrCreatePool(url: string): PoolEntry {\n\tconst existing = pools.get(url);\n\tif (existing) return existing;\n\n\t// \"Local\" = we skip TLS. Any Docker service alias (single-label hostname\n\t// with no dots) is on an internal network and won't serve TLS.\n\tconst host = (() => {\n\t\ttry {\n\t\t\treturn new URL(url).hostname;\n\t\t} catch {\n\t\t\treturn \"\";\n\t\t}\n\t})();\n\tconst isLocal =\n\t\thost === \"localhost\" || host === \"127.0.0.1\" || !host.includes(\".\");\n\tconst poolMax = Number.parseInt(process.env.DATABASE_POOL_MAX ?? \"20\", 10);\n\tconst rawClient = postgres(url, {\n\t\tmax: poolMax,\n\t\tssl: isLocal\n\t\t\t? undefined\n\t\t\t: {\n\t\t\t\t\trejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== \"0\",\n\t\t\t\t},\n\t});\n\tconst db = new Kysely<Database>({\n\t\tdialect: new PostgresJSDialect({ postgres: rawClient }),\n\t\t// Diagnostic hook: surface the failing SQL whenever postgres rejects\n\t\t// with code 42P10 (ON CONFLICT target doesn't match any unique\n\t\t// constraint). Temporary — remove once we've caught the culprit\n\t\t// query in prod logs and fixed the schema drift.\n\t\tlog: (event) => {\n\t\t\tif (event.level !== \"error\") return;\n\t\t\tconst err = event.error as {\n\t\t\t\tcode?: string;\n\t\t\t\tmessage?: string;\n\t\t\t} | null;\n\t\t\tif (err?.code !== \"42P10\") return;\n\t\t\tlogger.warn(\"db.on_conflict_constraint_missing\", {\n\t\t\t\tcode: err.code,\n\t\t\t\tmessage: err.message,\n\t\t\t\tsql: event.query.sql,\n\t\t\t\tparams: event.query.parameters,\n\t\t\t});\n\t\t},\n\t});\n\tconst entry: PoolEntry = { db, rawClient };\n\tpools.set(url, entry);\n\treturn entry;\n}\n\n/**\n * Kysely instance for the SOURCE DB (block/tx/event reads from the shared\n * indexer). Resolution: `SOURCE_DATABASE_URL || DATABASE_URL`.\n */\nexport function getSourceDb(): Kysely<Database> {\n\treturn getOrCreatePool(resolveSourceUrl()).db;\n}\n\n/**\n * Kysely instance for the TARGET DB (subgraph schemas, subgraphs table,\n * account-scoped data — tenant-side writes). Resolution:\n * `TARGET_DATABASE_URL || DATABASE_URL`.\n */\nexport function getTargetDb(): Kysely<Database> {\n\treturn getOrCreatePool(resolveTargetUrl()).db;\n}\n\n/**\n * Backward-compat alias for `getTargetDb()`. Accepts an optional\n * `connectionString` override used by seed/test helpers — when supplied,\n * bypasses env resolution and uses the provided URL directly (still cached).\n */\nexport function getDb(connectionString?: string): Kysely<Database> {\n\tif (connectionString) return getOrCreatePool(connectionString).db;\n\treturn getTargetDb();\n}\n\n/**\n * Raw postgres.js client for dynamic schema DDL (CREATE SCHEMA, DROP, etc.).\n * Defaults to the target role (tenant schemas live in the target DB).\n */\nexport function getRawClient(\n\trole: \"source\" | \"target\" = \"target\",\n): ReturnType<typeof postgres> {\n\tconst url = role === \"source\" ? resolveSourceUrl() : resolveTargetUrl();\n\treturn getOrCreatePool(url).rawClient;\n}\n\n/** Close all DB connection pools. Call in CLI commands to allow process exit. */\nexport async function closeDb(): Promise<void> {\n\tfor (const entry of pools.values()) {\n\t\tawait entry.db.destroy();\n\t\tawait entry.rawClient.end();\n\t}\n\tpools.clear();\n}\n\nimport { sql } from \"kysely\";\nexport { sql };\nexport * from \"./types.ts\";\nexport { jsonb, parseJsonb } from \"./jsonb.ts\";\n",
|
|
9
|
+
"import { getSourceDb, sql } from \"../index.ts\";\nimport type { Database } from \"../types.ts\";\nimport type { Kysely, Transaction } from \"kysely\";\n\nexport type ChainReorgCursor = {\n\tblock_height: number;\n\tevent_index: number;\n};\n\nexport type ChainReorgRecord = {\n\tid: string;\n\tdetected_at: string;\n\tfork_point_height: number;\n\told_index_block_hash: string | null;\n\tnew_index_block_hash: string | null;\n\torphaned_range: { from: string; to: string };\n\tnew_canonical_tip: string;\n};\n\nexport type InsertChainReorgParams = {\n\tforkPointHeight: number;\n\toldIndexBlockHash?: string | null;\n\tnewIndexBlockHash?: string | null;\n\torphanedFrom: ChainReorgCursor;\n\torphanedTo: ChainReorgCursor;\n\tnewCanonicalTip: ChainReorgCursor;\n\tdb?: Kysely<Database> | Transaction<Database>;\n};\n\nexport type ReadChainReorgsSinceParams = {\n\tsince: Date | ChainReorgCursor;\n\tlimit: number;\n\tdb?: Kysely<Database>;\n};\n\nexport type ReadChainReorgsForRangeParams = {\n\tfrom: ChainReorgCursor;\n\tto: ChainReorgCursor;\n\tdb?: Kysely<Database>;\n};\n\ntype ChainReorgRow = {\n\tid: string;\n\tdetected_at: Date | string;\n\tfork_point_height: string | number;\n\told_index_block_hash: string | null;\n\tnew_index_block_hash: string | null;\n\torphaned_from_height: string | number;\n\torphaned_from_event_index: string | number;\n\torphaned_to_height: string | number;\n\torphaned_to_event_index: string | number;\n\tnew_canonical_height: string | number;\n\tnew_canonical_event_index: string | number;\n};\n\nexport function encodeChainReorgCursor(cursor: ChainReorgCursor): string {\n\treturn `${cursor.block_height}:${cursor.event_index}`;\n}\n\nfunction normalizeRow(row: ChainReorgRow): ChainReorgRecord {\n\tconst detectedAt =\n\t\trow.detected_at instanceof Date\n\t\t\t? row.detected_at.toISOString()\n\t\t\t: new Date(row.detected_at).toISOString();\n\n\treturn {\n\t\tid: row.id,\n\t\tdetected_at: detectedAt,\n\t\tfork_point_height: Number(row.fork_point_height),\n\t\told_index_block_hash: row.old_index_block_hash,\n\t\tnew_index_block_hash: row.new_index_block_hash,\n\t\torphaned_range: {\n\t\t\tfrom: encodeChainReorgCursor({\n\t\t\t\tblock_height: Number(row.orphaned_from_height),\n\t\t\t\tevent_index: Number(row.orphaned_from_event_index),\n\t\t\t}),\n\t\t\tto: encodeChainReorgCursor({\n\t\t\t\tblock_height: Number(row.orphaned_to_height),\n\t\t\t\tevent_index: Number(row.orphaned_to_event_index),\n\t\t\t}),\n\t\t},\n\t\tnew_canonical_tip: encodeChainReorgCursor({\n\t\t\tblock_height: Number(row.new_canonical_height),\n\t\t\tevent_index: Number(row.new_canonical_event_index),\n\t\t}),\n\t};\n}\n\nexport async function insertChainReorg(\n\tparams: InsertChainReorgParams,\n): Promise<ChainReorgRecord> {\n\tconst db = params.db ?? getSourceDb();\n\tconst row = await db\n\t\t.insertInto(\"chain_reorgs\")\n\t\t.values({\n\t\t\tfork_point_height: params.forkPointHeight,\n\t\t\told_index_block_hash: params.oldIndexBlockHash ?? null,\n\t\t\tnew_index_block_hash: params.newIndexBlockHash ?? null,\n\t\t\torphaned_from_height: params.orphanedFrom.block_height,\n\t\t\torphaned_from_event_index: params.orphanedFrom.event_index,\n\t\t\torphaned_to_height: params.orphanedTo.block_height,\n\t\t\torphaned_to_event_index: params.orphanedTo.event_index,\n\t\t\tnew_canonical_height: params.newCanonicalTip.block_height,\n\t\t\tnew_canonical_event_index: params.newCanonicalTip.event_index,\n\t\t})\n\t\t.returningAll()\n\t\t.executeTakeFirstOrThrow();\n\n\treturn normalizeRow(row);\n}\n\nexport async function readChainReorgsSince(\n\tparams: ReadChainReorgsSinceParams,\n): Promise<ChainReorgRecord[]> {\n\tconst db = params.db ?? getSourceDb();\n\tconst limit = Math.min(1000, Math.max(1, params.limit));\n\n\tconst result =\n\t\tparams.since instanceof Date\n\t\t\t? await sql<ChainReorgRow>`\n\t\t\t\t\tSELECT *\n\t\t\t\t\tFROM chain_reorgs\n\t\t\t\t\tWHERE detected_at > ${params.since}\n\t\t\t\t\tORDER BY detected_at ASC, id ASC\n\t\t\t\t\tLIMIT ${limit}\n\t\t\t\t`.execute(db)\n\t\t\t: await sql<ChainReorgRow>`\n\t\t\t\t\tSELECT *\n\t\t\t\t\tFROM chain_reorgs\n\t\t\t\t\tWHERE\n\t\t\t\t\t\torphaned_to_height > ${params.since.block_height}\n\t\t\t\t\t\tOR (\n\t\t\t\t\t\t\torphaned_to_height = ${params.since.block_height}\n\t\t\t\t\t\t\tAND orphaned_to_event_index >= ${params.since.event_index}\n\t\t\t\t\t\t)\n\t\t\t\t\tORDER BY detected_at ASC, id ASC\n\t\t\t\t\tLIMIT ${limit}\n\t\t\t\t`.execute(db);\n\n\treturn result.rows.map(normalizeRow);\n}\n\nexport async function readChainReorgsForRange(\n\tparams: ReadChainReorgsForRangeParams,\n): Promise<ChainReorgRecord[]> {\n\tconst db = params.db ?? getSourceDb();\n\tconst { from, to } = params;\n\tconst { rows } = await sql<ChainReorgRow>`\n\t\tSELECT *\n\t\tFROM chain_reorgs\n\t\tWHERE\n\t\t\t(\n\t\t\t\torphaned_from_height < ${to.block_height}\n\t\t\t\tOR (\n\t\t\t\t\torphaned_from_height = ${to.block_height}\n\t\t\t\t\tAND orphaned_from_event_index <= ${to.event_index}\n\t\t\t\t)\n\t\t\t)\n\t\t\tAND (\n\t\t\t\torphaned_to_height > ${from.block_height}\n\t\t\t\tOR (\n\t\t\t\t\torphaned_to_height = ${from.block_height}\n\t\t\t\t\tAND orphaned_to_event_index >= ${from.event_index}\n\t\t\t\t)\n\t\t\t)\n\t\tORDER BY detected_at ASC, id ASC\n\t`.execute(db);\n\n\treturn rows.map(normalizeRow);\n}\n"
|
|
10
|
+
],
|
|
11
|
+
"mappings": "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",
|
|
12
|
+
"debugId": "0D1CBECB9E7B5B3664756E2164756E21",
|
|
13
|
+
"names": []
|
|
14
|
+
}
|
|
@@ -5,6 +5,7 @@ interface BlocksTable {
|
|
|
5
5
|
hash: string;
|
|
6
6
|
parent_hash: string;
|
|
7
7
|
burn_block_height: number;
|
|
8
|
+
burn_block_hash: ColumnType<string | null, string | null | undefined, string | null>;
|
|
8
9
|
timestamp: number;
|
|
9
10
|
canonical: Generated<boolean>;
|
|
10
11
|
created_at: Generated<Date>;
|
|
@@ -145,6 +146,8 @@ interface UsageDailyTable {
|
|
|
145
146
|
date: string;
|
|
146
147
|
api_requests: Generated<number>;
|
|
147
148
|
deliveries: Generated<number>;
|
|
149
|
+
streams_events_returned: Generated<number>;
|
|
150
|
+
index_decoded_events_returned: Generated<number>;
|
|
148
151
|
}
|
|
149
152
|
interface UsageSnapshotsTable {
|
|
150
153
|
id: Generated<string>;
|
|
@@ -273,6 +276,44 @@ interface ProcessedStripeEventsTable {
|
|
|
273
276
|
event_type: string;
|
|
274
277
|
processed_at: Generated<Date>;
|
|
275
278
|
}
|
|
279
|
+
interface DecodedEventsTable {
|
|
280
|
+
cursor: string;
|
|
281
|
+
block_height: number;
|
|
282
|
+
tx_id: string;
|
|
283
|
+
tx_index: number;
|
|
284
|
+
event_index: number;
|
|
285
|
+
event_type: string;
|
|
286
|
+
microblock_hash: string | null;
|
|
287
|
+
canonical: Generated<boolean>;
|
|
288
|
+
contract_id: string | null;
|
|
289
|
+
sender: string | null;
|
|
290
|
+
recipient: string | null;
|
|
291
|
+
amount: string | null;
|
|
292
|
+
asset_identifier: string | null;
|
|
293
|
+
value: string | null;
|
|
294
|
+
memo: string | null;
|
|
295
|
+
source_cursor: string;
|
|
296
|
+
created_at: Generated<Date>;
|
|
297
|
+
}
|
|
298
|
+
interface L2DecoderCheckpointsTable {
|
|
299
|
+
decoder_name: string;
|
|
300
|
+
last_cursor: string | null;
|
|
301
|
+
updated_at: Generated<Date>;
|
|
302
|
+
}
|
|
303
|
+
interface ChainReorgsTable {
|
|
304
|
+
id: Generated<string>;
|
|
305
|
+
detected_at: Generated<Date>;
|
|
306
|
+
fork_point_height: number;
|
|
307
|
+
old_index_block_hash: string | null;
|
|
308
|
+
new_index_block_hash: string | null;
|
|
309
|
+
orphaned_from_height: number;
|
|
310
|
+
orphaned_from_event_index: number;
|
|
311
|
+
orphaned_to_height: number;
|
|
312
|
+
orphaned_to_event_index: number;
|
|
313
|
+
new_canonical_height: number;
|
|
314
|
+
new_canonical_event_index: number;
|
|
315
|
+
created_at: Generated<Date>;
|
|
316
|
+
}
|
|
276
317
|
interface Database {
|
|
277
318
|
blocks: BlocksTable;
|
|
278
319
|
transactions: TransactionsTable;
|
|
@@ -308,6 +349,9 @@ interface Database {
|
|
|
308
349
|
subscriptions: SubscriptionsTable;
|
|
309
350
|
subscription_outbox: SubscriptionOutboxTable;
|
|
310
351
|
subscription_deliveries: SubscriptionDeliveriesTable;
|
|
352
|
+
decoded_events: DecodedEventsTable;
|
|
353
|
+
l2_decoder_checkpoints: L2DecoderCheckpointsTable;
|
|
354
|
+
chain_reorgs: ChainReorgsTable;
|
|
311
355
|
}
|
|
312
356
|
type TenantStatus = "provisioning" | "active" | "limit_warning" | "paused_limit" | "suspended" | "error" | "deleted";
|
|
313
357
|
interface TenantsTable {
|
|
@@ -5,6 +5,7 @@ interface BlocksTable {
|
|
|
5
5
|
hash: string;
|
|
6
6
|
parent_hash: string;
|
|
7
7
|
burn_block_height: number;
|
|
8
|
+
burn_block_hash: ColumnType<string | null, string | null | undefined, string | null>;
|
|
8
9
|
timestamp: number;
|
|
9
10
|
canonical: Generated<boolean>;
|
|
10
11
|
created_at: Generated<Date>;
|
|
@@ -145,6 +146,8 @@ interface UsageDailyTable {
|
|
|
145
146
|
date: string;
|
|
146
147
|
api_requests: Generated<number>;
|
|
147
148
|
deliveries: Generated<number>;
|
|
149
|
+
streams_events_returned: Generated<number>;
|
|
150
|
+
index_decoded_events_returned: Generated<number>;
|
|
148
151
|
}
|
|
149
152
|
interface UsageSnapshotsTable {
|
|
150
153
|
id: Generated<string>;
|
|
@@ -273,6 +276,44 @@ interface ProcessedStripeEventsTable {
|
|
|
273
276
|
event_type: string;
|
|
274
277
|
processed_at: Generated<Date>;
|
|
275
278
|
}
|
|
279
|
+
interface DecodedEventsTable {
|
|
280
|
+
cursor: string;
|
|
281
|
+
block_height: number;
|
|
282
|
+
tx_id: string;
|
|
283
|
+
tx_index: number;
|
|
284
|
+
event_index: number;
|
|
285
|
+
event_type: string;
|
|
286
|
+
microblock_hash: string | null;
|
|
287
|
+
canonical: Generated<boolean>;
|
|
288
|
+
contract_id: string | null;
|
|
289
|
+
sender: string | null;
|
|
290
|
+
recipient: string | null;
|
|
291
|
+
amount: string | null;
|
|
292
|
+
asset_identifier: string | null;
|
|
293
|
+
value: string | null;
|
|
294
|
+
memo: string | null;
|
|
295
|
+
source_cursor: string;
|
|
296
|
+
created_at: Generated<Date>;
|
|
297
|
+
}
|
|
298
|
+
interface L2DecoderCheckpointsTable {
|
|
299
|
+
decoder_name: string;
|
|
300
|
+
last_cursor: string | null;
|
|
301
|
+
updated_at: Generated<Date>;
|
|
302
|
+
}
|
|
303
|
+
interface ChainReorgsTable {
|
|
304
|
+
id: Generated<string>;
|
|
305
|
+
detected_at: Generated<Date>;
|
|
306
|
+
fork_point_height: number;
|
|
307
|
+
old_index_block_hash: string | null;
|
|
308
|
+
new_index_block_hash: string | null;
|
|
309
|
+
orphaned_from_height: number;
|
|
310
|
+
orphaned_from_event_index: number;
|
|
311
|
+
orphaned_to_height: number;
|
|
312
|
+
orphaned_to_event_index: number;
|
|
313
|
+
new_canonical_height: number;
|
|
314
|
+
new_canonical_event_index: number;
|
|
315
|
+
created_at: Generated<Date>;
|
|
316
|
+
}
|
|
276
317
|
interface Database {
|
|
277
318
|
blocks: BlocksTable;
|
|
278
319
|
transactions: TransactionsTable;
|
|
@@ -308,6 +349,9 @@ interface Database {
|
|
|
308
349
|
subscriptions: SubscriptionsTable;
|
|
309
350
|
subscription_outbox: SubscriptionOutboxTable;
|
|
310
351
|
subscription_deliveries: SubscriptionDeliveriesTable;
|
|
352
|
+
decoded_events: DecodedEventsTable;
|
|
353
|
+
l2_decoder_checkpoints: L2DecoderCheckpointsTable;
|
|
354
|
+
chain_reorgs: ChainReorgsTable;
|
|
311
355
|
}
|
|
312
356
|
type TenantStatus = "provisioning" | "active" | "limit_warning" | "paused_limit" | "suspended" | "error" | "deleted";
|
|
313
357
|
interface TenantsTable {
|
|
@@ -5,6 +5,7 @@ interface BlocksTable {
|
|
|
5
5
|
hash: string;
|
|
6
6
|
parent_hash: string;
|
|
7
7
|
burn_block_height: number;
|
|
8
|
+
burn_block_hash: ColumnType<string | null, string | null | undefined, string | null>;
|
|
8
9
|
timestamp: number;
|
|
9
10
|
canonical: Generated<boolean>;
|
|
10
11
|
created_at: Generated<Date>;
|
|
@@ -145,6 +146,8 @@ interface UsageDailyTable {
|
|
|
145
146
|
date: string;
|
|
146
147
|
api_requests: Generated<number>;
|
|
147
148
|
deliveries: Generated<number>;
|
|
149
|
+
streams_events_returned: Generated<number>;
|
|
150
|
+
index_decoded_events_returned: Generated<number>;
|
|
148
151
|
}
|
|
149
152
|
interface UsageSnapshotsTable {
|
|
150
153
|
id: Generated<string>;
|
|
@@ -273,6 +276,44 @@ interface ProcessedStripeEventsTable {
|
|
|
273
276
|
event_type: string;
|
|
274
277
|
processed_at: Generated<Date>;
|
|
275
278
|
}
|
|
279
|
+
interface DecodedEventsTable {
|
|
280
|
+
cursor: string;
|
|
281
|
+
block_height: number;
|
|
282
|
+
tx_id: string;
|
|
283
|
+
tx_index: number;
|
|
284
|
+
event_index: number;
|
|
285
|
+
event_type: string;
|
|
286
|
+
microblock_hash: string | null;
|
|
287
|
+
canonical: Generated<boolean>;
|
|
288
|
+
contract_id: string | null;
|
|
289
|
+
sender: string | null;
|
|
290
|
+
recipient: string | null;
|
|
291
|
+
amount: string | null;
|
|
292
|
+
asset_identifier: string | null;
|
|
293
|
+
value: string | null;
|
|
294
|
+
memo: string | null;
|
|
295
|
+
source_cursor: string;
|
|
296
|
+
created_at: Generated<Date>;
|
|
297
|
+
}
|
|
298
|
+
interface L2DecoderCheckpointsTable {
|
|
299
|
+
decoder_name: string;
|
|
300
|
+
last_cursor: string | null;
|
|
301
|
+
updated_at: Generated<Date>;
|
|
302
|
+
}
|
|
303
|
+
interface ChainReorgsTable {
|
|
304
|
+
id: Generated<string>;
|
|
305
|
+
detected_at: Generated<Date>;
|
|
306
|
+
fork_point_height: number;
|
|
307
|
+
old_index_block_hash: string | null;
|
|
308
|
+
new_index_block_hash: string | null;
|
|
309
|
+
orphaned_from_height: number;
|
|
310
|
+
orphaned_from_event_index: number;
|
|
311
|
+
orphaned_to_height: number;
|
|
312
|
+
orphaned_to_event_index: number;
|
|
313
|
+
new_canonical_height: number;
|
|
314
|
+
new_canonical_event_index: number;
|
|
315
|
+
created_at: Generated<Date>;
|
|
316
|
+
}
|
|
276
317
|
interface Database {
|
|
277
318
|
blocks: BlocksTable;
|
|
278
319
|
transactions: TransactionsTable;
|
|
@@ -308,6 +349,9 @@ interface Database {
|
|
|
308
349
|
subscriptions: SubscriptionsTable;
|
|
309
350
|
subscription_outbox: SubscriptionOutboxTable;
|
|
310
351
|
subscription_deliveries: SubscriptionDeliveriesTable;
|
|
352
|
+
decoded_events: DecodedEventsTable;
|
|
353
|
+
l2_decoder_checkpoints: L2DecoderCheckpointsTable;
|
|
354
|
+
chain_reorgs: ChainReorgsTable;
|
|
311
355
|
}
|
|
312
356
|
type TenantStatus = "provisioning" | "active" | "limit_warning" | "paused_limit" | "suspended" | "error" | "deleted";
|
|
313
357
|
interface TenantsTable {
|
|
@@ -5,6 +5,7 @@ interface BlocksTable {
|
|
|
5
5
|
hash: string;
|
|
6
6
|
parent_hash: string;
|
|
7
7
|
burn_block_height: number;
|
|
8
|
+
burn_block_hash: ColumnType<string | null, string | null | undefined, string | null>;
|
|
8
9
|
timestamp: number;
|
|
9
10
|
canonical: Generated<boolean>;
|
|
10
11
|
created_at: Generated<Date>;
|
|
@@ -145,6 +146,8 @@ interface UsageDailyTable {
|
|
|
145
146
|
date: string;
|
|
146
147
|
api_requests: Generated<number>;
|
|
147
148
|
deliveries: Generated<number>;
|
|
149
|
+
streams_events_returned: Generated<number>;
|
|
150
|
+
index_decoded_events_returned: Generated<number>;
|
|
148
151
|
}
|
|
149
152
|
interface UsageSnapshotsTable {
|
|
150
153
|
id: Generated<string>;
|
|
@@ -273,6 +276,44 @@ interface ProcessedStripeEventsTable {
|
|
|
273
276
|
event_type: string;
|
|
274
277
|
processed_at: Generated<Date>;
|
|
275
278
|
}
|
|
279
|
+
interface DecodedEventsTable {
|
|
280
|
+
cursor: string;
|
|
281
|
+
block_height: number;
|
|
282
|
+
tx_id: string;
|
|
283
|
+
tx_index: number;
|
|
284
|
+
event_index: number;
|
|
285
|
+
event_type: string;
|
|
286
|
+
microblock_hash: string | null;
|
|
287
|
+
canonical: Generated<boolean>;
|
|
288
|
+
contract_id: string | null;
|
|
289
|
+
sender: string | null;
|
|
290
|
+
recipient: string | null;
|
|
291
|
+
amount: string | null;
|
|
292
|
+
asset_identifier: string | null;
|
|
293
|
+
value: string | null;
|
|
294
|
+
memo: string | null;
|
|
295
|
+
source_cursor: string;
|
|
296
|
+
created_at: Generated<Date>;
|
|
297
|
+
}
|
|
298
|
+
interface L2DecoderCheckpointsTable {
|
|
299
|
+
decoder_name: string;
|
|
300
|
+
last_cursor: string | null;
|
|
301
|
+
updated_at: Generated<Date>;
|
|
302
|
+
}
|
|
303
|
+
interface ChainReorgsTable {
|
|
304
|
+
id: Generated<string>;
|
|
305
|
+
detected_at: Generated<Date>;
|
|
306
|
+
fork_point_height: number;
|
|
307
|
+
old_index_block_hash: string | null;
|
|
308
|
+
new_index_block_hash: string | null;
|
|
309
|
+
orphaned_from_height: number;
|
|
310
|
+
orphaned_from_event_index: number;
|
|
311
|
+
orphaned_to_height: number;
|
|
312
|
+
orphaned_to_event_index: number;
|
|
313
|
+
new_canonical_height: number;
|
|
314
|
+
new_canonical_event_index: number;
|
|
315
|
+
created_at: Generated<Date>;
|
|
316
|
+
}
|
|
276
317
|
interface Database {
|
|
277
318
|
blocks: BlocksTable;
|
|
278
319
|
transactions: TransactionsTable;
|
|
@@ -308,6 +349,9 @@ interface Database {
|
|
|
308
349
|
subscriptions: SubscriptionsTable;
|
|
309
350
|
subscription_outbox: SubscriptionOutboxTable;
|
|
310
351
|
subscription_deliveries: SubscriptionDeliveriesTable;
|
|
352
|
+
decoded_events: DecodedEventsTable;
|
|
353
|
+
l2_decoder_checkpoints: L2DecoderCheckpointsTable;
|
|
354
|
+
chain_reorgs: ChainReorgsTable;
|
|
311
355
|
}
|
|
312
356
|
type TenantStatus = "provisioning" | "active" | "limit_warning" | "paused_limit" | "suspended" | "error" | "deleted";
|
|
313
357
|
interface TenantsTable {
|