envio 3.3.0-alpha.1 → 3.3.0-alpha.11

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 (143) hide show
  1. package/evm.schema.json +10 -0
  2. package/index.d.ts +45 -25
  3. package/licenses/CLA.md +35 -0
  4. package/licenses/EULA.md +67 -0
  5. package/licenses/LICENSE.md +45 -0
  6. package/licenses/README.md +35 -0
  7. package/package.json +10 -9
  8. package/src/Address.res +5 -2
  9. package/src/Address.res.mjs +3 -1
  10. package/src/Api.res +1 -1
  11. package/src/Api.res.mjs +1 -1
  12. package/src/Batch.res +0 -6
  13. package/src/Batch.res.mjs +1 -12
  14. package/src/BatchProcessing.res +7 -12
  15. package/src/BatchProcessing.res.mjs +8 -7
  16. package/src/Bin.res +3 -0
  17. package/src/Bin.res.mjs +4 -0
  18. package/src/ChainFetching.res +53 -16
  19. package/src/ChainFetching.res.mjs +37 -19
  20. package/src/ChainMetadata.res +1 -11
  21. package/src/ChainMetadata.res.mjs +1 -10
  22. package/src/ChainState.res +630 -161
  23. package/src/ChainState.res.mjs +438 -101
  24. package/src/ChainState.resi +77 -4
  25. package/src/Config.res +70 -38
  26. package/src/Config.res.mjs +52 -12
  27. package/src/ContractRegisterContext.res +2 -12
  28. package/src/ContractRegisterContext.res.mjs +3 -5
  29. package/src/Core.res +34 -3
  30. package/src/Core.res.mjs +12 -0
  31. package/src/CrossChainState.res +130 -89
  32. package/src/CrossChainState.res.mjs +66 -61
  33. package/src/CrossChainState.resi +1 -1
  34. package/src/Ecosystem.res +5 -6
  35. package/src/Ecosystem.res.mjs +3 -3
  36. package/src/Envio.res +17 -11
  37. package/src/EnvioGlobal.res +53 -0
  38. package/src/EnvioGlobal.res.mjs +31 -0
  39. package/src/EventConfigBuilder.res +191 -127
  40. package/src/EventConfigBuilder.res.mjs +116 -66
  41. package/src/EventProcessing.res +77 -28
  42. package/src/EventProcessing.res.mjs +56 -29
  43. package/src/ExitOnCaughtUp.res +10 -2
  44. package/src/ExitOnCaughtUp.res.mjs +10 -1
  45. package/src/FetchState.res +684 -415
  46. package/src/FetchState.res.mjs +505 -486
  47. package/src/HandlerLoader.res +8 -104
  48. package/src/HandlerLoader.res.mjs +2 -81
  49. package/src/HandlerRegister.res +520 -144
  50. package/src/HandlerRegister.res.mjs +286 -133
  51. package/src/HandlerRegister.resi +24 -8
  52. package/src/IndexerState.res +10 -3
  53. package/src/IndexerState.res.mjs +11 -4
  54. package/src/IndexerState.resi +2 -1
  55. package/src/IndexingAddresses.res +108 -0
  56. package/src/IndexingAddresses.res.mjs +101 -0
  57. package/src/IndexingAddresses.resi +34 -0
  58. package/src/Internal.res +166 -48
  59. package/src/Internal.res.mjs +30 -2
  60. package/src/LoadLayer.res +5 -5
  61. package/src/LoadLayer.res.mjs +6 -6
  62. package/src/LogSelection.res +92 -217
  63. package/src/LogSelection.res.mjs +95 -184
  64. package/src/Main.res +71 -236
  65. package/src/Main.res.mjs +60 -145
  66. package/src/Metrics.res +74 -0
  67. package/src/Metrics.res.mjs +75 -0
  68. package/src/PgStorage.res +4 -4
  69. package/src/PgStorage.res.mjs +5 -5
  70. package/src/Prometheus.res +10 -63
  71. package/src/Prometheus.res.mjs +124 -171
  72. package/src/PruneStaleHistory.res +2 -2
  73. package/src/PruneStaleHistory.res.mjs +3 -3
  74. package/src/RawEvent.res +7 -2
  75. package/src/RawEvent.res.mjs +4 -4
  76. package/src/Rollback.res +3 -3
  77. package/src/Rollback.res.mjs +4 -4
  78. package/src/RollbackCommit.res +4 -1
  79. package/src/RollbackCommit.res.mjs +3 -2
  80. package/src/SimulateDeadInputTracker.res +85 -0
  81. package/src/SimulateDeadInputTracker.res.mjs +73 -0
  82. package/src/SimulateDeadInputTracker.resi +12 -0
  83. package/src/SimulateItems.res +128 -28
  84. package/src/SimulateItems.res.mjs +82 -40
  85. package/src/TestIndexer.res +55 -41
  86. package/src/TestIndexer.res.mjs +39 -32
  87. package/src/TopicFilter.res +1 -25
  88. package/src/TopicFilter.res.mjs +0 -74
  89. package/src/bindings/Performance.res +7 -0
  90. package/src/bindings/Performance.res.mjs +21 -0
  91. package/src/bindings/Performance.resi +7 -0
  92. package/src/bindings/Viem.res +0 -46
  93. package/src/bindings/Viem.res.mjs +1 -43
  94. package/src/sources/BlockStore.res +46 -0
  95. package/src/sources/BlockStore.res.mjs +24 -0
  96. package/src/sources/EventRouter.res +31 -49
  97. package/src/sources/EventRouter.res.mjs +12 -25
  98. package/src/sources/Evm.res +83 -72
  99. package/src/sources/Evm.res.mjs +53 -69
  100. package/src/sources/EvmChain.res +7 -34
  101. package/src/sources/EvmChain.res.mjs +6 -27
  102. package/src/sources/EvmRpcClient.res +71 -5
  103. package/src/sources/EvmRpcClient.res.mjs +13 -4
  104. package/src/sources/FieldMask.res +39 -0
  105. package/src/sources/FieldMask.res.mjs +42 -0
  106. package/src/sources/Fuel.res +9 -6
  107. package/src/sources/Fuel.res.mjs +5 -10
  108. package/src/sources/HyperFuelSource.res +46 -50
  109. package/src/sources/HyperFuelSource.res.mjs +64 -54
  110. package/src/sources/HyperSync.res +45 -42
  111. package/src/sources/HyperSync.res.mjs +68 -60
  112. package/src/sources/HyperSync.resi +14 -4
  113. package/src/sources/HyperSyncClient.res +107 -119
  114. package/src/sources/HyperSyncClient.res.mjs +36 -31
  115. package/src/sources/HyperSyncHeightStream.res +1 -8
  116. package/src/sources/HyperSyncHeightStream.res.mjs +0 -2
  117. package/src/sources/HyperSyncSource.res +60 -254
  118. package/src/sources/HyperSyncSource.res.mjs +57 -180
  119. package/src/sources/Rpc.res +15 -79
  120. package/src/sources/Rpc.res.mjs +25 -101
  121. package/src/sources/RpcSource.res +221 -514
  122. package/src/sources/RpcSource.res.mjs +216 -411
  123. package/src/sources/RpcWebSocketHeightStream.res +0 -5
  124. package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -2
  125. package/src/sources/SimulateSource.res +44 -20
  126. package/src/sources/SimulateSource.res.mjs +41 -14
  127. package/src/sources/Source.res +34 -6
  128. package/src/sources/SourceManager.res +77 -19
  129. package/src/sources/SourceManager.res.mjs +63 -21
  130. package/src/sources/SourceManager.resi +10 -0
  131. package/src/sources/Svm.res +31 -16
  132. package/src/sources/Svm.res.mjs +36 -13
  133. package/src/sources/SvmHyperSyncClient.res +5 -32
  134. package/src/sources/SvmHyperSyncSource.res +159 -134
  135. package/src/sources/SvmHyperSyncSource.res.mjs +164 -129
  136. package/src/sources/TransactionStore.res +49 -0
  137. package/src/sources/TransactionStore.res.mjs +30 -0
  138. package/src/tui/Tui.res +13 -16
  139. package/src/tui/Tui.res.mjs +12 -14
  140. package/svm.schema.json +49 -37
  141. package/src/bindings/Hrtime.res +0 -58
  142. package/src/bindings/Hrtime.res.mjs +0 -90
  143. package/src/bindings/Hrtime.resi +0 -30
@@ -1,10 +1,12 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
+ import * as Config from "./Config.res.mjs";
3
4
  import * as Address from "./Address.res.mjs";
4
5
  import * as ChainMap from "./ChainMap.res.mjs";
5
6
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
6
7
  import * as SimulateSource from "./sources/SimulateSource.res.mjs";
7
8
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
9
+ import * as HandlerRegister from "./HandlerRegister.res.mjs";
8
10
  import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
9
11
  import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
10
12
 
@@ -135,7 +137,37 @@ function findEventConfig(config, contractName, eventName) {
135
137
  return found.contents;
136
138
  }
137
139
 
138
- function parse(simulateItems, config, chainConfig) {
140
+ let dummySrcAddress = "0x0000000000000000000000000000000000000000";
141
+
142
+ function firstContractAddress(chainConfig, contractName) {
143
+ let found = {
144
+ contents: undefined
145
+ };
146
+ chainConfig.contracts.forEach(contract => {
147
+ if (Stdlib_Option.isNone(found.contents) && contract.name === contractName) {
148
+ found.contents = contract.addresses[0];
149
+ return;
150
+ }
151
+ });
152
+ return found.contents;
153
+ }
154
+
155
+ function deriveSrcAddress(providedSrcAddress, eventConfig, chainConfig, config) {
156
+ if (providedSrcAddress !== undefined) {
157
+ return Config.normalizeSimulateAddress(config, Primitive_option.valFromOption(providedSrcAddress));
158
+ }
159
+ if (HandlerRegister.isWildcard(eventConfig.contractName, eventConfig.name)) {
160
+ return dummySrcAddress;
161
+ }
162
+ let addr = firstContractAddress(chainConfig, eventConfig.contractName);
163
+ if (addr !== undefined) {
164
+ return Primitive_option.valFromOption(addr);
165
+ } else {
166
+ return dummySrcAddress;
167
+ }
168
+ }
169
+
170
+ function parse(simulateItems, config, chainConfig, onEventRegistrations) {
139
171
  let chain = ChainMap.Chain.makeUnsafe(chainConfig.id);
140
172
  let chainId = chainConfig.id;
141
173
  let startBlock = chainConfig.startBlock;
@@ -146,7 +178,8 @@ function parse(simulateItems, config, chainConfig) {
146
178
  contents: 0
147
179
  };
148
180
  let items = [];
149
- simulateItems.forEach(rawJson => {
181
+ let seenCoordinates = {};
182
+ simulateItems.forEach((rawJson, itemIndex) => {
150
183
  let match = rawJson.contract;
151
184
  let match$1 = rawJson.event;
152
185
  if (match === undefined) {
@@ -163,32 +196,16 @@ function parse(simulateItems, config, chainConfig) {
163
196
  let li = rawJson.logIndex;
164
197
  let logIndex;
165
198
  if (li !== undefined) {
199
+ if (li >= currentLogIndex.contents) {
200
+ currentLogIndex.contents = li + 1 | 0;
201
+ }
166
202
  logIndex = li;
167
203
  } else {
168
204
  let li$1 = currentLogIndex.contents;
169
205
  currentLogIndex.contents = li$1 + 1 | 0;
170
206
  logIndex = li$1;
171
207
  }
172
- let addr = rawJson.srcAddress;
173
- let srcAddress;
174
- if (addr !== undefined) {
175
- srcAddress = Primitive_option.valFromOption(addr);
176
- } else {
177
- let addr$1 = {
178
- contents: "0x0000000000000000000000000000000000000000"
179
- };
180
- chainConfig.contracts.forEach(contract => {
181
- if (contract.name !== match) {
182
- return;
183
- }
184
- let a = contract.addresses[0];
185
- if (a !== undefined) {
186
- addr$1.contents = Primitive_option.valFromOption(a);
187
- return;
188
- }
189
- });
190
- srcAddress = addr$1.contents;
191
- }
208
+ let srcAddress = deriveSrcAddress(rawJson.srcAddress, eventConfig, chainConfig, config);
192
209
  let blockJson = rawJson.block;
193
210
  let blockJson$1 = (blockJson == null) ? undefined : Primitive_option.some(blockJson);
194
211
  let transactionJson = rawJson.transaction;
@@ -200,18 +217,14 @@ function parse(simulateItems, config, chainConfig) {
200
217
  let block = parseEvmSimulateBlock(currentBlock.contents, blockJson$1);
201
218
  match$3 = [
202
219
  block,
203
- block.number,
204
- block.timestamp,
205
- block.hash
220
+ block.number
206
221
  ];
207
222
  break;
208
223
  case "fuel" :
209
224
  let block$1 = parseFuelSimulateBlock(currentBlock.contents, blockJson$1);
210
225
  match$3 = [
211
226
  block$1,
212
- block$1.height,
213
- block$1.time,
214
- block$1.id
227
+ block$1.height
215
228
  ];
216
229
  break;
217
230
  case "svm" :
@@ -233,14 +246,25 @@ function parse(simulateItems, config, chainConfig) {
233
246
  break;
234
247
  }
235
248
  currentBlock.contents = blockNumber;
249
+ let coordinate = blockNumber.toString() + `:` + logIndex.toString();
250
+ let firstIndex = seenCoordinates[coordinate];
251
+ if (firstIndex !== undefined) {
252
+ 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
+ } else {
254
+ seenCoordinates[coordinate] = itemIndex;
255
+ }
256
+ let onEventRegistration = HandlerRegister.buildOnEventRegistration(config, chainId, eventConfig, undefined);
257
+ let onEventRegistrationIndex = onEventRegistrations.length;
258
+ let newrecord = {...onEventRegistration};
259
+ newrecord.index = onEventRegistrationIndex;
260
+ onEventRegistrations.push(newrecord);
236
261
  items.push({
237
262
  kind: 0,
238
- eventConfig: eventConfig,
239
- timestamp: match$3[2],
263
+ onEventRegistration: newrecord,
240
264
  chain: chain,
241
265
  blockNumber: blockNumber,
242
- blockHash: match$3[3],
243
266
  logIndex: logIndex,
267
+ transactionIndex: 0,
244
268
  payload: {
245
269
  contractName: eventConfig.contractName,
246
270
  eventName: eventConfig.name,
@@ -248,15 +272,15 @@ function parse(simulateItems, config, chainConfig) {
248
272
  chainId: chainId,
249
273
  srcAddress: srcAddress,
250
274
  logIndex: logIndex,
251
- transaction: transaction,
252
- block: match$3[0]
275
+ transaction: Primitive_option.some(transaction),
276
+ block: Primitive_option.some(match$3[0])
253
277
  }
254
278
  });
255
279
  });
256
280
  return items;
257
281
  }
258
282
 
259
- function patchConfig(config, processConfig) {
283
+ function patchConfig(config, processConfig, registrationsByChainId) {
260
284
  let processChains = processConfig.chains;
261
285
  if (processChains == null) {
262
286
  return config;
@@ -271,18 +295,33 @@ function patchConfig(config, processConfig) {
271
295
  if (simulateRaw == null) {
272
296
  return chainConfig;
273
297
  }
274
- let items = parse(simulateRaw, config, chainConfig);
298
+ let registrations = registrationsByChainId[chainIdStr];
299
+ let chainRegistrations;
300
+ if (registrations !== undefined) {
301
+ chainRegistrations = registrations;
302
+ } else {
303
+ let registrations_onEventRegistrations = [];
304
+ let registrations_onBlockRegistrations = [];
305
+ let registrations$1 = {
306
+ onEventRegistrations: registrations_onEventRegistrations,
307
+ onBlockRegistrations: registrations_onBlockRegistrations
308
+ };
309
+ registrationsByChainId[chainIdStr] = registrations$1;
310
+ chainRegistrations = registrations$1;
311
+ }
275
312
  let startBlock = processChainJson.startBlock;
276
313
  let endBlock = processChainJson.endBlock;
277
- let source = SimulateSource.make(items, endBlock, chain);
278
314
  let newrecord = {...chainConfig};
279
- newrecord.sourceConfig = {
315
+ newrecord.endBlock = endBlock;
316
+ newrecord.startBlock = startBlock;
317
+ let items = parse(simulateRaw, config, newrecord, chainRegistrations.onEventRegistrations);
318
+ let source = SimulateSource.make(items, endBlock, chain);
319
+ let newrecord$1 = {...newrecord};
320
+ newrecord$1.sourceConfig = {
280
321
  TAG: "CustomSources",
281
322
  _0: [source]
282
323
  };
283
- newrecord.endBlock = endBlock;
284
- newrecord.startBlock = startBlock;
285
- return newrecord;
324
+ return newrecord$1;
286
325
  });
287
326
  return {
288
327
  name: config.name,
@@ -317,6 +356,9 @@ export {
317
356
  fuelSimulateTransactionSchema,
318
357
  parseFuelSimulateTransaction,
319
358
  findEventConfig,
359
+ dummySrcAddress,
360
+ firstContractAddress,
361
+ deriveSrcAddress,
320
362
  parse,
321
363
  patchConfig,
322
364
  }
@@ -43,6 +43,33 @@ let toIndexingAddress = (dc: InternalTable.EnvioAddresses.t): Internal.indexingA
43
43
  registrationBlock: dc.registrationBlock,
44
44
  }
45
45
 
46
+ // All indexing addresses (config-seeded + dynamically registered) grouped by
47
+ // chain id string, derived from the envio_addresses entities.
48
+ let getIndexingAddressesByChain = (state: testIndexerState): dict<
49
+ array<Internal.indexingAddress>,
50
+ > => {
51
+ let byChain = Dict.make()
52
+ switch state.entities->Dict.get(InternalTable.EnvioAddresses.name) {
53
+ | Some(dcDict) =>
54
+ dcDict
55
+ ->Dict.valuesToArray
56
+ ->Array.forEach(entity => {
57
+ let dc = entity->castToEnvioAddresses
58
+ let chainIdStr = dc.chainId->Int.toString
59
+ let contracts = switch byChain->Dict.get(chainIdStr) {
60
+ | Some(arr) => arr
61
+ | None =>
62
+ let arr = []
63
+ byChain->Dict.set(chainIdStr, arr)
64
+ arr
65
+ }
66
+ contracts->Array.push(dc->toIndexingAddress)->ignore
67
+ })
68
+ | None => ()
69
+ }
70
+ byChain
71
+ }
72
+
46
73
  let handleLoad = (state: testIndexerState, ~tableName: string, ~filter: EntityFilter.t): JSON.t => {
47
74
  // Loads for non-entity tables (e.g. effect caches `envio_effect_<name>`) reach
48
75
  // here too. TestIndexer never persists those, so there's nothing to return —
@@ -566,22 +593,10 @@ let makeCreateTestIndexer = (~config: Config.t, ~workerPath: string): (
566
593
  `Cannot access ${contract.name}.addresses while indexer.process() is running. ` ++ "Wait for process() to complete before reading contract addresses.",
567
594
  )
568
595
  }
569
- let addresses = []
570
- switch state.entities->Dict.get(InternalTable.EnvioAddresses.name) {
571
- | Some(dcDict) =>
572
- dcDict
573
- ->Dict.valuesToArray
574
- ->Array.forEach(
575
- entity => {
576
- let dc = entity->castToEnvioAddresses
577
- if dc.contractName === contract.name && dc.chainId === chainConfig.id {
578
- addresses->Array.push(dc->Config.EnvioAddresses.getAddress)->ignore
579
- }
580
- },
581
- )
582
- | None => ()
583
- }
584
- addresses
596
+ getIndexingAddressesByChain(state)
597
+ ->Dict.get(chainConfig.id->Int.toString)
598
+ ->Option.getOr([])
599
+ ->Array.filterMap(ia => ia.contractName === contract.name ? Some(ia.address) : None)
585
600
  },
586
601
  },
587
602
  )
@@ -652,7 +667,7 @@ let makeCreateTestIndexer = (~config: Config.t, ~workerPath: string): (
652
667
  Int.compare(aId, bId)
653
668
  })
654
669
 
655
- // Parse and validate all chain configs upfront before starting any workers
670
+ // Parse and validate the block ranges upfront before starting any workers.
656
671
  let chainEntries = sortedChainKeys->Array.map(chainIdStr => {
657
672
  let rawChainConfig = rawChains->Dict.getUnsafe(chainIdStr)
658
673
  let chainId = switch chainIdStr->Int.fromString {
@@ -684,26 +699,9 @@ let makeCreateTestIndexer = (~config: Config.t, ~workerPath: string): (
684
699
  let chains: dict<chainConfig> = Dict.make()
685
700
  chains->Dict.set(chainIdStr, processChainConfig)
686
701
 
687
- // Extract dynamic contracts from state.entities for each chain
688
- let indexingAddressesByChain: dict<array<Internal.indexingAddress>> = Dict.make()
689
- switch state.entities->Dict.get(InternalTable.EnvioAddresses.name) {
690
- | Some(dcDict) =>
691
- dcDict
692
- ->Dict.valuesToArray
693
- ->Array.forEach(entity => {
694
- let dc = entity->castToEnvioAddresses
695
- let dcChainIdStr = dc.chainId->Int.toString
696
- let contracts = switch indexingAddressesByChain->Dict.get(dcChainIdStr) {
697
- | Some(arr) => arr
698
- | None =>
699
- let arr = []
700
- indexingAddressesByChain->Dict.set(dcChainIdStr, arr)
701
- arr
702
- }
703
- contracts->Array.push(dc->toIndexingAddress)->ignore
704
- })
705
- | None => ()
706
- }
702
+ // Rebuilt per chain so workers see contracts registered by earlier
703
+ // chains in the same process() call.
704
+ let indexingAddressesByChain = getIndexingAddressesByChain(state)
707
705
 
708
706
  let initialState = makeInitialState(
709
707
  ~config,
@@ -852,7 +850,7 @@ let initTestWorker = () => {
852
850
  // Create proxy storage that communicates with main thread
853
851
  let proxy = TestIndexerProxyStorage.make(~parentPort, ~initialState)
854
852
  let storage = TestIndexerProxyStorage.makeStorage(proxy)
855
- let config = Config.loadWithoutRegistrations()
853
+ let config = Config.load()
856
854
  let persistence = Persistence.make(
857
855
  ~userEntities=config.userEntities,
858
856
  ~allEnums=config.allEnums,
@@ -865,8 +863,8 @@ let initTestWorker = () => {
865
863
  | Some(_) => ()
866
864
  }
867
865
 
868
- let patchConfig = (config, _registrations) => {
869
- let config = SimulateItems.patchConfig(~config, ~processConfig)
866
+ let patchConfig = (config: Config.t, registrationsByChainId) => {
867
+ let config = SimulateItems.patchConfig(~config, ~processConfig, ~registrationsByChainId)
870
868
 
871
869
  // In auto-exit mode, set batchSize=1 to process one block checkpoint at a time
872
870
  if exitAfterFirstEventBlock {
@@ -875,7 +873,23 @@ let initTestWorker = () => {
875
873
  config
876
874
  }
877
875
  }
878
- Main.start(~persistence, ~isTest=true, ~patchConfig, ~exitAfterFirstEventBlock)->ignore
876
+ Main.start(~persistence, ~isTest=true, ~patchConfig, ~exitAfterFirstEventBlock)
877
+ ->Promise.catch(exn => {
878
+ // `Main.start` rejects on any fatal error: a runtime failure arrives wrapped
879
+ // in `Main.FatalError` (already logged), a setup throw (e.g. an invalid
880
+ // simulate item) arrives raw. The parent only learns of failures
881
+ // through the worker `error` event, which fires on an *uncaught* exception.
882
+ // Throwing synchronously in this catch would just reject the catch's own
883
+ // promise (swallowed by `ignore`); `setImmediate` re-throws outside the
884
+ // promise chain so it becomes uncaught and reaches the parent.
885
+ let toThrow = switch exn {
886
+ | Main.FatalError(inner) => inner
887
+ | _ => exn->Utils.prettifyExn
888
+ }
889
+ NodeJs.setImmediate(() => throw(toThrow))
890
+ Promise.resolve()
891
+ })
892
+ ->ignore
879
893
  | None =>
880
894
  Logging.error("TestIndexerWorker: No worker data provided")
881
895
  NodeJs.process->NodeJs.exitWithCode(Failure)
@@ -12,6 +12,7 @@ import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
12
12
  import * as Persistence from "./Persistence.res.mjs";
13
13
  import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
14
14
  import * as EntityFilter from "./db/EntityFilter.res.mjs";
15
+ import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
15
16
  import * as InternalTable from "./db/InternalTable.res.mjs";
16
17
  import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
17
18
  import * as SimulateItems from "./SimulateItems.res.mjs";
@@ -32,6 +33,27 @@ function toIndexingAddress(dc) {
32
33
  };
33
34
  }
34
35
 
36
+ function getIndexingAddressesByChain(state) {
37
+ let byChain = {};
38
+ let dcDict = state.entities[Config.EnvioAddresses.name];
39
+ if (dcDict !== undefined) {
40
+ Object.values(dcDict).forEach(entity => {
41
+ let chainIdStr = entity.chain_id.toString();
42
+ let arr = byChain[chainIdStr];
43
+ let contracts;
44
+ if (arr !== undefined) {
45
+ contracts = arr;
46
+ } else {
47
+ let arr$1 = [];
48
+ byChain[chainIdStr] = arr$1;
49
+ contracts = arr$1;
50
+ }
51
+ contracts.push(toIndexingAddress(entity));
52
+ });
53
+ }
54
+ return byChain;
55
+ }
56
+
35
57
  function handleLoad(state, tableName, filter) {
36
58
  let entityConfig = state.entityConfigs[tableName];
37
59
  if (entityConfig === undefined) {
@@ -403,17 +425,11 @@ function makeCreateTestIndexer(config, workerPath) {
403
425
  if (state.processInProgress) {
404
426
  Stdlib_JsError.throwWithMessage(`Cannot access ` + contract.name + `.addresses while indexer.process() is running. ` + "Wait for process() to complete before reading contract addresses.");
405
427
  }
406
- let addresses = [];
407
- let dcDict = state.entities[Config.EnvioAddresses.name];
408
- if (dcDict !== undefined) {
409
- Object.values(dcDict).forEach(entity => {
410
- if (entity.contract_name === contract.name && entity.chain_id === chainConfig.id) {
411
- addresses.push(Config.EnvioAddresses.getAddress(entity));
412
- return;
413
- }
414
- });
415
- }
416
- return addresses;
428
+ return Stdlib_Array.filterMap(Stdlib_Option.getOr(getIndexingAddressesByChain(state)[chainConfig.id.toString()], []), ia => {
429
+ if (ia.contractName === contract.name) {
430
+ return Primitive_option.some(ia.address);
431
+ }
432
+ });
417
433
  }
418
434
  });
419
435
  Object.defineProperty(chainObj, contract.name, {
@@ -484,23 +500,7 @@ function makeCreateTestIndexer(config, workerPath) {
484
500
  let chainId = param[1];
485
501
  let chains = {};
486
502
  chains[param[0]] = processChainConfig;
487
- let indexingAddressesByChain = {};
488
- let dcDict = state.entities[Config.EnvioAddresses.name];
489
- if (dcDict !== undefined) {
490
- Object.values(dcDict).forEach(entity => {
491
- let dcChainIdStr = entity.chain_id.toString();
492
- let arr = indexingAddressesByChain[dcChainIdStr];
493
- let contracts;
494
- if (arr !== undefined) {
495
- contracts = arr;
496
- } else {
497
- let arr$1 = [];
498
- indexingAddressesByChain[dcChainIdStr] = arr$1;
499
- contracts = arr$1;
500
- }
501
- contracts.push(toIndexingAddress(entity));
502
- });
503
- }
503
+ let indexingAddressesByChain = getIndexingAddressesByChain(state);
504
504
  let initialState = makeInitialState(config, chains, indexingAddressesByChain);
505
505
  return new Promise((resolve, reject) => {
506
506
  let workerData_startBlock = processChainConfig.startBlock;
@@ -605,15 +605,15 @@ function initTestWorker() {
605
605
  };
606
606
  let proxy = TestIndexerProxyStorage.make(parentPort, workerData.initialState);
607
607
  let storage = TestIndexerProxyStorage.makeStorage(proxy);
608
- let config = Config.loadWithoutRegistrations();
608
+ let config = Config.load();
609
609
  let persistence = Persistence.make(config.userEntities, config.allEnums, storage);
610
610
  if (Env.userLogLevel !== undefined) {
611
611
 
612
612
  } else {
613
613
  Logging.setLogLevel("silent");
614
614
  }
615
- let patchConfig = (config, _registrations) => {
616
- let config$1 = SimulateItems.patchConfig(config, processConfig);
615
+ let patchConfig = (config, registrationsByChainId) => {
616
+ let config$1 = SimulateItems.patchConfig(config, processConfig, registrationsByChainId);
617
617
  if (exitAfterFirstEventBlock) {
618
618
  return {
619
619
  name: config$1.name,
@@ -640,11 +640,18 @@ function initTestWorker() {
640
640
  return config$1;
641
641
  }
642
642
  };
643
- Main.start(persistence, undefined, true, exitAfterFirstEventBlock, patchConfig);
643
+ Stdlib_Promise.$$catch(Main.start(persistence, undefined, true, exitAfterFirstEventBlock, patchConfig), exn => {
644
+ let toThrow = exn.RE_EXN_ID === Main.FatalError ? exn._1 : Utils.prettifyExn(exn);
645
+ setImmediate(() => {
646
+ throw toThrow;
647
+ });
648
+ return Promise.resolve();
649
+ });
644
650
  }
645
651
 
646
652
  export {
647
653
  toIndexingAddress,
654
+ getIndexingAddressesByChain,
648
655
  handleLoad,
649
656
  handleWriteBatch,
650
657
  makeInitialState,
@@ -1,27 +1,3 @@
1
- let toTwosComplement = (num: bigint, ~bytesLen: int) => {
2
- let maxValue = 1n->BigInt.shiftLeft(BigInt.fromInt(bytesLen * 8))
3
- let mask = maxValue->BigInt.sub(1n)
4
- num->BigInt.add(maxValue)->BigInt.bitwiseAnd(mask)
5
- }
6
-
7
- let fromSignedBigInt = val => {
8
- let bytesLen = 32
9
- let val = val >= 0n ? val : val->toTwosComplement(~bytesLen)
10
- val->Viem.bigintToHex(~options={size: bytesLen})
11
- }
12
-
13
1
  type hex = EvmTypes.Hex.t
14
- //bytes currently does not work with genType and we also currently generate bytes as a string type
15
- type bytesHex = string
16
- let keccak256 = Viem.keccak256
17
- let bytesToHex = Viem.bytesToHex
18
- let concat = Viem.concat
19
- let castToHexUnsafe: 'a => hex = val => val->(Utils.magic: 'a => hex)
20
- let fromBigInt: bigint => hex = val => val->Viem.bigintToHex(~options={size: 32})
21
- let fromDynamicString: string => hex = val => val->(Utils.magic: string => hex)->keccak256
22
- let fromString: string => hex = val => val->Viem.stringToHex(~options={size: 32})
2
+
23
3
  let fromAddress: Address.t => hex = addr => addr->(Utils.magic: Address.t => hex)->Viem.pad
24
- let fromDynamicBytes: bytesHex => hex = bytes => bytes->(Utils.magic: bytesHex => hex)->keccak256
25
- let fromBytes: bytesHex => hex = bytes =>
26
- bytes->(Utils.magic: bytesHex => Uint8Array.t)->Viem.bytesToHex(~options={size: 32})
27
- let fromBool: bool => hex = b => b->Viem.boolToHex(~options={size: 32})
@@ -1,86 +1,12 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
3
  import * as Viem from "viem";
4
- import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
5
-
6
- function toTwosComplement(num, bytesLen) {
7
- let maxValue = (1n << BigInt((bytesLen << 3)));
8
- let mask = maxValue - 1n;
9
- return num + maxValue & mask;
10
- }
11
-
12
- function fromSignedBigInt(val) {
13
- let val$1 = val >= 0n ? val : toTwosComplement(val, 32);
14
- return Viem.numberToHex(val$1, {
15
- size: 32
16
- });
17
- }
18
-
19
- function keccak256(prim) {
20
- return Viem.keccak256(prim);
21
- }
22
-
23
- function bytesToHex(prim0, prim1) {
24
- return Viem.bytesToHex(prim0, prim1 !== undefined ? Primitive_option.valFromOption(prim1) : undefined);
25
- }
26
-
27
- function concat(prim) {
28
- return Viem.concat(prim);
29
- }
30
-
31
- function castToHexUnsafe(val) {
32
- return val;
33
- }
34
-
35
- function fromBigInt(val) {
36
- return Viem.numberToHex(val, {
37
- size: 32
38
- });
39
- }
40
-
41
- function fromDynamicString(val) {
42
- return Viem.keccak256(val);
43
- }
44
-
45
- function fromString(val) {
46
- return Viem.stringToHex(val, {
47
- size: 32
48
- });
49
- }
50
4
 
51
5
  function fromAddress(addr) {
52
6
  return Viem.pad(addr);
53
7
  }
54
8
 
55
- function fromDynamicBytes(bytes) {
56
- return Viem.keccak256(bytes);
57
- }
58
-
59
- function fromBytes(bytes) {
60
- return Viem.bytesToHex(bytes, {
61
- size: 32
62
- });
63
- }
64
-
65
- function fromBool(b) {
66
- return Viem.boolToHex(b, {
67
- size: 32
68
- });
69
- }
70
-
71
9
  export {
72
- toTwosComplement,
73
- fromSignedBigInt,
74
- keccak256,
75
- bytesToHex,
76
- concat,
77
- castToHexUnsafe,
78
- fromBigInt,
79
- fromDynamicString,
80
- fromString,
81
10
  fromAddress,
82
- fromDynamicBytes,
83
- fromBytes,
84
- fromBool,
85
11
  }
86
12
  /* viem Not a pure module */
@@ -0,0 +1,7 @@
1
+ type timeRef = float
2
+
3
+ @val @scope("performance") external now: unit => timeRef = "now"
4
+
5
+ let secondsSince = (from: timeRef): float => (now() -. from) /. 1000.
6
+
7
+ let secondsBetween = (~from: timeRef, ~to: timeRef): float => (to -. from) /. 1000.
@@ -0,0 +1,21 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+
4
+ function secondsSince(from) {
5
+ return (performance.now() - from) / 1000;
6
+ }
7
+
8
+ function secondsBetween(from, to) {
9
+ return (to - from) / 1000;
10
+ }
11
+
12
+ function now(prim) {
13
+ return performance.now();
14
+ }
15
+
16
+ export {
17
+ now,
18
+ secondsSince,
19
+ secondsBetween,
20
+ }
21
+ /* No side effect */
@@ -0,0 +1,7 @@
1
+ type timeRef = float
2
+
3
+ let now: unit => timeRef
4
+
5
+ let secondsSince: timeRef => float
6
+
7
+ let secondsBetween: (~from: timeRef, ~to: timeRef) => float
@@ -1,52 +1,6 @@
1
- type eventLog = {
2
- abi: EvmTypes.Abi.t,
3
- data: string,
4
- topics: array<EvmTypes.Hex.t>,
5
- }
6
-
7
- type decodedEvent<'a> = {
8
- eventName: string,
9
- args: 'a,
10
- }
11
-
12
- @module("viem") external decodeEventLogOrThrow: eventLog => decodedEvent<'a> = "decodeEventLog"
13
-
14
1
  type hex = EvmTypes.Hex.t
15
2
  @module("viem") external toHex: 'a => hex = "toHex"
16
- @module("viem") external keccak256: hex => hex = "keccak256"
17
- @module("viem") external keccak256Bytes: Uint8Array.t => hex = "keccak256"
18
3
  @module("viem") external pad: hex => hex = "pad"
19
- @module("viem")
20
- external encodePacked: (~types: array<string>, ~values: array<'a>) => hex = "encodePacked"
21
4
 
22
5
  type sizeOptions = {size: int}
23
- @module("viem") external intToHex: (int, ~options: sizeOptions=?) => hex = "numberToHex"
24
6
  @module("viem") external bigintToHex: (bigint, ~options: sizeOptions=?) => hex = "numberToHex"
25
- @module("viem") external stringToHex: (string, ~options: sizeOptions=?) => hex = "stringToHex"
26
- @module("viem") external boolToHex: (bool, ~options: sizeOptions=?) => hex = "boolToHex"
27
- @module("viem") external bytesToHex: (Uint8Array.t, ~options: sizeOptions=?) => hex = "bytesToHex"
28
- @module("viem") external concat: array<hex> => hex = "concat"
29
-
30
- exception ParseError(exn)
31
- exception UnknownContractName({contractName: string})
32
-
33
- let parseLogOrThrow = (
34
- contractNameAbiMapping: dict<EvmTypes.Abi.t>,
35
- ~contractName,
36
- ~topics,
37
- ~data,
38
- ) => {
39
- switch contractNameAbiMapping->Utils.Dict.dangerouslyGetNonOption(contractName) {
40
- | None => throw(UnknownContractName({contractName: contractName}))
41
- | Some(abi) =>
42
- let viemLog: eventLog = {
43
- abi,
44
- data,
45
- topics,
46
- }
47
-
48
- try viemLog->decodeEventLogOrThrow catch {
49
- | exn => throw(ParseError(exn))
50
- }
51
- }
52
- }