envio 3.3.0-alpha.6 → 3.3.0-alpha.8
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/index.d.ts +23 -5
- package/package.json +6 -6
- 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/ChainFetching.res +34 -34
- package/src/ChainFetching.res.mjs +29 -29
- package/src/ChainState.res +328 -165
- package/src/ChainState.res.mjs +205 -100
- package/src/ChainState.resi +16 -7
- package/src/Config.res +55 -27
- package/src/Config.res.mjs +46 -7
- package/src/ContractRegisterContext.res +2 -12
- package/src/ContractRegisterContext.res.mjs +3 -5
- package/src/Core.res +7 -0
- package/src/CrossChainState.res +54 -79
- package/src/CrossChainState.res.mjs +45 -60
- package/src/CrossChainState.resi +1 -1
- package/src/Ecosystem.res +3 -3
- package/src/Ecosystem.res.mjs +3 -3
- package/src/Envio.res +14 -9
- package/src/EventConfigBuilder.res +105 -56
- package/src/EventConfigBuilder.res.mjs +69 -33
- package/src/EventProcessing.res +19 -15
- package/src/EventProcessing.res.mjs +13 -12
- package/src/FetchState.res +383 -182
- package/src/FetchState.res.mjs +260 -264
- package/src/HandlerLoader.res +7 -112
- package/src/HandlerLoader.res.mjs +1 -87
- package/src/HandlerRegister.res +209 -6
- package/src/HandlerRegister.res.mjs +90 -5
- package/src/HandlerRegister.resi +13 -2
- package/src/IndexerState.res +6 -3
- package/src/IndexerState.res.mjs +3 -3
- package/src/IndexerState.resi +1 -1
- package/src/IndexingAddresses.res +10 -7
- package/src/IndexingAddresses.res.mjs +8 -7
- package/src/IndexingAddresses.resi +3 -1
- package/src/Internal.res +82 -36
- package/src/Internal.res.mjs +11 -1
- package/src/Main.res +22 -23
- package/src/Main.res.mjs +15 -17
- package/src/Metrics.res +43 -2
- package/src/Metrics.res.mjs +39 -3
- package/src/Prometheus.res +0 -35
- package/src/Prometheus.res.mjs +33 -68
- package/src/RawEvent.res +7 -2
- package/src/RawEvent.res.mjs +4 -4
- package/src/SimulateItems.res +26 -8
- package/src/SimulateItems.res.mjs +11 -14
- package/src/TestIndexer.res +1 -1
- package/src/TestIndexer.res.mjs +1 -1
- package/src/sources/BlockStore.res +46 -0
- package/src/sources/BlockStore.res.mjs +24 -0
- package/src/sources/EventRouter.res +19 -12
- package/src/sources/EventRouter.res.mjs +7 -5
- package/src/sources/Evm.res +54 -4
- package/src/sources/Evm.res.mjs +43 -4
- package/src/sources/EvmChain.res +14 -18
- package/src/sources/EvmChain.res.mjs +12 -13
- package/src/sources/FieldMask.res +39 -0
- package/src/sources/FieldMask.res.mjs +42 -0
- package/src/sources/Fuel.res +5 -2
- package/src/sources/Fuel.res.mjs +4 -3
- package/src/sources/HyperFuelSource.res +32 -40
- package/src/sources/HyperFuelSource.res.mjs +53 -45
- package/src/sources/HyperSync.res +35 -9
- package/src/sources/HyperSync.res.mjs +52 -35
- package/src/sources/HyperSync.resi +11 -3
- package/src/sources/HyperSyncClient.res +15 -4
- package/src/sources/HyperSyncHeightStream.res +1 -8
- package/src/sources/HyperSyncHeightStream.res.mjs +0 -2
- package/src/sources/HyperSyncSource.res +39 -58
- package/src/sources/HyperSyncSource.res.mjs +44 -44
- package/src/sources/RpcSource.res +114 -92
- package/src/sources/RpcSource.res.mjs +77 -46
- package/src/sources/RpcWebSocketHeightStream.res +0 -5
- package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -2
- package/src/sources/SimulateSource.res +6 -3
- package/src/sources/SimulateSource.res.mjs +13 -5
- package/src/sources/Source.res +25 -5
- package/src/sources/SourceManager.res +66 -3
- package/src/sources/SourceManager.res.mjs +55 -7
- package/src/sources/SourceManager.resi +10 -0
- package/src/sources/Svm.res +15 -10
- package/src/sources/Svm.res.mjs +24 -7
- package/src/sources/SvmHyperSyncClient.res +5 -6
- package/src/sources/SvmHyperSyncSource.res +84 -41
- package/src/sources/SvmHyperSyncSource.res.mjs +90 -43
- package/src/sources/TransactionStore.res +6 -107
- package/src/sources/TransactionStore.res.mjs +5 -86
- package/svm.schema.json +19 -0
|
@@ -4,7 +4,7 @@ type options = {
|
|
|
4
4
|
chain: ChainMap.Chain.t,
|
|
5
5
|
endpointUrl: string,
|
|
6
6
|
apiToken: option<string>,
|
|
7
|
-
|
|
7
|
+
onEventRegistrations: array<Internal.svmOnEventRegistration>,
|
|
8
8
|
clientTimeoutMillis: int,
|
|
9
9
|
}
|
|
10
10
|
|
|
@@ -184,12 +184,12 @@ let parseDecoded = (
|
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
+
// `block` is omitted; it's materialised from the block store at batch prep.
|
|
187
188
|
let toSvmInstruction = (
|
|
188
189
|
instr: SvmHyperSyncClient.ResponseTypes.instruction,
|
|
189
190
|
~programName,
|
|
190
191
|
~instructionName,
|
|
191
192
|
~logs,
|
|
192
|
-
~block,
|
|
193
193
|
): Envio.svmInstruction => {
|
|
194
194
|
programName,
|
|
195
195
|
instructionName,
|
|
@@ -204,14 +204,13 @@ let toSvmInstruction = (
|
|
|
204
204
|
d8: ?instr.d8,
|
|
205
205
|
params: ?(instr.decoded->Option.map(parseDecoded)),
|
|
206
206
|
?logs,
|
|
207
|
-
block,
|
|
208
207
|
}
|
|
209
208
|
|
|
210
209
|
// Probe the discriminator byte-length ordering longest-first. Stops at the
|
|
211
210
|
// first router hit. Falls back to the `_none` key (program-wide handler) when
|
|
212
211
|
// no discriminator-keyed handler matches.
|
|
213
212
|
let probeRouter = (
|
|
214
|
-
router: EventRouter.t<Internal.
|
|
213
|
+
router: EventRouter.t<Internal.svmOnEventRegistration>,
|
|
215
214
|
programId: SvmTypes.Pubkey.t,
|
|
216
215
|
instr: SvmHyperSyncClient.ResponseTypes.instruction,
|
|
217
216
|
byteLengthsDesc: array<int>,
|
|
@@ -268,9 +267,30 @@ let toQueryTxField = (field: Internal.svmTransactionField): option<
|
|
|
268
267
|
| TokenBalances => None
|
|
269
268
|
}
|
|
270
269
|
|
|
271
|
-
|
|
270
|
+
// Map a selected block field to its HyperSync query column. Slot/Blockhash/
|
|
271
|
+
// BlockTime are requested unconditionally (needed for reorg detection and the
|
|
272
|
+
// item's slot/timestamp), so selecting `slot`/`time`/`hash` adds no extra column.
|
|
273
|
+
let toQueryBlockField = (field: Internal.svmBlockField): option<
|
|
274
|
+
SvmHyperSyncClient.QueryTypes.blockField,
|
|
275
|
+
> =>
|
|
276
|
+
switch field {
|
|
277
|
+
| Slot | Time | Hash => None
|
|
278
|
+
| Height => Some(BlockHeight)
|
|
279
|
+
| ParentSlot => Some(ParentSlot)
|
|
280
|
+
| ParentHash => Some(ParentBlockhash)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
let make = (
|
|
284
|
+
{chain, endpointUrl, apiToken, onEventRegistrations, clientTimeoutMillis}: options,
|
|
285
|
+
): t => {
|
|
272
286
|
let name = "SvmHyperSync"
|
|
273
|
-
|
|
287
|
+
|
|
288
|
+
// Definitions drive query/decode building; the registrations drive routing
|
|
289
|
+
// (they carry `isWildcard` and become each decoded item's `onEventRegistration`).
|
|
290
|
+
let eventConfigs =
|
|
291
|
+
onEventRegistrations->Array.map(reg =>
|
|
292
|
+
reg.eventConfig->(Utils.magic: Internal.eventConfig => Internal.svmInstructionEventConfig)
|
|
293
|
+
)
|
|
274
294
|
|
|
275
295
|
// Built once at startup and handed to the client so `get` decodes matching
|
|
276
296
|
// instructions in Rust rather than per-instruction over the napi boundary.
|
|
@@ -285,7 +305,10 @@ let make = ({chain, endpointUrl, apiToken, eventConfigs, clientTimeoutMillis}: o
|
|
|
285
305
|
},
|
|
286
306
|
)
|
|
287
307
|
|
|
288
|
-
let (eventRouter, programOrderings) = EventRouter.fromSvmEventConfigsOrThrow(
|
|
308
|
+
let (eventRouter, programOrderings) = EventRouter.fromSvmEventConfigsOrThrow(
|
|
309
|
+
onEventRegistrations,
|
|
310
|
+
~chain,
|
|
311
|
+
)
|
|
289
312
|
|
|
290
313
|
// programId.toString -> sorted-desc byte lengths
|
|
291
314
|
let orderingByProgram = Dict.make()
|
|
@@ -332,6 +355,24 @@ let make = ({chain, endpointUrl, apiToken, eventConfigs, clientTimeoutMillis}: o
|
|
|
332
355
|
}
|
|
333
356
|
)
|
|
334
357
|
|
|
358
|
+
// Union of selected block fields across the chain's events. `slot`/`time`/
|
|
359
|
+
// `hash` are always fetched (as Slot/BlockTime/Blockhash); the rest are added
|
|
360
|
+
// only when an instruction selected them.
|
|
361
|
+
let blockQueryFields = {
|
|
362
|
+
let fields: array<SvmHyperSyncClient.QueryTypes.blockField> = [Slot, Blockhash, BlockTime]
|
|
363
|
+
let selected = Utils.Set.make()
|
|
364
|
+
eventConfigs->Array.forEach(cfg =>
|
|
365
|
+
cfg.selectedBlockFields->Utils.Set.forEach(field => selected->Utils.Set.add(field)->ignore)
|
|
366
|
+
)
|
|
367
|
+
selected->Utils.Set.forEach(field =>
|
|
368
|
+
switch field->toQueryBlockField {
|
|
369
|
+
| Some(queryField) => fields->Array.push(queryField)->ignore
|
|
370
|
+
| None => ()
|
|
371
|
+
}
|
|
372
|
+
)
|
|
373
|
+
fields
|
|
374
|
+
}
|
|
375
|
+
|
|
335
376
|
let getItemsOrThrow = async (
|
|
336
377
|
~fromBlock,
|
|
337
378
|
~toBlock,
|
|
@@ -340,6 +381,7 @@ let make = ({chain, endpointUrl, apiToken, eventConfigs, clientTimeoutMillis}: o
|
|
|
340
381
|
~knownHeight,
|
|
341
382
|
~partitionId as _,
|
|
342
383
|
~selection as _,
|
|
384
|
+
~itemsTarget,
|
|
343
385
|
~retry,
|
|
344
386
|
~logger,
|
|
345
387
|
) => {
|
|
@@ -352,7 +394,7 @@ let make = ({chain, endpointUrl, apiToken, eventConfigs, clientTimeoutMillis}: o
|
|
|
352
394
|
// field list returns no rows (instructions and blocks are exempt), so each
|
|
353
395
|
// opted-into table needs its columns spelled out here.
|
|
354
396
|
let fields: SvmHyperSyncClient.QueryTypes.fieldSelection = {
|
|
355
|
-
block:
|
|
397
|
+
block: blockQueryFields,
|
|
356
398
|
transaction: ?(needsTransactions ? Some(txQueryFields) : None),
|
|
357
399
|
log: ?(needsLogs ? Some([Slot, TransactionIndex, InstructionAddress, Kind, Message]) : None),
|
|
358
400
|
tokenBalance: ?(
|
|
@@ -368,11 +410,10 @@ let make = ({chain, endpointUrl, apiToken, eventConfigs, clientTimeoutMillis}: o
|
|
|
368
410
|
toSlot: ?(toBlock->Option.map(toBlock => toBlock + 1)),
|
|
369
411
|
instructions: instructionSelections,
|
|
370
412
|
fields,
|
|
413
|
+
maxNumInstructions: itemsTarget,
|
|
371
414
|
}
|
|
372
415
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
let (resp, transactionStore) = try await client.get(~query) catch {
|
|
416
|
+
let (resp, transactionStore, blockStore) = try await client.get(~query) catch {
|
|
376
417
|
| exn =>
|
|
377
418
|
throw(
|
|
378
419
|
Source.GetItemsError(
|
|
@@ -391,11 +432,13 @@ let make = ({chain, endpointUrl, apiToken, eventConfigs, clientTimeoutMillis}: o
|
|
|
391
432
|
)
|
|
392
433
|
}
|
|
393
434
|
let pageFetchTime = pageFetchRef->Performance.secondsSince
|
|
435
|
+
let requestStats = [{Source.method: "getInstructions", seconds: pageFetchTime}]
|
|
394
436
|
|
|
395
437
|
let parsingRef = Performance.now()
|
|
396
438
|
|
|
397
|
-
// Per-slot
|
|
398
|
-
// without a block row (rare;
|
|
439
|
+
// Per-slot blockTime lookup from the response's `blocks` table, for the
|
|
440
|
+
// batch's `latestFetchedBlockTimestamp`. Slots without a block row (rare;
|
|
441
|
+
// usually skipped slots) fall back to `None`.
|
|
399
442
|
let blockTimeBySlot = Dict.make()
|
|
400
443
|
resp.data.blocks->Array.forEach(b => {
|
|
401
444
|
switch b.blockTime {
|
|
@@ -445,7 +488,11 @@ let make = ({chain, endpointUrl, apiToken, eventConfigs, clientTimeoutMillis}: o
|
|
|
445
488
|
|
|
446
489
|
switch maybeConfig {
|
|
447
490
|
| None => ()
|
|
448
|
-
| Some(
|
|
491
|
+
| Some(onEventRegistration) =>
|
|
492
|
+
let eventConfig =
|
|
493
|
+
onEventRegistration.eventConfig->(
|
|
494
|
+
Utils.magic: Internal.eventConfig => Internal.svmInstructionEventConfig
|
|
495
|
+
)
|
|
449
496
|
let logKey =
|
|
450
497
|
instr.slot->Int.toString ++
|
|
451
498
|
":" ++
|
|
@@ -464,28 +511,19 @@ let make = ({chain, endpointUrl, apiToken, eventConfigs, clientTimeoutMillis}: o
|
|
|
464
511
|
)
|
|
465
512
|
)
|
|
466
513
|
|
|
467
|
-
let slotKey = instr.slot->Int.toString
|
|
468
|
-
let blockTime = blockTimeBySlot->Utils.Dict.dangerouslyGetNonOption(slotKey)
|
|
469
514
|
let payload = toSvmInstruction(
|
|
470
515
|
instr,
|
|
471
516
|
~programName=eventConfig.contractName,
|
|
472
517
|
~instructionName=eventConfig.name,
|
|
473
518
|
~logs=eventConfig.includeLogs ? maybeLogs : None,
|
|
474
|
-
~block={
|
|
475
|
-
slot: instr.slot,
|
|
476
|
-
time: blockTime->Option.getOr(0),
|
|
477
|
-
hash: "",
|
|
478
|
-
},
|
|
479
519
|
)
|
|
480
520
|
|
|
481
521
|
parsedQueueItems
|
|
482
522
|
->Array.push(
|
|
483
523
|
Internal.Event({
|
|
484
|
-
|
|
485
|
-
timestamp: blockTime->Option.getOr(0),
|
|
524
|
+
onEventRegistration,
|
|
486
525
|
chain,
|
|
487
526
|
blockNumber: instr.slot,
|
|
488
|
-
blockHash: "",
|
|
489
527
|
logIndex: synthLogIndex(instr),
|
|
490
528
|
// The parent transaction is materialised from the store at batch prep.
|
|
491
529
|
transactionIndex: instr.transactionIndex,
|
|
@@ -520,11 +558,14 @@ let make = ({chain, endpointUrl, apiToken, eventConfigs, clientTimeoutMillis}: o
|
|
|
520
558
|
parsedQueueItems,
|
|
521
559
|
// Raw transactions kept in Rust; materialised (selected fields) at batch prep.
|
|
522
560
|
transactionStore: Some(transactionStore),
|
|
561
|
+
// Raw blocks kept in Rust; materialised onto the payload at batch prep.
|
|
562
|
+
blockStore: Some(blockStore),
|
|
523
563
|
latestFetchedBlockNumber: highestSlot,
|
|
524
564
|
stats: {totalTimeElapsed, parsingTimeElapsed, pageFetchTime},
|
|
525
565
|
knownHeight,
|
|
526
566
|
blockHashes,
|
|
527
567
|
fromBlockQueried: fromBlock,
|
|
568
|
+
requestStats,
|
|
528
569
|
}
|
|
529
570
|
}
|
|
530
571
|
|
|
@@ -533,6 +574,7 @@ let make = ({chain, endpointUrl, apiToken, eventConfigs, clientTimeoutMillis}: o
|
|
|
533
574
|
// wire, so we request `maxSlot + 1`; the caller filters to the exact slots.
|
|
534
575
|
let queryBlockDataRange = async (~fromSlot, ~toSlot) => {
|
|
535
576
|
let blockDatas = []
|
|
577
|
+
let requestStats = []
|
|
536
578
|
let fromRef = ref(fromSlot)
|
|
537
579
|
let keepGoing = ref(true)
|
|
538
580
|
while keepGoing.contents {
|
|
@@ -543,9 +585,12 @@ let make = ({chain, endpointUrl, apiToken, eventConfigs, clientTimeoutMillis}: o
|
|
|
543
585
|
fields: {block: [Slot, Blockhash, BlockTime]},
|
|
544
586
|
maxNumBlocks: 1000,
|
|
545
587
|
}
|
|
546
|
-
|
|
547
|
-
// Block-only query; the store
|
|
548
|
-
let (resp, _) = await client.get(~query)
|
|
588
|
+
let timerRef = Performance.now()
|
|
589
|
+
// Block-only query; the store pages are empty.
|
|
590
|
+
let (resp, _, _) = await client.get(~query)
|
|
591
|
+
requestStats
|
|
592
|
+
->Array.push({Source.method: "getBlockHashes", seconds: timerRef->Performance.secondsSince})
|
|
593
|
+
->ignore
|
|
549
594
|
resp.data.blocks->Array.forEach(b =>
|
|
550
595
|
blockDatas
|
|
551
596
|
->Array.push({
|
|
@@ -564,12 +609,12 @@ let make = ({chain, endpointUrl, apiToken, eventConfigs, clientTimeoutMillis}: o
|
|
|
564
609
|
fromRef := resp.nextSlot
|
|
565
610
|
}
|
|
566
611
|
}
|
|
567
|
-
blockDatas
|
|
612
|
+
(blockDatas, requestStats)
|
|
568
613
|
}
|
|
569
614
|
|
|
570
615
|
let getBlockHashes = async (~blockNumbers, ~logger as _) =>
|
|
571
616
|
switch blockNumbers->Array.get(0) {
|
|
572
|
-
| None => Ok([])
|
|
617
|
+
| None => {Source.result: Ok([]), requestStats: []}
|
|
573
618
|
| Some(firstSlot) =>
|
|
574
619
|
try {
|
|
575
620
|
let minSlot = ref(firstSlot)
|
|
@@ -584,14 +629,19 @@ let make = ({chain, endpointUrl, apiToken, eventConfigs, clientTimeoutMillis}: o
|
|
|
584
629
|
}
|
|
585
630
|
requested->Utils.Set.add(slot)->ignore
|
|
586
631
|
})
|
|
587
|
-
let blockDatas = await queryBlockDataRange(
|
|
632
|
+
let (blockDatas, requestStats) = await queryBlockDataRange(
|
|
588
633
|
~fromSlot=minSlot.contents,
|
|
589
634
|
~toSlot=maxSlot.contents,
|
|
590
635
|
)
|
|
591
636
|
// Keep one entry per requested slot; drop duplicates and unrelated slots.
|
|
592
|
-
|
|
637
|
+
{
|
|
638
|
+
Source.result: Ok(
|
|
639
|
+
blockDatas->Array.filter(data => requested->Utils.Set.delete(data.blockNumber)),
|
|
640
|
+
),
|
|
641
|
+
requestStats,
|
|
642
|
+
}
|
|
593
643
|
} catch {
|
|
594
|
-
| exn => Error(exn)
|
|
644
|
+
| exn => {Source.result: Error(exn), requestStats: []}
|
|
595
645
|
}
|
|
596
646
|
}
|
|
597
647
|
|
|
@@ -604,16 +654,9 @@ let make = ({chain, endpointUrl, apiToken, eventConfigs, clientTimeoutMillis}: o
|
|
|
604
654
|
getBlockHashes,
|
|
605
655
|
getHeightOrThrow: async () => {
|
|
606
656
|
let timer = Performance.now()
|
|
607
|
-
let
|
|
657
|
+
let height = await client.getHeight()
|
|
608
658
|
let seconds = timer->Performance.secondsSince
|
|
609
|
-
|
|
610
|
-
Prometheus.SourceRequestCount.addSeconds(
|
|
611
|
-
~sourceName=name,
|
|
612
|
-
~chainId,
|
|
613
|
-
~method="getHeight",
|
|
614
|
-
~seconds,
|
|
615
|
-
)
|
|
616
|
-
h
|
|
659
|
+
{height, requestStats: [{method: "getHeight", seconds}]}
|
|
617
660
|
},
|
|
618
661
|
getItemsOrThrow,
|
|
619
662
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Source from "./Source.res.mjs";
|
|
4
|
-
import * as Prometheus from "../Prometheus.res.mjs";
|
|
5
4
|
import * as EventRouter from "./EventRouter.res.mjs";
|
|
6
5
|
import * as Performance from "../bindings/Performance.res.mjs";
|
|
7
6
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
@@ -166,7 +165,7 @@ function parseDecoded(d) {
|
|
|
166
165
|
};
|
|
167
166
|
}
|
|
168
167
|
|
|
169
|
-
function toSvmInstruction(instr, programName, instructionName, logs
|
|
168
|
+
function toSvmInstruction(instr, programName, instructionName, logs) {
|
|
170
169
|
return {
|
|
171
170
|
programName: programName,
|
|
172
171
|
instructionName: instructionName,
|
|
@@ -180,8 +179,7 @@ function toSvmInstruction(instr, programName, instructionName, logs, block) {
|
|
|
180
179
|
d4: instr.d4,
|
|
181
180
|
d8: instr.d8,
|
|
182
181
|
params: Stdlib_Option.map(instr.decoded, parseDecoded),
|
|
183
|
-
logs: logs
|
|
184
|
-
block: block
|
|
182
|
+
logs: logs
|
|
185
183
|
};
|
|
186
184
|
}
|
|
187
185
|
|
|
@@ -248,13 +246,26 @@ function toQueryTxField(field) {
|
|
|
248
246
|
}
|
|
249
247
|
}
|
|
250
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
|
+
|
|
251
262
|
function make(param) {
|
|
252
|
-
let
|
|
263
|
+
let onEventRegistrations = param.onEventRegistrations;
|
|
253
264
|
let chain = param.chain;
|
|
254
|
-
let
|
|
265
|
+
let eventConfigs = onEventRegistrations.map(reg => reg.eventConfig);
|
|
255
266
|
let programSchemas = buildProgramSchemas(eventConfigs);
|
|
256
267
|
let client = SvmHyperSyncClient.make(param.endpointUrl, param.apiToken, param.clientTimeoutMillis, undefined, undefined, undefined, programSchemas.length !== 0 ? programSchemas : undefined);
|
|
257
|
-
let match = EventRouter.fromSvmEventConfigsOrThrow(
|
|
268
|
+
let match = EventRouter.fromSvmEventConfigsOrThrow(onEventRegistrations, chain);
|
|
258
269
|
let eventRouter = match[0];
|
|
259
270
|
let orderingByProgram = {};
|
|
260
271
|
match[1].forEach(o => {
|
|
@@ -288,15 +299,29 @@ function make(param) {
|
|
|
288
299
|
return true;
|
|
289
300
|
}
|
|
290
301
|
});
|
|
291
|
-
let
|
|
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) => {
|
|
292
321
|
let totalTimeRef = Performance.now();
|
|
293
322
|
let pageFetchRef = Performance.now();
|
|
294
323
|
let instructionSelections = buildInstructionSelections(eventConfigs);
|
|
295
|
-
let fields_block =
|
|
296
|
-
"slot",
|
|
297
|
-
"blockhash",
|
|
298
|
-
"block_time"
|
|
299
|
-
];
|
|
324
|
+
let fields_block = fields$1;
|
|
300
325
|
let fields_transaction = needsTransactions ? fields : undefined;
|
|
301
326
|
let fields_log = needsLogs ? [
|
|
302
327
|
"slot",
|
|
@@ -314,7 +339,7 @@ function make(param) {
|
|
|
314
339
|
"pre_amount",
|
|
315
340
|
"post_amount"
|
|
316
341
|
] : undefined;
|
|
317
|
-
let fields$
|
|
342
|
+
let fields$2 = {
|
|
318
343
|
block: fields_block,
|
|
319
344
|
transaction: fields_transaction,
|
|
320
345
|
log: fields_log,
|
|
@@ -322,14 +347,15 @@ function make(param) {
|
|
|
322
347
|
};
|
|
323
348
|
let query_toSlot = Stdlib_Option.map(toBlock, toBlock => toBlock + 1 | 0);
|
|
324
349
|
let query_instructions = instructionSelections;
|
|
325
|
-
let query_fields = fields$
|
|
350
|
+
let query_fields = fields$2;
|
|
351
|
+
let query_maxNumInstructions = itemsTarget;
|
|
326
352
|
let query = {
|
|
327
353
|
fromSlot: fromBlock,
|
|
328
354
|
toSlot: query_toSlot,
|
|
329
355
|
instructions: query_instructions,
|
|
330
|
-
fields: query_fields
|
|
356
|
+
fields: query_fields,
|
|
357
|
+
maxNumInstructions: query_maxNumInstructions
|
|
331
358
|
};
|
|
332
|
-
Prometheus.SourceRequestCount.increment(name, chain, "getInstructions");
|
|
333
359
|
let match;
|
|
334
360
|
try {
|
|
335
361
|
match = await client.get(query);
|
|
@@ -352,6 +378,10 @@ function make(param) {
|
|
|
352
378
|
}
|
|
353
379
|
let resp = match[0];
|
|
354
380
|
let pageFetchTime = Performance.secondsSince(pageFetchRef);
|
|
381
|
+
let requestStats = [{
|
|
382
|
+
method: "getInstructions",
|
|
383
|
+
seconds: pageFetchTime
|
|
384
|
+
}];
|
|
355
385
|
let parsingRef = Performance.now();
|
|
356
386
|
let blockTimeBySlot = {};
|
|
357
387
|
resp.data.blocks.forEach(b => {
|
|
@@ -386,25 +416,18 @@ function make(param) {
|
|
|
386
416
|
let contractAddress = instr.programId;
|
|
387
417
|
let maybeConfig = probeRouter(eventRouter, programId, instr, byteLengths, contractAddress, contractNameByAddress);
|
|
388
418
|
if (maybeConfig !== undefined) {
|
|
419
|
+
let eventConfig = maybeConfig.eventConfig;
|
|
389
420
|
let logKey = instr.slot.toString() + ":" + instr.transactionIndex.toString() + ":" + serializeInstructionAddress(instr.instructionAddress);
|
|
390
421
|
let maybeLogs = Stdlib_Option.map(logsByKey[logKey], logs => logs.map(log => ({
|
|
391
422
|
kind: Stdlib_Option.getOr(log.kind, ""),
|
|
392
423
|
message: Stdlib_Option.getOr(log.message, "")
|
|
393
424
|
})));
|
|
394
|
-
let
|
|
395
|
-
let blockTime = blockTimeBySlot[slotKey];
|
|
396
|
-
let payload = toSvmInstruction(instr, maybeConfig.contractName, maybeConfig.name, maybeConfig.includeLogs ? maybeLogs : undefined, {
|
|
397
|
-
slot: instr.slot,
|
|
398
|
-
time: Stdlib_Option.getOr(blockTime, 0),
|
|
399
|
-
hash: ""
|
|
400
|
-
});
|
|
425
|
+
let payload = toSvmInstruction(instr, eventConfig.contractName, eventConfig.name, eventConfig.includeLogs ? maybeLogs : undefined);
|
|
401
426
|
parsedQueueItems.push({
|
|
402
427
|
kind: 0,
|
|
403
|
-
|
|
404
|
-
timestamp: Stdlib_Option.getOr(blockTime, 0),
|
|
428
|
+
onEventRegistration: maybeConfig,
|
|
405
429
|
chain: chain,
|
|
406
430
|
blockNumber: instr.slot,
|
|
407
|
-
blockHash: "",
|
|
408
431
|
logIndex: synthLogIndex(instr),
|
|
409
432
|
transactionIndex: instr.transactionIndex,
|
|
410
433
|
payload: payload
|
|
@@ -424,6 +447,7 @@ function make(param) {
|
|
|
424
447
|
blockHashes: blockHashes,
|
|
425
448
|
parsedQueueItems: parsedQueueItems,
|
|
426
449
|
transactionStore: Primitive_option.some(match[1]),
|
|
450
|
+
blockStore: Primitive_option.some(match[2]),
|
|
427
451
|
fromBlockQueried: fromBlock,
|
|
428
452
|
latestFetchedBlockNumber: highestSlot,
|
|
429
453
|
latestFetchedBlockTimestamp: latestBlockTime,
|
|
@@ -431,11 +455,13 @@ function make(param) {
|
|
|
431
455
|
"total time elapsed (s)": totalTimeElapsed,
|
|
432
456
|
"parsing time (s)": parsingTimeElapsed,
|
|
433
457
|
"page fetch time (s)": pageFetchTime
|
|
434
|
-
}
|
|
458
|
+
},
|
|
459
|
+
requestStats: requestStats
|
|
435
460
|
};
|
|
436
461
|
};
|
|
437
462
|
let queryBlockDataRange = async (fromSlot, toSlot) => {
|
|
438
463
|
let blockDatas = [];
|
|
464
|
+
let requestStats = [];
|
|
439
465
|
let fromRef = fromSlot;
|
|
440
466
|
let keepGoing = true;
|
|
441
467
|
while (keepGoing) {
|
|
@@ -456,9 +482,13 @@ function make(param) {
|
|
|
456
482
|
fields: query_fields,
|
|
457
483
|
maxNumBlocks: query_maxNumBlocks
|
|
458
484
|
};
|
|
459
|
-
|
|
485
|
+
let timerRef = Performance.now();
|
|
460
486
|
let match = await client.get(query);
|
|
461
487
|
let resp = match[0];
|
|
488
|
+
requestStats.push({
|
|
489
|
+
method: "getBlockHashes",
|
|
490
|
+
seconds: Performance.secondsSince(timerRef)
|
|
491
|
+
});
|
|
462
492
|
resp.data.blocks.forEach(b => {
|
|
463
493
|
blockDatas.push({
|
|
464
494
|
blockHash: b.blockhash,
|
|
@@ -472,14 +502,20 @@ function make(param) {
|
|
|
472
502
|
fromRef = resp.nextSlot;
|
|
473
503
|
}
|
|
474
504
|
};
|
|
475
|
-
return
|
|
505
|
+
return [
|
|
506
|
+
blockDatas,
|
|
507
|
+
requestStats
|
|
508
|
+
];
|
|
476
509
|
};
|
|
477
510
|
let getBlockHashes = async (blockNumbers, param) => {
|
|
478
511
|
let firstSlot = blockNumbers[0];
|
|
479
512
|
if (firstSlot === undefined) {
|
|
480
513
|
return {
|
|
481
|
-
|
|
482
|
-
|
|
514
|
+
result: {
|
|
515
|
+
TAG: "Ok",
|
|
516
|
+
_0: []
|
|
517
|
+
},
|
|
518
|
+
requestStats: []
|
|
483
519
|
};
|
|
484
520
|
}
|
|
485
521
|
try {
|
|
@@ -499,21 +535,27 @@ function make(param) {
|
|
|
499
535
|
}
|
|
500
536
|
requested.add(slot);
|
|
501
537
|
});
|
|
502
|
-
let
|
|
538
|
+
let match = await queryBlockDataRange(minSlot.contents, maxSlot.contents);
|
|
503
539
|
return {
|
|
504
|
-
|
|
505
|
-
|
|
540
|
+
result: {
|
|
541
|
+
TAG: "Ok",
|
|
542
|
+
_0: match[0].filter(data => requested.delete(data.blockNumber))
|
|
543
|
+
},
|
|
544
|
+
requestStats: match[1]
|
|
506
545
|
};
|
|
507
546
|
} catch (raw_exn) {
|
|
508
547
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
509
548
|
return {
|
|
510
|
-
|
|
511
|
-
|
|
549
|
+
result: {
|
|
550
|
+
TAG: "Error",
|
|
551
|
+
_0: exn
|
|
552
|
+
},
|
|
553
|
+
requestStats: []
|
|
512
554
|
};
|
|
513
555
|
}
|
|
514
556
|
};
|
|
515
557
|
return {
|
|
516
|
-
name:
|
|
558
|
+
name: "SvmHyperSync",
|
|
517
559
|
sourceFor: "Sync",
|
|
518
560
|
chain: chain,
|
|
519
561
|
poweredByHyperSync: true,
|
|
@@ -521,11 +563,15 @@ function make(param) {
|
|
|
521
563
|
getBlockHashes: getBlockHashes,
|
|
522
564
|
getHeightOrThrow: async () => {
|
|
523
565
|
let timer = Performance.now();
|
|
524
|
-
let
|
|
566
|
+
let height = await client.getHeight();
|
|
525
567
|
let seconds = Performance.secondsSince(timer);
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
568
|
+
return {
|
|
569
|
+
height: height,
|
|
570
|
+
requestStats: [{
|
|
571
|
+
method: "getHeight",
|
|
572
|
+
seconds: seconds
|
|
573
|
+
}]
|
|
574
|
+
};
|
|
529
575
|
},
|
|
530
576
|
getItemsOrThrow: getItemsOrThrow
|
|
531
577
|
};
|
|
@@ -540,6 +586,7 @@ export {
|
|
|
540
586
|
toSvmInstruction,
|
|
541
587
|
probeRouter,
|
|
542
588
|
toQueryTxField,
|
|
589
|
+
toQueryBlockField,
|
|
543
590
|
make,
|
|
544
591
|
}
|
|
545
|
-
/*
|
|
592
|
+
/* EventRouter Not a pure module */
|