envio 3.3.0-alpha.9 → 3.3.0
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 +19 -0
- 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 +9 -8
- package/src/Batch.res.mjs +1 -1
- package/src/BatchProcessing.res +0 -7
- package/src/BatchProcessing.res.mjs +1 -8
- package/src/ChainFetching.res +30 -18
- package/src/ChainFetching.res.mjs +23 -13
- package/src/ChainState.res +134 -55
- package/src/ChainState.res.mjs +78 -36
- package/src/ChainState.resi +14 -2
- package/src/Config.res +9 -5
- package/src/Config.res.mjs +2 -2
- package/src/Core.res +20 -0
- package/src/Core.res.mjs +12 -0
- package/src/CrossChainState.res +115 -34
- package/src/CrossChainState.res.mjs +37 -14
- package/src/EffectState.res +100 -0
- package/src/EffectState.res.mjs +74 -0
- package/src/EffectState.resi +32 -0
- package/src/Envio.res +25 -7
- package/src/Envio.res.mjs +15 -19
- package/src/EventConfigBuilder.res +21 -46
- package/src/EventConfigBuilder.res.mjs +18 -25
- package/src/EventProcessing.res +8 -5
- package/src/EventProcessing.res.mjs +2 -1
- package/src/FetchState.res +814 -467
- package/src/FetchState.res.mjs +541 -369
- package/src/HandlerRegister.res +3 -1
- package/src/HandlerRegister.res.mjs +3 -2
- package/src/InMemoryStore.res +14 -26
- package/src/InMemoryStore.res.mjs +6 -19
- package/src/IndexerState.res +15 -39
- package/src/IndexerState.res.mjs +18 -29
- package/src/IndexerState.resi +2 -10
- package/src/Internal.res +98 -14
- package/src/Internal.res.mjs +96 -2
- package/src/LoadLayer.res +44 -24
- package/src/LoadLayer.res.mjs +43 -20
- package/src/LoadLayer.resi +1 -0
- package/src/LogSelection.res +0 -62
- package/src/LogSelection.res.mjs +0 -74
- package/src/Metrics.res +1 -1
- package/src/Metrics.res.mjs +1 -1
- package/src/Persistence.res +12 -3
- package/src/PgStorage.res +155 -82
- package/src/PgStorage.res.mjs +130 -77
- package/src/Prometheus.res +20 -10
- package/src/Prometheus.res.mjs +22 -10
- package/src/PruneStaleHistory.res +146 -35
- package/src/PruneStaleHistory.res.mjs +114 -20
- package/src/RawEvent.res +2 -2
- package/src/Rollback.res +32 -13
- package/src/Rollback.res.mjs +24 -11
- package/src/SimulateDeadInputTracker.res +1 -1
- package/src/SimulateItems.res +38 -6
- package/src/SimulateItems.res.mjs +28 -9
- package/src/TestIndexer.res +2 -2
- package/src/TestIndexer.res.mjs +2 -2
- package/src/TopicFilter.res +1 -25
- package/src/TopicFilter.res.mjs +0 -74
- package/src/UserContext.res +62 -23
- package/src/UserContext.res.mjs +26 -6
- package/src/Writing.res +60 -21
- package/src/Writing.res.mjs +27 -9
- package/src/bindings/NodeJs.res +5 -0
- package/src/bindings/Viem.res +0 -5
- package/src/sources/EventRouter.res +0 -21
- package/src/sources/EventRouter.res.mjs +0 -12
- package/src/sources/EvmChain.res +2 -27
- package/src/sources/EvmChain.res.mjs +2 -23
- package/src/sources/EvmRpcClient.res +58 -23
- package/src/sources/EvmRpcClient.res.mjs +11 -5
- package/src/sources/HyperSync.res +9 -38
- package/src/sources/HyperSync.res.mjs +16 -28
- package/src/sources/HyperSync.resi +2 -2
- package/src/sources/HyperSyncClient.res +88 -11
- package/src/sources/HyperSyncClient.res.mjs +39 -6
- package/src/sources/HyperSyncSource.res +18 -199
- package/src/sources/HyperSyncSource.res.mjs +9 -128
- package/src/sources/Rpc.res +0 -32
- package/src/sources/Rpc.res.mjs +1 -46
- package/src/sources/RpcSource.res +129 -522
- package/src/sources/RpcSource.res.mjs +161 -366
- package/src/sources/SimulateSource.res +37 -19
- package/src/sources/SimulateSource.res.mjs +27 -10
- package/src/sources/SourceManager.res +3 -7
- package/src/sources/SourceManager.res.mjs +2 -7
- package/src/sources/SourceManager.resi +0 -2
- package/src/sources/SvmHyperSyncSource.res +13 -3
- package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
package/src/Envio.res.mjs
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import * as Address from "./Address.res.mjs";
|
|
4
4
|
import * as Process from "process";
|
|
5
|
-
import * as Internal from "./Internal.res.mjs";
|
|
6
5
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
6
|
+
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
7
7
|
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
8
8
|
|
|
9
9
|
function durationToMs(duration) {
|
|
@@ -18,41 +18,36 @@ function durationToMs(duration) {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
let effectNameRe = /^[A-Za-z0-9_-][A-Za-z0-9_.-]*$/;
|
|
22
|
+
|
|
21
23
|
function createEffect(options, handler) {
|
|
24
|
+
if (!effectNameRe.test(options.name)) {
|
|
25
|
+
Stdlib_JsError.throwWithMessage(`Invalid effect name "` + options.name + `". Effect names may contain letters, numbers, underscores, hyphens and dots (but must not start with a dot or contain a path separator), because the name is used as the cache table name and cache file path.`);
|
|
26
|
+
}
|
|
22
27
|
let outputSchema = S$RescriptSchema.schema(param => options.output);
|
|
23
28
|
let itemSchema = S$RescriptSchema.schema(s => ({
|
|
24
29
|
id: s.m(S$RescriptSchema.string),
|
|
25
30
|
output: s.m(outputSchema)
|
|
26
31
|
}));
|
|
27
32
|
let match = options.cache;
|
|
28
|
-
let match$1 = options.
|
|
33
|
+
let match$1 = options.crossChain;
|
|
34
|
+
let match$2 = options.rateLimit;
|
|
29
35
|
let tmp;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
tmp = {
|
|
35
|
-
callsPerDuration: calls,
|
|
36
|
-
durationMs: durationToMs(match$1.per),
|
|
37
|
-
availableCalls: calls,
|
|
38
|
-
windowStartTime: Date.now(),
|
|
39
|
-
queueCount: 0,
|
|
40
|
-
nextWindowPromise: undefined
|
|
41
|
-
};
|
|
42
|
-
}
|
|
36
|
+
tmp = match$2 === false ? undefined : ({
|
|
37
|
+
callsPerDuration: match$2.calls,
|
|
38
|
+
durationMs: durationToMs(match$2.per)
|
|
39
|
+
});
|
|
43
40
|
return {
|
|
44
41
|
name: options.name,
|
|
45
42
|
handler: handler,
|
|
46
43
|
storageMeta: {
|
|
47
44
|
itemSchema: itemSchema,
|
|
48
|
-
outputSchema: outputSchema
|
|
49
|
-
table: Internal.makeCacheTable(options.name)
|
|
45
|
+
outputSchema: outputSchema
|
|
50
46
|
},
|
|
51
47
|
defaultShouldCache: match !== undefined ? match : false,
|
|
48
|
+
crossChain: match$1 !== undefined ? match$1 : true,
|
|
52
49
|
output: outputSchema,
|
|
53
50
|
input: S$RescriptSchema.schema(param => options.input),
|
|
54
|
-
activeCallsCount: 0,
|
|
55
|
-
prevCallStartTimerRef: null,
|
|
56
51
|
rateLimit: tmp
|
|
57
52
|
};
|
|
58
53
|
}
|
|
@@ -102,6 +97,7 @@ let TestHelpers = {
|
|
|
102
97
|
|
|
103
98
|
export {
|
|
104
99
|
durationToMs,
|
|
100
|
+
effectNameRe,
|
|
105
101
|
createEffect,
|
|
106
102
|
isNonInteractive,
|
|
107
103
|
TestHelpers,
|
|
@@ -236,58 +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
|
-
// Lowercase before encoding so mixed-case (checksummed) user input
|
|
247
|
-
// still matches the lowercase hex topics returned by sources.
|
|
248
|
-
|
|
249
|
-
(
|
|
250
|
-
(value: string) =>
|
|
251
|
-
value->String.toLowerCase->Address.unsafeFromString->TopicFilter.fromAddress
|
|
252
|
-
)->(Utils.magic: (string => EvmTypes.Hex.t) => unknown => EvmTypes.Hex.t)
|
|
253
|
-
|
|
254
|
-
| "bool" =>
|
|
255
|
-
TopicFilter.fromBool->(Utils.magic: (bool => EvmTypes.Hex.t) => unknown => EvmTypes.Hex.t)
|
|
256
|
-
| "string" =>
|
|
257
|
-
TopicFilter.fromDynamicString->(
|
|
258
|
-
Utils.magic: (string => EvmTypes.Hex.t) => unknown => EvmTypes.Hex.t
|
|
259
|
-
)
|
|
260
|
-
|
|
261
|
-
| "bytes" =>
|
|
262
|
-
TopicFilter.fromDynamicBytes->(
|
|
263
|
-
Utils.magic: (string => EvmTypes.Hex.t) => unknown => EvmTypes.Hex.t
|
|
264
|
-
)
|
|
265
|
-
|
|
266
|
-
| t if t->String.startsWith("uint") =>
|
|
267
|
-
TopicFilter.fromBigInt->(Utils.magic: (bigint => EvmTypes.Hex.t) => unknown => EvmTypes.Hex.t)
|
|
268
|
-
| t if t->String.startsWith("int") =>
|
|
269
|
-
TopicFilter.fromSignedBigInt->(
|
|
270
|
-
Utils.magic: (bigint => EvmTypes.Hex.t) => unknown => EvmTypes.Hex.t
|
|
271
|
-
)
|
|
272
|
-
|
|
273
|
-
| t if t->String.startsWith("bytes") =>
|
|
274
|
-
TopicFilter.castToHexUnsafe->(
|
|
275
|
-
Utils.magic: ('a => EvmTypes.Hex.t) => unknown => EvmTypes.Hex.t
|
|
276
|
-
)
|
|
277
|
-
|
|
278
|
-
| other => JsError.throwWithMessage(`Unsupported topic filter ABI type: ${other}`)
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
239
|
+
let getTopicEncoder = (abiType: string): (unknown => EvmTypes.Hex.t) => value =>
|
|
240
|
+
Core.getAddon().encodeIndexedTopic(~abiType, ~value)
|
|
282
241
|
|
|
283
242
|
let buildTopicGetter = (p: paramMeta) => {
|
|
284
243
|
let encoder = getTopicEncoder(p.abiType)
|
|
244
|
+
let isTuple = p.abiType->String.startsWith("(")
|
|
285
245
|
(eventFilter: dict<JSON.t>) =>
|
|
286
246
|
eventFilter
|
|
287
247
|
->Utils.Dict.dangerouslyGetNonOption(p.name)
|
|
288
|
-
->Option.mapOr([], topicFilters =>
|
|
289
|
-
topicFilters->(Utils.magic: JSON.t => unknown)
|
|
290
|
-
|
|
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
|
+
})
|
|
291
263
|
}
|
|
292
264
|
|
|
293
265
|
// ============== Field selection ==============
|
|
@@ -452,6 +424,7 @@ let buildEvmOnEventRegistration = (
|
|
|
452
424
|
}
|
|
453
425
|
|
|
454
426
|
{
|
|
427
|
+
index: -1,
|
|
455
428
|
eventConfig: (eventConfig :> Internal.eventConfig),
|
|
456
429
|
isWildcard,
|
|
457
430
|
handler,
|
|
@@ -536,6 +509,7 @@ let buildSvmOnEventRegistration = (
|
|
|
536
509
|
~contractRegister: option<Internal.contractRegister>,
|
|
537
510
|
~startBlock: option<int>=?,
|
|
538
511
|
): Internal.svmOnEventRegistration => {
|
|
512
|
+
index: -1,
|
|
539
513
|
eventConfig: (eventConfig :> Internal.eventConfig),
|
|
540
514
|
handler,
|
|
541
515
|
contractRegister,
|
|
@@ -613,6 +587,7 @@ let buildFuelOnEventRegistration = (
|
|
|
613
587
|
~contractRegister: option<Internal.contractRegister>,
|
|
614
588
|
~startBlock: option<int>=?,
|
|
615
589
|
): Internal.fuelOnEventRegistration => {
|
|
590
|
+
index: -1,
|
|
616
591
|
eventConfig: (eventConfig :> Internal.eventConfig),
|
|
617
592
|
handler,
|
|
618
593
|
contractRegister,
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
import * as Evm from "./sources/Evm.res.mjs";
|
|
4
4
|
import * as Svm from "./sources/Svm.res.mjs";
|
|
5
|
+
import * as Core from "./Core.res.mjs";
|
|
5
6
|
import * as Utils from "./Utils.res.mjs";
|
|
6
7
|
import * as Address from "./Address.res.mjs";
|
|
7
8
|
import * as FuelSDK from "./sources/FuelSDK.res.mjs";
|
|
8
9
|
import * as Internal from "./Internal.res.mjs";
|
|
9
|
-
import * as TopicFilter from "./TopicFilter.res.mjs";
|
|
10
10
|
import * as LogSelection from "./LogSelection.res.mjs";
|
|
11
11
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
12
12
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
@@ -208,34 +208,24 @@ function buildSimulateParamsSchema(params) {
|
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
function getTopicEncoder(abiType) {
|
|
211
|
-
|
|
212
|
-
return TopicFilter.castToHexUnsafe;
|
|
213
|
-
}
|
|
214
|
-
switch (abiType) {
|
|
215
|
-
case "address" :
|
|
216
|
-
return value => TopicFilter.fromAddress(value.toLowerCase());
|
|
217
|
-
case "bool" :
|
|
218
|
-
return TopicFilter.fromBool;
|
|
219
|
-
case "bytes" :
|
|
220
|
-
return TopicFilter.fromDynamicBytes;
|
|
221
|
-
case "string" :
|
|
222
|
-
return TopicFilter.fromDynamicString;
|
|
223
|
-
default:
|
|
224
|
-
if (abiType.startsWith("uint")) {
|
|
225
|
-
return TopicFilter.fromBigInt;
|
|
226
|
-
} else if (abiType.startsWith("int")) {
|
|
227
|
-
return TopicFilter.fromSignedBigInt;
|
|
228
|
-
} else if (abiType.startsWith("bytes")) {
|
|
229
|
-
return TopicFilter.castToHexUnsafe;
|
|
230
|
-
} else {
|
|
231
|
-
return Stdlib_JsError.throwWithMessage(`Unsupported topic filter ABI type: ` + abiType);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
211
|
+
return value => Core.getAddon().encodeIndexedTopic(abiType, value);
|
|
234
212
|
}
|
|
235
213
|
|
|
236
214
|
function buildTopicGetter(p) {
|
|
237
215
|
let encoder = getTopicEncoder(p.abiType);
|
|
238
|
-
|
|
216
|
+
let isTuple = p.abiType.startsWith("(");
|
|
217
|
+
return eventFilter => Stdlib_Option.mapOr(eventFilter[p.name], [], topicFilters => {
|
|
218
|
+
if (!isTuple) {
|
|
219
|
+
return normalizeOrThrow(topicFilters).map(encoder);
|
|
220
|
+
}
|
|
221
|
+
let encoded;
|
|
222
|
+
try {
|
|
223
|
+
encoded = encoder(topicFilters);
|
|
224
|
+
} catch (exn) {
|
|
225
|
+
return normalizeOrThrow(topicFilters).map(encoder);
|
|
226
|
+
}
|
|
227
|
+
return [encoded];
|
|
228
|
+
});
|
|
239
229
|
}
|
|
240
230
|
|
|
241
231
|
let alwaysIncludedBlockFields = [
|
|
@@ -317,6 +307,7 @@ function buildEvmOnEventRegistration(eventConfig, isWildcard, handler, contractR
|
|
|
317
307
|
let sb = resolvedWhere.startBlock;
|
|
318
308
|
let resolvedStartBlock = sb !== undefined ? sb : startBlock;
|
|
319
309
|
return {
|
|
310
|
+
index: -1,
|
|
320
311
|
eventConfig: eventConfig,
|
|
321
312
|
handler: handler,
|
|
322
313
|
contractRegister: contractRegister,
|
|
@@ -369,6 +360,7 @@ function buildSvmInstructionEventConfig(contractName, instructionName, programId
|
|
|
369
360
|
|
|
370
361
|
function buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, startBlock) {
|
|
371
362
|
return {
|
|
363
|
+
index: -1,
|
|
372
364
|
eventConfig: eventConfig,
|
|
373
365
|
handler: handler,
|
|
374
366
|
contractRegister: contractRegister,
|
|
@@ -438,6 +430,7 @@ function buildFuelEventConfig(contractName, eventName, kind, sighash, rawAbi) {
|
|
|
438
430
|
|
|
439
431
|
function buildFuelOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, startBlock) {
|
|
440
432
|
return {
|
|
433
|
+
index: -1,
|
|
441
434
|
eventConfig: eventConfig,
|
|
442
435
|
handler: handler,
|
|
443
436
|
contractRegister: contractRegister,
|
package/src/EventProcessing.res
CHANGED
|
@@ -73,9 +73,10 @@ let runEventHandlerOrThrow = async (
|
|
|
73
73
|
)
|
|
74
74
|
}
|
|
75
75
|
let handlerDuration = timeBeforeHandler->Performance.secondsSince
|
|
76
|
+
let eventConfig = eventItem.onEventRegistration.eventConfig
|
|
76
77
|
Prometheus.ProcessingHandler.increment(
|
|
77
|
-
~contract=
|
|
78
|
-
~event=
|
|
78
|
+
~contract=eventConfig.contractName,
|
|
79
|
+
~event=eventConfig.name,
|
|
79
80
|
~duration=handlerDuration,
|
|
80
81
|
)
|
|
81
82
|
}
|
|
@@ -121,8 +122,8 @@ let runHandlerOrThrow = async (
|
|
|
121
122
|
}),
|
|
122
123
|
)
|
|
123
124
|
}
|
|
124
|
-
| Event(
|
|
125
|
-
switch onEventRegistration.handler {
|
|
125
|
+
| Event(_) =>
|
|
126
|
+
switch (item->Internal.castUnsafeEventItem).onEventRegistration.handler {
|
|
126
127
|
| Some(handler) =>
|
|
127
128
|
await item->runEventHandlerOrThrow(
|
|
128
129
|
~handler,
|
|
@@ -161,7 +162,9 @@ let preloadBatchOrThrow = async (
|
|
|
161
162
|
for idx in 0 to checkpointEventsProcessed - 1 {
|
|
162
163
|
let item = batch.items->Array.getUnsafe(itemIdx.contents + idx)
|
|
163
164
|
switch item {
|
|
164
|
-
| Event(
|
|
165
|
+
| Event(_) =>
|
|
166
|
+
let {handler, eventConfig: {contractName, name: eventName}} =
|
|
167
|
+
(item->Internal.castUnsafeEventItem).onEventRegistration
|
|
165
168
|
switch handler {
|
|
166
169
|
| None => ()
|
|
167
170
|
| Some(handler) =>
|
|
@@ -65,7 +65,8 @@ async function runEventHandlerOrThrow(item, checkpointId, handler, indexerState,
|
|
|
65
65
|
};
|
|
66
66
|
}
|
|
67
67
|
let handlerDuration = Performance.secondsSince(timeBeforeHandler);
|
|
68
|
-
|
|
68
|
+
let eventConfig = item.onEventRegistration.eventConfig;
|
|
69
|
+
return Prometheus.ProcessingHandler.increment(eventConfig.contractName, eventConfig.name, handlerDuration);
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
async function runHandlerOrThrow(item, checkpointId, indexerState, loadManager, persistence, config, chains) {
|