envio 3.3.0-alpha.1 → 3.3.0-alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/evm.schema.json +10 -0
- package/index.d.ts +45 -25
- package/licenses/CLA.md +35 -0
- package/licenses/EULA.md +67 -0
- package/licenses/LICENSE.md +45 -0
- package/licenses/README.md +35 -0
- package/package.json +10 -9
- package/src/Address.res +5 -2
- package/src/Address.res.mjs +3 -1
- package/src/Api.res +1 -1
- package/src/Api.res.mjs +1 -1
- package/src/Batch.res +0 -6
- package/src/Batch.res.mjs +1 -12
- package/src/BatchProcessing.res +7 -12
- package/src/BatchProcessing.res.mjs +8 -7
- package/src/Bin.res +3 -0
- package/src/Bin.res.mjs +4 -0
- package/src/ChainFetching.res +53 -16
- package/src/ChainFetching.res.mjs +37 -19
- package/src/ChainMetadata.res +1 -11
- package/src/ChainMetadata.res.mjs +1 -10
- package/src/ChainState.res +630 -161
- package/src/ChainState.res.mjs +438 -101
- package/src/ChainState.resi +77 -4
- package/src/Config.res +70 -38
- package/src/Config.res.mjs +52 -12
- package/src/ContractRegisterContext.res +2 -12
- package/src/ContractRegisterContext.res.mjs +3 -5
- package/src/Core.res +34 -3
- package/src/Core.res.mjs +12 -0
- package/src/CrossChainState.res +130 -89
- package/src/CrossChainState.res.mjs +66 -61
- package/src/CrossChainState.resi +1 -1
- package/src/Ecosystem.res +5 -6
- package/src/Ecosystem.res.mjs +3 -3
- package/src/Envio.res +17 -11
- package/src/EnvioGlobal.res +53 -0
- package/src/EnvioGlobal.res.mjs +31 -0
- package/src/EventConfigBuilder.res +191 -127
- package/src/EventConfigBuilder.res.mjs +116 -66
- package/src/EventProcessing.res +77 -28
- package/src/EventProcessing.res.mjs +56 -29
- package/src/ExitOnCaughtUp.res +10 -2
- package/src/ExitOnCaughtUp.res.mjs +10 -1
- package/src/FetchState.res +684 -415
- package/src/FetchState.res.mjs +505 -486
- package/src/HandlerLoader.res +8 -104
- package/src/HandlerLoader.res.mjs +2 -81
- package/src/HandlerRegister.res +520 -144
- package/src/HandlerRegister.res.mjs +286 -133
- package/src/HandlerRegister.resi +24 -8
- package/src/IndexerState.res +10 -3
- package/src/IndexerState.res.mjs +11 -4
- package/src/IndexerState.resi +2 -1
- package/src/IndexingAddresses.res +108 -0
- package/src/IndexingAddresses.res.mjs +101 -0
- package/src/IndexingAddresses.resi +34 -0
- package/src/Internal.res +166 -48
- package/src/Internal.res.mjs +30 -2
- package/src/LoadLayer.res +5 -5
- package/src/LoadLayer.res.mjs +6 -6
- package/src/LogSelection.res +92 -217
- package/src/LogSelection.res.mjs +95 -184
- package/src/Main.res +71 -236
- package/src/Main.res.mjs +60 -145
- package/src/Metrics.res +74 -0
- package/src/Metrics.res.mjs +75 -0
- package/src/PgStorage.res +4 -4
- package/src/PgStorage.res.mjs +5 -5
- package/src/Prometheus.res +10 -63
- package/src/Prometheus.res.mjs +124 -171
- package/src/PruneStaleHistory.res +2 -2
- package/src/PruneStaleHistory.res.mjs +3 -3
- package/src/RawEvent.res +7 -2
- package/src/RawEvent.res.mjs +4 -4
- package/src/Rollback.res +3 -3
- package/src/Rollback.res.mjs +4 -4
- package/src/RollbackCommit.res +4 -1
- package/src/RollbackCommit.res.mjs +3 -2
- package/src/SimulateDeadInputTracker.res +85 -0
- package/src/SimulateDeadInputTracker.res.mjs +73 -0
- package/src/SimulateDeadInputTracker.resi +12 -0
- package/src/SimulateItems.res +128 -28
- package/src/SimulateItems.res.mjs +82 -40
- package/src/TestIndexer.res +55 -41
- package/src/TestIndexer.res.mjs +39 -32
- package/src/TopicFilter.res +1 -25
- package/src/TopicFilter.res.mjs +0 -74
- package/src/bindings/Performance.res +7 -0
- package/src/bindings/Performance.res.mjs +21 -0
- package/src/bindings/Performance.resi +7 -0
- package/src/bindings/Viem.res +0 -46
- package/src/bindings/Viem.res.mjs +1 -43
- package/src/sources/BlockStore.res +46 -0
- package/src/sources/BlockStore.res.mjs +24 -0
- package/src/sources/EventRouter.res +31 -49
- package/src/sources/EventRouter.res.mjs +12 -25
- package/src/sources/Evm.res +83 -72
- package/src/sources/Evm.res.mjs +53 -69
- package/src/sources/EvmChain.res +7 -34
- package/src/sources/EvmChain.res.mjs +6 -27
- package/src/sources/EvmRpcClient.res +71 -5
- package/src/sources/EvmRpcClient.res.mjs +13 -4
- package/src/sources/FieldMask.res +39 -0
- package/src/sources/FieldMask.res.mjs +42 -0
- package/src/sources/Fuel.res +9 -6
- package/src/sources/Fuel.res.mjs +5 -10
- package/src/sources/HyperFuelSource.res +46 -50
- package/src/sources/HyperFuelSource.res.mjs +64 -54
- package/src/sources/HyperSync.res +45 -42
- package/src/sources/HyperSync.res.mjs +68 -60
- package/src/sources/HyperSync.resi +14 -4
- package/src/sources/HyperSyncClient.res +107 -119
- package/src/sources/HyperSyncClient.res.mjs +36 -31
- package/src/sources/HyperSyncHeightStream.res +1 -8
- package/src/sources/HyperSyncHeightStream.res.mjs +0 -2
- package/src/sources/HyperSyncSource.res +60 -254
- package/src/sources/HyperSyncSource.res.mjs +57 -180
- package/src/sources/Rpc.res +15 -79
- package/src/sources/Rpc.res.mjs +25 -101
- package/src/sources/RpcSource.res +221 -514
- package/src/sources/RpcSource.res.mjs +216 -411
- package/src/sources/RpcWebSocketHeightStream.res +0 -5
- package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -2
- package/src/sources/SimulateSource.res +44 -20
- package/src/sources/SimulateSource.res.mjs +41 -14
- package/src/sources/Source.res +34 -6
- package/src/sources/SourceManager.res +77 -19
- package/src/sources/SourceManager.res.mjs +63 -21
- package/src/sources/SourceManager.resi +10 -0
- package/src/sources/Svm.res +31 -16
- package/src/sources/Svm.res.mjs +36 -13
- package/src/sources/SvmHyperSyncClient.res +5 -32
- package/src/sources/SvmHyperSyncSource.res +159 -134
- package/src/sources/SvmHyperSyncSource.res.mjs +164 -129
- package/src/sources/TransactionStore.res +49 -0
- package/src/sources/TransactionStore.res.mjs +30 -0
- package/src/tui/Tui.res +13 -16
- package/src/tui/Tui.res.mjs +12 -14
- package/svm.schema.json +49 -37
- package/src/bindings/Hrtime.res +0 -58
- package/src/bindings/Hrtime.res.mjs +0 -90
- package/src/bindings/Hrtime.resi +0 -30
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Utils from "./Utils.res.mjs";
|
|
4
|
+
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
5
|
+
|
|
6
|
+
let version = Utils.EnvioPackage.value.version;
|
|
7
|
+
|
|
8
|
+
let existing = globalThis.__envioGlobal;
|
|
9
|
+
|
|
10
|
+
let value;
|
|
11
|
+
|
|
12
|
+
if (existing == null) {
|
|
13
|
+
let fresh = {
|
|
14
|
+
version: version,
|
|
15
|
+
eventRegistrations: {},
|
|
16
|
+
activeRegistration: undefined,
|
|
17
|
+
preRegistered: [],
|
|
18
|
+
rollbackCommitCallbacks: [],
|
|
19
|
+
indexerState: undefined,
|
|
20
|
+
persistence: undefined
|
|
21
|
+
};
|
|
22
|
+
globalThis.__envioGlobal = fresh;
|
|
23
|
+
value = fresh;
|
|
24
|
+
} else {
|
|
25
|
+
value = existing.version === version ? existing : Stdlib_JsError.throwWithMessage(`Multiple incompatible envio versions loaded in the same process: ` + existing.version + ` and ` + version + `. Deduplicate the 'envio' dependency in your project.`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export {
|
|
29
|
+
value,
|
|
30
|
+
}
|
|
31
|
+
/* existing Not a pure module */
|
|
@@ -236,54 +236,30 @@ let buildSimulateParamsSchema = (params: array<paramMeta>): S.t<Internal.eventPa
|
|
|
236
236
|
|
|
237
237
|
// ============== Build topic filter getters ==============
|
|
238
238
|
|
|
239
|
-
let getTopicEncoder = (abiType: string): (unknown => EvmTypes.Hex.t) =>
|
|
240
|
-
|
|
241
|
-
if abiType->String.endsWith("]") || abiType->String.startsWith("(") {
|
|
242
|
-
TopicFilter.castToHexUnsafe->(Utils.magic: ('a => EvmTypes.Hex.t) => unknown => EvmTypes.Hex.t)
|
|
243
|
-
} else {
|
|
244
|
-
switch abiType {
|
|
245
|
-
| "address" =>
|
|
246
|
-
TopicFilter.fromAddress->(
|
|
247
|
-
Utils.magic: (Address.t => EvmTypes.Hex.t) => unknown => EvmTypes.Hex.t
|
|
248
|
-
)
|
|
249
|
-
|
|
250
|
-
| "bool" =>
|
|
251
|
-
TopicFilter.fromBool->(Utils.magic: (bool => EvmTypes.Hex.t) => unknown => EvmTypes.Hex.t)
|
|
252
|
-
| "string" =>
|
|
253
|
-
TopicFilter.fromDynamicString->(
|
|
254
|
-
Utils.magic: (string => EvmTypes.Hex.t) => unknown => EvmTypes.Hex.t
|
|
255
|
-
)
|
|
256
|
-
|
|
257
|
-
| "bytes" =>
|
|
258
|
-
TopicFilter.fromDynamicBytes->(
|
|
259
|
-
Utils.magic: (string => EvmTypes.Hex.t) => unknown => EvmTypes.Hex.t
|
|
260
|
-
)
|
|
261
|
-
|
|
262
|
-
| t if t->String.startsWith("uint") =>
|
|
263
|
-
TopicFilter.fromBigInt->(Utils.magic: (bigint => EvmTypes.Hex.t) => unknown => EvmTypes.Hex.t)
|
|
264
|
-
| t if t->String.startsWith("int") =>
|
|
265
|
-
TopicFilter.fromSignedBigInt->(
|
|
266
|
-
Utils.magic: (bigint => EvmTypes.Hex.t) => unknown => EvmTypes.Hex.t
|
|
267
|
-
)
|
|
268
|
-
|
|
269
|
-
| t if t->String.startsWith("bytes") =>
|
|
270
|
-
TopicFilter.castToHexUnsafe->(
|
|
271
|
-
Utils.magic: ('a => EvmTypes.Hex.t) => unknown => EvmTypes.Hex.t
|
|
272
|
-
)
|
|
273
|
-
|
|
274
|
-
| other => JsError.throwWithMessage(`Unsupported topic filter ABI type: ${other}`)
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
239
|
+
let getTopicEncoder = (abiType: string): (unknown => EvmTypes.Hex.t) => value =>
|
|
240
|
+
Core.getAddon().encodeIndexedTopic(~abiType, ~value)
|
|
278
241
|
|
|
279
242
|
let buildTopicGetter = (p: paramMeta) => {
|
|
280
243
|
let encoder = getTopicEncoder(p.abiType)
|
|
244
|
+
let isTuple = p.abiType->String.startsWith("(")
|
|
281
245
|
(eventFilter: dict<JSON.t>) =>
|
|
282
246
|
eventFilter
|
|
283
247
|
->Utils.Dict.dangerouslyGetNonOption(p.name)
|
|
284
|
-
->Option.mapOr([], topicFilters =>
|
|
285
|
-
topicFilters->(Utils.magic: JSON.t => unknown)
|
|
286
|
-
|
|
248
|
+
->Option.mapOr([], topicFilters => {
|
|
249
|
+
let raw = topicFilters->(Utils.magic: JSON.t => unknown)
|
|
250
|
+
// A tuple filter value is itself an array, so a directly-passed tuple is
|
|
251
|
+
// indistinguishable from an OR-list by shape alone. A single tuple is
|
|
252
|
+
// the common case, so try it first; when the value doesn't ABI-encode as
|
|
253
|
+
// one tuple it must be an OR-list of tuples.
|
|
254
|
+
if isTuple {
|
|
255
|
+
switch encoder(raw) {
|
|
256
|
+
| encoded => [encoded]
|
|
257
|
+
| exception _ => raw->normalizeOrThrow->Array.map(encoder)
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
raw->normalizeOrThrow->Array.map(encoder)
|
|
261
|
+
}
|
|
262
|
+
})
|
|
287
263
|
}
|
|
288
264
|
|
|
289
265
|
// ============== Field selection ==============
|
|
@@ -306,7 +282,14 @@ let resolveFieldSelection = (
|
|
|
306
282
|
| Some(fields) => Utils.Set.fromArray(fields)
|
|
307
283
|
| None => globalTransactionFieldsSet
|
|
308
284
|
}
|
|
309
|
-
(
|
|
285
|
+
// The base eventConfig stores these as a string set (field names match the
|
|
286
|
+
// typed variants at runtime).
|
|
287
|
+
(
|
|
288
|
+
selectedBlockFields,
|
|
289
|
+
selectedTransactionFields->(
|
|
290
|
+
Utils.magic: Utils.Set.t<Internal.evmTransactionField> => Utils.Set.t<string>
|
|
291
|
+
),
|
|
292
|
+
)
|
|
310
293
|
}
|
|
311
294
|
|
|
312
295
|
// ============== Client-side address filter ==============
|
|
@@ -319,28 +302,50 @@ let compileAddressFilter: string => (
|
|
|
319
302
|
return new Function("event", "blockNumber", "indexingAddresses", body);
|
|
320
303
|
}`)
|
|
321
304
|
|
|
322
|
-
// Body of the client-side address filter
|
|
323
|
-
//
|
|
324
|
-
// registered
|
|
325
|
-
//
|
|
326
|
-
//
|
|
327
|
-
|
|
328
|
-
|
|
305
|
+
// Body of the client-side address filter. Two analogous registered-at-or-before
|
|
306
|
+
// checks, ANDed: (1) for non-wildcard events, the log's srcAddress must itself be
|
|
307
|
+
// registered (ownership is resolved structurally by partition, but the temporal
|
|
308
|
+
// `effectiveStartBlock` gate lives here now); (2) a DNF of address-filtered param
|
|
309
|
+
// names (OR of AND-groups) for events that filter an indexed address param. The
|
|
310
|
+
// DNF is fixed here, so it's unrolled into one boolean expression — no per-event
|
|
311
|
+
// closure, loop, or array. `None` only for wildcard events without a param
|
|
312
|
+
// filter. Exposed for snapshotting.
|
|
313
|
+
// `srcAddressExpr` is the JS expression for the event's owning address: EVM and
|
|
314
|
+
// Fuel events expose `event.srcAddress`; SVM instructions expose `event.programId`.
|
|
315
|
+
let buildAddressFilterBody = (
|
|
316
|
+
groups: array<array<string>>,
|
|
317
|
+
~isWildcard: bool,
|
|
318
|
+
~srcAddressExpr: string="event.srcAddress",
|
|
319
|
+
): option<string> => {
|
|
320
|
+
let paramLeaf = name =>
|
|
321
|
+
`(ic = indexingAddresses[p[${JSON.stringify(
|
|
322
|
+
JSON.String(name),
|
|
323
|
+
)}]]) !== undefined && ic.effectiveStartBlock <= blockNumber`
|
|
324
|
+
let paramDnf = switch groups {
|
|
329
325
|
| [] => None
|
|
330
326
|
| _ =>
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
327
|
+
Some(
|
|
328
|
+
groups
|
|
329
|
+
->Array.map(group => "(" ++ group->Array.map(paramLeaf)->Array.join(" && ") ++ ")")
|
|
330
|
+
->Array.join(" || "),
|
|
331
|
+
)
|
|
332
|
+
}
|
|
333
|
+
let srcLeaf = `(ic = indexingAddresses[${srcAddressExpr}]) !== undefined && ic.effectiveStartBlock <= blockNumber`
|
|
334
|
+
switch (isWildcard, paramDnf) {
|
|
335
|
+
| (true, None) => None
|
|
336
|
+
| (true, Some(dnf)) => Some("var p = event.params, ic; return " ++ dnf ++ ";")
|
|
337
|
+
| (false, None) => Some("var ic; return " ++ srcLeaf ++ ";")
|
|
338
|
+
| (false, Some(dnf)) =>
|
|
339
|
+
Some("var p = event.params, ic; return " ++ srcLeaf ++ " && (" ++ dnf ++ ");")
|
|
338
340
|
}
|
|
339
341
|
}
|
|
340
342
|
|
|
341
|
-
let buildAddressFilter = (
|
|
342
|
-
|
|
343
|
-
|
|
343
|
+
let buildAddressFilter = (
|
|
344
|
+
groups: array<array<string>>,
|
|
345
|
+
~isWildcard: bool,
|
|
346
|
+
~srcAddressExpr: string="event.srcAddress",
|
|
347
|
+
): option<(Internal.eventPayload, int, dict<Internal.indexingContract>) => bool> =>
|
|
348
|
+
buildAddressFilterBody(groups, ~isWildcard, ~srcAddressExpr)->Option.map(compileAddressFilter)
|
|
344
349
|
|
|
345
350
|
// ============== Build complete EVM event config ==============
|
|
346
351
|
|
|
@@ -349,46 +354,12 @@ let buildEvmEventConfig = (
|
|
|
349
354
|
~eventName: string,
|
|
350
355
|
~sighash: string,
|
|
351
356
|
~params: array<paramMeta>,
|
|
352
|
-
~isWildcard: bool,
|
|
353
|
-
~handler: option<Internal.handler>,
|
|
354
|
-
~contractRegister: option<Internal.contractRegister>,
|
|
355
|
-
~eventFilters: option<JSON.t>,
|
|
356
|
-
~probeChainId: int,
|
|
357
|
-
~onEventBlockFilterSchema: S.t<option<unknown>>,
|
|
358
357
|
~blockFields: option<array<Internal.evmBlockField>>=?,
|
|
359
358
|
~transactionFields: option<array<Internal.evmTransactionField>>=?,
|
|
360
|
-
~startBlock: option<int>=?,
|
|
361
359
|
~globalBlockFieldsSet: Utils.Set.t<Internal.evmBlockField>=Utils.Set.make(),
|
|
362
360
|
~globalTransactionFieldsSet: Utils.Set.t<Internal.evmTransactionField>=Utils.Set.make(),
|
|
363
361
|
): Internal.evmEventConfig => {
|
|
364
362
|
let topicCount = params->Array.reduce(1, (acc, p) => p.indexed ? acc + 1 : acc)
|
|
365
|
-
let indexedParams = params->Array.filter(p => p.indexed)
|
|
366
|
-
|
|
367
|
-
let {
|
|
368
|
-
getEventFiltersOrThrow,
|
|
369
|
-
filterByAddresses,
|
|
370
|
-
addressFilterParamGroups,
|
|
371
|
-
startBlock: whereStartBlock,
|
|
372
|
-
} = LogSelection.parseEventFiltersOrThrow(
|
|
373
|
-
~eventFilters,
|
|
374
|
-
~sighash,
|
|
375
|
-
~params=indexedParams->Array.map(p => p.name),
|
|
376
|
-
~contractName,
|
|
377
|
-
~probeChainId,
|
|
378
|
-
~onEventBlockFilterSchema,
|
|
379
|
-
~topic1=?indexedParams->Array.get(0)->Option.map(buildTopicGetter),
|
|
380
|
-
~topic2=?indexedParams->Array.get(1)->Option.map(buildTopicGetter),
|
|
381
|
-
~topic3=?indexedParams->Array.get(2)->Option.map(buildTopicGetter),
|
|
382
|
-
)
|
|
383
|
-
|
|
384
|
-
// `where.block.number._gte` overrides the contract-level startBlock
|
|
385
|
-
// when present. The user opts into this explicitly in handler code so
|
|
386
|
-
// it should win over the `config.yaml` contract `start_block`; absent
|
|
387
|
-
// `where.block`, the caller's contract-level value passes through.
|
|
388
|
-
let resolvedStartBlock = switch whereStartBlock {
|
|
389
|
-
| Some(_) as sb => sb
|
|
390
|
-
| None => startBlock
|
|
391
|
-
}
|
|
392
363
|
|
|
393
364
|
let (selectedBlockFields, selectedTransactionFields) = resolveFieldSelection(
|
|
394
365
|
~blockFields,
|
|
@@ -401,25 +372,76 @@ let buildEvmEventConfig = (
|
|
|
401
372
|
id: sighash ++ "_" ++ topicCount->Int.toString,
|
|
402
373
|
name: eventName,
|
|
403
374
|
contractName,
|
|
404
|
-
isWildcard,
|
|
405
|
-
handler,
|
|
406
|
-
contractRegister,
|
|
407
375
|
paramsRawEventSchema: buildParamsSchema(params),
|
|
408
376
|
simulateParamsSchema: buildSimulateParamsSchema(params),
|
|
409
|
-
getEventFiltersOrThrow,
|
|
410
|
-
filterByAddresses,
|
|
411
|
-
clientAddressFilter: ?buildAddressFilter(addressFilterParamGroups),
|
|
412
|
-
dependsOnAddresses: !isWildcard || filterByAddresses,
|
|
413
|
-
startBlock: resolvedStartBlock,
|
|
414
377
|
selectedBlockFields,
|
|
415
378
|
selectedTransactionFields,
|
|
379
|
+
transactionFieldMask: Evm.eventTransactionFieldMask(selectedTransactionFields),
|
|
380
|
+
blockFieldMask: Evm.eventBlockFieldMask(
|
|
381
|
+
selectedBlockFields->(
|
|
382
|
+
Utils.magic: Utils.Set.t<Internal.evmBlockField> => Utils.Set.t<string>
|
|
383
|
+
),
|
|
384
|
+
),
|
|
416
385
|
sighash,
|
|
417
386
|
topicCount,
|
|
418
387
|
paramsMetadata: params,
|
|
419
388
|
}
|
|
420
389
|
}
|
|
421
390
|
|
|
422
|
-
//
|
|
391
|
+
// Enrich an EVM definition into a per-(event,chain) registration: resolve the
|
|
392
|
+
// registered `where` for this chain into `resolvedWhere` + address filters,
|
|
393
|
+
// and override `startBlock` with `where.block._gte`.
|
|
394
|
+
let buildEvmOnEventRegistration = (
|
|
395
|
+
~eventConfig: Internal.evmEventConfig,
|
|
396
|
+
~isWildcard: bool,
|
|
397
|
+
~handler: option<Internal.handler>,
|
|
398
|
+
~contractRegister: option<Internal.contractRegister>,
|
|
399
|
+
~where: option<JSON.t>,
|
|
400
|
+
~chainId: int,
|
|
401
|
+
~onEventBlockFilterSchema: S.t<option<unknown>>,
|
|
402
|
+
~startBlock: option<int>=?,
|
|
403
|
+
): Internal.evmOnEventRegistration => {
|
|
404
|
+
let indexedParams = eventConfig.paramsMetadata->Array.filter(p => p.indexed)
|
|
405
|
+
|
|
406
|
+
let {resolvedWhere, filterByAddresses, addressFilterParamGroups} = LogSelection.parseWhereOrThrow(
|
|
407
|
+
~where,
|
|
408
|
+
~sighash=eventConfig.sighash,
|
|
409
|
+
~params=indexedParams->Array.map(p => p.name),
|
|
410
|
+
~contractName=eventConfig.contractName,
|
|
411
|
+
~chainId,
|
|
412
|
+
~onEventBlockFilterSchema,
|
|
413
|
+
~topic1=?indexedParams->Array.get(0)->Option.map(buildTopicGetter),
|
|
414
|
+
~topic2=?indexedParams->Array.get(1)->Option.map(buildTopicGetter),
|
|
415
|
+
~topic3=?indexedParams->Array.get(2)->Option.map(buildTopicGetter),
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
// `where.block.number._gte` overrides the contract-level startBlock when
|
|
419
|
+
// present (an explicit per-event opt-in that wins over `config.yaml`);
|
|
420
|
+
// otherwise the contract/chain value passes through.
|
|
421
|
+
let resolvedStartBlock = switch resolvedWhere.startBlock {
|
|
422
|
+
| Some(_) as sb => sb
|
|
423
|
+
| None => startBlock
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
{
|
|
427
|
+
index: -1,
|
|
428
|
+
eventConfig: (eventConfig :> Internal.eventConfig),
|
|
429
|
+
isWildcard,
|
|
430
|
+
handler,
|
|
431
|
+
contractRegister,
|
|
432
|
+
resolvedWhere,
|
|
433
|
+
filterByAddresses,
|
|
434
|
+
clientAddressFilter: ?buildAddressFilter(addressFilterParamGroups, ~isWildcard),
|
|
435
|
+
dependsOnAddresses: Internal.dependsOnAddresses(~isWildcard, ~filterByAddresses),
|
|
436
|
+
startBlock: resolvedStartBlock,
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// ============== Build SVM instruction event config ==============
|
|
441
|
+
|
|
442
|
+
// Always-included block fields (slot, time, hash) are prepended at runtime so
|
|
443
|
+
// they're always present regardless of config.
|
|
444
|
+
let alwaysIncludedSvmBlockFields: array<Internal.svmBlockField> = [Slot, Time, Hash]
|
|
423
445
|
|
|
424
446
|
let buildSvmInstructionEventConfig = (
|
|
425
447
|
~contractName: string,
|
|
@@ -427,23 +449,32 @@ let buildSvmInstructionEventConfig = (
|
|
|
427
449
|
~programId: SvmTypes.Pubkey.t,
|
|
428
450
|
~discriminator: option<string>,
|
|
429
451
|
~discriminatorByteLen: int,
|
|
430
|
-
~includeTransaction: bool,
|
|
431
452
|
~includeLogs: bool,
|
|
432
|
-
~
|
|
453
|
+
~transactionFields: array<Internal.svmTransactionField>=[],
|
|
454
|
+
~blockFields: array<Internal.svmBlockField>=[],
|
|
433
455
|
~accountFilters: array<Internal.svmAccountFilterGroup>,
|
|
434
456
|
~isInner: option<bool>,
|
|
435
|
-
~isWildcard: bool,
|
|
436
|
-
~handler: option<Internal.handler>,
|
|
437
|
-
~contractRegister: option<Internal.contractRegister>,
|
|
438
457
|
~accounts: array<string>=[],
|
|
439
458
|
~args: JSON.t=JSON.Null,
|
|
440
459
|
~definedTypes: JSON.t=JSON.Null,
|
|
441
|
-
~startBlock: option<int>=?,
|
|
442
460
|
): Internal.svmInstructionEventConfig => {
|
|
443
461
|
let paramsSchema =
|
|
444
462
|
S.json(~validate=false)
|
|
445
463
|
->Utils.Schema.coerceToJsonPgType
|
|
446
464
|
->(Utils.magic: S.t<JSON.t> => S.t<Internal.eventParams>)
|
|
465
|
+
|
|
466
|
+
// The base eventConfig stores these as a string set (field names match the
|
|
467
|
+
// typed variants at runtime).
|
|
468
|
+
let selectedTransactionFields =
|
|
469
|
+
Utils.Set.fromArray(transactionFields)->(
|
|
470
|
+
Utils.magic: Utils.Set.t<Internal.svmTransactionField> => Utils.Set.t<string>
|
|
471
|
+
)
|
|
472
|
+
let selectedBlockFields = Utils.Set.fromArray(
|
|
473
|
+
Array.concat(alwaysIncludedSvmBlockFields, blockFields),
|
|
474
|
+
)
|
|
475
|
+
let blockFieldMask = Svm.eventBlockFieldMask(
|
|
476
|
+
selectedBlockFields->(Utils.magic: Utils.Set.t<Internal.svmBlockField> => Utils.Set.t<string>),
|
|
477
|
+
)
|
|
447
478
|
{
|
|
448
479
|
id: switch discriminator {
|
|
449
480
|
| Some(d) => d
|
|
@@ -451,20 +482,16 @@ let buildSvmInstructionEventConfig = (
|
|
|
451
482
|
},
|
|
452
483
|
name: instructionName,
|
|
453
484
|
contractName,
|
|
454
|
-
isWildcard,
|
|
455
|
-
handler,
|
|
456
|
-
contractRegister,
|
|
457
485
|
paramsRawEventSchema: paramsSchema,
|
|
458
486
|
simulateParamsSchema: paramsSchema,
|
|
459
|
-
filterByAddresses: false,
|
|
460
|
-
dependsOnAddresses: !isWildcard,
|
|
461
|
-
startBlock,
|
|
462
487
|
programId,
|
|
463
488
|
discriminator,
|
|
464
489
|
discriminatorByteLen,
|
|
465
|
-
includeTransaction,
|
|
466
490
|
includeLogs,
|
|
467
|
-
|
|
491
|
+
selectedTransactionFields,
|
|
492
|
+
transactionFieldMask: Svm.eventTransactionFieldMask(selectedTransactionFields),
|
|
493
|
+
selectedBlockFields,
|
|
494
|
+
blockFieldMask,
|
|
468
495
|
accountFilters,
|
|
469
496
|
isInner,
|
|
470
497
|
accounts,
|
|
@@ -473,16 +500,34 @@ let buildSvmInstructionEventConfig = (
|
|
|
473
500
|
}
|
|
474
501
|
}
|
|
475
502
|
|
|
503
|
+
// Enrich an SVM definition into a registration. SVM has no `where`; only the
|
|
504
|
+
// handler binding + wildcard-derived address gate are registration state.
|
|
505
|
+
let buildSvmOnEventRegistration = (
|
|
506
|
+
~eventConfig: Internal.svmInstructionEventConfig,
|
|
507
|
+
~isWildcard: bool,
|
|
508
|
+
~handler: option<Internal.handler>,
|
|
509
|
+
~contractRegister: option<Internal.contractRegister>,
|
|
510
|
+
~startBlock: option<int>=?,
|
|
511
|
+
): Internal.svmOnEventRegistration => {
|
|
512
|
+
index: -1,
|
|
513
|
+
eventConfig: (eventConfig :> Internal.eventConfig),
|
|
514
|
+
handler,
|
|
515
|
+
contractRegister,
|
|
516
|
+
isWildcard,
|
|
517
|
+
filterByAddresses: false,
|
|
518
|
+
dependsOnAddresses: Internal.dependsOnAddresses(~isWildcard, ~filterByAddresses=false),
|
|
519
|
+
clientAddressFilter: ?buildAddressFilter([], ~isWildcard, ~srcAddressExpr="event.programId"),
|
|
520
|
+
startBlock,
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// ============== Build Fuel event config ==============
|
|
524
|
+
|
|
476
525
|
let buildFuelEventConfig = (
|
|
477
526
|
~contractName: string,
|
|
478
527
|
~eventName: string,
|
|
479
528
|
~kind: string,
|
|
480
529
|
~sighash: string,
|
|
481
530
|
~rawAbi: JSON.t,
|
|
482
|
-
~isWildcard: bool,
|
|
483
|
-
~handler: option<Internal.handler>,
|
|
484
|
-
~contractRegister: option<Internal.contractRegister>,
|
|
485
|
-
~startBlock: option<int>=?,
|
|
486
531
|
): Internal.fuelEventConfig => {
|
|
487
532
|
let fuelKind = switch kind {
|
|
488
533
|
| "logData" =>
|
|
@@ -522,14 +567,33 @@ let buildFuelEventConfig = (
|
|
|
522
567
|
},
|
|
523
568
|
name: eventName,
|
|
524
569
|
contractName,
|
|
525
|
-
isWildcard,
|
|
526
|
-
handler,
|
|
527
|
-
contractRegister,
|
|
528
570
|
paramsRawEventSchema: paramsSchema,
|
|
529
571
|
simulateParamsSchema: paramsSchema,
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
572
|
+
// Fuel keeps the transaction and block inline on the payload; nothing to
|
|
573
|
+
// materialise.
|
|
574
|
+
selectedTransactionFields: Utils.Set.make(),
|
|
575
|
+
transactionFieldMask: 0.,
|
|
576
|
+
blockFieldMask: 0.,
|
|
533
577
|
kind: fuelKind,
|
|
534
578
|
}
|
|
535
579
|
}
|
|
580
|
+
|
|
581
|
+
// Enrich a Fuel definition into a registration (handler binding +
|
|
582
|
+
// wildcard-derived address gate; Fuel never filters by addresses).
|
|
583
|
+
let buildFuelOnEventRegistration = (
|
|
584
|
+
~eventConfig: Internal.fuelEventConfig,
|
|
585
|
+
~isWildcard: bool,
|
|
586
|
+
~handler: option<Internal.handler>,
|
|
587
|
+
~contractRegister: option<Internal.contractRegister>,
|
|
588
|
+
~startBlock: option<int>=?,
|
|
589
|
+
): Internal.fuelOnEventRegistration => {
|
|
590
|
+
index: -1,
|
|
591
|
+
eventConfig: (eventConfig :> Internal.eventConfig),
|
|
592
|
+
handler,
|
|
593
|
+
contractRegister,
|
|
594
|
+
isWildcard,
|
|
595
|
+
filterByAddresses: false,
|
|
596
|
+
dependsOnAddresses: Internal.dependsOnAddresses(~isWildcard, ~filterByAddresses=false),
|
|
597
|
+
clientAddressFilter: ?buildAddressFilter([], ~isWildcard),
|
|
598
|
+
startBlock,
|
|
599
|
+
}
|