envio 3.3.0-alpha.0 → 3.3.0-alpha.10
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/evm.schema.json +10 -0
- package/index.d.ts +45 -25
- package/package.json +7 -7
- package/src/Address.res +5 -2
- package/src/Address.res.mjs +3 -1
- package/src/Api.res +1 -1
- package/src/Api.res.mjs +1 -1
- package/src/Batch.res +0 -6
- package/src/Batch.res.mjs +1 -12
- package/src/BatchProcessing.res +7 -12
- package/src/BatchProcessing.res.mjs +8 -7
- package/src/Bin.res +3 -0
- package/src/Bin.res.mjs +4 -0
- package/src/ChainFetching.res +48 -16
- package/src/ChainFetching.res.mjs +36 -17
- package/src/ChainMetadata.res +1 -11
- package/src/ChainMetadata.res.mjs +1 -10
- package/src/ChainState.res +628 -149
- package/src/ChainState.res.mjs +440 -102
- package/src/ChainState.resi +74 -4
- package/src/Config.res +61 -33
- package/src/Config.res.mjs +50 -10
- package/src/ContractRegisterContext.res +2 -12
- package/src/ContractRegisterContext.res.mjs +3 -5
- package/src/Core.res +14 -3
- package/src/CrossChainState.res +142 -93
- package/src/CrossChainState.res.mjs +88 -60
- package/src/CrossChainState.resi +2 -10
- package/src/Ecosystem.res +5 -6
- package/src/Ecosystem.res.mjs +3 -3
- package/src/Env.res +0 -7
- package/src/Env.res.mjs +0 -6
- package/src/Envio.res +17 -11
- package/src/EnvioGlobal.res +53 -0
- package/src/EnvioGlobal.res.mjs +31 -0
- package/src/EventConfigBuilder.res +177 -88
- package/src/EventConfigBuilder.res.mjs +99 -42
- package/src/EventProcessing.res +74 -28
- package/src/EventProcessing.res.mjs +55 -29
- package/src/ExitOnCaughtUp.res +10 -2
- package/src/ExitOnCaughtUp.res.mjs +10 -1
- package/src/FetchState.res +558 -300
- package/src/FetchState.res.mjs +437 -423
- package/src/HandlerLoader.res +8 -104
- package/src/HandlerLoader.res.mjs +2 -81
- package/src/HandlerRegister.res +518 -144
- package/src/HandlerRegister.res.mjs +285 -133
- package/src/HandlerRegister.resi +24 -8
- package/src/IndexerLoop.res +2 -3
- package/src/IndexerLoop.res.mjs +1 -1
- package/src/IndexerState.res +10 -11
- package/src/IndexerState.res.mjs +14 -11
- package/src/IndexerState.resi +2 -5
- package/src/IndexingAddresses.res +108 -0
- package/src/IndexingAddresses.res.mjs +101 -0
- package/src/IndexingAddresses.resi +34 -0
- package/src/Internal.res +155 -46
- package/src/Internal.res.mjs +30 -2
- package/src/LoadLayer.res +5 -5
- package/src/LoadLayer.res.mjs +6 -6
- package/src/LogSelection.res +102 -165
- package/src/LogSelection.res.mjs +101 -116
- package/src/Main.res +71 -236
- package/src/Main.res.mjs +60 -145
- package/src/Metrics.res +74 -0
- package/src/Metrics.res.mjs +75 -0
- package/src/PgStorage.res +4 -4
- package/src/PgStorage.res.mjs +5 -5
- package/src/Prometheus.res +10 -74
- package/src/Prometheus.res.mjs +124 -186
- package/src/PruneStaleHistory.res +2 -2
- package/src/PruneStaleHistory.res.mjs +3 -3
- package/src/RawEvent.res +7 -2
- package/src/RawEvent.res.mjs +4 -4
- package/src/Rollback.res +3 -3
- package/src/Rollback.res.mjs +4 -4
- package/src/RollbackCommit.res +4 -1
- package/src/RollbackCommit.res.mjs +3 -2
- package/src/SimulateDeadInputTracker.res +85 -0
- package/src/SimulateDeadInputTracker.res.mjs +73 -0
- package/src/SimulateDeadInputTracker.resi +12 -0
- package/src/SimulateItems.res +91 -23
- package/src/SimulateItems.res.mjs +55 -32
- package/src/TestIndexer.res +54 -40
- package/src/TestIndexer.res.mjs +37 -30
- package/src/bindings/Performance.res +7 -0
- package/src/bindings/Performance.res.mjs +21 -0
- package/src/bindings/Performance.resi +7 -0
- package/src/bindings/Viem.res +0 -41
- package/src/bindings/Viem.res.mjs +1 -43
- package/src/sources/BlockStore.res +46 -0
- package/src/sources/BlockStore.res.mjs +24 -0
- package/src/sources/EventRouter.res +36 -33
- package/src/sources/EventRouter.res.mjs +13 -14
- package/src/sources/Evm.res +83 -72
- package/src/sources/Evm.res.mjs +53 -69
- package/src/sources/EvmChain.res +18 -20
- package/src/sources/EvmChain.res.mjs +15 -15
- package/src/sources/EvmRpcClient.res +74 -5
- package/src/sources/EvmRpcClient.res.mjs +13 -4
- package/src/sources/FieldMask.res +39 -0
- package/src/sources/FieldMask.res.mjs +42 -0
- package/src/sources/Fuel.res +9 -6
- package/src/sources/Fuel.res.mjs +5 -10
- package/src/sources/HyperFuelSource.res +46 -50
- package/src/sources/HyperFuelSource.res.mjs +64 -54
- package/src/sources/HyperSync.res +39 -7
- package/src/sources/HyperSync.res.mjs +57 -37
- package/src/sources/HyperSync.resi +12 -2
- package/src/sources/HyperSyncClient.res +22 -111
- package/src/sources/HyperSyncClient.res.mjs +2 -30
- package/src/sources/HyperSyncHeightStream.res +1 -8
- package/src/sources/HyperSyncHeightStream.res.mjs +0 -2
- package/src/sources/HyperSyncSource.res +94 -107
- package/src/sources/HyperSyncSource.res.mjs +82 -86
- package/src/sources/Rpc.res +15 -47
- package/src/sources/Rpc.res.mjs +25 -56
- package/src/sources/RpcSource.res +320 -467
- package/src/sources/RpcSource.res.mjs +268 -385
- package/src/sources/RpcWebSocketHeightStream.res +0 -5
- package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -2
- package/src/sources/SimulateSource.res +10 -4
- package/src/sources/SimulateSource.res.mjs +16 -6
- package/src/sources/Source.res +34 -6
- package/src/sources/SourceManager.res +86 -27
- package/src/sources/SourceManager.res.mjs +84 -47
- package/src/sources/SourceManager.resi +12 -3
- package/src/sources/Svm.res +31 -16
- package/src/sources/Svm.res.mjs +36 -13
- package/src/sources/SvmHyperSyncClient.res +5 -32
- package/src/sources/SvmHyperSyncSource.res +159 -134
- package/src/sources/SvmHyperSyncSource.res.mjs +164 -129
- package/src/sources/TransactionStore.res +49 -0
- package/src/sources/TransactionStore.res.mjs +30 -0
- package/src/tui/Tui.res +13 -16
- package/src/tui/Tui.res.mjs +12 -14
- package/svm.schema.json +49 -37
- package/src/bindings/Hrtime.res +0 -58
- package/src/bindings/Hrtime.res.mjs +0 -90
- package/src/bindings/Hrtime.resi +0 -30
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
-
import * as Hrtime from "../bindings/Hrtime.res.mjs";
|
|
4
3
|
import * as Source from "./Source.res.mjs";
|
|
5
|
-
import * as Prometheus from "../Prometheus.res.mjs";
|
|
6
4
|
import * as EventRouter from "./EventRouter.res.mjs";
|
|
5
|
+
import * as Performance from "../bindings/Performance.res.mjs";
|
|
7
6
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
8
7
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
9
8
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
@@ -166,7 +165,7 @@ function parseDecoded(d) {
|
|
|
166
165
|
};
|
|
167
166
|
}
|
|
168
167
|
|
|
169
|
-
function toSvmInstruction(instr, programName, instructionName,
|
|
168
|
+
function toSvmInstruction(instr, programName, instructionName, logs) {
|
|
170
169
|
return {
|
|
171
170
|
programName: programName,
|
|
172
171
|
instructionName: instructionName,
|
|
@@ -180,40 +179,14 @@ function toSvmInstruction(instr, programName, instructionName, transaction, logs
|
|
|
180
179
|
d4: instr.d4,
|
|
181
180
|
d8: instr.d8,
|
|
182
181
|
params: Stdlib_Option.map(instr.decoded, parseDecoded),
|
|
183
|
-
|
|
184
|
-
logs: logs,
|
|
185
|
-
block: block
|
|
182
|
+
logs: logs
|
|
186
183
|
};
|
|
187
184
|
}
|
|
188
185
|
|
|
189
|
-
function
|
|
190
|
-
return {
|
|
191
|
-
signatures: tx.signatures,
|
|
192
|
-
feePayer: Stdlib_Option.map(tx.feePayer, prim => prim),
|
|
193
|
-
success: tx.success,
|
|
194
|
-
err: tx.err,
|
|
195
|
-
fee: Stdlib_Option.map(tx.fee, prim => BigInt(prim)),
|
|
196
|
-
computeUnitsConsumed: Stdlib_Option.map(tx.computeUnitsConsumed, prim => BigInt(prim)),
|
|
197
|
-
accountKeys: tx.accountKeys,
|
|
198
|
-
recentBlockhash: tx.recentBlockhash,
|
|
199
|
-
version: tx.version
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
function toSvmTokenBalance(tb) {
|
|
204
|
-
return {
|
|
205
|
-
account: Stdlib_Option.map(tb.account, prim => prim),
|
|
206
|
-
mint: Stdlib_Option.map(tb.mint, prim => prim),
|
|
207
|
-
owner: Stdlib_Option.map(tb.owner, prim => prim),
|
|
208
|
-
preAmount: tb.preAmount,
|
|
209
|
-
postAmount: tb.postAmount
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
function probeRouter(router, programId, instr, byteLengthsDesc, contractAddress, indexingAddresses) {
|
|
186
|
+
function probeRouter(router, programId, instr, byteLengthsDesc, contractAddress, contractNameByAddress) {
|
|
214
187
|
let probe = dN => {
|
|
215
188
|
let tag = EventRouter.getSvmEventId(programId, dN);
|
|
216
|
-
return EventRouter.get(router, tag, contractAddress,
|
|
189
|
+
return EventRouter.get(router, tag, contractAddress, contractNameByAddress);
|
|
217
190
|
};
|
|
218
191
|
let result = Stdlib_Array.reduce(byteLengthsDesc, undefined, (acc, len) => {
|
|
219
192
|
if (acc !== undefined) {
|
|
@@ -247,43 +220,109 @@ function probeRouter(router, programId, instr, byteLengthsDesc, contractAddress,
|
|
|
247
220
|
}
|
|
248
221
|
}
|
|
249
222
|
|
|
223
|
+
function toQueryTxField(field) {
|
|
224
|
+
switch (field) {
|
|
225
|
+
case "signatures" :
|
|
226
|
+
return "signatures";
|
|
227
|
+
case "feePayer" :
|
|
228
|
+
return "fee_payer";
|
|
229
|
+
case "success" :
|
|
230
|
+
return "success";
|
|
231
|
+
case "err" :
|
|
232
|
+
return "err";
|
|
233
|
+
case "fee" :
|
|
234
|
+
return "fee";
|
|
235
|
+
case "computeUnitsConsumed" :
|
|
236
|
+
return "compute_units_consumed";
|
|
237
|
+
case "accountKeys" :
|
|
238
|
+
return "account_keys";
|
|
239
|
+
case "recentBlockhash" :
|
|
240
|
+
return "recent_blockhash";
|
|
241
|
+
case "version" :
|
|
242
|
+
return "version";
|
|
243
|
+
case "transactionIndex" :
|
|
244
|
+
case "tokenBalances" :
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function toQueryBlockField(field) {
|
|
250
|
+
switch (field) {
|
|
251
|
+
case "height" :
|
|
252
|
+
return "block_height";
|
|
253
|
+
case "parentSlot" :
|
|
254
|
+
return "parent_slot";
|
|
255
|
+
case "parentHash" :
|
|
256
|
+
return "parent_blockhash";
|
|
257
|
+
default:
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
250
262
|
function make(param) {
|
|
251
|
-
let
|
|
263
|
+
let onEventRegistrations = param.onEventRegistrations;
|
|
252
264
|
let chain = param.chain;
|
|
253
|
-
let
|
|
265
|
+
let eventConfigs = onEventRegistrations.map(reg => reg.eventConfig);
|
|
254
266
|
let programSchemas = buildProgramSchemas(eventConfigs);
|
|
255
267
|
let client = SvmHyperSyncClient.make(param.endpointUrl, param.apiToken, param.clientTimeoutMillis, undefined, undefined, undefined, programSchemas.length !== 0 ? programSchemas : undefined);
|
|
256
|
-
let match = EventRouter.fromSvmEventConfigsOrThrow(
|
|
268
|
+
let match = EventRouter.fromSvmEventConfigsOrThrow(onEventRegistrations, chain);
|
|
257
269
|
let eventRouter = match[0];
|
|
258
270
|
let orderingByProgram = {};
|
|
259
271
|
match[1].forEach(o => {
|
|
260
272
|
orderingByProgram[o.programId] = o.byteLengthsDesc;
|
|
261
273
|
});
|
|
262
|
-
let needsTransactions = eventConfigs.some(cfg => cfg.includeTransaction);
|
|
263
274
|
let needsLogs = eventConfigs.some(cfg => cfg.includeLogs);
|
|
264
|
-
let
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
275
|
+
let selectedTxFields = new Set();
|
|
276
|
+
eventConfigs.forEach(cfg => {
|
|
277
|
+
cfg.selectedTransactionFields.forEach(field => {
|
|
278
|
+
selectedTxFields.add(field);
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
let needsTokenBalances = selectedTxFields.has("tokenBalances");
|
|
282
|
+
let fields = [
|
|
283
|
+
"slot",
|
|
284
|
+
"transaction_index"
|
|
285
|
+
];
|
|
286
|
+
Array.from(selectedTxFields).forEach(field => {
|
|
287
|
+
let queryField = toQueryTxField(field);
|
|
288
|
+
if (queryField !== undefined) {
|
|
289
|
+
fields.push(queryField);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
let needsTransactions = Array.from(selectedTxFields).some(field => {
|
|
294
|
+
switch (field) {
|
|
295
|
+
case "transactionIndex" :
|
|
296
|
+
case "tokenBalances" :
|
|
297
|
+
return false;
|
|
298
|
+
default:
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
let fields$1 = [
|
|
303
|
+
"slot",
|
|
304
|
+
"blockhash",
|
|
305
|
+
"block_time"
|
|
306
|
+
];
|
|
307
|
+
let selected = new Set();
|
|
308
|
+
eventConfigs.forEach(cfg => {
|
|
309
|
+
cfg.selectedBlockFields.forEach(field => {
|
|
310
|
+
selected.add(field);
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
selected.forEach(field => {
|
|
314
|
+
let queryField = toQueryBlockField(field);
|
|
315
|
+
if (queryField !== undefined) {
|
|
316
|
+
fields$1.push(queryField);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
let getItemsOrThrow = async (fromBlock, toBlock, param, contractNameByAddress, knownHeight, param$1, param$2, itemsTarget, retry, logger) => {
|
|
321
|
+
let totalTimeRef = Performance.now();
|
|
322
|
+
let pageFetchRef = Performance.now();
|
|
268
323
|
let instructionSelections = buildInstructionSelections(eventConfigs);
|
|
269
|
-
let fields_block =
|
|
270
|
-
|
|
271
|
-
"blockhash",
|
|
272
|
-
"block_time"
|
|
273
|
-
];
|
|
274
|
-
let fields_transaction = needsTransactions ? [
|
|
275
|
-
"slot",
|
|
276
|
-
"transaction_index",
|
|
277
|
-
"signatures",
|
|
278
|
-
"fee_payer",
|
|
279
|
-
"success",
|
|
280
|
-
"err",
|
|
281
|
-
"fee",
|
|
282
|
-
"compute_units_consumed",
|
|
283
|
-
"account_keys",
|
|
284
|
-
"recent_blockhash",
|
|
285
|
-
"version"
|
|
286
|
-
] : undefined;
|
|
324
|
+
let fields_block = fields$1;
|
|
325
|
+
let fields_transaction = needsTransactions ? fields : undefined;
|
|
287
326
|
let fields_log = needsLogs ? [
|
|
288
327
|
"slot",
|
|
289
328
|
"transaction_index",
|
|
@@ -300,7 +339,7 @@ function make(param) {
|
|
|
300
339
|
"pre_amount",
|
|
301
340
|
"post_amount"
|
|
302
341
|
] : undefined;
|
|
303
|
-
let fields = {
|
|
342
|
+
let fields$2 = {
|
|
304
343
|
block: fields_block,
|
|
305
344
|
transaction: fields_transaction,
|
|
306
345
|
log: fields_log,
|
|
@@ -308,17 +347,18 @@ function make(param) {
|
|
|
308
347
|
};
|
|
309
348
|
let query_toSlot = Stdlib_Option.map(toBlock, toBlock => toBlock + 1 | 0);
|
|
310
349
|
let query_instructions = instructionSelections;
|
|
311
|
-
let query_fields = fields;
|
|
350
|
+
let query_fields = fields$2;
|
|
351
|
+
let query_maxNumInstructions = itemsTarget;
|
|
312
352
|
let query = {
|
|
313
353
|
fromSlot: fromBlock,
|
|
314
354
|
toSlot: query_toSlot,
|
|
315
355
|
instructions: query_instructions,
|
|
316
|
-
fields: query_fields
|
|
356
|
+
fields: query_fields,
|
|
357
|
+
maxNumInstructions: query_maxNumInstructions
|
|
317
358
|
};
|
|
318
|
-
|
|
319
|
-
let resp;
|
|
359
|
+
let match;
|
|
320
360
|
try {
|
|
321
|
-
|
|
361
|
+
match = await client.get(query);
|
|
322
362
|
} catch (raw_exn) {
|
|
323
363
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
324
364
|
throw {
|
|
@@ -336,8 +376,13 @@ function make(param) {
|
|
|
336
376
|
Error: new Error()
|
|
337
377
|
};
|
|
338
378
|
}
|
|
339
|
-
let
|
|
340
|
-
let
|
|
379
|
+
let resp = match[0];
|
|
380
|
+
let pageFetchTime = Performance.secondsSince(pageFetchRef);
|
|
381
|
+
let requestStats = [{
|
|
382
|
+
method: "getInstructions",
|
|
383
|
+
seconds: pageFetchTime
|
|
384
|
+
}];
|
|
385
|
+
let parsingRef = Performance.now();
|
|
341
386
|
let blockTimeBySlot = {};
|
|
342
387
|
resp.data.blocks.forEach(b => {
|
|
343
388
|
let t = b.blockTime;
|
|
@@ -346,11 +391,6 @@ function make(param) {
|
|
|
346
391
|
return;
|
|
347
392
|
}
|
|
348
393
|
});
|
|
349
|
-
let txByKey = {};
|
|
350
|
-
resp.data.transactions.forEach(tx => {
|
|
351
|
-
let key = tx.slot.toString() + ":" + tx.transactionIndex.toString();
|
|
352
|
-
txByKey[key] = tx;
|
|
353
|
-
});
|
|
354
394
|
let logsByKey = {};
|
|
355
395
|
resp.data.logs.forEach(log => {
|
|
356
396
|
let match = log.transactionIndex;
|
|
@@ -369,73 +409,45 @@ function make(param) {
|
|
|
369
409
|
logsByKey[key] = [log];
|
|
370
410
|
}
|
|
371
411
|
});
|
|
372
|
-
let tokenBalancesByTx = {};
|
|
373
|
-
if (needsTokenBalances) {
|
|
374
|
-
resp.data.tokenBalances.forEach(tb => {
|
|
375
|
-
let txIdx = tb.transactionIndex;
|
|
376
|
-
if (txIdx === undefined) {
|
|
377
|
-
return;
|
|
378
|
-
}
|
|
379
|
-
let key = tb.slot.toString() + ":" + txIdx.toString();
|
|
380
|
-
let existing = tokenBalancesByTx[key];
|
|
381
|
-
if (existing !== undefined) {
|
|
382
|
-
existing.push(tb);
|
|
383
|
-
} else {
|
|
384
|
-
tokenBalancesByTx[key] = [tb];
|
|
385
|
-
}
|
|
386
|
-
});
|
|
387
|
-
}
|
|
388
412
|
let parsedQueueItems = [];
|
|
389
413
|
resp.data.instructions.forEach(instr => {
|
|
390
414
|
let programId = instr.programId;
|
|
391
415
|
let byteLengths = Stdlib_Option.getOr(orderingByProgram[instr.programId], []);
|
|
392
416
|
let contractAddress = instr.programId;
|
|
393
|
-
let maybeConfig = probeRouter(eventRouter, programId, instr, byteLengths, contractAddress,
|
|
417
|
+
let maybeConfig = probeRouter(eventRouter, programId, instr, byteLengths, contractAddress, contractNameByAddress);
|
|
394
418
|
if (maybeConfig !== undefined) {
|
|
395
|
-
let
|
|
396
|
-
let maybeTx = Stdlib_Option.map(txByKey[txKey], toSvmTransaction);
|
|
397
|
-
let maybeTx$1 = maybeConfig.includeTokenBalances ? Stdlib_Option.map(maybeTx, tx => {
|
|
398
|
-
let maybeBalances = Stdlib_Option.map(tokenBalancesByTx[txKey], bals => bals.map(toSvmTokenBalance));
|
|
399
|
-
let newrecord = {...tx};
|
|
400
|
-
newrecord.tokenBalances = maybeBalances;
|
|
401
|
-
return newrecord;
|
|
402
|
-
}) : maybeTx;
|
|
419
|
+
let eventConfig = maybeConfig.eventConfig;
|
|
403
420
|
let logKey = instr.slot.toString() + ":" + instr.transactionIndex.toString() + ":" + serializeInstructionAddress(instr.instructionAddress);
|
|
404
421
|
let maybeLogs = Stdlib_Option.map(logsByKey[logKey], logs => logs.map(log => ({
|
|
405
422
|
kind: Stdlib_Option.getOr(log.kind, ""),
|
|
406
423
|
message: Stdlib_Option.getOr(log.message, "")
|
|
407
424
|
})));
|
|
408
|
-
let
|
|
409
|
-
let blockTime = blockTimeBySlot[slotKey];
|
|
410
|
-
let payload = toSvmInstruction(instr, maybeConfig.contractName, maybeConfig.name, maybeConfig.includeTransaction ? maybeTx$1 : undefined, maybeConfig.includeLogs ? maybeLogs : undefined, {
|
|
411
|
-
slot: instr.slot,
|
|
412
|
-
time: Stdlib_Option.getOr(blockTime, 0),
|
|
413
|
-
hash: ""
|
|
414
|
-
});
|
|
425
|
+
let payload = toSvmInstruction(instr, eventConfig.contractName, eventConfig.name, eventConfig.includeLogs ? maybeLogs : undefined);
|
|
415
426
|
parsedQueueItems.push({
|
|
416
427
|
kind: 0,
|
|
417
|
-
|
|
418
|
-
timestamp: Stdlib_Option.getOr(blockTime, 0),
|
|
428
|
+
onEventRegistration: maybeConfig,
|
|
419
429
|
chain: chain,
|
|
420
430
|
blockNumber: instr.slot,
|
|
421
|
-
blockHash: "",
|
|
422
431
|
logIndex: synthLogIndex(instr),
|
|
432
|
+
transactionIndex: instr.transactionIndex,
|
|
423
433
|
payload: payload
|
|
424
434
|
});
|
|
425
435
|
}
|
|
426
436
|
});
|
|
427
|
-
let parsingTimeElapsed =
|
|
437
|
+
let parsingTimeElapsed = Performance.secondsSince(parsingRef);
|
|
428
438
|
let highestSlot = resp.nextSlot - 1 | 0;
|
|
429
439
|
let latestBlockTime = Stdlib_Option.getOr(blockTimeBySlot[highestSlot.toString()], 0);
|
|
430
440
|
let blockHashes = resp.data.blocks.map(b => ({
|
|
431
441
|
blockHash: b.blockhash,
|
|
432
442
|
blockNumber: b.slot
|
|
433
443
|
}));
|
|
434
|
-
let totalTimeElapsed =
|
|
444
|
+
let totalTimeElapsed = Performance.secondsSince(totalTimeRef);
|
|
435
445
|
return {
|
|
436
446
|
knownHeight: knownHeight,
|
|
437
447
|
blockHashes: blockHashes,
|
|
438
448
|
parsedQueueItems: parsedQueueItems,
|
|
449
|
+
transactionStore: Primitive_option.some(match[1]),
|
|
450
|
+
blockStore: Primitive_option.some(match[2]),
|
|
439
451
|
fromBlockQueried: fromBlock,
|
|
440
452
|
latestFetchedBlockNumber: highestSlot,
|
|
441
453
|
latestFetchedBlockTimestamp: latestBlockTime,
|
|
@@ -443,11 +455,13 @@ function make(param) {
|
|
|
443
455
|
"total time elapsed (s)": totalTimeElapsed,
|
|
444
456
|
"parsing time (s)": parsingTimeElapsed,
|
|
445
457
|
"page fetch time (s)": pageFetchTime
|
|
446
|
-
}
|
|
458
|
+
},
|
|
459
|
+
requestStats: requestStats
|
|
447
460
|
};
|
|
448
461
|
};
|
|
449
462
|
let queryBlockDataRange = async (fromSlot, toSlot) => {
|
|
450
463
|
let blockDatas = [];
|
|
464
|
+
let requestStats = [];
|
|
451
465
|
let fromRef = fromSlot;
|
|
452
466
|
let keepGoing = true;
|
|
453
467
|
while (keepGoing) {
|
|
@@ -468,8 +482,13 @@ function make(param) {
|
|
|
468
482
|
fields: query_fields,
|
|
469
483
|
maxNumBlocks: query_maxNumBlocks
|
|
470
484
|
};
|
|
471
|
-
|
|
472
|
-
let
|
|
485
|
+
let timerRef = Performance.now();
|
|
486
|
+
let match = await client.get(query);
|
|
487
|
+
let resp = match[0];
|
|
488
|
+
requestStats.push({
|
|
489
|
+
method: "getBlockHashes",
|
|
490
|
+
seconds: Performance.secondsSince(timerRef)
|
|
491
|
+
});
|
|
473
492
|
resp.data.blocks.forEach(b => {
|
|
474
493
|
blockDatas.push({
|
|
475
494
|
blockHash: b.blockhash,
|
|
@@ -483,14 +502,20 @@ function make(param) {
|
|
|
483
502
|
fromRef = resp.nextSlot;
|
|
484
503
|
}
|
|
485
504
|
};
|
|
486
|
-
return
|
|
505
|
+
return [
|
|
506
|
+
blockDatas,
|
|
507
|
+
requestStats
|
|
508
|
+
];
|
|
487
509
|
};
|
|
488
510
|
let getBlockHashes = async (blockNumbers, param) => {
|
|
489
511
|
let firstSlot = blockNumbers[0];
|
|
490
512
|
if (firstSlot === undefined) {
|
|
491
513
|
return {
|
|
492
|
-
|
|
493
|
-
|
|
514
|
+
result: {
|
|
515
|
+
TAG: "Ok",
|
|
516
|
+
_0: []
|
|
517
|
+
},
|
|
518
|
+
requestStats: []
|
|
494
519
|
};
|
|
495
520
|
}
|
|
496
521
|
try {
|
|
@@ -510,33 +535,43 @@ function make(param) {
|
|
|
510
535
|
}
|
|
511
536
|
requested.add(slot);
|
|
512
537
|
});
|
|
513
|
-
let
|
|
538
|
+
let match = await queryBlockDataRange(minSlot.contents, maxSlot.contents);
|
|
514
539
|
return {
|
|
515
|
-
|
|
516
|
-
|
|
540
|
+
result: {
|
|
541
|
+
TAG: "Ok",
|
|
542
|
+
_0: match[0].filter(data => requested.delete(data.blockNumber))
|
|
543
|
+
},
|
|
544
|
+
requestStats: match[1]
|
|
517
545
|
};
|
|
518
546
|
} catch (raw_exn) {
|
|
519
547
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
520
548
|
return {
|
|
521
|
-
|
|
522
|
-
|
|
549
|
+
result: {
|
|
550
|
+
TAG: "Error",
|
|
551
|
+
_0: exn
|
|
552
|
+
},
|
|
553
|
+
requestStats: []
|
|
523
554
|
};
|
|
524
555
|
}
|
|
525
556
|
};
|
|
526
557
|
return {
|
|
527
|
-
name:
|
|
558
|
+
name: "SvmHyperSync",
|
|
528
559
|
sourceFor: "Sync",
|
|
529
560
|
chain: chain,
|
|
530
561
|
poweredByHyperSync: true,
|
|
531
562
|
pollingInterval: 1000,
|
|
532
563
|
getBlockHashes: getBlockHashes,
|
|
533
564
|
getHeightOrThrow: async () => {
|
|
534
|
-
let timer =
|
|
535
|
-
let
|
|
536
|
-
let seconds =
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
565
|
+
let timer = Performance.now();
|
|
566
|
+
let height = await client.getHeight();
|
|
567
|
+
let seconds = Performance.secondsSince(timer);
|
|
568
|
+
return {
|
|
569
|
+
height: height,
|
|
570
|
+
requestStats: [{
|
|
571
|
+
method: "getHeight",
|
|
572
|
+
seconds: seconds
|
|
573
|
+
}]
|
|
574
|
+
};
|
|
540
575
|
},
|
|
541
576
|
getItemsOrThrow: getItemsOrThrow
|
|
542
577
|
};
|
|
@@ -549,9 +584,9 @@ export {
|
|
|
549
584
|
buildProgramSchemas,
|
|
550
585
|
parseDecoded,
|
|
551
586
|
toSvmInstruction,
|
|
552
|
-
toSvmTransaction,
|
|
553
|
-
toSvmTokenBalance,
|
|
554
587
|
probeRouter,
|
|
588
|
+
toQueryTxField,
|
|
589
|
+
toQueryBlockField,
|
|
555
590
|
make,
|
|
556
591
|
}
|
|
557
|
-
/*
|
|
592
|
+
/* EventRouter Not a pure module */
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Binding to the Rust `TransactionStore` napi class. Transactions are kept in
|
|
2
|
+
// Rust as raw structs (their large fields never enter JS until read) keyed by
|
|
3
|
+
// (blockNumber, transactionIndex). One store lives per chain on `ChainState`;
|
|
4
|
+
// each fetch response contributes a page that is merged in. At batch
|
|
5
|
+
// preparation the selected fields are materialised in bulk, off the JS thread,
|
|
6
|
+
// in columnar form and zipped into plain JS objects on the main thread.
|
|
7
|
+
type t
|
|
8
|
+
|
|
9
|
+
@send external newEvm: (Core.transactionStoreCtor, ~shouldChecksum: bool) => t = "newEvm"
|
|
10
|
+
@send external newSvm: Core.transactionStoreCtor => t = "newSvm"
|
|
11
|
+
@send external newFuel: Core.transactionStoreCtor => t = "newFuel"
|
|
12
|
+
|
|
13
|
+
// The store's ecosystem is fixed here, from the chain's config. EVM carries the
|
|
14
|
+
// chain's address-checksumming setting; SVM/Fuel need no extra data.
|
|
15
|
+
let make = (~ecosystem: Ecosystem.name, ~shouldChecksum: bool): t => {
|
|
16
|
+
let ctor = Core.getAddon().transactionStore
|
|
17
|
+
switch ecosystem {
|
|
18
|
+
| Evm => ctor->newEvm(~shouldChecksum)
|
|
19
|
+
| Svm => ctor->newSvm
|
|
20
|
+
| Fuel => ctor->newFuel
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// One event's selected transaction fields → store selection bitmask, built from
|
|
25
|
+
// the ecosystem's ordered field-name array (the bit index is the field code
|
|
26
|
+
// shared with the Rust store, `EvmTxField`/`SvmTxField`).
|
|
27
|
+
let makeMaskFn = FieldMask.makeMaskFn
|
|
28
|
+
let orMask = FieldMask.orMask
|
|
29
|
+
let fieldCodes = FieldMask.fieldCodes
|
|
30
|
+
|
|
31
|
+
// Drain another store (a fetch-response page) into this one.
|
|
32
|
+
@send external merge: (t, t) => unit = "merge"
|
|
33
|
+
|
|
34
|
+
// Bulk-materialise transactions off the JS thread, one row per
|
|
35
|
+
// (blockNumbers[i], transactionIndices[i]) key, decoding only the fields set in
|
|
36
|
+
// that row's own masks[i]. Result is aligned with the input.
|
|
37
|
+
@send
|
|
38
|
+
external materialize: (
|
|
39
|
+
t,
|
|
40
|
+
~blockNumbers: array<int>,
|
|
41
|
+
~transactionIndices: array<int>,
|
|
42
|
+
~masks: array<float>,
|
|
43
|
+
) => promise<array<Internal.eventTransaction>> = "materialize"
|
|
44
|
+
|
|
45
|
+
// Drop transactions for blocks at or below the given block (already processed).
|
|
46
|
+
@send external prune: (t, int) => unit = "prune"
|
|
47
|
+
|
|
48
|
+
// Drop transactions for blocks above the given block (rolled back).
|
|
49
|
+
@send external rollback: (t, int) => unit = "rollback"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Core from "../Core.res.mjs";
|
|
4
|
+
import * as FieldMask from "./FieldMask.res.mjs";
|
|
5
|
+
|
|
6
|
+
function make(ecosystem, shouldChecksum) {
|
|
7
|
+
let ctor = Core.getAddon().TransactionStore;
|
|
8
|
+
switch (ecosystem) {
|
|
9
|
+
case "evm" :
|
|
10
|
+
return ctor.newEvm(shouldChecksum);
|
|
11
|
+
case "fuel" :
|
|
12
|
+
return ctor.newFuel();
|
|
13
|
+
case "svm" :
|
|
14
|
+
return ctor.newSvm();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let makeMaskFn = FieldMask.makeMaskFn;
|
|
19
|
+
|
|
20
|
+
let orMask = FieldMask.orMask;
|
|
21
|
+
|
|
22
|
+
let fieldCodes = FieldMask.fieldCodes;
|
|
23
|
+
|
|
24
|
+
export {
|
|
25
|
+
make,
|
|
26
|
+
makeMaskFn,
|
|
27
|
+
orMask,
|
|
28
|
+
fieldCodes,
|
|
29
|
+
}
|
|
30
|
+
/* Core Not a pure module */
|
package/src/tui/Tui.res
CHANGED
|
@@ -157,18 +157,15 @@ module App = {
|
|
|
157
157
|
->IndexerState.chainStates
|
|
158
158
|
->Dict.valuesToArray
|
|
159
159
|
->Array.map(cs => {
|
|
160
|
-
let
|
|
161
|
-
let
|
|
160
|
+
let data = cs->ChainState.toChainData
|
|
161
|
+
let numEventsProcessed = data.numEventsProcessed
|
|
162
162
|
let committedProgressBlockNumber = cs->ChainState.committedProgressBlockNumber
|
|
163
|
-
let timestampCaughtUpToHeadOrEndblock =
|
|
163
|
+
let timestampCaughtUpToHeadOrEndblock = data.timestampCaughtUpToHeadOrEndblock
|
|
164
164
|
let sourceManager = cs->ChainState.sourceManager
|
|
165
|
-
let latestFetchedBlockNumber =
|
|
165
|
+
let latestFetchedBlockNumber = data.latestFetchedBlockNumber
|
|
166
166
|
let hasProcessedToEndblock = cs->ChainState.hasProcessedToEndblock
|
|
167
|
-
let knownHeight = hasProcessedToEndblock
|
|
168
|
-
? fetchState.endBlock->Option.getOr(fetchState.knownHeight)
|
|
169
|
-
: fetchState.knownHeight
|
|
170
167
|
|
|
171
|
-
let firstEventBlock =
|
|
168
|
+
let firstEventBlock = data.firstEventBlockNumber
|
|
172
169
|
let progress: TuiData.progress = if hasProcessedToEndblock {
|
|
173
170
|
// If the endblock has been reached then set the progress to synced.
|
|
174
171
|
// if there's chains that have no events in the block range start->end,
|
|
@@ -204,19 +201,19 @@ module App = {
|
|
|
204
201
|
(
|
|
205
202
|
{
|
|
206
203
|
progress,
|
|
207
|
-
knownHeight,
|
|
204
|
+
knownHeight: data.knownHeight,
|
|
208
205
|
latestFetchedBlockNumber,
|
|
209
206
|
eventsProcessed: numEventsProcessed,
|
|
210
207
|
chainId: (cs->ChainState.chainConfig).id->Int.toString,
|
|
211
|
-
progressBlock: committedProgressBlockNumber <
|
|
212
|
-
? Some(
|
|
208
|
+
progressBlock: committedProgressBlockNumber < data.startBlock
|
|
209
|
+
? Some(data.startBlock)
|
|
213
210
|
: Some(committedProgressBlockNumber),
|
|
214
211
|
bufferBlock: Some(latestFetchedBlockNumber),
|
|
215
|
-
sourceBlock: Some(
|
|
216
|
-
firstEventBlockNumber:
|
|
217
|
-
startBlock:
|
|
218
|
-
endBlock:
|
|
219
|
-
poweredByHyperSync:
|
|
212
|
+
sourceBlock: Some(cs->ChainState.knownHeight),
|
|
213
|
+
firstEventBlockNumber: firstEventBlock,
|
|
214
|
+
startBlock: data.startBlock,
|
|
215
|
+
endBlock: data.endBlock,
|
|
216
|
+
poweredByHyperSync: data.poweredByHyperSync,
|
|
220
217
|
blockUnit: switch (state->IndexerState.config).ecosystem.name {
|
|
221
218
|
| Svm => "Slot"
|
|
222
219
|
| Evm | Fuel => "Block"
|
package/src/tui/Tui.res.mjs
CHANGED
|
@@ -8,7 +8,6 @@ import * as SyncETA from "./components/SyncETA.res.mjs";
|
|
|
8
8
|
import * as TuiData from "./components/TuiData.res.mjs";
|
|
9
9
|
import * as Messages from "./components/Messages.res.mjs";
|
|
10
10
|
import * as ChainState from "../ChainState.res.mjs";
|
|
11
|
-
import * as FetchState from "../FetchState.res.mjs";
|
|
12
11
|
import * as IndexerState from "../IndexerState.res.mjs";
|
|
13
12
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
14
13
|
import InkBigText from "ink-big-text";
|
|
@@ -208,15 +207,14 @@ function Tui$App(props) {
|
|
|
208
207
|
};
|
|
209
208
|
}, [getState]);
|
|
210
209
|
let chains = Object.values(IndexerState.chainStates(state)).map(cs => {
|
|
211
|
-
let
|
|
212
|
-
let
|
|
210
|
+
let data = ChainState.toChainData(cs);
|
|
211
|
+
let numEventsProcessed = data.numEventsProcessed;
|
|
213
212
|
let committedProgressBlockNumber = ChainState.committedProgressBlockNumber(cs);
|
|
214
|
-
let timestampCaughtUpToHeadOrEndblock =
|
|
213
|
+
let timestampCaughtUpToHeadOrEndblock = data.timestampCaughtUpToHeadOrEndblock;
|
|
215
214
|
let sourceManager = ChainState.sourceManager(cs);
|
|
216
|
-
let latestFetchedBlockNumber =
|
|
215
|
+
let latestFetchedBlockNumber = data.latestFetchedBlockNumber;
|
|
217
216
|
let hasProcessedToEndblock = ChainState.hasProcessedToEndblock(cs);
|
|
218
|
-
let
|
|
219
|
-
let firstEventBlock = fetchState.firstEventBlock;
|
|
217
|
+
let firstEventBlock = data.firstEventBlockNumber;
|
|
220
218
|
let progress = hasProcessedToEndblock ? ({
|
|
221
219
|
TAG: "Synced",
|
|
222
220
|
_0: {
|
|
@@ -259,16 +257,16 @@ function Tui$App(props) {
|
|
|
259
257
|
return {
|
|
260
258
|
chainId: ChainState.chainConfig(cs).id.toString(),
|
|
261
259
|
eventsProcessed: numEventsProcessed,
|
|
262
|
-
progressBlock: committedProgressBlockNumber <
|
|
260
|
+
progressBlock: committedProgressBlockNumber < data.startBlock ? data.startBlock : committedProgressBlockNumber,
|
|
263
261
|
bufferBlock: latestFetchedBlockNumber,
|
|
264
|
-
sourceBlock:
|
|
265
|
-
startBlock:
|
|
266
|
-
endBlock:
|
|
267
|
-
firstEventBlockNumber:
|
|
268
|
-
poweredByHyperSync:
|
|
262
|
+
sourceBlock: ChainState.knownHeight(cs),
|
|
263
|
+
startBlock: data.startBlock,
|
|
264
|
+
endBlock: data.endBlock,
|
|
265
|
+
firstEventBlockNumber: firstEventBlock,
|
|
266
|
+
poweredByHyperSync: data.poweredByHyperSync,
|
|
269
267
|
progress: progress,
|
|
270
268
|
latestFetchedBlockNumber: latestFetchedBlockNumber,
|
|
271
|
-
knownHeight:
|
|
269
|
+
knownHeight: data.currentBlockHeight,
|
|
272
270
|
blockUnit: tmp,
|
|
273
271
|
rateLimitTimeMs: SourceManager.getRateLimitTimeMs(sourceManager),
|
|
274
272
|
isRateLimited: SourceManager.isRateLimited(sourceManager),
|