envio 3.3.0-alpha.2 → 3.3.0-alpha.4
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/Bin.res +3 -0
- package/src/Bin.res.mjs +4 -0
- package/src/ChainFetching.res +26 -3
- package/src/ChainFetching.res.mjs +22 -3
- package/src/ChainState.res +3 -12
- package/src/ChainState.res.mjs +6 -8
- package/src/ChainState.resi +0 -2
- package/src/CrossChainState.res +15 -0
- package/src/CrossChainState.res.mjs +12 -0
- package/src/Ecosystem.res +0 -6
- package/src/EventConfigBuilder.res +45 -18
- package/src/EventConfigBuilder.res.mjs +28 -10
- package/src/EventProcessing.res +53 -37
- package/src/EventProcessing.res.mjs +41 -36
- package/src/FetchState.res +35 -42
- package/src/FetchState.res.mjs +37 -63
- package/src/HandlerLoader.res +10 -1
- package/src/HandlerLoader.res.mjs +15 -8
- package/src/Internal.res +8 -3
- package/src/Internal.res.mjs +1 -1
- package/src/LoadLayer.res +5 -5
- package/src/LoadLayer.res.mjs +6 -6
- package/src/Main.res +17 -9
- package/src/Main.res.mjs +15 -6
- 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 +2 -2
- package/src/Rollback.res.mjs +3 -3
- package/src/SimulateItems.res +81 -15
- package/src/SimulateItems.res.mjs +63 -20
- package/src/TestIndexer.res +77 -39
- package/src/TestIndexer.res.mjs +45 -31
- 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 +10 -37
- package/src/sources/Evm.res.mjs +5 -40
- package/src/sources/Fuel.res +0 -4
- package/src/sources/Fuel.res.mjs +0 -7
- package/src/sources/HyperFuelSource.res +10 -11
- package/src/sources/HyperFuelSource.res.mjs +11 -11
- package/src/sources/HyperSync.res +3 -0
- package/src/sources/HyperSync.res.mjs +1 -0
- package/src/sources/HyperSync.resi +1 -0
- package/src/sources/HyperSyncClient.res +5 -1
- package/src/sources/HyperSyncSource.res +42 -24
- package/src/sources/HyperSyncSource.res.mjs +30 -26
- package/src/sources/RpcSource.res +7 -8
- package/src/sources/RpcSource.res.mjs +8 -8
- package/src/sources/SimulateSource.res +1 -1
- package/src/sources/Source.res +1 -1
- package/src/sources/SourceManager.res +17 -16
- package/src/sources/SourceManager.res.mjs +10 -15
- package/src/sources/Svm.res +6 -11
- package/src/sources/Svm.res.mjs +6 -14
- package/src/sources/SvmHyperSyncSource.res +24 -18
- package/src/sources/SvmHyperSyncSource.res.mjs +22 -15
- package/src/sources/TransactionStore.res +62 -35
- package/src/sources/TransactionStore.res.mjs +44 -18
- 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
package/index.d.ts
CHANGED
|
@@ -997,24 +997,6 @@ export type SvmTokenBalance = {
|
|
|
997
997
|
readonly postAmount?: string;
|
|
998
998
|
};
|
|
999
999
|
|
|
1000
|
-
/** Parent transaction surfaced when an instruction's
|
|
1001
|
-
* `include_transaction` flag is `true`. */
|
|
1002
|
-
export type SvmTransaction = {
|
|
1003
|
-
readonly signatures: readonly string[];
|
|
1004
|
-
readonly feePayer?: string;
|
|
1005
|
-
readonly success?: boolean;
|
|
1006
|
-
readonly err?: string;
|
|
1007
|
-
/** Lamports. */
|
|
1008
|
-
readonly fee?: bigint;
|
|
1009
|
-
readonly computeUnitsConsumed?: bigint;
|
|
1010
|
-
readonly accountKeys: readonly string[];
|
|
1011
|
-
readonly recentBlockhash?: string;
|
|
1012
|
-
readonly version?: string;
|
|
1013
|
-
/** SPL Token / Token-2022 balance snapshots for this transaction.
|
|
1014
|
-
* Present when `include_token_balances` is `true`. */
|
|
1015
|
-
readonly tokenBalances?: readonly SvmTokenBalance[];
|
|
1016
|
-
};
|
|
1017
|
-
|
|
1018
1000
|
export type SvmLog = {
|
|
1019
1001
|
readonly kind: string;
|
|
1020
1002
|
readonly message: string;
|
|
@@ -1033,6 +1015,7 @@ export type SvmLog = {
|
|
|
1033
1015
|
* are base58 strings. */
|
|
1034
1016
|
export type SvmInstruction<
|
|
1035
1017
|
Params extends SvmInstructionParams = SvmInstructionParams,
|
|
1018
|
+
Tx = SvmTransaction,
|
|
1036
1019
|
> = {
|
|
1037
1020
|
/** Program name as declared under `programs[].name` in `config.yaml`. */
|
|
1038
1021
|
readonly programName: string;
|
|
@@ -1050,8 +1033,11 @@ export type SvmInstruction<
|
|
|
1050
1033
|
readonly d8?: string;
|
|
1051
1034
|
/** Borsh-decoded params. Present when a schema is configured and matched. */
|
|
1052
1035
|
readonly params?: Params;
|
|
1053
|
-
/**
|
|
1054
|
-
|
|
1036
|
+
/** Parent transaction. Carries only the fields selected via this
|
|
1037
|
+
* instruction's `field_selection`; unselected fields are typed as
|
|
1038
|
+
* `FieldNotSelected<...>` so reading them is a compile error. Always present
|
|
1039
|
+
* (`{}` when no fields are selected). */
|
|
1040
|
+
readonly transaction: Tx;
|
|
1055
1041
|
/** Present when the instruction's `include_logs` is `true`; only logs
|
|
1056
1042
|
* scoped to this exact instruction (matching `instruction_address`). */
|
|
1057
1043
|
readonly logs?: readonly SvmLog[];
|
|
@@ -1327,7 +1313,10 @@ type SvmEcosystem<Config extends IndexerConfigTypes = GlobalConfig> =
|
|
|
1327
1313
|
handler: (
|
|
1328
1314
|
args: SvmOnInstructionHandlerArgs<
|
|
1329
1315
|
Config,
|
|
1330
|
-
SvmInstruction<
|
|
1316
|
+
SvmInstruction<
|
|
1317
|
+
SvmParamsFromProgramTable<Programs[P][I]>,
|
|
1318
|
+
Programs[P][I]["transaction"]
|
|
1319
|
+
>
|
|
1331
1320
|
>,
|
|
1332
1321
|
) => Promise<void>,
|
|
1333
1322
|
) => void;
|
|
@@ -1695,6 +1684,7 @@ type EvmContractsT = GlobalConfig extends { evm: { contracts: infer X extends
|
|
|
1695
1684
|
type FuelChainsT = GlobalConfig extends { fuel: { chains: infer X extends Record<string, { id: number }> } } ? X : {};
|
|
1696
1685
|
type FuelContractsT = GlobalConfig extends { fuel: { contracts: infer X extends Record<string, Record<string, any>> } } ? X : {};
|
|
1697
1686
|
type SvmChainsT = GlobalConfig extends { svm: { chains: infer X extends Record<string, { id: number }> } } ? X : {};
|
|
1687
|
+
type SvmProgramsT = GlobalConfig extends { svm: { programs: infer X extends Record<string, Record<string, any>> } } ? X : {};
|
|
1698
1688
|
type EntitiesT = GlobalConfig extends { entities: infer X extends Record<string, object> } ? X : {};
|
|
1699
1689
|
type EnumsT = GlobalConfig extends { enums: infer X extends Record<string, any> } ? X : {};
|
|
1700
1690
|
|
|
@@ -1716,6 +1706,18 @@ export type FuelChainId = IsEmptyObject<FuelChainsT> extends true ? NotConfigure
|
|
|
1716
1706
|
/** Union of all configured SVM chain IDs. */
|
|
1717
1707
|
export type SvmChainId = IsEmptyObject<SvmChainsT> extends true ? NotConfigured<"SvmChainId", "Configure SVM chains"> : SvmChainsT [keyof SvmChainsT ]["id"];
|
|
1718
1708
|
|
|
1709
|
+
/** The SVM parent-transaction type generated from this project's
|
|
1710
|
+
* `field_selection`: the union of every instruction's `transaction` shape,
|
|
1711
|
+
* with unselected fields typed as `FieldNotSelected<...>`. Resolves to a
|
|
1712
|
+
* `NotConfigured` hint until `envio codegen` augments {@link Global}. */
|
|
1713
|
+
export type SvmTransaction = IsEmptyObject<SvmProgramsT> extends true
|
|
1714
|
+
? NotConfigured<"SvmTransaction", "Configure SVM programs">
|
|
1715
|
+
: {
|
|
1716
|
+
[P in keyof SvmProgramsT]: {
|
|
1717
|
+
[I in keyof SvmProgramsT[P]]: SvmProgramsT[P][I]["transaction"];
|
|
1718
|
+
}[keyof SvmProgramsT[P]];
|
|
1719
|
+
}[keyof SvmProgramsT];
|
|
1720
|
+
|
|
1719
1721
|
/** Lookup an EVM event type by contract and event name. Without generics,
|
|
1720
1722
|
* resolves to the discriminated union of every EVM event in the project. */
|
|
1721
1723
|
export type EvmEvent<
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "envio",
|
|
3
|
-
"version": "3.3.0-alpha.
|
|
3
|
+
"version": "3.3.0-alpha.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
|
|
6
6
|
"bin": "./bin.mjs",
|
|
@@ -69,10 +69,10 @@
|
|
|
69
69
|
"tsx": "4.21.0"
|
|
70
70
|
},
|
|
71
71
|
"optionalDependencies": {
|
|
72
|
-
"envio-linux-x64": "3.3.0-alpha.
|
|
73
|
-
"envio-linux-x64-musl": "3.3.0-alpha.
|
|
74
|
-
"envio-linux-arm64": "3.3.0-alpha.
|
|
75
|
-
"envio-darwin-x64": "3.3.0-alpha.
|
|
76
|
-
"envio-darwin-arm64": "3.3.0-alpha.
|
|
72
|
+
"envio-linux-x64": "3.3.0-alpha.4",
|
|
73
|
+
"envio-linux-x64-musl": "3.3.0-alpha.4",
|
|
74
|
+
"envio-linux-arm64": "3.3.0-alpha.4",
|
|
75
|
+
"envio-darwin-x64": "3.3.0-alpha.4",
|
|
76
|
+
"envio-darwin-arm64": "3.3.0-alpha.4"
|
|
77
77
|
}
|
|
78
78
|
}
|
package/src/Bin.res
CHANGED
|
@@ -71,6 +71,9 @@ let run = async args => {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
} catch {
|
|
74
|
+
| Main.FatalError(_) =>
|
|
75
|
+
// Already logged with full context by Main.start's onError; just exit.
|
|
76
|
+
NodeJs.process->NodeJs.exitWithCode(Failure)
|
|
74
77
|
| exn =>
|
|
75
78
|
// Log just the exception's own message — wrapping it in "Failed at
|
|
76
79
|
// initialization" and pino's err serializer buries the real cause under
|
package/src/Bin.res.mjs
CHANGED
|
@@ -79,6 +79,10 @@ async function run(args) {
|
|
|
79
79
|
}
|
|
80
80
|
} catch (raw_exn) {
|
|
81
81
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
82
|
+
if (exn.RE_EXN_ID === Main.FatalError) {
|
|
83
|
+
Process.exit(1);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
82
86
|
let e = Primitive_exceptions.internalToException(exn);
|
|
83
87
|
let message = e.RE_EXN_ID === "JsExn" ? Stdlib_Option.getOr(Stdlib_JsExn.message(e._1), "Failed at initialization") : "Failed at initialization";
|
|
84
88
|
Logging.error(message);
|
package/src/ChainFetching.res
CHANGED
|
@@ -11,13 +11,12 @@ type partitionQueryResponse = {
|
|
|
11
11
|
let runContractRegistersOrThrow = async (
|
|
12
12
|
~itemsWithContractRegister: array<Internal.item>,
|
|
13
13
|
~config: Config.t,
|
|
14
|
-
~chainState: ChainState.t,
|
|
15
14
|
~page: option<TransactionStore.t>,
|
|
16
15
|
) => {
|
|
17
16
|
// contractRegister handlers can read event.transaction, so materialise the
|
|
18
17
|
// selected fields onto the payloads before running them. All items belong to
|
|
19
18
|
// the chain being fetched, hence its single page store and mask.
|
|
20
|
-
await
|
|
19
|
+
await ChainState.materializePageItems(~items=itemsWithContractRegister, ~page)
|
|
21
20
|
|
|
22
21
|
let itemsWithDcs = []
|
|
23
22
|
|
|
@@ -233,7 +232,6 @@ let rec onQueryResponse = async (
|
|
|
233
232
|
switch await runContractRegistersOrThrow(
|
|
234
233
|
~itemsWithContractRegister,
|
|
235
234
|
~config=state->IndexerState.config,
|
|
236
|
-
~chainState,
|
|
237
235
|
~page=transactionStore,
|
|
238
236
|
) {
|
|
239
237
|
| exception exn => IndexerState.errorExit(state, exn->ErrorHandling.make)
|
|
@@ -336,6 +334,15 @@ let fetchChain = async (
|
|
|
336
334
|
// there's nothing to fetch. During backfill any such chain is idle.
|
|
337
335
|
let reducedPolling = !isRealtime
|
|
338
336
|
|
|
337
|
+
// Accumulated across all queries dispatched in this tick so their per-query
|
|
338
|
+
// results collapse into a single completion log instead of one per query.
|
|
339
|
+
let dispatchedCount = switch action {
|
|
340
|
+
| FetchState.Ready(queries) => queries->Array.length
|
|
341
|
+
| WaitingForNewBlock | NothingToQuery => 0
|
|
342
|
+
}
|
|
343
|
+
let fetchedByPartition = Dict.make()
|
|
344
|
+
let fetchedCount = ref(0)
|
|
345
|
+
|
|
339
346
|
// Owns its error boundary: launch doesn't catch, so any failure here (the
|
|
340
347
|
// query, response handling, or dispatch itself) must stop the indexer.
|
|
341
348
|
try {
|
|
@@ -361,6 +368,22 @@ let fetchChain = async (
|
|
|
361
368
|
~knownHeight=chainState->ChainState.knownHeight,
|
|
362
369
|
~isRealtime,
|
|
363
370
|
)
|
|
371
|
+
fetchedCount := fetchedCount.contents + 1
|
|
372
|
+
fetchedByPartition->Dict.set(
|
|
373
|
+
query.partitionId,
|
|
374
|
+
{
|
|
375
|
+
"fromBlock": response.fromBlockQueried,
|
|
376
|
+
"toBlock": response.latestFetchedBlockNumber,
|
|
377
|
+
"numEvents": response.parsedQueueItems->Array.length,
|
|
378
|
+
},
|
|
379
|
+
)
|
|
380
|
+
if dispatchedCount > 0 && fetchedCount.contents === dispatchedCount {
|
|
381
|
+
Logging.trace({
|
|
382
|
+
"msg": "Finished querying",
|
|
383
|
+
"chainId": chain->ChainMap.Chain.toChainId,
|
|
384
|
+
"partitions": fetchedByPartition,
|
|
385
|
+
})
|
|
386
|
+
}
|
|
364
387
|
await onQueryResponse(
|
|
365
388
|
state,
|
|
366
389
|
{chain, response, query},
|
|
@@ -16,8 +16,8 @@ import * as Stdlib_Promise from "@rescript/runtime/lib/es6/Stdlib_Promise.js";
|
|
|
16
16
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
17
17
|
import * as ContractRegisterContext from "./ContractRegisterContext.res.mjs";
|
|
18
18
|
|
|
19
|
-
async function runContractRegistersOrThrow(itemsWithContractRegister, config,
|
|
20
|
-
await ChainState.materializePageItems(
|
|
19
|
+
async function runContractRegistersOrThrow(itemsWithContractRegister, config, page) {
|
|
20
|
+
await ChainState.materializePageItems(itemsWithContractRegister, page);
|
|
21
21
|
let itemsWithDcs = [];
|
|
22
22
|
let onRegister = (item, contractAddress, contractName) => {
|
|
23
23
|
let dc_registrationBlock = item.blockNumber;
|
|
@@ -145,7 +145,7 @@ async function onQueryResponse(state, param, stateId, scheduleFetch, schedulePro
|
|
|
145
145
|
}
|
|
146
146
|
let newItemsWithDcs;
|
|
147
147
|
try {
|
|
148
|
-
newItemsWithDcs = await runContractRegistersOrThrow(itemsWithContractRegister, IndexerState.config(state),
|
|
148
|
+
newItemsWithDcs = await runContractRegistersOrThrow(itemsWithContractRegister, IndexerState.config(state), transactionStore);
|
|
149
149
|
} catch (raw_exn) {
|
|
150
150
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
151
151
|
return IndexerState.errorExit(state, ErrorHandling.make(exn, undefined, undefined));
|
|
@@ -176,10 +176,29 @@ async function fetchChain(state, chain, action, stateId, scheduleFetch, schedule
|
|
|
176
176
|
let isRealtime = IndexerState.isRealtime(state);
|
|
177
177
|
let sourceManager = ChainState.sourceManager(chainState);
|
|
178
178
|
let reducedPolling = !isRealtime;
|
|
179
|
+
let dispatchedCount;
|
|
180
|
+
dispatchedCount = typeof action !== "object" ? 0 : action._0.length;
|
|
181
|
+
let fetchedByPartition = {};
|
|
182
|
+
let fetchedCount = {
|
|
183
|
+
contents: 0
|
|
184
|
+
};
|
|
179
185
|
try {
|
|
180
186
|
return await ChainState.dispatch(chainState, async query => {
|
|
181
187
|
try {
|
|
182
188
|
let response = await SourceManager.executeQuery(sourceManager, query, ChainState.knownHeight(chainState), isRealtime);
|
|
189
|
+
fetchedCount.contents = fetchedCount.contents + 1 | 0;
|
|
190
|
+
fetchedByPartition[query.partitionId] = {
|
|
191
|
+
fromBlock: response.fromBlockQueried,
|
|
192
|
+
toBlock: response.latestFetchedBlockNumber,
|
|
193
|
+
numEvents: response.parsedQueueItems.length
|
|
194
|
+
};
|
|
195
|
+
if (dispatchedCount > 0 && fetchedCount.contents === dispatchedCount) {
|
|
196
|
+
Logging.trace({
|
|
197
|
+
msg: "Finished querying",
|
|
198
|
+
chainId: chain,
|
|
199
|
+
partitions: fetchedByPartition
|
|
200
|
+
});
|
|
201
|
+
}
|
|
183
202
|
return await onQueryResponse(state, {
|
|
184
203
|
chain: chain,
|
|
185
204
|
response: response,
|
package/src/ChainState.res
CHANGED
|
@@ -21,8 +21,6 @@ type t = {
|
|
|
21
21
|
// transactionIndex). Fetch responses merge their page in; entries are pruned
|
|
22
22
|
// as the chain progresses and dropped above the target on rollback.
|
|
23
23
|
transactionStore: TransactionStore.t,
|
|
24
|
-
// Bitmask of the transaction fields the store materialises at batch prep.
|
|
25
|
-
transactionFieldMask: float,
|
|
26
24
|
}
|
|
27
25
|
|
|
28
26
|
// Per-chain shape returned by the status API.
|
|
@@ -67,7 +65,6 @@ let make = (
|
|
|
67
65
|
~numEventsProcessed=0.,
|
|
68
66
|
~timestampCaughtUpToHeadOrEndblock=None,
|
|
69
67
|
~isProgressAtHead=false,
|
|
70
|
-
~transactionFieldMask=0.,
|
|
71
68
|
~logger: Pino.t,
|
|
72
69
|
): t => {
|
|
73
70
|
logger,
|
|
@@ -82,7 +79,6 @@ let make = (
|
|
|
82
79
|
reorgDetection,
|
|
83
80
|
safeCheckpointTracking,
|
|
84
81
|
transactionStore: TransactionStore.make(),
|
|
85
|
-
transactionFieldMask,
|
|
86
82
|
}
|
|
87
83
|
|
|
88
84
|
let makeInternal = (
|
|
@@ -328,7 +324,6 @@ let makeInternal = (
|
|
|
328
324
|
~committedProgressBlockNumber=progressBlockNumber,
|
|
329
325
|
~timestampCaughtUpToHeadOrEndblock,
|
|
330
326
|
~numEventsProcessed,
|
|
331
|
-
~transactionFieldMask=config.ecosystem.transactionFieldMask(eventConfigs),
|
|
332
327
|
~logger,
|
|
333
328
|
)
|
|
334
329
|
}
|
|
@@ -503,18 +498,14 @@ let isAtHeadWithoutEndBlock = (cs: t) =>
|
|
|
503
498
|
// Materialise the chain store's selected transaction fields onto a batch's
|
|
504
499
|
// items at batch prep (the persistent-store path).
|
|
505
500
|
let materializeBatchItems = (cs: t, ~items: array<Internal.item>) =>
|
|
506
|
-
cs.transactionStore->TransactionStore.materializeItems(~items
|
|
501
|
+
cs.transactionStore->TransactionStore.materializeItems(~items)
|
|
507
502
|
|
|
508
503
|
// Materialise a fetch-response page's transactions onto its items before
|
|
509
504
|
// contract-register handlers read them. `None` pages (RPC/Fuel/Simulate keep the
|
|
510
505
|
// transaction inline) are a no-op.
|
|
511
|
-
let materializePageItems = (
|
|
512
|
-
cs: t,
|
|
513
|
-
~items: array<Internal.item>,
|
|
514
|
-
~page: option<TransactionStore.t>,
|
|
515
|
-
) =>
|
|
506
|
+
let materializePageItems = (~items: array<Internal.item>, ~page: option<TransactionStore.t>) =>
|
|
516
507
|
switch page {
|
|
517
|
-
| Some(store) => store->TransactionStore.materializeItems(~items
|
|
508
|
+
| Some(store) => store->TransactionStore.materializeItems(~items)
|
|
518
509
|
| None => Promise.resolve()
|
|
519
510
|
}
|
|
520
511
|
|
package/src/ChainState.res.mjs
CHANGED
|
@@ -38,12 +38,11 @@ function configAddresses(chainConfig) {
|
|
|
38
38
|
return addresses;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
function make(chainConfig, fetchState, sourceManager, reorgDetection, committedProgressBlockNumber, safeCheckpointTrackingOpt, numEventsProcessedOpt, timestampCaughtUpToHeadOrEndblockOpt, isProgressAtHeadOpt,
|
|
41
|
+
function make(chainConfig, fetchState, sourceManager, reorgDetection, committedProgressBlockNumber, safeCheckpointTrackingOpt, numEventsProcessedOpt, timestampCaughtUpToHeadOrEndblockOpt, isProgressAtHeadOpt, logger) {
|
|
42
42
|
let safeCheckpointTracking = safeCheckpointTrackingOpt !== undefined ? Primitive_option.valFromOption(safeCheckpointTrackingOpt) : undefined;
|
|
43
43
|
let numEventsProcessed = numEventsProcessedOpt !== undefined ? numEventsProcessedOpt : 0;
|
|
44
44
|
let timestampCaughtUpToHeadOrEndblock = timestampCaughtUpToHeadOrEndblockOpt !== undefined ? Primitive_option.valFromOption(timestampCaughtUpToHeadOrEndblockOpt) : undefined;
|
|
45
45
|
let isProgressAtHead = isProgressAtHeadOpt !== undefined ? isProgressAtHeadOpt : false;
|
|
46
|
-
let transactionFieldMask = transactionFieldMaskOpt !== undefined ? transactionFieldMaskOpt : 0;
|
|
47
46
|
return {
|
|
48
47
|
logger: logger,
|
|
49
48
|
fetchState: fetchState,
|
|
@@ -56,8 +55,7 @@ function make(chainConfig, fetchState, sourceManager, reorgDetection, committedP
|
|
|
56
55
|
pendingBudget: 0,
|
|
57
56
|
reorgDetection: reorgDetection,
|
|
58
57
|
safeCheckpointTracking: safeCheckpointTracking,
|
|
59
|
-
transactionStore: TransactionStore.make()
|
|
60
|
-
transactionFieldMask: transactionFieldMask
|
|
58
|
+
transactionStore: TransactionStore.make()
|
|
61
59
|
};
|
|
62
60
|
}
|
|
63
61
|
|
|
@@ -176,7 +174,7 @@ function makeInternal(chainConfig, indexingAddresses, startBlock, endBlock, firs
|
|
|
176
174
|
sources$1 = sources._0;
|
|
177
175
|
break;
|
|
178
176
|
}
|
|
179
|
-
return make(chainConfig, fetchState, SourceManager.make(sources$1, isRealtime, undefined, undefined, undefined, reducedPollingInterval, undefined, undefined), ReorgDetection.make(chainReorgCheckpoints, maxReorgDepth, config.shouldRollbackOnReorg), progressBlockNumber, Primitive_option.some(SafeCheckpointTracking.make(maxReorgDepth, config.shouldRollbackOnReorg, chainReorgCheckpoints)), numEventsProcessed, Primitive_option.some(timestampCaughtUpToHeadOrEndblock), undefined,
|
|
177
|
+
return make(chainConfig, fetchState, SourceManager.make(sources$1, isRealtime, undefined, undefined, undefined, reducedPollingInterval, undefined, undefined), ReorgDetection.make(chainReorgCheckpoints, maxReorgDepth, config.shouldRollbackOnReorg), progressBlockNumber, Primitive_option.some(SafeCheckpointTracking.make(maxReorgDepth, config.shouldRollbackOnReorg, chainReorgCheckpoints)), numEventsProcessed, Primitive_option.some(timestampCaughtUpToHeadOrEndblock), undefined, logger);
|
|
180
178
|
}
|
|
181
179
|
|
|
182
180
|
function makeFromConfig(chainConfig, config, registrations, knownHeight) {
|
|
@@ -326,12 +324,12 @@ function isAtHeadWithoutEndBlock(cs) {
|
|
|
326
324
|
}
|
|
327
325
|
|
|
328
326
|
function materializeBatchItems(cs, items) {
|
|
329
|
-
return TransactionStore.materializeItems(cs.transactionStore, items
|
|
327
|
+
return TransactionStore.materializeItems(cs.transactionStore, items);
|
|
330
328
|
}
|
|
331
329
|
|
|
332
|
-
function materializePageItems(
|
|
330
|
+
function materializePageItems(items, page) {
|
|
333
331
|
if (page !== undefined) {
|
|
334
|
-
return TransactionStore.materializeItems(Primitive_option.valFromOption(page), items
|
|
332
|
+
return TransactionStore.materializeItems(Primitive_option.valFromOption(page), items);
|
|
335
333
|
} else {
|
|
336
334
|
return Promise.resolve();
|
|
337
335
|
}
|
package/src/ChainState.resi
CHANGED
|
@@ -15,7 +15,6 @@ let make: (
|
|
|
15
15
|
~numEventsProcessed: float=?,
|
|
16
16
|
~timestampCaughtUpToHeadOrEndblock: option<Date.t>=?,
|
|
17
17
|
~isProgressAtHead: bool=?,
|
|
18
|
-
~transactionFieldMask: float=?,
|
|
19
18
|
~logger: Pino.t,
|
|
20
19
|
) => t
|
|
21
20
|
|
|
@@ -112,7 +111,6 @@ let handleQueryResult: (
|
|
|
112
111
|
) => unit
|
|
113
112
|
let materializeBatchItems: (t, ~items: array<Internal.item>) => promise<unit>
|
|
114
113
|
let materializePageItems: (
|
|
115
|
-
t,
|
|
116
114
|
~items: array<Internal.item>,
|
|
117
115
|
~page: option<TransactionStore.t>,
|
|
118
116
|
) => promise<unit>
|
package/src/CrossChainState.res
CHANGED
|
@@ -254,6 +254,21 @@ let checkAndFetch = async (
|
|
|
254
254
|
idx := idx.contents + 1
|
|
255
255
|
}
|
|
256
256
|
admittedByChain->Dict.forEachWithKey((queries, chainId) => {
|
|
257
|
+
let partitions = Dict.make()
|
|
258
|
+
queries->Array.forEach((query: FetchState.query) =>
|
|
259
|
+
partitions->Dict.set(
|
|
260
|
+
query.partitionId,
|
|
261
|
+
{
|
|
262
|
+
"fromBlock": query.fromBlock,
|
|
263
|
+
"targetBlock": query.toBlock,
|
|
264
|
+
},
|
|
265
|
+
)
|
|
266
|
+
)
|
|
267
|
+
Logging.trace({
|
|
268
|
+
"msg": "Started querying",
|
|
269
|
+
"chainId": chainId->Int.fromString->Option.getUnsafe,
|
|
270
|
+
"partitions": partitions,
|
|
271
|
+
})
|
|
257
272
|
actionByChain->Dict.set(chainId, FetchState.Ready(queries))
|
|
258
273
|
// Mark the admitted queries in flight and reserve their size against the
|
|
259
274
|
// shared budget; released as each response lands in handleQueryResult.
|
|
@@ -170,6 +170,18 @@ async function checkAndFetch(crossChainState, dispatchChain) {
|
|
|
170
170
|
idx = idx + 1 | 0;
|
|
171
171
|
};
|
|
172
172
|
Stdlib_Dict.forEachWithKey(admittedByChain, (queries, chainId) => {
|
|
173
|
+
let partitions = {};
|
|
174
|
+
queries.forEach(query => {
|
|
175
|
+
partitions[query.partitionId] = {
|
|
176
|
+
fromBlock: query.fromBlock,
|
|
177
|
+
targetBlock: query.toBlock
|
|
178
|
+
};
|
|
179
|
+
});
|
|
180
|
+
Logging.trace({
|
|
181
|
+
msg: "Started querying",
|
|
182
|
+
chainId: Stdlib_Int.fromString(chainId, undefined),
|
|
183
|
+
partitions: partitions
|
|
184
|
+
});
|
|
173
185
|
actionByChain[chainId] = {
|
|
174
186
|
TAG: "Ready",
|
|
175
187
|
_0: queries
|
package/src/Ecosystem.res
CHANGED
|
@@ -2,8 +2,6 @@ type name = | @as("evm") Evm | @as("fuel") Fuel | @as("svm") Svm
|
|
|
2
2
|
|
|
3
3
|
type t = {
|
|
4
4
|
name: name,
|
|
5
|
-
blockFields: array<string>,
|
|
6
|
-
transactionFields: array<string>,
|
|
7
5
|
blockNumberName: string,
|
|
8
6
|
blockTimestampName: string,
|
|
9
7
|
blockHashName: string,
|
|
@@ -36,10 +34,6 @@ type t = {
|
|
|
36
34
|
registration from an item's opaque payload. `event.transaction` is written
|
|
37
35
|
onto the payload at batch prep (HyperSync) or inline (RPC/simulate). */
|
|
38
36
|
toEvent: Internal.eventItem => Internal.event,
|
|
39
|
-
/** Bitmask (as a float) of the transaction fields selected across the chain's
|
|
40
|
-
events — the set the store materialises at batch prep. `0.` when the
|
|
41
|
-
ecosystem carries transactions inline. */
|
|
42
|
-
transactionFieldMask: array<Internal.eventConfig> => float,
|
|
43
37
|
/** Build the per-item child logger for an event item, with
|
|
44
38
|
ecosystem-specific log fields (EVM/Fuel: contract/event/address; SVM:
|
|
45
39
|
program/instruction/programId). Closes over the injected logger. */
|
|
@@ -326,28 +326,50 @@ let compileAddressFilter: string => (
|
|
|
326
326
|
return new Function("event", "blockNumber", "indexingAddresses", body);
|
|
327
327
|
}`)
|
|
328
328
|
|
|
329
|
-
// Body of the client-side address filter
|
|
330
|
-
//
|
|
331
|
-
// registered
|
|
332
|
-
//
|
|
333
|
-
//
|
|
334
|
-
|
|
335
|
-
|
|
329
|
+
// Body of the client-side address filter. Two analogous registered-at-or-before
|
|
330
|
+
// checks, ANDed: (1) for non-wildcard events, the log's srcAddress must itself be
|
|
331
|
+
// registered (ownership is resolved structurally by partition, but the temporal
|
|
332
|
+
// `effectiveStartBlock` gate lives here now); (2) a DNF of address-filtered param
|
|
333
|
+
// names (OR of AND-groups) for events that filter an indexed address param. The
|
|
334
|
+
// DNF is fixed here, so it's unrolled into one boolean expression — no per-event
|
|
335
|
+
// closure, loop, or array. `None` only for wildcard events without a param
|
|
336
|
+
// filter. Exposed for snapshotting.
|
|
337
|
+
// `srcAddressExpr` is the JS expression for the event's owning address: EVM and
|
|
338
|
+
// Fuel events expose `event.srcAddress`; SVM instructions expose `event.programId`.
|
|
339
|
+
let buildAddressFilterBody = (
|
|
340
|
+
groups: array<array<string>>,
|
|
341
|
+
~isWildcard: bool,
|
|
342
|
+
~srcAddressExpr: string="event.srcAddress",
|
|
343
|
+
): option<string> => {
|
|
344
|
+
let paramLeaf = name =>
|
|
345
|
+
`(ic = indexingAddresses[p[${JSON.stringify(
|
|
346
|
+
JSON.String(name),
|
|
347
|
+
)}]]) !== undefined && ic.effectiveStartBlock <= blockNumber`
|
|
348
|
+
let paramDnf = switch groups {
|
|
336
349
|
| [] => None
|
|
337
350
|
| _ =>
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
351
|
+
Some(
|
|
352
|
+
groups
|
|
353
|
+
->Array.map(group => "(" ++ group->Array.map(paramLeaf)->Array.join(" && ") ++ ")")
|
|
354
|
+
->Array.join(" || "),
|
|
355
|
+
)
|
|
356
|
+
}
|
|
357
|
+
let srcLeaf = `(ic = indexingAddresses[${srcAddressExpr}]) !== undefined && ic.effectiveStartBlock <= blockNumber`
|
|
358
|
+
switch (isWildcard, paramDnf) {
|
|
359
|
+
| (true, None) => None
|
|
360
|
+
| (true, Some(dnf)) => Some("var p = event.params, ic; return " ++ dnf ++ ";")
|
|
361
|
+
| (false, None) => Some("var ic; return " ++ srcLeaf ++ ";")
|
|
362
|
+
| (false, Some(dnf)) =>
|
|
363
|
+
Some("var p = event.params, ic; return " ++ srcLeaf ++ " && (" ++ dnf ++ ");")
|
|
345
364
|
}
|
|
346
365
|
}
|
|
347
366
|
|
|
348
|
-
let buildAddressFilter = (
|
|
349
|
-
|
|
350
|
-
|
|
367
|
+
let buildAddressFilter = (
|
|
368
|
+
groups: array<array<string>>,
|
|
369
|
+
~isWildcard: bool,
|
|
370
|
+
~srcAddressExpr: string="event.srcAddress",
|
|
371
|
+
): option<(Internal.eventPayload, int, dict<Internal.indexingContract>) => bool> =>
|
|
372
|
+
buildAddressFilterBody(groups, ~isWildcard, ~srcAddressExpr)->Option.map(compileAddressFilter)
|
|
351
373
|
|
|
352
374
|
// ============== Build complete EVM event config ==============
|
|
353
375
|
|
|
@@ -415,11 +437,12 @@ let buildEvmEventConfig = (
|
|
|
415
437
|
simulateParamsSchema: buildSimulateParamsSchema(params),
|
|
416
438
|
getEventFiltersOrThrow,
|
|
417
439
|
filterByAddresses,
|
|
418
|
-
clientAddressFilter: ?buildAddressFilter(addressFilterParamGroups),
|
|
440
|
+
clientAddressFilter: ?buildAddressFilter(addressFilterParamGroups, ~isWildcard),
|
|
419
441
|
dependsOnAddresses: !isWildcard || filterByAddresses,
|
|
420
442
|
startBlock: resolvedStartBlock,
|
|
421
443
|
selectedBlockFields,
|
|
422
444
|
selectedTransactionFields,
|
|
445
|
+
transactionFieldMask: Evm.eventTransactionFieldMask(selectedTransactionFields),
|
|
423
446
|
sighash,
|
|
424
447
|
topicCount,
|
|
425
448
|
paramsMetadata: params,
|
|
@@ -471,12 +494,14 @@ let buildSvmInstructionEventConfig = (
|
|
|
471
494
|
simulateParamsSchema: paramsSchema,
|
|
472
495
|
filterByAddresses: false,
|
|
473
496
|
dependsOnAddresses: !isWildcard,
|
|
497
|
+
clientAddressFilter: ?buildAddressFilter([], ~isWildcard, ~srcAddressExpr="event.programId"),
|
|
474
498
|
startBlock,
|
|
475
499
|
programId,
|
|
476
500
|
discriminator,
|
|
477
501
|
discriminatorByteLen,
|
|
478
502
|
includeLogs,
|
|
479
503
|
selectedTransactionFields,
|
|
504
|
+
transactionFieldMask: Svm.eventTransactionFieldMask(selectedTransactionFields),
|
|
480
505
|
accountFilters,
|
|
481
506
|
isInner,
|
|
482
507
|
accounts,
|
|
@@ -541,9 +566,11 @@ let buildFuelEventConfig = (
|
|
|
541
566
|
simulateParamsSchema: paramsSchema,
|
|
542
567
|
filterByAddresses: false,
|
|
543
568
|
dependsOnAddresses: !isWildcard,
|
|
569
|
+
clientAddressFilter: ?buildAddressFilter([], ~isWildcard),
|
|
544
570
|
startBlock,
|
|
545
571
|
// Fuel keeps the transaction inline on the payload; nothing to materialise.
|
|
546
572
|
selectedTransactionFields: Utils.Set.make(),
|
|
573
|
+
transactionFieldMask: 0.,
|
|
547
574
|
kind: fuelKind,
|
|
548
575
|
}
|
|
549
576
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
+
import * as Evm from "./sources/Evm.res.mjs";
|
|
4
|
+
import * as Svm from "./sources/Svm.res.mjs";
|
|
3
5
|
import * as Utils from "./Utils.res.mjs";
|
|
4
6
|
import * as Address from "./Address.res.mjs";
|
|
5
7
|
import * as FuelSDK from "./sources/FuelSDK.res.mjs";
|
|
@@ -255,17 +257,27 @@ let compileAddressFilter = (function (body) {
|
|
|
255
257
|
return new Function("event", "blockNumber", "indexingAddresses", body);
|
|
256
258
|
});
|
|
257
259
|
|
|
258
|
-
function buildAddressFilterBody(groups) {
|
|
259
|
-
|
|
260
|
-
|
|
260
|
+
function buildAddressFilterBody(groups, isWildcard, srcAddressExprOpt) {
|
|
261
|
+
let srcAddressExpr = srcAddressExprOpt !== undefined ? srcAddressExprOpt : "event.srcAddress";
|
|
262
|
+
let paramLeaf = name => `(ic = indexingAddresses[p[` + JSON.stringify(name) + `]]) !== undefined && ic.effectiveStartBlock <= blockNumber`;
|
|
263
|
+
let paramDnf = groups.length !== 0 ? groups.map(group => "(" + group.map(paramLeaf).join(" && ") + ")").join(" || ") : undefined;
|
|
264
|
+
let srcLeaf = `(ic = indexingAddresses[` + srcAddressExpr + `]) !== undefined && ic.effectiveStartBlock <= blockNumber`;
|
|
265
|
+
if (isWildcard) {
|
|
266
|
+
if (paramDnf !== undefined) {
|
|
267
|
+
return "var p = event.params, ic; return " + paramDnf + ";";
|
|
268
|
+
} else {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
} else if (paramDnf !== undefined) {
|
|
272
|
+
return "var p = event.params, ic; return " + srcLeaf + " && (" + paramDnf + ");";
|
|
273
|
+
} else {
|
|
274
|
+
return "var ic; return " + srcLeaf + ";";
|
|
261
275
|
}
|
|
262
|
-
let leaf = name => `(ic = indexingAddresses[p[` + JSON.stringify(name) + `]]) !== undefined && ic.effectiveStartBlock <= blockNumber`;
|
|
263
|
-
let groupExprs = groups.map(group => "(" + group.map(leaf).join(" && ") + ")");
|
|
264
|
-
return "var p = event.params, ic; return " + groupExprs.join(" || ") + ";";
|
|
265
276
|
}
|
|
266
277
|
|
|
267
|
-
function buildAddressFilter(groups) {
|
|
268
|
-
|
|
278
|
+
function buildAddressFilter(groups, isWildcard, srcAddressExprOpt) {
|
|
279
|
+
let srcAddressExpr = srcAddressExprOpt !== undefined ? srcAddressExprOpt : "event.srcAddress";
|
|
280
|
+
return Stdlib_Option.map(buildAddressFilterBody(groups, isWildcard, srcAddressExpr), compileAddressFilter);
|
|
269
281
|
}
|
|
270
282
|
|
|
271
283
|
function buildEvmEventConfig(contractName, eventName, sighash, params, isWildcard, handler, contractRegister, eventFilters, probeChainId, onEventBlockFilterSchema, blockFields, transactionFields, startBlock, globalBlockFieldsSetOpt, globalTransactionFieldsSetOpt) {
|
|
@@ -284,6 +296,7 @@ function buildEvmEventConfig(contractName, eventName, sighash, params, isWildcar
|
|
|
284
296
|
let filterByAddresses = match.filterByAddresses;
|
|
285
297
|
let resolvedStartBlock = whereStartBlock !== undefined ? whereStartBlock : startBlock;
|
|
286
298
|
let match$1 = resolveFieldSelection(blockFields, transactionFields, globalBlockFieldsSet, globalTransactionFieldsSet);
|
|
299
|
+
let selectedTransactionFields = match$1[1];
|
|
287
300
|
return {
|
|
288
301
|
id: sighash + "_" + topicCount.toString(),
|
|
289
302
|
name: eventName,
|
|
@@ -291,13 +304,14 @@ function buildEvmEventConfig(contractName, eventName, sighash, params, isWildcar
|
|
|
291
304
|
isWildcard: isWildcard,
|
|
292
305
|
filterByAddresses: filterByAddresses,
|
|
293
306
|
dependsOnAddresses: !isWildcard || filterByAddresses,
|
|
294
|
-
clientAddressFilter:
|
|
307
|
+
clientAddressFilter: buildAddressFilter(match.addressFilterParamGroups, isWildcard, undefined),
|
|
295
308
|
handler: handler,
|
|
296
309
|
contractRegister: contractRegister,
|
|
297
310
|
paramsRawEventSchema: buildParamsSchema(params),
|
|
298
311
|
simulateParamsSchema: buildSimulateParamsSchema(params),
|
|
299
312
|
startBlock: resolvedStartBlock,
|
|
300
|
-
selectedTransactionFields:
|
|
313
|
+
selectedTransactionFields: selectedTransactionFields,
|
|
314
|
+
transactionFieldMask: Evm.eventTransactionFieldMask(selectedTransactionFields),
|
|
301
315
|
getEventFiltersOrThrow: match.getEventFiltersOrThrow,
|
|
302
316
|
selectedBlockFields: match$1[0],
|
|
303
317
|
sighash: sighash,
|
|
@@ -320,12 +334,14 @@ function buildSvmInstructionEventConfig(contractName, instructionName, programId
|
|
|
320
334
|
isWildcard: isWildcard,
|
|
321
335
|
filterByAddresses: false,
|
|
322
336
|
dependsOnAddresses: !isWildcard,
|
|
337
|
+
clientAddressFilter: buildAddressFilter([], isWildcard, "event.programId"),
|
|
323
338
|
handler: handler,
|
|
324
339
|
contractRegister: contractRegister,
|
|
325
340
|
paramsRawEventSchema: paramsSchema,
|
|
326
341
|
simulateParamsSchema: paramsSchema,
|
|
327
342
|
startBlock: startBlock,
|
|
328
343
|
selectedTransactionFields: selectedTransactionFields,
|
|
344
|
+
transactionFieldMask: Svm.eventTransactionFieldMask(selectedTransactionFields),
|
|
329
345
|
programId: programId,
|
|
330
346
|
discriminator: discriminator,
|
|
331
347
|
discriminatorByteLen: discriminatorByteLen,
|
|
@@ -388,12 +404,14 @@ function buildFuelEventConfig(contractName, eventName, kind, sighash, rawAbi, is
|
|
|
388
404
|
isWildcard: isWildcard,
|
|
389
405
|
filterByAddresses: false,
|
|
390
406
|
dependsOnAddresses: !isWildcard,
|
|
407
|
+
clientAddressFilter: buildAddressFilter([], isWildcard, undefined),
|
|
391
408
|
handler: handler,
|
|
392
409
|
contractRegister: contractRegister,
|
|
393
410
|
paramsRawEventSchema: paramsSchema,
|
|
394
411
|
simulateParamsSchema: paramsSchema,
|
|
395
412
|
startBlock: startBlock,
|
|
396
413
|
selectedTransactionFields: new Set(),
|
|
414
|
+
transactionFieldMask: 0,
|
|
397
415
|
kind: fuelKind
|
|
398
416
|
};
|
|
399
417
|
}
|