@secondlayer/shared 0.6.1 → 0.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/crypto/hmac.js +1 -2
- package/dist/src/crypto/hmac.js.map +2 -2
- package/dist/src/db/index.d.ts +3 -2
- package/dist/src/db/index.js +3 -2
- package/dist/src/db/index.js.map +3 -3
- package/dist/src/db/jsonb.js +1 -2
- package/dist/src/db/jsonb.js.map +2 -2
- package/dist/src/db/queries/accounts.d.ts +4 -3
- package/dist/src/db/queries/accounts.js +6 -4
- package/dist/src/db/queries/accounts.js.map +3 -3
- package/dist/src/db/queries/integrity.d.ts +3 -2
- package/dist/src/db/queries/integrity.js +1 -2
- package/dist/src/db/queries/integrity.js.map +2 -2
- package/dist/src/db/queries/metrics.d.ts +3 -2
- package/dist/src/db/queries/metrics.js +1 -2
- package/dist/src/db/queries/metrics.js.map +2 -2
- package/dist/src/db/queries/subgraphs.d.ts +3 -2
- package/dist/src/db/queries/subgraphs.js +2 -3
- package/dist/src/db/queries/subgraphs.js.map +3 -3
- package/dist/src/db/queries/usage.d.ts +11 -3
- package/dist/src/db/queries/usage.js +23 -2
- package/dist/src/db/queries/usage.js.map +3 -3
- package/dist/src/db/schema.d.ts +3 -2
- package/dist/src/env.js +1 -2
- package/dist/src/env.js.map +2 -2
- package/dist/src/errors.d.ts +19 -3
- package/dist/src/errors.js +23 -2
- package/dist/src/errors.js.map +3 -3
- package/dist/src/index.d.ts +22 -5
- package/dist/src/index.js +25 -2
- package/dist/src/index.js.map +4 -4
- package/dist/src/lib/plans.js +1 -2
- package/dist/src/lib/plans.js.map +2 -2
- package/dist/src/logger.js +1 -2
- package/dist/src/logger.js.map +2 -2
- package/dist/src/node/archive-client.d.ts +14 -1
- package/dist/src/node/archive-client.js +104 -21
- package/dist/src/node/archive-client.js.map +3 -3
- package/dist/src/node/client.js +1 -2
- package/dist/src/node/client.js.map +2 -2
- package/dist/src/node/hiro-client.js +1 -2
- package/dist/src/node/hiro-client.js.map +2 -2
- package/dist/src/node/hiro-pg-client.js +1 -2
- package/dist/src/node/hiro-pg-client.js.map +2 -2
- package/dist/src/node/local-client.d.ts +3 -2
- package/dist/src/node/local-client.js +1 -2
- package/dist/src/node/local-client.js.map +2 -2
- package/dist/src/queue/index.js +3 -2
- package/dist/src/queue/index.js.map +3 -3
- package/dist/src/queue/listener.js +1 -2
- package/dist/src/queue/listener.js.map +2 -2
- package/dist/src/queue/recovery.js +3 -2
- package/dist/src/queue/recovery.js.map +3 -3
- package/dist/src/schemas/filters.js +1 -2
- package/dist/src/schemas/filters.js.map +2 -2
- package/dist/src/schemas/index.js +1 -2
- package/dist/src/schemas/index.js.map +2 -2
- package/dist/src/schemas/subgraphs.js +1 -2
- package/dist/src/schemas/subgraphs.js.map +2 -2
- package/dist/src/types.d.ts +1 -1
- package/migrations/0017_security_hardening.ts +20 -0
- package/package.json +1 -1
|
@@ -13,7 +13,6 @@ var __export = (target, all) => {
|
|
|
13
13
|
set: __exportSetter.bind(all, name)
|
|
14
14
|
});
|
|
15
15
|
};
|
|
16
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
17
16
|
|
|
18
17
|
// src/env.ts
|
|
19
18
|
import { z } from "zod/v4";
|
|
@@ -129,8 +128,10 @@ class Logger {
|
|
|
129
128
|
var logger = new Logger;
|
|
130
129
|
|
|
131
130
|
// src/node/archive-client.ts
|
|
131
|
+
import { existsSync, unlinkSync, renameSync, readFileSync, writeFileSync } from "node:fs";
|
|
132
132
|
var DEFAULT_ARCHIVE_URL = "https://archive.hiro.so/mainnet/stacks-blockchain-api/mainnet-stacks-blockchain-api-latest.zst";
|
|
133
133
|
var HEIGHT_REGEX = /"block_height":\s*(\d+)/;
|
|
134
|
+
var CACHE_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
134
135
|
|
|
135
136
|
class ArchiveReplayClient {
|
|
136
137
|
archiveUrl;
|
|
@@ -139,6 +140,15 @@ class ArchiveReplayClient {
|
|
|
139
140
|
this.archiveUrl = opts?.archiveUrl || process.env.ARCHIVE_URL || DEFAULT_ARCHIVE_URL;
|
|
140
141
|
this.archiveDir = opts?.archiveDir || process.env.ARCHIVE_DIR || "/tmp";
|
|
141
142
|
}
|
|
143
|
+
get archivePath() {
|
|
144
|
+
return `${this.archiveDir}/secondlayer-archive.zst`;
|
|
145
|
+
}
|
|
146
|
+
get metaPath() {
|
|
147
|
+
return `${this.archiveDir}/secondlayer-archive.meta.json`;
|
|
148
|
+
}
|
|
149
|
+
get partialPath() {
|
|
150
|
+
return `${this.archiveDir}/secondlayer-archive.zst.partial`;
|
|
151
|
+
}
|
|
142
152
|
async isAvailable() {
|
|
143
153
|
try {
|
|
144
154
|
const res = await fetch(this.archiveUrl, {
|
|
@@ -155,18 +165,15 @@ class ArchiveReplayClient {
|
|
|
155
165
|
if (gapHeights.size === 0)
|
|
156
166
|
return { replayed: 0, errors: 0 };
|
|
157
167
|
const maxHeight = Math.max(...gapHeights);
|
|
158
|
-
const archivePath = `${this.archiveDir}/secondlayer-archive.zst`;
|
|
159
168
|
let replayed = 0;
|
|
160
169
|
let errors = 0;
|
|
161
|
-
logger.info("Archive replay: downloading archive", {
|
|
162
|
-
url: this.archiveUrl.split("/").pop(),
|
|
163
|
-
targetHeights: gapHeights.size,
|
|
164
|
-
maxHeight
|
|
165
|
-
});
|
|
166
170
|
try {
|
|
167
|
-
await this.
|
|
168
|
-
logger.info("Archive replay:
|
|
169
|
-
|
|
171
|
+
await this.ensureArchive();
|
|
172
|
+
logger.info("Archive replay: starting decompression + replay", {
|
|
173
|
+
targetHeights: gapHeights.size,
|
|
174
|
+
maxHeight
|
|
175
|
+
});
|
|
176
|
+
const proc = Bun.spawn(["zstd", "-d", this.archivePath, "--stdout"], {
|
|
170
177
|
stdout: "pipe",
|
|
171
178
|
stderr: "ignore"
|
|
172
179
|
});
|
|
@@ -236,25 +243,100 @@ class ArchiveReplayClient {
|
|
|
236
243
|
});
|
|
237
244
|
}
|
|
238
245
|
logger.info("Archive replay: complete", { replayed, errors, missing: remaining.size });
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
const { unlinkSync } = await import("node:fs");
|
|
245
|
-
unlinkSync(archivePath);
|
|
246
|
-
}
|
|
247
|
-
} catch {}
|
|
246
|
+
} catch (err) {
|
|
247
|
+
this.cleanupFile(this.archivePath);
|
|
248
|
+
this.cleanupFile(this.metaPath);
|
|
249
|
+
this.cleanupFile(this.partialPath);
|
|
250
|
+
throw err;
|
|
248
251
|
}
|
|
249
252
|
return { replayed, errors };
|
|
250
253
|
}
|
|
254
|
+
async ensureArchive() {
|
|
255
|
+
this.cleanStaleFiles();
|
|
256
|
+
const meta = this.readMeta();
|
|
257
|
+
const cached = existsSync(this.archivePath) && meta !== null;
|
|
258
|
+
if (cached) {
|
|
259
|
+
const age = Date.now() - new Date(meta.downloadedAt).getTime();
|
|
260
|
+
if (age < CACHE_MAX_AGE_MS) {
|
|
261
|
+
const headers = {};
|
|
262
|
+
if (meta.lastModified) {
|
|
263
|
+
headers["If-Modified-Since"] = meta.lastModified;
|
|
264
|
+
}
|
|
265
|
+
try {
|
|
266
|
+
const res = await fetch(this.archiveUrl, {
|
|
267
|
+
method: "HEAD",
|
|
268
|
+
headers,
|
|
269
|
+
signal: AbortSignal.timeout(15000)
|
|
270
|
+
});
|
|
271
|
+
if (res.status === 304) {
|
|
272
|
+
logger.info("Archive replay: using cached archive", {
|
|
273
|
+
ageHrs: (age / 3600000).toFixed(1)
|
|
274
|
+
});
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
logger.info("Archive replay: remote archive is newer, re-downloading");
|
|
278
|
+
} catch {
|
|
279
|
+
logger.info("Archive replay: remote unreachable, using cached archive");
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
} else {
|
|
283
|
+
logger.info("Archive replay: cache expired, re-downloading");
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
logger.info("Archive replay: downloading archive", {
|
|
287
|
+
url: this.archiveUrl.split("/").pop()
|
|
288
|
+
});
|
|
289
|
+
const lastModified = await this.download(this.partialPath);
|
|
290
|
+
renameSync(this.partialPath, this.archivePath);
|
|
291
|
+
this.writeMeta({ lastModified, downloadedAt: new Date().toISOString() });
|
|
292
|
+
logger.info("Archive replay: download complete");
|
|
293
|
+
}
|
|
294
|
+
cleanStaleFiles() {
|
|
295
|
+
try {
|
|
296
|
+
if (existsSync(this.partialPath)) {
|
|
297
|
+
unlinkSync(this.partialPath);
|
|
298
|
+
}
|
|
299
|
+
const meta = this.readMeta();
|
|
300
|
+
if (meta) {
|
|
301
|
+
const age = Date.now() - new Date(meta.downloadedAt).getTime();
|
|
302
|
+
if (age > CACHE_MAX_AGE_MS) {
|
|
303
|
+
this.cleanupFile(this.archivePath);
|
|
304
|
+
this.cleanupFile(this.metaPath);
|
|
305
|
+
logger.info("Archive replay: cleaned stale cache");
|
|
306
|
+
}
|
|
307
|
+
} else if (existsSync(this.archivePath)) {
|
|
308
|
+
this.cleanupFile(this.archivePath);
|
|
309
|
+
}
|
|
310
|
+
} catch {}
|
|
311
|
+
}
|
|
312
|
+
readMeta() {
|
|
313
|
+
try {
|
|
314
|
+
if (!existsSync(this.metaPath))
|
|
315
|
+
return null;
|
|
316
|
+
return JSON.parse(readFileSync(this.metaPath, "utf-8"));
|
|
317
|
+
} catch {
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
writeMeta(meta) {
|
|
322
|
+
try {
|
|
323
|
+
writeFileSync(this.metaPath, JSON.stringify(meta));
|
|
324
|
+
} catch {}
|
|
325
|
+
}
|
|
326
|
+
cleanupFile(path) {
|
|
327
|
+
try {
|
|
328
|
+
if (existsSync(path))
|
|
329
|
+
unlinkSync(path);
|
|
330
|
+
} catch {}
|
|
331
|
+
}
|
|
251
332
|
async download(destPath) {
|
|
252
333
|
const res = await fetch(this.archiveUrl, {
|
|
253
|
-
signal: AbortSignal.timeout(
|
|
334
|
+
signal: AbortSignal.timeout(30 * 60 * 1000)
|
|
254
335
|
});
|
|
255
336
|
if (!res.ok || !res.body) {
|
|
256
337
|
throw new Error(`Archive download failed: HTTP ${res.status}`);
|
|
257
338
|
}
|
|
339
|
+
const lastModified = res.headers.get("last-modified");
|
|
258
340
|
const totalBytes = Number(res.headers.get("content-length") || 0);
|
|
259
341
|
const writer = Bun.file(destPath).writer();
|
|
260
342
|
let downloaded = 0;
|
|
@@ -269,6 +351,7 @@ class ArchiveReplayClient {
|
|
|
269
351
|
}
|
|
270
352
|
}
|
|
271
353
|
await writer.end();
|
|
354
|
+
return lastModified;
|
|
272
355
|
}
|
|
273
356
|
}
|
|
274
357
|
function nthIndex(str, char, n) {
|
|
@@ -284,5 +367,5 @@ export {
|
|
|
284
367
|
ArchiveReplayClient
|
|
285
368
|
};
|
|
286
369
|
|
|
287
|
-
//# debugId=
|
|
370
|
+
//# debugId=255654A8B0CFD43D64756E2164756E21
|
|
288
371
|
//# sourceMappingURL=archive-client.js.map
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"import { z } from \"zod/v4\";\n\n// Parse comma-separated networks\nconst networksSchema = z.string().transform((val) => {\n const networks = val.split(\",\").map((n) => n.trim()).filter(Boolean);\n const valid = [\"mainnet\", \"testnet\"];\n for (const n of networks) {\n if (!valid.includes(n)) {\n throw new Error(`Invalid network: ${n}. Must be one of: ${valid.join(\", \")}`);\n }\n }\n return networks as (\"mainnet\" | \"testnet\")[];\n});\n\ninterface EnvSchemaOutput {\n DATABASE_URL?: string;\n NETWORK?: \"mainnet\" | \"testnet\";\n NETWORKS?: (\"mainnet\" | \"testnet\")[];\n LOG_LEVEL: \"debug\" | \"info\" | \"warn\" | \"error\";\n NODE_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 DATABASE_URL: z.preprocess(\n (val) => (typeof val === \"string\" && val.length === 0) ? undefined : val,\n z.string().url().optional(),\n ),\n NETWORK: z.enum([\"mainnet\", \"testnet\"]).optional(),\n NETWORKS: networksSchema.optional(),\n LOG_LEVEL: z.enum([\"debug\", \"info\", \"warn\", \"error\"]).default(\"info\"),\n NODE_ENV: z.enum([\"development\", \"production\", \"test\"]).default(\"development\"),\n}) as unknown as z.ZodType<EnvSchemaOutput>;\n\nexport type Env = EnvSchemaOutput & {\n enabledNetworks: (\"mainnet\" | \"testnet\")[];\n};\n\nlet cachedEnv: Env | null = null;\n\nexport function getEnv(): Env {\n if (cachedEnv) {\n return cachedEnv;\n }\n\n const result = envSchema.safeParse(process.env);\n\n if (!result.success) {\n console.error(\"❌ Invalid environment configuration:\");\n console.error(z.treeifyError(result.error));\n throw new Error(\"Invalid environment configuration\");\n }\n\n // Compute enabled networks from NETWORKS or NETWORK\n let enabledNetworks: (\"mainnet\" | \"testnet\")[];\n if (result.data.NETWORKS && result.data.NETWORKS.length > 0) {\n enabledNetworks = result.data.NETWORKS;\n } else if (result.data.NETWORK) {\n enabledNetworks = [result.data.NETWORK];\n } else {\n enabledNetworks = [\"mainnet\"]; // Default\n }\n\n cachedEnv = { ...result.data, enabledNetworks };\n return cachedEnv;\n}\n\n// Export for testing\nexport { envSchema };\n",
|
|
6
6
|
"import { getEnv } from \"./env.ts\";\n\ntype LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nclass Logger {\n private _level?: LogLevel;\n private _isProduction?: boolean;\n private _initialized = false;\n\n private init() {\n if (this._initialized) return;\n this._initialized = true;\n try {\n const env = getEnv();\n this._level = env.LOG_LEVEL;\n this._isProduction = env.NODE_ENV === \"production\";\n } catch {\n // Fallback when env is unavailable (e.g. tests without DATABASE_URL)\n this._level = \"info\";\n this._isProduction = false;\n }\n }\n\n private get level(): LogLevel {\n this.init();\n return this._level!;\n }\n\n private get isProduction(): boolean {\n this.init();\n return this._isProduction!;\n }\n\n private shouldLog(level: LogLevel): boolean {\n return LOG_LEVELS[level] >= LOG_LEVELS[this.level];\n }\n\n private formatMessage(level: LogLevel, message: string, meta?: Record<string, any>) {\n const timestamp = new Date().toISOString();\n\n if (this.isProduction) {\n // JSON output for production\n return JSON.stringify({\n timestamp,\n level,\n message,\n ...meta,\n });\n }\n\n // Human-readable output for development\n const metaStr = meta ? ` ${JSON.stringify(meta)}` : \"\";\n return `[${timestamp}] ${level.toUpperCase()}: ${message}${metaStr}`;\n }\n\n debug(message: string, meta?: Record<string, any>): void {\n if (this.shouldLog(\"debug\")) {\n console.debug(this.formatMessage(\"debug\", message, meta));\n }\n }\n\n info(message: string, meta?: Record<string, any>): void {\n if (this.shouldLog(\"info\")) {\n console.info(this.formatMessage(\"info\", message, meta));\n }\n }\n\n warn(message: string, meta?: Record<string, any>): void {\n if (this.shouldLog(\"warn\")) {\n console.warn(this.formatMessage(\"warn\", message, meta));\n }\n }\n\n error(message: string, meta?: Record<string, any>): void {\n if (this.shouldLog(\"error\")) {\n console.error(this.formatMessage(\"error\", message, meta));\n }\n }\n}\n\n// Export singleton instance\nexport const logger: Logger = new Logger();\n",
|
|
7
|
-
"/**\n * Archive Replay Client — backfills blocks from Hiro's daily event observer archive.\n *\n * The archive at archive.hiro.so contains zstd-compressed TSV files of raw\n * /new_block payloads (the exact NewBlockPayload JSON our indexer expects).\n * This client downloads the archive, streams + filters for specific block\n * heights, and POSTs matching payloads directly to the indexer.\n *\n * Zero external API dependency — only needs the static archive file.\n */\n\nimport { logger } from \"../logger.ts\";\n\nconst DEFAULT_ARCHIVE_URL =\n \"https://archive.hiro.so/mainnet/stacks-blockchain-api/mainnet-stacks-blockchain-api-latest.zst\";\n\nconst HEIGHT_REGEX = /\"block_height\":\\s*(\\d+)/;\n\nexport interface ReplayResult {\n replayed: number;\n errors: number;\n}\n\nexport interface ReplayOptions {\n onProgress?: (count: number, height: number) => void;\n}\n\nexport class ArchiveReplayClient {\n private archiveUrl: string;\n private archiveDir: string;\n\n constructor(opts?: { archiveUrl?: string; archiveDir?: string }) {\n this.archiveUrl = opts?.archiveUrl || process.env.ARCHIVE_URL || DEFAULT_ARCHIVE_URL;\n this.archiveDir = opts?.archiveDir || process.env.ARCHIVE_DIR || \"/tmp\";\n }\n\n /** HEAD request to archive URL — verify reachable and has content */\n async isAvailable(): Promise<boolean> {\n try {\n const res = await fetch(this.archiveUrl, {\n method: \"HEAD\",\n signal: AbortSignal.timeout(15_000),\n });\n const contentLength = Number(res.headers.get(\"content-length\") || 0);\n return res.ok && contentLength > 0;\n } catch {\n return false;\n }\n }\n\n /**\n * Download archive, stream-decompress, replay blocks matching gapHeights\n * to the indexer's /new_block endpoint.\n */\n async replayGaps(\n gapHeights: Set<number>,\n indexerUrl: string,\n opts?: ReplayOptions,\n ): Promise<ReplayResult> {\n if (gapHeights.size === 0) return { replayed: 0, errors: 0 };\n\n const maxHeight = Math.max(...gapHeights);\n const archivePath = `${this.archiveDir}/secondlayer-archive.zst`;\n let replayed = 0;\n let errors = 0;\n\n logger.info(\"Archive replay: downloading archive\", {\n url: this.archiveUrl.split(\"/\").pop(),\n targetHeights: gapHeights.size,\n maxHeight,\n });\n\n try {\n // Download archive\n await this.download(archivePath);\n\n logger.info(\"Archive replay: download complete, starting decompression + replay\");\n\n // Decompress via zstd subprocess\n const proc = Bun.spawn([\"zstd\", \"-d\", archivePath, \"--stdout\"], {\n stdout: \"pipe\",\n stderr: \"ignore\",\n });\n\n const reader = proc.stdout.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n const remaining = new Set(gapHeights);\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (remaining.size === 0) break;\n\n // Quick height check via regex (avoid full JSON parse)\n const match = HEIGHT_REGEX.exec(line);\n if (!match) continue;\n\n const height = parseInt(match[1]);\n\n // Skip blocks we don't need\n if (!remaining.has(height)) {\n // Early exit if past all gap heights\n if (height > maxHeight) break;\n continue;\n }\n\n // Extract payload from TSV (id \\t timestamp \\t path \\t payload)\n const tabIdx3 = nthIndex(line, \"\\t\", 3);\n if (tabIdx3 === -1) continue;\n\n const path = line.substring(nthIndex(line, \"\\t\", 2) + 1, tabIdx3);\n if (path !== \"/new_block\") continue;\n\n const payload = line.substring(tabIdx3 + 1);\n\n try {\n const res = await fetch(`${indexerUrl}/new_block`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Source\": \"archive-replay\",\n },\n body: payload,\n });\n\n if (res.ok) {\n replayed++;\n remaining.delete(height);\n opts?.onProgress?.(replayed, height);\n } else {\n errors++;\n logger.warn(\"Archive replay: indexer rejected block\", { height, status: res.status });\n }\n } catch (err) {\n errors++;\n logger.warn(\"Archive replay: POST failed\", { height, error: String(err) });\n }\n }\n\n // Early exit if all gaps filled or past max height\n if (remaining.size === 0) {\n proc.kill();\n break;\n }\n }\n\n // Wait for process to exit\n await proc.exited;\n\n if (remaining.size > 0) {\n logger.warn(\"Archive replay: some heights not found in archive\", {\n missing: remaining.size,\n sample: [...remaining].slice(0, 5),\n });\n }\n\n logger.info(\"Archive replay: complete\", { replayed, errors, missing: remaining.size });\n } finally {\n // Clean up archive file\n try {\n const file = Bun.file(archivePath);\n if (await file.exists()) {\n await Bun.write(archivePath, \"\"); // truncate\n const { unlinkSync } = await import(\"node:fs\");\n unlinkSync(archivePath);\n }\n } catch {\n // Best-effort cleanup\n }\n }\n\n return { replayed, errors };\n }\n\n /** Download archive to disk with streaming */\n private async download(destPath: string): Promise<void> {\n const res = await fetch(this.archiveUrl, {\n signal: AbortSignal.timeout(30 * 60 * 1000), // 30 min timeout\n });\n\n if (!res.ok || !res.body) {\n throw new Error(`Archive download failed: HTTP ${res.status}`);\n }\n\n const totalBytes = Number(res.headers.get(\"content-length\") || 0);\n const writer = Bun.file(destPath).writer();\n let downloaded = 0;\n let lastLog = 0;\n\n for await (const chunk of res.body) {\n writer.write(chunk);\n downloaded += chunk.byteLength;\n\n // Log progress every 5GB\n if (totalBytes > 0 && downloaded - lastLog > 5_000_000_000) {\n lastLog = downloaded;\n const pct = ((downloaded / totalBytes) * 100).toFixed(0);\n logger.info(\"Archive replay: downloading\", { progress: `${pct}%` });\n }\n }\n\n await writer.end();\n }\n}\n\n/** Find the nth occurrence of a character in a string */\nfunction nthIndex(str: string, char: string, n: number): number {\n let idx = -1;\n for (let i = 0; i < n; i++) {\n idx = str.indexOf(char, idx + 1);\n if (idx === -1) return -1;\n }\n return idx;\n}\n"
|
|
7
|
+
"/**\n * Archive Replay Client — backfills blocks from Hiro's daily event observer archive.\n *\n * The archive at archive.hiro.so contains zstd-compressed TSV files of raw\n * /new_block payloads (the exact NewBlockPayload JSON our indexer expects).\n * This client downloads the archive, streams + filters for specific block\n * heights, and POSTs matching payloads directly to the indexer.\n *\n * Caches the archive locally for up to 24h to avoid redundant ~25GB downloads.\n * Zero external API dependency — only needs the static archive file.\n */\n\nimport { logger } from \"../logger.ts\";\nimport { existsSync, unlinkSync, renameSync, readFileSync, writeFileSync } from \"node:fs\";\n\nconst DEFAULT_ARCHIVE_URL =\n \"https://archive.hiro.so/mainnet/stacks-blockchain-api/mainnet-stacks-blockchain-api-latest.zst\";\n\nconst HEIGHT_REGEX = /\"block_height\":\\s*(\\d+)/;\nconst CACHE_MAX_AGE_MS = 24 * 60 * 60 * 1000; // 24 hours\n\ninterface ArchiveMeta {\n lastModified: string | null;\n downloadedAt: string;\n}\n\nexport interface ReplayResult {\n replayed: number;\n errors: number;\n}\n\nexport interface ReplayOptions {\n onProgress?: (count: number, height: number) => void;\n}\n\nexport class ArchiveReplayClient {\n private archiveUrl: string;\n private archiveDir: string;\n\n constructor(opts?: { archiveUrl?: string; archiveDir?: string }) {\n this.archiveUrl = opts?.archiveUrl || process.env.ARCHIVE_URL || DEFAULT_ARCHIVE_URL;\n this.archiveDir = opts?.archiveDir || process.env.ARCHIVE_DIR || \"/tmp\";\n }\n\n private get archivePath() {\n return `${this.archiveDir}/secondlayer-archive.zst`;\n }\n private get metaPath() {\n return `${this.archiveDir}/secondlayer-archive.meta.json`;\n }\n private get partialPath() {\n return `${this.archiveDir}/secondlayer-archive.zst.partial`;\n }\n\n /** HEAD request to archive URL — verify reachable and has content */\n async isAvailable(): Promise<boolean> {\n try {\n const res = await fetch(this.archiveUrl, {\n method: \"HEAD\",\n signal: AbortSignal.timeout(15_000),\n });\n const contentLength = Number(res.headers.get(\"content-length\") || 0);\n return res.ok && contentLength > 0;\n } catch {\n return false;\n }\n }\n\n /**\n * Download archive, stream-decompress, replay blocks matching gapHeights\n * to the indexer's /new_block endpoint.\n */\n async replayGaps(\n gapHeights: Set<number>,\n indexerUrl: string,\n opts?: ReplayOptions,\n ): Promise<ReplayResult> {\n if (gapHeights.size === 0) return { replayed: 0, errors: 0 };\n\n const maxHeight = Math.max(...gapHeights);\n let replayed = 0;\n let errors = 0;\n\n try {\n await this.ensureArchive();\n\n logger.info(\"Archive replay: starting decompression + replay\", {\n targetHeights: gapHeights.size,\n maxHeight,\n });\n\n // Decompress via zstd subprocess\n const proc = Bun.spawn([\"zstd\", \"-d\", this.archivePath, \"--stdout\"], {\n stdout: \"pipe\",\n stderr: \"ignore\",\n });\n\n const reader = proc.stdout.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n const remaining = new Set(gapHeights);\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (remaining.size === 0) break;\n\n // Quick height check via regex (avoid full JSON parse)\n const match = HEIGHT_REGEX.exec(line);\n if (!match) continue;\n\n const height = parseInt(match[1]);\n\n // Skip blocks we don't need\n if (!remaining.has(height)) {\n // Early exit if past all gap heights\n if (height > maxHeight) break;\n continue;\n }\n\n // Extract payload from TSV (id \\t timestamp \\t path \\t payload)\n const tabIdx3 = nthIndex(line, \"\\t\", 3);\n if (tabIdx3 === -1) continue;\n\n const path = line.substring(nthIndex(line, \"\\t\", 2) + 1, tabIdx3);\n if (path !== \"/new_block\") continue;\n\n const payload = line.substring(tabIdx3 + 1);\n\n try {\n const res = await fetch(`${indexerUrl}/new_block`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Source\": \"archive-replay\",\n },\n body: payload,\n });\n\n if (res.ok) {\n replayed++;\n remaining.delete(height);\n opts?.onProgress?.(replayed, height);\n } else {\n errors++;\n logger.warn(\"Archive replay: indexer rejected block\", { height, status: res.status });\n }\n } catch (err) {\n errors++;\n logger.warn(\"Archive replay: POST failed\", { height, error: String(err) });\n }\n }\n\n // Early exit if all gaps filled or past max height\n if (remaining.size === 0) {\n proc.kill();\n break;\n }\n }\n\n // Wait for process to exit\n await proc.exited;\n\n if (remaining.size > 0) {\n logger.warn(\"Archive replay: some heights not found in archive\", {\n missing: remaining.size,\n sample: [...remaining].slice(0, 5),\n });\n }\n\n logger.info(\"Archive replay: complete\", { replayed, errors, missing: remaining.size });\n } catch (err) {\n // Clean up on error (corrupt/partial downloads)\n this.cleanupFile(this.archivePath);\n this.cleanupFile(this.metaPath);\n this.cleanupFile(this.partialPath);\n throw err;\n }\n\n return { replayed, errors };\n }\n\n /**\n * Ensure a fresh-enough archive exists locally.\n * Uses HTTP conditional requests to avoid redundant downloads.\n */\n private async ensureArchive(): Promise<void> {\n this.cleanStaleFiles();\n\n const meta = this.readMeta();\n const cached = existsSync(this.archivePath) && meta !== null;\n\n if (cached) {\n const age = Date.now() - new Date(meta.downloadedAt).getTime();\n if (age < CACHE_MAX_AGE_MS) {\n // Cache is fresh enough — check if remote has a newer version\n const headers: Record<string, string> = {};\n if (meta.lastModified) {\n headers[\"If-Modified-Since\"] = meta.lastModified;\n }\n\n try {\n const res = await fetch(this.archiveUrl, {\n method: \"HEAD\",\n headers,\n signal: AbortSignal.timeout(15_000),\n });\n\n if (res.status === 304) {\n logger.info(\"Archive replay: using cached archive\", {\n ageHrs: (age / 3600000).toFixed(1),\n });\n return;\n }\n\n // 200 = remote is newer, re-download below\n logger.info(\"Archive replay: remote archive is newer, re-downloading\");\n } catch {\n // Can't reach remote — use cache anyway\n logger.info(\"Archive replay: remote unreachable, using cached archive\");\n return;\n }\n } else {\n logger.info(\"Archive replay: cache expired, re-downloading\");\n }\n }\n\n // Download fresh archive\n logger.info(\"Archive replay: downloading archive\", {\n url: this.archiveUrl.split(\"/\").pop(),\n });\n\n const lastModified = await this.download(this.partialPath);\n\n // Atomic rename: partial → final\n renameSync(this.partialPath, this.archivePath);\n\n // Write meta sidecar\n this.writeMeta({ lastModified, downloadedAt: new Date().toISOString() });\n\n logger.info(\"Archive replay: download complete\");\n }\n\n /** Remove stale cache (> 24h) and orphaned partial files */\n private cleanStaleFiles(): void {\n try {\n // Clean orphaned partial downloads\n if (existsSync(this.partialPath)) {\n unlinkSync(this.partialPath);\n }\n\n // Clean stale cache\n const meta = this.readMeta();\n if (meta) {\n const age = Date.now() - new Date(meta.downloadedAt).getTime();\n if (age > CACHE_MAX_AGE_MS) {\n this.cleanupFile(this.archivePath);\n this.cleanupFile(this.metaPath);\n logger.info(\"Archive replay: cleaned stale cache\");\n }\n } else if (existsSync(this.archivePath)) {\n // Archive without meta — orphaned, clean up\n this.cleanupFile(this.archivePath);\n }\n } catch {\n // Best-effort cleanup\n }\n }\n\n private readMeta(): ArchiveMeta | null {\n try {\n if (!existsSync(this.metaPath)) return null;\n return JSON.parse(readFileSync(this.metaPath, \"utf-8\")) as ArchiveMeta;\n } catch {\n return null;\n }\n }\n\n private writeMeta(meta: ArchiveMeta): void {\n try {\n writeFileSync(this.metaPath, JSON.stringify(meta));\n } catch {\n // Best-effort\n }\n }\n\n private cleanupFile(path: string): void {\n try {\n if (existsSync(path)) unlinkSync(path);\n } catch {\n // Best-effort\n }\n }\n\n /** Download archive to disk with streaming. Returns Last-Modified header. */\n private async download(destPath: string): Promise<string | null> {\n const res = await fetch(this.archiveUrl, {\n signal: AbortSignal.timeout(30 * 60 * 1000), // 30 min timeout\n });\n\n if (!res.ok || !res.body) {\n throw new Error(`Archive download failed: HTTP ${res.status}`);\n }\n\n const lastModified = res.headers.get(\"last-modified\");\n const totalBytes = Number(res.headers.get(\"content-length\") || 0);\n const writer = Bun.file(destPath).writer();\n let downloaded = 0;\n let lastLog = 0;\n\n for await (const chunk of res.body) {\n writer.write(chunk);\n downloaded += chunk.byteLength;\n\n // Log progress every 5GB\n if (totalBytes > 0 && downloaded - lastLog > 5_000_000_000) {\n lastLog = downloaded;\n const pct = ((downloaded / totalBytes) * 100).toFixed(0);\n logger.info(\"Archive replay: downloading\", { progress: `${pct}%` });\n }\n }\n\n await writer.end();\n return lastModified;\n }\n}\n\n/** Find the nth occurrence of a character in a string */\nfunction nthIndex(str: string, char: string, n: number): number {\n let idx = -1;\n for (let i = 0; i < n; i++) {\n idx = str.indexOf(char, idx + 1);\n if (idx === -1) return -1;\n }\n return idx;\n}\n"
|
|
8
8
|
],
|
|
9
|
-
"mappings": "
|
|
10
|
-
"debugId": "
|
|
9
|
+
"mappings": "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",
|
|
10
|
+
"debugId": "255654A8B0CFD43D64756E2164756E21",
|
|
11
11
|
"names": []
|
|
12
12
|
}
|
package/dist/src/node/client.js
CHANGED
|
@@ -13,7 +13,6 @@ var __export = (target, all) => {
|
|
|
13
13
|
set: __exportSetter.bind(all, name)
|
|
14
14
|
});
|
|
15
15
|
};
|
|
16
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
17
16
|
|
|
18
17
|
// src/node/client.ts
|
|
19
18
|
class StacksNodeClient {
|
|
@@ -69,5 +68,5 @@ export {
|
|
|
69
68
|
StacksNodeClient
|
|
70
69
|
};
|
|
71
70
|
|
|
72
|
-
//# debugId=
|
|
71
|
+
//# debugId=76864EA72C96976464756E2164756E21
|
|
73
72
|
//# sourceMappingURL=client.js.map
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"\nexport interface NodeInfo {\n peer_version: number;\n pox_consensus: string;\n burn_block_height: number;\n stable_pox_consensus: string;\n stable_burn_block_height: number;\n server_version: string;\n network_id: number;\n parent_network_id: number;\n stacks_tip_height: number;\n stacks_tip: string;\n stacks_tip_consensus_hash: string;\n genesis_chainstate_hash: string;\n}\n\nexport interface BlockResponse {\n hash: string;\n height: number;\n parent_block_hash: string;\n burn_block_height: number;\n burn_block_hash: string;\n burn_block_time: number;\n index_block_hash: string;\n parent_index_block_hash: string;\n miner_txid: string;\n txs: string[];\n // Full block data varies by endpoint — kept minimal for fetch use case\n}\n\nexport class StacksNodeClient {\n private rpcUrl: string;\n\n constructor(rpcUrl?: string) {\n this.rpcUrl = rpcUrl || process.env.STACKS_NODE_RPC_URL || \"http://localhost:20443\";\n }\n\n async getInfo(): Promise<NodeInfo> {\n const res = await fetch(`${this.rpcUrl}/v2/info`, {\n signal: AbortSignal.timeout(10_000),\n });\n if (!res.ok) {\n throw new Error(`Node RPC /v2/info returned ${res.status}`);\n }\n return res.json() as Promise<NodeInfo>;\n }\n\n async getBlock(height: number): Promise<BlockResponse | null> {\n // Stacks API v2 block-by-height endpoint\n const res = await fetch(`${this.rpcUrl}/v2/blocks/${height}`, {\n signal: AbortSignal.timeout(30_000),\n });\n if (res.status === 404) return null;\n if (!res.ok) {\n throw new Error(`Node RPC /v2/blocks/${height} returned ${res.status}`);\n }\n return res.json() as Promise<BlockResponse>;\n }\n\n async isHealthy(): Promise<boolean> {\n try {\n const info = await this.getInfo();\n return info.stacks_tip_height > 0;\n } catch {\n return false;\n }\n }\n\n async getContractAbi(contractId: string): Promise<unknown> {\n const dotIdx = contractId.indexOf(\".\");\n const address = contractId.slice(0, dotIdx);\n const name = contractId.slice(dotIdx + 1);\n const res = await fetch(`${this.rpcUrl}/v2/contracts/interface/${address}/${name}`, {\n signal: AbortSignal.timeout(30_000),\n });\n if (!res.ok) {\n throw new Error(`Node RPC /v2/contracts/interface/${address}/${name} returned ${res.status}`);\n }\n return res.json();\n }\n\n getRpcUrl(): string {\n return this.rpcUrl;\n }\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;AA8BO,MAAM,iBAAiB;AAAA,EACpB;AAAA,EAER,WAAW,CAAC,QAAiB;AAAA,IAC3B,KAAK,SAAS,UAAU,QAAQ,IAAI,uBAAuB;AAAA;AAAA,OAGvD,QAAO,GAAsB;AAAA,IACjC,MAAM,MAAM,MAAM,MAAM,GAAG,KAAK,kBAAkB;AAAA,MAChD,QAAQ,YAAY,QAAQ,GAAM;AAAA,IACpC,CAAC;AAAA,IACD,IAAI,CAAC,IAAI,IAAI;AAAA,MACX,MAAM,IAAI,MAAM,8BAA8B,IAAI,QAAQ;AAAA,IAC5D;AAAA,IACA,OAAO,IAAI,KAAK;AAAA;AAAA,OAGZ,SAAQ,CAAC,QAA+C;AAAA,IAE5D,MAAM,MAAM,MAAM,MAAM,GAAG,KAAK,oBAAoB,UAAU;AAAA,MAC5D,QAAQ,YAAY,QAAQ,KAAM;AAAA,IACpC,CAAC;AAAA,IACD,IAAI,IAAI,WAAW;AAAA,MAAK,OAAO;AAAA,IAC/B,IAAI,CAAC,IAAI,IAAI;AAAA,MACX,MAAM,IAAI,MAAM,uBAAuB,mBAAmB,IAAI,QAAQ;AAAA,IACxE;AAAA,IACA,OAAO,IAAI,KAAK;AAAA;AAAA,OAGZ,UAAS,GAAqB;AAAA,IAClC,IAAI;AAAA,MACF,MAAM,OAAO,MAAM,KAAK,QAAQ;AAAA,MAChC,OAAO,KAAK,oBAAoB;AAAA,MAChC,MAAM;AAAA,MACN,OAAO;AAAA;AAAA;AAAA,OAIL,eAAc,CAAC,YAAsC;AAAA,IACzD,MAAM,SAAS,WAAW,QAAQ,GAAG;AAAA,IACrC,MAAM,UAAU,WAAW,MAAM,GAAG,MAAM;AAAA,IAC1C,MAAM,OAAO,WAAW,MAAM,SAAS,CAAC;AAAA,IACxC,MAAM,MAAM,MAAM,MAAM,GAAG,KAAK,iCAAiC,WAAW,QAAQ;AAAA,MAClF,QAAQ,YAAY,QAAQ,KAAM;AAAA,IACpC,CAAC;AAAA,IACD,IAAI,CAAC,IAAI,IAAI;AAAA,MACX,MAAM,IAAI,MAAM,oCAAoC,WAAW,iBAAiB,IAAI,QAAQ;AAAA,IAC9F;AAAA,IACA,OAAO,IAAI,KAAK;AAAA;AAAA,EAGlB,SAAS,GAAW;AAAA,IAClB,OAAO,KAAK;AAAA;AAEhB;",
|
|
8
|
+
"debugId": "76864EA72C96976464756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -13,7 +13,6 @@ var __export = (target, all) => {
|
|
|
13
13
|
set: __exportSetter.bind(all, name)
|
|
14
14
|
});
|
|
15
15
|
};
|
|
16
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
17
16
|
|
|
18
17
|
// src/env.ts
|
|
19
18
|
import { z } from "zod/v4";
|
|
@@ -469,5 +468,5 @@ export {
|
|
|
469
468
|
HiroClient
|
|
470
469
|
};
|
|
471
470
|
|
|
472
|
-
//# debugId=
|
|
471
|
+
//# debugId=84E732ABB4DEC21A64756E2164756E21
|
|
473
472
|
//# sourceMappingURL=hiro-client.js.map
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"import { getEnv } from \"./env.ts\";\n\ntype LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nclass Logger {\n private _level?: LogLevel;\n private _isProduction?: boolean;\n private _initialized = false;\n\n private init() {\n if (this._initialized) return;\n this._initialized = true;\n try {\n const env = getEnv();\n this._level = env.LOG_LEVEL;\n this._isProduction = env.NODE_ENV === \"production\";\n } catch {\n // Fallback when env is unavailable (e.g. tests without DATABASE_URL)\n this._level = \"info\";\n this._isProduction = false;\n }\n }\n\n private get level(): LogLevel {\n this.init();\n return this._level!;\n }\n\n private get isProduction(): boolean {\n this.init();\n return this._isProduction!;\n }\n\n private shouldLog(level: LogLevel): boolean {\n return LOG_LEVELS[level] >= LOG_LEVELS[this.level];\n }\n\n private formatMessage(level: LogLevel, message: string, meta?: Record<string, any>) {\n const timestamp = new Date().toISOString();\n\n if (this.isProduction) {\n // JSON output for production\n return JSON.stringify({\n timestamp,\n level,\n message,\n ...meta,\n });\n }\n\n // Human-readable output for development\n const metaStr = meta ? ` ${JSON.stringify(meta)}` : \"\";\n return `[${timestamp}] ${level.toUpperCase()}: ${message}${metaStr}`;\n }\n\n debug(message: string, meta?: Record<string, any>): void {\n if (this.shouldLog(\"debug\")) {\n console.debug(this.formatMessage(\"debug\", message, meta));\n }\n }\n\n info(message: string, meta?: Record<string, any>): void {\n if (this.shouldLog(\"info\")) {\n console.info(this.formatMessage(\"info\", message, meta));\n }\n }\n\n warn(message: string, meta?: Record<string, any>): void {\n if (this.shouldLog(\"warn\")) {\n console.warn(this.formatMessage(\"warn\", message, meta));\n }\n }\n\n error(message: string, meta?: Record<string, any>): void {\n if (this.shouldLog(\"error\")) {\n console.error(this.formatMessage(\"error\", message, meta));\n }\n }\n}\n\n// Export singleton instance\nexport const logger: Logger = new Logger();\n",
|
|
7
7
|
"/**\n * Hiro public API client for backfilling historical block data.\n *\n * The stacks-node RPC `/v2/blocks/{height}` only returns block headers + tx IDs,\n * not full transaction data or events. The Hiro API serves complete block data\n * that we can transform into the NewBlockPayload format our indexer expects.\n */\n\nimport { logger } from \"../logger.ts\";\n\nconst DEFAULT_HIRO_API_URL = \"https://api.mainnet.hiro.so\";\n\n/** v2 /extended/v2/blocks/{height} response */\nexport interface HiroBlockResponse {\n canonical: boolean;\n height: number;\n hash: string;\n block_time: number;\n block_time_iso: string;\n index_block_hash: string;\n parent_block_hash: string;\n parent_index_block_hash: string;\n burn_block_hash: string;\n burn_block_height: number;\n burn_block_time: number;\n miner_txid: string;\n tx_count: number;\n}\n\n/** v2 /extended/v2/blocks/{height}/transactions response */\nexport interface HiroBlockTxsResponse {\n limit: number;\n offset: number;\n total: number;\n results: HiroTxResponse[];\n}\n\nexport interface HiroTxResponse {\n tx_id: string;\n tx_type: string;\n tx_status: string;\n sender_address: string;\n fee_rate: string;\n nonce: number;\n block_hash: string;\n block_height: number;\n burn_block_height: number;\n tx_index: number;\n event_count: number;\n token_transfer?: {\n recipient_address: string;\n amount: string;\n memo: string;\n };\n contract_call?: {\n contract_id: string;\n function_name: string;\n function_args: unknown[];\n };\n smart_contract?: {\n contract_id: string;\n source_code: string;\n };\n}\n\nexport interface HiroEvent {\n event_index: number;\n event_type: string; // \"stx_asset\" | \"fungible_token_asset\" | \"non_fungible_token_asset\" | \"smart_contract_log\"\n tx_id: string;\n asset?: {\n asset_event_type: string; // \"transfer\" | \"mint\" | \"burn\"\n sender?: string;\n recipient?: string;\n amount?: string;\n memo?: string;\n asset_id?: string;\n value?: unknown;\n };\n contract_log?: {\n contract_id: string;\n topic: string;\n value: unknown;\n };\n}\n\nexport interface HiroEventsResponse {\n limit: number;\n offset: number;\n events: HiroEvent[];\n}\n\n/** Shape our indexer expects at POST /new_block */\nexport interface NewBlockPayload {\n block_hash: string;\n block_height: number;\n index_block_hash: string;\n parent_block_hash: string;\n parent_index_block_hash: string;\n burn_block_hash: string;\n burn_block_height: number;\n burn_block_timestamp: number;\n miner_txid: string;\n timestamp: number;\n transactions: TransactionPayload[];\n events: TransactionEventPayload[];\n}\n\ninterface TransactionPayload {\n txid: string;\n raw_tx: string;\n status: string;\n tx_index: number;\n tx_type?: string;\n sender_address?: string;\n}\n\ninterface TransactionEventPayload {\n txid: string;\n event_index: number;\n committed: boolean;\n type: string;\n stx_transfer_event?: { sender: string; recipient: string; amount: string; memo?: string };\n stx_mint_event?: { recipient: string; amount: string };\n stx_burn_event?: { sender: string; amount: string };\n stx_lock_event?: { locked_amount: string; unlock_height: string; locked_address: string };\n ft_transfer_event?: { asset_identifier: string; sender: string; recipient: string; amount: string };\n ft_mint_event?: { asset_identifier: string; recipient: string; amount: string };\n ft_burn_event?: { asset_identifier: string; sender: string; amount: string };\n nft_transfer_event?: { asset_identifier: string; sender: string; recipient: string; value: unknown };\n nft_mint_event?: { asset_identifier: string; recipient: string; value: unknown };\n nft_burn_event?: { asset_identifier: string; sender: string; value: unknown };\n smart_contract_event?: { contract_identifier: string; topic: string; value: unknown };\n}\n\nexport interface GetBlockOptions {\n /** Fetch actual raw_tx hex for each transaction (instead of \"0x00\" placeholder) */\n includeRawTx?: boolean;\n /** Max concurrent raw_tx fetches per block (default: 10) */\n rawTxConcurrency?: number;\n}\n\nexport class HiroClient {\n private apiUrl: string;\n private fallbackUrl: string | undefined;\n private apiKey: string | undefined;\n private maxRetries: number;\n\n constructor(apiUrl?: string, maxRetries = 5) {\n this.apiUrl = apiUrl || process.env.HIRO_API_URL || DEFAULT_HIRO_API_URL;\n this.fallbackUrl = process.env.HIRO_FALLBACK_URL;\n this.apiKey = process.env.HIRO_API_KEY;\n this.maxRetries = maxRetries;\n }\n\n private get headers(): Record<string, string> {\n return this.apiKey ? { \"x-hiro-api-key\": this.apiKey } : {};\n }\n\n /** Fetch with retry on 429/5xx using exponential backoff */\n private async fetchWithRetry(url: string, timeoutMs = 120_000): Promise<Response> {\n for (let attempt = 0; attempt < this.maxRetries; attempt++) {\n const res = await fetch(url, { headers: this.headers, signal: AbortSignal.timeout(timeoutMs) });\n\n if (res.ok || res.status === 404) return res;\n\n if (res.status === 429 || res.status >= 500) {\n const delay = Math.min(1000 * Math.pow(2, attempt), 10_000);\n logger.info(\"Rate limited, retrying\", { url: url.split(\"/\").slice(-2).join(\"/\"), attempt, delay });\n await new Promise((r) => setTimeout(r, delay));\n continue;\n }\n\n // 4xx (not 404/429) — don't retry\n return res;\n }\n\n // Final attempt\n return fetch(url, { headers: this.headers, signal: AbortSignal.timeout(timeoutMs) });\n }\n\n /**\n * Fetch a complete block by height, including all transactions and events,\n * transformed into the NewBlockPayload format our indexer expects.\n *\n * Uses 3-step approach:\n * 1. GET /extended/v2/blocks/{height} — block metadata\n * 2. GET /extended/v2/blocks/{height}/transactions — all txs (paginated)\n * 3. GET /extended/v1/tx/events?tx_id={txId} — events per tx (only for txs with events)\n */\n async getBlockForIndexer(height: number, options?: GetBlockOptions): Promise<NewBlockPayload | null> {\n // 1. Fetch block metadata (try primary, fallback on 404)\n let block = await this.fetchBlock(height);\n let usingFallback = false;\n if (!block && this.fallbackUrl) {\n block = await this.fetchBlock(height, this.fallbackUrl);\n if (block) usingFallback = true;\n }\n if (!block) return null;\n\n // 2. Fetch all transactions via v2 block/transactions endpoint\n const baseUrl = usingFallback ? this.fallbackUrl! : this.apiUrl;\n const hiroTxs = await this.fetchBlockTransactions(height, baseUrl);\n\n const txPayloads: TransactionPayload[] = [];\n const eventPayloads: TransactionEventPayload[] = [];\n\n for (const hiroTx of hiroTxs) {\n txPayloads.push({\n txid: hiroTx.tx_id,\n raw_tx: \"0x00\",\n status: mapTxStatus(hiroTx.tx_status),\n tx_index: hiroTx.tx_index ?? 0,\n tx_type: mapTxType(hiroTx.tx_type),\n sender_address: hiroTx.sender_address,\n });\n\n // 3. Fetch events only for txs that have them\n if (hiroTx.event_count > 0) {\n if (hiroTx.event_count > 1000) {\n logger.info(\"Fetching large event set\", { txId: hiroTx.tx_id, eventCount: hiroTx.event_count, height });\n }\n try {\n const events = await this.fetchAllEvents(hiroTx.tx_id, baseUrl);\n eventPayloads.push(...events);\n } catch (err) {\n logger.warn(\"Failed to fetch events for backfill\", { txId: hiroTx.tx_id, error: String(err) });\n }\n }\n }\n\n // 4. Optionally fetch raw_tx for all transactions\n if (options?.includeRawTx && txPayloads.length > 0) {\n const txIds = txPayloads.map((t) => t.txid);\n const rawTxMap = await this.fetchRawTxBatch(txIds, options.rawTxConcurrency);\n for (const txPayload of txPayloads) {\n const raw = rawTxMap.get(txPayload.txid);\n if (raw) txPayload.raw_tx = raw;\n }\n }\n\n return {\n block_hash: block.hash,\n block_height: block.height,\n index_block_hash: block.index_block_hash,\n parent_block_hash: block.parent_block_hash,\n parent_index_block_hash: block.parent_index_block_hash,\n burn_block_hash: block.burn_block_hash,\n burn_block_height: block.burn_block_height,\n burn_block_timestamp: block.burn_block_time,\n miner_txid: block.miner_txid,\n timestamp: block.block_time,\n transactions: txPayloads,\n events: eventPayloads,\n };\n }\n\n /** v2 block metadata */\n private async fetchBlock(height: number, baseUrl?: string): Promise<HiroBlockResponse | null> {\n const url = baseUrl || this.apiUrl;\n const res = await this.fetchWithRetry(`${url}/extended/v2/blocks/${height}`);\n if (res.status === 404) return null;\n if (!res.ok) throw new Error(`Hiro API block/${height} returned ${res.status}`);\n return res.json() as Promise<HiroBlockResponse>;\n }\n\n /** v2 block transactions (paginated) */\n private async fetchBlockTransactions(height: number, baseUrl?: string): Promise<HiroTxResponse[]> {\n const url = baseUrl || this.apiUrl;\n const txs: HiroTxResponse[] = [];\n let offset = 0;\n const limit = 50;\n\n while (true) {\n const res = await this.fetchWithRetry(\n `${url}/extended/v2/blocks/${height}/transactions?limit=${limit}&offset=${offset}`\n );\n if (!res.ok) throw new Error(`Hiro API block/${height}/transactions returned ${res.status}`);\n\n const data = (await res.json()) as HiroBlockTxsResponse;\n txs.push(...data.results);\n\n if (txs.length >= data.total || data.results.length < limit) break;\n offset += limit;\n }\n\n return txs;\n }\n\n private async fetchAllEvents(txId: string, baseUrl?: string, _maxEvents?: number): Promise<TransactionEventPayload[]> {\n const url = baseUrl || this.apiUrl;\n const events: TransactionEventPayload[] = [];\n let offset = 0;\n const limit = 100;\n\n while (true) {\n const res = await this.fetchWithRetry(\n `${url}/extended/v1/tx/events?tx_id=${txId}&limit=${limit}&offset=${offset}`\n );\n if (!res.ok) {\n logger.warn(\"Failed to fetch events from Hiro\", { txId, status: res.status });\n break;\n }\n\n const data = (await res.json()) as HiroEventsResponse;\n for (const hEvent of data.events) {\n const converted = convertHiroEvent(hEvent);\n if (converted) events.push(converted);\n }\n\n if (data.events.length < limit) break;\n offset += limit;\n }\n\n return events;\n }\n\n /** Fetch raw_tx hex for a single transaction */\n async fetchRawTx(txId: string): Promise<string | null> {\n try {\n const res = await this.fetchWithRetry(`${this.apiUrl}/extended/v1/tx/${txId}/raw`, 10_000);\n if (!res.ok) return null;\n const data = (await res.json()) as { raw_tx: string };\n return data.raw_tx || null;\n } catch {\n return null;\n }\n }\n\n /** Fetch raw_tx for multiple transactions with bounded concurrency */\n async fetchRawTxBatch(txIds: string[], concurrency = 10): Promise<Map<string, string>> {\n const results = new Map<string, string>();\n for (let i = 0; i < txIds.length; i += concurrency) {\n const chunk = txIds.slice(i, i + concurrency);\n const settled = await Promise.allSettled(\n chunk.map(async (txId) => {\n const raw = await this.fetchRawTx(txId);\n return { txId, raw };\n })\n );\n for (const result of settled) {\n if (result.status === \"fulfilled\" && result.value.raw) {\n results.set(result.value.txId, result.value.raw);\n }\n }\n }\n return results;\n }\n\n /** Fetch current chain tip height from Hiro API status endpoint */\n async fetchChainTip(): Promise<number> {\n const res = await this.fetchWithRetry(`${this.apiUrl}/extended/v1/status`);\n if (!res.ok) throw new Error(`Hiro API /status returned ${res.status}`);\n const data = (await res.json()) as { chain_tip?: { block_height: number }; stacks_tip_height?: number };\n return data.chain_tip?.block_height ?? data.stacks_tip_height ?? 0;\n }\n\n async isHealthy(): Promise<boolean> {\n try {\n const res = await fetch(`${this.apiUrl}/extended/v1/status`, {\n headers: this.headers,\n signal: AbortSignal.timeout(10_000),\n });\n // 429 = rate limited but reachable\n return res.ok || res.status === 429;\n } catch {\n return false;\n }\n }\n\n getApiUrl(): string {\n return this.apiUrl;\n }\n}\n\n/** Map Hiro tx_status to our indexer's expected format */\nfunction mapTxStatus(status: string): string {\n switch (status) {\n case \"success\":\n return \"success\";\n case \"abort_by_response\":\n case \"abort_by_post_condition\":\n return status;\n default:\n return \"success\";\n }\n}\n\n/** Map Hiro tx_type to node event tx_type */\nfunction mapTxType(type: string): string {\n switch (type) {\n case \"token_transfer\":\n return \"token_transfer\";\n case \"contract_call\":\n return \"contract_call\";\n case \"smart_contract\":\n return \"smart_contract\";\n case \"coinbase\":\n return \"coinbase\";\n case \"tenure_change\":\n return \"tenure_change\";\n case \"poison_microblock\":\n return \"poison_microblock\";\n default:\n return type;\n }\n}\n\n/**\n * Convert a Hiro API event to our indexer's TransactionEvent format.\n *\n * Hiro uses:\n * event_type: \"stx_asset\" | \"fungible_token_asset\" | \"non_fungible_token_asset\" | \"smart_contract_log\"\n * asset.asset_event_type: \"transfer\" | \"mint\" | \"burn\" | \"lock\"\n *\n * Our indexer expects:\n * type: \"stx_transfer_event\" | \"stx_mint_event\" | \"ft_transfer_event\" | \"smart_contract_event\" | ...\n */\nfunction convertHiroEvent(hEvent: HiroEvent): TransactionEventPayload | null {\n const base = {\n txid: hEvent.tx_id,\n event_index: hEvent.event_index,\n committed: true,\n };\n\n if (hEvent.event_type === \"stx_asset\" && hEvent.asset) {\n const a = hEvent.asset;\n switch (a.asset_event_type) {\n case \"transfer\":\n return {\n ...base,\n type: \"stx_transfer_event\",\n stx_transfer_event: {\n sender: a.sender!,\n recipient: a.recipient!,\n amount: a.amount!,\n memo: a.memo,\n },\n };\n case \"mint\":\n return {\n ...base,\n type: \"stx_mint_event\",\n stx_mint_event: { recipient: a.recipient!, amount: a.amount! },\n };\n case \"burn\":\n return {\n ...base,\n type: \"stx_burn_event\",\n stx_burn_event: { sender: a.sender!, amount: a.amount! },\n };\n case \"lock\":\n return {\n ...base,\n type: \"stx_lock_event\",\n stx_lock_event: {\n locked_amount: a.amount!,\n unlock_height: \"0\",\n locked_address: a.sender!,\n },\n };\n }\n }\n\n if (hEvent.event_type === \"fungible_token_asset\" && hEvent.asset) {\n const a = hEvent.asset;\n const assetId = a.asset_id || \"\";\n switch (a.asset_event_type) {\n case \"transfer\":\n return {\n ...base,\n type: \"ft_transfer_event\",\n ft_transfer_event: {\n asset_identifier: assetId,\n sender: a.sender!,\n recipient: a.recipient!,\n amount: a.amount!,\n },\n };\n case \"mint\":\n return {\n ...base,\n type: \"ft_mint_event\",\n ft_mint_event: { asset_identifier: assetId, recipient: a.recipient!, amount: a.amount! },\n };\n case \"burn\":\n return {\n ...base,\n type: \"ft_burn_event\",\n ft_burn_event: { asset_identifier: assetId, sender: a.sender!, amount: a.amount! },\n };\n }\n }\n\n if (hEvent.event_type === \"non_fungible_token_asset\" && hEvent.asset) {\n const a = hEvent.asset;\n const assetId = a.asset_id || \"\";\n switch (a.asset_event_type) {\n case \"transfer\":\n return {\n ...base,\n type: \"nft_transfer_event\",\n nft_transfer_event: {\n asset_identifier: assetId,\n sender: a.sender!,\n recipient: a.recipient!,\n value: a.value,\n },\n };\n case \"mint\":\n return {\n ...base,\n type: \"nft_mint_event\",\n nft_mint_event: { asset_identifier: assetId, recipient: a.recipient!, value: a.value },\n };\n case \"burn\":\n return {\n ...base,\n type: \"nft_burn_event\",\n nft_burn_event: { asset_identifier: assetId, sender: a.sender!, value: a.value },\n };\n }\n }\n\n if (hEvent.event_type === \"smart_contract_log\" && hEvent.contract_log) {\n return {\n ...base,\n type: \"smart_contract_event\",\n smart_contract_event: {\n contract_identifier: hEvent.contract_log.contract_id,\n topic: hEvent.contract_log.topic,\n value: hEvent.contract_log.value,\n },\n };\n }\n\n logger.debug(\"Unknown Hiro event type, skipping\", {\n eventType: hEvent.event_type,\n txId: hEvent.tx_id,\n });\n return null;\n}\n"
|
|
8
8
|
],
|
|
9
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAGA,IAAM,iBAAiB,EAAE,OAAO,EAAE,UAAU,CAAC,QAAQ;AAAA,EACnD,MAAM,WAAW,IAAI,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AAAA,EACnE,MAAM,QAAQ,CAAC,WAAW,SAAS;AAAA,EACnC,WAAW,KAAK,UAAU;AAAA,IACxB,IAAI,CAAC,MAAM,SAAS,CAAC,GAAG;AAAA,MACtB,MAAM,IAAI,MAAM,oBAAoB,sBAAsB,MAAM,KAAK,IAAI,GAAG;AAAA,IAC9E;AAAA,EACF;AAAA,EACA,OAAO;AAAA,CACR;AAYD,IAAM,YAAwC,EAAE,OAAO;AAAA,EACrD,cAAc,EAAE,WACd,CAAC,QAAS,OAAO,QAAQ,YAAY,IAAI,WAAW,IAAK,YAAY,KACrE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAC5B;AAAA,EACA,SAAS,EAAE,KAAK,CAAC,WAAW,SAAS,CAAC,EAAE,SAAS;AAAA,EACjD,UAAU,eAAe,SAAS;AAAA,EAClC,WAAW,EAAE,KAAK,CAAC,SAAS,QAAQ,QAAQ,OAAO,CAAC,EAAE,QAAQ,MAAM;AAAA,EACpE,UAAU,EAAE,KAAK,CAAC,eAAe,cAAc,MAAM,CAAC,EAAE,QAAQ,aAAa;AAC/E,CAAC;AAMD,IAAI,YAAwB;AAErB,SAAS,MAAM,GAAQ;AAAA,EAC5B,IAAI,WAAW;AAAA,IACb,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,SAAS,UAAU,UAAU,QAAQ,GAAG;AAAA,EAE9C,IAAI,CAAC,OAAO,SAAS;AAAA,IACnB,QAAQ,MAAM,sCAAqC;AAAA,IACnD,QAAQ,MAAM,EAAE,aAAa,OAAO,KAAK,CAAC;AAAA,IAC1C,MAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AAAA,EAGA,IAAI;AAAA,EACJ,IAAI,OAAO,KAAK,YAAY,OAAO,KAAK,SAAS,SAAS,GAAG;AAAA,IAC3D,kBAAkB,OAAO,KAAK;AAAA,EAChC,EAAO,SAAI,OAAO,KAAK,SAAS;AAAA,IAC9B,kBAAkB,CAAC,OAAO,KAAK,OAAO;AAAA,EACxC,EAAO;AAAA,IACL,kBAAkB,CAAC,SAAS;AAAA;AAAA,EAG9B,YAAY,KAAK,OAAO,MAAM,gBAAgB;AAAA,EAC9C,OAAO;AAAA;;AC7DT,IAAM,aAAuC;AAAA,EAC3C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AACT;AAAA;AAEA,MAAM,OAAO;AAAA,EACH;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EAEf,IAAI,GAAG;AAAA,IACb,IAAI,KAAK;AAAA,MAAc;AAAA,IACvB,KAAK,eAAe;AAAA,IACpB,IAAI;AAAA,MACF,MAAM,MAAM,OAAO;AAAA,MACnB,KAAK,SAAS,IAAI;AAAA,MAClB,KAAK,gBAAgB,IAAI,aAAa;AAAA,MACtC,MAAM;AAAA,MAEN,KAAK,SAAS;AAAA,MACd,KAAK,gBAAgB;AAAA;AAAA;AAAA,MAIb,KAAK,GAAa;AAAA,IAC5B,KAAK,KAAK;AAAA,IACV,OAAO,KAAK;AAAA;AAAA,MAGF,YAAY,GAAY;AAAA,IAClC,KAAK,KAAK;AAAA,IACV,OAAO,KAAK;AAAA;AAAA,EAGN,SAAS,CAAC,OAA0B;AAAA,IAC1C,OAAO,WAAW,UAAU,WAAW,KAAK;AAAA;AAAA,EAGtC,aAAa,CAAC,OAAiB,SAAiB,MAA4B;AAAA,IAClF,MAAM,YAAY,IAAI,KAAK,EAAE,YAAY;AAAA,IAEzC,IAAI,KAAK,cAAc;AAAA,MAErB,OAAO,KAAK,UAAU;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,WACG;AAAA,MACL,CAAC;AAAA,IACH;AAAA,IAGA,MAAM,UAAU,OAAO,IAAI,KAAK,UAAU,IAAI,MAAM;AAAA,IACpD,OAAO,IAAI,cAAc,MAAM,YAAY,MAAM,UAAU;AAAA;AAAA,EAG7D,KAAK,CAAC,SAAiB,MAAkC;AAAA,IACvD,IAAI,KAAK,UAAU,OAAO,GAAG;AAAA,MAC3B,QAAQ,MAAM,KAAK,cAAc,SAAS,SAAS,IAAI,CAAC;AAAA,IAC1D;AAAA;AAAA,EAGF,IAAI,CAAC,SAAiB,MAAkC;AAAA,IACtD,IAAI,KAAK,UAAU,MAAM,GAAG;AAAA,MAC1B,QAAQ,KAAK,KAAK,cAAc,QAAQ,SAAS,IAAI,CAAC;AAAA,IACxD;AAAA;AAAA,EAGF,IAAI,CAAC,SAAiB,MAAkC;AAAA,IACtD,IAAI,KAAK,UAAU,MAAM,GAAG;AAAA,MAC1B,QAAQ,KAAK,KAAK,cAAc,QAAQ,SAAS,IAAI,CAAC;AAAA,IACxD;AAAA;AAAA,EAGF,KAAK,CAAC,SAAiB,MAAkC;AAAA,IACvD,IAAI,KAAK,UAAU,OAAO,GAAG;AAAA,MAC3B,QAAQ,MAAM,KAAK,cAAc,SAAS,SAAS,IAAI,CAAC;AAAA,IAC1D;AAAA;AAEJ;AAGO,IAAM,SAAiB,IAAI;;;AC9ElC,IAAM,uBAAuB;AAAA;AAmItB,MAAM,WAAW;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,WAAW,CAAC,QAAiB,aAAa,GAAG;AAAA,IAC3C,KAAK,SAAS,UAAU,QAAQ,IAAI,gBAAgB;AAAA,IACpD,KAAK,cAAc,QAAQ,IAAI;AAAA,IAC/B,KAAK,SAAS,QAAQ,IAAI;AAAA,IAC1B,KAAK,aAAa;AAAA;AAAA,MAGR,OAAO,GAA2B;AAAA,IAC5C,OAAO,KAAK,SAAS,EAAE,kBAAkB,KAAK,OAAO,IAAI,CAAC;AAAA;AAAA,OAI9C,eAAc,CAAC,KAAa,YAAY,QAA4B;AAAA,IAChF,SAAS,UAAU,EAAG,UAAU,KAAK,YAAY,WAAW;AAAA,MAC1D,MAAM,MAAM,MAAM,MAAM,KAAK,EAAE,SAAS,KAAK,SAAS,QAAQ,YAAY,QAAQ,SAAS,EAAE,CAAC;AAAA,MAE9F,IAAI,IAAI,MAAM,IAAI,WAAW;AAAA,QAAK,OAAO;AAAA,MAEzC,IAAI,IAAI,WAAW,OAAO,IAAI,UAAU,KAAK;AAAA,QAC3C,MAAM,QAAQ,KAAK,IAAI,OAAO,KAAK,IAAI,GAAG,OAAO,GAAG,GAAM;AAAA,QAC1D,OAAO,KAAK,0BAA0B,EAAE,KAAK,IAAI,MAAM,GAAG,EAAE,MAAM,EAAE,EAAE,KAAK,GAAG,GAAG,SAAS,MAAM,CAAC;AAAA,QACjG,MAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC;AAAA,QAC7C;AAAA,MACF;AAAA,MAGA,OAAO;AAAA,IACT;AAAA,IAGA,OAAO,MAAM,KAAK,EAAE,SAAS,KAAK,SAAS,QAAQ,YAAY,QAAQ,SAAS,EAAE,CAAC;AAAA;AAAA,OAY/E,mBAAkB,CAAC,QAAgB,SAA4D;AAAA,IAEnG,IAAI,QAAQ,MAAM,KAAK,WAAW,MAAM;AAAA,IACxC,IAAI,gBAAgB;AAAA,IACpB,IAAI,CAAC,SAAS,KAAK,aAAa;AAAA,MAC9B,QAAQ,MAAM,KAAK,WAAW,QAAQ,KAAK,WAAW;AAAA,MACtD,IAAI;AAAA,QAAO,gBAAgB;AAAA,IAC7B;AAAA,IACA,IAAI,CAAC;AAAA,MAAO,OAAO;AAAA,IAGnB,MAAM,UAAU,gBAAgB,KAAK,cAAe,KAAK;AAAA,IACzD,MAAM,UAAU,MAAM,KAAK,uBAAuB,QAAQ,OAAO;AAAA,IAEjE,MAAM,aAAmC,CAAC;AAAA,IAC1C,MAAM,gBAA2C,CAAC;AAAA,IAElD,WAAW,UAAU,SAAS;AAAA,MAC5B,WAAW,KAAK;AAAA,QACd,MAAM,OAAO;AAAA,QACb,QAAQ;AAAA,QACR,QAAQ,YAAY,OAAO,SAAS;AAAA,QACpC,UAAU,OAAO,YAAY;AAAA,QAC7B,SAAS,UAAU,OAAO,OAAO;AAAA,QACjC,gBAAgB,OAAO;AAAA,MACzB,CAAC;AAAA,MAGD,IAAI,OAAO,cAAc,GAAG;AAAA,QAC1B,IAAI,OAAO,cAAc,MAAM;AAAA,UAC7B,OAAO,KAAK,4BAA4B,EAAE,MAAM,OAAO,OAAO,YAAY,OAAO,aAAa,OAAO,CAAC;AAAA,QACxG;AAAA,QACA,IAAI;AAAA,UACF,MAAM,SAAS,MAAM,KAAK,eAAe,OAAO,OAAO,OAAO;AAAA,UAC9D,cAAc,KAAK,GAAG,MAAM;AAAA,UAC5B,OAAO,KAAK;AAAA,UACZ,OAAO,KAAK,uCAAuC,EAAE,MAAM,OAAO,OAAO,OAAO,OAAO,GAAG,EAAE,CAAC;AAAA;AAAA,MAEjG;AAAA,IACF;AAAA,IAGA,IAAI,SAAS,gBAAgB,WAAW,SAAS,GAAG;AAAA,MAClD,MAAM,QAAQ,WAAW,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,MAC1C,MAAM,WAAW,MAAM,KAAK,gBAAgB,OAAO,QAAQ,gBAAgB;AAAA,MAC3E,WAAW,aAAa,YAAY;AAAA,QAClC,MAAM,MAAM,SAAS,IAAI,UAAU,IAAI;AAAA,QACvC,IAAI;AAAA,UAAK,UAAU,SAAS;AAAA,MAC9B;AAAA,IACF;AAAA,IAEA,OAAO;AAAA,MACL,YAAY,MAAM;AAAA,MAClB,cAAc,MAAM;AAAA,MACpB,kBAAkB,MAAM;AAAA,MACxB,mBAAmB,MAAM;AAAA,MACzB,yBAAyB,MAAM;AAAA,MAC/B,iBAAiB,MAAM;AAAA,MACvB,mBAAmB,MAAM;AAAA,MACzB,sBAAsB,MAAM;AAAA,MAC5B,YAAY,MAAM;AAAA,MAClB,WAAW,MAAM;AAAA,MACjB,cAAc;AAAA,MACd,QAAQ;AAAA,IACV;AAAA;AAAA,OAIY,WAAU,CAAC,QAAgB,SAAqD;AAAA,IAC5F,MAAM,MAAM,WAAW,KAAK;AAAA,IAC5B,MAAM,MAAM,MAAM,KAAK,eAAe,GAAG,0BAA0B,QAAQ;AAAA,IAC3E,IAAI,IAAI,WAAW;AAAA,MAAK,OAAO;AAAA,IAC/B,IAAI,CAAC,IAAI;AAAA,MAAI,MAAM,IAAI,MAAM,kBAAkB,mBAAmB,IAAI,QAAQ;AAAA,IAC9E,OAAO,IAAI,KAAK;AAAA;AAAA,OAIJ,uBAAsB,CAAC,QAAgB,SAA6C;AAAA,IAChG,MAAM,MAAM,WAAW,KAAK;AAAA,IAC5B,MAAM,MAAwB,CAAC;AAAA,IAC/B,IAAI,SAAS;AAAA,IACb,MAAM,QAAQ;AAAA,IAEd,OAAO,MAAM;AAAA,MACX,MAAM,MAAM,MAAM,KAAK,eACrB,GAAG,0BAA0B,6BAA6B,gBAAgB,QAC5E;AAAA,MACA,IAAI,CAAC,IAAI;AAAA,QAAI,MAAM,IAAI,MAAM,kBAAkB,gCAAgC,IAAI,QAAQ;AAAA,MAE3F,MAAM,OAAQ,MAAM,IAAI,KAAK;AAAA,MAC7B,IAAI,KAAK,GAAG,KAAK,OAAO;AAAA,MAExB,IAAI,IAAI,UAAU,KAAK,SAAS,KAAK,QAAQ,SAAS;AAAA,QAAO;AAAA,MAC7D,UAAU;AAAA,IACZ;AAAA,IAEA,OAAO;AAAA;AAAA,OAGK,eAAc,CAAC,MAAc,SAAkB,YAAyD;AAAA,IACpH,MAAM,MAAM,WAAW,KAAK;AAAA,IAC5B,MAAM,SAAoC,CAAC;AAAA,IAC3C,IAAI,SAAS;AAAA,IACb,MAAM,QAAQ;AAAA,IAEd,OAAO,MAAM;AAAA,MACX,MAAM,MAAM,MAAM,KAAK,eACrB,GAAG,mCAAmC,cAAc,gBAAgB,QACtE;AAAA,MACA,IAAI,CAAC,IAAI,IAAI;AAAA,QACX,OAAO,KAAK,oCAAoC,EAAE,MAAM,QAAQ,IAAI,OAAO,CAAC;AAAA,QAC5E;AAAA,MACF;AAAA,MAEA,MAAM,OAAQ,MAAM,IAAI,KAAK;AAAA,MAC7B,WAAW,UAAU,KAAK,QAAQ;AAAA,QAChC,MAAM,YAAY,iBAAiB,MAAM;AAAA,QACzC,IAAI;AAAA,UAAW,OAAO,KAAK,SAAS;AAAA,MACtC;AAAA,MAEA,IAAI,KAAK,OAAO,SAAS;AAAA,QAAO;AAAA,MAChC,UAAU;AAAA,IACZ;AAAA,IAEA,OAAO;AAAA;AAAA,OAIH,WAAU,CAAC,MAAsC;AAAA,IACrD,IAAI;AAAA,MACF,MAAM,MAAM,MAAM,KAAK,eAAe,GAAG,KAAK,yBAAyB,YAAY,GAAM;AAAA,MACzF,IAAI,CAAC,IAAI;AAAA,QAAI,OAAO;AAAA,MACpB,MAAM,OAAQ,MAAM,IAAI,KAAK;AAAA,MAC7B,OAAO,KAAK,UAAU;AAAA,MACtB,MAAM;AAAA,MACN,OAAO;AAAA;AAAA;AAAA,OAKL,gBAAe,CAAC,OAAiB,cAAc,IAAkC;AAAA,IACrF,MAAM,UAAU,IAAI;AAAA,IACpB,SAAS,IAAI,EAAG,IAAI,MAAM,QAAQ,KAAK,aAAa;AAAA,MAClD,MAAM,QAAQ,MAAM,MAAM,GAAG,IAAI,WAAW;AAAA,MAC5C,MAAM,UAAU,MAAM,QAAQ,WAC5B,MAAM,IAAI,OAAO,SAAS;AAAA,QACxB,MAAM,MAAM,MAAM,KAAK,WAAW,IAAI;AAAA,QACtC,OAAO,EAAE,MAAM,IAAI;AAAA,OACpB,CACH;AAAA,MACA,WAAW,UAAU,SAAS;AAAA,QAC5B,IAAI,OAAO,WAAW,eAAe,OAAO,MAAM,KAAK;AAAA,UACrD,QAAQ,IAAI,OAAO,MAAM,MAAM,OAAO,MAAM,GAAG;AAAA,QACjD;AAAA,MACF;AAAA,IACF;AAAA,IACA,OAAO;AAAA;AAAA,OAIH,cAAa,GAAoB;AAAA,IACrC,MAAM,MAAM,MAAM,KAAK,eAAe,GAAG,KAAK,2BAA2B;AAAA,IACzE,IAAI,CAAC,IAAI;AAAA,MAAI,MAAM,IAAI,MAAM,6BAA6B,IAAI,QAAQ;AAAA,IACtE,MAAM,OAAQ,MAAM,IAAI,KAAK;AAAA,IAC7B,OAAO,KAAK,WAAW,gBAAgB,KAAK,qBAAqB;AAAA;AAAA,OAG7D,UAAS,GAAqB;AAAA,IAClC,IAAI;AAAA,MACF,MAAM,MAAM,MAAM,MAAM,GAAG,KAAK,6BAA6B;AAAA,QAC3D,SAAS,KAAK;AAAA,QACd,QAAQ,YAAY,QAAQ,GAAM;AAAA,MACpC,CAAC;AAAA,MAED,OAAO,IAAI,MAAM,IAAI,WAAW;AAAA,MAChC,MAAM;AAAA,MACN,OAAO;AAAA;AAAA;AAAA,EAIX,SAAS,GAAW;AAAA,IAClB,OAAO,KAAK;AAAA;AAEhB;AAGA,SAAS,WAAW,CAAC,QAAwB;AAAA,EAC3C,QAAQ;AAAA,SACD;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,SACA;AAAA,MACH,OAAO;AAAA;AAAA,MAEP,OAAO;AAAA;AAAA;AAKb,SAAS,SAAS,CAAC,MAAsB;AAAA,EACvC,QAAQ;AAAA,SACD;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA;AAAA,MAEP,OAAO;AAAA;AAAA;AAcb,SAAS,gBAAgB,CAAC,QAAmD;AAAA,EAC3E,MAAM,OAAO;AAAA,IACX,MAAM,OAAO;AAAA,IACb,aAAa,OAAO;AAAA,IACpB,WAAW;AAAA,EACb;AAAA,EAEA,IAAI,OAAO,eAAe,eAAe,OAAO,OAAO;AAAA,IACrD,MAAM,IAAI,OAAO;AAAA,IACjB,QAAQ,EAAE;AAAA,WACH;AAAA,QACH,OAAO;AAAA,aACF;AAAA,UACH,MAAM;AAAA,UACN,oBAAoB;AAAA,YAClB,QAAQ,EAAE;AAAA,YACV,WAAW,EAAE;AAAA,YACb,QAAQ,EAAE;AAAA,YACV,MAAM,EAAE;AAAA,UACV;AAAA,QACF;AAAA,WACG;AAAA,QACH,OAAO;AAAA,aACF;AAAA,UACH,MAAM;AAAA,UACN,gBAAgB,EAAE,WAAW,EAAE,WAAY,QAAQ,EAAE,OAAQ;AAAA,QAC/D;AAAA,WACG;AAAA,QACH,OAAO;AAAA,aACF;AAAA,UACH,MAAM;AAAA,UACN,gBAAgB,EAAE,QAAQ,EAAE,QAAS,QAAQ,EAAE,OAAQ;AAAA,QACzD;AAAA,WACG;AAAA,QACH,OAAO;AAAA,aACF;AAAA,UACH,MAAM;AAAA,UACN,gBAAgB;AAAA,YACd,eAAe,EAAE;AAAA,YACjB,eAAe;AAAA,YACf,gBAAgB,EAAE;AAAA,UACpB;AAAA,QACF;AAAA;AAAA,EAEN;AAAA,EAEA,IAAI,OAAO,eAAe,0BAA0B,OAAO,OAAO;AAAA,IAChE,MAAM,IAAI,OAAO;AAAA,IACjB,MAAM,UAAU,EAAE,YAAY;AAAA,IAC9B,QAAQ,EAAE;AAAA,WACH;AAAA,QACH,OAAO;AAAA,aACF;AAAA,UACH,MAAM;AAAA,UACN,mBAAmB;AAAA,YACjB,kBAAkB;AAAA,YAClB,QAAQ,EAAE;AAAA,YACV,WAAW,EAAE;AAAA,YACb,QAAQ,EAAE;AAAA,UACZ;AAAA,QACF;AAAA,WACG;AAAA,QACH,OAAO;AAAA,aACF;AAAA,UACH,MAAM;AAAA,UACN,eAAe,EAAE,kBAAkB,SAAS,WAAW,EAAE,WAAY,QAAQ,EAAE,OAAQ;AAAA,QACzF;AAAA,WACG;AAAA,QACH,OAAO;AAAA,aACF;AAAA,UACH,MAAM;AAAA,UACN,eAAe,EAAE,kBAAkB,SAAS,QAAQ,EAAE,QAAS,QAAQ,EAAE,OAAQ;AAAA,QACnF;AAAA;AAAA,EAEN;AAAA,EAEA,IAAI,OAAO,eAAe,8BAA8B,OAAO,OAAO;AAAA,IACpE,MAAM,IAAI,OAAO;AAAA,IACjB,MAAM,UAAU,EAAE,YAAY;AAAA,IAC9B,QAAQ,EAAE;AAAA,WACH;AAAA,QACH,OAAO;AAAA,aACF;AAAA,UACH,MAAM;AAAA,UACN,oBAAoB;AAAA,YAClB,kBAAkB;AAAA,YAClB,QAAQ,EAAE;AAAA,YACV,WAAW,EAAE;AAAA,YACb,OAAO,EAAE;AAAA,UACX;AAAA,QACF;AAAA,WACG;AAAA,QACH,OAAO;AAAA,aACF;AAAA,UACH,MAAM;AAAA,UACN,gBAAgB,EAAE,kBAAkB,SAAS,WAAW,EAAE,WAAY,OAAO,EAAE,MAAM;AAAA,QACvF;AAAA,WACG;AAAA,QACH,OAAO;AAAA,aACF;AAAA,UACH,MAAM;AAAA,UACN,gBAAgB,EAAE,kBAAkB,SAAS,QAAQ,EAAE,QAAS,OAAO,EAAE,MAAM;AAAA,QACjF;AAAA;AAAA,EAEN;AAAA,EAEA,IAAI,OAAO,eAAe,wBAAwB,OAAO,cAAc;AAAA,IACrE,OAAO;AAAA,SACF;AAAA,MACH,MAAM;AAAA,MACN,sBAAsB;AAAA,QACpB,qBAAqB,OAAO,aAAa;AAAA,QACzC,OAAO,OAAO,aAAa;AAAA,QAC3B,OAAO,OAAO,aAAa;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO,MAAM,qCAAqC;AAAA,IAChD,WAAW,OAAO;AAAA,IAClB,MAAM,OAAO;AAAA,EACf,CAAC;AAAA,EACD,OAAO;AAAA;",
|
|
10
|
-
"debugId": "
|
|
9
|
+
"mappings": "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",
|
|
10
|
+
"debugId": "84E732ABB4DEC21A64756E2164756E21",
|
|
11
11
|
"names": []
|
|
12
12
|
}
|
|
@@ -13,7 +13,6 @@ var __export = (target, all) => {
|
|
|
13
13
|
set: __exportSetter.bind(all, name)
|
|
14
14
|
});
|
|
15
15
|
};
|
|
16
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
17
16
|
|
|
18
17
|
// src/node/hiro-pg-client.ts
|
|
19
18
|
import postgres from "postgres";
|
|
@@ -435,5 +434,5 @@ export {
|
|
|
435
434
|
HiroPgClient
|
|
436
435
|
};
|
|
437
436
|
|
|
438
|
-
//# debugId=
|
|
437
|
+
//# debugId=E1188F876C00BE8364756E2164756E21
|
|
439
438
|
//# sourceMappingURL=hiro-pg-client.js.map
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"/**\n * Direct Postgres client for reading from a local Hiro API database.\n *\n * Bypasses the Hiro HTTP API entirely — queries the stacks_blockchain_api\n * schema directly. Orders of magnitude faster for bulk backfill since we\n * avoid per-tx HTTP round-trips and the API's slow UNION event queries.\n *\n * Expects HIRO_PG_URL env var pointing to the Hiro API database, e.g.:\n * postgres://secondlayer:pass@localhost:5432/stacks_blockchain_api\n */\n\nimport postgres from \"postgres\";\n\nconst SCHEMA = \"stacks_blockchain_api\";\n\n// Hiro DB stores bytea; we need 0x-prefixed hex strings\nfunction toHex(buf: Buffer | Uint8Array | null): string {\n if (!buf) return \"0x\";\n return \"0x\" + Buffer.from(buf).toString(\"hex\");\n}\n\n// asset_event_type_id mapping: 1=transfer, 2=mint, 3=burn\nfunction stxEventType(assetTypeId: number): string {\n switch (assetTypeId) {\n case 1: return \"stx_transfer_event\";\n case 2: return \"stx_mint_event\";\n case 3: return \"stx_burn_event\";\n default: return \"stx_transfer_event\";\n }\n}\n\nfunction ftEventType(assetTypeId: number): string {\n switch (assetTypeId) {\n case 1: return \"ft_transfer_event\";\n case 2: return \"ft_mint_event\";\n case 3: return \"ft_burn_event\";\n default: return \"ft_transfer_event\";\n }\n}\n\nfunction nftEventType(assetTypeId: number): string {\n switch (assetTypeId) {\n case 1: return \"nft_transfer_event\";\n case 2: return \"nft_mint_event\";\n case 3: return \"nft_burn_event\";\n default: return \"nft_transfer_event\";\n }\n}\n\n// Hiro tx type_id mapping\nfunction mapTxTypeId(typeId: number): string {\n switch (typeId) {\n case 0: return \"token_transfer\";\n case 1: return \"smart_contract\";\n case 2: return \"contract_call\";\n case 3: return \"poison_microblock\";\n case 4: return \"coinbase\";\n case 5: return \"coinbase\"; // coinbase-pay-to-alt\n case 6: return \"smart_contract\"; // versioned\n case 7: return \"tenure_change\";\n case 8: return \"coinbase\"; // nakamoto coinbase\n default: return \"token_transfer\";\n }\n}\n\n// Hiro tx status mapping\nfunction mapTxStatus(status: number): string {\n switch (status) {\n case 1: return \"success\";\n case 0: return \"abort_by_response\";\n default: return \"abort_by_post_condition\";\n }\n}\n\ninterface BlockRow {\n block_hash: Buffer;\n block_height: number;\n index_block_hash: Buffer;\n parent_block_hash: Buffer;\n parent_index_block_hash: Buffer;\n burn_block_hash: Buffer;\n burn_block_height: number;\n burn_block_time: number;\n block_time: number;\n miner_txid: Buffer;\n}\n\ninterface TxRow {\n tx_id: Buffer;\n tx_index: number;\n type_id: number;\n status: number;\n sender_address: string;\n raw_tx: Buffer;\n event_count: number;\n contract_call_contract_id: string | null;\n contract_call_function_name: string | null;\n smart_contract_contract_id: string | null;\n}\n\nexport class HiroPgClient {\n private sql: ReturnType<typeof postgres>;\n\n constructor(connectionUrl?: string) {\n const url = connectionUrl || process.env.HIRO_PG_URL;\n if (!url) throw new Error(\"HIRO_PG_URL is required for HiroPgClient\");\n this.sql = postgres(url, {\n max: 10,\n idle_timeout: 30,\n });\n }\n\n async getChainTip(): Promise<number> {\n const rows = await this.sql`\n SELECT MAX(block_height) as tip FROM ${this.sql(SCHEMA)}.blocks WHERE canonical = true\n `;\n return Number(rows[0]?.tip ?? 0);\n }\n\n /**\n * Fetch a complete block by height directly from PG.\n * Returns data in the same NewBlockPayload shape the backfill expects.\n */\n async getBlockForIndexer(height: number, options?: { includeRawTx?: boolean }): Promise<any | null> {\n // 1. Block metadata\n const blocks = await this.sql<BlockRow[]>`\n SELECT block_hash, block_height, index_block_hash, parent_block_hash,\n parent_index_block_hash, burn_block_hash, burn_block_height,\n burn_block_time, block_time, miner_txid\n FROM ${this.sql(SCHEMA)}.blocks\n WHERE block_height = ${height} AND canonical = true\n LIMIT 1\n `;\n if (blocks.length === 0) return null;\n const block = blocks[0];\n\n // 2. Transactions\n const txs = await this.sql<TxRow[]>`\n SELECT tx_id, tx_index, type_id, status, sender_address, raw_tx, event_count,\n contract_call_contract_id, contract_call_function_name, smart_contract_contract_id\n FROM ${this.sql(SCHEMA)}.txs\n WHERE block_height = ${height} AND canonical = true AND microblock_canonical = true\n ORDER BY tx_index\n `;\n\n const transactions = txs.map((tx) => {\n const txType = mapTxTypeId(tx.type_id);\n const entry: any = {\n txid: toHex(tx.tx_id),\n raw_tx: options?.includeRawTx ? toHex(tx.raw_tx) : \"0x00\",\n status: mapTxStatus(tx.status),\n tx_index: tx.tx_index,\n tx_type: txType,\n sender_address: tx.sender_address,\n };\n if (txType === \"contract_call\" && tx.contract_call_contract_id) {\n entry.contract_call = {\n contract_id: tx.contract_call_contract_id,\n function_name: tx.contract_call_function_name || \"\",\n };\n } else if (txType === \"smart_contract\" && tx.smart_contract_contract_id) {\n entry.smart_contract = {\n contract_id: tx.smart_contract_contract_id,\n };\n }\n return entry;\n });\n\n // 3. Events — query all event tables by block_height (fast, indexed)\n const events: any[] = [];\n\n // STX events\n const stxEvents = await this.sql`\n SELECT tx_id, event_index, asset_event_type_id, amount, sender, recipient, memo\n FROM ${this.sql(SCHEMA)}.stx_events\n WHERE block_height = ${height} AND canonical = true AND microblock_canonical = true\n ORDER BY event_index\n `;\n for (const e of stxEvents) {\n const type = stxEventType(e.asset_event_type_id);\n const evt: any = { txid: toHex(e.tx_id), event_index: e.event_index, committed: true, type };\n if (type === \"stx_transfer_event\") {\n evt.stx_transfer_event = {\n sender: e.sender || \"\",\n recipient: e.recipient || \"\",\n amount: String(e.amount),\n ...(e.memo ? { memo: toHex(e.memo) } : {}),\n };\n } else if (type === \"stx_mint_event\") {\n evt.stx_mint_event = { recipient: e.recipient || \"\", amount: String(e.amount) };\n } else if (type === \"stx_burn_event\") {\n evt.stx_burn_event = { sender: e.sender || \"\", amount: String(e.amount) };\n }\n events.push(evt);\n }\n\n // STX lock events\n const lockEvents = await this.sql`\n SELECT tx_id, event_index, locked_amount, unlock_height, locked_address\n FROM ${this.sql(SCHEMA)}.stx_lock_events\n WHERE block_height = ${height} AND canonical = true AND microblock_canonical = true\n ORDER BY event_index\n `;\n for (const e of lockEvents) {\n events.push({\n txid: toHex(e.tx_id),\n event_index: e.event_index,\n committed: true,\n type: \"stx_lock_event\",\n stx_lock_event: {\n locked_amount: String(e.locked_amount),\n unlock_height: String(e.unlock_height),\n locked_address: e.locked_address,\n },\n });\n }\n\n // FT events\n const ftEvents = await this.sql`\n SELECT tx_id, event_index, asset_event_type_id, asset_identifier, amount, sender, recipient\n FROM ${this.sql(SCHEMA)}.ft_events\n WHERE block_height = ${height} AND canonical = true AND microblock_canonical = true\n ORDER BY event_index\n `;\n for (const e of ftEvents) {\n const type = ftEventType(e.asset_event_type_id);\n const evt: any = { txid: toHex(e.tx_id), event_index: e.event_index, committed: true, type };\n if (type === \"ft_transfer_event\") {\n evt.ft_transfer_event = {\n asset_identifier: e.asset_identifier,\n sender: e.sender || \"\",\n recipient: e.recipient || \"\",\n amount: String(e.amount),\n };\n } else if (type === \"ft_mint_event\") {\n evt.ft_mint_event = { asset_identifier: e.asset_identifier, recipient: e.recipient || \"\", amount: String(e.amount) };\n } else if (type === \"ft_burn_event\") {\n evt.ft_burn_event = { asset_identifier: e.asset_identifier, sender: e.sender || \"\", amount: String(e.amount) };\n }\n events.push(evt);\n }\n\n // NFT events\n const nftEvents = await this.sql`\n SELECT tx_id, event_index, asset_event_type_id, asset_identifier, value, sender, recipient\n FROM ${this.sql(SCHEMA)}.nft_events\n WHERE block_height = ${height} AND canonical = true AND microblock_canonical = true\n ORDER BY event_index\n `;\n for (const e of nftEvents) {\n const type = nftEventType(e.asset_event_type_id);\n const evt: any = { txid: toHex(e.tx_id), event_index: e.event_index, committed: true, type };\n const val = toHex(e.value);\n if (type === \"nft_transfer_event\") {\n evt.nft_transfer_event = { asset_identifier: e.asset_identifier, sender: e.sender || \"\", recipient: e.recipient || \"\", value: val };\n } else if (type === \"nft_mint_event\") {\n evt.nft_mint_event = { asset_identifier: e.asset_identifier, recipient: e.recipient || \"\", value: val };\n } else if (type === \"nft_burn_event\") {\n evt.nft_burn_event = { asset_identifier: e.asset_identifier, sender: e.sender || \"\", value: val };\n }\n events.push(evt);\n }\n\n // Contract log events\n const logEvents = await this.sql`\n SELECT tx_id, event_index, contract_identifier, topic, value\n FROM ${this.sql(SCHEMA)}.contract_logs\n WHERE block_height = ${height} AND canonical = true AND microblock_canonical = true\n ORDER BY event_index\n `;\n for (const e of logEvents) {\n events.push({\n txid: toHex(e.tx_id),\n event_index: e.event_index,\n committed: true,\n type: \"smart_contract_event\",\n smart_contract_event: {\n contract_identifier: e.contract_identifier,\n topic: e.topic,\n value: toHex(e.value),\n },\n });\n }\n\n return {\n block_hash: toHex(block.block_hash),\n block_height: block.block_height,\n index_block_hash: toHex(block.index_block_hash),\n parent_block_hash: toHex(block.parent_block_hash),\n parent_index_block_hash: toHex(block.parent_index_block_hash),\n burn_block_hash: toHex(block.burn_block_hash),\n burn_block_height: block.burn_block_height,\n burn_block_timestamp: block.burn_block_time,\n miner_txid: toHex(block.miner_txid),\n timestamp: block.block_time,\n transactions,\n events,\n };\n }\n\n /**\n * Fetch multiple blocks in bulk — 6 queries total instead of 6 per block.\n * Returns array of NewBlockPayload in height order.\n */\n async getBlockBatch(heights: number[], options?: { includeRawTx?: boolean }): Promise<any[]> {\n if (heights.length === 0) return [];\n\n // 1. All blocks in range\n const blocks = await this.sql`\n SELECT block_hash, block_height, index_block_hash, parent_block_hash,\n parent_index_block_hash, burn_block_hash, burn_block_height,\n burn_block_time, block_time, miner_txid\n FROM ${this.sql(SCHEMA)}.blocks\n WHERE block_height = ANY(${heights}) AND canonical = true\n `;\n\n if (blocks.length === 0) return [];\n const blockMap = new Map<number, any>();\n for (const b of blocks) {\n blockMap.set(b.block_height, { ...b, transactions: [], events: [] });\n }\n\n // 2. All transactions\n const txs = await this.sql`\n SELECT tx_id, tx_index, type_id, status, sender_address, raw_tx, event_count, block_height,\n contract_call_contract_id, contract_call_function_name, smart_contract_contract_id\n FROM ${this.sql(SCHEMA)}.txs\n WHERE block_height = ANY(${heights}) AND canonical = true AND microblock_canonical = true\n ORDER BY block_height, tx_index\n `;\n for (const tx of txs) {\n const block = blockMap.get(tx.block_height);\n if (!block) continue;\n const txType = mapTxTypeId(tx.type_id);\n const entry: any = {\n txid: toHex(tx.tx_id),\n raw_tx: options?.includeRawTx ? toHex(tx.raw_tx) : \"0x00\",\n status: mapTxStatus(tx.status),\n tx_index: tx.tx_index,\n tx_type: txType,\n sender_address: tx.sender_address,\n };\n if (txType === \"contract_call\" && tx.contract_call_contract_id) {\n entry.contract_call = { contract_id: tx.contract_call_contract_id, function_name: tx.contract_call_function_name || \"\" };\n } else if (txType === \"smart_contract\" && tx.smart_contract_contract_id) {\n entry.smart_contract = { contract_id: tx.smart_contract_contract_id };\n }\n block.transactions.push(entry);\n }\n\n // 3. STX events\n const stxEvents = await this.sql`\n SELECT tx_id, event_index, asset_event_type_id, amount, sender, recipient, memo, block_height\n FROM ${this.sql(SCHEMA)}.stx_events\n WHERE block_height = ANY(${heights}) AND canonical = true AND microblock_canonical = true\n `;\n for (const e of stxEvents) {\n const block = blockMap.get(e.block_height);\n if (!block) continue;\n const type = stxEventType(e.asset_event_type_id);\n const evt: any = { txid: toHex(e.tx_id), event_index: e.event_index, committed: true, type };\n if (type === \"stx_transfer_event\") {\n evt.stx_transfer_event = { sender: e.sender || \"\", recipient: e.recipient || \"\", amount: String(e.amount), ...(e.memo ? { memo: toHex(e.memo) } : {}) };\n } else if (type === \"stx_mint_event\") {\n evt.stx_mint_event = { recipient: e.recipient || \"\", amount: String(e.amount) };\n } else if (type === \"stx_burn_event\") {\n evt.stx_burn_event = { sender: e.sender || \"\", amount: String(e.amount) };\n }\n block.events.push(evt);\n }\n\n // 4. STX lock events\n const lockEvents = await this.sql`\n SELECT tx_id, event_index, locked_amount, unlock_height, locked_address, block_height\n FROM ${this.sql(SCHEMA)}.stx_lock_events\n WHERE block_height = ANY(${heights}) AND canonical = true AND microblock_canonical = true\n `;\n for (const e of lockEvents) {\n const block = blockMap.get(e.block_height);\n if (!block) continue;\n block.events.push({\n txid: toHex(e.tx_id), event_index: e.event_index, committed: true, type: \"stx_lock_event\",\n stx_lock_event: { locked_amount: String(e.locked_amount), unlock_height: String(e.unlock_height), locked_address: e.locked_address },\n });\n }\n\n // 5. FT events\n const ftEvents = await this.sql`\n SELECT tx_id, event_index, asset_event_type_id, asset_identifier, amount, sender, recipient, block_height\n FROM ${this.sql(SCHEMA)}.ft_events\n WHERE block_height = ANY(${heights}) AND canonical = true AND microblock_canonical = true\n `;\n for (const e of ftEvents) {\n const block = blockMap.get(e.block_height);\n if (!block) continue;\n const type = ftEventType(e.asset_event_type_id);\n const evt: any = { txid: toHex(e.tx_id), event_index: e.event_index, committed: true, type };\n if (type === \"ft_transfer_event\") {\n evt.ft_transfer_event = { asset_identifier: e.asset_identifier, sender: e.sender || \"\", recipient: e.recipient || \"\", amount: String(e.amount) };\n } else if (type === \"ft_mint_event\") {\n evt.ft_mint_event = { asset_identifier: e.asset_identifier, recipient: e.recipient || \"\", amount: String(e.amount) };\n } else if (type === \"ft_burn_event\") {\n evt.ft_burn_event = { asset_identifier: e.asset_identifier, sender: e.sender || \"\", amount: String(e.amount) };\n }\n block.events.push(evt);\n }\n\n // 6. NFT events\n const nftEvents = await this.sql`\n SELECT tx_id, event_index, asset_event_type_id, asset_identifier, value, sender, recipient, block_height\n FROM ${this.sql(SCHEMA)}.nft_events\n WHERE block_height = ANY(${heights}) AND canonical = true AND microblock_canonical = true\n `;\n for (const e of nftEvents) {\n const block = blockMap.get(e.block_height);\n if (!block) continue;\n const type = nftEventType(e.asset_event_type_id);\n const evt: any = { txid: toHex(e.tx_id), event_index: e.event_index, committed: true, type };\n const val = toHex(e.value);\n if (type === \"nft_transfer_event\") {\n evt.nft_transfer_event = { asset_identifier: e.asset_identifier, sender: e.sender || \"\", recipient: e.recipient || \"\", value: val };\n } else if (type === \"nft_mint_event\") {\n evt.nft_mint_event = { asset_identifier: e.asset_identifier, recipient: e.recipient || \"\", value: val };\n } else if (type === \"nft_burn_event\") {\n evt.nft_burn_event = { asset_identifier: e.asset_identifier, sender: e.sender || \"\", value: val };\n }\n block.events.push(evt);\n }\n\n // 7. Contract log events\n const logEvents = await this.sql`\n SELECT tx_id, event_index, contract_identifier, topic, value, block_height\n FROM ${this.sql(SCHEMA)}.contract_logs\n WHERE block_height = ANY(${heights}) AND canonical = true AND microblock_canonical = true\n `;\n for (const e of logEvents) {\n const block = blockMap.get(e.block_height);\n if (!block) continue;\n block.events.push({\n txid: toHex(e.tx_id), event_index: e.event_index, committed: true, type: \"smart_contract_event\",\n smart_contract_event: { contract_identifier: e.contract_identifier, topic: e.topic, value: toHex(e.value) },\n });\n }\n\n // Build results in height order\n return heights\n .filter((h) => blockMap.has(h))\n .map((h) => {\n const b = blockMap.get(h)!;\n return {\n block_hash: toHex(b.block_hash),\n block_height: b.block_height,\n index_block_hash: toHex(b.index_block_hash),\n parent_block_hash: toHex(b.parent_block_hash),\n parent_index_block_hash: toHex(b.parent_index_block_hash),\n burn_block_hash: toHex(b.burn_block_hash),\n burn_block_height: b.burn_block_height,\n burn_block_timestamp: b.burn_block_time,\n miner_txid: toHex(b.miner_txid),\n timestamp: b.block_time,\n transactions: b.transactions,\n events: b.events,\n };\n });\n }\n\n async close(): Promise<void> {\n await this.sql.end();\n }\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "E1188F876C00BE8364756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -38,7 +38,7 @@ interface StreamsTable {
|
|
|
38
38
|
options: Generated<unknown>;
|
|
39
39
|
endpoint_url: string;
|
|
40
40
|
signing_secret: string | null;
|
|
41
|
-
api_key_id: string
|
|
41
|
+
api_key_id: string;
|
|
42
42
|
created_at: Generated<Date>;
|
|
43
43
|
updated_at: Generated<Date>;
|
|
44
44
|
}
|
|
@@ -97,7 +97,7 @@ interface SubgraphsTable {
|
|
|
97
97
|
last_error_at: Date | null;
|
|
98
98
|
total_processed: Generated<number>;
|
|
99
99
|
total_errors: Generated<number>;
|
|
100
|
-
api_key_id: string
|
|
100
|
+
api_key_id: string;
|
|
101
101
|
created_at: Generated<Date>;
|
|
102
102
|
updated_at: Generated<Date>;
|
|
103
103
|
}
|
|
@@ -137,6 +137,7 @@ interface MagicLinksTable {
|
|
|
137
137
|
token: string;
|
|
138
138
|
expires_at: Date;
|
|
139
139
|
used_at: Date | null;
|
|
140
|
+
failed_attempts: Generated<number>;
|
|
140
141
|
created_at: Generated<Date>;
|
|
141
142
|
}
|
|
142
143
|
interface UsageDailyTable {
|
|
@@ -13,7 +13,6 @@ var __export = (target, all) => {
|
|
|
13
13
|
set: __exportSetter.bind(all, name)
|
|
14
14
|
});
|
|
15
15
|
};
|
|
16
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
17
16
|
|
|
18
17
|
// src/node/local-client.ts
|
|
19
18
|
class LocalClient {
|
|
@@ -71,5 +70,5 @@ export {
|
|
|
71
70
|
LocalClient
|
|
72
71
|
};
|
|
73
72
|
|
|
74
|
-
//# debugId=
|
|
73
|
+
//# debugId=DE87E3DF563DF80464756E2164756E21
|
|
75
74
|
//# sourceMappingURL=local-client.js.map
|