envio 3.1.1 → 3.2.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/evm.schema.json +83 -11
- package/fuel.schema.json +83 -11
- package/index.d.ts +184 -3
- package/package.json +6 -6
- package/src/Batch.res +2 -2
- package/src/ChainFetcher.res +27 -3
- package/src/ChainFetcher.res.mjs +17 -3
- package/src/ChainManager.res +163 -0
- package/src/ChainManager.res.mjs +136 -0
- package/src/Config.res +213 -30
- package/src/Config.res.mjs +102 -41
- package/src/Core.res +16 -10
- package/src/Ecosystem.res +0 -3
- package/src/Env.res +2 -2
- package/src/Env.res.mjs +2 -2
- package/src/Envio.res +101 -2
- package/src/Envio.res.mjs +2 -3
- package/src/EventConfigBuilder.res +52 -0
- package/src/EventConfigBuilder.res.mjs +32 -0
- package/src/EventUtils.res +2 -2
- package/src/FetchState.res +126 -71
- package/src/FetchState.res.mjs +73 -51
- package/src/GlobalState.res +219 -363
- package/src/GlobalState.res.mjs +314 -491
- package/src/GlobalStateManager.res +49 -59
- package/src/GlobalStateManager.res.mjs +5 -4
- package/src/GlobalStateManager.resi +1 -1
- package/src/HandlerLoader.res +12 -1
- package/src/HandlerLoader.res.mjs +6 -1
- package/src/HandlerRegister.res +9 -9
- package/src/HandlerRegister.res.mjs +9 -9
- package/src/Hasura.res +102 -32
- package/src/Hasura.res.mjs +88 -34
- package/src/InMemoryStore.res +10 -1
- package/src/InMemoryStore.res.mjs +4 -1
- package/src/InMemoryTable.res +83 -136
- package/src/InMemoryTable.res.mjs +57 -86
- package/src/Internal.res +54 -5
- package/src/Internal.res.mjs +2 -8
- package/src/LazyLoader.res +2 -2
- package/src/LazyLoader.res.mjs +3 -3
- package/src/LoadLayer.res +47 -60
- package/src/LoadLayer.res.mjs +28 -50
- package/src/LoadLayer.resi +2 -5
- package/src/LogSelection.res +4 -4
- package/src/LogSelection.res.mjs +5 -7
- package/src/Logging.res +1 -1
- package/src/Main.res +61 -2
- package/src/Main.res.mjs +37 -1
- package/src/Persistence.res +3 -16
- package/src/PgStorage.res +125 -114
- package/src/PgStorage.res.mjs +112 -95
- package/src/Ports.res +5 -0
- package/src/Ports.res.mjs +9 -0
- package/src/Prometheus.res +3 -3
- package/src/Prometheus.res.mjs +4 -4
- package/src/ReorgDetection.res +4 -4
- package/src/ReorgDetection.res.mjs +4 -5
- package/src/SafeCheckpointTracking.res +16 -16
- package/src/SafeCheckpointTracking.res.mjs +2 -2
- package/src/SimulateItems.res +10 -14
- package/src/SimulateItems.res.mjs +5 -2
- package/src/Sink.res +1 -1
- package/src/Sink.res.mjs +1 -2
- package/src/SvmTypes.res +9 -0
- package/src/SvmTypes.res.mjs +14 -0
- package/src/TestIndexer.res +17 -57
- package/src/TestIndexer.res.mjs +14 -48
- package/src/TestIndexerProxyStorage.res +23 -23
- package/src/TestIndexerProxyStorage.res.mjs +12 -15
- package/src/Throttler.res +2 -2
- package/src/Time.res +2 -2
- package/src/Time.res.mjs +2 -2
- package/src/UserContext.res +19 -118
- package/src/UserContext.res.mjs +10 -66
- package/src/Utils.res +15 -15
- package/src/Utils.res.mjs +7 -8
- package/src/adapters/MarkBatchProcessedAdapter.res +5 -0
- package/src/adapters/MarkBatchProcessedAdapter.res.mjs +14 -0
- package/src/bindings/BigDecimal.res +1 -1
- package/src/bindings/BigDecimal.res.mjs +2 -2
- package/src/bindings/ClickHouse.res +8 -6
- package/src/bindings/ClickHouse.res.mjs +5 -5
- package/src/bindings/Hrtime.res +1 -1
- package/src/bindings/Pino.res +2 -2
- package/src/bindings/Pino.res.mjs +3 -4
- package/src/db/EntityFilter.res +410 -0
- package/src/db/EntityFilter.res.mjs +424 -0
- package/src/db/EntityHistory.res +1 -1
- package/src/db/EntityHistory.res.mjs +1 -1
- package/src/db/InternalTable.res +10 -10
- package/src/db/InternalTable.res.mjs +41 -45
- package/src/db/Schema.res +2 -2
- package/src/db/Schema.res.mjs +3 -3
- package/src/db/Table.res +106 -22
- package/src/db/Table.res.mjs +84 -35
- package/src/sources/EventRouter.res +67 -2
- package/src/sources/EventRouter.res.mjs +45 -3
- package/src/sources/Evm.res +0 -7
- package/src/sources/Evm.res.mjs +0 -15
- package/src/sources/EvmChain.res +1 -1
- package/src/sources/EvmChain.res.mjs +1 -2
- package/src/sources/EvmRpcClient.res +42 -0
- package/src/sources/EvmRpcClient.res.mjs +64 -0
- package/src/sources/Fuel.res +0 -7
- package/src/sources/Fuel.res.mjs +0 -15
- package/src/sources/HyperFuelSource.res +5 -4
- package/src/sources/HyperFuelSource.res.mjs +2 -2
- package/src/sources/HyperSyncClient.res +9 -5
- package/src/sources/HyperSyncClient.res.mjs +2 -2
- package/src/sources/HyperSyncHeightStream.res +2 -2
- package/src/sources/HyperSyncHeightStream.res.mjs +2 -2
- package/src/sources/HyperSyncSource.res +10 -9
- package/src/sources/HyperSyncSource.res.mjs +4 -4
- package/src/sources/Rpc.res +1 -5
- package/src/sources/Rpc.res.mjs +1 -9
- package/src/sources/RpcSource.res +57 -21
- package/src/sources/RpcSource.res.mjs +47 -20
- package/src/sources/RpcWebSocketHeightStream.res +1 -1
- package/src/sources/SourceManager.res +3 -2
- package/src/sources/SourceManager.res.mjs +1 -1
- package/src/sources/Svm.res +3 -10
- package/src/sources/Svm.res.mjs +4 -18
- package/src/sources/SvmHyperSyncClient.res +265 -0
- package/src/sources/SvmHyperSyncClient.res.mjs +28 -0
- package/src/sources/SvmHyperSyncSource.res +638 -0
- package/src/sources/SvmHyperSyncSource.res.mjs +557 -0
- package/src/tui/Tui.res +9 -2
- package/src/tui/Tui.res.mjs +18 -3
- package/src/tui/components/BufferedProgressBar.res +2 -2
- package/src/tui/components/TuiData.res +3 -0
- package/svm.schema.json +523 -14
- package/src/TableIndices.res +0 -115
- package/src/TableIndices.res.mjs +0 -144
package/src/LoadLayer.res.mjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
+
import * as Table from "./db/Table.res.mjs";
|
|
3
4
|
import * as Utils from "./Utils.res.mjs";
|
|
4
5
|
import * as Hrtime from "./bindings/Hrtime.res.mjs";
|
|
5
6
|
import * as Logging from "./Logging.res.mjs";
|
|
6
|
-
import * as Internal from "./Internal.res.mjs";
|
|
7
|
-
import * as Belt_Array from "@rescript/runtime/lib/es6/Belt_Array.js";
|
|
8
7
|
import * as Prometheus from "./Prometheus.res.mjs";
|
|
9
8
|
import * as LoadManager from "./LoadManager.res.mjs";
|
|
10
9
|
import * as Persistence from "./Persistence.res.mjs";
|
|
11
|
-
import * as
|
|
10
|
+
import * as EntityFilter from "./db/EntityFilter.res.mjs";
|
|
11
|
+
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
12
12
|
import * as ErrorHandling from "./ErrorHandling.res.mjs";
|
|
13
13
|
import * as InMemoryStore from "./InMemoryStore.res.mjs";
|
|
14
14
|
import * as InMemoryTable from "./InMemoryTable.res.mjs";
|
|
@@ -23,7 +23,11 @@ function loadById(loadManager, persistence, entityConfig, inMemoryStore, shouldG
|
|
|
23
23
|
let timerRef = Prometheus.StorageLoad.startOperation(storage.name, key);
|
|
24
24
|
let dbEntities;
|
|
25
25
|
try {
|
|
26
|
-
dbEntities = await storage.
|
|
26
|
+
dbEntities = await storage.loadOrThrow({
|
|
27
|
+
operator: "in",
|
|
28
|
+
fieldName: Table.idFieldName,
|
|
29
|
+
fieldValue: idsToLoad
|
|
30
|
+
}, entityConfig.table);
|
|
27
31
|
} catch (raw_exn) {
|
|
28
32
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
29
33
|
if (exn.RE_EXN_ID === Persistence.StorageError) {
|
|
@@ -79,8 +83,8 @@ function executeWithRateLimit(effect, effectArgs, inMemTable, onError, isFromQue
|
|
|
79
83
|
state.nextWindowPromise = undefined;
|
|
80
84
|
}
|
|
81
85
|
let immediateCount = Math.min(state.availableCalls, effectArgs.length);
|
|
82
|
-
let immediateArgs =
|
|
83
|
-
let queuedArgs =
|
|
86
|
+
let immediateArgs = effectArgs.slice(0, immediateCount);
|
|
87
|
+
let queuedArgs = effectArgs.slice(immediateCount);
|
|
84
88
|
state.availableCalls = state.availableCalls - immediateCount | 0;
|
|
85
89
|
for (let idx = 0, idx_finish = immediateArgs.length; idx < idx_finish; ++idx) {
|
|
86
90
|
promises.push(callEffect(effect, immediateArgs[idx], inMemTable, timerRef, onError));
|
|
@@ -139,7 +143,11 @@ function loadEffect(loadManager, persistence, effect, effectArgs, inMemoryStore,
|
|
|
139
143
|
let outputSchema = match$1.outputSchema;
|
|
140
144
|
let dbEntities;
|
|
141
145
|
try {
|
|
142
|
-
dbEntities = await storage.
|
|
146
|
+
dbEntities = await storage.loadOrThrow({
|
|
147
|
+
operator: "in",
|
|
148
|
+
fieldName: Table.idFieldName,
|
|
149
|
+
fieldValue: idsToLoad
|
|
150
|
+
}, match$1.table);
|
|
143
151
|
} catch (raw_exn) {
|
|
144
152
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
145
153
|
Logging.childWarn(Logging.getItemLogger(item), {
|
|
@@ -189,48 +197,20 @@ function loadEffect(loadManager, persistence, effect, effectArgs, inMemoryStore,
|
|
|
189
197
|
return LoadManager.call(loadManager, effectArgs, key, load, args => args.cacheKey, shouldGroup, hash => InMemoryStore.hasEffectOutput(inMemTable, hash), hash => InMemoryStore.getEffectOutputUnsafe(inMemTable, hash));
|
|
190
198
|
}
|
|
191
199
|
|
|
192
|
-
function
|
|
193
|
-
let
|
|
194
|
-
switch (operator) {
|
|
195
|
-
case "Eq" :
|
|
196
|
-
operatorCallName = "eq";
|
|
197
|
-
break;
|
|
198
|
-
case "Gt" :
|
|
199
|
-
operatorCallName = "gt";
|
|
200
|
-
break;
|
|
201
|
-
case "Lt" :
|
|
202
|
-
operatorCallName = "lt";
|
|
203
|
-
break;
|
|
204
|
-
}
|
|
205
|
-
let key = entityConfig.name + `.getWhere.` + fieldName + `.` + operatorCallName;
|
|
200
|
+
function loadByFilter(loadManager, persistence, entityConfig, inMemoryStore, shouldGroup, item, filter) {
|
|
201
|
+
let key = EntityFilter.toOperationKey(filter, entityConfig.name);
|
|
206
202
|
let inMemTable = InMemoryStore.getInMemTable(inMemoryStore, entityConfig);
|
|
207
|
-
let load = async (
|
|
203
|
+
let load = async (filters, param) => {
|
|
208
204
|
let storage = Persistence.getInitializedStorageOrThrow(persistence);
|
|
209
205
|
let timerRef = Prometheus.StorageLoad.startOperation(storage.name, key);
|
|
210
206
|
let size = {
|
|
211
207
|
contents: 0
|
|
212
208
|
};
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
operator: operator
|
|
217
|
-
}));
|
|
218
|
-
await Promise.all(indiciesToLoad.map(async index => {
|
|
219
|
-
InMemoryTable.Entity.addEmptyIndex(inMemTable, index);
|
|
209
|
+
filters.forEach(filter => InMemoryTable.Entity.addEmptyIndex(inMemTable, filter));
|
|
210
|
+
let queries = EntityFilter.merge(filters);
|
|
211
|
+
await Promise.all(queries.map(async filter => {
|
|
220
212
|
try {
|
|
221
|
-
let
|
|
222
|
-
switch (index.operator) {
|
|
223
|
-
case "Eq" :
|
|
224
|
-
tmp = "=";
|
|
225
|
-
break;
|
|
226
|
-
case "Gt" :
|
|
227
|
-
tmp = ">";
|
|
228
|
-
break;
|
|
229
|
-
case "Lt" :
|
|
230
|
-
tmp = "<";
|
|
231
|
-
break;
|
|
232
|
-
}
|
|
233
|
-
let entities = await storage.loadByFieldOrThrow(TableIndices.Index.getFieldName(index), fieldValueSchema, index.fieldValue, tmp, entityConfig.table, entityConfig.rowsSchema);
|
|
213
|
+
let entities = await storage.loadOrThrow(filter, entityConfig.table);
|
|
234
214
|
entities.forEach(entity => InMemoryTable.Entity.initValue(inMemTable, inMemoryStore.committedCheckpointId, entity.id, entity));
|
|
235
215
|
size.contents = size.contents + entities.length | 0;
|
|
236
216
|
return;
|
|
@@ -238,23 +218,21 @@ function loadByField(loadManager, persistence, operator, entityConfig, inMemoryS
|
|
|
238
218
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
239
219
|
if (exn.RE_EXN_ID === Persistence.StorageError) {
|
|
240
220
|
return ErrorHandling.mkLogAndRaise(Logging.createChildFrom(Logging.getItemLogger(item), {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
fieldName: fieldName,
|
|
244
|
-
fieldValue: fieldValue
|
|
221
|
+
operation: key,
|
|
222
|
+
params: EntityFilter.getParams(filter)
|
|
245
223
|
}), exn.message, exn.reason);
|
|
246
224
|
}
|
|
247
225
|
throw exn;
|
|
248
226
|
}
|
|
249
227
|
}));
|
|
250
|
-
return Prometheus.StorageLoad.endOperation(timerRef, storage.name, key,
|
|
228
|
+
return Prometheus.StorageLoad.endOperation(timerRef, storage.name, key, Stdlib_Array.reduce(queries, 0, (acc, query) => acc + EntityFilter.valuesCount(query) | 0), size.contents);
|
|
251
229
|
};
|
|
252
|
-
return LoadManager.call(loadManager,
|
|
230
|
+
return LoadManager.call(loadManager, filter, key, load, EntityFilter.toString, shouldGroup, InMemoryTable.Entity.hasIndex(inMemTable), InMemoryTable.Entity.getUnsafeOnIndex(inMemTable));
|
|
253
231
|
}
|
|
254
232
|
|
|
255
233
|
export {
|
|
256
234
|
loadById,
|
|
257
|
-
|
|
235
|
+
loadByFilter,
|
|
258
236
|
loadEffect,
|
|
259
237
|
}
|
|
260
|
-
/*
|
|
238
|
+
/* Table Not a pure module */
|
package/src/LoadLayer.resi
CHANGED
|
@@ -8,17 +8,14 @@ let loadById: (
|
|
|
8
8
|
~entityId: string,
|
|
9
9
|
) => promise<option<Internal.entity>>
|
|
10
10
|
|
|
11
|
-
let
|
|
11
|
+
let loadByFilter: (
|
|
12
12
|
~loadManager: LoadManager.t,
|
|
13
13
|
~persistence: Persistence.t,
|
|
14
|
-
~operator: TableIndices.Operator.t,
|
|
15
14
|
~entityConfig: Internal.entityConfig,
|
|
16
15
|
~inMemoryStore: InMemoryStore.t,
|
|
17
|
-
~fieldName: string,
|
|
18
|
-
~fieldValueSchema: RescriptSchema.S.t<'fieldValue>,
|
|
19
16
|
~shouldGroup: bool,
|
|
20
17
|
~item: Internal.item,
|
|
21
|
-
~
|
|
18
|
+
~filter: EntityFilter.t,
|
|
22
19
|
) => promise<array<Internal.entity>>
|
|
23
20
|
|
|
24
21
|
let loadEffect: (
|
package/src/LogSelection.res
CHANGED
|
@@ -12,7 +12,7 @@ let makeTopicSelection = (~topic0, ~topic1=[], ~topic2=[], ~topic3=[]) =>
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
let hasFilters = ({topic1, topic2, topic3}: Internal.topicSelection) => {
|
|
15
|
-
[topic1, topic2, topic3]->Array.find(topic => !Utils.Array.isEmpty(topic))->
|
|
15
|
+
[topic1, topic2, topic3]->Array.find(topic => !Utils.Array.isEmpty(topic))->Option.isSome
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
/**
|
|
@@ -24,11 +24,11 @@ let compressTopicSelections = (topicSelections: array<Internal.topicSelection>)
|
|
|
24
24
|
|
|
25
25
|
let selectionsWithFilters = []
|
|
26
26
|
|
|
27
|
-
topicSelections->
|
|
27
|
+
topicSelections->Array.forEach(selection => {
|
|
28
28
|
if selection->hasFilters {
|
|
29
29
|
selectionsWithFilters->Array.push(selection)->ignore
|
|
30
30
|
} else {
|
|
31
|
-
selection.topic0->
|
|
31
|
+
selection.topic0->Array.forEach(topic0 => {
|
|
32
32
|
topic0sOfSelectionsWithoutFilters->Array.push(topic0)->ignore
|
|
33
33
|
})
|
|
34
34
|
}
|
|
@@ -43,7 +43,7 @@ let compressTopicSelections = (topicSelections: array<Internal.topicSelection>)
|
|
|
43
43
|
topic2: [],
|
|
44
44
|
topic3: [],
|
|
45
45
|
}
|
|
46
|
-
|
|
46
|
+
Array.concat([selectionWithoutFilters], selectionsWithFilters)
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
package/src/LogSelection.res.mjs
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Utils from "./Utils.res.mjs";
|
|
4
|
-
import * as
|
|
5
|
-
import * as Belt_Option from "@rescript/runtime/lib/es6/Belt_Option.js";
|
|
4
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
6
5
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
7
6
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
8
7
|
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
@@ -35,7 +34,7 @@ function makeTopicSelection(topic0, topic1Opt, topic2Opt, topic3Opt) {
|
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
function hasFilters(param) {
|
|
38
|
-
return
|
|
37
|
+
return Stdlib_Option.isSome([
|
|
39
38
|
param.topic1,
|
|
40
39
|
param.topic2,
|
|
41
40
|
param.topic3
|
|
@@ -45,12 +44,11 @@ function hasFilters(param) {
|
|
|
45
44
|
function compressTopicSelections(topicSelections) {
|
|
46
45
|
let topic0sOfSelectionsWithoutFilters = [];
|
|
47
46
|
let selectionsWithFilters = [];
|
|
48
|
-
|
|
47
|
+
topicSelections.forEach(selection => {
|
|
49
48
|
if (hasFilters(selection)) {
|
|
50
49
|
selectionsWithFilters.push(selection);
|
|
51
|
-
return;
|
|
52
50
|
} else {
|
|
53
|
-
|
|
51
|
+
selection.topic0.forEach(topic0 => {
|
|
54
52
|
topic0sOfSelectionsWithoutFilters.push(topic0);
|
|
55
53
|
});
|
|
56
54
|
}
|
|
@@ -67,7 +65,7 @@ function compressTopicSelections(topicSelections) {
|
|
|
67
65
|
topic2: selectionWithoutFilters_topic2,
|
|
68
66
|
topic3: selectionWithoutFilters_topic3
|
|
69
67
|
};
|
|
70
|
-
return
|
|
68
|
+
return [selectionWithoutFilters].concat(selectionsWithFilters);
|
|
71
69
|
}
|
|
72
70
|
|
|
73
71
|
function make(addresses, topicSelections) {
|
package/src/Logging.res
CHANGED
|
@@ -172,7 +172,7 @@ let getItemLogger = {
|
|
|
172
172
|
"chainId": chain->ChainMap.Chain.toChainId,
|
|
173
173
|
"block": blockNumber,
|
|
174
174
|
"logIndex": logIndex,
|
|
175
|
-
"address": event.srcAddress,
|
|
175
|
+
"address": (event->Internal.toGenericEvent).srcAddress,
|
|
176
176
|
}->createChildParams
|
|
177
177
|
| Block({blockNumber, onBlockConfig}) =>
|
|
178
178
|
{
|
package/src/Main.res
CHANGED
|
@@ -296,6 +296,59 @@ let getGlobalIndexer = (): 'indexer => {
|
|
|
296
296
|
)
|
|
297
297
|
}
|
|
298
298
|
|
|
299
|
+
// SVM identity: `{program, instruction}` from TS or
|
|
300
|
+
// `{instruction: GADT{contract, _0}}` from ReScript. Same two-format dance
|
|
301
|
+
// as the EVM `parseIdentityConfig`, but reading the SVM-native field names.
|
|
302
|
+
let parseSvmIdentityConfig = (identityConfig: 'a) => {
|
|
303
|
+
let raw =
|
|
304
|
+
identityConfig->(
|
|
305
|
+
Utils.magic: 'a => {"program": unknown, "instruction": unknown, "where": option<JSON.t>}
|
|
306
|
+
)
|
|
307
|
+
let (programName, instructionName) = if typeof(raw["program"]) === #string {
|
|
308
|
+
(
|
|
309
|
+
raw["program"]->(Utils.magic: unknown => string),
|
|
310
|
+
raw["instruction"]->(Utils.magic: unknown => string),
|
|
311
|
+
)
|
|
312
|
+
} else {
|
|
313
|
+
let inst = raw["instruction"]->(Utils.magic: unknown => {"contract": string, "_0": string})
|
|
314
|
+
(inst["contract"], inst["_0"])
|
|
315
|
+
}
|
|
316
|
+
let where = raw["where"]
|
|
317
|
+
let eventOptions: option<Internal.eventOptions<_>> = switch where {
|
|
318
|
+
| None => None
|
|
319
|
+
| Some(_) =>
|
|
320
|
+
Some({
|
|
321
|
+
where: ?(where->(Utils.magic: option<JSON.t> => option<_>)),
|
|
322
|
+
})
|
|
323
|
+
}
|
|
324
|
+
(programName, instructionName, eventOptions)
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// onInstruction: delegates to HandlerRegister.setHandler. The SVM analog of
|
|
328
|
+
// onEvent; the registration store keys on `(contractName, eventName)` which
|
|
329
|
+
// for SVM is `(programName, instructionName)`.
|
|
330
|
+
let onInstructionFn = (identityConfig: 'a, handler: 'b) => {
|
|
331
|
+
HandlerRegister.throwIfFinishedRegistration(~methodName="onInstruction")
|
|
332
|
+
let (programName, instructionName, eventOptions) = parseSvmIdentityConfig(identityConfig)
|
|
333
|
+
// The generic dispatch hands every handler `{event, context}`. SVM handlers
|
|
334
|
+
// receive the instruction under `instruction`, so remap the field here; the
|
|
335
|
+
// payload object itself is the `svmInstruction` built in SvmHyperSyncSource.
|
|
336
|
+
let userHandler =
|
|
337
|
+
handler->(
|
|
338
|
+
Utils.magic: 'b => Envio.svmOnInstructionArgs<Internal.handlerContext> => promise<unit>
|
|
339
|
+
)
|
|
340
|
+
HandlerRegister.setHandler(
|
|
341
|
+
~contractName=programName,
|
|
342
|
+
~eventName=instructionName,
|
|
343
|
+
(args: Internal.genericHandlerArgs<Internal.event, Internal.handlerContext>) =>
|
|
344
|
+
userHandler({
|
|
345
|
+
instruction: args.event->(Utils.magic: Internal.event => Envio.svmInstruction),
|
|
346
|
+
context: args.context,
|
|
347
|
+
}),
|
|
348
|
+
~eventOptions,
|
|
349
|
+
)
|
|
350
|
+
}
|
|
351
|
+
|
|
299
352
|
// contractRegister: delegates to HandlerRegister.setContractRegister
|
|
300
353
|
let contractRegisterFn = (identityConfig: 'a, handler: 'b) => {
|
|
301
354
|
HandlerRegister.throwIfFinishedRegistration(~methodName="contractRegister")
|
|
@@ -467,6 +520,7 @@ let getGlobalIndexer = (): 'indexer => {
|
|
|
467
520
|
"description",
|
|
468
521
|
"chainIds",
|
|
469
522
|
"chains",
|
|
523
|
+
"onInstruction",
|
|
470
524
|
"onSlot",
|
|
471
525
|
"~internalAndWillBeRemovedSoon_onRollbackCommit",
|
|
472
526
|
]
|
|
@@ -490,6 +544,7 @@ let getGlobalIndexer = (): 'indexer => {
|
|
|
490
544
|
chains->(Utils.magic: {..} => unknown)
|
|
491
545
|
}
|
|
492
546
|
| "onEvent" => onEventFn->Utils.magic
|
|
547
|
+
| "onInstruction" => onInstructionFn->Utils.magic
|
|
493
548
|
| "contractRegister" => contractRegisterFn->Utils.magic
|
|
494
549
|
| "onBlock" | "onSlot" => onBlockFn->Utils.magic
|
|
495
550
|
| "~internalAndWillBeRemovedSoon_onRollbackCommit" => onRollbackCommitFn->Utils.magic
|
|
@@ -791,8 +846,12 @@ let start = async (
|
|
|
791
846
|
~onError,
|
|
792
847
|
)
|
|
793
848
|
let gsManager =
|
|
794
|
-
globalState->GlobalStateManager.make(
|
|
795
|
-
|
|
849
|
+
globalState->GlobalStateManager.make(
|
|
850
|
+
~reducers=GlobalState.makeReducers(
|
|
851
|
+
~markBatchProcessed=MarkBatchProcessedAdapter.make(~inMemoryStore=ctx.inMemoryStore),
|
|
852
|
+
),
|
|
853
|
+
~onError=exn =>
|
|
854
|
+
onError(exn->ErrorHandling.make(~msg="Indexer has failed with an unexpected error")),
|
|
796
855
|
)
|
|
797
856
|
if shouldUseTui {
|
|
798
857
|
let _rerender = Tui.start(~getState=() => gsManager->GlobalStateManager.getState)
|
package/src/Main.res.mjs
CHANGED
|
@@ -32,6 +32,7 @@ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js
|
|
|
32
32
|
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
33
33
|
import * as GlobalStateManager from "./GlobalStateManager.res.mjs";
|
|
34
34
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
35
|
+
import * as MarkBatchProcessedAdapter from "./adapters/MarkBatchProcessedAdapter.res.mjs";
|
|
35
36
|
|
|
36
37
|
let chainDataSchema = S$RescriptSchema.schema(s => ({
|
|
37
38
|
chainId: s.m(S$RescriptSchema.float),
|
|
@@ -251,6 +252,38 @@ function getGlobalIndexer() {
|
|
|
251
252
|
let match = parseIdentityConfig(identityConfig);
|
|
252
253
|
HandlerRegister.setHandler(match[0], match[1], handler, match[2], undefined);
|
|
253
254
|
};
|
|
255
|
+
let parseSvmIdentityConfig = identityConfig => {
|
|
256
|
+
let match;
|
|
257
|
+
if (typeof identityConfig.program === "string") {
|
|
258
|
+
match = [
|
|
259
|
+
identityConfig.program,
|
|
260
|
+
identityConfig.instruction
|
|
261
|
+
];
|
|
262
|
+
} else {
|
|
263
|
+
let inst = identityConfig.instruction;
|
|
264
|
+
match = [
|
|
265
|
+
inst.contract,
|
|
266
|
+
inst._0
|
|
267
|
+
];
|
|
268
|
+
}
|
|
269
|
+
let where = identityConfig.where;
|
|
270
|
+
let eventOptions = where !== undefined ? ({
|
|
271
|
+
where: where
|
|
272
|
+
}) : undefined;
|
|
273
|
+
return [
|
|
274
|
+
match[0],
|
|
275
|
+
match[1],
|
|
276
|
+
eventOptions
|
|
277
|
+
];
|
|
278
|
+
};
|
|
279
|
+
let onInstructionFn = (identityConfig, handler) => {
|
|
280
|
+
HandlerRegister.throwIfFinishedRegistration("onInstruction");
|
|
281
|
+
let match = parseSvmIdentityConfig(identityConfig);
|
|
282
|
+
HandlerRegister.setHandler(match[0], match[1], args => handler({
|
|
283
|
+
instruction: args.event,
|
|
284
|
+
context: args.context
|
|
285
|
+
}), match[2], undefined);
|
|
286
|
+
};
|
|
254
287
|
let contractRegisterFn = (identityConfig, handler) => {
|
|
255
288
|
HandlerRegister.throwIfFinishedRegistration("contractRegister");
|
|
256
289
|
let match = parseIdentityConfig(identityConfig);
|
|
@@ -346,6 +379,7 @@ function getGlobalIndexer() {
|
|
|
346
379
|
"description",
|
|
347
380
|
"chainIds",
|
|
348
381
|
"chains",
|
|
382
|
+
"onInstruction",
|
|
349
383
|
"onSlot",
|
|
350
384
|
"~internalAndWillBeRemovedSoon_onRollbackCommit"
|
|
351
385
|
];
|
|
@@ -380,6 +414,8 @@ function getGlobalIndexer() {
|
|
|
380
414
|
return Config.loadWithoutRegistrations().name;
|
|
381
415
|
case "onEvent" :
|
|
382
416
|
return onEventFn;
|
|
417
|
+
case "onInstruction" :
|
|
418
|
+
return onInstructionFn;
|
|
383
419
|
case "onBlock" :
|
|
384
420
|
case "onSlot" :
|
|
385
421
|
return onBlockFn;
|
|
@@ -587,7 +623,7 @@ async function start(persistence, resetOpt, isTestOpt, exitAfterFirstEventBlockO
|
|
|
587
623
|
}
|
|
588
624
|
let chainManager = ChainManager.makeFromDbState(Persistence.getInitializedState(persistence$1), config$2, registrations, undefined);
|
|
589
625
|
let globalState = GlobalState.make(ctx, chainManager, isDevelopmentMode, shouldUseTui, exitAfterFirstEventBlock, onError);
|
|
590
|
-
let gsManager = GlobalStateManager.make(globalState, exn => onError(ErrorHandling.make(exn, undefined, "Indexer has failed with an unexpected error")));
|
|
626
|
+
let gsManager = GlobalStateManager.make(globalState, GlobalState.makeReducers(undefined, undefined, undefined, MarkBatchProcessedAdapter.make(ctx_inMemoryStore)), exn => onError(ErrorHandling.make(exn, undefined, "Indexer has failed with an unexpected error")));
|
|
591
627
|
if (shouldUseTui) {
|
|
592
628
|
Tui.start(() => GlobalStateManager.getState(gsManager));
|
|
593
629
|
}
|
package/src/Persistence.res
CHANGED
|
@@ -40,8 +40,6 @@ type initialState = {
|
|
|
40
40
|
envioInfo: option<JSON.t>,
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
type operator = [#">" | #"=" | #"<"]
|
|
44
|
-
|
|
45
43
|
type updatedEffectCache = {
|
|
46
44
|
effect: Internal.effect,
|
|
47
45
|
items: array<Internal.effectCacheItem>,
|
|
@@ -78,21 +76,10 @@ type storage = {
|
|
|
78
76
|
~envioInfo: JSON.t,
|
|
79
77
|
) => promise<initialState>,
|
|
80
78
|
resumeInitialState: unit => promise<initialState>,
|
|
79
|
+
// Returns rows matching the filter.
|
|
80
|
+
// Field values are serialized and rows parsed with the table's field schemas.
|
|
81
81
|
@raises("StorageError")
|
|
82
|
-
|
|
83
|
-
~ids: array<string>,
|
|
84
|
-
~table: Table.table,
|
|
85
|
-
~rowsSchema: S.t<array<'item>>,
|
|
86
|
-
) => promise<array<'item>>,
|
|
87
|
-
@raises("StorageError")
|
|
88
|
-
loadByFieldOrThrow: 'item 'value. (
|
|
89
|
-
~fieldName: string,
|
|
90
|
-
~fieldSchema: S.t<'value>,
|
|
91
|
-
~fieldValue: 'value,
|
|
92
|
-
~operator: operator,
|
|
93
|
-
~table: Table.table,
|
|
94
|
-
~rowsSchema: S.t<array<'item>>,
|
|
95
|
-
) => promise<array<'item>>,
|
|
82
|
+
loadOrThrow: (~filter: EntityFilter.t, ~table: Table.table) => promise<array<unknown>>,
|
|
96
83
|
// This is to download cache from the database to .envio/cache
|
|
97
84
|
dumpEffectCache: unit => promise<unit>,
|
|
98
85
|
reset: unit => promise<unit>,
|