envio 3.3.0-alpha.1 → 3.3.0-alpha.3
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 -21
- 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 +42 -6
- package/src/ChainFetching.res.mjs +30 -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 +24 -26
- package/src/CrossChainState.res.mjs +19 -16
- package/src/Ecosystem.res +6 -3
- package/src/Envio.res +3 -2
- package/src/EventConfigBuilder.res +61 -23
- package/src/EventConfigBuilder.res.mjs +27 -13
- package/src/EventProcessing.res +63 -21
- package/src/EventProcessing.res.mjs +47 -22
- package/src/FetchState.res +53 -43
- package/src/FetchState.res.mjs +71 -54
- package/src/HandlerLoader.res +10 -1
- package/src/HandlerLoader.res.mjs +15 -8
- package/src/Internal.res +46 -7
- package/src/Internal.res.mjs +19 -1
- package/src/LoadLayer.res +5 -5
- package/src/LoadLayer.res.mjs +6 -6
- package/src/Main.res +3 -50
- package/src/Main.res.mjs +2 -23
- package/src/PgStorage.res +4 -4
- package/src/PgStorage.res.mjs +5 -5
- package/src/Prometheus.res +10 -10
- package/src/Prometheus.res.mjs +9 -9
- package/src/PruneStaleHistory.res +2 -2
- package/src/PruneStaleHistory.res.mjs +3 -3
- package/src/Rollback.res +3 -3
- package/src/Rollback.res.mjs +4 -4
- package/src/SimulateItems.res +80 -15
- package/src/SimulateItems.res.mjs +65 -21
- package/src/TestIndexer.res +48 -36
- package/src/TestIndexer.res.mjs +35 -28
- package/src/bindings/Performance.res +7 -0
- package/src/bindings/Performance.res.mjs +21 -0
- package/src/bindings/Performance.resi +7 -0
- package/src/sources/EventRouter.res +17 -21
- package/src/sources/EventRouter.res.mjs +6 -9
- package/src/sources/Evm.res +47 -67
- package/src/sources/Evm.res.mjs +42 -65
- package/src/sources/Fuel.res +3 -3
- package/src/sources/Fuel.res.mjs +1 -6
- package/src/sources/HyperFuelSource.res +15 -11
- package/src/sources/HyperFuelSource.res.mjs +13 -11
- package/src/sources/HyperSync.res +7 -1
- package/src/sources/HyperSync.res.mjs +6 -3
- package/src/sources/HyperSync.resi +2 -0
- package/src/sources/HyperSyncClient.res +14 -79
- package/src/sources/HyperSyncClient.res.mjs +1 -22
- package/src/sources/HyperSyncSource.res +44 -27
- package/src/sources/HyperSyncSource.res.mjs +32 -27
- package/src/sources/RpcSource.res +14 -10
- package/src/sources/RpcSource.res.mjs +11 -9
- package/src/sources/SimulateSource.res +4 -2
- package/src/sources/SimulateSource.res.mjs +1 -0
- package/src/sources/Source.res +5 -1
- package/src/sources/SourceManager.res +17 -16
- package/src/sources/SourceManager.res.mjs +10 -15
- package/src/sources/Svm.res +23 -6
- package/src/sources/Svm.res.mjs +24 -6
- package/src/sources/SvmHyperSyncClient.res +3 -29
- package/src/sources/SvmHyperSyncSource.res +78 -96
- package/src/sources/SvmHyperSyncSource.res.mjs +79 -91
- package/src/sources/TransactionStore.res +128 -0
- package/src/sources/TransactionStore.res.mjs +97 -0
- package/src/tui/Tui.res +13 -16
- package/src/tui/Tui.res.mjs +12 -14
- package/svm.schema.json +30 -37
- package/src/bindings/Hrtime.res +0 -58
- package/src/bindings/Hrtime.res.mjs +0 -90
- package/src/bindings/Hrtime.resi +0 -30
|
@@ -135,6 +135,64 @@ function findEventConfig(config, contractName, eventName) {
|
|
|
135
135
|
return found.contents;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
let dummySrcAddress = "0x0000000000000000000000000000000000000000";
|
|
139
|
+
|
|
140
|
+
function firstContractAddress(chainConfig, contractName) {
|
|
141
|
+
let found = {
|
|
142
|
+
contents: undefined
|
|
143
|
+
};
|
|
144
|
+
chainConfig.contracts.forEach(contract => {
|
|
145
|
+
if (Stdlib_Option.isNone(found.contents) && contract.name === contractName) {
|
|
146
|
+
found.contents = contract.addresses[0];
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
return found.contents;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function deriveSrcAddress(providedSrcAddress, eventConfig, chainConfig) {
|
|
154
|
+
if (providedSrcAddress !== undefined) {
|
|
155
|
+
return Primitive_option.valFromOption(providedSrcAddress);
|
|
156
|
+
}
|
|
157
|
+
if (eventConfig.isWildcard) {
|
|
158
|
+
return dummySrcAddress;
|
|
159
|
+
}
|
|
160
|
+
let addr = firstContractAddress(chainConfig, eventConfig.contractName);
|
|
161
|
+
if (addr !== undefined) {
|
|
162
|
+
return Primitive_option.valFromOption(addr);
|
|
163
|
+
} else {
|
|
164
|
+
return dummySrcAddress;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function validateSrcAddresses(simulateItems, config, chainConfig, indexingAddresses) {
|
|
169
|
+
let known = new Set();
|
|
170
|
+
indexingAddresses.forEach(ia => {
|
|
171
|
+
known.add(ia.address);
|
|
172
|
+
});
|
|
173
|
+
simulateItems.forEach(rawJson => {
|
|
174
|
+
let match = rawJson.contract;
|
|
175
|
+
let match$1 = rawJson.event;
|
|
176
|
+
if (match === undefined) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (match$1 === undefined) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
let eventConfig = findEventConfig(config, match, match$1);
|
|
183
|
+
if (eventConfig === undefined) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (eventConfig.isWildcard) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
let srcAddress = deriveSrcAddress(rawJson.srcAddress, eventConfig, chainConfig);
|
|
190
|
+
if (!known.has(srcAddress)) {
|
|
191
|
+
return Stdlib_JsError.throwWithMessage(`simulate: ` + match + `.` + match$1 + ` resolved to address ` + srcAddress + `, which isn't indexed on chain ` + chainConfig.id.toString() + `. ` + (`Provide a "srcAddress" configured or registered for ` + match + ` on this chain, or use a wildcard event.`));
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
138
196
|
function parse(simulateItems, config, chainConfig) {
|
|
139
197
|
let chain = ChainMap.Chain.makeUnsafe(chainConfig.id);
|
|
140
198
|
let chainId = chainConfig.id;
|
|
@@ -169,26 +227,7 @@ function parse(simulateItems, config, chainConfig) {
|
|
|
169
227
|
currentLogIndex.contents = li$1 + 1 | 0;
|
|
170
228
|
logIndex = li$1;
|
|
171
229
|
}
|
|
172
|
-
let
|
|
173
|
-
let srcAddress;
|
|
174
|
-
if (addr !== undefined) {
|
|
175
|
-
srcAddress = Primitive_option.valFromOption(addr);
|
|
176
|
-
} else {
|
|
177
|
-
let addr$1 = {
|
|
178
|
-
contents: "0x0000000000000000000000000000000000000000"
|
|
179
|
-
};
|
|
180
|
-
chainConfig.contracts.forEach(contract => {
|
|
181
|
-
if (contract.name !== match) {
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
let a = contract.addresses[0];
|
|
185
|
-
if (a !== undefined) {
|
|
186
|
-
addr$1.contents = Primitive_option.valFromOption(a);
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
srcAddress = addr$1.contents;
|
|
191
|
-
}
|
|
230
|
+
let srcAddress = deriveSrcAddress(rawJson.srcAddress, eventConfig, chainConfig);
|
|
192
231
|
let blockJson = rawJson.block;
|
|
193
232
|
let blockJson$1 = (blockJson == null) ? undefined : Primitive_option.some(blockJson);
|
|
194
233
|
let transactionJson = rawJson.transaction;
|
|
@@ -241,6 +280,7 @@ function parse(simulateItems, config, chainConfig) {
|
|
|
241
280
|
blockNumber: blockNumber,
|
|
242
281
|
blockHash: match$3[3],
|
|
243
282
|
logIndex: logIndex,
|
|
283
|
+
transactionIndex: 0,
|
|
244
284
|
payload: {
|
|
245
285
|
contractName: eventConfig.contractName,
|
|
246
286
|
eventName: eventConfig.name,
|
|
@@ -248,7 +288,7 @@ function parse(simulateItems, config, chainConfig) {
|
|
|
248
288
|
chainId: chainId,
|
|
249
289
|
srcAddress: srcAddress,
|
|
250
290
|
logIndex: logIndex,
|
|
251
|
-
transaction: transaction,
|
|
291
|
+
transaction: Primitive_option.some(transaction),
|
|
252
292
|
block: match$3[0]
|
|
253
293
|
}
|
|
254
294
|
});
|
|
@@ -317,6 +357,10 @@ export {
|
|
|
317
357
|
fuelSimulateTransactionSchema,
|
|
318
358
|
parseFuelSimulateTransaction,
|
|
319
359
|
findEventConfig,
|
|
360
|
+
dummySrcAddress,
|
|
361
|
+
firstContractAddress,
|
|
362
|
+
deriveSrcAddress,
|
|
363
|
+
validateSrcAddresses,
|
|
320
364
|
parse,
|
|
321
365
|
patchConfig,
|
|
322
366
|
}
|
package/src/TestIndexer.res
CHANGED
|
@@ -43,6 +43,33 @@ let toIndexingAddress = (dc: InternalTable.EnvioAddresses.t): Internal.indexingA
|
|
|
43
43
|
registrationBlock: dc.registrationBlock,
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
// All indexing addresses (config-seeded + dynamically registered) grouped by
|
|
47
|
+
// chain id string, derived from the envio_addresses entities.
|
|
48
|
+
let getIndexingAddressesByChain = (state: testIndexerState): dict<
|
|
49
|
+
array<Internal.indexingAddress>,
|
|
50
|
+
> => {
|
|
51
|
+
let byChain = Dict.make()
|
|
52
|
+
switch state.entities->Dict.get(InternalTable.EnvioAddresses.name) {
|
|
53
|
+
| Some(dcDict) =>
|
|
54
|
+
dcDict
|
|
55
|
+
->Dict.valuesToArray
|
|
56
|
+
->Array.forEach(entity => {
|
|
57
|
+
let dc = entity->castToEnvioAddresses
|
|
58
|
+
let chainIdStr = dc.chainId->Int.toString
|
|
59
|
+
let contracts = switch byChain->Dict.get(chainIdStr) {
|
|
60
|
+
| Some(arr) => arr
|
|
61
|
+
| None =>
|
|
62
|
+
let arr = []
|
|
63
|
+
byChain->Dict.set(chainIdStr, arr)
|
|
64
|
+
arr
|
|
65
|
+
}
|
|
66
|
+
contracts->Array.push(dc->toIndexingAddress)->ignore
|
|
67
|
+
})
|
|
68
|
+
| None => ()
|
|
69
|
+
}
|
|
70
|
+
byChain
|
|
71
|
+
}
|
|
72
|
+
|
|
46
73
|
let handleLoad = (state: testIndexerState, ~tableName: string, ~filter: EntityFilter.t): JSON.t => {
|
|
47
74
|
// Loads for non-entity tables (e.g. effect caches `envio_effect_<name>`) reach
|
|
48
75
|
// here too. TestIndexer never persists those, so there's nothing to return —
|
|
@@ -566,22 +593,10 @@ let makeCreateTestIndexer = (~config: Config.t, ~workerPath: string): (
|
|
|
566
593
|
`Cannot access ${contract.name}.addresses while indexer.process() is running. ` ++ "Wait for process() to complete before reading contract addresses.",
|
|
567
594
|
)
|
|
568
595
|
}
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
->Dict.valuesToArray
|
|
574
|
-
->Array.forEach(
|
|
575
|
-
entity => {
|
|
576
|
-
let dc = entity->castToEnvioAddresses
|
|
577
|
-
if dc.contractName === contract.name && dc.chainId === chainConfig.id {
|
|
578
|
-
addresses->Array.push(dc->Config.EnvioAddresses.getAddress)->ignore
|
|
579
|
-
}
|
|
580
|
-
},
|
|
581
|
-
)
|
|
582
|
-
| None => ()
|
|
583
|
-
}
|
|
584
|
-
addresses
|
|
596
|
+
getIndexingAddressesByChain(state)
|
|
597
|
+
->Dict.get(chainConfig.id->Int.toString)
|
|
598
|
+
->Option.getOr([])
|
|
599
|
+
->Array.filterMap(ia => ia.contractName === contract.name ? Some(ia.address) : None)
|
|
585
600
|
},
|
|
586
601
|
},
|
|
587
602
|
)
|
|
@@ -653,6 +668,7 @@ let makeCreateTestIndexer = (~config: Config.t, ~workerPath: string): (
|
|
|
653
668
|
})
|
|
654
669
|
|
|
655
670
|
// Parse and validate all chain configs upfront before starting any workers
|
|
671
|
+
let preflightAddressesByChain = getIndexingAddressesByChain(state)
|
|
656
672
|
let chainEntries = sortedChainKeys->Array.map(chainIdStr => {
|
|
657
673
|
let rawChainConfig = rawChains->Dict.getUnsafe(chainIdStr)
|
|
658
674
|
let chainId = switch chainIdStr->Int.fromString {
|
|
@@ -668,6 +684,19 @@ let makeCreateTestIndexer = (~config: Config.t, ~workerPath: string): (
|
|
|
668
684
|
~rawChainConfig,
|
|
669
685
|
~progressBlock=state.progressBlockByChain->Dict.get(chainIdStr),
|
|
670
686
|
)
|
|
687
|
+
switch rawChainConfig.simulate {
|
|
688
|
+
| Some(simulateItems) =>
|
|
689
|
+
let chainConfig = config.chainMap->ChainMap.get(ChainMap.Chain.makeUnsafe(~chainId))
|
|
690
|
+
SimulateItems.validateSrcAddresses(
|
|
691
|
+
~simulateItems,
|
|
692
|
+
~config,
|
|
693
|
+
~chainConfig,
|
|
694
|
+
~indexingAddresses=preflightAddressesByChain
|
|
695
|
+
->Dict.get(chainIdStr)
|
|
696
|
+
->Option.getOr([]),
|
|
697
|
+
)
|
|
698
|
+
| None => ()
|
|
699
|
+
}
|
|
671
700
|
(chainIdStr, chainId, rawChainConfig, processChainConfig)
|
|
672
701
|
})
|
|
673
702
|
|
|
@@ -684,26 +713,9 @@ let makeCreateTestIndexer = (~config: Config.t, ~workerPath: string): (
|
|
|
684
713
|
let chains: dict<chainConfig> = Dict.make()
|
|
685
714
|
chains->Dict.set(chainIdStr, processChainConfig)
|
|
686
715
|
|
|
687
|
-
//
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
| Some(dcDict) =>
|
|
691
|
-
dcDict
|
|
692
|
-
->Dict.valuesToArray
|
|
693
|
-
->Array.forEach(entity => {
|
|
694
|
-
let dc = entity->castToEnvioAddresses
|
|
695
|
-
let dcChainIdStr = dc.chainId->Int.toString
|
|
696
|
-
let contracts = switch indexingAddressesByChain->Dict.get(dcChainIdStr) {
|
|
697
|
-
| Some(arr) => arr
|
|
698
|
-
| None =>
|
|
699
|
-
let arr = []
|
|
700
|
-
indexingAddressesByChain->Dict.set(dcChainIdStr, arr)
|
|
701
|
-
arr
|
|
702
|
-
}
|
|
703
|
-
contracts->Array.push(dc->toIndexingAddress)->ignore
|
|
704
|
-
})
|
|
705
|
-
| None => ()
|
|
706
|
-
}
|
|
716
|
+
// Rebuilt per chain so workers see contracts registered by earlier
|
|
717
|
+
// chains in the same process() call.
|
|
718
|
+
let indexingAddressesByChain = getIndexingAddressesByChain(state)
|
|
707
719
|
|
|
708
720
|
let initialState = makeInitialState(
|
|
709
721
|
~config,
|
package/src/TestIndexer.res.mjs
CHANGED
|
@@ -12,6 +12,7 @@ import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
|
|
|
12
12
|
import * as Persistence from "./Persistence.res.mjs";
|
|
13
13
|
import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
|
|
14
14
|
import * as EntityFilter from "./db/EntityFilter.res.mjs";
|
|
15
|
+
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
15
16
|
import * as InternalTable from "./db/InternalTable.res.mjs";
|
|
16
17
|
import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
|
|
17
18
|
import * as SimulateItems from "./SimulateItems.res.mjs";
|
|
@@ -32,6 +33,27 @@ function toIndexingAddress(dc) {
|
|
|
32
33
|
};
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
function getIndexingAddressesByChain(state) {
|
|
37
|
+
let byChain = {};
|
|
38
|
+
let dcDict = state.entities[Config.EnvioAddresses.name];
|
|
39
|
+
if (dcDict !== undefined) {
|
|
40
|
+
Object.values(dcDict).forEach(entity => {
|
|
41
|
+
let chainIdStr = entity.chain_id.toString();
|
|
42
|
+
let arr = byChain[chainIdStr];
|
|
43
|
+
let contracts;
|
|
44
|
+
if (arr !== undefined) {
|
|
45
|
+
contracts = arr;
|
|
46
|
+
} else {
|
|
47
|
+
let arr$1 = [];
|
|
48
|
+
byChain[chainIdStr] = arr$1;
|
|
49
|
+
contracts = arr$1;
|
|
50
|
+
}
|
|
51
|
+
contracts.push(toIndexingAddress(entity));
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return byChain;
|
|
55
|
+
}
|
|
56
|
+
|
|
35
57
|
function handleLoad(state, tableName, filter) {
|
|
36
58
|
let entityConfig = state.entityConfigs[tableName];
|
|
37
59
|
if (entityConfig === undefined) {
|
|
@@ -403,17 +425,11 @@ function makeCreateTestIndexer(config, workerPath) {
|
|
|
403
425
|
if (state.processInProgress) {
|
|
404
426
|
Stdlib_JsError.throwWithMessage(`Cannot access ` + contract.name + `.addresses while indexer.process() is running. ` + "Wait for process() to complete before reading contract addresses.");
|
|
405
427
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
addresses.push(Config.EnvioAddresses.getAddress(entity));
|
|
412
|
-
return;
|
|
413
|
-
}
|
|
414
|
-
});
|
|
415
|
-
}
|
|
416
|
-
return addresses;
|
|
428
|
+
return Stdlib_Array.filterMap(Stdlib_Option.getOr(getIndexingAddressesByChain(state)[chainConfig.id.toString()], []), ia => {
|
|
429
|
+
if (ia.contractName === contract.name) {
|
|
430
|
+
return Primitive_option.some(ia.address);
|
|
431
|
+
}
|
|
432
|
+
});
|
|
417
433
|
}
|
|
418
434
|
});
|
|
419
435
|
Object.defineProperty(chainObj, contract.name, {
|
|
@@ -465,11 +481,17 @@ function makeCreateTestIndexer(config, workerPath) {
|
|
|
465
481
|
let bId = Stdlib_Option.getOr(Stdlib_Int.fromString(b, undefined), 0);
|
|
466
482
|
return Primitive_int.compare(aId, bId);
|
|
467
483
|
});
|
|
484
|
+
let preflightAddressesByChain = getIndexingAddressesByChain(state);
|
|
468
485
|
let chainEntries = sortedChainKeys.map(chainIdStr => {
|
|
469
486
|
let rawChainConfig = rawChains[chainIdStr];
|
|
470
487
|
let id = Stdlib_Int.fromString(chainIdStr, undefined);
|
|
471
488
|
let chainId = id !== undefined ? id : Stdlib_JsError.throwWithMessage(`Invalid chain ID "` + chainIdStr + `": expected a numeric chain ID`);
|
|
472
489
|
let processChainConfig = parseBlockRange(chainIdStr, config, rawChainConfig, state.progressBlockByChain[chainIdStr]);
|
|
490
|
+
let simulateItems = rawChainConfig.simulate;
|
|
491
|
+
if (simulateItems !== undefined) {
|
|
492
|
+
let chainConfig = ChainMap.get(config.chainMap, ChainMap.Chain.makeUnsafe(chainId));
|
|
493
|
+
SimulateItems.validateSrcAddresses(simulateItems, config, chainConfig, Stdlib_Option.getOr(preflightAddressesByChain[chainIdStr], []));
|
|
494
|
+
}
|
|
473
495
|
return [
|
|
474
496
|
chainIdStr,
|
|
475
497
|
chainId,
|
|
@@ -484,23 +506,7 @@ function makeCreateTestIndexer(config, workerPath) {
|
|
|
484
506
|
let chainId = param[1];
|
|
485
507
|
let chains = {};
|
|
486
508
|
chains[param[0]] = processChainConfig;
|
|
487
|
-
let indexingAddressesByChain =
|
|
488
|
-
let dcDict = state.entities[Config.EnvioAddresses.name];
|
|
489
|
-
if (dcDict !== undefined) {
|
|
490
|
-
Object.values(dcDict).forEach(entity => {
|
|
491
|
-
let dcChainIdStr = entity.chain_id.toString();
|
|
492
|
-
let arr = indexingAddressesByChain[dcChainIdStr];
|
|
493
|
-
let contracts;
|
|
494
|
-
if (arr !== undefined) {
|
|
495
|
-
contracts = arr;
|
|
496
|
-
} else {
|
|
497
|
-
let arr$1 = [];
|
|
498
|
-
indexingAddressesByChain[dcChainIdStr] = arr$1;
|
|
499
|
-
contracts = arr$1;
|
|
500
|
-
}
|
|
501
|
-
contracts.push(toIndexingAddress(entity));
|
|
502
|
-
});
|
|
503
|
-
}
|
|
509
|
+
let indexingAddressesByChain = getIndexingAddressesByChain(state);
|
|
504
510
|
let initialState = makeInitialState(config, chains, indexingAddressesByChain);
|
|
505
511
|
return new Promise((resolve, reject) => {
|
|
506
512
|
let workerData_startBlock = processChainConfig.startBlock;
|
|
@@ -645,6 +651,7 @@ function initTestWorker() {
|
|
|
645
651
|
|
|
646
652
|
export {
|
|
647
653
|
toIndexingAddress,
|
|
654
|
+
getIndexingAddressesByChain,
|
|
648
655
|
handleLoad,
|
|
649
656
|
handleWriteBatch,
|
|
650
657
|
makeInitialState,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
function secondsSince(from) {
|
|
5
|
+
return (performance.now() - from) / 1000;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function secondsBetween(from, to) {
|
|
9
|
+
return (to - from) / 1000;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function now(prim) {
|
|
13
|
+
return performance.now();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
now,
|
|
18
|
+
secondsSince,
|
|
19
|
+
secondsBetween,
|
|
20
|
+
}
|
|
21
|
+
/* No side effect */
|
|
@@ -28,29 +28,25 @@ module Group = {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
) =>
|
|
31
|
+
// Ownership only: resolve the owning contract from the partition's reverse
|
|
32
|
+
// index (the partition that fetched the log), not a chain-wide snapshot. The
|
|
33
|
+
// `effectiveStartBlock` temporal gate now lives in `clientAddressFilter`. The
|
|
34
|
+
// wildcard partition has an empty index → every log falls back to `wildcard`,
|
|
35
|
+
// so it can never claim an address-bound contract's logs.
|
|
36
|
+
let get = (group: t<'a>, ~contractAddress, ~contractNameByAddress: dict<string>) =>
|
|
37
37
|
switch group {
|
|
38
38
|
| {wildcard, byContractName} =>
|
|
39
|
-
switch
|
|
39
|
+
switch contractNameByAddress->Utils.Dict.dangerouslyGetNonOption(
|
|
40
40
|
contractAddress->Address.toString,
|
|
41
41
|
) {
|
|
42
|
-
| Some(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
| Some(_) as event => event
|
|
51
|
-
}
|
|
52
|
-
} else {
|
|
53
|
-
None
|
|
42
|
+
| Some(contractName) =>
|
|
43
|
+
switch byContractName->Utils.Dict.dangerouslyGetNonOption(contractName) {
|
|
44
|
+
// Fall back to the wildcard handler when the owning contract has no
|
|
45
|
+
// matching event for this tag. This covers addresses registered for
|
|
46
|
+
// contracts without events (persisted for future config changes) as
|
|
47
|
+
// well as addresses whose contract has other events but not this one.
|
|
48
|
+
| None => wildcard
|
|
49
|
+
| Some(_) as event => event
|
|
54
50
|
}
|
|
55
51
|
| None => wildcard
|
|
56
52
|
}
|
|
@@ -89,10 +85,10 @@ let addOrThrow = (
|
|
|
89
85
|
}
|
|
90
86
|
}
|
|
91
87
|
|
|
92
|
-
let get = (router: t<'a>, ~tag, ~contractAddress, ~
|
|
88
|
+
let get = (router: t<'a>, ~tag, ~contractAddress, ~contractNameByAddress) => {
|
|
93
89
|
switch router->Utils.Dict.dangerouslyGetNonOption(tag) {
|
|
94
90
|
| None => None
|
|
95
|
-
| Some(group) => group->Group.get(~contractAddress, ~
|
|
91
|
+
| Some(group) => group->Group.get(~contractAddress, ~contractNameByAddress)
|
|
96
92
|
}
|
|
97
93
|
}
|
|
98
94
|
|
|
@@ -39,16 +39,13 @@ function addOrThrow(group, event, contractName, isWildcard) {
|
|
|
39
39
|
byContractName[contractName] = event;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
function get(group, contractAddress,
|
|
42
|
+
function get(group, contractAddress, contractNameByAddress) {
|
|
43
43
|
let wildcard = group.wildcard;
|
|
44
|
-
let
|
|
45
|
-
if (
|
|
44
|
+
let contractName = contractNameByAddress[contractAddress];
|
|
45
|
+
if (contractName === undefined) {
|
|
46
46
|
return wildcard;
|
|
47
47
|
}
|
|
48
|
-
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
let event = group.byContractName[indexingContract.contractName];
|
|
48
|
+
let event = group.byContractName[contractName];
|
|
52
49
|
if (event !== undefined) {
|
|
53
50
|
return event;
|
|
54
51
|
} else {
|
|
@@ -93,10 +90,10 @@ function addOrThrow$1(router, eventId, event, contractName, isWildcard, eventNam
|
|
|
93
90
|
}
|
|
94
91
|
}
|
|
95
92
|
|
|
96
|
-
function get$1(router, tag, contractAddress,
|
|
93
|
+
function get$1(router, tag, contractAddress, contractNameByAddress) {
|
|
97
94
|
let group = router[tag];
|
|
98
95
|
if (group !== undefined) {
|
|
99
|
-
return get(group, contractAddress,
|
|
96
|
+
return get(group, contractAddress, contractNameByAddress);
|
|
100
97
|
}
|
|
101
98
|
}
|
|
102
99
|
|
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,51 @@ 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
|
+
let transactionFieldMask = TransactionStore.makeMaskFn(transactionFields)
|
|
56
|
+
|
|
16
57
|
let cleanUpRawEventFieldsInPlace: JSON.t => unit = %raw(`fields => {
|
|
17
58
|
delete fields.hash
|
|
18
59
|
delete fields.number
|
|
@@ -21,70 +62,6 @@ let cleanUpRawEventFieldsInPlace: JSON.t => unit = %raw(`fields => {
|
|
|
21
62
|
|
|
22
63
|
let make = (~logger: Pino.t): Ecosystem.t => {
|
|
23
64
|
name: Evm,
|
|
24
|
-
blockFields: [
|
|
25
|
-
"number",
|
|
26
|
-
"timestamp",
|
|
27
|
-
"hash",
|
|
28
|
-
"parentHash",
|
|
29
|
-
"nonce",
|
|
30
|
-
"sha3Uncles",
|
|
31
|
-
"logsBloom",
|
|
32
|
-
"transactionsRoot",
|
|
33
|
-
"stateRoot",
|
|
34
|
-
"receiptsRoot",
|
|
35
|
-
"miner",
|
|
36
|
-
"difficulty",
|
|
37
|
-
"totalDifficulty",
|
|
38
|
-
"extraData",
|
|
39
|
-
"size",
|
|
40
|
-
"gasLimit",
|
|
41
|
-
"gasUsed",
|
|
42
|
-
"uncles",
|
|
43
|
-
"baseFeePerGas",
|
|
44
|
-
"blobGasUsed",
|
|
45
|
-
"excessBlobGas",
|
|
46
|
-
"parentBeaconBlockRoot",
|
|
47
|
-
"withdrawalsRoot",
|
|
48
|
-
"l1BlockNumber",
|
|
49
|
-
"sendCount",
|
|
50
|
-
"sendRoot",
|
|
51
|
-
"mixHash",
|
|
52
|
-
],
|
|
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
|
-
],
|
|
88
65
|
blockNumberName: "number",
|
|
89
66
|
blockTimestampName: "timestamp",
|
|
90
67
|
blockHashName: "hash",
|
|
@@ -106,7 +83,10 @@ let make = (~logger: Pino.t): Ecosystem.t => {
|
|
|
106
83
|
s.field("block", S.option(S.object(s2 => s2.field("number", S.unknown))))
|
|
107
84
|
),
|
|
108
85
|
logger,
|
|
109
|
-
|
|
86
|
+
transactionFieldMask,
|
|
87
|
+
// The payload carries `transaction` by batch prep (HyperSync) or inline
|
|
88
|
+
// (RPC/simulate), so the event is the payload as-is.
|
|
89
|
+
toEvent: eventItem => eventItem.payload->(Utils.magic: Internal.eventPayload => Internal.event),
|
|
110
90
|
toEventLogger: eventItem =>
|
|
111
91
|
Logging.createChildFrom(
|
|
112
92
|
~logger,
|