envio 3.0.0-alpha.18-main-pg-client-downgrade → 3.0.0-alpha.19-main-node-pg-client
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/ChainFetcher.res +4 -2
- package/src/ChainFetcher.res.mjs +2 -2
- package/src/ChainManager.res +20 -2
- package/src/ChainManager.res.mjs +22 -2
- package/src/Config.res +155 -52
- package/src/Config.res.mjs +107 -19
- package/src/Ctx.res +1 -1
- package/src/Env.res +1 -2
- package/src/Env.res.mjs +2 -2
- package/src/EventProcessing.res +7 -9
- package/src/EventProcessing.res.mjs +1 -1
- package/src/FetchState.res +16 -14
- package/src/GlobalState.res +24 -18
- package/src/GlobalState.res.mjs +74 -73
- package/src/HandlerRegister.res +69 -31
- package/src/HandlerRegister.resi +5 -4
- package/src/Hasura.res +109 -173
- package/src/Hasura.res.mjs +86 -148
- package/src/Internal.res +183 -2
- package/src/Internal.res.mjs +116 -2
- package/src/Logging.res +9 -2
- package/src/Main.res +3 -3
- package/src/Main.res.mjs +2 -1
- package/src/Persistence.res +3 -3
- package/src/PgStorage.res +199 -120
- package/src/PgStorage.res.mjs +219 -111
- package/src/Prometheus.res +23 -9
- package/src/Prometheus.res.mjs +111 -91
- package/src/TableIndices.res +0 -1
- package/src/TestIndexer.res +26 -29
- package/src/UserContext.res +17 -5
- package/src/Utils.res +12 -25
- package/src/Utils.res.mjs +8 -38
- package/src/bindings/ClickHouse.res +1 -1
- package/src/bindings/ClickHouse.res.mjs +1 -1
- package/src/bindings/DateFns.res +4 -1
- package/src/bindings/Lodash.res +0 -1
- package/src/bindings/Pg.res +146 -0
- package/src/bindings/{Postgres.res.d.mts → Pg.res.d.mts} +1 -1
- package/src/bindings/Pg.res.mjs +110 -0
- package/src/bindings/PromClient.res +0 -1
- package/src/bindings/Yargs.res +1 -1
- package/src/db/EntityHistory.res +21 -21
- package/src/db/EntityHistory.res.mjs +16 -3
- package/src/db/InternalTable.res +48 -55
- package/src/db/InternalTable.res.mjs +57 -23
- package/src/db/Table.res +45 -33
- package/src/db/Table.res.mjs +43 -41
- package/src/sources/Evm.res +0 -3
- package/src/sources/HyperFuelSource.res +17 -5
- package/src/sources/HyperSync.res +25 -4
- package/src/sources/HyperSyncSource.res +36 -17
- package/src/sources/HyperSyncSource.res.mjs +13 -6
- package/src/sources/Rpc.res +2 -10
- package/src/sources/RpcSource.res +251 -211
- package/src/sources/RpcSource.res.mjs +98 -101
- package/src/sources/RpcWebSocketHeightStream.res +20 -16
- package/src/sources/Svm.res +6 -1
- package/src/PgStorage.gen.ts +0 -10
- package/src/bindings/Postgres.gen.ts +0 -8
- package/src/bindings/Postgres.res +0 -119
- package/src/bindings/Postgres.res.mjs +0 -17
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "envio",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.19-main-node-pg-client",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
|
|
6
6
|
"bin": "./bin.mjs",
|
|
@@ -61,13 +61,13 @@
|
|
|
61
61
|
"ink": "6.8.0",
|
|
62
62
|
"ink-big-text": "2.0.0",
|
|
63
63
|
"ink-spinner": "5.0.0",
|
|
64
|
-
"
|
|
64
|
+
"pg": "8.16.0",
|
|
65
65
|
"tsx": "4.21.0"
|
|
66
66
|
},
|
|
67
67
|
"optionalDependencies": {
|
|
68
|
-
"envio-linux-x64": "3.0.0-alpha.
|
|
69
|
-
"envio-linux-arm64": "3.0.0-alpha.
|
|
70
|
-
"envio-darwin-x64": "3.0.0-alpha.
|
|
71
|
-
"envio-darwin-arm64": "3.0.0-alpha.
|
|
68
|
+
"envio-linux-x64": "3.0.0-alpha.19-main-node-pg-client",
|
|
69
|
+
"envio-linux-arm64": "3.0.0-alpha.19-main-node-pg-client",
|
|
70
|
+
"envio-darwin-x64": "3.0.0-alpha.19-main-node-pg-client",
|
|
71
|
+
"envio-darwin-arm64": "3.0.0-alpha.19-main-node-pg-client"
|
|
72
72
|
}
|
|
73
73
|
}
|
package/src/ChainFetcher.res
CHANGED
|
@@ -88,7 +88,9 @@ let make = (
|
|
|
88
88
|
).getEventFiltersOrThrow
|
|
89
89
|
|
|
90
90
|
// Check for non-evm chains
|
|
91
|
-
if
|
|
91
|
+
if (
|
|
92
|
+
getEventFiltersOrThrow->(Utils.magic: (ChainMap.Chain.t => Internal.eventFilters) => bool)
|
|
93
|
+
) {
|
|
92
94
|
switch getEventFiltersOrThrow(ChainMap.Chain.makeUnsafe(~chainId=chainConfig.id)) {
|
|
93
95
|
| Static([]) => true
|
|
94
96
|
| _ => false
|
|
@@ -525,4 +527,4 @@ let getLastKnownValidBlock = async (
|
|
|
525
527
|
|
|
526
528
|
let isActivelyIndexing = (chainFetcher: t) => chainFetcher.fetchState->FetchState.isActivelyIndexing
|
|
527
529
|
|
|
528
|
-
let
|
|
530
|
+
let isReady = (chainFetcher: t) => chainFetcher.timestampCaughtUpToHeadOrEndblock !== None
|
package/src/ChainFetcher.res.mjs
CHANGED
|
@@ -318,7 +318,7 @@ function isActivelyIndexing(chainFetcher) {
|
|
|
318
318
|
return FetchState.isActivelyIndexing(chainFetcher.fetchState);
|
|
319
319
|
}
|
|
320
320
|
|
|
321
|
-
function
|
|
321
|
+
function isReady(chainFetcher) {
|
|
322
322
|
return chainFetcher.timestampCaughtUpToHeadOrEndblock !== undefined;
|
|
323
323
|
}
|
|
324
324
|
|
|
@@ -334,6 +334,6 @@ export {
|
|
|
334
334
|
getHighestBlockBelowThreshold ,
|
|
335
335
|
getLastKnownValidBlock ,
|
|
336
336
|
isActivelyIndexing ,
|
|
337
|
-
|
|
337
|
+
isReady ,
|
|
338
338
|
}
|
|
339
339
|
/* Env Not a pure module */
|
package/src/ChainManager.res
CHANGED
|
@@ -21,11 +21,12 @@ let calculateTargetBufferSize = (~activeChainsCount) => {
|
|
|
21
21
|
| Some(size) => size
|
|
22
22
|
| None =>
|
|
23
23
|
switch activeChainsCount {
|
|
24
|
-
| 1 =>
|
|
24
|
+
| 1 => 60_000
|
|
25
25
|
| 2 => 30_000
|
|
26
26
|
| 3 => 20_000
|
|
27
27
|
| 4 => 15_000
|
|
28
|
-
|
|
|
28
|
+
| 5 => 10_000
|
|
29
|
+
| _ => 5_000
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
32
|
}
|
|
@@ -80,6 +81,23 @@ let makeFromDbState = async (
|
|
|
80
81
|
|
|
81
82
|
let chainFetchers = ChainMap.fromArrayUnsafe(chainFetchersArr)
|
|
82
83
|
|
|
84
|
+
// Set initial progress metrics from DB state so dashboards reflect
|
|
85
|
+
// the persisted state immediately on restart
|
|
86
|
+
let allChainsReady = ref(chainFetchersArr->Array.length > 0)
|
|
87
|
+
chainFetchersArr->Array.forEach(((chain, cf)) => {
|
|
88
|
+
let chainId = chain->ChainMap.Chain.toChainId
|
|
89
|
+
Prometheus.ProgressBlockNumber.set(~blockNumber=cf.committedProgressBlockNumber, ~chainId)
|
|
90
|
+
Prometheus.ProgressReady.init(~chainId)
|
|
91
|
+
if cf->ChainFetcher.isReady {
|
|
92
|
+
Prometheus.ProgressReady.set(~chainId)
|
|
93
|
+
} else {
|
|
94
|
+
allChainsReady := false
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
if allChainsReady.contents {
|
|
98
|
+
Prometheus.ProgressReady.setAllReady()
|
|
99
|
+
}
|
|
100
|
+
|
|
83
101
|
{
|
|
84
102
|
committedCheckpointId: initialState.checkpointId,
|
|
85
103
|
multichain: config.multichain,
|
package/src/ChainManager.res.mjs
CHANGED
|
@@ -25,15 +25,17 @@ function calculateTargetBufferSize(activeChainsCount) {
|
|
|
25
25
|
}
|
|
26
26
|
switch (activeChainsCount) {
|
|
27
27
|
case 1 :
|
|
28
|
-
return
|
|
28
|
+
return 60000;
|
|
29
29
|
case 2 :
|
|
30
30
|
return 30000;
|
|
31
31
|
case 3 :
|
|
32
32
|
return 20000;
|
|
33
33
|
case 4 :
|
|
34
34
|
return 15000;
|
|
35
|
+
case 5 :
|
|
36
|
+
return 10000;
|
|
35
37
|
default:
|
|
36
|
-
return
|
|
38
|
+
return 5000;
|
|
37
39
|
}
|
|
38
40
|
}
|
|
39
41
|
|
|
@@ -58,6 +60,24 @@ async function makeFromDbState(initialState, config, registrations) {
|
|
|
58
60
|
];
|
|
59
61
|
})));
|
|
60
62
|
var chainFetchers = ChainMap.fromArrayUnsafe(chainFetchersArr);
|
|
63
|
+
var allChainsReady = {
|
|
64
|
+
contents: chainFetchersArr.length !== 0
|
|
65
|
+
};
|
|
66
|
+
Belt_Array.forEach(chainFetchersArr, (function (param) {
|
|
67
|
+
var cf = param[1];
|
|
68
|
+
var chain = param[0];
|
|
69
|
+
Prometheus.ProgressBlockNumber.set(cf.committedProgressBlockNumber, chain);
|
|
70
|
+
Prometheus.ProgressReady.init(chain);
|
|
71
|
+
if (ChainFetcher.isReady(cf)) {
|
|
72
|
+
return Prometheus.ProgressReady.set(chain);
|
|
73
|
+
} else {
|
|
74
|
+
allChainsReady.contents = false;
|
|
75
|
+
return ;
|
|
76
|
+
}
|
|
77
|
+
}));
|
|
78
|
+
if (allChainsReady.contents) {
|
|
79
|
+
Prometheus.ProgressReady.setAllReady();
|
|
80
|
+
}
|
|
61
81
|
return {
|
|
62
82
|
committedCheckpointId: initialState.checkpointId,
|
|
63
83
|
chainFetchers: chainFetchers,
|
package/src/Config.res
CHANGED
|
@@ -203,6 +203,9 @@ let publicConfigChainSchema = S.schema(s =>
|
|
|
203
203
|
let contractEventItemSchema = S.schema(s =>
|
|
204
204
|
{
|
|
205
205
|
"event": s.matches(S.string),
|
|
206
|
+
"name": s.matches(S.string),
|
|
207
|
+
"blockFields": s.matches(S.option(S.array(S.string))),
|
|
208
|
+
"transactionFields": s.matches(S.option(S.array(S.string))),
|
|
206
209
|
}
|
|
207
210
|
)
|
|
208
211
|
|
|
@@ -229,6 +232,8 @@ let publicConfigEvmSchema = S.schema(s =>
|
|
|
229
232
|
"chains": s.matches(S.dict(publicConfigChainSchema)),
|
|
230
233
|
"contracts": s.matches(S.option(S.dict(contractConfigSchema))),
|
|
231
234
|
"addressFormat": s.matches(S.option(S.enum([Lowercase, Checksum]))),
|
|
235
|
+
"globalBlockFields": s.matches(S.option(S.array(Internal.evmBlockFieldSchema))),
|
|
236
|
+
"globalTransactionFields": s.matches(S.option(S.array(Internal.evmTransactionFieldSchema))),
|
|
232
237
|
}
|
|
233
238
|
)
|
|
234
239
|
|
|
@@ -273,10 +278,7 @@ let entityJsonSchema = S.schema(s =>
|
|
|
273
278
|
}
|
|
274
279
|
)
|
|
275
280
|
|
|
276
|
-
let getFieldTypeAndSchema = (
|
|
277
|
-
prop,
|
|
278
|
-
~enumConfigsByName: dict<Table.enumConfig<Table.enum>>,
|
|
279
|
-
) => {
|
|
281
|
+
let getFieldTypeAndSchema = (prop, ~enumConfigsByName: dict<Table.enumConfig<Table.enum>>) => {
|
|
280
282
|
let typ = prop["type"]
|
|
281
283
|
let isNullable = prop["isNullable"]->Option.getWithDefault(false)
|
|
282
284
|
let isArray = prop["isArray"]->Option.getWithDefault(false)
|
|
@@ -312,8 +314,16 @@ let getFieldTypeAndSchema = (
|
|
|
312
314
|
| other => Js.Exn.raiseError("Unknown field type in entity config: " ++ other)
|
|
313
315
|
}
|
|
314
316
|
|
|
315
|
-
let fieldSchema = if isArray {
|
|
316
|
-
|
|
317
|
+
let fieldSchema = if isArray {
|
|
318
|
+
S.array(baseSchema)->S.toUnknown
|
|
319
|
+
} else {
|
|
320
|
+
baseSchema
|
|
321
|
+
}
|
|
322
|
+
let fieldSchema = if isNullable {
|
|
323
|
+
S.null(fieldSchema)->S.toUnknown
|
|
324
|
+
} else {
|
|
325
|
+
fieldSchema
|
|
326
|
+
}
|
|
317
327
|
|
|
318
328
|
(fieldType, fieldSchema, isNullable, isArray, isIndex)
|
|
319
329
|
}
|
|
@@ -333,21 +343,22 @@ let parseEntitiesFromJson = (
|
|
|
333
343
|
entitiesJson->Array.mapWithIndex((index, entityJson) => {
|
|
334
344
|
let entityName = entityJson["name"]
|
|
335
345
|
|
|
336
|
-
let fields: array<Table.fieldOrDerived> =
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
346
|
+
let fields: array<Table.fieldOrDerived> = entityJson["properties"]->Array.map(prop => {
|
|
347
|
+
let (fieldType, fieldSchema, isNullable, isArray, isIndex) = getFieldTypeAndSchema(
|
|
348
|
+
prop,
|
|
349
|
+
~enumConfigsByName,
|
|
350
|
+
)
|
|
351
|
+
Table.mkField(
|
|
352
|
+
prop["name"],
|
|
353
|
+
fieldType,
|
|
354
|
+
~fieldSchema,
|
|
355
|
+
~isPrimaryKey=prop["name"] === "id",
|
|
356
|
+
~isNullable,
|
|
357
|
+
~isArray,
|
|
358
|
+
~isIndex,
|
|
359
|
+
~linkedEntity=?prop["linkedEntity"],
|
|
360
|
+
)
|
|
361
|
+
})
|
|
351
362
|
|
|
352
363
|
let derivedFields: array<Table.fieldOrDerived> =
|
|
353
364
|
entityJson["derivedFields"]
|
|
@@ -364,14 +375,17 @@ let parseEntitiesFromJson = (
|
|
|
364
375
|
entityJson["compositeIndices"]
|
|
365
376
|
->Option.getWithDefault([])
|
|
366
377
|
->Array.map(ci =>
|
|
367
|
-
ci->Array.map(
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
378
|
+
ci->Array.map(
|
|
379
|
+
f => {
|
|
380
|
+
Table.fieldName: f["fieldName"],
|
|
381
|
+
direction: f["direction"] == "Asc" ? Table.Asc : Table.Desc,
|
|
382
|
+
},
|
|
383
|
+
)
|
|
371
384
|
)
|
|
372
385
|
|
|
373
386
|
let table = Table.mkTable(
|
|
374
387
|
entityName,
|
|
388
|
+
~stmtId=index->Belt.Int.toString,
|
|
375
389
|
~fields=Array.concat(fields, derivedFields),
|
|
376
390
|
~compositeIndices,
|
|
377
391
|
)
|
|
@@ -381,14 +395,16 @@ let parseEntitiesFromJson = (
|
|
|
381
395
|
// to match the database column names used in Table.toSqlParams
|
|
382
396
|
let schema = S.schema(s => {
|
|
383
397
|
let dict = Js.Dict.empty()
|
|
384
|
-
entityJson["properties"]->Array.forEach(
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
398
|
+
entityJson["properties"]->Array.forEach(
|
|
399
|
+
prop => {
|
|
400
|
+
let (_, fieldSchema, _, _, _) = getFieldTypeAndSchema(prop, ~enumConfigsByName)
|
|
401
|
+
let dbFieldName = switch prop["linkedEntity"] {
|
|
402
|
+
| Some(_) => prop["name"] ++ "_id"
|
|
403
|
+
| None => prop["name"]
|
|
404
|
+
}
|
|
405
|
+
dict->Js.Dict.set(dbFieldName, s.matches(fieldSchema))
|
|
406
|
+
},
|
|
407
|
+
)
|
|
392
408
|
dict
|
|
393
409
|
})
|
|
394
410
|
|
|
@@ -396,7 +412,9 @@ let parseEntitiesFromJson = (
|
|
|
396
412
|
Internal.name: entityName,
|
|
397
413
|
index,
|
|
398
414
|
schema: schema->(Utils.magic: S.t<dict<unknown>> => S.t<Internal.entity>),
|
|
399
|
-
rowsSchema: S.array(schema)->(
|
|
415
|
+
rowsSchema: S.array(schema)->(
|
|
416
|
+
Utils.magic: S.t<array<dict<unknown>>> => S.t<array<Internal.entity>>
|
|
417
|
+
),
|
|
400
418
|
table,
|
|
401
419
|
}->Internal.fromGenericEntityConfig
|
|
402
420
|
})
|
|
@@ -420,6 +438,66 @@ let publicConfigSchema = S.schema(s =>
|
|
|
420
438
|
}
|
|
421
439
|
)
|
|
422
440
|
|
|
441
|
+
// Always-included block fields (number, timestamp, hash) are not in the JSON;
|
|
442
|
+
// they're prepended at runtime so they're always present.
|
|
443
|
+
let alwaysIncludedBlockFields: array<Internal.evmBlockField> = [Number, Timestamp, Hash]
|
|
444
|
+
|
|
445
|
+
// Enrich EVM event configs with field selections from the JSON config.
|
|
446
|
+
// Mutates the event configs in-place to set selectedBlockFields/selectedTransactionFields.
|
|
447
|
+
let enrichEvmFieldSelections = (
|
|
448
|
+
events: array<Internal.eventConfig>,
|
|
449
|
+
~jsonEvents: option<array<_>>,
|
|
450
|
+
~globalBlockFieldsSet: Utils.Set.t<Internal.evmBlockField>,
|
|
451
|
+
~globalTransactionFieldsSet: Utils.Set.t<Internal.evmTransactionField>,
|
|
452
|
+
) => {
|
|
453
|
+
// Build a lookup by event name for events with per-event field overrides
|
|
454
|
+
let fieldsByName: Js.Dict.t<_> = Js.Dict.empty()
|
|
455
|
+
switch jsonEvents {
|
|
456
|
+
| Some(jes) =>
|
|
457
|
+
jes->Array.forEach(je => {
|
|
458
|
+
let name = je["name"]
|
|
459
|
+
if je["blockFields"] != None || je["transactionFields"] != None {
|
|
460
|
+
fieldsByName->Js.Dict.set(name, je)
|
|
461
|
+
}
|
|
462
|
+
})
|
|
463
|
+
| None => ()
|
|
464
|
+
}
|
|
465
|
+
events->Js.Array2.forEachi((event, i) => {
|
|
466
|
+
let evmEvent = event->(Utils.magic: Internal.eventConfig => Internal.evmEventConfig)
|
|
467
|
+
let (selectedBlockFields, selectedTransactionFields) = switch fieldsByName->Js.Dict.get(
|
|
468
|
+
evmEvent.name,
|
|
469
|
+
) {
|
|
470
|
+
| Some(je) => (
|
|
471
|
+
switch je["blockFields"] {
|
|
472
|
+
| Some(fields) =>
|
|
473
|
+
// Prepend always-included block fields for per-event overrides too
|
|
474
|
+
Utils.Set.fromArray(
|
|
475
|
+
Array.concat(
|
|
476
|
+
alwaysIncludedBlockFields,
|
|
477
|
+
fields->(Utils.magic: array<string> => array<Internal.evmBlockField>),
|
|
478
|
+
),
|
|
479
|
+
)
|
|
480
|
+
| None => globalBlockFieldsSet
|
|
481
|
+
},
|
|
482
|
+
switch je["transactionFields"] {
|
|
483
|
+
| Some(fields) =>
|
|
484
|
+
Utils.Set.fromArray(
|
|
485
|
+
fields->(Utils.magic: array<string> => array<Internal.evmTransactionField>),
|
|
486
|
+
)
|
|
487
|
+
| None => globalTransactionFieldsSet
|
|
488
|
+
},
|
|
489
|
+
)
|
|
490
|
+
| None => (globalBlockFieldsSet, globalTransactionFieldsSet)
|
|
491
|
+
}
|
|
492
|
+
events->Js.Array2.unsafe_set(
|
|
493
|
+
i,
|
|
494
|
+
{...evmEvent, selectedBlockFields, selectedTransactionFields}->(
|
|
495
|
+
Utils.magic: Internal.evmEventConfig => Internal.eventConfig
|
|
496
|
+
),
|
|
497
|
+
)
|
|
498
|
+
})
|
|
499
|
+
}
|
|
500
|
+
|
|
423
501
|
let fromPublic = (
|
|
424
502
|
publicConfigJson: Js.Json.t,
|
|
425
503
|
~codegenChains: array<codegenChain>=[],
|
|
@@ -428,7 +506,9 @@ let fromPublic = (
|
|
|
428
506
|
// Parse public config
|
|
429
507
|
let publicConfig = try publicConfigJson->S.parseOrThrow(publicConfigSchema) catch {
|
|
430
508
|
| S.Raised(exn) =>
|
|
431
|
-
Js.Exn.raiseError(
|
|
509
|
+
Js.Exn.raiseError(
|
|
510
|
+
`Invalid internal.config.ts: ${exn->Utils.prettifyExn->(Utils.magic: exn => string)}`,
|
|
511
|
+
)
|
|
432
512
|
}
|
|
433
513
|
|
|
434
514
|
// Determine ecosystem from publicConfig (extract just chains for unified handling)
|
|
@@ -461,21 +541,42 @@ let fromPublic = (
|
|
|
461
541
|
| _ => None
|
|
462
542
|
}
|
|
463
543
|
|
|
464
|
-
//
|
|
465
|
-
let
|
|
544
|
+
// Create global field selection Sets once (shared across events without per-event overrides)
|
|
545
|
+
let (globalBlockFieldsSet, globalTransactionFieldsSet) = switch publicConfig["evm"] {
|
|
546
|
+
| Some(evm) => (
|
|
547
|
+
Utils.Set.fromArray(
|
|
548
|
+
Array.concat(
|
|
549
|
+
alwaysIncludedBlockFields,
|
|
550
|
+
evm["globalBlockFields"]->Option.getWithDefault([]),
|
|
551
|
+
),
|
|
552
|
+
),
|
|
553
|
+
Utils.Set.fromArray(evm["globalTransactionFields"]->Option.getWithDefault([])),
|
|
554
|
+
)
|
|
555
|
+
| None => (Utils.Set.fromArray(alwaysIncludedBlockFields), Utils.Set.make())
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// Store ABI and event signatures for each contract
|
|
559
|
+
let contractsWithAbis: Js.Dict.t<(EvmTypes.Abi.t, array<string>)> = Js.Dict.empty()
|
|
560
|
+
// Per-event field selection overrides, keyed by capitalized contract name
|
|
561
|
+
let jsonEventsByContract: Js.Dict.t<array<_>> = Js.Dict.empty()
|
|
562
|
+
switch publicContractsConfig {
|
|
466
563
|
| Some(contractsDict) =>
|
|
467
564
|
contractsDict
|
|
468
565
|
->Js.Dict.entries
|
|
469
|
-
->
|
|
566
|
+
->Array.forEach(((contractName, contractConfig)) => {
|
|
567
|
+
let capitalizedName = contractName->Utils.String.capitalize
|
|
470
568
|
let abi = contractConfig["abi"]->(Utils.magic: Js.Json.t => EvmTypes.Abi.t)
|
|
471
569
|
let eventSignatures = switch contractConfig["events"] {
|
|
472
570
|
| Some(events) => events->Array.map(eventItem => eventItem["event"])
|
|
473
571
|
| None => []
|
|
474
572
|
}
|
|
475
|
-
|
|
573
|
+
contractsWithAbis->Js.Dict.set(capitalizedName, (abi, eventSignatures))
|
|
574
|
+
switch contractConfig["events"] {
|
|
575
|
+
| Some(events) => jsonEventsByContract->Js.Dict.set(capitalizedName, events)
|
|
576
|
+
| None => ()
|
|
577
|
+
}
|
|
476
578
|
})
|
|
477
|
-
|
|
478
|
-
| None => Js.Dict.empty()
|
|
579
|
+
| None => ()
|
|
479
580
|
}
|
|
480
581
|
|
|
481
582
|
// Index codegenChains by id for efficient lookup
|
|
@@ -504,6 +605,16 @@ let fromPublic = (
|
|
|
504
605
|
}
|
|
505
606
|
},
|
|
506
607
|
)
|
|
608
|
+
|
|
609
|
+
// Enrich EVM event configs with field selections from JSON config
|
|
610
|
+
if ecosystemName == Ecosystem.Evm {
|
|
611
|
+
enrichEvmFieldSelections(
|
|
612
|
+
codegenContract.events,
|
|
613
|
+
~jsonEvents=jsonEventsByContract->Js.Dict.get(codegenContract.name),
|
|
614
|
+
~globalBlockFieldsSet,
|
|
615
|
+
~globalTransactionFieldsSet,
|
|
616
|
+
)
|
|
617
|
+
}
|
|
507
618
|
// Convert codegenContract to contract by adding abi and eventSignatures
|
|
508
619
|
{
|
|
509
620
|
name: codegenContract.name,
|
|
@@ -601,18 +712,12 @@ let fromPublic = (
|
|
|
601
712
|
| Ecosystem.Fuel =>
|
|
602
713
|
switch publicChainConfig["hypersync"] {
|
|
603
714
|
| Some(hypersync) => FuelSourceConfig({hypersync: hypersync})
|
|
604
|
-
| None =>
|
|
605
|
-
Js.Exn.raiseError(
|
|
606
|
-
`Chain ${chainName} is missing hypersync endpoint in config`,
|
|
607
|
-
)
|
|
715
|
+
| None => Js.Exn.raiseError(`Chain ${chainName} is missing hypersync endpoint in config`)
|
|
608
716
|
}
|
|
609
717
|
| Ecosystem.Svm =>
|
|
610
718
|
switch publicChainConfig["rpc"] {
|
|
611
719
|
| Some(rpc) => SvmSourceConfig({rpc: rpc})
|
|
612
|
-
| None =>
|
|
613
|
-
Js.Exn.raiseError(
|
|
614
|
-
`Chain ${chainName} is missing rpc endpoint in config`,
|
|
615
|
-
)
|
|
720
|
+
| None => Js.Exn.raiseError(`Chain ${chainName} is missing rpc endpoint in config`)
|
|
616
721
|
}
|
|
617
722
|
}
|
|
618
723
|
|
|
@@ -670,8 +775,7 @@ let fromPublic = (
|
|
|
670
775
|
->Option.getWithDefault([])
|
|
671
776
|
->parseEntitiesFromJson(~enumConfigsByName)
|
|
672
777
|
|
|
673
|
-
let allEntities =
|
|
674
|
-
userEntities->Js.Array2.concat([DynamicContractRegistry.entityConfig])
|
|
778
|
+
let allEntities = userEntities->Js.Array2.concat([DynamicContractRegistry.entityConfig])
|
|
675
779
|
|
|
676
780
|
let userEntitiesByName =
|
|
677
781
|
userEntities
|
|
@@ -731,4 +835,3 @@ let getChain = (config, ~chainId) => {
|
|
|
731
835
|
"No chain with id " ++ chain->ChainMap.Chain.toString ++ " found in config.yaml",
|
|
732
836
|
)
|
|
733
837
|
}
|
|
734
|
-
|
package/src/Config.res.mjs
CHANGED
|
@@ -10,6 +10,7 @@ import * as Js_exn from "rescript/lib/es6/js_exn.js";
|
|
|
10
10
|
import * as Address from "./Address.res.mjs";
|
|
11
11
|
import * as Js_dict from "rescript/lib/es6/js_dict.js";
|
|
12
12
|
import * as ChainMap from "./ChainMap.res.mjs";
|
|
13
|
+
import * as Internal from "./Internal.res.mjs";
|
|
13
14
|
import * as Belt_Array from "rescript/lib/es6/belt_Array.js";
|
|
14
15
|
import * as BigDecimal from "./bindings/BigDecimal.res.mjs";
|
|
15
16
|
import * as Belt_Option from "rescript/lib/es6/belt_Option.js";
|
|
@@ -40,7 +41,7 @@ var schema = S$RescriptSchema.schema(function (s) {
|
|
|
40
41
|
|
|
41
42
|
var rowsSchema = S$RescriptSchema.array(schema);
|
|
42
43
|
|
|
43
|
-
var table = Table.mkTable(name, undefined, [
|
|
44
|
+
var table = Table.mkTable(name, undefined, undefined, [
|
|
44
45
|
Table.mkField("id", "String", S$RescriptSchema.string, undefined, undefined, undefined, true, undefined, undefined),
|
|
45
46
|
Table.mkField("chain_id", "Int32", S$RescriptSchema.$$int, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
46
47
|
Table.mkField("registering_event_block_number", "Int32", S$RescriptSchema.$$int, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
@@ -108,7 +109,10 @@ var publicConfigChainSchema = S$RescriptSchema.schema(function (s) {
|
|
|
108
109
|
|
|
109
110
|
var contractEventItemSchema = S$RescriptSchema.schema(function (s) {
|
|
110
111
|
return {
|
|
111
|
-
event: s.m(S$RescriptSchema.string)
|
|
112
|
+
event: s.m(S$RescriptSchema.string),
|
|
113
|
+
name: s.m(S$RescriptSchema.string),
|
|
114
|
+
blockFields: s.m(S$RescriptSchema.option(S$RescriptSchema.array(S$RescriptSchema.string))),
|
|
115
|
+
transactionFields: s.m(S$RescriptSchema.option(S$RescriptSchema.array(S$RescriptSchema.string)))
|
|
112
116
|
};
|
|
113
117
|
});
|
|
114
118
|
|
|
@@ -134,7 +138,9 @@ var publicConfigEvmSchema = S$RescriptSchema.schema(function (s) {
|
|
|
134
138
|
addressFormat: s.m(S$RescriptSchema.option(S$RescriptSchema.$$enum([
|
|
135
139
|
"lowercase",
|
|
136
140
|
"checksum"
|
|
137
|
-
])))
|
|
141
|
+
]))),
|
|
142
|
+
globalBlockFields: s.m(S$RescriptSchema.option(S$RescriptSchema.array(Internal.evmBlockFieldSchema))),
|
|
143
|
+
globalTransactionFields: s.m(S$RescriptSchema.option(S$RescriptSchema.array(Internal.evmTransactionFieldSchema)))
|
|
138
144
|
};
|
|
139
145
|
});
|
|
140
146
|
|
|
@@ -314,7 +320,7 @@ function parseEntitiesFromJson(entitiesJson, enumConfigsByName) {
|
|
|
314
320
|
};
|
|
315
321
|
}));
|
|
316
322
|
}));
|
|
317
|
-
var table = Table.mkTable(entityName, compositeIndices, Belt_Array.concat(fields, derivedFields));
|
|
323
|
+
var table = Table.mkTable(entityName, String(index), compositeIndices, Belt_Array.concat(fields, derivedFields));
|
|
318
324
|
var schema = S$RescriptSchema.schema(function (s) {
|
|
319
325
|
var dict = {};
|
|
320
326
|
Belt_Array.forEach(entityJson.properties, (function (prop) {
|
|
@@ -353,6 +359,59 @@ var publicConfigSchema = S$RescriptSchema.schema(function (s) {
|
|
|
353
359
|
};
|
|
354
360
|
});
|
|
355
361
|
|
|
362
|
+
var alwaysIncludedBlockFields = [
|
|
363
|
+
"number",
|
|
364
|
+
"timestamp",
|
|
365
|
+
"hash"
|
|
366
|
+
];
|
|
367
|
+
|
|
368
|
+
function enrichEvmFieldSelections(events, jsonEvents, globalBlockFieldsSet, globalTransactionFieldsSet) {
|
|
369
|
+
var fieldsByName = {};
|
|
370
|
+
if (jsonEvents !== undefined) {
|
|
371
|
+
Belt_Array.forEach(jsonEvents, (function (je) {
|
|
372
|
+
var name = je.name;
|
|
373
|
+
if (je.blockFields !== undefined || je.transactionFields !== undefined) {
|
|
374
|
+
fieldsByName[name] = je;
|
|
375
|
+
return ;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
}));
|
|
379
|
+
}
|
|
380
|
+
events.forEach(function ($$event, i) {
|
|
381
|
+
var je = Js_dict.get(fieldsByName, $$event.name);
|
|
382
|
+
var match;
|
|
383
|
+
if (je !== undefined) {
|
|
384
|
+
var je$1 = Caml_option.valFromOption(je);
|
|
385
|
+
var fields = je$1.blockFields;
|
|
386
|
+
var fields$1 = je$1.transactionFields;
|
|
387
|
+
match = [
|
|
388
|
+
fields !== undefined ? new Set(Belt_Array.concat(alwaysIncludedBlockFields, fields)) : globalBlockFieldsSet,
|
|
389
|
+
fields$1 !== undefined ? new Set(fields$1) : globalTransactionFieldsSet
|
|
390
|
+
];
|
|
391
|
+
} else {
|
|
392
|
+
match = [
|
|
393
|
+
globalBlockFieldsSet,
|
|
394
|
+
globalTransactionFieldsSet
|
|
395
|
+
];
|
|
396
|
+
}
|
|
397
|
+
events[i] = {
|
|
398
|
+
id: $$event.id,
|
|
399
|
+
name: $$event.name,
|
|
400
|
+
contractName: $$event.contractName,
|
|
401
|
+
isWildcard: $$event.isWildcard,
|
|
402
|
+
filterByAddresses: $$event.filterByAddresses,
|
|
403
|
+
dependsOnAddresses: $$event.dependsOnAddresses,
|
|
404
|
+
handler: $$event.handler,
|
|
405
|
+
contractRegister: $$event.contractRegister,
|
|
406
|
+
paramsRawEventSchema: $$event.paramsRawEventSchema,
|
|
407
|
+
getEventFiltersOrThrow: $$event.getEventFiltersOrThrow,
|
|
408
|
+
convertHyperSyncEventArgs: $$event.convertHyperSyncEventArgs,
|
|
409
|
+
selectedBlockFields: match[0],
|
|
410
|
+
selectedTransactionFields: match[1]
|
|
411
|
+
};
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
|
|
356
415
|
function fromPublic(publicConfigJson, codegenChainsOpt, maxAddrInPartitionOpt) {
|
|
357
416
|
var codegenChains = codegenChainsOpt !== undefined ? codegenChainsOpt : [];
|
|
358
417
|
var maxAddrInPartition = maxAddrInPartitionOpt !== undefined ? maxAddrInPartitionOpt : 5000;
|
|
@@ -408,21 +467,45 @@ function fromPublic(publicConfigJson, codegenChainsOpt, maxAddrInPartitionOpt) {
|
|
|
408
467
|
break;
|
|
409
468
|
|
|
410
469
|
}
|
|
411
|
-
var
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
470
|
+
var evm$1 = publicConfig.evm;
|
|
471
|
+
var match$6;
|
|
472
|
+
if (evm$1 !== undefined) {
|
|
473
|
+
var evm$2 = Caml_option.valFromOption(evm$1);
|
|
474
|
+
match$6 = [
|
|
475
|
+
new Set(Belt_Array.concat(alwaysIncludedBlockFields, Belt_Option.getWithDefault(evm$2.globalBlockFields, []))),
|
|
476
|
+
new Set(Belt_Option.getWithDefault(evm$2.globalTransactionFields, []))
|
|
477
|
+
];
|
|
478
|
+
} else {
|
|
479
|
+
match$6 = [
|
|
480
|
+
new Set(alwaysIncludedBlockFields),
|
|
481
|
+
new Set()
|
|
482
|
+
];
|
|
483
|
+
}
|
|
484
|
+
var globalTransactionFieldsSet = match$6[1];
|
|
485
|
+
var globalBlockFieldsSet = match$6[0];
|
|
486
|
+
var contractsWithAbis = {};
|
|
487
|
+
var jsonEventsByContract = {};
|
|
488
|
+
if (publicContractsConfig !== undefined) {
|
|
489
|
+
Belt_Array.forEach(Js_dict.entries(publicContractsConfig), (function (param) {
|
|
490
|
+
var contractConfig = param[1];
|
|
491
|
+
var capitalizedName = Utils.$$String.capitalize(param[0]);
|
|
492
|
+
var abi = contractConfig.abi;
|
|
493
|
+
var events = contractConfig.events;
|
|
494
|
+
var eventSignatures = events !== undefined ? Belt_Array.map(events, (function (eventItem) {
|
|
495
|
+
return eventItem.event;
|
|
496
|
+
})) : [];
|
|
497
|
+
contractsWithAbis[capitalizedName] = [
|
|
498
|
+
abi,
|
|
499
|
+
eventSignatures
|
|
500
|
+
];
|
|
501
|
+
var events$1 = contractConfig.events;
|
|
502
|
+
if (events$1 !== undefined) {
|
|
503
|
+
jsonEventsByContract[capitalizedName] = events$1;
|
|
504
|
+
return ;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
}));
|
|
508
|
+
}
|
|
426
509
|
var codegenChainById = {};
|
|
427
510
|
Belt_Array.forEach(codegenChains, (function (codegenChain) {
|
|
428
511
|
codegenChainById[String(codegenChain.id)] = codegenChain;
|
|
@@ -448,6 +531,9 @@ function fromPublic(publicConfigJson, codegenChainsOpt, maxAddrInPartitionOpt) {
|
|
|
448
531
|
|
|
449
532
|
}
|
|
450
533
|
}));
|
|
534
|
+
if (ecosystemName === "evm") {
|
|
535
|
+
enrichEvmFieldSelections(codegenContract.events, Js_dict.get(jsonEventsByContract, codegenContract.name), globalBlockFieldsSet, globalTransactionFieldsSet);
|
|
536
|
+
}
|
|
451
537
|
return {
|
|
452
538
|
name: codegenContract.name,
|
|
453
539
|
abi: match[0],
|
|
@@ -666,6 +752,8 @@ export {
|
|
|
666
752
|
parseEnumsFromJson ,
|
|
667
753
|
parseEntitiesFromJson ,
|
|
668
754
|
publicConfigSchema ,
|
|
755
|
+
alwaysIncludedBlockFields ,
|
|
756
|
+
enrichEvmFieldSelections ,
|
|
669
757
|
fromPublic ,
|
|
670
758
|
shouldSaveHistory ,
|
|
671
759
|
shouldPruneHistory ,
|
package/src/Ctx.res
CHANGED
package/src/Env.res
CHANGED
|
@@ -109,7 +109,7 @@ module Db = {
|
|
|
109
109
|
)
|
|
110
110
|
let ssl = envSafe->EnvSafe.get(
|
|
111
111
|
"ENVIO_PG_SSL_MODE",
|
|
112
|
-
|
|
112
|
+
Pg.sslOptionsSchema,
|
|
113
113
|
//this is a dev fallback option for local deployments, shouldn't run in the prod env
|
|
114
114
|
//the SSL modes should be provided as string otherwise as 'require' | 'allow' | 'prefer' | 'verify-full'
|
|
115
115
|
~devFallback=Bool(false),
|
|
@@ -194,7 +194,6 @@ module ThrottleWrites = {
|
|
|
194
194
|
S.int,
|
|
195
195
|
~devFallback=30_000,
|
|
196
196
|
)
|
|
197
|
-
|
|
198
197
|
}
|
|
199
198
|
|
|
200
199
|
// You need to close the envSafe after you're done with it so that it immediately tells you about your misconfigured environment on startup.
|