@saga-sync/producer 0.0.0 → 0.1.2
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/chunk-builder/accumulator.d.ts +29 -0
- package/dist/chunk-builder/accumulator.d.ts.map +1 -0
- package/dist/chunk-builder/accumulator.js +72 -0
- package/dist/chunk-builder/accumulator.js.map +1 -0
- package/dist/chunk-builder/archive.d.ts +18 -0
- package/dist/chunk-builder/archive.d.ts.map +1 -0
- package/dist/chunk-builder/archive.js +68 -0
- package/dist/chunk-builder/archive.js.map +1 -0
- package/dist/chunk-builder/cli.d.ts +28 -0
- package/dist/chunk-builder/cli.d.ts.map +1 -0
- package/dist/chunk-builder/cli.js +167 -0
- package/dist/chunk-builder/cli.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/keygen.d.ts +3 -0
- package/dist/keygen.d.ts.map +1 -0
- package/dist/keygen.js +10 -0
- package/dist/keygen.js.map +1 -0
- package/dist/orchestrator/cli.d.ts +37 -0
- package/dist/orchestrator/cli.d.ts.map +1 -0
- package/dist/orchestrator/cli.js +336 -0
- package/dist/orchestrator/cli.js.map +1 -0
- package/dist/orchestrator/pipeline.d.ts +32 -0
- package/dist/orchestrator/pipeline.d.ts.map +1 -0
- package/dist/orchestrator/pipeline.js +32 -0
- package/dist/orchestrator/pipeline.js.map +1 -0
- package/dist/scraper/cli.d.ts +5 -0
- package/dist/scraper/cli.d.ts.map +1 -0
- package/dist/scraper/cli.js +153 -0
- package/dist/scraper/cli.js.map +1 -0
- package/dist/scraper/config.d.ts +15 -0
- package/dist/scraper/config.d.ts.map +1 -0
- package/dist/scraper/config.js +87 -0
- package/dist/scraper/config.js.map +1 -0
- package/dist/scraper/cursor.d.ts +12 -0
- package/dist/scraper/cursor.d.ts.map +1 -0
- package/dist/scraper/cursor.js +38 -0
- package/dist/scraper/cursor.js.map +1 -0
- package/dist/scraper/normalize.d.ts +5 -0
- package/dist/scraper/normalize.d.ts.map +1 -0
- package/dist/scraper/normalize.js +19 -0
- package/dist/scraper/normalize.js.map +1 -0
- package/dist/scraper/scrape.d.ts +10 -0
- package/dist/scraper/scrape.d.ts.map +1 -0
- package/dist/scraper/scrape.js +70 -0
- package/dist/scraper/scrape.js.map +1 -0
- package/dist/storage/dry-run-store.d.ts +10 -0
- package/dist/storage/dry-run-store.d.ts.map +1 -0
- package/dist/storage/dry-run-store.js +22 -0
- package/dist/storage/dry-run-store.js.map +1 -0
- package/dist/storage/gcs-store.d.ts +44 -0
- package/dist/storage/gcs-store.d.ts.map +1 -0
- package/dist/storage/gcs-store.js +85 -0
- package/dist/storage/gcs-store.js.map +1 -0
- package/dist/storage/index.d.ts +15 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +52 -0
- package/dist/storage/index.js.map +1 -0
- package/package.json +38 -16
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { parseArgs } from "node:util";
|
|
3
|
+
import { mkdirSync, openSync, writeFileSync, closeSync, unlinkSync, readFileSync, realpathSync, } from "node:fs";
|
|
4
|
+
import { resolve, join } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { createPublicClient, http, numberToHex } from "viem";
|
|
7
|
+
import { finalizedBlock, assertChainId } from "../scraper/cli.js";
|
|
8
|
+
import { loadAllProtocols } from "../scraper/config.js";
|
|
9
|
+
import { createStore, parseStoreTarget } from "../storage/index.js";
|
|
10
|
+
import { Manifest } from "@saga-sync/core";
|
|
11
|
+
import { signerFromEnv } from "@saga-sync/core";
|
|
12
|
+
import { ChunkArchive } from "../chunk-builder/archive.js";
|
|
13
|
+
import { runProtocolOnce } from "./pipeline.js";
|
|
14
|
+
const DEFAULT_WINDOW = 2000;
|
|
15
|
+
const DEFAULT_CONFIRMATIONS = 12n;
|
|
16
|
+
const DEFAULT_SIZE_LIMIT = 10 * 1024 * 1024;
|
|
17
|
+
const DEFAULT_BATCH_SIZE = 100000n;
|
|
18
|
+
const USAGE = `orchestrator — run scrape→chunk in batches for every protocol
|
|
19
|
+
|
|
20
|
+
Usage:
|
|
21
|
+
orchestrator --config <path> --rpc <url> --output-dir <path> [options]
|
|
22
|
+
|
|
23
|
+
Required:
|
|
24
|
+
--config <path> scraper config JSON (all protocols read)
|
|
25
|
+
--rpc <url> Ethereum JSON-RPC URL (single chain per run)
|
|
26
|
+
--output-dir <path> chunks + index.json directory
|
|
27
|
+
|
|
28
|
+
Options:
|
|
29
|
+
--lock-dir <path> directory for .orchestrator.lock; default = output-dir
|
|
30
|
+
--protocol-id <id> restrict to one protocol (backfills / ad-hoc runs)
|
|
31
|
+
--batch-size <n> blocks per batch (default 100000). Smaller batches
|
|
32
|
+
bound the crash blast radius; larger batches reduce
|
|
33
|
+
hot-head rewrite overhead.
|
|
34
|
+
--confirmations <n> fallback reorg buffer when "finalized" tag is unsupported
|
|
35
|
+
(default 12)
|
|
36
|
+
--window <n> scraper window size in blocks (default 2000)
|
|
37
|
+
--size-limit <n> chunk size cap in bytes if config does not specify it
|
|
38
|
+
(default 10485760 = 10 MiB)
|
|
39
|
+
--dry-run compute what would run, don't touch disk
|
|
40
|
+
--help
|
|
41
|
+
`;
|
|
42
|
+
function fail(msg) {
|
|
43
|
+
process.stderr.write(`orchestrator: ${msg}\n`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
function parseCliArgs() {
|
|
47
|
+
const { values } = parseArgs({
|
|
48
|
+
options: {
|
|
49
|
+
config: { type: "string" },
|
|
50
|
+
rpc: { type: "string" },
|
|
51
|
+
"output-dir": { type: "string" },
|
|
52
|
+
"lock-dir": { type: "string" },
|
|
53
|
+
"protocol-id": { type: "string" },
|
|
54
|
+
"batch-size": { type: "string" },
|
|
55
|
+
confirmations: { type: "string" },
|
|
56
|
+
window: { type: "string" },
|
|
57
|
+
"size-limit": { type: "string" },
|
|
58
|
+
"dry-run": { type: "boolean", default: false },
|
|
59
|
+
help: { type: "boolean", default: false },
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
if (values.help) {
|
|
63
|
+
process.stdout.write(USAGE);
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
const need = (name) => {
|
|
67
|
+
const v = values[name];
|
|
68
|
+
if (!v)
|
|
69
|
+
fail(`missing required --${name}\n\n${USAGE}`);
|
|
70
|
+
return v;
|
|
71
|
+
};
|
|
72
|
+
const batchSize = values["batch-size"] ? BigInt(values["batch-size"]) : DEFAULT_BATCH_SIZE;
|
|
73
|
+
if (batchSize <= 0n)
|
|
74
|
+
fail(`--batch-size must be positive; got ${values["batch-size"]}`);
|
|
75
|
+
return {
|
|
76
|
+
configPath: resolve(need("config")),
|
|
77
|
+
rpc: need("rpc"),
|
|
78
|
+
output: need("output-dir"), // raw — may be a local dir or a gs:// target
|
|
79
|
+
lockDir: values["lock-dir"] ? resolve(values["lock-dir"]) : undefined,
|
|
80
|
+
protocolId: values["protocol-id"],
|
|
81
|
+
batchSize,
|
|
82
|
+
confirmations: values.confirmations ? BigInt(values.confirmations) : DEFAULT_CONFIRMATIONS,
|
|
83
|
+
window: values.window ? Number(values.window) : DEFAULT_WINDOW,
|
|
84
|
+
sizeLimit: values["size-limit"] ? Number(values["size-limit"]) : DEFAULT_SIZE_LIMIT,
|
|
85
|
+
dryRun: values["dry-run"] ?? false,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
// Atomic lock acquisition with stale-pid recovery. Returns true if we got the
|
|
89
|
+
// lock, false if another live process already holds it. Disk-only by design —
|
|
90
|
+
// the lock is a local single-machine coordination primitive, not object storage.
|
|
91
|
+
export function acquireLock(path) {
|
|
92
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
93
|
+
try {
|
|
94
|
+
const fd = openSync(path, "wx");
|
|
95
|
+
writeFileSync(fd, String(process.pid), "utf8");
|
|
96
|
+
closeSync(fd);
|
|
97
|
+
const cleanup = () => {
|
|
98
|
+
try {
|
|
99
|
+
unlinkSync(path);
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
/* already gone */
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
process.on("exit", cleanup);
|
|
106
|
+
process.on("SIGINT", () => {
|
|
107
|
+
cleanup();
|
|
108
|
+
process.exit(130);
|
|
109
|
+
});
|
|
110
|
+
process.on("SIGTERM", () => {
|
|
111
|
+
cleanup();
|
|
112
|
+
process.exit(143);
|
|
113
|
+
});
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
const code = err.code;
|
|
118
|
+
if (code !== "EEXIST")
|
|
119
|
+
throw err;
|
|
120
|
+
let stalePid;
|
|
121
|
+
try {
|
|
122
|
+
stalePid = parseInt(readFileSync(path, "utf8").trim(), 10);
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (!Number.isFinite(stalePid) || stalePid <= 0) {
|
|
128
|
+
try {
|
|
129
|
+
unlinkSync(path);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
/* race with another recovery */
|
|
133
|
+
}
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
process.kill(stalePid, 0);
|
|
138
|
+
return false; // owner alive
|
|
139
|
+
}
|
|
140
|
+
catch (e) {
|
|
141
|
+
const ec = e.code;
|
|
142
|
+
if (ec === "ESRCH") {
|
|
143
|
+
try {
|
|
144
|
+
unlinkSync(path);
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
/* race */
|
|
148
|
+
}
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
return false; // EPERM: exists but unsignalable — treat as alive
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
// Process one protocol: clean any stale hot head, loop in batches, persist the
|
|
158
|
+
// final trailing accumulator as the new hot head.
|
|
159
|
+
async function processProtocol(args) {
|
|
160
|
+
const { manifest, archive, protocolId, protocol, tip, batchSize } = args;
|
|
161
|
+
// 1. Resolve where to start. Take the max() of the hot head's toBlock and the
|
|
162
|
+
// last sealed chunk's toBlock — robust to a crash-post-seal-pre-clear state.
|
|
163
|
+
const sealedChunks = manifest.sealedChunks(protocolId);
|
|
164
|
+
const lastSealedChunk = sealedChunks.length > 0 ? sealedChunks[sealedChunks.length - 1] : undefined;
|
|
165
|
+
const lastSealed = lastSealedChunk ? BigInt(lastSealedChunk.toBlock) : null;
|
|
166
|
+
const recordedHot = manifest.hotHead(protocolId);
|
|
167
|
+
const recordedHotTo = recordedHot ? BigInt(recordedHot.toBlock) : null;
|
|
168
|
+
// Stale hot head: its toBlock is no further forward than what's already
|
|
169
|
+
// sealed. Clear it from the manifest and delete the file (best-effort).
|
|
170
|
+
let validHot = recordedHot;
|
|
171
|
+
if (recordedHot && lastSealed !== null && recordedHotTo !== null && recordedHotTo <= lastSealed) {
|
|
172
|
+
process.stderr.write(`orchestrator: ${protocolId} — stale hot head (toBlock ${recordedHot.toBlock} <= sealed ${numberToHex(lastSealed)}); cleaning up\n`);
|
|
173
|
+
await manifest.clearHotHead(protocolId);
|
|
174
|
+
await archive.delete(recordedHot);
|
|
175
|
+
validHot = undefined;
|
|
176
|
+
}
|
|
177
|
+
const startBlock = validHot && recordedHotTo !== null
|
|
178
|
+
? recordedHotTo
|
|
179
|
+
: lastSealed !== null
|
|
180
|
+
? lastSealed
|
|
181
|
+
: BigInt(protocol.fromBlock);
|
|
182
|
+
if (startBlock > tip) {
|
|
183
|
+
return { ranBatches: 0, sealedChunks: 0, finalHotHead: null };
|
|
184
|
+
}
|
|
185
|
+
// 2. Load the prior hot head's events — the seed for the first batch.
|
|
186
|
+
let trailing;
|
|
187
|
+
if (validHot) {
|
|
188
|
+
trailing = {
|
|
189
|
+
events: await archive.readEvents(validHot),
|
|
190
|
+
fromBlock: BigInt(validHot.fromBlock),
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
const sizeLimit = protocol.maxSizeBytes ?? args.sizeLimit;
|
|
194
|
+
// 3. Batch loop. Each batch's trailing carries into the next as the seed.
|
|
195
|
+
let batchStart = startBlock;
|
|
196
|
+
let totalSealed = 0;
|
|
197
|
+
let ranBatches = 0;
|
|
198
|
+
while (batchStart <= tip) {
|
|
199
|
+
const candidate = batchStart + batchSize - 1n;
|
|
200
|
+
const batchEnd = candidate > tip ? tip : candidate;
|
|
201
|
+
const result = await runProtocolOnce({
|
|
202
|
+
client: args.client,
|
|
203
|
+
protocolId,
|
|
204
|
+
fromBlock: batchStart,
|
|
205
|
+
toBlock: batchEnd,
|
|
206
|
+
events: protocol.events,
|
|
207
|
+
sizeLimit,
|
|
208
|
+
window: args.window,
|
|
209
|
+
archive,
|
|
210
|
+
manifest,
|
|
211
|
+
...(trailing && {
|
|
212
|
+
hotHead: { events: trailing.events, fromBlock: trailing.fromBlock },
|
|
213
|
+
}),
|
|
214
|
+
trailingMode: "suspend",
|
|
215
|
+
});
|
|
216
|
+
totalSealed += result.sealed.length;
|
|
217
|
+
trailing = result.trailing;
|
|
218
|
+
batchStart = batchEnd + 1n;
|
|
219
|
+
ranBatches += 1;
|
|
220
|
+
}
|
|
221
|
+
// 4. Persist the final trailing accumulator as the new hot head. Even when
|
|
222
|
+
// events is empty the range advances, so the manifest must reflect it.
|
|
223
|
+
let finalHotHead = null;
|
|
224
|
+
if (trailing) {
|
|
225
|
+
const trailingState = trailing;
|
|
226
|
+
finalHotHead = await archive.writeHotHead(protocolId, trailingState.events, {
|
|
227
|
+
from: trailingState.fromBlock,
|
|
228
|
+
to: tip + 1n,
|
|
229
|
+
});
|
|
230
|
+
await manifest.setHotHead(protocolId, finalHotHead);
|
|
231
|
+
// Delete the prior hot-head file if the new file has a different name
|
|
232
|
+
// (it does whenever the range advanced — i.e., always, unless a no-op tick).
|
|
233
|
+
if (validHot && validHot.file !== finalHotHead.file) {
|
|
234
|
+
await archive.delete(validHot);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return { ranBatches, sealedChunks: totalSealed, finalHotHead };
|
|
238
|
+
}
|
|
239
|
+
async function main() {
|
|
240
|
+
const args = parseCliArgs();
|
|
241
|
+
const storeConfig = parseStoreTarget(args.output);
|
|
242
|
+
// The lockfile is filesystem-only. For a local output dir it lives there; for a
|
|
243
|
+
// gs:// target there is no local dir, so default to the cwd (override with
|
|
244
|
+
// --lock-dir). (On Cloud Run, single-execution scheduling is the real guard.)
|
|
245
|
+
const lockDir = args.lockDir ?? (storeConfig.protocol === "disk" ? storeConfig.baseDir : resolve("."));
|
|
246
|
+
// Dry-run is read-only: don't create dirs or hold the lock.
|
|
247
|
+
if (!args.dryRun) {
|
|
248
|
+
mkdirSync(lockDir, { recursive: true });
|
|
249
|
+
const lockPath = join(lockDir, ".orchestrator.lock");
|
|
250
|
+
if (!acquireLock(lockPath)) {
|
|
251
|
+
process.stderr.write(`orchestrator: another instance is running (lock ${lockPath}); exiting\n`);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
const protocols = loadAllProtocols(args.configPath);
|
|
256
|
+
const store = createStore({ ...storeConfig, dryRun: args.dryRun });
|
|
257
|
+
const archive = new ChunkArchive(store);
|
|
258
|
+
const manifest = await Manifest.load(store, undefined, { signer: signerFromEnv() });
|
|
259
|
+
const client = createPublicClient({ transport: http(args.rpc) });
|
|
260
|
+
const tip = (await finalizedBlock(client)) ?? (await client.getBlockNumber()) - args.confirmations;
|
|
261
|
+
const ids = args.protocolId
|
|
262
|
+
? args.protocolId in protocols
|
|
263
|
+
? [args.protocolId]
|
|
264
|
+
: fail(`unknown --protocol-id "${args.protocolId}". Known: ${Object.keys(protocols).join(", ")}`)
|
|
265
|
+
: Object.keys(protocols);
|
|
266
|
+
let ran = 0;
|
|
267
|
+
let skipped = 0;
|
|
268
|
+
let failed = 0;
|
|
269
|
+
for (const protocolId of ids) {
|
|
270
|
+
const protocol = protocols[protocolId];
|
|
271
|
+
if (!protocol)
|
|
272
|
+
continue;
|
|
273
|
+
try {
|
|
274
|
+
await assertChainId(client, protocol.chainId);
|
|
275
|
+
}
|
|
276
|
+
catch (err) {
|
|
277
|
+
process.stderr.write(`orchestrator: skipping ${protocolId} — ${err.message}\n`);
|
|
278
|
+
skipped += 1;
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
const startFrom = manifest.lastCoveredBlock(protocolId) ?? BigInt(protocol.fromBlock);
|
|
282
|
+
if (startFrom > tip) {
|
|
283
|
+
skipped += 1;
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
if (args.dryRun) {
|
|
287
|
+
const batches = Math.ceil(Number((tip - startFrom + 1n) / args.batchSize)) || 1;
|
|
288
|
+
process.stderr.write(`orchestrator: [dry-run] ${protocolId} would scan ` +
|
|
289
|
+
`[${numberToHex(startFrom)}, ${numberToHex(tip)}] in ${batches} batch(es)\n`);
|
|
290
|
+
ran += 1;
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
try {
|
|
294
|
+
const result = await processProtocol({
|
|
295
|
+
client,
|
|
296
|
+
protocolId,
|
|
297
|
+
protocol,
|
|
298
|
+
archive,
|
|
299
|
+
manifest,
|
|
300
|
+
tip,
|
|
301
|
+
batchSize: args.batchSize,
|
|
302
|
+
window: args.window,
|
|
303
|
+
sizeLimit: args.sizeLimit,
|
|
304
|
+
});
|
|
305
|
+
const hot = result.finalHotHead
|
|
306
|
+
? ` + hot head [${result.finalHotHead.fromBlock}, ${result.finalHotHead.toBlock})`
|
|
307
|
+
: "";
|
|
308
|
+
process.stderr.write(`orchestrator: ${protocolId} ran ${result.ranBatches} batch(es), ` +
|
|
309
|
+
`sealed ${result.sealedChunks} chunk(s)${hot}\n`);
|
|
310
|
+
ran += 1;
|
|
311
|
+
}
|
|
312
|
+
catch (err) {
|
|
313
|
+
process.stderr.write(`orchestrator: ${protocolId} failed — ${err.message}\n`);
|
|
314
|
+
failed += 1;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
process.stderr.write(`orchestrator: ${ran} ran, ${skipped} skipped, ${failed} failed [tip ${numberToHex(tip)}]` +
|
|
318
|
+
(args.dryRun ? " (dry-run)\n" : "\n"));
|
|
319
|
+
if (failed > 0)
|
|
320
|
+
process.exit(2);
|
|
321
|
+
}
|
|
322
|
+
function isMainModule() {
|
|
323
|
+
try {
|
|
324
|
+
return realpathSync(process.argv[1] ?? "") === realpathSync(fileURLToPath(import.meta.url));
|
|
325
|
+
}
|
|
326
|
+
catch {
|
|
327
|
+
return false;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
if (isMainModule()) {
|
|
331
|
+
main().catch((err) => {
|
|
332
|
+
fail(err instanceof Error ? err.message : String(err));
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
export { main, parseCliArgs, processProtocol };
|
|
336
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/orchestrator/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { PublicClient } from "viem";
|
|
2
|
+
import type { CanonicalEvent } from "../scraper/normalize.js";
|
|
3
|
+
import type { EventFilter } from "../scraper/config.js";
|
|
4
|
+
import { ChunkArchive } from "../chunk-builder/archive.js";
|
|
5
|
+
import { Manifest } from "@saga-sync/core";
|
|
6
|
+
import type { ChunkMeta } from "@saga-sync/core";
|
|
7
|
+
export type RunProtocolOptions = {
|
|
8
|
+
client: PublicClient;
|
|
9
|
+
protocolId: string;
|
|
10
|
+
fromBlock: bigint;
|
|
11
|
+
toBlock: bigint;
|
|
12
|
+
events: EventFilter[];
|
|
13
|
+
sizeLimit: number;
|
|
14
|
+
window: number;
|
|
15
|
+
archive: ChunkArchive;
|
|
16
|
+
manifest: Manifest;
|
|
17
|
+
hotHead?: {
|
|
18
|
+
events: CanonicalEvent[];
|
|
19
|
+
fromBlock: bigint;
|
|
20
|
+
};
|
|
21
|
+
trailingMode?: "seal" | "suspend";
|
|
22
|
+
};
|
|
23
|
+
export type RunProtocolResult = {
|
|
24
|
+
sealed: ChunkMeta[];
|
|
25
|
+
trailing?: {
|
|
26
|
+
events: CanonicalEvent[];
|
|
27
|
+
fromBlock: bigint;
|
|
28
|
+
toBlock: bigint;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
export declare function runProtocolOnce(opts: RunProtocolOptions): Promise<RunProtocolResult>;
|
|
32
|
+
//# sourceMappingURL=pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/orchestrator/pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAGzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,QAAQ,CAAC;IAInB,OAAO,CAAC,EAAE;QAAE,MAAM,EAAE,cAAc,EAAE,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAG1D,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,QAAQ,CAAC,EAAE;QAAE,MAAM,EAAE,cAAc,EAAE,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7E,CAAC;AAKF,wBAAsB,eAAe,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAyB1F"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { scrape } from "../scraper/scrape.js";
|
|
2
|
+
import { normalize } from "../scraper/normalize.js";
|
|
3
|
+
import { processStream } from "../chunk-builder/cli.js";
|
|
4
|
+
// Compose scraper + chunk-builder in-process: scrape() yields raw logs, we
|
|
5
|
+
// normalize and stringify into NDJSON lines, and processStream consumes them.
|
|
6
|
+
// No subprocess, no stdio piping — errors propagate as exceptions.
|
|
7
|
+
export async function runProtocolOnce(opts) {
|
|
8
|
+
async function* lines() {
|
|
9
|
+
for await (const log of scrape(opts.client, {
|
|
10
|
+
fromBlock: opts.fromBlock,
|
|
11
|
+
toBlock: opts.toBlock,
|
|
12
|
+
events: opts.events,
|
|
13
|
+
window: opts.window,
|
|
14
|
+
})) {
|
|
15
|
+
yield JSON.stringify(normalize(log));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return processStream(lines(), {
|
|
19
|
+
protocolId: opts.protocolId,
|
|
20
|
+
fromBlock: opts.fromBlock,
|
|
21
|
+
// scraper's inclusive [from, to] → chunk-builder's half-open [from, to+1)
|
|
22
|
+
toBlock: opts.toBlock + 1n,
|
|
23
|
+
sizeLimit: opts.sizeLimit,
|
|
24
|
+
archive: opts.archive,
|
|
25
|
+
manifest: opts.manifest,
|
|
26
|
+
...(opts.hotHead && {
|
|
27
|
+
seed: { events: opts.hotHead.events, chunkFrom: opts.hotHead.fromBlock },
|
|
28
|
+
}),
|
|
29
|
+
...(opts.trailingMode && { trailingMode: opts.trailingMode }),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/orchestrator/pipeline.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGpD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AA6BxD,2EAA2E;AAC3E,8EAA8E;AAC9E,mEAAmE;AACnE,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAwB;IAC5D,KAAK,SAAS,CAAC,CAAC,KAAK;QACnB,IAAI,KAAK,EAAE,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE;YAC1C,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,EAAE,CAAC;YACH,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,OAAO,aAAa,CAAC,KAAK,EAAE,EAAE;QAC5B,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,0EAA0E;QAC1E,OAAO,EAAE,IAAI,CAAC,OAAO,GAAG,EAAE;QAC1B,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI;YAClB,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE;SACzE,CAAC;QACF,GAAG,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC;KAC9D,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import type { Hex, PublicClient } from "viem";
|
|
3
|
+
export declare function finalizedBlock(client: PublicClient): Promise<bigint | null>;
|
|
4
|
+
export declare function assertChainId(client: PublicClient, expected: Hex): Promise<void>;
|
|
5
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/scraper/cli.ts"],"names":[],"mappings":";AAMA,OAAO,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAiF9C,wBAAsB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOjF;AAID,wBAAsB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAOtF"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { parseArgs } from "node:util";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
4
|
+
import { realpathSync } from "node:fs";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { createPublicClient, http, numberToHex } from "viem";
|
|
7
|
+
import { loadConfig } from "./config.js";
|
|
8
|
+
import { Cursor } from "./cursor.js";
|
|
9
|
+
import { scrape } from "./scrape.js";
|
|
10
|
+
import { normalize } from "./normalize.js";
|
|
11
|
+
import { createStore } from "../storage/index.js";
|
|
12
|
+
const DEFAULT_WINDOW = 2000;
|
|
13
|
+
const DEFAULT_CONFIRMATIONS = 12n;
|
|
14
|
+
const USAGE = `scraper — fetch and normalize privacy-protocol events to NDJSON on stdout
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
scraper --config <path> --protocol-id <id> --rpc <url> [options]
|
|
18
|
+
|
|
19
|
+
Required:
|
|
20
|
+
--config <path> scraper config JSON
|
|
21
|
+
--protocol-id <id> key in config.protocols to scrape
|
|
22
|
+
--rpc <url> Ethereum JSON-RPC URL
|
|
23
|
+
|
|
24
|
+
Options:
|
|
25
|
+
--from-block <hex> override cursor / config fromBlock (e.g. for backfills)
|
|
26
|
+
--to-block <hex> override the resolved finalized/head block
|
|
27
|
+
--confirmations <n> fallback reorg buffer, default 12 (used only when the RPC
|
|
28
|
+
does not support the "finalized" block tag)
|
|
29
|
+
--window <n> blocks per eth_getLogs call, default 2000
|
|
30
|
+
--cursor-dir <path> directory for cursor.json, default = config file's directory
|
|
31
|
+
--dry-run do not persist the cursor update
|
|
32
|
+
--help show this message
|
|
33
|
+
`;
|
|
34
|
+
function fail(msg) {
|
|
35
|
+
process.stderr.write(`scraper: ${msg}\n`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
function parseCliArgs() {
|
|
39
|
+
const { values } = parseArgs({
|
|
40
|
+
options: {
|
|
41
|
+
config: { type: "string" },
|
|
42
|
+
"protocol-id": { type: "string" },
|
|
43
|
+
rpc: { type: "string" },
|
|
44
|
+
"from-block": { type: "string" },
|
|
45
|
+
"to-block": { type: "string" },
|
|
46
|
+
confirmations: { type: "string" },
|
|
47
|
+
window: { type: "string" },
|
|
48
|
+
"cursor-dir": { type: "string" },
|
|
49
|
+
"dry-run": { type: "boolean", default: false },
|
|
50
|
+
help: { type: "boolean", default: false },
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
if (values.help) {
|
|
54
|
+
process.stdout.write(USAGE);
|
|
55
|
+
process.exit(0);
|
|
56
|
+
}
|
|
57
|
+
const need = (name) => {
|
|
58
|
+
const v = values[name];
|
|
59
|
+
if (!v)
|
|
60
|
+
fail(`missing required --${name}\n\n${USAGE}`);
|
|
61
|
+
return v;
|
|
62
|
+
};
|
|
63
|
+
const configPath = resolve(need("config"));
|
|
64
|
+
return {
|
|
65
|
+
configPath,
|
|
66
|
+
protocolId: need("protocol-id"),
|
|
67
|
+
rpc: need("rpc"),
|
|
68
|
+
fromBlock: values["from-block"] ? BigInt(values["from-block"]) : undefined,
|
|
69
|
+
toBlock: values["to-block"] ? BigInt(values["to-block"]) : undefined,
|
|
70
|
+
confirmations: values.confirmations ? BigInt(values.confirmations) : DEFAULT_CONFIRMATIONS,
|
|
71
|
+
window: values.window ? Number(values.window) : DEFAULT_WINDOW,
|
|
72
|
+
cursorDir: resolve(values["cursor-dir"] ?? dirname(configPath)),
|
|
73
|
+
dryRun: values["dry-run"] ?? false,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
// The chain's own finalized block — reorg-proof, no per-chain table needed.
|
|
77
|
+
// Returns null if the RPC/chain does not support the "finalized" tag, which
|
|
78
|
+
// triggers the --confirmations fallback in step 2.
|
|
79
|
+
export async function finalizedBlock(client) {
|
|
80
|
+
try {
|
|
81
|
+
const block = await client.getBlock({ blockTag: "finalized" });
|
|
82
|
+
return block.number;
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Verify the RPC is actually on the chain the config declares — catches a
|
|
89
|
+
// misconfigured --rpc pointed at the wrong network before any data is emitted.
|
|
90
|
+
export async function assertChainId(client, expected) {
|
|
91
|
+
const actual = await client.getChainId();
|
|
92
|
+
if (BigInt(actual) !== BigInt(expected)) {
|
|
93
|
+
throw new Error(`chain mismatch: config declares chainId ${expected}, but the RPC reports ${numberToHex(actual)}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async function main() {
|
|
97
|
+
const args = parseCliArgs();
|
|
98
|
+
const config = loadConfig(args.configPath, args.protocolId);
|
|
99
|
+
const cursorStore = createStore({
|
|
100
|
+
protocol: "disk",
|
|
101
|
+
baseDir: args.cursorDir,
|
|
102
|
+
dryRun: args.dryRun,
|
|
103
|
+
});
|
|
104
|
+
const cursor = await Cursor.load(cursorStore);
|
|
105
|
+
// 1. Connect to the RPC (and verify it is on the chain the config declares)
|
|
106
|
+
const client = createPublicClient({ transport: http(args.rpc) });
|
|
107
|
+
await assertChainId(client, config.chainId);
|
|
108
|
+
// 2. Resolve the block range to scan
|
|
109
|
+
const toBlock = args.toBlock ??
|
|
110
|
+
(await finalizedBlock(client)) ??
|
|
111
|
+
(await client.getBlockNumber()) - args.confirmations;
|
|
112
|
+
const lastScraped = cursor.lastScrapedBlock(args.protocolId);
|
|
113
|
+
const fromBlock = args.fromBlock ??
|
|
114
|
+
(lastScraped ? BigInt(lastScraped) + 1n : undefined) ??
|
|
115
|
+
BigInt(config.fromBlock);
|
|
116
|
+
if (fromBlock > toBlock) {
|
|
117
|
+
process.stderr.write(`scraper: nothing to do — fromBlock ${numberToHex(fromBlock)} > toBlock ${numberToHex(toBlock)}\n`);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
// 3. Fetch logs (windowed, streaming) + 4. Normalize + 5. Emit
|
|
121
|
+
let count = 0;
|
|
122
|
+
for await (const log of scrape(client, {
|
|
123
|
+
fromBlock,
|
|
124
|
+
toBlock,
|
|
125
|
+
events: config.events,
|
|
126
|
+
window: args.window,
|
|
127
|
+
})) {
|
|
128
|
+
process.stdout.write(JSON.stringify(normalize(log)) + "\n");
|
|
129
|
+
count += 1;
|
|
130
|
+
}
|
|
131
|
+
// persist progress — one cursor update per successful run. In dry-run the
|
|
132
|
+
// cursor store is DryRunStore-wrapped, so this set() no-ops.
|
|
133
|
+
await cursor.set(args.protocolId, numberToHex(toBlock));
|
|
134
|
+
process.stderr.write(`scraper: ${count} event(s) for ${args.protocolId} ` +
|
|
135
|
+
`[${numberToHex(fromBlock)}, ${numberToHex(toBlock)}]` +
|
|
136
|
+
(args.dryRun ? " (dry-run: cursor not updated)\n" : "\n"));
|
|
137
|
+
}
|
|
138
|
+
// Only run the pipeline when invoked as the entry point — importing this module
|
|
139
|
+
// (e.g. from tests) must not kick off a scrape.
|
|
140
|
+
function isMainModule() {
|
|
141
|
+
try {
|
|
142
|
+
return realpathSync(process.argv[1] ?? "") === realpathSync(fileURLToPath(import.meta.url));
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (isMainModule()) {
|
|
149
|
+
main().catch((err) => {
|
|
150
|
+
fail(err instanceof Error ? err.message : String(err));
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/scraper/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Hex } from "viem";
|
|
2
|
+
export type EventFilter = {
|
|
3
|
+
contractAddress: Hex;
|
|
4
|
+
eventTopic: Hex;
|
|
5
|
+
filter?: Hex[];
|
|
6
|
+
};
|
|
7
|
+
export type ScraperTarget = {
|
|
8
|
+
chainId: Hex;
|
|
9
|
+
fromBlock: Hex;
|
|
10
|
+
events: EventFilter[];
|
|
11
|
+
maxSizeBytes?: number;
|
|
12
|
+
};
|
|
13
|
+
export declare function loadConfig(path: string, protocolId: string): ScraperTarget;
|
|
14
|
+
export declare function loadAllProtocols(path: string): Record<string, ScraperTarget>;
|
|
15
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/scraper/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAmChC,MAAM,MAAM,WAAW,GAAG;IACxB,eAAe,EAAE,GAAG,CAAC;IACrB,UAAU,EAAE,GAAG,CAAC;IAChB,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,GAAG,CAAC;IACb,SAAS,EAAE,GAAG,CAAC;IACf,MAAM,EAAE,WAAW,EAAE,CAAC;IAGtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAwCF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,aAAa,CAO1E;AAID,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAO5E"}
|