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.
Files changed (63) hide show
  1. package/package.json +6 -6
  2. package/src/ChainFetcher.res +4 -2
  3. package/src/ChainFetcher.res.mjs +2 -2
  4. package/src/ChainManager.res +20 -2
  5. package/src/ChainManager.res.mjs +22 -2
  6. package/src/Config.res +155 -52
  7. package/src/Config.res.mjs +107 -19
  8. package/src/Ctx.res +1 -1
  9. package/src/Env.res +1 -2
  10. package/src/Env.res.mjs +2 -2
  11. package/src/EventProcessing.res +7 -9
  12. package/src/EventProcessing.res.mjs +1 -1
  13. package/src/FetchState.res +16 -14
  14. package/src/GlobalState.res +24 -18
  15. package/src/GlobalState.res.mjs +74 -73
  16. package/src/HandlerRegister.res +69 -31
  17. package/src/HandlerRegister.resi +5 -4
  18. package/src/Hasura.res +109 -173
  19. package/src/Hasura.res.mjs +86 -148
  20. package/src/Internal.res +183 -2
  21. package/src/Internal.res.mjs +116 -2
  22. package/src/Logging.res +9 -2
  23. package/src/Main.res +3 -3
  24. package/src/Main.res.mjs +2 -1
  25. package/src/Persistence.res +3 -3
  26. package/src/PgStorage.res +199 -120
  27. package/src/PgStorage.res.mjs +219 -111
  28. package/src/Prometheus.res +23 -9
  29. package/src/Prometheus.res.mjs +111 -91
  30. package/src/TableIndices.res +0 -1
  31. package/src/TestIndexer.res +26 -29
  32. package/src/UserContext.res +17 -5
  33. package/src/Utils.res +12 -25
  34. package/src/Utils.res.mjs +8 -38
  35. package/src/bindings/ClickHouse.res +1 -1
  36. package/src/bindings/ClickHouse.res.mjs +1 -1
  37. package/src/bindings/DateFns.res +4 -1
  38. package/src/bindings/Lodash.res +0 -1
  39. package/src/bindings/Pg.res +146 -0
  40. package/src/bindings/{Postgres.res.d.mts → Pg.res.d.mts} +1 -1
  41. package/src/bindings/Pg.res.mjs +110 -0
  42. package/src/bindings/PromClient.res +0 -1
  43. package/src/bindings/Yargs.res +1 -1
  44. package/src/db/EntityHistory.res +21 -21
  45. package/src/db/EntityHistory.res.mjs +16 -3
  46. package/src/db/InternalTable.res +48 -55
  47. package/src/db/InternalTable.res.mjs +57 -23
  48. package/src/db/Table.res +45 -33
  49. package/src/db/Table.res.mjs +43 -41
  50. package/src/sources/Evm.res +0 -3
  51. package/src/sources/HyperFuelSource.res +17 -5
  52. package/src/sources/HyperSync.res +25 -4
  53. package/src/sources/HyperSyncSource.res +36 -17
  54. package/src/sources/HyperSyncSource.res.mjs +13 -6
  55. package/src/sources/Rpc.res +2 -10
  56. package/src/sources/RpcSource.res +251 -211
  57. package/src/sources/RpcSource.res.mjs +98 -101
  58. package/src/sources/RpcWebSocketHeightStream.res +20 -16
  59. package/src/sources/Svm.res +6 -1
  60. package/src/PgStorage.gen.ts +0 -10
  61. package/src/bindings/Postgres.gen.ts +0 -8
  62. package/src/bindings/Postgres.res +0 -119
  63. 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.18-main-pg-client-downgrade",
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
- "postgres": "3.4.1",
64
+ "pg": "8.16.0",
65
65
  "tsx": "4.21.0"
66
66
  },
67
67
  "optionalDependencies": {
68
- "envio-linux-x64": "3.0.0-alpha.18-main-pg-client-downgrade",
69
- "envio-linux-arm64": "3.0.0-alpha.18-main-pg-client-downgrade",
70
- "envio-darwin-x64": "3.0.0-alpha.18-main-pg-client-downgrade",
71
- "envio-darwin-arm64": "3.0.0-alpha.18-main-pg-client-downgrade"
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
  }
@@ -88,7 +88,9 @@ let make = (
88
88
  ).getEventFiltersOrThrow
89
89
 
90
90
  // Check for non-evm chains
91
- if getEventFiltersOrThrow->(Utils.magic: (ChainMap.Chain.t => Internal.eventFilters) => bool) {
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 isLive = (chainFetcher: t) => chainFetcher.timestampCaughtUpToHeadOrEndblock !== None
530
+ let isReady = (chainFetcher: t) => chainFetcher.timestampCaughtUpToHeadOrEndblock !== None
@@ -318,7 +318,7 @@ function isActivelyIndexing(chainFetcher) {
318
318
  return FetchState.isActivelyIndexing(chainFetcher.fetchState);
319
319
  }
320
320
 
321
- function isLive(chainFetcher) {
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
- isLive ,
337
+ isReady ,
338
338
  }
339
339
  /* Env Not a pure module */
@@ -21,11 +21,12 @@ let calculateTargetBufferSize = (~activeChainsCount) => {
21
21
  | Some(size) => size
22
22
  | None =>
23
23
  switch activeChainsCount {
24
- | 1 => 50_000
24
+ | 1 => 60_000
25
25
  | 2 => 30_000
26
26
  | 3 => 20_000
27
27
  | 4 => 15_000
28
- | _ => 10_000
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,
@@ -25,15 +25,17 @@ function calculateTargetBufferSize(activeChainsCount) {
25
25
  }
26
26
  switch (activeChainsCount) {
27
27
  case 1 :
28
- return 50000;
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 10000;
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 {S.array(baseSchema)->S.toUnknown} else {baseSchema}
316
- let fieldSchema = if isNullable {S.null(fieldSchema)->S.toUnknown} else {fieldSchema}
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
- entityJson["properties"]->Array.map(prop => {
338
- let (fieldType, fieldSchema, isNullable, isArray, isIndex) =
339
- getFieldTypeAndSchema(prop, ~enumConfigsByName)
340
- Table.mkField(
341
- prop["name"],
342
- fieldType,
343
- ~fieldSchema,
344
- ~isPrimaryKey=prop["name"] === "id",
345
- ~isNullable,
346
- ~isArray,
347
- ~isIndex,
348
- ~linkedEntity=?prop["linkedEntity"],
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(f => {
368
- Table.fieldName: f["fieldName"],
369
- direction: f["direction"] == "Asc" ? Table.Asc : Table.Desc,
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(prop => {
385
- let (_, fieldSchema, _, _, _) = getFieldTypeAndSchema(prop, ~enumConfigsByName)
386
- let dbFieldName = switch prop["linkedEntity"] {
387
- | Some(_) => prop["name"] ++ "_id"
388
- | None => prop["name"]
389
- }
390
- dict->Js.Dict.set(dbFieldName, s.matches(fieldSchema))
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)->(Utils.magic: S.t<array<dict<unknown>>> => S.t<array<Internal.entity>>),
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(`Invalid internal.config.ts: ${exn->Utils.prettifyExn->(Utils.magic: exn => string)}`)
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
- // Store both ABI and event signatures for each contract (using inline tuple)
465
- let contractsWithAbis: Js.Dict.t<(EvmTypes.Abi.t, array<string>)> = switch publicContractsConfig {
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
- ->Js.Array2.map(((contractName, contractConfig)) => {
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
- (contractName->Utils.String.capitalize, (abi, eventSignatures))
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
- ->Js.Dict.fromArray
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
-
@@ -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 contractsWithAbis = publicContractsConfig !== undefined ? Js_dict.fromArray(Js_dict.entries(publicContractsConfig).map(function (param) {
412
- var contractConfig = param[1];
413
- var abi = contractConfig.abi;
414
- var events = contractConfig.events;
415
- var eventSignatures = events !== undefined ? Belt_Array.map(events, (function (eventItem) {
416
- return eventItem.event;
417
- })) : [];
418
- return [
419
- Utils.$$String.capitalize(param[0]),
420
- [
421
- abi,
422
- eventSignatures
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
@@ -2,4 +2,4 @@ type t = {
2
2
  registrations: HandlerRegister.registrations,
3
3
  config: Config.t,
4
4
  persistence: Persistence.t,
5
- }
5
+ }
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
- Postgres.sslOptionsSchema,
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.