envio 3.5.0-alpha.2 → 3.5.0-rc.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/package.json +6 -6
- package/src/Batch.res +8 -8
- package/src/Batch.res.mjs +4 -3
- package/src/BatchProcessing.res +24 -0
- package/src/BatchProcessing.res.mjs +12 -0
- package/src/ChainFetching.res +20 -19
- package/src/ChainFetching.res.mjs +14 -14
- package/src/ChainId.res +58 -0
- package/src/ChainId.res.mjs +49 -0
- package/src/ChainId.resi +27 -0
- package/src/ChainMap.res +12 -26
- package/src/ChainMap.res.mjs +5 -41
- package/src/ChainMap.resi +5 -20
- package/src/ChainMetadata.res +1 -1
- package/src/ChainMetadata.res.mjs +3 -2
- package/src/ChainState.res +45 -24
- package/src/ChainState.res.mjs +40 -16
- package/src/ChainState.resi +3 -1
- package/src/Config.res +43 -26
- package/src/Config.res.mjs +19 -16
- package/src/ContractRegisterContext.res +1 -1
- package/src/ContractRegisterContext.res.mjs +1 -1
- package/src/Core.res +1 -0
- package/src/CrossChainState.res +90 -22
- package/src/CrossChainState.res.mjs +55 -16
- package/src/CrossChainState.resi +5 -1
- package/src/Env.res +0 -3
- package/src/Env.res.mjs +0 -3
- package/src/EventConfigBuilder.res +1 -1
- package/src/EventProcessing.res +4 -4
- package/src/EventProcessing.res.mjs +5 -5
- package/src/FetchState.res +489 -153
- package/src/FetchState.res.mjs +399 -129
- package/src/FinalizeBackfill.res +61 -0
- package/src/FinalizeBackfill.res.mjs +44 -0
- package/src/HandlerRegister.res +8 -8
- package/src/HandlerRegister.res.mjs +5 -4
- package/src/HandlerRegister.resi +1 -1
- package/src/InMemoryStore.res +4 -0
- package/src/InMemoryStore.res.mjs +1 -1
- package/src/InMemoryTable.res +15 -15
- package/src/InMemoryTable.res.mjs +14 -14
- package/src/IndexerLoop.res +9 -2
- package/src/IndexerLoop.res.mjs +8 -1
- package/src/IndexerState.res +52 -23
- package/src/IndexerState.res.mjs +52 -14
- package/src/IndexerState.resi +11 -6
- package/src/Internal.res +19 -17
- package/src/Internal.res.mjs +18 -9
- package/src/LoadLayer.res +10 -2
- package/src/LoadLayer.res.mjs +3 -1
- package/src/LogSelection.res +2 -2
- package/src/Main.res +7 -11
- package/src/Main.res.mjs +4 -6
- package/src/Metrics.res +6 -6
- package/src/Metrics.res.mjs +4 -3
- package/src/Persistence.res +23 -4
- package/src/PgStorage.res +447 -100
- package/src/PgStorage.res.mjs +285 -99
- package/src/RawEvent.res +1 -2
- package/src/RawEvent.res.mjs +1 -1
- package/src/Rollback.res +18 -20
- package/src/Rollback.res.mjs +9 -9
- package/src/RollbackCommit.res +2 -2
- package/src/RollbackCommit.res.mjs +3 -3
- package/src/SafeCheckpointTracking.res +2 -2
- package/src/SimulateDeadInputTracker.res +17 -21
- package/src/SimulateDeadInputTracker.res.mjs +9 -8
- package/src/SimulateItems.res +8 -10
- package/src/SimulateItems.res.mjs +9 -10
- package/src/Sink.res +2 -2
- package/src/Sink.res.mjs +3 -2
- package/src/TestIndexer.res +14 -14
- package/src/TestIndexer.res.mjs +16 -10
- package/src/UserContext.res +2 -2
- package/src/UserContext.res.mjs +2 -1
- package/src/Utils.res +0 -4
- package/src/Utils.res.mjs +1 -6
- package/src/bindings/ClickHouse.res +20 -2
- package/src/bindings/ClickHouse.res.mjs +25 -14
- package/src/db/EntityFilter.res +0 -4
- package/src/db/EntityFilter.res.mjs +1 -8
- package/src/db/EntityHistory.res +1 -1
- package/src/db/IndexCatalog.res +248 -0
- package/src/db/IndexCatalog.res.mjs +222 -0
- package/src/db/IndexDefinition.res +131 -0
- package/src/db/IndexDefinition.res.mjs +138 -0
- package/src/db/IndexManager.res +145 -0
- package/src/db/IndexManager.res.mjs +130 -0
- package/src/db/InternalTable.res +54 -23
- package/src/db/InternalTable.res.mjs +38 -23
- package/src/db/Table.res +24 -14
- package/src/db/Table.res.mjs +21 -16
- package/src/sources/AddressSet.res +5 -4
- package/src/sources/AddressStore.res +25 -14
- package/src/sources/AddressStore.res.mjs +10 -12
- package/src/sources/Evm.res +2 -2
- package/src/sources/Evm.res.mjs +1 -1
- package/src/sources/EvmChain.res +3 -3
- package/src/sources/EvmChain.res.mjs +3 -3
- package/src/sources/EvmHyperSyncSource.res +7 -7
- package/src/sources/EvmHyperSyncSource.res.mjs +6 -6
- package/src/sources/Fuel.res +2 -2
- package/src/sources/Fuel.res.mjs +1 -1
- package/src/sources/FuelHyperSyncClient.res +3 -0
- package/src/sources/FuelHyperSyncClient.res.mjs +1 -0
- package/src/sources/FuelHyperSyncSource.res +5 -7
- package/src/sources/FuelHyperSyncSource.res.mjs +5 -5
- package/src/sources/HyperSync.resi +2 -2
- package/src/sources/HyperSyncClient.res +5 -0
- package/src/sources/HyperSyncClient.res.mjs +1 -0
- package/src/sources/RpcSource.res +13 -14
- package/src/sources/RpcSource.res.mjs +13 -12
- package/src/sources/SimulateSource.res +42 -15
- package/src/sources/SimulateSource.res.mjs +27 -9
- package/src/sources/Source.res +1 -5
- package/src/sources/SourceManager.res +12 -12
- package/src/sources/SourceManager.res.mjs +11 -10
- package/src/sources/SourceManager.resi +2 -2
- package/src/sources/Svm.res +4 -5
- package/src/sources/Svm.res.mjs +5 -4
- package/src/sources/SvmHyperSyncClient.res +3 -0
- package/src/sources/SvmHyperSyncClient.res.mjs +1 -0
- package/src/sources/SvmHyperSyncSource.res +4 -4
- package/src/sources/SvmHyperSyncSource.res.mjs +3 -3
- package/src/tui/Tui.res +1 -1
- package/src/tui/Tui.res.mjs +2 -1
- package/src/tui/components/CustomHooks.res +5 -4
- package/src/tui/components/CustomHooks.res.mjs +4 -2
package/src/db/Table.res.mjs
CHANGED
|
@@ -96,7 +96,8 @@ function getPgFieldName(fieldOrDerived) {
|
|
|
96
96
|
|
|
97
97
|
let idFieldName = "id";
|
|
98
98
|
|
|
99
|
-
function getPgFieldType(fieldType, pgSchema, isArray, isNumericArrayAsText, isNullable) {
|
|
99
|
+
function getPgFieldType(fieldType, pgSchema, isArray, isNumericArrayAsText, isNullable, chainIdModeOpt) {
|
|
100
|
+
let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
|
|
100
101
|
let columnType;
|
|
101
102
|
if (typeof fieldType !== "object") {
|
|
102
103
|
switch (fieldType) {
|
|
@@ -109,6 +110,9 @@ function getPgFieldType(fieldType, pgSchema, isArray, isNumericArrayAsText, isNu
|
|
|
109
110
|
case "Int32" :
|
|
110
111
|
columnType = "INTEGER";
|
|
111
112
|
break;
|
|
113
|
+
case "ChainId" :
|
|
114
|
+
columnType = chainIdMode === "int32" ? "INTEGER" : "BIGINT";
|
|
115
|
+
break;
|
|
112
116
|
case "Number" :
|
|
113
117
|
columnType = "DOUBLE PRECISION";
|
|
114
118
|
break;
|
|
@@ -153,12 +157,12 @@ function getPgFieldType(fieldType, pgSchema, isArray, isNumericArrayAsText, isNu
|
|
|
153
157
|
);
|
|
154
158
|
}
|
|
155
159
|
|
|
156
|
-
function mkTable(tableName,
|
|
157
|
-
let
|
|
160
|
+
function mkTable(tableName, compositeIndexesOpt, fields, description) {
|
|
161
|
+
let compositeIndexes = compositeIndexesOpt !== undefined ? compositeIndexesOpt : [];
|
|
158
162
|
return {
|
|
159
163
|
tableName: tableName,
|
|
160
164
|
fields: fields,
|
|
161
|
-
|
|
165
|
+
compositeIndexes: compositeIndexes,
|
|
162
166
|
description: description
|
|
163
167
|
};
|
|
164
168
|
}
|
|
@@ -247,7 +251,7 @@ function getIdFieldOrThrow(table) {
|
|
|
247
251
|
}
|
|
248
252
|
|
|
249
253
|
function getIdPgFieldType(table, pgSchema) {
|
|
250
|
-
return getPgFieldType(getIdFieldOrThrow(table).fieldType, pgSchema, false, false, false);
|
|
254
|
+
return getPgFieldType(getIdFieldOrThrow(table).fieldType, pgSchema, false, false, false, undefined);
|
|
251
255
|
}
|
|
252
256
|
|
|
253
257
|
function getIdSchema(table) {
|
|
@@ -304,8 +308,8 @@ let pgRowsSchema = Utils.$$WeakMap.memoize(table => makeRowsSchema(table, getPgD
|
|
|
304
308
|
|
|
305
309
|
let NonExistingTableField = /* @__PURE__ */Primitive_exceptions.create("Table.NonExistingTableField");
|
|
306
310
|
|
|
307
|
-
function
|
|
308
|
-
return table.
|
|
311
|
+
function getUnfilteredCompositeIndexesUnsafe(table) {
|
|
312
|
+
return table.compositeIndexes.map(compositeIndex => compositeIndex.map(indexField => {
|
|
309
313
|
let field = getFieldByName(table, indexField.fieldName);
|
|
310
314
|
let dbFieldName;
|
|
311
315
|
if (field !== undefined) {
|
|
@@ -324,7 +328,8 @@ function getUnfilteredCompositeIndicesUnsafe(table) {
|
|
|
324
328
|
}));
|
|
325
329
|
}
|
|
326
330
|
|
|
327
|
-
function toSqlParams(table, schema, pgSchema) {
|
|
331
|
+
function toSqlParams(table, schema, pgSchema, chainIdModeOpt) {
|
|
332
|
+
let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
|
|
328
333
|
let quotedFieldNames = [];
|
|
329
334
|
let quotedNonPrimaryFieldNames = [];
|
|
330
335
|
let arrayFieldTypes = [];
|
|
@@ -395,7 +400,7 @@ function toSqlParams(table, schema, pgSchema) {
|
|
|
395
400
|
let tmp;
|
|
396
401
|
if (field$1.TAG === "Field") {
|
|
397
402
|
let f = field$1._0;
|
|
398
|
-
let pgFieldType = getPgFieldType(f.fieldType, pgSchema, true, false, f.isNullable);
|
|
403
|
+
let pgFieldType = getPgFieldType(f.fieldType, pgSchema, true, false, f.isNullable, chainIdMode);
|
|
399
404
|
let match = f.fieldType;
|
|
400
405
|
tmp = typeof match !== "object" ? (
|
|
401
406
|
match === "Boolean" ? "INTEGER" + `[]::` + pgFieldType : pgFieldType
|
|
@@ -419,7 +424,7 @@ function toSqlParams(table, schema, pgSchema) {
|
|
|
419
424
|
};
|
|
420
425
|
}
|
|
421
426
|
|
|
422
|
-
function
|
|
427
|
+
function getSingleIndexes(table) {
|
|
423
428
|
let indexFields = Stdlib_Array.filterMap(table.fields, field => {
|
|
424
429
|
if (field.TAG !== "Field") {
|
|
425
430
|
return;
|
|
@@ -429,7 +434,7 @@ function getSingleIndices(table) {
|
|
|
429
434
|
return getPgDbFieldName(field$1);
|
|
430
435
|
}
|
|
431
436
|
});
|
|
432
|
-
return Array.from(new Set(Stdlib_Array.filterMap(
|
|
437
|
+
return Array.from(new Set(Stdlib_Array.filterMap(getUnfilteredCompositeIndexesUnsafe(table), cidx => {
|
|
433
438
|
if (cidx.length !== 1) {
|
|
434
439
|
return;
|
|
435
440
|
}
|
|
@@ -438,8 +443,8 @@ function getSingleIndices(table) {
|
|
|
438
443
|
}).concat([indexFields]).flat())).toSorted(Primitive_string.compare);
|
|
439
444
|
}
|
|
440
445
|
|
|
441
|
-
function
|
|
442
|
-
return
|
|
446
|
+
function getCompositeIndexes(table) {
|
|
447
|
+
return getUnfilteredCompositeIndexesUnsafe(table).filter(ind => ind.length > 1);
|
|
443
448
|
}
|
|
444
449
|
|
|
445
450
|
export {
|
|
@@ -473,9 +478,9 @@ export {
|
|
|
473
478
|
rowsSchema,
|
|
474
479
|
pgRowsSchema,
|
|
475
480
|
NonExistingTableField,
|
|
476
|
-
|
|
481
|
+
getUnfilteredCompositeIndexesUnsafe,
|
|
477
482
|
toSqlParams,
|
|
478
|
-
|
|
479
|
-
|
|
483
|
+
getSingleIndexes,
|
|
484
|
+
getCompositeIndexes,
|
|
480
485
|
}
|
|
481
486
|
/* idsArraySchema Not a pure module */
|
|
@@ -15,10 +15,11 @@ type startBlockGroup = {startBlock: int, count: int}
|
|
|
15
15
|
// fetch state can size and split partitions without ever walking the addresses.
|
|
16
16
|
@send external countFor: (t, string) => int = "countFor"
|
|
17
17
|
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
|
|
18
|
+
// This set holds the address under the contract and it has already started at
|
|
19
|
+
// the block — the gate a real source's router applies to a server-side
|
|
20
|
+
// address-filtered query. The temporal half still comes from the store: a
|
|
21
|
+
// merged partition's addresses don't all start at the same block.
|
|
22
|
+
@send external containsAt: (t, Address.t, string, int) => bool = "containsAt"
|
|
22
23
|
|
|
23
24
|
@send external contractNames: t => array<string> = "contractNames"
|
|
24
25
|
|
|
@@ -67,28 +67,39 @@ let make = (~ecosystem: Ecosystem.name, ~shouldChecksum: bool, ~contracts: array
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
// The contracts of a chain that have events, with the earliest block any of
|
|
70
|
-
// their events may fire at.
|
|
70
|
+
// their events may fire at. `None` means unrestricted, so it wins over any
|
|
71
|
+
// `Some`: one registration without a start block makes the whole contract's
|
|
72
|
+
// address gate open from the chain's start, and the per-registration start
|
|
73
|
+
// block still holds back the registrations that declared one.
|
|
71
74
|
let contractsOf = (~onEventRegistrations: array<Internal.onEventRegistration>): array<contract> => {
|
|
72
|
-
|
|
75
|
+
// Only ever holds a declared start block, so a missing key is unambiguous —
|
|
76
|
+
// storing `None` in a dict would be indistinguishable from "not seen yet".
|
|
77
|
+
let startBlocks: dict<int> = Dict.make()
|
|
78
|
+
let unrestricted = Utils.Set.make()
|
|
73
79
|
let names = []
|
|
74
80
|
onEventRegistrations->Array.forEach(reg => {
|
|
75
81
|
let name = reg.eventConfig.contractName
|
|
76
|
-
|
|
77
|
-
| None =>
|
|
82
|
+
if !(names->Array.includes(name)) {
|
|
78
83
|
names->Array.push(name)->ignore
|
|
79
|
-
|
|
80
|
-
|
|
84
|
+
}
|
|
85
|
+
switch reg.startBlock {
|
|
86
|
+
| None => unrestricted->Utils.Set.add(name)->ignore
|
|
87
|
+
| Some(startBlock) =>
|
|
81
88
|
startBlocks->Dict.set(
|
|
82
89
|
name,
|
|
83
|
-
switch (
|
|
84
|
-
|
|
|
85
|
-
|
|
|
86
|
-
| (None, None) => None
|
|
90
|
+
switch startBlocks->Utils.Dict.dangerouslyGetNonOption(name) {
|
|
91
|
+
| Some(existing) => Pervasives.min(existing, startBlock)
|
|
92
|
+
| None => startBlock
|
|
87
93
|
},
|
|
88
94
|
)
|
|
89
95
|
}
|
|
90
96
|
})
|
|
91
|
-
names->Array.map(name => {
|
|
97
|
+
names->Array.map(name => {
|
|
98
|
+
name,
|
|
99
|
+
startBlock: unrestricted->Utils.Set.has(name)
|
|
100
|
+
? None
|
|
101
|
+
: startBlocks->Utils.Dict.dangerouslyGetNonOption(name),
|
|
102
|
+
})
|
|
92
103
|
}
|
|
93
104
|
|
|
94
105
|
@send external nextId: t => int = "nextId"
|
|
@@ -108,9 +119,9 @@ external startBlockGroups: (t, string) => array<AddressSet.startBlockGroup> = "s
|
|
|
108
119
|
@send external contractCount: (t, string) => int = "contractCount"
|
|
109
120
|
@send external size: t => int = "size"
|
|
110
121
|
|
|
111
|
-
// The gate routing applies, exposed for the simulate source — it has
|
|
112
|
-
// query boundary to gate at.
|
|
113
|
-
@send external
|
|
122
|
+
// The chain-wide gate routing applies, exposed for the simulate source — it has
|
|
123
|
+
// no real query boundary to gate at.
|
|
124
|
+
@send external isIndexedAt: (t, Address.t, string, int) => bool = "isIndexedAt"
|
|
114
125
|
|
|
115
126
|
// Drops every address registered after the target block, returning how many
|
|
116
127
|
// were dropped. Ids are tombstoned rather than reused, so sets built before the
|
|
@@ -19,26 +19,24 @@ function make(ecosystem, shouldChecksum, contracts) {
|
|
|
19
19
|
|
|
20
20
|
function contractsOf(onEventRegistrations) {
|
|
21
21
|
let startBlocks = {};
|
|
22
|
+
let unrestricted = new Set();
|
|
22
23
|
let names = [];
|
|
23
24
|
onEventRegistrations.forEach(reg => {
|
|
24
25
|
let name = reg.eventConfig.contractName;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
match !== undefined ? match : undefined
|
|
33
|
-
);
|
|
26
|
+
if (!names.includes(name)) {
|
|
27
|
+
names.push(name);
|
|
28
|
+
}
|
|
29
|
+
let startBlock = reg.startBlock;
|
|
30
|
+
if (startBlock !== undefined) {
|
|
31
|
+
let existing = startBlocks[name];
|
|
32
|
+
startBlocks[name] = existing !== undefined ? Primitive_int.min(existing, startBlock) : startBlock;
|
|
34
33
|
return;
|
|
35
34
|
}
|
|
36
|
-
|
|
37
|
-
startBlocks[name] = reg.startBlock;
|
|
35
|
+
unrestricted.add(name);
|
|
38
36
|
});
|
|
39
37
|
return names.map(name => ({
|
|
40
38
|
name: name,
|
|
41
|
-
startBlock: startBlocks[name]
|
|
39
|
+
startBlock: unrestricted.has(name) ? undefined : startBlocks[name]
|
|
42
40
|
}));
|
|
43
41
|
}
|
|
44
42
|
|
package/src/sources/Evm.res
CHANGED
|
@@ -6,7 +6,7 @@ type payload = {
|
|
|
6
6
|
contractName: string,
|
|
7
7
|
eventName: string,
|
|
8
8
|
params: Internal.eventParams,
|
|
9
|
-
chainId:
|
|
9
|
+
chainId: ChainId.t,
|
|
10
10
|
srcAddress: Address.t,
|
|
11
11
|
logIndex: int,
|
|
12
12
|
transaction?: Internal.eventTransaction,
|
|
@@ -106,7 +106,7 @@ let make = (~logger: Pino.t): Ecosystem.t => {
|
|
|
106
106
|
~params={
|
|
107
107
|
"contract": eventItem.onEventRegistration.eventConfig.contractName,
|
|
108
108
|
"event": eventItem.onEventRegistration.eventConfig.name,
|
|
109
|
-
"chainId": eventItem.
|
|
109
|
+
"chainId": eventItem.chainId,
|
|
110
110
|
"block": eventItem.blockNumber,
|
|
111
111
|
"logIndex": eventItem.logIndex,
|
|
112
112
|
"address": (eventItem.payload->toPayload).srcAddress,
|
package/src/sources/Evm.res.mjs
CHANGED
|
@@ -64,7 +64,7 @@ function make(logger) {
|
|
|
64
64
|
toEventLogger: eventItem => Logging.createChildFrom(logger, {
|
|
65
65
|
contract: eventItem.onEventRegistration.eventConfig.contractName,
|
|
66
66
|
event: eventItem.onEventRegistration.eventConfig.name,
|
|
67
|
-
chainId: eventItem.
|
|
67
|
+
chainId: eventItem.chainId,
|
|
68
68
|
block: eventItem.blockNumber,
|
|
69
69
|
logIndex: eventItem.logIndex,
|
|
70
70
|
address: eventItem.payload.srcAddress
|
package/src/sources/EvmChain.res
CHANGED
|
@@ -40,7 +40,7 @@ let getSyncConfig = (
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
let makeSources = (
|
|
43
|
-
~
|
|
43
|
+
~chainId,
|
|
44
44
|
~onEventRegistrations: array<Internal.evmOnEventRegistration>,
|
|
45
45
|
~hyperSync,
|
|
46
46
|
~rpcs: array<rpc>,
|
|
@@ -50,7 +50,7 @@ let makeSources = (
|
|
|
50
50
|
let sources = switch hyperSync {
|
|
51
51
|
| Some(endpointUrl) => [
|
|
52
52
|
EvmHyperSyncSource.make({
|
|
53
|
-
|
|
53
|
+
chainId,
|
|
54
54
|
endpointUrl,
|
|
55
55
|
onEventRegistrations,
|
|
56
56
|
apiToken: Env.envioApiToken,
|
|
@@ -66,7 +66,7 @@ let makeSources = (
|
|
|
66
66
|
}
|
|
67
67
|
rpcs->Array.forEach(({?syncConfig, url, sourceFor, ?ws, ?headers}) => {
|
|
68
68
|
let source = RpcSource.make({
|
|
69
|
-
|
|
69
|
+
chainId,
|
|
70
70
|
sourceFor,
|
|
71
71
|
syncConfig: getSyncConfig(syncConfig->Option.getOr({})),
|
|
72
72
|
url,
|
|
@@ -19,9 +19,9 @@ function getSyncConfig(param) {
|
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
function makeSources(
|
|
22
|
+
function makeSources(chainId, onEventRegistrations, hyperSync, rpcs, lowercaseAddresses, addressStore) {
|
|
23
23
|
let sources = hyperSync !== undefined ? [EvmHyperSyncSource.make({
|
|
24
|
-
|
|
24
|
+
chainId: chainId,
|
|
25
25
|
endpointUrl: hyperSync,
|
|
26
26
|
onEventRegistrations: onEventRegistrations,
|
|
27
27
|
apiToken: Env.envioApiToken,
|
|
@@ -37,7 +37,7 @@ function makeSources(chain, onEventRegistrations, hyperSync, rpcs, lowercaseAddr
|
|
|
37
37
|
sourceFor: param.sourceFor,
|
|
38
38
|
syncConfig: getSyncConfig(Stdlib_Option.getOr(param.syncConfig, {})),
|
|
39
39
|
url: param.url,
|
|
40
|
-
|
|
40
|
+
chainId: chainId,
|
|
41
41
|
onEventRegistrations: onEventRegistrations,
|
|
42
42
|
lowercaseAddresses: lowercaseAddresses,
|
|
43
43
|
addressStore: addressStore,
|
|
@@ -6,7 +6,7 @@ open Source
|
|
|
6
6
|
let isUnauthorizedError = (message: string) => message->String.includes("401 Unauthorized")
|
|
7
7
|
|
|
8
8
|
type options = {
|
|
9
|
-
|
|
9
|
+
chainId: ChainId.t,
|
|
10
10
|
endpointUrl: string,
|
|
11
11
|
// The chain's registrations, indexed by their sequential `index`.
|
|
12
12
|
onEventRegistrations: array<Internal.evmOnEventRegistration>,
|
|
@@ -22,7 +22,7 @@ type options = {
|
|
|
22
22
|
|
|
23
23
|
let make = (
|
|
24
24
|
{
|
|
25
|
-
|
|
25
|
+
chainId,
|
|
26
26
|
endpointUrl,
|
|
27
27
|
onEventRegistrations,
|
|
28
28
|
apiToken,
|
|
@@ -70,7 +70,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
70
70
|
|
|
71
71
|
Internal.Event({
|
|
72
72
|
onEventRegistration: (onEventRegistration :> Internal.onEventRegistration),
|
|
73
|
-
|
|
73
|
+
chainId,
|
|
74
74
|
blockNumber: item.blockNumber,
|
|
75
75
|
logIndex,
|
|
76
76
|
transactionIndex,
|
|
@@ -79,7 +79,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
79
79
|
payload: {
|
|
80
80
|
contractName: onEventRegistration.eventConfig.contractName,
|
|
81
81
|
eventName: onEventRegistration.eventConfig.name,
|
|
82
|
-
chainId:
|
|
82
|
+
chainId: chainId,
|
|
83
83
|
params: item.params,
|
|
84
84
|
srcAddress,
|
|
85
85
|
logIndex,
|
|
@@ -253,7 +253,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
253
253
|
~client,
|
|
254
254
|
~blockNumbers,
|
|
255
255
|
~sourceName=name,
|
|
256
|
-
~chainId=
|
|
256
|
+
~chainId=chainId,
|
|
257
257
|
~logger,
|
|
258
258
|
)->Promise.thenResolve(((queryRes, requestStats)) => {
|
|
259
259
|
Source.result: queryRes->HyperSync.mapExn,
|
|
@@ -263,7 +263,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
263
263
|
{
|
|
264
264
|
name,
|
|
265
265
|
sourceFor: Sync,
|
|
266
|
-
|
|
266
|
+
chainId,
|
|
267
267
|
pollingInterval: 100,
|
|
268
268
|
poweredByHyperSync: true,
|
|
269
269
|
getBlockHashes,
|
|
@@ -290,7 +290,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
290
290
|
HyperSyncHeightStream.subscribe(
|
|
291
291
|
~hyperSyncUrl=endpointUrl,
|
|
292
292
|
~apiToken,
|
|
293
|
-
~chainId=
|
|
293
|
+
~chainId=chainId,
|
|
294
294
|
~onHeight,
|
|
295
295
|
),
|
|
296
296
|
}
|
|
@@ -21,7 +21,7 @@ function make(param) {
|
|
|
21
21
|
let apiToken = param.apiToken;
|
|
22
22
|
let onEventRegistrations = param.onEventRegistrations;
|
|
23
23
|
let endpointUrl = param.endpointUrl;
|
|
24
|
-
let
|
|
24
|
+
let chainId = param.chainId;
|
|
25
25
|
let name = "HyperSync";
|
|
26
26
|
let apiToken$1 = apiToken !== undefined ? apiToken : Stdlib_JsError.throwWithMessage(`An Envio API token is required for using HyperSync as a data-source.
|
|
27
27
|
Set the ENVIO_API_TOKEN environment variable in your .env file.
|
|
@@ -38,7 +38,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
38
38
|
return {
|
|
39
39
|
kind: 0,
|
|
40
40
|
onEventRegistration: onEventRegistration,
|
|
41
|
-
|
|
41
|
+
chainId: chainId,
|
|
42
42
|
blockNumber: item.blockNumber,
|
|
43
43
|
logIndex: logIndex,
|
|
44
44
|
transactionIndex: item.transactionIndex,
|
|
@@ -46,7 +46,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
46
46
|
contractName: onEventRegistration.eventConfig.contractName,
|
|
47
47
|
eventName: onEventRegistration.eventConfig.name,
|
|
48
48
|
params: item.params,
|
|
49
|
-
chainId:
|
|
49
|
+
chainId: chainId,
|
|
50
50
|
srcAddress: item.srcAddress,
|
|
51
51
|
logIndex: logIndex
|
|
52
52
|
}
|
|
@@ -170,14 +170,14 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
170
170
|
requestStats: requestStats
|
|
171
171
|
};
|
|
172
172
|
};
|
|
173
|
-
let getBlockHashes = (blockNumbers, logger) => HyperSync.queryBlockDataMulti(client, blockNumbers, name,
|
|
173
|
+
let getBlockHashes = (blockNumbers, logger) => HyperSync.queryBlockDataMulti(client, blockNumbers, name, chainId, logger).then(param => ({
|
|
174
174
|
result: HyperSync.mapExn(param[0]),
|
|
175
175
|
requestStats: param[1]
|
|
176
176
|
}));
|
|
177
177
|
return {
|
|
178
178
|
name: name,
|
|
179
179
|
sourceFor: "Sync",
|
|
180
|
-
|
|
180
|
+
chainId: chainId,
|
|
181
181
|
poweredByHyperSync: true,
|
|
182
182
|
pollingInterval: 100,
|
|
183
183
|
getBlockHashes: getBlockHashes,
|
|
@@ -224,7 +224,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
224
224
|
};
|
|
225
225
|
},
|
|
226
226
|
getItemsOrThrow: getItemsOrThrow,
|
|
227
|
-
createHeightSubscription: onHeight => HyperSyncHeightStream.subscribe(endpointUrl, apiToken$1,
|
|
227
|
+
createHeightSubscription: onHeight => HyperSyncHeightStream.subscribe(endpointUrl, apiToken$1, chainId, onHeight)
|
|
228
228
|
};
|
|
229
229
|
}
|
|
230
230
|
|
package/src/sources/Fuel.res
CHANGED
|
@@ -4,7 +4,7 @@ type payload = {
|
|
|
4
4
|
contractName: string,
|
|
5
5
|
eventName: string,
|
|
6
6
|
params: Internal.eventParams,
|
|
7
|
-
chainId:
|
|
7
|
+
chainId: ChainId.t,
|
|
8
8
|
srcAddress: Address.t,
|
|
9
9
|
logIndex: int,
|
|
10
10
|
transaction: Internal.eventTransaction,
|
|
@@ -48,7 +48,7 @@ let make = (~logger: Pino.t): Ecosystem.t => {
|
|
|
48
48
|
~params={
|
|
49
49
|
"contract": eventItem.onEventRegistration.eventConfig.contractName,
|
|
50
50
|
"event": eventItem.onEventRegistration.eventConfig.name,
|
|
51
|
-
"chainId": eventItem.
|
|
51
|
+
"chainId": eventItem.chainId,
|
|
52
52
|
"block": eventItem.blockNumber,
|
|
53
53
|
"logIndex": eventItem.logIndex,
|
|
54
54
|
"address": (eventItem.payload->toPayload).srcAddress,
|
package/src/sources/Fuel.res.mjs
CHANGED
|
@@ -25,7 +25,7 @@ function make(logger) {
|
|
|
25
25
|
toEventLogger: eventItem => Logging.createChildFrom(logger, {
|
|
26
26
|
contract: eventItem.onEventRegistration.eventConfig.contractName,
|
|
27
27
|
event: eventItem.onEventRegistration.eventConfig.name,
|
|
28
|
-
chainId: eventItem.
|
|
28
|
+
chainId: eventItem.chainId,
|
|
29
29
|
block: eventItem.blockNumber,
|
|
30
30
|
logIndex: eventItem.logIndex,
|
|
31
31
|
address: eventItem.payload.srcAddress
|
|
@@ -22,6 +22,8 @@ module Registration = {
|
|
|
22
22
|
eventName: string,
|
|
23
23
|
contractName: string,
|
|
24
24
|
isWildcard: bool,
|
|
25
|
+
// Earliest block height this registration accepts; `None` is unrestricted.
|
|
26
|
+
startBlock: option<int>,
|
|
25
27
|
kind: kind,
|
|
26
28
|
// The LogData `rb` value as a decimal string; absent for other kinds.
|
|
27
29
|
logId?: string,
|
|
@@ -45,6 +47,7 @@ module Registration = {
|
|
|
45
47
|
eventName: eventConfig.name,
|
|
46
48
|
contractName: eventConfig.contractName,
|
|
47
49
|
isWildcard: reg.isWildcard,
|
|
50
|
+
startBlock: reg.startBlock,
|
|
48
51
|
kind,
|
|
49
52
|
?logId,
|
|
50
53
|
}
|
|
@@ -3,7 +3,7 @@ open Source
|
|
|
3
3
|
let isUnauthorizedError = (message: string) => message->String.includes("401 Unauthorized")
|
|
4
4
|
|
|
5
5
|
type options = {
|
|
6
|
-
|
|
6
|
+
chainId: ChainId.t,
|
|
7
7
|
endpointUrl: string,
|
|
8
8
|
apiToken: option<string>,
|
|
9
9
|
// The chain's registrations, indexed by their sequential `index`.
|
|
@@ -12,7 +12,7 @@ type options = {
|
|
|
12
12
|
addressStore: AddressStore.t,
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
let make = ({
|
|
15
|
+
let make = ({chainId, endpointUrl, apiToken, onEventRegistrations, addressStore}: options): t => {
|
|
16
16
|
let name = "HyperFuel"
|
|
17
17
|
|
|
18
18
|
let apiToken = switch apiToken {
|
|
@@ -120,8 +120,6 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
120
120
|
blocksByHeight->Utils.Map.set(block.height, block)->ignore
|
|
121
121
|
})
|
|
122
122
|
|
|
123
|
-
let chainId = chain->ChainMap.Chain.toChainId
|
|
124
|
-
|
|
125
123
|
let parsedQueueItems = pageUnsafe.items->Array.map(item => {
|
|
126
124
|
// Routing happened in Rust; the item references its registration by
|
|
127
125
|
// chain-scoped index.
|
|
@@ -171,7 +169,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
171
169
|
|
|
172
170
|
Internal.Event({
|
|
173
171
|
onEventRegistration,
|
|
174
|
-
|
|
172
|
+
chainId,
|
|
175
173
|
blockNumber: item.blockHeight,
|
|
176
174
|
logIndex: item.receiptIndex,
|
|
177
175
|
// Fuel carries the transaction inline on the payload; the store key is
|
|
@@ -180,7 +178,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
180
178
|
payload: {
|
|
181
179
|
contractName: eventConfig.contractName,
|
|
182
180
|
eventName: eventConfig.name,
|
|
183
|
-
chainId,
|
|
181
|
+
chainId: chainId,
|
|
184
182
|
params,
|
|
185
183
|
transaction: {
|
|
186
184
|
"id": item.txId,
|
|
@@ -235,7 +233,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
235
233
|
{
|
|
236
234
|
name,
|
|
237
235
|
sourceFor: Sync,
|
|
238
|
-
|
|
236
|
+
chainId,
|
|
239
237
|
getBlockHashes,
|
|
240
238
|
pollingInterval: 100,
|
|
241
239
|
poweredByHyperSync: true,
|
|
@@ -18,7 +18,7 @@ function isUnauthorizedError(message) {
|
|
|
18
18
|
function make(param) {
|
|
19
19
|
let onEventRegistrations = param.onEventRegistrations;
|
|
20
20
|
let apiToken = param.apiToken;
|
|
21
|
-
let
|
|
21
|
+
let chainId = param.chainId;
|
|
22
22
|
let apiToken$1 = apiToken !== undefined ? apiToken : Stdlib_JsError.throwWithMessage(`An Envio API token is required for using HyperFuel as a data-source.
|
|
23
23
|
Set the ENVIO_API_TOKEN environment variable in your .env file.
|
|
24
24
|
Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
@@ -119,7 +119,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
119
119
|
} catch (raw_exn) {
|
|
120
120
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
121
121
|
let params$1 = {
|
|
122
|
-
chainId:
|
|
122
|
+
chainId: chainId,
|
|
123
123
|
blockNumber: item.blockHeight,
|
|
124
124
|
logIndex: item.receiptIndex
|
|
125
125
|
};
|
|
@@ -145,7 +145,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
145
145
|
return {
|
|
146
146
|
kind: 0,
|
|
147
147
|
onEventRegistration: onEventRegistration,
|
|
148
|
-
|
|
148
|
+
chainId: chainId,
|
|
149
149
|
blockNumber: item.blockHeight,
|
|
150
150
|
logIndex: item.receiptIndex,
|
|
151
151
|
transactionIndex: 0,
|
|
@@ -153,7 +153,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
153
153
|
contractName: eventConfig.contractName,
|
|
154
154
|
eventName: eventConfig.name,
|
|
155
155
|
params: params,
|
|
156
|
-
chainId:
|
|
156
|
+
chainId: chainId,
|
|
157
157
|
srcAddress: item.srcAddress,
|
|
158
158
|
logIndex: item.receiptIndex,
|
|
159
159
|
transaction: {
|
|
@@ -195,7 +195,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
195
195
|
return {
|
|
196
196
|
name: "HyperFuel",
|
|
197
197
|
sourceFor: "Sync",
|
|
198
|
-
|
|
198
|
+
chainId: chainId,
|
|
199
199
|
poweredByHyperSync: true,
|
|
200
200
|
pollingInterval: 100,
|
|
201
201
|
getBlockHashes: getBlockHashes,
|
|
@@ -43,7 +43,7 @@ let queryBlockData: (
|
|
|
43
43
|
~client: HyperSyncClient.t,
|
|
44
44
|
~blockNumber: int,
|
|
45
45
|
~sourceName: string,
|
|
46
|
-
~chainId:
|
|
46
|
+
~chainId: ChainId.t,
|
|
47
47
|
~logger: Pino.t,
|
|
48
48
|
) => promise<(
|
|
49
49
|
queryResponse<option<ReorgDetection.blockDataWithTimestamp>>,
|
|
@@ -54,7 +54,7 @@ let queryBlockDataMulti: (
|
|
|
54
54
|
~client: HyperSyncClient.t,
|
|
55
55
|
~blockNumbers: array<int>,
|
|
56
56
|
~sourceName: string,
|
|
57
|
-
~chainId:
|
|
57
|
+
~chainId: ChainId.t,
|
|
58
58
|
~logger: Pino.t,
|
|
59
59
|
) => promise<(
|
|
60
60
|
queryResponse<array<ReorgDetection.blockDataWithTimestamp>>,
|
|
@@ -254,6 +254,10 @@ module Registration = {
|
|
|
254
254
|
contractName: string,
|
|
255
255
|
isWildcard: bool,
|
|
256
256
|
dependsOnAddresses: bool,
|
|
257
|
+
// Earliest block this registration accepts; `None` is unrestricted. The
|
|
258
|
+
// address store's start block is contract-wide, so it can't hold one
|
|
259
|
+
// registration back when a sibling declares no start block.
|
|
260
|
+
startBlock: option<int>,
|
|
257
261
|
params: array<Internal.paramMeta>,
|
|
258
262
|
topicSelections: array<topicSelectionInput>,
|
|
259
263
|
// Capitalized field names matching the Rust BlockField/TransactionField
|
|
@@ -281,6 +285,7 @@ module Registration = {
|
|
|
281
285
|
contractName: event.contractName,
|
|
282
286
|
isWildcard: reg.isWildcard,
|
|
283
287
|
dependsOnAddresses: reg.dependsOnAddresses,
|
|
288
|
+
startBlock: reg.startBlock,
|
|
284
289
|
params: event.paramsMetadata,
|
|
285
290
|
topicSelections: reg.resolvedWhere.topicSelections->Array.map((ts): topicSelectionInput => {
|
|
286
291
|
topic0: ts.topic0->EvmTypes.Hex.toStrings,
|
|
@@ -53,6 +53,7 @@ function fromOnEventRegistrations(onEventRegistrations) {
|
|
|
53
53
|
contractName: event.contractName,
|
|
54
54
|
isWildcard: reg.isWildcard,
|
|
55
55
|
dependsOnAddresses: reg.dependsOnAddresses,
|
|
56
|
+
startBlock: reg.startBlock,
|
|
56
57
|
params: event.paramsMetadata,
|
|
57
58
|
topicSelections: reg.resolvedWhere.topicSelections.map(ts => ({
|
|
58
59
|
topic0: ts.topic0,
|