envio 3.9.0 → 3.10.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 (110) hide show
  1. package/evm.schema.json +26 -0
  2. package/fuel.schema.json +26 -0
  3. package/index.d.ts +35 -3
  4. package/package.json +6 -7
  5. package/src/Batch.res +9 -0
  6. package/src/ChainState.res +35 -39
  7. package/src/ChainState.res.mjs +14 -11
  8. package/src/ChainState.resi +15 -7
  9. package/src/Config.res +52 -44
  10. package/src/Config.res.mjs +51 -17
  11. package/src/Core.res +4 -0
  12. package/src/CrossChainState.res +15 -23
  13. package/src/CrossChainState.res.mjs +10 -18
  14. package/src/CrossChainState.resi +4 -1
  15. package/src/Ecosystem.res +7 -2
  16. package/src/Envio.res +6 -4
  17. package/src/EventConfigBuilder.res +169 -26
  18. package/src/EventConfigBuilder.res.mjs +124 -15
  19. package/src/HandlerRegister.res +21 -4
  20. package/src/HandlerRegister.res.mjs +24 -5
  21. package/src/InMemoryStore.res +9 -7
  22. package/src/InMemoryStore.res.mjs +3 -3
  23. package/src/IndexerState.res +43 -6
  24. package/src/IndexerState.res.mjs +36 -7
  25. package/src/IndexerState.resi +4 -4
  26. package/src/Internal.res +16 -17
  27. package/src/Metrics.res +72 -6
  28. package/src/Metrics.res.mjs +30 -2
  29. package/src/Persistence.res +36 -30
  30. package/src/Persistence.res.mjs +1 -20
  31. package/src/PgStorage.res +104 -56
  32. package/src/PgStorage.res.mjs +57 -35
  33. package/src/PruneStaleHistory.res +85 -52
  34. package/src/PruneStaleHistory.res.mjs +63 -37
  35. package/src/Rollback.res +68 -45
  36. package/src/Rollback.res.mjs +38 -19
  37. package/src/RollbackCommit.res +7 -9
  38. package/src/RollbackCommit.res.mjs +5 -6
  39. package/src/SafeCheckpointTracking.res +11 -11
  40. package/src/SafeCheckpointTracking.res.mjs +7 -6
  41. package/src/SimulateItems.res +33 -18
  42. package/src/SimulateItems.res.mjs +26 -22
  43. package/src/Sink.res +38 -26
  44. package/src/Sink.res.mjs +21 -16
  45. package/src/TestIndexer.res +5 -5
  46. package/src/TestIndexer.res.mjs +1 -1
  47. package/src/Utils.res +170 -0
  48. package/src/Utils.res.mjs +153 -0
  49. package/src/Writing.res +2 -2
  50. package/src/Writing.res.mjs +1 -1
  51. package/src/bindings/ClickHouse.res +366 -698
  52. package/src/bindings/ClickHouse.res.mjs +371 -421
  53. package/src/bindings/ClickHouseSink.res +337 -0
  54. package/src/bindings/ClickHouseSink.res.mjs +246 -0
  55. package/src/bindings/EventSource.res +8 -2
  56. package/src/bindings/NodeJs.res +6 -0
  57. package/src/bindings/Vitest.res +23 -0
  58. package/src/bindings/Vitest.res.mjs +3 -0
  59. package/src/bindings/WebSocket.res +9 -10
  60. package/src/db/CheckpointBounds.res +53 -0
  61. package/src/db/CheckpointBounds.res.mjs +44 -0
  62. package/src/db/EntityFilter.res +36 -17
  63. package/src/db/EntityFilter.res.mjs +25 -14
  64. package/src/db/EntityHistory.res +47 -22
  65. package/src/db/EntityHistory.res.mjs +19 -12
  66. package/src/db/InternalTable.res +84 -35
  67. package/src/db/InternalTable.res.mjs +56 -23
  68. package/src/db/RollbackFloors.res +55 -0
  69. package/src/db/RollbackFloors.res.mjs +92 -0
  70. package/src/db/Table.res +22 -4
  71. package/src/db/Table.res.mjs +30 -9
  72. package/src/sources/Evm.res +2 -0
  73. package/src/sources/Evm.res.mjs +2 -0
  74. package/src/sources/EvmHyperSyncSource.res +3 -3
  75. package/src/sources/EvmHyperSyncSource.res.mjs +3 -3
  76. package/src/sources/EvmRpcWs.res +124 -0
  77. package/src/sources/EvmRpcWs.res.mjs +117 -0
  78. package/src/sources/Fuel.res +2 -0
  79. package/src/sources/Fuel.res.mjs +2 -0
  80. package/src/sources/FuelHyperSyncSource.res +1 -1
  81. package/src/sources/FuelHyperSyncSource.res.mjs +2 -1
  82. package/src/sources/HeightFeed.res +568 -0
  83. package/src/sources/HeightFeed.res.mjs +452 -0
  84. package/src/sources/HeightStream.res +257 -0
  85. package/src/sources/HeightStream.res.mjs +194 -0
  86. package/src/sources/HyperSync.res +5 -0
  87. package/src/sources/HyperSync.res.mjs +3 -0
  88. package/src/sources/HyperSync.resi +4 -0
  89. package/src/sources/HyperSyncSSE.res +49 -0
  90. package/src/sources/HyperSyncSSE.res.mjs +79 -0
  91. package/src/sources/RpcSource.res +1 -1
  92. package/src/sources/RpcSource.res.mjs +2 -2
  93. package/src/sources/Source.res +54 -1
  94. package/src/sources/Source.res.mjs +25 -0
  95. package/src/sources/SourceManager.res +220 -227
  96. package/src/sources/SourceManager.res.mjs +139 -164
  97. package/src/sources/SourceManager.resi +8 -0
  98. package/src/sources/Svm.res +2 -0
  99. package/src/sources/Svm.res.mjs +2 -0
  100. package/src/sources/SvmHyperSyncClient.res +70 -127
  101. package/src/sources/SvmHyperSyncClient.res.mjs +51 -25
  102. package/src/sources/SvmHyperSyncSource.res +18 -15
  103. package/src/sources/SvmHyperSyncSource.res.mjs +5 -4
  104. package/svm.schema.json +1 -75
  105. package/src/MemoryStorage.res +0 -729
  106. package/src/MemoryStorage.res.mjs +0 -586
  107. package/src/sources/HyperSyncHeightStream.res +0 -129
  108. package/src/sources/HyperSyncHeightStream.res.mjs +0 -110
  109. package/src/sources/RpcWebSocketHeightStream.res +0 -175
  110. package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -180
package/src/Rollback.res CHANGED
@@ -127,86 +127,105 @@ and executeRollback = async (
127
127
  }
128
128
  }
129
129
 
130
- let eventsProcessedDiffByChain = Dict.make()
131
- let newProgressBlockNumberPerChain = Dict.make()
130
+ // The diff computed here replaces a pending one rather than merging with it,
131
+ // so its deletes have to cover everything that one would have deleted. The
132
+ // flush above leaves a diff pending only when no batch has come along to
133
+ // carry it.
134
+ let floors = {
135
+ let next = if state->IndexerState.config->Config.isIsolatedMultichain {
136
+ RollbackFloors.isolated(
137
+ ~chainId=reorgChain,
138
+ ~floorCheckpointId=rollbackTargetCheckpointId,
139
+ ~forkBlockNumber=rollbackTargetBlockNumber,
140
+ )
141
+ } else {
142
+ RollbackFloors.global(
143
+ ~floorCheckpointId=rollbackTargetCheckpointId,
144
+ ~reorgChainId=reorgChain,
145
+ ~forkBlockNumber=rollbackTargetBlockNumber,
146
+ )
147
+ }
148
+ switch state->IndexerState.pendingRollback {
149
+ | None => next
150
+ | Some({floors: pending}) => RollbackFloors.merge(pending, next)
151
+ }
152
+ }
153
+
154
+ let progressDiffByChain: dict<ChainState.progressDiff> = Dict.make()
132
155
  let rollbackedProcessedEvents = ref(0.)
133
156
 
134
157
  {
135
158
  let rollbackProgressDiff = await (
136
159
  state->IndexerState.persistence
137
- ).storage.getRollbackProgressDiff(~rollbackTargetCheckpointId)
160
+ ).storage.getRollbackProgressDiff(~floors)
138
161
  for idx in 0 to rollbackProgressDiff->Array.length - 1 {
139
162
  let diff = rollbackProgressDiff->Array.getUnsafe(idx)
140
- eventsProcessedDiffByChain->ChainId.Dict.set(
141
- diff["chain_id"],
163
+ let chainId = diff["chain_id"]
164
+ let eventsProcessed = Float.fromString(diff["events_processed_diff"])->Option.getOrThrow
165
+ rollbackedProcessedEvents := rollbackedProcessedEvents.contents +. eventsProcessed
166
+ progressDiffByChain->ChainId.Dict.set(
167
+ chainId,
142
168
  {
143
- let eventsProcessedDiff =
144
- Float.fromString(diff["events_processed_diff"])->Option.getOrThrow
145
- rollbackedProcessedEvents := rollbackedProcessedEvents.contents +. eventsProcessedDiff
146
- eventsProcessedDiff
147
- },
148
- )
149
- newProgressBlockNumberPerChain->ChainId.Dict.set(
150
- diff["chain_id"],
151
- if rollbackTargetCheckpointId === 0n && diff["chain_id"] === reorgChain {
152
- Pervasives.min(diff["new_progress_block_number"], rollbackTargetBlockNumber)
153
- } else {
154
- diff["new_progress_block_number"]
169
+ blockNumber: diff["new_progress_block_number"],
170
+ eventsProcessed,
155
171
  },
156
172
  )
157
173
  }
158
174
  }
159
175
 
160
- let rolledBackChains = []
176
+ // Where the rollback leaves each chain it moved, written with the diff: the
177
+ // batch that carries it may belong to a chain the rollback never touched.
178
+ let rolledBackChains: array<InternalTable.Chains.progressedChain> = []
161
179
  let rolledBackAddresses = []
162
180
  state
163
181
  ->IndexerState.chainStates
164
182
  ->Utils.Dict.forEach(cs => {
165
183
  let chainId = (cs->ChainState.chainConfig).id
166
184
  let fromBlock = cs->ChainState.committedProgressBlockNumber
167
- let killedAddresses =
168
- cs->ChainState.rollback(
169
- ~newProgressBlockNumber=newProgressBlockNumberPerChain->ChainId.Dict.dangerouslyGetNonOption(
170
- chainId,
171
- ),
172
- ~eventsProcessedDiff=eventsProcessedDiffByChain->ChainId.Dict.dangerouslyGetNonOption(
173
- chainId,
174
- ),
175
- ~rollbackTargetBlockNumber,
176
- ~isReorgChain=chainId === reorgChain,
177
- )
185
+ let progressDiff = progressDiffByChain->ChainId.Dict.dangerouslyGetNonOption(chainId)
186
+ let killedAddresses = cs->ChainState.rollback(
187
+ ~rolledBackTo=switch (progressDiff, floors->RollbackFloors.forkBlockNumber(chainId)) {
188
+ | (Some(progressDiff), forkBlockNumber) =>
189
+ RecomputedProgress({
190
+ ...progressDiff,
191
+ blockNumber: forkBlockNumber->Option.mapOr(progressDiff.blockNumber, forkBlockNumber =>
192
+ Pervasives.min(progressDiff.blockNumber, forkBlockNumber)
193
+ ),
194
+ })
195
+ // Nothing of this chain's is above its floor, so there are no checkpoints
196
+ // to recompute from.
197
+ | (None, Some(forkBlockNumber)) => ForkBlock(forkBlockNumber)
198
+ | (None, None) => Untouched
199
+ },
200
+ )
178
201
  rolledBackAddresses->Array.pushMany(killedAddresses)->ignore
179
202
  let toBlock = cs->ChainState.committedProgressBlockNumber
180
203
  if fromBlock !== toBlock {
181
204
  rolledBackChains
182
205
  ->Array.push({
206
+ chainId,
207
+ progressBlockNumber: toBlock,
208
+ sourceBlockNumber: cs->ChainState.knownHeight,
209
+ totalEventsProcessed: cs->ChainState.numEventsProcessed,
210
+ })
211
+ ->ignore
212
+ logger->Logging.childInfo({
213
+ "msg": "Rollbacked",
183
214
  "chainId": chainId,
184
215
  "fromBlock": fromBlock,
185
216
  "toBlock": toBlock,
186
- "rollbackedEvents": eventsProcessedDiffByChain
187
- ->ChainId.Dict.dangerouslyGetNonOption(chainId)
188
- ->Option.getOr(0.),
217
+ "rollbackedEvents": progressDiff->Option.mapOr(0., diff => diff.eventsProcessed),
189
218
  })
190
- ->ignore
191
219
  }
192
220
  })
193
221
 
194
222
  let diff = await state->InMemoryStore.prepareRollbackDiff(
195
- ~rollbackTargetCheckpointId,
223
+ ~floors,
196
224
  ~rollbackDiffCheckpointId=state->IndexerState.committedCheckpointId->BigInt.add(1n),
197
- ~progressBlockNumberByChainId=newProgressBlockNumberPerChain,
225
+ ~progressedChains=rolledBackChains,
198
226
  ~rolledBackAddresses,
199
227
  )
200
228
 
201
- rolledBackChains->Array.forEach(rolledBack => {
202
- logger->Logging.childInfo({
203
- "msg": "Rollbacked",
204
- "chainId": rolledBack["chainId"],
205
- "fromBlock": rolledBack["fromBlock"],
206
- "toBlock": rolledBack["toBlock"],
207
- "rollbackedEvents": rolledBack["rollbackedEvents"],
208
- })
209
- })
210
229
  logger->Logging.childTrace({
211
230
  "msg": "Rollback entity changes",
212
231
  "deleted": diff["deletedEntities"],
@@ -217,7 +236,11 @@ and executeRollback = async (
217
236
  ~rollbackedProcessedEvents=rollbackedProcessedEvents.contents,
218
237
  )
219
238
 
220
- state->IndexerState.completeRollback(~eventsProcessedDiffByChain)
239
+ state->IndexerState.completeRollback(
240
+ ~eventsProcessedDiffByChain=progressDiffByChain->Utils.Dict.mapValues(diff =>
241
+ diff.eventsProcessed
242
+ ),
243
+ )
221
244
  scheduleFetch()
222
245
  scheduleProcessing()
223
246
  }
@@ -1,6 +1,7 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
3
  import * as Utils from "./Utils.res.mjs";
4
+ import * as Config from "./Config.res.mjs";
4
5
  import * as Logging from "./Logging.res.mjs";
5
6
  import * as Writing from "./Writing.res.mjs";
6
7
  import * as ChainState from "./ChainState.res.mjs";
@@ -12,6 +13,7 @@ import * as InMemoryStore from "./InMemoryStore.res.mjs";
12
13
  import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
13
14
  import * as SourceManager from "./sources/SourceManager.res.mjs";
14
15
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
16
+ import * as RollbackFloors from "./db/RollbackFloors.res.mjs";
15
17
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
16
18
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
17
19
 
@@ -42,50 +44,67 @@ async function executeRollback(state, reorgChain, rollbackTargetBlockNumber, sch
42
44
  await Writing.flush(state);
43
45
  let checkpointId = await IndexerState.persistence(state).storage.getRollbackTargetCheckpoint(reorgChain, rollbackTargetBlockNumber);
44
46
  let rollbackTargetCheckpointId = checkpointId !== undefined ? checkpointId : 0n;
45
- let eventsProcessedDiffByChain = {};
46
- let newProgressBlockNumberPerChain = {};
47
+ let next = Config.isIsolatedMultichain(IndexerState.config(state)) ? RollbackFloors.isolated(reorgChain, rollbackTargetCheckpointId, rollbackTargetBlockNumber) : RollbackFloors.global(rollbackTargetCheckpointId, reorgChain, rollbackTargetBlockNumber);
48
+ let match = IndexerState.pendingRollback(state);
49
+ let floors = match !== undefined ? RollbackFloors.merge(match.floors, next) : next;
50
+ let progressDiffByChain = {};
47
51
  let rollbackedProcessedEvents = 0;
48
- let rollbackProgressDiff = await IndexerState.persistence(state).storage.getRollbackProgressDiff(rollbackTargetCheckpointId);
52
+ let rollbackProgressDiff = await IndexerState.persistence(state).storage.getRollbackProgressDiff(floors);
49
53
  for (let idx = 0, idx_finish = rollbackProgressDiff.length; idx < idx_finish; ++idx) {
50
54
  let diff = rollbackProgressDiff[idx];
51
- let eventsProcessedDiff = Stdlib_Option.getOrThrow(Stdlib_Float.fromString(diff.events_processed_diff), undefined);
52
- rollbackedProcessedEvents = rollbackedProcessedEvents + eventsProcessedDiff;
53
- eventsProcessedDiffByChain[diff.chain_id] = eventsProcessedDiff;
54
- newProgressBlockNumberPerChain[diff.chain_id] = rollbackTargetCheckpointId === 0n && diff.chain_id === reorgChain ? Primitive_int.min(diff.new_progress_block_number, rollbackTargetBlockNumber) : diff.new_progress_block_number;
55
+ let chainId = diff.chain_id;
56
+ let eventsProcessed = Stdlib_Option.getOrThrow(Stdlib_Float.fromString(diff.events_processed_diff), undefined);
57
+ rollbackedProcessedEvents = rollbackedProcessedEvents + eventsProcessed;
58
+ progressDiffByChain[chainId] = {
59
+ blockNumber: diff.new_progress_block_number,
60
+ eventsProcessed: eventsProcessed
61
+ };
55
62
  }
56
63
  let rolledBackChains = [];
57
64
  let rolledBackAddresses = [];
58
65
  Utils.Dict.forEach(IndexerState.chainStates(state), cs => {
59
66
  let chainId = ChainState.chainConfig(cs).id;
60
67
  let fromBlock = ChainState.committedProgressBlockNumber(cs);
61
- let killedAddresses = ChainState.rollback(cs, newProgressBlockNumberPerChain[chainId], eventsProcessedDiffByChain[chainId], rollbackTargetBlockNumber, chainId === reorgChain);
68
+ let progressDiff = progressDiffByChain[chainId];
69
+ let match = RollbackFloors.forkBlockNumber(floors, chainId);
70
+ let killedAddresses = ChainState.rollback(cs, progressDiff !== undefined ? ({
71
+ TAG: "RecomputedProgress",
72
+ _0: {
73
+ blockNumber: Stdlib_Option.mapOr(match, progressDiff.blockNumber, forkBlockNumber => Primitive_int.min(progressDiff.blockNumber, forkBlockNumber)),
74
+ eventsProcessed: progressDiff.eventsProcessed
75
+ }
76
+ }) : (
77
+ match !== undefined ? ({
78
+ TAG: "ForkBlock",
79
+ _0: match
80
+ }) : "Untouched"
81
+ ));
62
82
  rolledBackAddresses.push(...killedAddresses);
63
83
  let toBlock = ChainState.committedProgressBlockNumber(cs);
64
84
  if (fromBlock !== toBlock) {
65
85
  rolledBackChains.push({
86
+ chainId: chainId,
87
+ progressBlockNumber: toBlock,
88
+ sourceBlockNumber: ChainState.knownHeight(cs),
89
+ totalEventsProcessed: ChainState.numEventsProcessed(cs)
90
+ });
91
+ return Logging.childInfo(logger, {
92
+ msg: "Rollbacked",
66
93
  chainId: chainId,
67
94
  fromBlock: fromBlock,
68
95
  toBlock: toBlock,
69
- rollbackedEvents: Stdlib_Option.getOr(eventsProcessedDiffByChain[chainId], 0)
96
+ rollbackedEvents: Stdlib_Option.mapOr(progressDiff, 0, diff => diff.eventsProcessed)
70
97
  });
71
- return;
72
98
  }
73
99
  });
74
- let diff$1 = await InMemoryStore.prepareRollbackDiff(state, rollbackTargetCheckpointId, IndexerState.committedCheckpointId(state) + 1n, newProgressBlockNumberPerChain, rolledBackAddresses);
75
- rolledBackChains.forEach(rolledBack => Logging.childInfo(logger, {
76
- msg: "Rollbacked",
77
- chainId: rolledBack.chainId,
78
- fromBlock: rolledBack.fromBlock,
79
- toBlock: rolledBack.toBlock,
80
- rollbackedEvents: rolledBack.rollbackedEvents
81
- }));
100
+ let diff$1 = await InMemoryStore.prepareRollbackDiff(state, floors, IndexerState.committedCheckpointId(state) + 1n, rolledBackChains, rolledBackAddresses);
82
101
  Logging.childTrace(logger, {
83
102
  msg: "Rollback entity changes",
84
103
  deleted: diff$1.deletedEntities,
85
104
  upserted: diff$1.setEntities
86
105
  });
87
106
  IndexerState.recordRollbackSuccess(state, Performance.secondsSince(startTime), rollbackedProcessedEvents);
88
- IndexerState.completeRollback(state, eventsProcessedDiffByChain);
107
+ IndexerState.completeRollback(state, Utils.Dict.mapValues(progressDiffByChain, diff => diff.eventsProcessed));
89
108
  scheduleFetch();
90
109
  return scheduleProcessing();
91
110
  }
@@ -20,15 +20,13 @@ let register = (callback: callback) => {
20
20
  }
21
21
  }
22
22
 
23
- // Fired after a rollback diff is durably written, once per affected chain.
24
- // `progressBlockNumberByChainId` is the last valid block per chain, taken from
25
- // the in-memory store's rollback object. A throwing callback bubbles to the
26
- // write loop's onError, crashing the indexer like a failed write.
27
- let fire = async (~progressBlockNumberByChainId: dict<int>) => {
28
- let _ = await progressBlockNumberByChainId
29
- ->Dict.toArray
30
- ->Array.flatMap(((chainIdKey, rollbackToBlock)) => {
31
- let args = {chainId: chainIdKey->ChainId.normalizeOrThrow, rollbackToBlock}
23
+ // Fired after a rollback diff is durably written, once per affected chain, with
24
+ // the last valid block the rollback left that chain at. A throwing callback
25
+ // bubbles to the write loop's onError, crashing the indexer like a failed write.
26
+ let fire = async (~progressedChains: array<InternalTable.Chains.progressedChain>) => {
27
+ let _ = await progressedChains
28
+ ->Array.flatMap(({chainId, progressBlockNumber}) => {
29
+ let args = {chainId, rollbackToBlock: progressBlockNumber}
32
30
  callbacks->Array.map(callback => callback(args))
33
31
  })
34
32
  ->Promise.all
@@ -1,6 +1,5 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
- import * as ChainId from "./ChainId.res.mjs";
4
3
  import * as EnvioGlobal from "./EnvioGlobal.res.mjs";
5
4
 
6
5
  let callbacks = EnvioGlobal.value.rollbackCommitCallbacks;
@@ -16,10 +15,10 @@ function register(callback) {
16
15
  };
17
16
  }
18
17
 
19
- async function fire(progressBlockNumberByChainId) {
20
- await Promise.all(Object.entries(progressBlockNumberByChainId).flatMap(param => {
21
- let args_chainId = ChainId.normalizeOrThrow(param[0]);
22
- let args_rollbackToBlock = param[1];
18
+ async function fire(progressedChains) {
19
+ await Promise.all(progressedChains.flatMap(param => {
20
+ let args_chainId = param.chainId;
21
+ let args_rollbackToBlock = param.progressBlockNumber;
23
22
  let args = {
24
23
  chainId: args_chainId,
25
24
  rollbackToBlock: args_rollbackToBlock
@@ -33,4 +32,4 @@ export {
33
32
  register,
34
33
  fire,
35
34
  }
36
- /* ChainId Not a pure module */
35
+ /* EnvioGlobal Not a pure module */
@@ -33,15 +33,15 @@ let make = (
33
33
  }
34
34
  }
35
35
 
36
- let getSafeCheckpointId = (safeCheckpointTracking: t, ~sourceBlockNumber: int) => {
36
+ let getSafeCheckpointId = (safeCheckpointTracking: t, ~sourceBlockNumber: int): option<
37
+ Internal.checkpointId,
38
+ > => {
37
39
  let safeBlockNumber = sourceBlockNumber - safeCheckpointTracking.maxReorgDepth
38
40
 
39
41
  switch safeCheckpointTracking.checkpointIds {
40
- | [] => 0n
41
- | _
42
- if safeCheckpointTracking.checkpointBlockNumbers->Array.getUnsafe(0) >
43
- safeBlockNumber => 0n
44
- | [checkpointId] => checkpointId
42
+ | [] => None
43
+ | _ if safeCheckpointTracking.checkpointBlockNumbers->Array.getUnsafe(0) > safeBlockNumber => None
44
+ | [checkpointId] => Some(checkpointId)
45
45
  | _ => {
46
46
  let trackingCheckpointsCount = safeCheckpointTracking.checkpointIds->Array.length
47
47
  let result = ref(None)
@@ -52,16 +52,15 @@ let getSafeCheckpointId = (safeCheckpointTracking: t, ~sourceBlockNumber: int) =
52
52
  safeCheckpointTracking.checkpointBlockNumbers->Array.getUnsafe(idx.contents) >
53
53
  safeBlockNumber
54
54
  ) {
55
- result :=
56
- Some(safeCheckpointTracking.checkpointIds->Array.getUnsafe(idx.contents - 1))
55
+ result := Some(safeCheckpointTracking.checkpointIds->Array.getUnsafe(idx.contents - 1))
57
56
  }
58
57
  idx := idx.contents + 1
59
58
  }
60
59
 
61
60
  switch result.contents {
62
- | Some(checkpointId) => checkpointId
61
+ | Some(_) => result.contents
63
62
  | None =>
64
- safeCheckpointTracking.checkpointIds->Array.getUnsafe(trackingCheckpointsCount - 1)
63
+ Some(safeCheckpointTracking.checkpointIds->Array.getUnsafe(trackingCheckpointsCount - 1))
65
64
  }
66
65
  }
67
66
  }
@@ -75,7 +74,8 @@ let updateOnNewBatch = (
75
74
  ~batchCheckpointBlockNumbers: array<int>,
76
75
  ~batchCheckpointChainIds: array<ChainId.t>,
77
76
  ) => {
78
- let safeCheckpointId = getSafeCheckpointId(safeCheckpointTracking, ~sourceBlockNumber)
77
+ let safeCheckpointId =
78
+ getSafeCheckpointId(safeCheckpointTracking, ~sourceBlockNumber)->Option.getOr(0n)
79
79
 
80
80
  let mutCheckpointIds = []
81
81
  let mutCheckpointBlockNumbers = []
@@ -1,5 +1,6 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
3
4
 
4
5
  function make(maxReorgDepth, shouldRollbackOnReorg, chainReorgCheckpoints) {
5
6
  if (!(maxReorgDepth > 0 && shouldRollbackOnReorg)) {
@@ -22,10 +23,10 @@ function getSafeCheckpointId(safeCheckpointTracking, sourceBlockNumber) {
22
23
  let safeBlockNumber = sourceBlockNumber - safeCheckpointTracking.maxReorgDepth | 0;
23
24
  let match = safeCheckpointTracking.checkpointIds;
24
25
  if (match.length === 0) {
25
- return 0n;
26
+ return;
26
27
  }
27
28
  if (safeCheckpointTracking.checkpointBlockNumbers[0] > safeBlockNumber) {
28
- return 0n;
29
+ return;
29
30
  }
30
31
  if (match.length === 1) {
31
32
  return match[0];
@@ -39,16 +40,16 @@ function getSafeCheckpointId(safeCheckpointTracking, sourceBlockNumber) {
39
40
  }
40
41
  idx = idx + 1 | 0;
41
42
  };
42
- let checkpointId = result;
43
- if (checkpointId !== undefined) {
44
- return checkpointId;
43
+ let match$1 = result;
44
+ if (match$1 !== undefined) {
45
+ return result;
45
46
  } else {
46
47
  return safeCheckpointTracking.checkpointIds[trackingCheckpointsCount - 1 | 0];
47
48
  }
48
49
  }
49
50
 
50
51
  function updateOnNewBatch(safeCheckpointTracking, sourceBlockNumber, chainId, batchCheckpointIds, batchCheckpointBlockNumbers, batchCheckpointChainIds) {
51
- let safeCheckpointId = getSafeCheckpointId(safeCheckpointTracking, sourceBlockNumber);
52
+ let safeCheckpointId = Stdlib_Option.getOr(getSafeCheckpointId(safeCheckpointTracking, sourceBlockNumber), 0n);
52
53
  let mutCheckpointIds = [];
53
54
  let mutCheckpointBlockNumbers = [];
54
55
  for (let idx = 0, idx_finish = safeCheckpointTracking.checkpointIds.length; idx < idx_finish; ++idx) {
@@ -338,11 +338,12 @@ let parse = (
338
338
  | None =>
339
339
  switch blockJson {
340
340
  | Some(bj) =>
341
- switch (bj->(Utils.magic: JSON.t => dict<JSON.t>))->Dict.get("slot") {
341
+ switch bj->(Utils.magic: JSON.t => dict<JSON.t>)->Dict.get("slot") {
342
342
  | Some(v) =>
343
- v->(Utils.magic: JSON.t => Nullable.t<int>)->Nullable.toOption->Option.getOr(
344
- currentBlock.contents,
345
- )
343
+ v
344
+ ->(Utils.magic: JSON.t => Nullable.t<int>)
345
+ ->Nullable.toOption
346
+ ->Option.getOr(currentBlock.contents)
346
347
  | None => currentBlock.contents
347
348
  }
348
349
  | None => currentBlock.contents
@@ -371,13 +372,23 @@ let parse = (
371
372
  | None => []
372
373
  }
373
374
  }
374
- let data = item.data->Option.getOr(svmEventConfig.discriminator->Option.getOr("0x"))
375
- let argsJson = item.args->Option.mapOr("{}", args => args->JSON.stringify)
375
+ let data = switch (item.data, svmEventConfig.discriminator) {
376
+ | (Some(data), _) => data
377
+ | (None, Some(discriminator)) =>
378
+ discriminator
379
+ ->String.replace("0x", "")
380
+ ->NodeJs.Buffer.fromHex
381
+ ->Uint8Array.fromArrayLikeOrIterable
382
+ | (None, None) => Uint8Array.fromLength(0)
383
+ }
384
+ let args = item.args->Option.getOr(Dict.make()->(Utils.magic: dict<unknown> => unknown))
376
385
  let logs = item.logs->Option.map(logs =>
377
- logs->Array.map((log): SvmHyperSyncClient.EventItems.log => {
378
- kind: log.kind->Null.fromOption,
379
- message: log.message->Null.fromOption,
380
- })
386
+ logs->Array.map(
387
+ (log): SvmHyperSyncClient.EventItems.log => {
388
+ kind: log.kind->Null.fromOption,
389
+ message: log.message->Null.fromOption,
390
+ },
391
+ )
381
392
  )
382
393
 
383
394
  let liveRegistrations = liveRegistrationsFor(~config, ~chainId, ~eventConfig)
@@ -414,13 +425,13 @@ let parse = (
414
425
  accountIndex: ?activity.transactionAccountIndex,
415
426
  isSigner: ?activity.isSigner,
416
427
  isWritable: ?activity.isWritable,
417
- preBalance: ?activity.lamports->Option.flatMap(l => l.pre),
418
- postBalance: ?activity.lamports->Option.flatMap(l => l.post),
419
- mint: ?activity.token->Option.flatMap(t => t.mint),
420
- owner: ?activity.token->Option.flatMap(t => t.owner),
421
- decimals: ?activity.token->Option.flatMap(t => t.decimals),
422
- preAmount: ?activity.token->Option.flatMap(t => t.preAmount),
423
- postAmount: ?activity.token->Option.flatMap(t => t.postAmount),
428
+ preBalance: ?(activity.lamports->Option.flatMap(l => l.pre)),
429
+ postBalance: ?(activity.lamports->Option.flatMap(l => l.post)),
430
+ mint: ?(activity.token->Option.flatMap(t => t.mint)),
431
+ owner: ?(activity.token->Option.flatMap(t => t.owner)),
432
+ decimals: ?(activity.token->Option.flatMap(t => t.decimals)),
433
+ preAmount: ?(activity.token->Option.flatMap(t => t.preAmount)),
434
+ postAmount: ?(activity.token->Option.flatMap(t => t.postAmount)),
424
435
  })
425
436
  ->ignore
426
437
  )
@@ -456,7 +467,11 @@ let parse = (
456
467
  accounts: accountArguments,
457
468
  data,
458
469
  isInner: item.isInner->Option.getOr(false),
459
- argsJson,
470
+ // As the Rust client does: present exactly when this registration
471
+ // selected `args`.
472
+ args: onEventRegistration.fieldSelection.instructionFields->Utils.Set.has("args")
473
+ ? Null.make(args)
474
+ : Null.null,
460
475
  logs: logs->Null.fromOption,
461
476
  },
462
477
  ~programName,
@@ -245,8 +245,12 @@ function parse(simulateItems, config, chainConfig, onEventRegistrations) {
245
245
  }
246
246
  }) : [];
247
247
  }
248
- let data = Stdlib_Option.getOr(rawJson.data, Stdlib_Option.getOr(eventConfig.discriminator, "0x"));
249
- let argsJson = Stdlib_Option.mapOr(rawJson.args, "{}", args => JSON.stringify(args));
248
+ let match$3 = rawJson.data;
249
+ let match$4 = eventConfig.discriminator;
250
+ let data = match$3 !== undefined ? match$3 : (
251
+ match$4 !== undefined ? Uint8Array.from(Buffer.from(match$4.replace("0x", ""), "hex")) : new Uint8Array(0)
252
+ );
253
+ let args$1 = Stdlib_Option.getOr(rawJson.args, {});
250
254
  let logs = Stdlib_Option.map(rawJson.logs, logs => logs.map(log => ({
251
255
  kind: Stdlib_Null.fromOption(log.kind),
252
256
  message: Stdlib_Null.fromOption(log.message)
@@ -312,7 +316,7 @@ function parse(simulateItems, config, chainConfig, onEventRegistrations) {
312
316
  accounts: accountArguments,
313
317
  data: data,
314
318
  isInner: Stdlib_Option.getOr(rawJson.isInner, false),
315
- argsJson: argsJson,
319
+ args: newrecord.fieldSelection.instructionFields.has("args") ? args$1 : null,
316
320
  logs: Stdlib_Null.fromOption(logs)
317
321
  }, match$1, match$2, eventConfig, newrecord.fieldSelection);
318
322
  payload["srcAddress"] = programId;
@@ -329,14 +333,14 @@ function parse(simulateItems, config, chainConfig, onEventRegistrations) {
329
333
  });
330
334
  return;
331
335
  }
332
- let match$3 = rawJson.contract;
333
- let match$4 = rawJson.event;
334
- let match$5 = match$3 !== undefined && match$4 !== undefined ? [
335
- match$3,
336
- match$4
336
+ let match$5 = rawJson.contract;
337
+ let match$6 = rawJson.event;
338
+ let match$7 = match$5 !== undefined && match$6 !== undefined ? [
339
+ match$5,
340
+ match$6
337
341
  ] : Stdlib_JsError.throwWithMessage(`simulate: Invalid item. Each item must have "contract" and "event" fields.`);
338
- let eventName = match$5[1];
339
- let contractName = match$5[0];
342
+ let eventName = match$7[1];
343
+ let contractName = match$7[0];
340
344
  let ec$1 = findEventConfig(config, contractName, eventName);
341
345
  let eventConfig$1 = ec$1 !== undefined ? ec$1 : Stdlib_JsError.throwWithMessage(`simulate: Event "` + eventName + `" not found on contract "` + contractName + `". Check that the contract and event names match your config.yaml.`);
342
346
  let json = rawJson.params;
@@ -359,32 +363,32 @@ function parse(simulateItems, config, chainConfig, onEventRegistrations) {
359
363
  let blockJson$2 = (blockJson$1 == null) ? undefined : Primitive_option.some(blockJson$1);
360
364
  let transactionJson = rawJson.transaction;
361
365
  let transactionJson$1 = (transactionJson == null) ? undefined : Primitive_option.some(transactionJson);
362
- let match$6 = config.ecosystem.name;
363
- let match$7;
364
- switch (match$6) {
366
+ let match$8 = config.ecosystem.name;
367
+ let match$9;
368
+ switch (match$8) {
365
369
  case "evm" :
366
370
  let block$2 = parseEvmSimulateBlock(currentBlock.contents, blockJson$2);
367
- match$7 = [
371
+ match$9 = [
368
372
  block$2,
369
373
  block$2.number
370
374
  ];
371
375
  break;
372
376
  case "fuel" :
373
377
  let block$3 = parseFuelSimulateBlock(currentBlock.contents, blockJson$2);
374
- match$7 = [
378
+ match$9 = [
375
379
  block$3,
376
380
  block$3.height
377
381
  ];
378
382
  break;
379
383
  case "svm" :
380
- match$7 = Stdlib_JsError.throwWithMessage("simulate is not supported for SVM ecosystem");
384
+ match$9 = Stdlib_JsError.throwWithMessage("simulate is not supported for SVM ecosystem");
381
385
  break;
382
386
  }
383
- let blockNumber = match$7[1];
384
- let block$4 = match$7[0];
385
- let match$8 = config.ecosystem.name;
387
+ let blockNumber = match$9[1];
388
+ let block$4 = match$9[0];
389
+ let match$10 = config.ecosystem.name;
386
390
  let transaction$1;
387
- switch (match$8) {
391
+ switch (match$10) {
388
392
  case "evm" :
389
393
  transaction$1 = parseEvmSimulateTransaction(transactionJson$1);
390
394
  break;
@@ -411,9 +415,9 @@ function parse(simulateItems, config, chainConfig, onEventRegistrations) {
411
415
  }
412
416
  });
413
417
  if (Utils.$$Array.isEmpty(liveRegistrations$1)) {
414
- let match$9 = ChainMap.values(config.chainMap).length;
418
+ let match$11 = ChainMap.values(config.chainMap).length;
415
419
  Stdlib_JsError.throwWithMessage(`simulate: no handler runs for event "` + eventName + `" on contract "` + contractName + `"` + (
416
- match$9 !== 1 ? ` on chain ` + ChainId.toString(chainId) : ""
420
+ match$11 !== 1 ? ` on chain ` + ChainId.toString(chainId) : ""
417
421
  ) + `. Register a handler with indexer.onEvent (and check any \`where\` filter isn't excluding this chain) before simulating it.`);
418
422
  }
419
423
  liveRegistrations$1.forEach(reg => {