@secondlayer/subgraphs 6.4.0 → 6.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/index.d.ts +121 -121
- package/dist/index.js +262 -27
- package/dist/index.js.map +9 -8
- package/dist/runtime/emitter.js +1 -1
- package/dist/runtime/emitter.js.map +2 -2
- package/dist/runtime/replay.d.ts +32 -13
- package/dist/runtime/replay.js +723 -22
- package/dist/runtime/replay.js.map +8 -5
- package/dist/schema/index.d.ts +39 -39
- package/dist/schema/index.js +27 -14
- package/dist/schema/index.js.map +5 -5
- package/dist/testing/index.d.ts +105 -105
- package/dist/testing/index.js +406 -95
- package/dist/testing/index.js.map +7 -6
- package/dist/types.d.ts +31 -31
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/dist/validate.d.ts +27 -27
- package/dist/validate.js +1 -1
- package/dist/validate.js.map +2 -2
- package/dist/verification.d.ts +41 -26
- package/dist/verification.js +23 -13
- package/dist/verification.js.map +4 -4
- package/dist/verify/index.d.ts +475 -0
- package/dist/verify/index.js +3341 -0
- package/dist/verify/index.js.map +27 -0
- package/package.json +9 -3
package/dist/index.js
CHANGED
|
@@ -787,7 +787,7 @@ import { createHash } from "node:crypto";
|
|
|
787
787
|
// package.json
|
|
788
788
|
var package_default = {
|
|
789
789
|
name: "@secondlayer/subgraphs",
|
|
790
|
-
version: "6.
|
|
790
|
+
version: "6.5.0",
|
|
791
791
|
description: "Describe the Stacks data you want as one TypeScript file; it fills itself and survives reorgs.",
|
|
792
792
|
license: "MIT",
|
|
793
793
|
repository: {
|
|
@@ -831,6 +831,10 @@ var package_default = {
|
|
|
831
831
|
"./testing": {
|
|
832
832
|
types: "./dist/testing/index.d.ts",
|
|
833
833
|
import: "./dist/testing/index.js"
|
|
834
|
+
},
|
|
835
|
+
"./verify": {
|
|
836
|
+
types: "./dist/verify/index.d.ts",
|
|
837
|
+
import: "./dist/verify/index.js"
|
|
834
838
|
}
|
|
835
839
|
},
|
|
836
840
|
files: ["dist"],
|
|
@@ -842,14 +846,16 @@ var package_default = {
|
|
|
842
846
|
prepublishOnly: "bun run build"
|
|
843
847
|
},
|
|
844
848
|
dependencies: {
|
|
845
|
-
"@secondlayer/shared": "^11.
|
|
846
|
-
"@secondlayer/stacks": "^6.
|
|
849
|
+
"@secondlayer/shared": "^11.23.0",
|
|
850
|
+
"@secondlayer/stacks": "^6.2.0",
|
|
851
|
+
"@secondlayer/verify": "^0.3.0",
|
|
847
852
|
esbuild: "^0.28.2",
|
|
848
853
|
kysely: "0.28.17",
|
|
849
854
|
zod: "^4.3.6"
|
|
850
855
|
},
|
|
851
856
|
devDependencies: {
|
|
852
857
|
"@types/bun": "latest",
|
|
858
|
+
bunup: "0.16.32",
|
|
853
859
|
typescript: "^5"
|
|
854
860
|
},
|
|
855
861
|
publishConfig: {
|
|
@@ -979,7 +985,6 @@ function formatFinding(f) {
|
|
|
979
985
|
var STATE_SOURCE_TYPES = new Set([
|
|
980
986
|
"var_set",
|
|
981
987
|
"map_set",
|
|
982
|
-
"map_insert",
|
|
983
988
|
"map_delete"
|
|
984
989
|
]);
|
|
985
990
|
var LEVEL_RANK = { state: 0, events: 1, none: 2 };
|
|
@@ -996,6 +1001,9 @@ function deriveVerification(def, findings = []) {
|
|
|
996
1001
|
if (filter.trait) {
|
|
997
1002
|
raise("none");
|
|
998
1003
|
reasons.push(`source "${name}": trait scope needs a proven contract registry`);
|
|
1004
|
+
} else if (filter.type === "map_insert") {
|
|
1005
|
+
raise("events");
|
|
1006
|
+
reasons.push(`map_insert source "${name}": map_insert vs map_set needs event proofs`);
|
|
999
1007
|
} else if (!STATE_SOURCE_TYPES.has(filter.type)) {
|
|
1000
1008
|
raise("events");
|
|
1001
1009
|
reasons.push(`${filter.type} source "${name}" needs event proofs`);
|
|
@@ -1013,14 +1021,12 @@ function deriveVerification(def, findings = []) {
|
|
|
1013
1021
|
if (findings.length > MAX_LISTED_FINDINGS) {
|
|
1014
1022
|
reasons.push(`…and ${findings.length - MAX_LISTED_FINDINGS} more handler findings`);
|
|
1015
1023
|
}
|
|
1016
|
-
const writesMapInsert = Object.values(def.sources ?? {}).some((s) => s.type === "map_insert");
|
|
1017
1024
|
return {
|
|
1018
1025
|
level,
|
|
1019
1026
|
reasons,
|
|
1020
1027
|
unproven: reasons.length === 0 ? [
|
|
1021
1028
|
"tx attribution of writes: event.tx, _tx_id (needs event proofs)",
|
|
1022
|
-
"intermediate writes within a block (needs event proofs)"
|
|
1023
|
-
...writesMapInsert ? ["map_insert vs map_set (needs event proofs)"] : []
|
|
1029
|
+
"intermediate writes within a block (needs event proofs)"
|
|
1024
1030
|
] : []
|
|
1025
1031
|
};
|
|
1026
1032
|
}
|
|
@@ -1030,15 +1036,18 @@ function isDeterminismViolation(v) {
|
|
|
1030
1036
|
function sha256(input) {
|
|
1031
1037
|
return createHash("sha256").update(input).digest("hex");
|
|
1032
1038
|
}
|
|
1033
|
-
function
|
|
1034
|
-
const
|
|
1039
|
+
function pinPreimage(input) {
|
|
1040
|
+
const fields = {
|
|
1035
1041
|
handlerHash: sha256(input.handlerCode),
|
|
1036
1042
|
network: input.network,
|
|
1037
1043
|
runtime: input.runtime ?? SUBGRAPHS_RUNTIME,
|
|
1038
1044
|
schemaHash: input.schemaHash,
|
|
1039
1045
|
startBlock: input.startBlock ?? null
|
|
1040
|
-
}
|
|
1041
|
-
return
|
|
1046
|
+
};
|
|
1047
|
+
return JSON.stringify(fields);
|
|
1048
|
+
}
|
|
1049
|
+
function computePin(input) {
|
|
1050
|
+
return sha256(pinPreimage(input));
|
|
1042
1051
|
}
|
|
1043
1052
|
// src/runtime/realm.ts
|
|
1044
1053
|
import vm from "node:vm";
|
|
@@ -1049,6 +1058,9 @@ class NondeterminismError extends Error {
|
|
|
1049
1058
|
class HandlerReadError extends Error {
|
|
1050
1059
|
name = "HandlerReadError";
|
|
1051
1060
|
}
|
|
1061
|
+
function abortsBlock(err) {
|
|
1062
|
+
return err instanceof NondeterminismError || err instanceof HandlerReadError;
|
|
1063
|
+
}
|
|
1052
1064
|
var HOST_GLOBALS = [
|
|
1053
1065
|
"ArrayBuffer",
|
|
1054
1066
|
"DataView",
|
|
@@ -1220,6 +1232,7 @@ function deterministicContext(ctx, schema) {
|
|
|
1220
1232
|
}
|
|
1221
1233
|
};
|
|
1222
1234
|
}
|
|
1235
|
+
var realmDefinitions = new WeakSet;
|
|
1223
1236
|
async function loadDeterministicDefinition(handlerCode) {
|
|
1224
1237
|
const { transform } = await import("esbuild");
|
|
1225
1238
|
const { code } = await transform(handlerCode, {
|
|
@@ -1248,7 +1261,9 @@ ${code}
|
|
|
1248
1261
|
return handler(event, facade);
|
|
1249
1262
|
};
|
|
1250
1263
|
}
|
|
1251
|
-
|
|
1264
|
+
const loaded = { ...def, sources, schema, handlers };
|
|
1265
|
+
realmDefinitions.add(loaded);
|
|
1266
|
+
return loaded;
|
|
1252
1267
|
}
|
|
1253
1268
|
// src/schema/generator.ts
|
|
1254
1269
|
import { createHash as createHash2 } from "node:crypto";
|
|
@@ -2000,12 +2015,14 @@ function renderDeployPlan(def, schemaName) {
|
|
|
2000
2015
|
async function deploySchema(db, def, handlerPath, opts) {
|
|
2001
2016
|
validateSubgraphDefinition(def);
|
|
2002
2017
|
const { statements, hash } = generateSubgraphSQL(def, opts?.schemaName);
|
|
2003
|
-
const
|
|
2018
|
+
const pinInput = opts?.handlerCode != null ? {
|
|
2004
2019
|
schemaHash: hash,
|
|
2005
2020
|
handlerCode: opts.handlerCode,
|
|
2006
2021
|
startBlock: def.startBlock,
|
|
2007
2022
|
network: opts.network ?? process.env.NETWORK ?? "mainnet"
|
|
2008
|
-
}
|
|
2023
|
+
} : null;
|
|
2024
|
+
const pin = pinInput ? computePin(pinInput) : null;
|
|
2025
|
+
const preimage = pinInput ? pinPreimage(pinInput) : null;
|
|
2009
2026
|
const identity = pin ? { pin } : {};
|
|
2010
2027
|
const { getSubgraph, registerSubgraph } = await import("@secondlayer/shared/db/queries/subgraphs");
|
|
2011
2028
|
const ddlDb = db;
|
|
@@ -2031,6 +2048,7 @@ async function deploySchema(db, def, handlerPath, opts) {
|
|
|
2031
2048
|
schemaName,
|
|
2032
2049
|
startBlock: def.startBlock,
|
|
2033
2050
|
pin,
|
|
2051
|
+
pinPreimage: preimage,
|
|
2034
2052
|
verification: opts?.verification ?? null
|
|
2035
2053
|
};
|
|
2036
2054
|
if (existing) {
|
|
@@ -2059,6 +2077,7 @@ async function deploySchema(db, def, handlerPath, opts) {
|
|
|
2059
2077
|
handlerCode: opts?.handlerCode,
|
|
2060
2078
|
sourceCode: opts?.sourceCode,
|
|
2061
2079
|
pin,
|
|
2080
|
+
pinPreimage: preimage,
|
|
2062
2081
|
verification: opts?.verification ?? null
|
|
2063
2082
|
});
|
|
2064
2083
|
return {
|
|
@@ -2263,15 +2282,136 @@ import {
|
|
|
2263
2282
|
import { logger as logger2 } from "@secondlayer/shared/logger";
|
|
2264
2283
|
|
|
2265
2284
|
// src/runtime/batch-loader.ts
|
|
2285
|
+
import { sql as sql2 } from "kysely";
|
|
2286
|
+
|
|
2287
|
+
// src/runtime/state-writes.ts
|
|
2288
|
+
var DATA_MAP = "0";
|
|
2289
|
+
var VARIABLE = "1";
|
|
2290
|
+
var HEX = /^(?:[0-9a-f]{2})+$/;
|
|
2291
|
+
function parseStateWriteKey(key) {
|
|
2292
|
+
if (!key.startsWith("vm::"))
|
|
2293
|
+
return null;
|
|
2294
|
+
const parts = key.slice(4).split("::");
|
|
2295
|
+
const [contractId, store] = parts;
|
|
2296
|
+
if (!contractId?.includes("."))
|
|
2297
|
+
return null;
|
|
2298
|
+
if (store === DATA_MAP && parts.length === 4) {
|
|
2299
|
+
const [, , map, rawKey] = parts;
|
|
2300
|
+
if (!map || !rawKey || !HEX.test(rawKey))
|
|
2301
|
+
return null;
|
|
2302
|
+
return { contractId, kind: "map", map, rawKey };
|
|
2303
|
+
}
|
|
2304
|
+
if (store === VARIABLE && parts.length === 3 && parts[2]) {
|
|
2305
|
+
return { contractId, kind: "var", varName: parts[2] };
|
|
2306
|
+
}
|
|
2307
|
+
return null;
|
|
2308
|
+
}
|
|
2309
|
+
var utf8 = new TextDecoder("utf-8", { fatal: true });
|
|
2310
|
+
function storedValue(w) {
|
|
2311
|
+
const h = w.value_hex.startsWith("0x") ? w.value_hex.slice(2) : w.value_hex;
|
|
2312
|
+
const bytes = new Uint8Array(h.length / 2);
|
|
2313
|
+
for (let i = 0;i < bytes.length; i++) {
|
|
2314
|
+
bytes[i] = Number.parseInt(h.slice(i * 2, i * 2 + 2), 16);
|
|
2315
|
+
}
|
|
2316
|
+
let value;
|
|
2317
|
+
try {
|
|
2318
|
+
value = utf8.decode(bytes);
|
|
2319
|
+
} catch {
|
|
2320
|
+
throw new Error(`state write ${w.ordinal} value is not UTF-8 hex`);
|
|
2321
|
+
}
|
|
2322
|
+
value = value.toLowerCase();
|
|
2323
|
+
if (!HEX.test(value)) {
|
|
2324
|
+
throw new Error(`state write ${w.ordinal} value is not a Clarity value`);
|
|
2325
|
+
}
|
|
2326
|
+
return value;
|
|
2327
|
+
}
|
|
2328
|
+
function writeEvent(w) {
|
|
2329
|
+
const key = parseStateWriteKey(w.key);
|
|
2330
|
+
if (!key)
|
|
2331
|
+
return null;
|
|
2332
|
+
const value = storedValue(w);
|
|
2333
|
+
if (key.kind === "var") {
|
|
2334
|
+
return {
|
|
2335
|
+
type: "var_set",
|
|
2336
|
+
data: {
|
|
2337
|
+
contract_identifier: key.contractId,
|
|
2338
|
+
var_name: key.varName,
|
|
2339
|
+
raw_value: `0x${value}`
|
|
2340
|
+
}
|
|
2341
|
+
};
|
|
2342
|
+
}
|
|
2343
|
+
const base = {
|
|
2344
|
+
contract_identifier: key.contractId,
|
|
2345
|
+
map_name: key.map,
|
|
2346
|
+
raw_key: `0x${key.rawKey}`
|
|
2347
|
+
};
|
|
2348
|
+
if (value === "09")
|
|
2349
|
+
return { type: "map_delete", data: base };
|
|
2350
|
+
if (value.startsWith("0a")) {
|
|
2351
|
+
return {
|
|
2352
|
+
type: "map_set",
|
|
2353
|
+
data: { ...base, raw_value: `0x${value.slice(2)}` }
|
|
2354
|
+
};
|
|
2355
|
+
}
|
|
2356
|
+
throw new Error(`state write ${w.ordinal} map value is neither (some v) nor none`);
|
|
2357
|
+
}
|
|
2358
|
+
function stateWriteEvents(writes, txByIndex) {
|
|
2359
|
+
const txs = new Map;
|
|
2360
|
+
const vmEvents = [];
|
|
2361
|
+
for (const w of [...writes].sort((a, b) => a.ordinal - b.ordinal)) {
|
|
2362
|
+
const event = writeEvent(w);
|
|
2363
|
+
if (!event)
|
|
2364
|
+
continue;
|
|
2365
|
+
let tx = txs.get(w.tx_index);
|
|
2366
|
+
if (!tx) {
|
|
2367
|
+
if (w.tx_index === null) {
|
|
2368
|
+
tx = { tx_id: "", type: "block", sender: "", status: "success" };
|
|
2369
|
+
} else {
|
|
2370
|
+
const real = txByIndex.get(w.tx_index);
|
|
2371
|
+
if (!real) {
|
|
2372
|
+
throw new Error(`state write ${w.ordinal} names tx_index ${w.tx_index} the block does not have`);
|
|
2373
|
+
}
|
|
2374
|
+
tx = real;
|
|
2375
|
+
}
|
|
2376
|
+
tx = { ...tx, tx_index: 0 };
|
|
2377
|
+
txs.set(w.tx_index, tx);
|
|
2378
|
+
}
|
|
2379
|
+
vmEvents.push({
|
|
2380
|
+
id: vmEventId(tx.tx_id || "block", w.ordinal),
|
|
2381
|
+
tx_id: tx.tx_id,
|
|
2382
|
+
type: event.type,
|
|
2383
|
+
event_index: w.ordinal,
|
|
2384
|
+
data: event.data,
|
|
2385
|
+
clock: "vm"
|
|
2386
|
+
});
|
|
2387
|
+
}
|
|
2388
|
+
return { txs: [...txs.values()], vmEvents };
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2391
|
+
// src/runtime/batch-loader.ts
|
|
2392
|
+
function stateWriteBlocks(writesByHeight, txsByHeight) {
|
|
2393
|
+
const out = new Map;
|
|
2394
|
+
for (const [height, writes] of writesByHeight) {
|
|
2395
|
+
const txByIndex = new Map;
|
|
2396
|
+
for (const tx of txsByHeight.get(height) ?? []) {
|
|
2397
|
+
if (tx.tx_index !== undefined)
|
|
2398
|
+
txByIndex.set(tx.tx_index, tx);
|
|
2399
|
+
}
|
|
2400
|
+
out.set(height, stateWriteEvents(writes, txByIndex));
|
|
2401
|
+
}
|
|
2402
|
+
return out;
|
|
2403
|
+
}
|
|
2266
2404
|
function vmEventId(txId, vmEventIndex) {
|
|
2267
2405
|
return `${txId}#vm:${vmEventIndex}`;
|
|
2268
2406
|
}
|
|
2269
|
-
async function loadBlockRange(db, fromHeight, toHeight) {
|
|
2270
|
-
const
|
|
2407
|
+
async function loadBlockRange(db, fromHeight, toHeight, opts = {}) {
|
|
2408
|
+
const feed = opts.stateWrites;
|
|
2409
|
+
const [blocks, txs, events, vmRows, writeRows] = await Promise.all([
|
|
2271
2410
|
db.selectFrom("blocks").selectAll().where("height", ">=", fromHeight).where("height", "<=", toHeight).where("canonical", "=", true).execute(),
|
|
2272
2411
|
db.selectFrom("transactions").selectAll().where("block_height", ">=", fromHeight).where("block_height", "<=", toHeight).execute(),
|
|
2273
2412
|
db.selectFrom("events").selectAll().where("block_height", ">=", fromHeight).where("block_height", "<=", toHeight).execute(),
|
|
2274
|
-
db.selectFrom("vm_events").selectAll().where("block_height", ">=", fromHeight).where("block_height", "<=", toHeight).orderBy("ordinal", "asc").execute()
|
|
2413
|
+
feed ? Promise.resolve([]) : db.selectFrom("vm_events").selectAll().where("block_height", ">=", fromHeight).where("block_height", "<=", toHeight).orderBy("ordinal", "asc").execute(),
|
|
2414
|
+
feed ? loadStateWrites(db, fromHeight, toHeight, feed) : Promise.resolve([])
|
|
2275
2415
|
]);
|
|
2276
2416
|
const txsByHeight = new Map;
|
|
2277
2417
|
for (const tx of txs) {
|
|
@@ -2303,18 +2443,42 @@ async function loadBlockRange(db, fromHeight, toHeight) {
|
|
|
2303
2443
|
});
|
|
2304
2444
|
vmByHeight.set(h, list);
|
|
2305
2445
|
}
|
|
2446
|
+
const writesByHeight = new Map;
|
|
2447
|
+
for (const row of writeRows) {
|
|
2448
|
+
const h = Number(row.block_height);
|
|
2449
|
+
const list = writesByHeight.get(h) ?? [];
|
|
2450
|
+
list.push({
|
|
2451
|
+
ordinal: Number(row.ordinal),
|
|
2452
|
+
tx_index: row.tx_index === null ? null : Number(row.tx_index),
|
|
2453
|
+
key: row.key,
|
|
2454
|
+
value_hex: row.value_hex
|
|
2455
|
+
});
|
|
2456
|
+
writesByHeight.set(h, list);
|
|
2457
|
+
}
|
|
2458
|
+
const named = stateWriteBlocks(writesByHeight, txsByHeight);
|
|
2306
2459
|
const result = new Map;
|
|
2307
2460
|
for (const block of blocks) {
|
|
2308
2461
|
const h = Number(block.height);
|
|
2462
|
+
const fed = named.get(h);
|
|
2309
2463
|
result.set(h, {
|
|
2310
2464
|
block,
|
|
2311
|
-
txs: txsByHeight.get(h) ?? [],
|
|
2465
|
+
txs: feed ? fed?.txs ?? [] : txsByHeight.get(h) ?? [],
|
|
2312
2466
|
events: eventsByHeight.get(h) ?? [],
|
|
2313
|
-
vmEvents: vmByHeight.get(h) ?? []
|
|
2467
|
+
vmEvents: feed ? fed?.vmEvents ?? [] : vmByHeight.get(h) ?? []
|
|
2314
2468
|
});
|
|
2315
2469
|
}
|
|
2316
2470
|
return result;
|
|
2317
2471
|
}
|
|
2472
|
+
async function loadStateWrites(db, fromHeight, toHeight, feed) {
|
|
2473
|
+
const scope = feed.contracts ? sql2`AND (${sql2.join(feed.contracts.map((c) => sql2`starts_with(key, ${`vm::${c}::`})`), sql2` OR `)})` : sql2``;
|
|
2474
|
+
const { rows } = await sql2`
|
|
2475
|
+
SELECT block_height, ordinal, tx_index, key, value_hex
|
|
2476
|
+
FROM state_writes
|
|
2477
|
+
WHERE block_height >= ${fromHeight} AND block_height <= ${toHeight} ${scope}
|
|
2478
|
+
ORDER BY block_height, ordinal
|
|
2479
|
+
`.execute(db);
|
|
2480
|
+
return rows;
|
|
2481
|
+
}
|
|
2318
2482
|
|
|
2319
2483
|
// src/runtime/observer-http-source.ts
|
|
2320
2484
|
import {
|
|
@@ -2516,14 +2680,39 @@ function sparseProbeTargets(subgraph) {
|
|
|
2516
2680
|
}
|
|
2517
2681
|
return targets;
|
|
2518
2682
|
}
|
|
2519
|
-
|
|
2683
|
+
var COVERAGE_TTL_MS = 60000;
|
|
2684
|
+
function cachedCoverage(read, ttlMs = COVERAGE_TTL_MS) {
|
|
2685
|
+
let cached;
|
|
2686
|
+
const coverage = () => {
|
|
2687
|
+
const now = Date.now();
|
|
2688
|
+
if (!cached || now - cached.at > ttlMs) {
|
|
2689
|
+
cached = { at: now, value: read().catch(() => null) };
|
|
2690
|
+
}
|
|
2691
|
+
return cached.value;
|
|
2692
|
+
};
|
|
2693
|
+
return Object.assign(coverage, {
|
|
2694
|
+
forget: () => {
|
|
2695
|
+
cached = undefined;
|
|
2696
|
+
}
|
|
2697
|
+
});
|
|
2698
|
+
}
|
|
2699
|
+
var dbStateWritesCoverage = cachedCoverage(async () => {
|
|
2700
|
+
const row = await getSourceDb2().selectFrom("state_writes").select("block_height").orderBy("block_height", "asc").limit(1).executeTakeFirst();
|
|
2701
|
+
return row ? Number(row.block_height) : null;
|
|
2702
|
+
});
|
|
2520
2703
|
class PostgresBlockSource {
|
|
2704
|
+
feed;
|
|
2705
|
+
constructor(feed) {
|
|
2706
|
+
this.feed = feed;
|
|
2707
|
+
}
|
|
2521
2708
|
async getTip() {
|
|
2522
2709
|
const progress = await getSourceDb2().selectFrom("index_progress").selectAll().where("network", "=", process.env.NETWORK ?? "mainnet").executeTakeFirst();
|
|
2523
2710
|
return progress ? Number(progress.highest_seen_block) : 0;
|
|
2524
2711
|
}
|
|
2525
2712
|
loadBlockRange(fromHeight, toHeight) {
|
|
2526
|
-
return loadBlockRange(getSourceDb2(), fromHeight, toHeight
|
|
2713
|
+
return loadBlockRange(getSourceDb2(), fromHeight, toHeight, {
|
|
2714
|
+
stateWrites: this.feed
|
|
2715
|
+
});
|
|
2527
2716
|
}
|
|
2528
2717
|
}
|
|
2529
2718
|
var EVENT_FILTER_TO_INDEX_TYPE = {
|
|
@@ -2609,15 +2798,18 @@ class PublicApiBlockSource {
|
|
|
2609
2798
|
eventTypes;
|
|
2610
2799
|
probeTargets;
|
|
2611
2800
|
needsTransactions;
|
|
2612
|
-
|
|
2801
|
+
feed;
|
|
2802
|
+
constructor(http, eventTypes, probeTargets, needsTransactions = true, feed) {
|
|
2613
2803
|
this.http = http;
|
|
2614
2804
|
this.eventTypes = eventTypes;
|
|
2615
2805
|
this.probeTargets = probeTargets;
|
|
2616
2806
|
this.needsTransactions = needsTransactions;
|
|
2807
|
+
this.feed = feed;
|
|
2617
2808
|
}
|
|
2618
2809
|
walkTargets() {
|
|
2619
2810
|
const scoped = this.needsTransactions ? undefined : this.probeTargets;
|
|
2620
|
-
|
|
2811
|
+
const types = this.feed ? this.eventTypes.filter((t) => !VM_INDEX_EVENT_TYPES.has(t)) : this.eventTypes;
|
|
2812
|
+
return types.flatMap((eventType) => {
|
|
2621
2813
|
const own = scoped?.filter((t) => t.eventType === eventType);
|
|
2622
2814
|
return own?.length ? own : [{ eventType }];
|
|
2623
2815
|
});
|
|
@@ -2640,10 +2832,11 @@ class PublicApiBlockSource {
|
|
|
2640
2832
|
}
|
|
2641
2833
|
async loadBlockRange(fromHeight, toHeight) {
|
|
2642
2834
|
const withTx = !this.needsTransactions;
|
|
2643
|
-
const [blocks, txRows, eventLists] = await Promise.all([
|
|
2835
|
+
const [blocks, txRows, eventLists, writes] = await Promise.all([
|
|
2644
2836
|
this.http.walkBlocks(fromHeight, toHeight),
|
|
2645
2837
|
this.needsTransactions ? this.http.walkTransactions(fromHeight, toHeight) : Promise.resolve([]),
|
|
2646
|
-
Promise.all(this.walkTargets().map((t) => this.http.walkEvents(t.eventType, fromHeight, toHeight, withTx, t.contractId)))
|
|
2838
|
+
Promise.all(this.walkTargets().map((t) => this.http.walkEvents(t.eventType, fromHeight, toHeight, withTx, t.contractId))),
|
|
2839
|
+
this.feed ? this.walkWrites(fromHeight, toHeight, this.feed) : null
|
|
2647
2840
|
]);
|
|
2648
2841
|
const events = dedupeEvents(eventLists.flat());
|
|
2649
2842
|
const map = new Map;
|
|
@@ -2669,13 +2862,55 @@ class PublicApiBlockSource {
|
|
|
2669
2862
|
bd.events.push(reconstructEvent(e));
|
|
2670
2863
|
}
|
|
2671
2864
|
}
|
|
2865
|
+
if (writes) {
|
|
2866
|
+
for (const [height, fed] of writes) {
|
|
2867
|
+
const bd = map.get(height);
|
|
2868
|
+
if (!bd)
|
|
2869
|
+
continue;
|
|
2870
|
+
bd.txs.push(...fed.txs);
|
|
2871
|
+
bd.vmEvents = fed.vmEvents;
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2672
2874
|
for (const bd of map.values()) {
|
|
2673
|
-
bd.txs.sort((a, b) => a.tx_index - b.tx_index);
|
|
2875
|
+
bd.txs.sort((a, b) => (a.tx_index ?? 0) - (b.tx_index ?? 0));
|
|
2674
2876
|
bd.events.sort((a, b) => a.event_index - b.event_index);
|
|
2675
2877
|
bd.vmEvents?.sort((a, b) => a.event_index - b.event_index);
|
|
2676
2878
|
}
|
|
2677
2879
|
return map;
|
|
2678
2880
|
}
|
|
2881
|
+
async walkWrites(fromHeight, toHeight, feed) {
|
|
2882
|
+
const walks = await Promise.all((feed.contracts ?? [undefined]).map((c) => this.http.walkStateWrites(fromHeight, toHeight, c)));
|
|
2883
|
+
const writesByHeight = new Map;
|
|
2884
|
+
const txsByHeight = new Map;
|
|
2885
|
+
for (const row of walks.flat()) {
|
|
2886
|
+
const writes = writesByHeight.get(row.block_height) ?? new Map;
|
|
2887
|
+
writes.set(row.ordinal, row);
|
|
2888
|
+
writesByHeight.set(row.block_height, writes);
|
|
2889
|
+
const tx = writeTx(row);
|
|
2890
|
+
if (tx) {
|
|
2891
|
+
const txs = txsByHeight.get(row.block_height) ?? new Map;
|
|
2892
|
+
txs.set(row.tx_index, tx);
|
|
2893
|
+
txsByHeight.set(row.block_height, txs);
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
return stateWriteBlocks(new Map([...writesByHeight].map(([h, w]) => [
|
|
2897
|
+
h,
|
|
2898
|
+
[...w.values()].sort((a, b) => a.ordinal - b.ordinal)
|
|
2899
|
+
])), new Map([...txsByHeight].map(([h, t]) => [h, [...t.values()]])));
|
|
2900
|
+
}
|
|
2901
|
+
}
|
|
2902
|
+
function writeTx(row) {
|
|
2903
|
+
if (row.tx_index === null || !row.tx_id)
|
|
2904
|
+
return null;
|
|
2905
|
+
return {
|
|
2906
|
+
tx_id: row.tx_id,
|
|
2907
|
+
tx_index: row.tx_index,
|
|
2908
|
+
type: row.tx_type ?? "",
|
|
2909
|
+
sender: row.tx_sender ?? "",
|
|
2910
|
+
status: row.tx_status ?? "",
|
|
2911
|
+
contract_id: row.tx_contract_id ?? null,
|
|
2912
|
+
function_name: row.tx_function_name ?? null
|
|
2913
|
+
};
|
|
2679
2914
|
}
|
|
2680
2915
|
var postgresBlockSource = new PostgresBlockSource;
|
|
2681
2916
|
function buildHttpClient() {
|
|
@@ -2713,5 +2948,5 @@ export {
|
|
|
2713
2948
|
validateSubgraphDefinition
|
|
2714
2949
|
};
|
|
2715
2950
|
|
|
2716
|
-
//# debugId=
|
|
2951
|
+
//# debugId=411D5E1C7A6D7DEB64756E2164756E21
|
|
2717
2952
|
//# sourceMappingURL=index.js.map
|