envio 3.3.0-alpha.1 → 3.3.0-alpha.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/package.json +6 -6
- package/src/Batch.res +0 -6
- package/src/Batch.res.mjs +0 -11
- package/src/BatchProcessing.res +2 -12
- package/src/BatchProcessing.res.mjs +2 -7
- package/src/ChainFetching.res +17 -6
- package/src/ChainFetching.res.mjs +11 -11
- package/src/ChainMetadata.res +1 -11
- package/src/ChainMetadata.res.mjs +1 -10
- package/src/ChainState.res +150 -1
- package/src/ChainState.res.mjs +138 -9
- package/src/ChainState.resi +51 -1
- package/src/Config.res +3 -6
- package/src/Config.res.mjs +2 -3
- package/src/Core.res +7 -0
- package/src/CrossChainState.res +9 -26
- package/src/CrossChainState.res.mjs +7 -16
- package/src/Ecosystem.res +6 -1
- package/src/Envio.res +3 -2
- package/src/EventConfigBuilder.res +19 -5
- package/src/EventConfigBuilder.res.mjs +6 -4
- package/src/EventProcessing.res +26 -0
- package/src/EventProcessing.res.mjs +20 -0
- package/src/Internal.res +43 -4
- package/src/Internal.res.mjs +18 -0
- package/src/Main.res +3 -50
- package/src/Main.res.mjs +2 -23
- package/src/Rollback.res +1 -1
- package/src/Rollback.res.mjs +1 -1
- package/src/SimulateItems.res +3 -0
- package/src/SimulateItems.res.mjs +2 -1
- package/src/sources/Evm.res +52 -38
- package/src/sources/Evm.res.mjs +48 -36
- package/src/sources/Fuel.res +3 -1
- package/src/sources/Fuel.res.mjs +1 -0
- package/src/sources/HyperFuelSource.res +5 -0
- package/src/sources/HyperFuelSource.res.mjs +2 -0
- package/src/sources/HyperSync.res +4 -1
- package/src/sources/HyperSync.res.mjs +5 -3
- package/src/sources/HyperSync.resi +1 -0
- package/src/sources/HyperSyncClient.res +9 -78
- package/src/sources/HyperSyncClient.res.mjs +1 -22
- package/src/sources/HyperSyncSource.res +3 -4
- package/src/sources/HyperSyncSource.res.mjs +2 -1
- package/src/sources/RpcSource.res +7 -2
- package/src/sources/RpcSource.res.mjs +3 -1
- package/src/sources/SimulateSource.res +3 -1
- package/src/sources/SimulateSource.res.mjs +1 -0
- package/src/sources/Source.res +4 -0
- package/src/sources/Svm.res +25 -2
- package/src/sources/Svm.res.mjs +27 -2
- package/src/sources/SvmHyperSyncClient.res +3 -29
- package/src/sources/SvmHyperSyncSource.res +60 -84
- package/src/sources/SvmHyperSyncSource.res.mjs +59 -78
- package/src/sources/TransactionStore.res +111 -0
- package/src/sources/TransactionStore.res.mjs +77 -0
- package/src/tui/Tui.res +13 -16
- package/src/tui/Tui.res.mjs +12 -14
|
@@ -297,20 +297,22 @@ function buildEvmEventConfig(contractName, eventName, sighash, params, isWildcar
|
|
|
297
297
|
paramsRawEventSchema: buildParamsSchema(params),
|
|
298
298
|
simulateParamsSchema: buildSimulateParamsSchema(params),
|
|
299
299
|
startBlock: resolvedStartBlock,
|
|
300
|
+
selectedTransactionFields: match$1[1],
|
|
300
301
|
getEventFiltersOrThrow: match.getEventFiltersOrThrow,
|
|
301
302
|
selectedBlockFields: match$1[0],
|
|
302
|
-
selectedTransactionFields: match$1[1],
|
|
303
303
|
sighash: sighash,
|
|
304
304
|
topicCount: topicCount,
|
|
305
305
|
paramsMetadata: params
|
|
306
306
|
};
|
|
307
307
|
}
|
|
308
308
|
|
|
309
|
-
function buildSvmInstructionEventConfig(contractName, instructionName, programId, discriminator, discriminatorByteLen,
|
|
309
|
+
function buildSvmInstructionEventConfig(contractName, instructionName, programId, discriminator, discriminatorByteLen, includeLogs, transactionFieldsOpt, accountFilters, isInner, isWildcard, handler, contractRegister, accountsOpt, argsOpt, definedTypesOpt, startBlock) {
|
|
310
|
+
let transactionFields = transactionFieldsOpt !== undefined ? transactionFieldsOpt : [];
|
|
310
311
|
let accounts = accountsOpt !== undefined ? accountsOpt : [];
|
|
311
312
|
let args = argsOpt !== undefined ? argsOpt : null;
|
|
312
313
|
let definedTypes = definedTypesOpt !== undefined ? definedTypesOpt : null;
|
|
313
314
|
let paramsSchema = Utils.Schema.coerceToJsonPgType(S$RescriptSchema.json(false));
|
|
315
|
+
let selectedTransactionFields = new Set(transactionFields);
|
|
314
316
|
return {
|
|
315
317
|
id: discriminator !== undefined ? discriminator : "none",
|
|
316
318
|
name: instructionName,
|
|
@@ -323,12 +325,11 @@ function buildSvmInstructionEventConfig(contractName, instructionName, programId
|
|
|
323
325
|
paramsRawEventSchema: paramsSchema,
|
|
324
326
|
simulateParamsSchema: paramsSchema,
|
|
325
327
|
startBlock: startBlock,
|
|
328
|
+
selectedTransactionFields: selectedTransactionFields,
|
|
326
329
|
programId: programId,
|
|
327
330
|
discriminator: discriminator,
|
|
328
331
|
discriminatorByteLen: discriminatorByteLen,
|
|
329
|
-
includeTransaction: includeTransaction,
|
|
330
332
|
includeLogs: includeLogs,
|
|
331
|
-
includeTokenBalances: includeTokenBalances,
|
|
332
333
|
accountFilters: accountFilters,
|
|
333
334
|
isInner: isInner,
|
|
334
335
|
accounts: accounts,
|
|
@@ -392,6 +393,7 @@ function buildFuelEventConfig(contractName, eventName, kind, sighash, rawAbi, is
|
|
|
392
393
|
paramsRawEventSchema: paramsSchema,
|
|
393
394
|
simulateParamsSchema: paramsSchema,
|
|
394
395
|
startBlock: startBlock,
|
|
396
|
+
selectedTransactionFields: new Set(),
|
|
395
397
|
kind: fuelKind
|
|
396
398
|
};
|
|
397
399
|
}
|
package/src/EventProcessing.res
CHANGED
|
@@ -281,6 +281,29 @@ type logPartitionInfo = {
|
|
|
281
281
|
lastItemBlockNumber?: int,
|
|
282
282
|
}
|
|
283
283
|
|
|
284
|
+
// Off the hot path: bulk-materialise the selected transaction fields for the
|
|
285
|
+
// batch's store-backed (HyperSync) items and write them onto the payloads, so
|
|
286
|
+
// handlers read plain objects. A batch can span chains, each with its own store
|
|
287
|
+
// and field mask, so group items by chain before materialising.
|
|
288
|
+
let materializeBatchTransactions = async (batch: Batch.t, ~chainStates: dict<ChainState.t>) => {
|
|
289
|
+
let itemsByChain: dict<array<Internal.item>> = Dict.make()
|
|
290
|
+
batch.items->Array.forEach(item => {
|
|
291
|
+
let chainId = item->Internal.getItemChainId->Int.toString
|
|
292
|
+
switch itemsByChain->Utils.Dict.dangerouslyGetNonOption(chainId) {
|
|
293
|
+
| Some(items) => items->Array.push(item)
|
|
294
|
+
| None => itemsByChain->Dict.set(chainId, [item])
|
|
295
|
+
}
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
let _ = await itemsByChain
|
|
299
|
+
->Dict.toArray
|
|
300
|
+
->Array.map(async ((chainId, items)) => {
|
|
301
|
+
let cs = chainStates->Dict.getUnsafe(chainId)
|
|
302
|
+
await cs->ChainState.materializeBatchItems(~items)
|
|
303
|
+
})
|
|
304
|
+
->Promise.all
|
|
305
|
+
}
|
|
306
|
+
|
|
284
307
|
let processEventBatch = async (
|
|
285
308
|
~batch: Batch.t,
|
|
286
309
|
~indexerState: IndexerState.t,
|
|
@@ -312,6 +335,9 @@ let processEventBatch = async (
|
|
|
312
335
|
let timeRef = Hrtime.makeTimer()
|
|
313
336
|
|
|
314
337
|
if batch.items->Utils.Array.notEmpty {
|
|
338
|
+
// Materialise store-backed transactions onto payloads before any handler
|
|
339
|
+
// (preload or execute) reads them.
|
|
340
|
+
await materializeBatchTransactions(batch, ~chainStates)
|
|
315
341
|
await batch->preloadBatchOrThrow(~loadManager, ~persistence, ~indexerState, ~chains, ~config)
|
|
316
342
|
}
|
|
317
343
|
|
|
@@ -4,6 +4,7 @@ import * as Utils from "./Utils.res.mjs";
|
|
|
4
4
|
import * as Hrtime from "./bindings/Hrtime.res.mjs";
|
|
5
5
|
import * as Logging from "./Logging.res.mjs";
|
|
6
6
|
import * as Writing from "./Writing.res.mjs";
|
|
7
|
+
import * as Internal from "./Internal.res.mjs";
|
|
7
8
|
import * as Ecosystem from "./Ecosystem.res.mjs";
|
|
8
9
|
import * as ChainState from "./ChainState.res.mjs";
|
|
9
10
|
import * as Prometheus from "./Prometheus.res.mjs";
|
|
@@ -180,6 +181,23 @@ function registerProcessEventBatchMetrics(logger, loadDuration, handlerDuration)
|
|
|
180
181
|
Prometheus.ProcessingBatch.registerMetrics(loadDuration, handlerDuration);
|
|
181
182
|
}
|
|
182
183
|
|
|
184
|
+
async function materializeBatchTransactions(batch, chainStates) {
|
|
185
|
+
let itemsByChain = {};
|
|
186
|
+
batch.items.forEach(item => {
|
|
187
|
+
let chainId = Internal.getItemChainId(item).toString();
|
|
188
|
+
let items = itemsByChain[chainId];
|
|
189
|
+
if (items !== undefined) {
|
|
190
|
+
items.push(item);
|
|
191
|
+
} else {
|
|
192
|
+
itemsByChain[chainId] = [item];
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
await Promise.all(Object.entries(itemsByChain).map(async param => {
|
|
196
|
+
let cs = chainStates[param[0]];
|
|
197
|
+
return await ChainState.materializeBatchItems(cs, param[1]);
|
|
198
|
+
}));
|
|
199
|
+
}
|
|
200
|
+
|
|
183
201
|
async function processEventBatch(batch, indexerState, loadManager, persistence, config, chainStates) {
|
|
184
202
|
let totalBatchSize = batch.totalBatchSize;
|
|
185
203
|
let chains = computeChainsState(chainStates);
|
|
@@ -196,6 +214,7 @@ async function processEventBatch(batch, indexerState, loadManager, persistence,
|
|
|
196
214
|
await Writing.awaitCapacity(indexerState);
|
|
197
215
|
let timeRef = Hrtime.makeTimer();
|
|
198
216
|
if (Utils.$$Array.notEmpty(batch.items)) {
|
|
217
|
+
await materializeBatchTransactions(batch, chainStates);
|
|
199
218
|
await preloadBatchOrThrow(batch, loadManager, persistence, config, indexerState, chains);
|
|
200
219
|
}
|
|
201
220
|
let elapsedTimeAfterLoaders = Hrtime.toSecondsFloat(Hrtime.timeSince(timeRef));
|
|
@@ -240,6 +259,7 @@ export {
|
|
|
240
259
|
preloadBatchOrThrow,
|
|
241
260
|
runBatchHandlersOrThrow,
|
|
242
261
|
registerProcessEventBatchMetrics,
|
|
262
|
+
materializeBatchTransactions,
|
|
243
263
|
processEventBatch,
|
|
244
264
|
}
|
|
245
265
|
/* Utils Not a pure module */
|
package/src/Internal.res
CHANGED
|
@@ -136,6 +136,36 @@ let allEvmTransactionFields: array<evmTransactionField> = [
|
|
|
136
136
|
]
|
|
137
137
|
let evmTransactionFieldSchema = S.enum(allEvmTransactionFields)
|
|
138
138
|
|
|
139
|
+
// SVM transaction fields. Order mirrors the Rust `SvmTxField` ordinals (the bit
|
|
140
|
+
// position in the selection mask) and `Svm.res` `transactionFields`.
|
|
141
|
+
type svmTransactionField =
|
|
142
|
+
| @as("transactionIndex") TransactionIndex
|
|
143
|
+
| @as("signatures") Signatures
|
|
144
|
+
| @as("feePayer") FeePayer
|
|
145
|
+
| @as("success") Success
|
|
146
|
+
| @as("err") Err
|
|
147
|
+
| @as("fee") Fee
|
|
148
|
+
| @as("computeUnitsConsumed") ComputeUnitsConsumed
|
|
149
|
+
| @as("accountKeys") AccountKeys
|
|
150
|
+
| @as("recentBlockhash") RecentBlockhash
|
|
151
|
+
| @as("version") Version
|
|
152
|
+
| @as("tokenBalances") TokenBalances
|
|
153
|
+
|
|
154
|
+
let allSvmTransactionFields: array<svmTransactionField> = [
|
|
155
|
+
TransactionIndex,
|
|
156
|
+
Signatures,
|
|
157
|
+
FeePayer,
|
|
158
|
+
Success,
|
|
159
|
+
Err,
|
|
160
|
+
Fee,
|
|
161
|
+
ComputeUnitsConsumed,
|
|
162
|
+
AccountKeys,
|
|
163
|
+
RecentBlockhash,
|
|
164
|
+
Version,
|
|
165
|
+
TokenBalances,
|
|
166
|
+
]
|
|
167
|
+
let svmTransactionFieldSchema = S.enum(allSvmTransactionFields)
|
|
168
|
+
|
|
139
169
|
// Static sets of nullable field names — used by RpcSource and HyperSyncSource to wrap schemas with S.nullable
|
|
140
170
|
let evmNullableBlockFields = Utils.Set.fromArray(
|
|
141
171
|
(
|
|
@@ -277,7 +307,10 @@ type event
|
|
|
277
307
|
// modules, not here, and are distinct per ecosystem.
|
|
278
308
|
type eventPayload
|
|
279
309
|
|
|
280
|
-
|
|
310
|
+
// Generic access to the payload's `transaction`, written at batch prep for
|
|
311
|
+
// store-backed ecosystems (HyperSync) and present inline otherwise.
|
|
312
|
+
@get external getPayloadTransaction: eventPayload => Nullable.t<eventTransaction> = "transaction"
|
|
313
|
+
@set external setPayloadTransaction: (eventPayload, eventTransaction) => unit = "transaction"
|
|
281
314
|
|
|
282
315
|
type genericLoaderArgs<'event, 'context> = {
|
|
283
316
|
event: 'event,
|
|
@@ -382,6 +415,11 @@ type eventConfig = private {
|
|
|
382
415
|
paramsRawEventSchema: S.schema<eventParams>,
|
|
383
416
|
simulateParamsSchema: S.schema<eventParams>,
|
|
384
417
|
startBlock: option<int>,
|
|
418
|
+
// Field names selected for the chain's transaction-store materialisation
|
|
419
|
+
// (camelCase, matching the ecosystem's `transactionFields`). Stored as a
|
|
420
|
+
// string set so the shared mask logic is ecosystem-agnostic; sources recover
|
|
421
|
+
// the typed view where they need it.
|
|
422
|
+
selectedTransactionFields: Utils.Set.t<string>,
|
|
385
423
|
}
|
|
386
424
|
|
|
387
425
|
type fuelEventKind =
|
|
@@ -419,7 +457,6 @@ type evmEventConfig = {
|
|
|
419
457
|
...eventConfig,
|
|
420
458
|
getEventFiltersOrThrow: ChainMap.Chain.t => eventFilters,
|
|
421
459
|
selectedBlockFields: Utils.Set.t<evmBlockField>,
|
|
422
|
-
selectedTransactionFields: Utils.Set.t<evmTransactionField>,
|
|
423
460
|
sighash: string,
|
|
424
461
|
topicCount: int,
|
|
425
462
|
paramsMetadata: array<paramMeta>,
|
|
@@ -456,9 +493,7 @@ type svmInstructionEventConfig = {
|
|
|
456
493
|
`dN` selector at query time and the dispatch-key precomputation in the
|
|
457
494
|
router. */
|
|
458
495
|
discriminatorByteLen: int,
|
|
459
|
-
includeTransaction: bool,
|
|
460
496
|
includeLogs: bool,
|
|
461
|
-
includeTokenBalances: bool,
|
|
462
497
|
/** Disjunctive normal form: outer array is OR of AND-groups, inner array is
|
|
463
498
|
AND across positions. Empty outer array means "no account filter". */
|
|
464
499
|
accountFilters: array<svmAccountFilterGroup>,
|
|
@@ -502,6 +537,9 @@ type eventItem = private {
|
|
|
502
537
|
blockNumber: int,
|
|
503
538
|
blockHash: string,
|
|
504
539
|
logIndex: int,
|
|
540
|
+
// Within-block transaction index — the key into the per-chain transaction
|
|
541
|
+
// store. Unused (0) for ecosystems that carry the transaction inline (Fuel).
|
|
542
|
+
transactionIndex: int,
|
|
505
543
|
payload: eventPayload,
|
|
506
544
|
}
|
|
507
545
|
|
|
@@ -554,6 +592,7 @@ type item =
|
|
|
554
592
|
blockNumber: int,
|
|
555
593
|
blockHash: string,
|
|
556
594
|
logIndex: int,
|
|
595
|
+
transactionIndex: int,
|
|
557
596
|
payload: eventPayload,
|
|
558
597
|
})
|
|
559
598
|
| @as(1) Block({onBlockConfig: onBlockConfig, blockNumber: int, logIndex: int})
|
package/src/Internal.res.mjs
CHANGED
|
@@ -74,6 +74,22 @@ let allEvmTransactionFields = [
|
|
|
74
74
|
|
|
75
75
|
let evmTransactionFieldSchema = S$RescriptSchema.$$enum(allEvmTransactionFields);
|
|
76
76
|
|
|
77
|
+
let allSvmTransactionFields = [
|
|
78
|
+
"transactionIndex",
|
|
79
|
+
"signatures",
|
|
80
|
+
"feePayer",
|
|
81
|
+
"success",
|
|
82
|
+
"err",
|
|
83
|
+
"fee",
|
|
84
|
+
"computeUnitsConsumed",
|
|
85
|
+
"accountKeys",
|
|
86
|
+
"recentBlockhash",
|
|
87
|
+
"version",
|
|
88
|
+
"tokenBalances"
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
let svmTransactionFieldSchema = S$RescriptSchema.$$enum(allSvmTransactionFields);
|
|
92
|
+
|
|
77
93
|
let evmNullableBlockFields = new Set([
|
|
78
94
|
"nonce",
|
|
79
95
|
"difficulty",
|
|
@@ -160,6 +176,8 @@ export {
|
|
|
160
176
|
evmBlockFieldSchema,
|
|
161
177
|
allEvmTransactionFields,
|
|
162
178
|
evmTransactionFieldSchema,
|
|
179
|
+
allSvmTransactionFields,
|
|
180
|
+
svmTransactionFieldSchema,
|
|
163
181
|
evmNullableBlockFields,
|
|
164
182
|
evmNullableTransactionFields,
|
|
165
183
|
dependsOnAddresses,
|
package/src/Main.res
CHANGED
|
@@ -1,19 +1,4 @@
|
|
|
1
|
-
type chainData =
|
|
2
|
-
chainId: float,
|
|
3
|
-
poweredByHyperSync: bool,
|
|
4
|
-
firstEventBlockNumber: option<int>,
|
|
5
|
-
latestProcessedBlock: option<int>,
|
|
6
|
-
timestampCaughtUpToHeadOrEndblock: option<Date.t>,
|
|
7
|
-
numEventsProcessed: float,
|
|
8
|
-
latestFetchedBlockNumber: int,
|
|
9
|
-
// Need this for API backwards compatibility
|
|
10
|
-
@as("currentBlockHeight")
|
|
11
|
-
knownHeight: int,
|
|
12
|
-
numBatchesFetched: int,
|
|
13
|
-
startBlock: int,
|
|
14
|
-
endBlock: option<int>,
|
|
15
|
-
numAddresses: int,
|
|
16
|
-
}
|
|
1
|
+
type chainData = ChainState.chainData
|
|
17
2
|
@tag("status")
|
|
18
3
|
type state =
|
|
19
4
|
| @as("disabled") Disabled({})
|
|
@@ -183,7 +168,7 @@ let buildChainsObject = (~config: Config.t) => {
|
|
|
183
168
|
| Some(state) => {
|
|
184
169
|
let chain = ChainMap.Chain.makeUnsafe(~chainId=chainConfig.id)
|
|
185
170
|
let chainState = state->IndexerState.getChainState(~chain)
|
|
186
|
-
let indexingAddresses =
|
|
171
|
+
let indexingAddresses = chainState->ChainState.indexingAddresses
|
|
187
172
|
|
|
188
173
|
// Collect all addresses for this contract name from indexingAddresses
|
|
189
174
|
let addresses = []
|
|
@@ -780,39 +765,7 @@ let start = async (
|
|
|
780
765
|
| None => Initializing({})
|
|
781
766
|
| Some(state) => {
|
|
782
767
|
let chains =
|
|
783
|
-
state
|
|
784
|
-
->IndexerState.chainStates
|
|
785
|
-
->Dict.valuesToArray
|
|
786
|
-
->Array.map(cs => {
|
|
787
|
-
let fetchState = cs->ChainState.fetchState
|
|
788
|
-
let latestFetchedBlockNumber = Pervasives.max(
|
|
789
|
-
FetchState.bufferBlockNumber(fetchState),
|
|
790
|
-
0,
|
|
791
|
-
)
|
|
792
|
-
let knownHeight =
|
|
793
|
-
cs->ChainState.hasProcessedToEndblock
|
|
794
|
-
? fetchState.endBlock->Option.getOr(fetchState.knownHeight)
|
|
795
|
-
: fetchState.knownHeight
|
|
796
|
-
|
|
797
|
-
{
|
|
798
|
-
chainId: (cs->ChainState.chainConfig).id->Int.toFloat,
|
|
799
|
-
poweredByHyperSync: (
|
|
800
|
-
cs->ChainState.sourceManager->SourceManager.getActiveSource
|
|
801
|
-
).poweredByHyperSync,
|
|
802
|
-
latestFetchedBlockNumber,
|
|
803
|
-
knownHeight,
|
|
804
|
-
numBatchesFetched: 0,
|
|
805
|
-
startBlock: fetchState.startBlock,
|
|
806
|
-
endBlock: fetchState.endBlock,
|
|
807
|
-
firstEventBlockNumber: fetchState.firstEventBlock,
|
|
808
|
-
latestProcessedBlock: cs->ChainState.committedProgressBlockNumber === -1
|
|
809
|
-
? None
|
|
810
|
-
: Some(cs->ChainState.committedProgressBlockNumber),
|
|
811
|
-
timestampCaughtUpToHeadOrEndblock: cs->ChainState.timestampCaughtUpToHeadOrEndblock,
|
|
812
|
-
numEventsProcessed: cs->ChainState.numEventsProcessed,
|
|
813
|
-
numAddresses: fetchState->FetchState.numAddresses,
|
|
814
|
-
}
|
|
815
|
-
})
|
|
768
|
+
state->IndexerState.chainStates->Dict.valuesToArray->Array.map(ChainState.toChainData)
|
|
816
769
|
Active({
|
|
817
770
|
envioVersion,
|
|
818
771
|
chains,
|
package/src/Main.res.mjs
CHANGED
|
@@ -11,7 +11,6 @@ import * as Process from "process";
|
|
|
11
11
|
import * as ChainMap from "./ChainMap.res.mjs";
|
|
12
12
|
import * as PgStorage from "./PgStorage.res.mjs";
|
|
13
13
|
import * as ChainState from "./ChainState.res.mjs";
|
|
14
|
-
import * as FetchState from "./FetchState.res.mjs";
|
|
15
14
|
import * as Prometheus from "./Prometheus.res.mjs";
|
|
16
15
|
import * as IndexerLoop from "./IndexerLoop.res.mjs";
|
|
17
16
|
import * as Persistence from "./Persistence.res.mjs";
|
|
@@ -20,8 +19,6 @@ import Yargs from "yargs/yargs";
|
|
|
20
19
|
import * as IndexerState from "./IndexerState.res.mjs";
|
|
21
20
|
import * as ErrorHandling from "./ErrorHandling.res.mjs";
|
|
22
21
|
import * as HandlerLoader from "./HandlerLoader.res.mjs";
|
|
23
|
-
import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
|
|
24
|
-
import * as SourceManager from "./sources/SourceManager.res.mjs";
|
|
25
22
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
26
23
|
import * as Helpers from "yargs/helpers";
|
|
27
24
|
import * as RollbackCommit from "./RollbackCommit.res.mjs";
|
|
@@ -168,7 +165,7 @@ function buildChainsObject(config) {
|
|
|
168
165
|
if (state !== undefined) {
|
|
169
166
|
let chain = ChainMap.Chain.makeUnsafe(chainConfig.id);
|
|
170
167
|
let chainState = IndexerState.getChainState(Primitive_option.valFromOption(state), chain);
|
|
171
|
-
let indexingAddresses = ChainState.
|
|
168
|
+
let indexingAddresses = ChainState.indexingAddresses(chainState);
|
|
172
169
|
let addresses = [];
|
|
173
170
|
let values = Object.values(indexingAddresses);
|
|
174
171
|
for (let idx = 0, idx_finish = values.length; idx < idx_finish; ++idx) {
|
|
@@ -586,25 +583,7 @@ async function start(persistence, resetOpt, isTestOpt, exitAfterFirstEventBlockO
|
|
|
586
583
|
};
|
|
587
584
|
}
|
|
588
585
|
let state$1 = Primitive_option.valFromOption(state);
|
|
589
|
-
let chains = Object.values(IndexerState.chainStates(state$1)).map(
|
|
590
|
-
let fetchState = ChainState.fetchState(cs);
|
|
591
|
-
let latestFetchedBlockNumber = Primitive_int.max(FetchState.bufferBlockNumber(fetchState), 0);
|
|
592
|
-
let knownHeight = ChainState.hasProcessedToEndblock(cs) ? Stdlib_Option.getOr(fetchState.endBlock, fetchState.knownHeight) : fetchState.knownHeight;
|
|
593
|
-
return {
|
|
594
|
-
chainId: ChainState.chainConfig(cs).id,
|
|
595
|
-
poweredByHyperSync: SourceManager.getActiveSource(ChainState.sourceManager(cs)).poweredByHyperSync,
|
|
596
|
-
firstEventBlockNumber: fetchState.firstEventBlock,
|
|
597
|
-
latestProcessedBlock: ChainState.committedProgressBlockNumber(cs) === -1 ? undefined : ChainState.committedProgressBlockNumber(cs),
|
|
598
|
-
timestampCaughtUpToHeadOrEndblock: ChainState.timestampCaughtUpToHeadOrEndblock(cs),
|
|
599
|
-
numEventsProcessed: ChainState.numEventsProcessed(cs),
|
|
600
|
-
latestFetchedBlockNumber: latestFetchedBlockNumber,
|
|
601
|
-
currentBlockHeight: knownHeight,
|
|
602
|
-
numBatchesFetched: 0,
|
|
603
|
-
startBlock: fetchState.startBlock,
|
|
604
|
-
endBlock: fetchState.endBlock,
|
|
605
|
-
numAddresses: FetchState.numAddresses(fetchState)
|
|
606
|
-
};
|
|
607
|
-
});
|
|
586
|
+
let chains = Object.values(IndexerState.chainStates(state$1)).map(ChainState.toChainData);
|
|
608
587
|
return {
|
|
609
588
|
status: "active",
|
|
610
589
|
envioVersion: envioVersion,
|
package/src/Rollback.res
CHANGED
|
@@ -18,7 +18,7 @@ let getLastKnownValidBlock = async (
|
|
|
18
18
|
->ChainState.reorgDetection
|
|
19
19
|
->ReorgDetection.getThresholdBlockNumbersBelowBlock(
|
|
20
20
|
~blockNumber=reorgBlockNumber,
|
|
21
|
-
~knownHeight=
|
|
21
|
+
~knownHeight=chainState->ChainState.knownHeight,
|
|
22
22
|
)
|
|
23
23
|
|
|
24
24
|
switch scannedBlockNumbers {
|
package/src/Rollback.res.mjs
CHANGED
|
@@ -18,7 +18,7 @@ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
|
18
18
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
19
19
|
|
|
20
20
|
async function getLastKnownValidBlock(chainState, reorgBlockNumber, isRealtime) {
|
|
21
|
-
let scannedBlockNumbers = ReorgDetection.getThresholdBlockNumbersBelowBlock(ChainState.reorgDetection(chainState), reorgBlockNumber, ChainState.
|
|
21
|
+
let scannedBlockNumbers = ReorgDetection.getThresholdBlockNumbersBelowBlock(ChainState.reorgDetection(chainState), reorgBlockNumber, ChainState.knownHeight(chainState));
|
|
22
22
|
if (scannedBlockNumbers.length === 0) {
|
|
23
23
|
return ChainState.getHighestBlockBelowThreshold(chainState);
|
|
24
24
|
}
|
package/src/SimulateItems.res
CHANGED
|
@@ -288,6 +288,9 @@ let parse = (~simulateItems: array<JSON.t>, ~config: Config.t, ~chainConfig: Con
|
|
|
288
288
|
blockNumber,
|
|
289
289
|
blockHash,
|
|
290
290
|
logIndex,
|
|
291
|
+
// Simulate keeps the transaction inline on the payload, so the store
|
|
292
|
+
// key is unused.
|
|
293
|
+
transactionIndex: 0,
|
|
291
294
|
payload: (
|
|
292
295
|
{
|
|
293
296
|
contractName: eventConfig.contractName,
|
|
@@ -241,6 +241,7 @@ function parse(simulateItems, config, chainConfig) {
|
|
|
241
241
|
blockNumber: blockNumber,
|
|
242
242
|
blockHash: match$3[3],
|
|
243
243
|
logIndex: logIndex,
|
|
244
|
+
transactionIndex: 0,
|
|
244
245
|
payload: {
|
|
245
246
|
contractName: eventConfig.contractName,
|
|
246
247
|
eventName: eventConfig.name,
|
|
@@ -248,7 +249,7 @@ function parse(simulateItems, config, chainConfig) {
|
|
|
248
249
|
chainId: chainId,
|
|
249
250
|
srcAddress: srcAddress,
|
|
250
251
|
logIndex: logIndex,
|
|
251
|
-
transaction: transaction,
|
|
252
|
+
transaction: Primitive_option.some(transaction),
|
|
252
253
|
block: match$3[0]
|
|
253
254
|
}
|
|
254
255
|
});
|
package/src/sources/Evm.res
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// EVM's concrete item payload. Erased to `Internal.eventPayload` on the item
|
|
2
|
-
// and recovered here via `toPayload`.
|
|
2
|
+
// and recovered here via `toPayload`. HyperSync omits `transaction` (it lives
|
|
3
|
+
// raw in the per-chain store and is written onto the payload at batch prep);
|
|
4
|
+
// RPC/simulate build it inline.
|
|
3
5
|
type payload = {
|
|
4
6
|
contractName: string,
|
|
5
7
|
eventName: string,
|
|
@@ -7,12 +9,55 @@ type payload = {
|
|
|
7
9
|
chainId: int,
|
|
8
10
|
srcAddress: Address.t,
|
|
9
11
|
logIndex: int,
|
|
10
|
-
transaction
|
|
12
|
+
transaction?: Internal.eventTransaction,
|
|
11
13
|
block: Internal.eventBlock,
|
|
12
14
|
}
|
|
13
15
|
external fromPayload: payload => Internal.eventPayload = "%identity"
|
|
14
16
|
external toPayload: Internal.eventPayload => payload = "%identity"
|
|
15
17
|
|
|
18
|
+
// Ordered transaction field names. The index of each is the field code shared
|
|
19
|
+
// with the Rust store (`EvmTxField`) — keep this order in sync.
|
|
20
|
+
let transactionFields = [
|
|
21
|
+
"transactionIndex",
|
|
22
|
+
"hash",
|
|
23
|
+
"from",
|
|
24
|
+
"to",
|
|
25
|
+
"gas",
|
|
26
|
+
"gasPrice",
|
|
27
|
+
"maxPriorityFeePerGas",
|
|
28
|
+
"maxFeePerGas",
|
|
29
|
+
"cumulativeGasUsed",
|
|
30
|
+
"effectiveGasPrice",
|
|
31
|
+
"gasUsed",
|
|
32
|
+
"input",
|
|
33
|
+
"nonce",
|
|
34
|
+
"value",
|
|
35
|
+
"v",
|
|
36
|
+
"r",
|
|
37
|
+
"s",
|
|
38
|
+
"contractAddress",
|
|
39
|
+
"logsBloom",
|
|
40
|
+
"root",
|
|
41
|
+
"status",
|
|
42
|
+
"yParity",
|
|
43
|
+
"maxFeePerBlobGas",
|
|
44
|
+
"blobVersionedHashes",
|
|
45
|
+
"type",
|
|
46
|
+
"l1Fee",
|
|
47
|
+
"l1GasPrice",
|
|
48
|
+
"l1GasUsed",
|
|
49
|
+
"l1FeeScalar",
|
|
50
|
+
"gasUsedForL1",
|
|
51
|
+
"accessList",
|
|
52
|
+
"authorizationList",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
// Field name → bit index (the code shared with the Rust store), built once.
|
|
56
|
+
let transactionFieldCodes = TransactionStore.fieldCodes(transactionFields)
|
|
57
|
+
|
|
58
|
+
let transactionFieldMask = (eventConfigs: array<Internal.eventConfig>): float =>
|
|
59
|
+
eventConfigs->TransactionStore.mask(~codes=transactionFieldCodes)
|
|
60
|
+
|
|
16
61
|
let cleanUpRawEventFieldsInPlace: JSON.t => unit = %raw(`fields => {
|
|
17
62
|
delete fields.hash
|
|
18
63
|
delete fields.number
|
|
@@ -50,41 +95,7 @@ let make = (~logger: Pino.t): Ecosystem.t => {
|
|
|
50
95
|
"sendRoot",
|
|
51
96
|
"mixHash",
|
|
52
97
|
],
|
|
53
|
-
transactionFields
|
|
54
|
-
"transactionIndex",
|
|
55
|
-
"hash",
|
|
56
|
-
"from",
|
|
57
|
-
"to",
|
|
58
|
-
"gas",
|
|
59
|
-
"gasPrice",
|
|
60
|
-
"maxPriorityFeePerGas",
|
|
61
|
-
"maxFeePerGas",
|
|
62
|
-
"cumulativeGasUsed",
|
|
63
|
-
"effectiveGasPrice",
|
|
64
|
-
"gasUsed",
|
|
65
|
-
"input",
|
|
66
|
-
"nonce",
|
|
67
|
-
"value",
|
|
68
|
-
"v",
|
|
69
|
-
"r",
|
|
70
|
-
"s",
|
|
71
|
-
"contractAddress",
|
|
72
|
-
"logsBloom",
|
|
73
|
-
"root",
|
|
74
|
-
"status",
|
|
75
|
-
"yParity",
|
|
76
|
-
"chainId",
|
|
77
|
-
"maxFeePerBlobGas",
|
|
78
|
-
"blobVersionedHashes",
|
|
79
|
-
"type",
|
|
80
|
-
"l1Fee",
|
|
81
|
-
"l1GasPrice",
|
|
82
|
-
"l1GasUsed",
|
|
83
|
-
"l1FeeScalar",
|
|
84
|
-
"gasUsedForL1",
|
|
85
|
-
"accessList",
|
|
86
|
-
"authorizationList",
|
|
87
|
-
],
|
|
98
|
+
transactionFields,
|
|
88
99
|
blockNumberName: "number",
|
|
89
100
|
blockTimestampName: "timestamp",
|
|
90
101
|
blockHashName: "hash",
|
|
@@ -106,7 +117,10 @@ let make = (~logger: Pino.t): Ecosystem.t => {
|
|
|
106
117
|
s.field("block", S.option(S.object(s2 => s2.field("number", S.unknown))))
|
|
107
118
|
),
|
|
108
119
|
logger,
|
|
109
|
-
|
|
120
|
+
transactionFieldMask,
|
|
121
|
+
// The payload carries `transaction` by batch prep (HyperSync) or inline
|
|
122
|
+
// (RPC/simulate), so the event is the payload as-is.
|
|
123
|
+
toEvent: eventItem => eventItem.payload->(Utils.magic: Internal.eventPayload => Internal.event),
|
|
110
124
|
toEventLogger: eventItem =>
|
|
111
125
|
Logging.createChildFrom(
|
|
112
126
|
~logger,
|
package/src/sources/Evm.res.mjs
CHANGED
|
@@ -3,6 +3,48 @@
|
|
|
3
3
|
import * as Logging from "../Logging.res.mjs";
|
|
4
4
|
import * as RawEvent from "../RawEvent.res.mjs";
|
|
5
5
|
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
6
|
+
import * as TransactionStore from "./TransactionStore.res.mjs";
|
|
7
|
+
|
|
8
|
+
let transactionFields = [
|
|
9
|
+
"transactionIndex",
|
|
10
|
+
"hash",
|
|
11
|
+
"from",
|
|
12
|
+
"to",
|
|
13
|
+
"gas",
|
|
14
|
+
"gasPrice",
|
|
15
|
+
"maxPriorityFeePerGas",
|
|
16
|
+
"maxFeePerGas",
|
|
17
|
+
"cumulativeGasUsed",
|
|
18
|
+
"effectiveGasPrice",
|
|
19
|
+
"gasUsed",
|
|
20
|
+
"input",
|
|
21
|
+
"nonce",
|
|
22
|
+
"value",
|
|
23
|
+
"v",
|
|
24
|
+
"r",
|
|
25
|
+
"s",
|
|
26
|
+
"contractAddress",
|
|
27
|
+
"logsBloom",
|
|
28
|
+
"root",
|
|
29
|
+
"status",
|
|
30
|
+
"yParity",
|
|
31
|
+
"maxFeePerBlobGas",
|
|
32
|
+
"blobVersionedHashes",
|
|
33
|
+
"type",
|
|
34
|
+
"l1Fee",
|
|
35
|
+
"l1GasPrice",
|
|
36
|
+
"l1GasUsed",
|
|
37
|
+
"l1FeeScalar",
|
|
38
|
+
"gasUsedForL1",
|
|
39
|
+
"accessList",
|
|
40
|
+
"authorizationList"
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
let transactionFieldCodes = TransactionStore.fieldCodes(transactionFields);
|
|
44
|
+
|
|
45
|
+
function transactionFieldMask(eventConfigs) {
|
|
46
|
+
return TransactionStore.mask(eventConfigs, transactionFieldCodes);
|
|
47
|
+
}
|
|
6
48
|
|
|
7
49
|
let cleanUpRawEventFieldsInPlace = (fields => {
|
|
8
50
|
delete fields.hash
|
|
@@ -42,41 +84,7 @@ function make(logger) {
|
|
|
42
84
|
"sendRoot",
|
|
43
85
|
"mixHash"
|
|
44
86
|
],
|
|
45
|
-
transactionFields:
|
|
46
|
-
"transactionIndex",
|
|
47
|
-
"hash",
|
|
48
|
-
"from",
|
|
49
|
-
"to",
|
|
50
|
-
"gas",
|
|
51
|
-
"gasPrice",
|
|
52
|
-
"maxPriorityFeePerGas",
|
|
53
|
-
"maxFeePerGas",
|
|
54
|
-
"cumulativeGasUsed",
|
|
55
|
-
"effectiveGasPrice",
|
|
56
|
-
"gasUsed",
|
|
57
|
-
"input",
|
|
58
|
-
"nonce",
|
|
59
|
-
"value",
|
|
60
|
-
"v",
|
|
61
|
-
"r",
|
|
62
|
-
"s",
|
|
63
|
-
"contractAddress",
|
|
64
|
-
"logsBloom",
|
|
65
|
-
"root",
|
|
66
|
-
"status",
|
|
67
|
-
"yParity",
|
|
68
|
-
"chainId",
|
|
69
|
-
"maxFeePerBlobGas",
|
|
70
|
-
"blobVersionedHashes",
|
|
71
|
-
"type",
|
|
72
|
-
"l1Fee",
|
|
73
|
-
"l1GasPrice",
|
|
74
|
-
"l1GasUsed",
|
|
75
|
-
"l1FeeScalar",
|
|
76
|
-
"gasUsedForL1",
|
|
77
|
-
"accessList",
|
|
78
|
-
"authorizationList"
|
|
79
|
-
],
|
|
87
|
+
transactionFields: transactionFields,
|
|
80
88
|
blockNumberName: "number",
|
|
81
89
|
blockTimestampName: "timestamp",
|
|
82
90
|
blockHashName: "hash",
|
|
@@ -86,6 +94,7 @@ function make(logger) {
|
|
|
86
94
|
onEventBlockFilterSchema: S$RescriptSchema.object(s => s.f("block", S$RescriptSchema.option(S$RescriptSchema.object(s2 => s2.f("number", S$RescriptSchema.unknown))))),
|
|
87
95
|
logger: logger,
|
|
88
96
|
toEvent: eventItem => eventItem.payload,
|
|
97
|
+
transactionFieldMask: transactionFieldMask,
|
|
89
98
|
toEventLogger: eventItem => Logging.createChildFrom(logger, {
|
|
90
99
|
contract: eventItem.eventConfig.contractName,
|
|
91
100
|
event: eventItem.eventConfig.name,
|
|
@@ -102,7 +111,10 @@ function make(logger) {
|
|
|
102
111
|
}
|
|
103
112
|
|
|
104
113
|
export {
|
|
114
|
+
transactionFields,
|
|
115
|
+
transactionFieldCodes,
|
|
116
|
+
transactionFieldMask,
|
|
105
117
|
cleanUpRawEventFieldsInPlace,
|
|
106
118
|
make,
|
|
107
119
|
}
|
|
108
|
-
/*
|
|
120
|
+
/* transactionFieldCodes Not a pure module */
|
package/src/sources/Fuel.res
CHANGED
|
@@ -41,7 +41,9 @@ let make = (~logger: Pino.t): Ecosystem.t => {
|
|
|
41
41
|
s.field("block", S.option(S.object(s2 => s2.field("height", S.unknown))))
|
|
42
42
|
),
|
|
43
43
|
logger,
|
|
44
|
-
|
|
44
|
+
// Fuel carries the transaction inline on the payload.
|
|
45
|
+
transactionFieldMask: _ => 0.,
|
|
46
|
+
toEvent: eventItem => eventItem.payload->(Utils.magic: Internal.eventPayload => Internal.event),
|
|
45
47
|
toEventLogger: eventItem =>
|
|
46
48
|
Logging.createChildFrom(
|
|
47
49
|
~logger,
|