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.
Files changed (129) hide show
  1. package/package.json +6 -6
  2. package/src/Batch.res +8 -8
  3. package/src/Batch.res.mjs +4 -3
  4. package/src/BatchProcessing.res +24 -0
  5. package/src/BatchProcessing.res.mjs +12 -0
  6. package/src/ChainFetching.res +20 -19
  7. package/src/ChainFetching.res.mjs +14 -14
  8. package/src/ChainId.res +58 -0
  9. package/src/ChainId.res.mjs +49 -0
  10. package/src/ChainId.resi +27 -0
  11. package/src/ChainMap.res +12 -26
  12. package/src/ChainMap.res.mjs +5 -41
  13. package/src/ChainMap.resi +5 -20
  14. package/src/ChainMetadata.res +1 -1
  15. package/src/ChainMetadata.res.mjs +3 -2
  16. package/src/ChainState.res +45 -24
  17. package/src/ChainState.res.mjs +40 -16
  18. package/src/ChainState.resi +3 -1
  19. package/src/Config.res +43 -26
  20. package/src/Config.res.mjs +19 -16
  21. package/src/ContractRegisterContext.res +1 -1
  22. package/src/ContractRegisterContext.res.mjs +1 -1
  23. package/src/Core.res +1 -0
  24. package/src/CrossChainState.res +90 -22
  25. package/src/CrossChainState.res.mjs +55 -16
  26. package/src/CrossChainState.resi +5 -1
  27. package/src/Env.res +0 -3
  28. package/src/Env.res.mjs +0 -3
  29. package/src/EventConfigBuilder.res +1 -1
  30. package/src/EventProcessing.res +4 -4
  31. package/src/EventProcessing.res.mjs +5 -5
  32. package/src/FetchState.res +489 -153
  33. package/src/FetchState.res.mjs +399 -129
  34. package/src/FinalizeBackfill.res +61 -0
  35. package/src/FinalizeBackfill.res.mjs +44 -0
  36. package/src/HandlerRegister.res +8 -8
  37. package/src/HandlerRegister.res.mjs +5 -4
  38. package/src/HandlerRegister.resi +1 -1
  39. package/src/InMemoryStore.res +4 -0
  40. package/src/InMemoryStore.res.mjs +1 -1
  41. package/src/InMemoryTable.res +15 -15
  42. package/src/InMemoryTable.res.mjs +14 -14
  43. package/src/IndexerLoop.res +9 -2
  44. package/src/IndexerLoop.res.mjs +8 -1
  45. package/src/IndexerState.res +52 -23
  46. package/src/IndexerState.res.mjs +52 -14
  47. package/src/IndexerState.resi +11 -6
  48. package/src/Internal.res +19 -17
  49. package/src/Internal.res.mjs +18 -9
  50. package/src/LoadLayer.res +10 -2
  51. package/src/LoadLayer.res.mjs +3 -1
  52. package/src/LogSelection.res +2 -2
  53. package/src/Main.res +7 -11
  54. package/src/Main.res.mjs +4 -6
  55. package/src/Metrics.res +6 -6
  56. package/src/Metrics.res.mjs +4 -3
  57. package/src/Persistence.res +23 -4
  58. package/src/PgStorage.res +447 -100
  59. package/src/PgStorage.res.mjs +285 -99
  60. package/src/RawEvent.res +1 -2
  61. package/src/RawEvent.res.mjs +1 -1
  62. package/src/Rollback.res +18 -20
  63. package/src/Rollback.res.mjs +9 -9
  64. package/src/RollbackCommit.res +2 -2
  65. package/src/RollbackCommit.res.mjs +3 -3
  66. package/src/SafeCheckpointTracking.res +2 -2
  67. package/src/SimulateDeadInputTracker.res +17 -21
  68. package/src/SimulateDeadInputTracker.res.mjs +9 -8
  69. package/src/SimulateItems.res +8 -10
  70. package/src/SimulateItems.res.mjs +9 -10
  71. package/src/Sink.res +2 -2
  72. package/src/Sink.res.mjs +3 -2
  73. package/src/TestIndexer.res +14 -14
  74. package/src/TestIndexer.res.mjs +16 -10
  75. package/src/UserContext.res +2 -2
  76. package/src/UserContext.res.mjs +2 -1
  77. package/src/Utils.res +0 -4
  78. package/src/Utils.res.mjs +1 -6
  79. package/src/bindings/ClickHouse.res +20 -2
  80. package/src/bindings/ClickHouse.res.mjs +25 -14
  81. package/src/db/EntityFilter.res +0 -4
  82. package/src/db/EntityFilter.res.mjs +1 -8
  83. package/src/db/EntityHistory.res +1 -1
  84. package/src/db/IndexCatalog.res +248 -0
  85. package/src/db/IndexCatalog.res.mjs +222 -0
  86. package/src/db/IndexDefinition.res +131 -0
  87. package/src/db/IndexDefinition.res.mjs +138 -0
  88. package/src/db/IndexManager.res +145 -0
  89. package/src/db/IndexManager.res.mjs +130 -0
  90. package/src/db/InternalTable.res +54 -23
  91. package/src/db/InternalTable.res.mjs +38 -23
  92. package/src/db/Table.res +24 -14
  93. package/src/db/Table.res.mjs +21 -16
  94. package/src/sources/AddressSet.res +5 -4
  95. package/src/sources/AddressStore.res +25 -14
  96. package/src/sources/AddressStore.res.mjs +10 -12
  97. package/src/sources/Evm.res +2 -2
  98. package/src/sources/Evm.res.mjs +1 -1
  99. package/src/sources/EvmChain.res +3 -3
  100. package/src/sources/EvmChain.res.mjs +3 -3
  101. package/src/sources/EvmHyperSyncSource.res +7 -7
  102. package/src/sources/EvmHyperSyncSource.res.mjs +6 -6
  103. package/src/sources/Fuel.res +2 -2
  104. package/src/sources/Fuel.res.mjs +1 -1
  105. package/src/sources/FuelHyperSyncClient.res +3 -0
  106. package/src/sources/FuelHyperSyncClient.res.mjs +1 -0
  107. package/src/sources/FuelHyperSyncSource.res +5 -7
  108. package/src/sources/FuelHyperSyncSource.res.mjs +5 -5
  109. package/src/sources/HyperSync.resi +2 -2
  110. package/src/sources/HyperSyncClient.res +5 -0
  111. package/src/sources/HyperSyncClient.res.mjs +1 -0
  112. package/src/sources/RpcSource.res +13 -14
  113. package/src/sources/RpcSource.res.mjs +13 -12
  114. package/src/sources/SimulateSource.res +42 -15
  115. package/src/sources/SimulateSource.res.mjs +27 -9
  116. package/src/sources/Source.res +1 -5
  117. package/src/sources/SourceManager.res +12 -12
  118. package/src/sources/SourceManager.res.mjs +11 -10
  119. package/src/sources/SourceManager.resi +2 -2
  120. package/src/sources/Svm.res +4 -5
  121. package/src/sources/Svm.res.mjs +5 -4
  122. package/src/sources/SvmHyperSyncClient.res +3 -0
  123. package/src/sources/SvmHyperSyncClient.res.mjs +1 -0
  124. package/src/sources/SvmHyperSyncSource.res +4 -4
  125. package/src/sources/SvmHyperSyncSource.res.mjs +3 -3
  126. package/src/tui/Tui.res +1 -1
  127. package/src/tui/Tui.res.mjs +2 -1
  128. package/src/tui/components/CustomHooks.res +5 -4
  129. package/src/tui/components/CustomHooks.res.mjs +4 -2
@@ -29,7 +29,7 @@ function make(eventItem, block, transaction, params, srcAddress, blockHash, bloc
29
29
  let params$1 = S$RescriptSchema.reverseConvertOrThrow(params, eventConfig.paramsRawEventSchema);
30
30
  let params$2 = params$1 === null ? "null" : params$1;
31
31
  return {
32
- chain_id: eventItem.chain,
32
+ chain_id: eventItem.chainId,
33
33
  event_id: eventId,
34
34
  event_name: eventConfig.name,
35
35
  contract_name: eventConfig.contractName,
package/src/Rollback.res CHANGED
@@ -50,8 +50,8 @@ let rec rollback = async (
50
50
  switch state->IndexerState.rollbackState {
51
51
  | NoRollback | RollbackReady(_) =>
52
52
  JsError.throwWithMessage("Internal error: Rollback initiated with invalid state")
53
- | ReorgDetected({chain, blockNumber: reorgBlockNumber}) =>
54
- let chainState = state->IndexerState.getChainState(~chain)
53
+ | ReorgDetected({chainId, blockNumber: reorgBlockNumber}) =>
54
+ let chainState = state->IndexerState.getChainState(~chainId)
55
55
 
56
56
  state->IndexerState.enterFindingReorgDepth
57
57
  let rollbackTargetBlockNumber = await chainState->getLastKnownValidBlock(
@@ -63,7 +63,7 @@ let rec rollback = async (
63
63
  ->ChainState.sourceManager
64
64
  ->SourceManager.onReorg(~rollbackTargetBlock=rollbackTargetBlockNumber)
65
65
 
66
- state->IndexerState.foundReorgDepth(~chain, ~rollbackTargetBlockNumber)
66
+ state->IndexerState.foundReorgDepth(~chainId, ~rollbackTargetBlockNumber)
67
67
  // Rendezvous with the processing loop: whichever of {depth found, loop
68
68
  // idle} happens last triggers the rollback; the earlier one finds the
69
69
  // other condition unmet and bails here.
@@ -73,7 +73,7 @@ let rec rollback = async (
73
73
  | FindingReorgDepth => ()
74
74
  | FoundReorgDepth(_) if state->IndexerState.isProcessing =>
75
75
  Logging.trace("Waiting for batch to finish processing before executing rollback")
76
- | FoundReorgDepth({chain: reorgChain, rollbackTargetBlockNumber}) =>
76
+ | FoundReorgDepth({chainId: reorgChain, rollbackTargetBlockNumber}) =>
77
77
  await executeRollback(
78
78
  state,
79
79
  ~reorgChain,
@@ -108,11 +108,9 @@ and executeRollback = async (
108
108
  )
109
109
  logger->Logging.childInfo("Started rollback on reorg")
110
110
  state
111
- ->IndexerState.getChainState(~chain=reorgChain)
111
+ ->IndexerState.getChainState(~chainId=reorgChain)
112
112
  ->ChainState.setRollbackTargetBlock(~blockNumber=rollbackTargetBlockNumber)
113
113
 
114
- let reorgChainId = reorgChain->ChainMap.Chain.toChainId
115
-
116
114
  // Finish pending batch writes first: the target checkpoint, the progress
117
115
  // diff and the rollback diff below must all be computed from the same db
118
116
  // state. Otherwise an in-flight batch lands after the progress reads and
@@ -122,7 +120,7 @@ and executeRollback = async (
122
120
 
123
121
  let rollbackTargetCheckpointId = {
124
122
  switch await (state->IndexerState.persistence).storage.getRollbackTargetCheckpoint(
125
- ~reorgChainId,
123
+ ~reorgChainId=reorgChain,
126
124
  ~lastKnownValidBlockNumber=rollbackTargetBlockNumber,
127
125
  ) {
128
126
  | Some(checkpointId) => checkpointId
@@ -140,7 +138,7 @@ and executeRollback = async (
140
138
  ).storage.getRollbackProgressDiff(~rollbackTargetCheckpointId)
141
139
  for idx in 0 to rollbackProgressDiff->Array.length - 1 {
142
140
  let diff = rollbackProgressDiff->Array.getUnsafe(idx)
143
- eventsProcessedDiffByChain->Utils.Dict.setByInt(
141
+ eventsProcessedDiffByChain->ChainId.Dict.set(
144
142
  diff["chain_id"],
145
143
  {
146
144
  let eventsProcessedDiff =
@@ -149,9 +147,9 @@ and executeRollback = async (
149
147
  eventsProcessedDiff
150
148
  },
151
149
  )
152
- newProgressBlockNumberPerChain->Utils.Dict.setByInt(
150
+ newProgressBlockNumberPerChain->ChainId.Dict.set(
153
151
  diff["chain_id"],
154
- if rollbackTargetCheckpointId === 0n && diff["chain_id"] === reorgChainId {
152
+ if rollbackTargetCheckpointId === 0n && diff["chain_id"] === reorgChain {
155
153
  Pervasives.min(diff["new_progress_block_number"], rollbackTargetBlockNumber)
156
154
  } else {
157
155
  diff["new_progress_block_number"]
@@ -167,14 +165,14 @@ and executeRollback = async (
167
165
  let chainId = (cs->ChainState.chainConfig).id
168
166
  let fromBlock = cs->ChainState.committedProgressBlockNumber
169
167
  cs->ChainState.rollback(
170
- ~newProgressBlockNumber=newProgressBlockNumberPerChain->Utils.Dict.dangerouslyGetByIntNonOption(
168
+ ~newProgressBlockNumber=newProgressBlockNumberPerChain->ChainId.Dict.dangerouslyGetNonOption(
171
169
  chainId,
172
170
  ),
173
- ~eventsProcessedDiff=eventsProcessedDiffByChain->Utils.Dict.dangerouslyGetByIntNonOption(
171
+ ~eventsProcessedDiff=eventsProcessedDiffByChain->ChainId.Dict.dangerouslyGetNonOption(
174
172
  chainId,
175
173
  ),
176
174
  ~rollbackTargetBlockNumber,
177
- ~isReorgChain=chainId === reorgChainId,
175
+ ~isReorgChain=chainId === reorgChain,
178
176
  )
179
177
  let toBlock = cs->ChainState.committedProgressBlockNumber
180
178
  if fromBlock !== toBlock {
@@ -184,7 +182,7 @@ and executeRollback = async (
184
182
  "fromBlock": fromBlock,
185
183
  "toBlock": toBlock,
186
184
  "rollbackedEvents": eventsProcessedDiffByChain
187
- ->Utils.Dict.dangerouslyGetByIntNonOption(chainId)
185
+ ->ChainId.Dict.dangerouslyGetNonOption(chainId)
188
186
  ->Option.getOr(0.),
189
187
  })
190
188
  ->ignore
@@ -197,13 +195,13 @@ and executeRollback = async (
197
195
  ~progressBlockNumberByChainId=newProgressBlockNumberPerChain,
198
196
  )
199
197
 
200
- rolledBackChains->Array.forEach(chain => {
198
+ rolledBackChains->Array.forEach(rolledBack => {
201
199
  logger->Logging.childInfo({
202
200
  "msg": "Rollbacked",
203
- "chainId": chain["chainId"],
204
- "fromBlock": chain["fromBlock"],
205
- "toBlock": chain["toBlock"],
206
- "rollbackedEvents": chain["rollbackedEvents"],
201
+ "chainId": rolledBack["chainId"],
202
+ "fromBlock": rolledBack["fromBlock"],
203
+ "toBlock": rolledBack["toBlock"],
204
+ "rollbackedEvents": rolledBack["rollbackedEvents"],
207
205
  })
208
206
  })
209
207
  logger->Logging.childTrace({
@@ -70,12 +70,12 @@ async function executeRollback(state, reorgChain, rollbackTargetBlockNumber, sch
70
70
  }
71
71
  });
72
72
  let diff$1 = await InMemoryStore.prepareRollbackDiff(state, rollbackTargetCheckpointId, IndexerState.committedCheckpointId(state) + 1n, newProgressBlockNumberPerChain);
73
- rolledBackChains.forEach(chain => Logging.childInfo(logger, {
73
+ rolledBackChains.forEach(rolledBack => Logging.childInfo(logger, {
74
74
  msg: "Rollbacked",
75
- chainId: chain.chainId,
76
- fromBlock: chain.fromBlock,
77
- toBlock: chain.toBlock,
78
- rollbackedEvents: chain.rollbackedEvents
75
+ chainId: rolledBack.chainId,
76
+ fromBlock: rolledBack.fromBlock,
77
+ toBlock: rolledBack.toBlock,
78
+ rollbackedEvents: rolledBack.rollbackedEvents
79
79
  }));
80
80
  Logging.childTrace(logger, {
81
81
  msg: "Rollback entity changes",
@@ -100,18 +100,18 @@ async function rollback(state, scheduleFetch, scheduleProcessing, scheduleRollba
100
100
  }
101
101
  switch (match.TAG) {
102
102
  case "ReorgDetected" :
103
- let chain = match.chain;
104
- let chainState = IndexerState.getChainState(state, chain);
103
+ let chainId = match.chainId;
104
+ let chainState = IndexerState.getChainState(state, chainId);
105
105
  IndexerState.enterFindingReorgDepth(state);
106
106
  let rollbackTargetBlockNumber = await getLastKnownValidBlock(chainState, match.blockNumber, IndexerState.isRealtime(state));
107
107
  SourceManager.onReorg(ChainState.sourceManager(chainState), rollbackTargetBlockNumber);
108
- IndexerState.foundReorgDepth(state, chain, rollbackTargetBlockNumber);
108
+ IndexerState.foundReorgDepth(state, chainId, rollbackTargetBlockNumber);
109
109
  return scheduleRollback();
110
110
  case "FoundReorgDepth" :
111
111
  if (IndexerState.isProcessing(state)) {
112
112
  return Logging.trace("Waiting for batch to finish processing before executing rollback");
113
113
  } else {
114
- return await executeRollback(state, match.chain, match.rollbackTargetBlockNumber, scheduleFetch, scheduleProcessing);
114
+ return await executeRollback(state, match.chainId, match.rollbackTargetBlockNumber, scheduleFetch, scheduleProcessing);
115
115
  }
116
116
  case "RollbackReady" :
117
117
  return Stdlib_JsError.throwWithMessage("Internal error: Rollback initiated with invalid state");
@@ -3,7 +3,7 @@
3
3
  // feature lives here plus two call sites: registration in `Main.res` and the
4
4
  // fire on a successful rollback write in `InMemoryStore.res`. Delete those
5
5
  // together with this module.
6
- type args = {chainId: int, rollbackToBlock: int}
6
+ type args = {chainId: ChainId.t, rollbackToBlock: int}
7
7
  type callback = args => promise<unit>
8
8
 
9
9
  // Lives in the process-wide `EnvioGlobal` record so callbacks registered
@@ -28,7 +28,7 @@ let fire = async (~progressBlockNumberByChainId: dict<int>) => {
28
28
  let _ = await progressBlockNumberByChainId
29
29
  ->Dict.toArray
30
30
  ->Array.flatMap(((chainIdKey, rollbackToBlock)) => {
31
- let args = {chainId: chainIdKey->Int.fromString->Option.getUnsafe, rollbackToBlock}
31
+ let args = {chainId: chainIdKey->ChainId.normalizeOrThrow, rollbackToBlock}
32
32
  callbacks->Array.map(callback => callback(args))
33
33
  })
34
34
  ->Promise.all
@@ -1,6 +1,6 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
- import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
3
+ import * as ChainId from "./ChainId.res.mjs";
4
4
  import * as EnvioGlobal from "./EnvioGlobal.res.mjs";
5
5
 
6
6
  let callbacks = EnvioGlobal.value.rollbackCommitCallbacks;
@@ -18,7 +18,7 @@ function register(callback) {
18
18
 
19
19
  async function fire(progressBlockNumberByChainId) {
20
20
  await Promise.all(Object.entries(progressBlockNumberByChainId).flatMap(param => {
21
- let args_chainId = Stdlib_Int.fromString(param[0], undefined);
21
+ let args_chainId = ChainId.normalizeOrThrow(param[0]);
22
22
  let args_rollbackToBlock = param[1];
23
23
  let args = {
24
24
  chainId: args_chainId,
@@ -33,4 +33,4 @@ export {
33
33
  register,
34
34
  fire,
35
35
  }
36
- /* EnvioGlobal Not a pure module */
36
+ /* ChainId Not a pure module */
@@ -70,10 +70,10 @@ let getSafeCheckpointId = (safeCheckpointTracking: t, ~sourceBlockNumber: int) =
70
70
  let updateOnNewBatch = (
71
71
  safeCheckpointTracking: t,
72
72
  ~sourceBlockNumber: int,
73
- ~chainId: int,
73
+ ~chainId: ChainId.t,
74
74
  ~batchCheckpointIds: array<bigint>,
75
75
  ~batchCheckpointBlockNumbers: array<int>,
76
- ~batchCheckpointChainIds: array<int>,
76
+ ~batchCheckpointChainIds: array<ChainId.t>,
77
77
  ) => {
78
78
  let safeCheckpointId = getSafeCheckpointId(safeCheckpointTracking, ~sourceBlockNumber)
79
79
 
@@ -6,16 +6,15 @@
6
6
  // transform of the item between the source and the batch.
7
7
  let itemKey = (item: Internal.item): string =>
8
8
  switch item {
9
- | Internal.Event({chain, blockNumber, logIndex}) =>
10
- `${chain
11
- ->ChainMap.Chain.toChainId
12
- ->Int.toString}:${blockNumber->Int.toString}:${logIndex->Int.toString}`
9
+ | Internal.Event({chainId, blockNumber, logIndex}) =>
10
+ `${chainId
11
+ ->ChainId.toString}:${blockNumber->Int.toString}:${logIndex->Int.toString}`
13
12
  | Internal.Block(_) => ""
14
13
  }
15
14
 
16
15
  // `index` is the item's position in its chain's `simulate` array, reported back
17
16
  // so a user finds it without echoing its fields.
18
- type entry = {chainId: int, index: int, key: string}
17
+ type entry = {chainId: ChainId.t, index: int, key: string}
19
18
 
20
19
  type t = {mutable unprocessed: array<entry>}
21
20
 
@@ -25,18 +24,12 @@ let makeFromConfig = (config: Config.t): option<t> => {
25
24
  ->ChainMap.values
26
25
  ->Array.flatMap(chainConfig =>
27
26
  switch chainConfig.sourceConfig {
28
- | Config.CustomSources(sources) =>
29
- sources->Array.flatMap(source =>
30
- source.simulateItems
31
- ->Option.getOr([])
32
- ->Array.mapWithIndex(
33
- (item, index) => {
34
- chainId: chainConfig.id,
35
- index,
36
- key: itemKey(item),
37
- },
38
- )
39
- )
27
+ | Config.SimulateSourceConfig({items}) =>
28
+ items->Array.mapWithIndex((item, index) => {
29
+ chainId: chainConfig.id,
30
+ index,
31
+ key: itemKey(item),
32
+ })
40
33
  | _ => []
41
34
  }
42
35
  )
@@ -52,17 +45,20 @@ let recordProcessed = (t: t, ~batch: Batch.t) => {
52
45
  }
53
46
 
54
47
  // Unrouted item indices grouped by chain, in the order chains were first seen.
55
- let unroutedByChain = (t: t): array<(int, array<int>)> => {
48
+ let unroutedByChain = (t: t): array<(ChainId.t, array<int>)> => {
56
49
  let indicesByChain = Dict.make()
57
50
  let chainOrder = []
58
51
  t.unprocessed->Array.forEach(entry => {
59
- let key = entry.chainId->Int.toString
52
+ let key = entry.chainId->ChainId.toString
60
53
  if indicesByChain->Dict.get(key)->Option.isNone {
61
54
  chainOrder->Array.push(entry.chainId)->ignore
62
55
  }
63
56
  indicesByChain->Utils.Dict.push(key, entry.index)
64
57
  })
65
- chainOrder->Array.map(chainId => (chainId, indicesByChain->Dict.getUnsafe(chainId->Int.toString)))
58
+ chainOrder->Array.map(chainId => (
59
+ chainId,
60
+ indicesByChain->Dict.getUnsafe(chainId->ChainId.toString),
61
+ ))
66
62
  }
67
63
 
68
64
  let failureMessage = (t: t): option<string> =>
@@ -74,7 +70,7 @@ let failureMessage = (t: t): option<string> =>
74
70
  let lines =
75
71
  byChain
76
72
  ->Array.map(((chainId, indices)) =>
77
- ` - chain ${chainId->Int.toString}: ${indices
73
+ ` - chain ${chainId->ChainId.toString}: ${indices
78
74
  ->Array.map(index => index->Int.toString)
79
75
  ->Array.join(", ")}`
80
76
  )
@@ -1,13 +1,14 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
3
  import * as Utils from "./Utils.res.mjs";
4
+ import * as ChainId from "./ChainId.res.mjs";
4
5
  import * as ChainMap from "./ChainMap.res.mjs";
5
6
  import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
6
7
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
7
8
 
8
9
  function itemKey(item) {
9
10
  if (item.kind === 0) {
10
- return item.chain.toString() + `:` + item.blockNumber.toString() + `:` + item.logIndex.toString();
11
+ return ChainId.toString(item.chainId) + `:` + item.blockNumber.toString() + `:` + item.logIndex.toString();
11
12
  } else {
12
13
  return "";
13
14
  }
@@ -15,13 +16,13 @@ function itemKey(item) {
15
16
 
16
17
  function makeFromConfig(config) {
17
18
  let entries = ChainMap.values(config.chainMap).flatMap(chainConfig => {
18
- let sources = chainConfig.sourceConfig;
19
- if (sources.TAG === "CustomSources") {
20
- return sources._0.flatMap(source => Stdlib_Option.getOr(source.simulateItems, []).map((item, index) => ({
19
+ let match = chainConfig.sourceConfig;
20
+ if (match.TAG === "SimulateSourceConfig") {
21
+ return match.items.map((item, index) => ({
21
22
  chainId: chainConfig.id,
22
23
  index: index,
23
24
  key: itemKey(item)
24
- })));
25
+ }));
25
26
  } else {
26
27
  return [];
27
28
  }
@@ -42,7 +43,7 @@ function unroutedByChain(t) {
42
43
  let indicesByChain = {};
43
44
  let chainOrder = [];
44
45
  t.unprocessed.forEach(entry => {
45
- let key = entry.chainId.toString();
46
+ let key = ChainId.toString(entry.chainId);
46
47
  if (Stdlib_Option.isNone(indicesByChain[key])) {
47
48
  chainOrder.push(entry.chainId);
48
49
  }
@@ -50,7 +51,7 @@ function unroutedByChain(t) {
50
51
  });
51
52
  return chainOrder.map(chainId => [
52
53
  chainId,
53
- indicesByChain[chainId.toString()]
54
+ indicesByChain[ChainId.toString(chainId)]
54
55
  ]);
55
56
  }
56
57
 
@@ -61,7 +62,7 @@ function failureMessage(t) {
61
62
  }
62
63
  let count = Stdlib_Array.reduce(byChain, 0, (acc, param) => acc + param[1].length | 0);
63
64
  let itemWord = count === 1 ? "item" : "items";
64
- let lines = byChain.map(param => ` - chain ` + param[0].toString() + `: ` + param[1].map(index => index.toString()).join(", ")).join("\n");
65
+ let lines = byChain.map(param => ` - chain ` + ChainId.toString(param[0]) + `: ` + param[1].map(index => index.toString()).join(", ")).join("\n");
65
66
  return `simulate: ` + count.toString() + ` ` + itemWord + ` you passed to simulate never reached a handler, so nothing ran for them. Each was filtered out before the handler — usually a non-wildcard srcAddress that isn't indexed for the contract, or a where/block filter that excluded the event. Unrouted items, by index in each chain's simulate array:\n` + lines;
66
67
  }
67
68
 
@@ -246,7 +246,6 @@ let parse = (
246
246
  ~chainConfig: Config.chain,
247
247
  ~onEventRegistrations: array<Internal.onEventRegistration>,
248
248
  ): array<Internal.item> => {
249
- let chain = ChainMap.Chain.makeUnsafe(~chainId=chainConfig.id)
250
249
  let chainId = chainConfig.id
251
250
  let startBlock = chainConfig.startBlock
252
251
  let currentBlock = ref(startBlock)
@@ -334,7 +333,7 @@ let parse = (
334
333
  switch seenCoordinates->Dict.get(coordinate) {
335
334
  | Some(firstIndex) =>
336
335
  JsError.throwWithMessage(
337
- `simulate: items at index ${firstIndex->Int.toString} and ${itemIndex->Int.toString} on chain ${chainId->Int.toString} both resolve to block ${blockNumber->Int.toString}, logIndex ${logIndex->Int.toString}. Give each item a distinct logIndex (or omit logIndex so they auto-increment).`,
336
+ `simulate: items at index ${firstIndex->Int.toString} and ${itemIndex->Int.toString} on chain ${chainId->ChainId.toString} both resolve to block ${blockNumber->Int.toString}, logIndex ${logIndex->Int.toString}. Give each item a distinct logIndex (or omit logIndex so they auto-increment).`,
338
337
  )
339
338
  | None => seenCoordinates->Dict.set(coordinate, itemIndex)
340
339
  }
@@ -351,7 +350,7 @@ let parse = (
351
350
  let liveRegistrations =
352
351
  HandlerRegister.getSimulateOnEventRegistrations(
353
352
  ~config,
354
- ~chainId,
353
+ ~chainId=chainId,
355
354
  ~eventConfig,
356
355
  )->Array.filter(reg =>
357
356
  (reg.handler->Option.isSome || reg.contractRegister->Option.isSome) &&
@@ -363,7 +362,7 @@ let parse = (
363
362
  ->ChainMap.values
364
363
  ->Array.length {
365
364
  | 1 => ""
366
- | _ => ` on chain ${chainId->Int.toString}`
365
+ | _ => ` on chain ${chainId->ChainId.toString}`
367
366
  }}. Register a handler with indexer.onEvent (and check any \`where\` filter isn't excluding this chain) before simulating it.`,
368
367
  )
369
368
  }
@@ -378,7 +377,7 @@ let parse = (
378
377
  ->Array.push(
379
378
  Internal.Event({
380
379
  onEventRegistration,
381
- chain,
380
+ chainId,
382
381
  blockNumber,
383
382
  logIndex,
384
383
  // Simulate keeps the transaction inline on the payload, so the store
@@ -389,7 +388,7 @@ let parse = (
389
388
  contractName: eventConfig.contractName,
390
389
  eventName: eventConfig.name,
391
390
  params,
392
- chainId,
391
+ chainId: chainId,
393
392
  srcAddress,
394
393
  logIndex,
395
394
  transaction,
@@ -420,8 +419,8 @@ let patchConfig = (
420
419
  (processConfig->(Utils.magic: JSON.t => {..}))["chains"]->Nullable.toOption
421
420
  switch processChains {
422
421
  | Some(chainsDict) =>
423
- let newChainMap = config.chainMap->ChainMap.mapWithKey((chain, chainConfig) => {
424
- let chainIdStr = chain->ChainMap.Chain.toChainId->Int.toString
422
+ let newChainMap = config.chainMap->ChainMap.mapWithKey((chainId, chainConfig) => {
423
+ let chainIdStr = chainId->ChainId.toString
425
424
  switch chainsDict->Dict.get(chainIdStr) {
426
425
  | Some(processChainJson) =>
427
426
  let raw = processChainJson->(Utils.magic: JSON.t => {..})
@@ -451,8 +450,7 @@ let patchConfig = (
451
450
  ~chainConfig,
452
451
  ~onEventRegistrations=chainRegistrations.onEventRegistrations,
453
452
  )
454
- let source = SimulateSource.make(~items, ~endBlock, ~chain)
455
- {...chainConfig, sourceConfig: Config.CustomSources([source])}
453
+ {...chainConfig, sourceConfig: Config.SimulateSourceConfig({items, endBlock})}
456
454
  | None => chainConfig
457
455
  }
458
456
  | None => chainConfig
@@ -3,9 +3,9 @@
3
3
  import * as Utils from "./Utils.res.mjs";
4
4
  import * as Config from "./Config.res.mjs";
5
5
  import * as Address from "./Address.res.mjs";
6
+ import * as ChainId from "./ChainId.res.mjs";
6
7
  import * as ChainMap from "./ChainMap.res.mjs";
7
8
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
8
- import * as SimulateSource from "./sources/SimulateSource.res.mjs";
9
9
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
10
10
  import * as HandlerRegister from "./HandlerRegister.res.mjs";
11
11
  import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
@@ -169,7 +169,6 @@ function deriveSrcAddress(providedSrcAddress, eventConfig, chainConfig, config)
169
169
  }
170
170
 
171
171
  function parse(simulateItems, config, chainConfig, onEventRegistrations) {
172
- let chain = ChainMap.Chain.makeUnsafe(chainConfig.id);
173
172
  let chainId = chainConfig.id;
174
173
  let startBlock = chainConfig.startBlock;
175
174
  let currentBlock = {
@@ -251,7 +250,7 @@ function parse(simulateItems, config, chainConfig, onEventRegistrations) {
251
250
  let coordinate = blockNumber.toString() + `:` + logIndex.toString();
252
251
  let firstIndex = seenCoordinates[coordinate];
253
252
  if (firstIndex !== undefined) {
254
- Stdlib_JsError.throwWithMessage(`simulate: items at index ` + firstIndex.toString() + ` and ` + itemIndex.toString() + ` on chain ` + chainId.toString() + ` both resolve to block ` + blockNumber.toString() + `, logIndex ` + logIndex.toString() + `. Give each item a distinct logIndex (or omit logIndex so they auto-increment).`);
253
+ Stdlib_JsError.throwWithMessage(`simulate: items at index ` + firstIndex.toString() + ` and ` + itemIndex.toString() + ` on chain ` + ChainId.toString(chainId) + ` both resolve to block ` + blockNumber.toString() + `, logIndex ` + logIndex.toString() + `. Give each item a distinct logIndex (or omit logIndex so they auto-increment).`);
255
254
  } else {
256
255
  seenCoordinates[coordinate] = itemIndex;
257
256
  }
@@ -265,7 +264,7 @@ function parse(simulateItems, config, chainConfig, onEventRegistrations) {
265
264
  if (Utils.$$Array.isEmpty(liveRegistrations)) {
266
265
  let match$5 = ChainMap.values(config.chainMap).length;
267
266
  Stdlib_JsError.throwWithMessage(`simulate: no handler runs for event "` + match$1 + `" on contract "` + match + `"` + (
268
- match$5 !== 1 ? ` on chain ` + chainId.toString() : ""
267
+ match$5 !== 1 ? ` on chain ` + ChainId.toString(chainId) : ""
269
268
  ) + `. Register a handler with indexer.onEvent (and check any \`where\` filter isn't excluding this chain) before simulating it.`);
270
269
  }
271
270
  liveRegistrations.forEach(reg => {
@@ -276,7 +275,7 @@ function parse(simulateItems, config, chainConfig, onEventRegistrations) {
276
275
  items.push({
277
276
  kind: 0,
278
277
  onEventRegistration: newrecord,
279
- chain: chain,
278
+ chainId: chainId,
280
279
  blockNumber: blockNumber,
281
280
  logIndex: logIndex,
282
281
  transactionIndex: 0,
@@ -301,8 +300,8 @@ function patchConfig(config, processConfig, registrationsByChainId) {
301
300
  if (processChains == null) {
302
301
  return config;
303
302
  }
304
- let newChainMap = ChainMap.mapWithKey(config.chainMap, (chain, chainConfig) => {
305
- let chainIdStr = chain.toString();
303
+ let newChainMap = ChainMap.mapWithKey(config.chainMap, (chainId, chainConfig) => {
304
+ let chainIdStr = ChainId.toString(chainId);
306
305
  let processChainJson = processChains[chainIdStr];
307
306
  if (processChainJson === undefined) {
308
307
  return chainConfig;
@@ -331,11 +330,11 @@ function patchConfig(config, processConfig, registrationsByChainId) {
331
330
  newrecord.endBlock = endBlock;
332
331
  newrecord.startBlock = startBlock;
333
332
  let items = parse(simulateRaw, config, newrecord, chainRegistrations.onEventRegistrations);
334
- let source = SimulateSource.make(items, endBlock, chain);
335
333
  let newrecord$1 = {...newrecord};
336
334
  newrecord$1.sourceConfig = {
337
- TAG: "CustomSources",
338
- _0: [source]
335
+ TAG: "SimulateSourceConfig",
336
+ items: items,
337
+ endBlock: endBlock
339
338
  };
340
339
  return newrecord$1;
341
340
  });
package/src/Sink.res CHANGED
@@ -12,7 +12,7 @@ type t = {
12
12
  ) => promise<unit>,
13
13
  }
14
14
 
15
- let makeClickHouse = (~host, ~database, ~username, ~password): t => {
15
+ let makeClickHouse = (~host, ~database, ~username, ~password, ~chainIdMode: ChainId.mode=Int32): t => {
16
16
  let client = ClickHouse.createClient({
17
17
  url: host,
18
18
  username,
@@ -27,7 +27,7 @@ let makeClickHouse = (~host, ~database, ~username, ~password): t => {
27
27
  {
28
28
  name: "clickhouse",
29
29
  initialize: (~chainConfigs as _=[], ~entities=[], ~enums=[]) => {
30
- ClickHouse.initialize(client, ~database, ~entities, ~enums)
30
+ ClickHouse.initialize(client, ~database, ~entities, ~enums, ~chainIdMode)
31
31
  },
32
32
  resume: (~checkpointId) => {
33
33
  ClickHouse.resume(client, ~database, ~checkpointId)
package/src/Sink.res.mjs CHANGED
@@ -3,7 +3,8 @@
3
3
  import * as ClickHouse from "./bindings/ClickHouse.res.mjs";
4
4
  import * as Client from "@clickhouse/client";
5
5
 
6
- function makeClickHouse(host, database, username, password) {
6
+ function makeClickHouse(host, database, username, password, chainIdModeOpt) {
7
+ let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
7
8
  let client = Client.createClient({
8
9
  url: host,
9
10
  username: username,
@@ -16,7 +17,7 @@ function makeClickHouse(host, database, username, password) {
16
17
  $staropt$star !== undefined;
17
18
  let entities = $staropt$star$1 !== undefined ? $staropt$star$1 : [];
18
19
  let enums = $staropt$star$2 !== undefined ? $staropt$star$2 : [];
19
- return ClickHouse.initialize(client, database, entities, enums);
20
+ return ClickHouse.initialize(client, database, entities, enums, chainIdMode);
20
21
  },
21
22
  resume: checkpointId => ClickHouse.resume(client, database, checkpointId),
22
23
  writeBatch: async (batch, updatedEntities) => {
@@ -55,7 +55,7 @@ let getIndexingAddressesByChain = (state: testIndexerState): dict<
55
55
  ->Dict.valuesToArray
56
56
  ->Array.forEach(entity => {
57
57
  let dc = entity->castToEnvioAddresses
58
- let chainIdStr = dc.chainId->Int.toString
58
+ let chainIdStr = dc.chainId->ChainId.toString
59
59
  let contracts = switch byChain->Dict.get(chainIdStr) {
60
60
  | Some(arr) => arr
61
61
  | None =>
@@ -96,7 +96,7 @@ let handleWriteBatch = (
96
96
  state: testIndexerState,
97
97
  ~updatedEntities: array<Persistence.updatedEntity>,
98
98
  ~checkpointIds: array<bigint>,
99
- ~checkpointChainIds: array<int>,
99
+ ~checkpointChainIds: array<ChainId.t>,
100
100
  ~checkpointBlockNumbers: array<int>,
101
101
  ~checkpointEventsProcessed: array<int>,
102
102
  ): unit => {
@@ -158,7 +158,7 @@ let handleWriteBatch = (
158
158
 
159
159
  // Update progress tracking from checkpoint data
160
160
  state.progressBlockByChain->Dict.set(
161
- checkpointChainIds->Array.getUnsafe(i)->Int.toString,
161
+ checkpointChainIds->Array.getUnsafe(i)->ChainId.toString,
162
162
  checkpointBlockNumbers->Array.getUnsafe(i),
163
163
  )
164
164
 
@@ -223,8 +223,7 @@ let makeInitialState = (
223
223
  ): Persistence.initialState => {
224
224
  let chainKeys = processConfigChains->Dict.keysToArray
225
225
  let chains = chainKeys->Array.map(chainIdStr => {
226
- let chainId = chainIdStr->Int.fromString->Option.getOr(0)
227
- let chain = ChainMap.Chain.makeUnsafe(~chainId)
226
+ let chain = chainIdStr->ChainId.normalizeOrThrow
228
227
 
229
228
  if !(config.chainMap->ChainMap.has(chain)) {
230
229
  JsError.throwWithMessage(`Chain ${chainIdStr} is not configured in config.yaml`)
@@ -233,7 +232,7 @@ let makeInitialState = (
233
232
  let processChainConfig = processConfigChains->Dict.getUnsafe(chainIdStr)
234
233
  let indexingAddresses = indexingAddressesByChain->Dict.get(chainIdStr)->Option.getOr([])
235
234
  {
236
- Persistence.id: chainId,
235
+ Persistence.id: chain,
237
236
  startBlock: processChainConfig.startBlock,
238
237
  endBlock: processChainConfig.endBlock,
239
238
  sourceBlockNumber: processChainConfig.endBlock->Option.getOr(0),
@@ -310,12 +309,9 @@ let parseBlockRange = (
310
309
  ~rawChainConfig: rawChainConfig,
311
310
  ~progressBlock: option<int>,
312
311
  ): chainConfig => {
313
- let chainId = switch chainIdStr->Int.fromString {
314
- | Some(id) => id
315
- | None =>
316
- JsError.throwWithMessage(`Invalid chain ID "${chainIdStr}": expected a numeric chain ID`)
312
+ let chain = try chainIdStr->ChainId.normalizeOrThrow catch {
313
+ | _ => JsError.throwWithMessage(`Invalid chain ID "${chainIdStr}": expected a numeric chain ID`)
317
314
  }
318
- let chain = ChainMap.Chain.makeUnsafe(~chainId)
319
315
  if !(config.chainMap->ChainMap.has(chain)) {
320
316
  JsError.throwWithMessage(`Chain ${chainIdStr} is not configured in config.yaml`)
321
317
  }
@@ -485,6 +481,10 @@ let makeInMemoryStorage = (~state: testIndexerState): Persistence.storage => {
485
481
  state
486
482
  ->handleLoad(~tableName=table.tableName, ~filter)
487
483
  ->(Utils.magic: array<Internal.entity> => array<unknown>),
484
+ // The in-memory storage has no indexes to build, and it's always ready.
485
+ ensureQueryIndexes: async (~table as _, ~filters as _) => (),
486
+ ensureSchemaIndexes: async (~entities as _) => (),
487
+ finalizeBackfill: async (~entities as _, ~chainIds as _, ~readyAt as _) => (),
488
488
  writeBatch: async (
489
489
  ~batch,
490
490
  ~rollback as _,
@@ -638,7 +638,7 @@ let createTestIndexer = (): t<'processConfig> => {
638
638
  config.chainMap
639
639
  ->ChainMap.values
640
640
  ->Array.forEach(chainConfig => {
641
- let chainIdStr = chainConfig.id->Int.toString
641
+ let chainIdStr = chainConfig.id->ChainId.toString
642
642
  chainIds->Array.push(chainConfig.id)->ignore
643
643
 
644
644
  let chainObj = Utils.Object.createNullObject()
@@ -673,7 +673,7 @@ let createTestIndexer = (): t<'processConfig> => {
673
673
  )
674
674
  }
675
675
  getIndexingAddressesByChain(state)
676
- ->Dict.get(chainConfig.id->Int.toString)
676
+ ->Dict.get(chainConfig.id->ChainId.toString)
677
677
  ->Option.getOr([])
678
678
  ->Array.filterMap(ia => ia.contractName === contract.name ? Some(ia.address) : None)
679
679
  },
@@ -699,7 +699,7 @@ let createTestIndexer = (): t<'processConfig> => {
699
699
 
700
700
  // Build the result object with process + entity operations + chain info
701
701
  let result: dict<unknown> = Dict.make()
702
- result->Dict.set("chainIds", chainIds->(Utils.magic: array<int> => unknown))
702
+ result->Dict.set("chainIds", chainIds->(Utils.magic: array<ChainId.t> => unknown))
703
703
  result->Dict.set("chains", chains->(Utils.magic: {..} => unknown))
704
704
  entityOpsDict
705
705
  ->Dict.toArray