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
@@ -13,7 +13,7 @@ type selectionConfig = {
13
13
  getRecieptsSelection: (
14
14
  ~addressesByContractName: dict<array<Address.t>>,
15
15
  ) => array<HyperFuelClient.QueryTypes.receiptSelection>,
16
- eventRouter: EventRouter.t<Internal.fuelEventConfig>,
16
+ eventRouter: EventRouter.t<Internal.fuelOnEventRegistration>,
17
17
  }
18
18
 
19
19
  let logDataReceiptTypeSelection: array<FuelSDK.receiptType> = [LogData]
@@ -127,39 +127,40 @@ let getSelectionConfig = (selection: FetchState.selection, ~chain) => {
127
127
 
128
128
  let contractNames = Utils.Set.make()
129
129
 
130
- selection.eventConfigs
131
- ->(Utils.magic: array<Internal.eventConfig> => array<Internal.fuelEventConfig>)
132
- ->Array.forEach(eventConfig => {
130
+ selection.onEventRegistrations->Array.forEach(reg => {
131
+ let eventConfig =
132
+ reg.eventConfig->(Utils.magic: Internal.eventConfig => Internal.fuelEventConfig)
133
133
  let contractName = eventConfig.contractName
134
- if !eventConfig.isWildcard {
134
+ let isWildcard = reg.isWildcard
135
+ if !isWildcard {
135
136
  let _ = contractNames->Utils.Set.add(contractName)
136
137
  }
137
138
  eventRouter->EventRouter.addOrThrow(
138
139
  eventConfig.id,
139
- eventConfig,
140
+ reg,
140
141
  ~contractName,
141
142
  ~eventName=eventConfig.name,
142
143
  ~chain,
143
- ~isWildcard=eventConfig.isWildcard,
144
+ ~isWildcard,
144
145
  )
145
146
 
146
- switch eventConfig {
147
- | {kind: Mint, isWildcard: true} => addNonLogDataWildcardReceiptTypes(Mint)
148
- | {kind: Mint} => addNonLogDataReceiptType(contractName, Mint)
149
- | {kind: Burn, isWildcard: true} => addNonLogDataWildcardReceiptTypes(Burn)
150
- | {kind: Burn} => addNonLogDataReceiptType(contractName, Burn)
151
- | {kind: Transfer, isWildcard: true} => {
147
+ switch (eventConfig.kind, isWildcard) {
148
+ | (Mint, true) => addNonLogDataWildcardReceiptTypes(Mint)
149
+ | (Mint, false) => addNonLogDataReceiptType(contractName, Mint)
150
+ | (Burn, true) => addNonLogDataWildcardReceiptTypes(Burn)
151
+ | (Burn, false) => addNonLogDataReceiptType(contractName, Burn)
152
+ | (Transfer, true) => {
152
153
  addNonLogDataWildcardReceiptTypes(Transfer)
153
154
  addNonLogDataWildcardReceiptTypes(TransferOut)
154
155
  }
155
- | {kind: Transfer} => {
156
+ | (Transfer, false) => {
156
157
  addNonLogDataReceiptType(contractName, Transfer)
157
158
  addNonLogDataReceiptType(contractName, TransferOut)
158
159
  }
159
- | {kind: Call, isWildcard: true} => addNonLogDataWildcardReceiptTypes(Call)
160
- | {kind: Call} =>
160
+ | (Call, true) => addNonLogDataWildcardReceiptTypes(Call)
161
+ | (Call, false) =>
161
162
  JsError.throwWithMessage("Call receipt indexing currently supported only in wildcard mode")
162
- | {kind: LogData({logId}), isWildcard} => {
163
+ | (LogData({logId}), _) => {
163
164
  let rb = logId->BigInt.fromStringOrThrow
164
165
  if isWildcard {
165
166
  wildcardLogDataRbs->Array.push(rb)->ignore
@@ -235,26 +236,22 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
235
236
  ~fromBlock,
236
237
  ~toBlock,
237
238
  ~addressesByContractName,
238
- ~indexingAddresses,
239
+ ~contractNameByAddress,
239
240
  ~knownHeight,
240
241
  ~partitionId as _,
241
242
  ~selection: FetchState.selection,
243
+ ~itemsTarget as _,
242
244
  ~retry,
243
245
  ~logger,
244
246
  ) => {
245
- let totalTimeRef = Hrtime.makeTimer()
247
+ let totalTimeRef = Performance.now()
246
248
 
247
249
  let selectionConfig = getSelectionConfig(selection)
248
250
  let recieptsSelection = selectionConfig.getRecieptsSelection(~addressesByContractName)
249
251
 
250
- let startFetchingBatchTimeRef = Hrtime.makeTimer()
252
+ let startFetchingBatchTimeRef = Performance.now()
251
253
 
252
254
  //fetch batch
253
- Prometheus.SourceRequestCount.increment(
254
- ~sourceName=name,
255
- ~chainId=chain->ChainMap.Chain.toChainId,
256
- ~method="getLogs",
257
- )
258
255
  let pageUnsafe = try await HyperFuel.GetLogs.query(
259
256
  ~client,
260
257
  ~fromBlock,
@@ -305,7 +302,8 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
305
302
  )
306
303
  }
307
304
 
308
- let pageFetchTime = startFetchingBatchTimeRef->Hrtime.timeSince->Hrtime.toSecondsFloat
305
+ let pageFetchTime = startFetchingBatchTimeRef->Performance.secondsSince
306
+ let requestStats = [{Source.method: "getLogs", seconds: pageFetchTime}]
309
307
 
310
308
  //set height and next from block
311
309
  let knownHeight = pageUnsafe.archiveHeight
@@ -315,7 +313,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
315
313
  //In the query
316
314
  let heighestBlockQueried = pageUnsafe.nextBlock - 1
317
315
 
318
- let parsingTimeRef = Hrtime.makeTimer()
316
+ let parsingTimeRef = Performance.now()
319
317
 
320
318
  let parsedQueueItems = pageUnsafe.items->Array.map(item => {
321
319
  let {contractId: contractAddress, receipt, block, receiptIndex} = item
@@ -330,11 +328,10 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
330
328
  | Call(_) => callEventTag
331
329
  }
332
330
 
333
- let eventConfig = switch selectionConfig.eventRouter->EventRouter.get(
331
+ let onEventRegistration = switch selectionConfig.eventRouter->EventRouter.get(
334
332
  ~tag=eventId,
335
- ~indexingAddresses,
333
+ ~contractNameByAddress,
336
334
  ~contractAddress,
337
- ~blockNumber=block.height,
338
335
  ) {
339
336
  | None => {
340
337
  let logger = Logging.createChildFrom(
@@ -352,9 +349,14 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
352
349
  ~logger,
353
350
  )
354
351
  }
355
- | Some(eventConfig) => eventConfig
352
+ | Some(onEventRegistration) => onEventRegistration
356
353
  }
357
354
 
355
+ let eventConfig =
356
+ onEventRegistration.eventConfig->(
357
+ Utils.magic: Internal.eventConfig => Internal.fuelEventConfig
358
+ )
359
+
358
360
  let params = switch (eventConfig, receipt) {
359
361
  | ({kind: LogData({decode})}, LogData({data})) =>
360
362
  try decode(data) catch {
@@ -408,12 +410,13 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
408
410
  }
409
411
 
410
412
  Internal.Event({
411
- eventConfig: (eventConfig :> Internal.eventConfig),
412
- timestamp: block.time,
413
+ onEventRegistration: (onEventRegistration :> Internal.onEventRegistration),
413
414
  chain,
414
415
  blockNumber: block.height,
415
- blockHash: block.id,
416
416
  logIndex: receiptIndex,
417
+ // Fuel carries the transaction inline on the payload; the store key is
418
+ // unused (Fuel identifies transactions by hash, kept on the payload).
419
+ transactionIndex: 0,
417
420
  payload: {
418
421
  contractName: eventConfig.contractName,
419
422
  eventName: eventConfig.name,
@@ -429,7 +432,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
429
432
  })
430
433
  })
431
434
 
432
- let parsingTimeElapsed = parsingTimeRef->Hrtime.timeSince->Hrtime.toSecondsFloat
435
+ let parsingTimeElapsed = parsingTimeRef->Performance.secondsSince
433
436
 
434
437
  // Fuel never rolls back on reorg, so block hashes here are purely informational
435
438
  // for detect-only logging via ReorgDetection.
@@ -445,7 +448,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
445
448
  | _ => 0
446
449
  }
447
450
 
448
- let totalTimeElapsed = totalTimeRef->Hrtime.timeSince->Hrtime.toSecondsFloat
451
+ let totalTimeElapsed = totalTimeRef->Performance.secondsSince
449
452
 
450
453
  let stats = {
451
454
  totalTimeElapsed,
@@ -456,11 +459,15 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
456
459
  {
457
460
  latestFetchedBlockTimestamp,
458
461
  parsedQueueItems,
462
+ // Fuel keeps transaction and block on the payload; no store pages.
463
+ transactionStore: None,
464
+ blockStore: None,
459
465
  latestFetchedBlockNumber: heighestBlockQueried,
460
466
  stats,
461
467
  knownHeight,
462
468
  blockHashes,
463
469
  fromBlockQueried: fromBlock,
470
+ requestStats,
464
471
  }
465
472
  }
466
473
 
@@ -475,7 +482,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
475
482
  pollingInterval: 100,
476
483
  poweredByHyperSync: true,
477
484
  getHeightOrThrow: async () => {
478
- let timerRef = Hrtime.makeTimer()
485
+ let timerRef = Performance.now()
479
486
  let height = try await client->HyperFuelClient.getHeight catch {
480
487
  | JsExn(e) =>
481
488
  switch e->JsExn.message {
@@ -487,19 +494,8 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
487
494
  | _ => throw(JsExn(e))
488
495
  }
489
496
  }
490
- let seconds = timerRef->Hrtime.timeSince->Hrtime.toSecondsFloat
491
- Prometheus.SourceRequestCount.increment(
492
- ~sourceName=name,
493
- ~chainId=chain->ChainMap.Chain.toChainId,
494
- ~method="getHeight",
495
- )
496
- Prometheus.SourceRequestCount.addSeconds(
497
- ~sourceName=name,
498
- ~chainId=chain->ChainMap.Chain.toChainId,
499
- ~method="getHeight",
500
- ~seconds,
501
- )
502
- height
497
+ let seconds = timerRef->Performance.secondsSince
498
+ {height, requestStats: [{method: "getHeight", seconds}]}
503
499
  },
504
500
  getItemsOrThrow,
505
501
  }
@@ -1,11 +1,10 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
- import * as Hrtime from "../bindings/Hrtime.res.mjs";
4
3
  import * as Source from "./Source.res.mjs";
5
4
  import * as Logging from "../Logging.res.mjs";
6
5
  import * as HyperFuel from "./HyperFuel.res.mjs";
7
- import * as Prometheus from "../Prometheus.res.mjs";
8
6
  import * as EventRouter from "./EventRouter.res.mjs";
7
+ import * as Performance from "../bindings/Performance.res.mjs";
9
8
  import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
10
9
  import * as ErrorHandling from "../ErrorHandling.res.mjs";
11
10
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
@@ -101,41 +100,43 @@ function getSelectionConfig(selection, chain) {
101
100
  }
102
101
  };
103
102
  let contractNames = new Set();
104
- selection.eventConfigs.forEach(eventConfig => {
103
+ selection.onEventRegistrations.forEach(reg => {
104
+ let eventConfig = reg.eventConfig;
105
105
  let contractName = eventConfig.contractName;
106
- if (!eventConfig.isWildcard) {
106
+ let isWildcard = reg.isWildcard;
107
+ if (!isWildcard) {
107
108
  contractNames.add(contractName);
108
109
  }
109
- EventRouter.addOrThrow(eventRouter, eventConfig.id, eventConfig, contractName, eventConfig.isWildcard, eventConfig.name, chain);
110
- let isWildcard = eventConfig.isWildcard;
111
- if (isWildcard) {
112
- let tmp = eventConfig.kind;
113
- if (typeof tmp !== "object") {
114
- switch (tmp) {
115
- case "Mint" :
116
- return addNonLogDataWildcardReceiptTypes(11);
117
- case "Burn" :
118
- return addNonLogDataWildcardReceiptTypes(12);
119
- case "Transfer" :
120
- addNonLogDataWildcardReceiptTypes(7);
121
- return addNonLogDataWildcardReceiptTypes(8);
122
- case "Call" :
123
- return addNonLogDataWildcardReceiptTypes(0);
124
- }
125
- }
126
- }
110
+ EventRouter.addOrThrow(eventRouter, eventConfig.id, reg, contractName, isWildcard, eventConfig.name, chain);
127
111
  let match = eventConfig.kind;
128
112
  if (typeof match !== "object") {
129
113
  switch (match) {
130
114
  case "Mint" :
131
- return addNonLogDataReceiptType(contractName, 11);
115
+ if (isWildcard) {
116
+ return addNonLogDataWildcardReceiptTypes(11);
117
+ } else {
118
+ return addNonLogDataReceiptType(contractName, 11);
119
+ }
132
120
  case "Burn" :
133
- return addNonLogDataReceiptType(contractName, 12);
121
+ if (isWildcard) {
122
+ return addNonLogDataWildcardReceiptTypes(12);
123
+ } else {
124
+ return addNonLogDataReceiptType(contractName, 12);
125
+ }
134
126
  case "Transfer" :
135
- addNonLogDataReceiptType(contractName, 7);
136
- return addNonLogDataReceiptType(contractName, 8);
127
+ if (isWildcard) {
128
+ addNonLogDataWildcardReceiptTypes(7);
129
+ return addNonLogDataWildcardReceiptTypes(8);
130
+ } else {
131
+ addNonLogDataReceiptType(contractName, 7);
132
+ return addNonLogDataReceiptType(contractName, 8);
133
+ }
137
134
  case "Call" :
138
- return Stdlib_JsError.throwWithMessage("Call receipt indexing currently supported only in wildcard mode");
135
+ if (isWildcard) {
136
+ return addNonLogDataWildcardReceiptTypes(0);
137
+ } else {
138
+ return Stdlib_JsError.throwWithMessage("Call receipt indexing currently supported only in wildcard mode");
139
+ }
139
140
  }
140
141
  } else {
141
142
  let rb = BigInt(match.logId);
@@ -181,7 +182,6 @@ function memoGetSelectionConfig(chain) {
181
182
  function make(param) {
182
183
  let apiToken = param.apiToken;
183
184
  let chain = param.chain;
184
- let name = "HyperFuel";
185
185
  let apiToken$1 = apiToken !== undefined ? apiToken : Stdlib_JsError.throwWithMessage(`An Envio API token is required for using HyperFuel as a data-source.
186
186
  Set the ENVIO_API_TOKEN environment variable in your .env file.
187
187
  Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
@@ -196,12 +196,11 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
196
196
  client = ErrorHandling.mkLogAndRaise(undefined, "Failed to instantiate the HyperFuel client", exn);
197
197
  }
198
198
  let getSelectionConfig = memoGetSelectionConfig(chain);
199
- let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName, indexingAddresses, knownHeight, param, selection, retry, logger) => {
200
- let totalTimeRef = Hrtime.makeTimer();
199
+ let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName, contractNameByAddress, knownHeight, param, selection, param$1, retry, logger) => {
200
+ let totalTimeRef = Performance.now();
201
201
  let selectionConfig = getSelectionConfig(selection);
202
202
  let recieptsSelection = selectionConfig.getRecieptsSelection(addressesByContractName);
203
- let startFetchingBatchTimeRef = Hrtime.makeTimer();
204
- Prometheus.SourceRequestCount.increment(name, chain, "getLogs");
203
+ let startFetchingBatchTimeRef = Performance.now();
205
204
  let pageUnsafe;
206
205
  try {
207
206
  pageUnsafe = await HyperFuel.GetLogs.query(client, fromBlock, toBlock, recieptsSelection);
@@ -249,10 +248,14 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
249
248
  Error: new Error()
250
249
  };
251
250
  }
252
- let pageFetchTime = Hrtime.toSecondsFloat(Hrtime.timeSince(startFetchingBatchTimeRef));
251
+ let pageFetchTime = Performance.secondsSince(startFetchingBatchTimeRef);
252
+ let requestStats = [{
253
+ method: "getLogs",
254
+ seconds: pageFetchTime
255
+ }];
253
256
  let knownHeight$1 = pageUnsafe.archiveHeight;
254
257
  let heighestBlockQueried = pageUnsafe.nextBlock - 1 | 0;
255
- let parsingTimeRef = Hrtime.makeTimer();
258
+ let parsingTimeRef = Performance.now();
256
259
  let parsedQueueItems = pageUnsafe.items.map(item => {
257
260
  let block = item.block;
258
261
  let receiptIndex = item.receiptIndex;
@@ -277,10 +280,10 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
277
280
  eventId = burnEventTag;
278
281
  break;
279
282
  }
280
- let eventConfig = EventRouter.get(selectionConfig.eventRouter, eventId, contractAddress, block.height, indexingAddresses);
281
- let eventConfig$1;
282
- if (eventConfig !== undefined) {
283
- eventConfig$1 = eventConfig;
283
+ let onEventRegistration = EventRouter.get(selectionConfig.eventRouter, eventId, contractAddress, contractNameByAddress);
284
+ let onEventRegistration$1;
285
+ if (onEventRegistration !== undefined) {
286
+ onEventRegistration$1 = onEventRegistration;
284
287
  } else {
285
288
  let logger$1 = Logging.createChildFrom(logger, {
286
289
  chainId: chain,
@@ -289,11 +292,12 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
289
292
  contractAddress: contractAddress,
290
293
  eventId: eventId
291
294
  });
292
- eventConfig$1 = ErrorHandling.mkLogAndRaise(logger$1, "Failed to route registered event", {
295
+ onEventRegistration$1 = ErrorHandling.mkLogAndRaise(logger$1, "Failed to route registered event", {
293
296
  RE_EXN_ID: EventRoutingFailed
294
297
  });
295
298
  }
296
- let match = eventConfig$1.kind;
299
+ let eventConfig = onEventRegistration$1.eventConfig;
300
+ let match = eventConfig.kind;
297
301
  let params;
298
302
  let exit = 0;
299
303
  if (typeof match !== "object" || receipt.receiptType !== 6) {
@@ -349,15 +353,14 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
349
353
  }
350
354
  return {
351
355
  kind: 0,
352
- eventConfig: eventConfig$1,
353
- timestamp: block.time,
356
+ onEventRegistration: onEventRegistration$1,
354
357
  chain: chain,
355
358
  blockNumber: block.height,
356
- blockHash: block.id,
357
359
  logIndex: receiptIndex,
360
+ transactionIndex: 0,
358
361
  payload: {
359
- contractName: eventConfig$1.contractName,
360
- eventName: eventConfig$1.name,
362
+ contractName: eventConfig.contractName,
363
+ eventName: eventConfig.name,
361
364
  params: params,
362
365
  chainId: chain,
363
366
  srcAddress: contractAddress,
@@ -369,7 +372,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
369
372
  }
370
373
  };
371
374
  });
372
- let parsingTimeElapsed = Hrtime.toSecondsFloat(Hrtime.timeSince(parsingTimeRef));
375
+ let parsingTimeElapsed = Performance.secondsSince(parsingTimeRef);
373
376
  let blockHashes = pageUnsafe.items.map(param => {
374
377
  let block = param.block;
375
378
  return {
@@ -385,7 +388,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
385
388
  } else {
386
389
  latestFetchedBlockTimestamp = 0;
387
390
  }
388
- let totalTimeElapsed = Hrtime.toSecondsFloat(Hrtime.timeSince(totalTimeRef));
391
+ let totalTimeElapsed = Performance.secondsSince(totalTimeRef);
389
392
  let stats_parsing$unknowntime$unknown$lpars$rpar = parsingTimeElapsed;
390
393
  let stats_page$unknownfetch$unknowntime$unknown$lpars$rpar = pageFetchTime;
391
394
  let stats = {
@@ -397,22 +400,25 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
397
400
  knownHeight: knownHeight$1,
398
401
  blockHashes: blockHashes,
399
402
  parsedQueueItems: parsedQueueItems,
403
+ transactionStore: undefined,
404
+ blockStore: undefined,
400
405
  fromBlockQueried: fromBlock,
401
406
  latestFetchedBlockNumber: heighestBlockQueried,
402
407
  latestFetchedBlockTimestamp: latestFetchedBlockTimestamp,
403
- stats: stats
408
+ stats: stats,
409
+ requestStats: requestStats
404
410
  };
405
411
  };
406
412
  let getBlockHashes = (param, param$1) => Stdlib_JsError.throwWithMessage("HyperFuel does not support getting block hashes");
407
413
  return {
408
- name: name,
414
+ name: "HyperFuel",
409
415
  sourceFor: "Sync",
410
416
  chain: chain,
411
417
  poweredByHyperSync: true,
412
418
  pollingInterval: 100,
413
419
  getBlockHashes: getBlockHashes,
414
420
  getHeightOrThrow: async () => {
415
- let timerRef = Hrtime.makeTimer();
421
+ let timerRef = Performance.now();
416
422
  let height;
417
423
  try {
418
424
  height = await client.getHeight();
@@ -444,10 +450,14 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
444
450
  throw e;
445
451
  }
446
452
  }
447
- let seconds = Hrtime.toSecondsFloat(Hrtime.timeSince(timerRef));
448
- Prometheus.SourceRequestCount.increment(name, chain, "getHeight");
449
- Prometheus.SourceRequestCount.addSeconds(name, chain, "getHeight", seconds);
450
- return height;
453
+ let seconds = Performance.secondsSince(timerRef);
454
+ return {
455
+ height: height,
456
+ requestStats: [{
457
+ method: "getHeight",
458
+ seconds: seconds
459
+ }]
460
+ };
451
461
  },
452
462
  getItemsOrThrow: getItemsOrThrow
453
463
  };
@@ -16,9 +16,15 @@ let reraisIfRateLimited = exn =>
16
16
 
17
17
  type logsQueryPage = {
18
18
  items: array<HyperSyncClient.EventItems.item>,
19
+ // Block headers referenced by `items`, deduplicated by block number.
20
+ blocks: array<HyperSyncClient.EventItems.blockHeader>,
19
21
  nextBlock: int,
20
22
  archiveHeight: int,
21
23
  rollbackGuard: option<HyperSyncClient.ResponseTypes.rollbackGuard>,
24
+ // Page store owning this page's raw transactions.
25
+ transactionStore: TransactionStore.t,
26
+ // Page store owning this page's raw blocks.
27
+ blockStore: BlockStore.t,
22
28
  }
23
29
 
24
30
  type missingParams = {
@@ -55,21 +61,6 @@ module GetLogs = {
55
61
 
56
62
  exception Error(error)
57
63
 
58
- let makeRequestBody = (
59
- ~fromBlock,
60
- ~toBlockInclusive,
61
- ~addressesWithTopics,
62
- ~fieldSelection,
63
- ): HyperSyncClient.QueryTypes.query => {
64
- fromBlock,
65
- toBlockExclusive: ?switch toBlockInclusive {
66
- | Some(toBlockInclusive) => Some(toBlockInclusive + 1)
67
- | None => None
68
- },
69
- logs: addressesWithTopics,
70
- fieldSelection,
71
- }
72
-
73
64
  // Rust encodes structured failures as a JSON payload in the napi error's
74
65
  // message: `{"kind":"MissingFields","fields":["block.timestamp", ...]}`.
75
66
  // JSON.parse + shape check is the recovery protocol — no string-grepping
@@ -99,29 +90,19 @@ module GetLogs = {
99
90
  ~client: HyperSyncClient.t,
100
91
  ~fromBlock,
101
92
  ~toBlock,
102
- ~logSelections: array<LogSelection.t>,
103
- ~fieldSelection,
93
+ ~maxNumLogs,
94
+ ~registrationIndexes,
95
+ ~addressesByContractName,
104
96
  ): logsQueryPage => {
105
- let addressesWithTopics = logSelections->Array.flatMap(({addresses, topicSelections}) =>
106
- topicSelections->Array.map(({topic0, topic1, topic2, topic3}) => {
107
- let topics = HyperSyncClient.QueryTypes.makeTopicSelection(
108
- ~topic0,
109
- ~topic1,
110
- ~topic2,
111
- ~topic3,
112
- )
113
- HyperSyncClient.QueryTypes.makeLogSelection(~address=addresses, ~topics)
114
- })
115
- )
116
-
117
- let query = makeRequestBody(
118
- ~fromBlock,
119
- ~toBlockInclusive=toBlock,
120
- ~addressesWithTopics,
121
- ~fieldSelection,
122
- )
97
+ let query: HyperSyncClient.EventItems.query = {
98
+ fromBlock,
99
+ toBlock,
100
+ maxNumLogs,
101
+ registrationIndexes,
102
+ addressesByContractName,
103
+ }
123
104
 
124
- let res = switch await client.getEventItems(~query) {
105
+ let (res, transactionStore, blockStore) = switch await client.getEventItems(~query) {
125
106
  | res => res
126
107
  | exception exn =>
127
108
  reraisIfRateLimited(exn)
@@ -137,9 +118,12 @@ module GetLogs = {
137
118
 
138
119
  {
139
120
  items: res.items,
121
+ blocks: res.blocks,
140
122
  nextBlock: res.nextBlock,
141
123
  archiveHeight: res.archiveHeight->Option.getOr(0), //Archive Height is only None if height is 0
142
124
  rollbackGuard: res.rollbackGuard,
125
+ transactionStore,
126
+ blockStore,
143
127
  }
144
128
  }
145
129
  }
@@ -196,6 +180,7 @@ module BlockData = {
196
180
  ~sourceName,
197
181
  ~chainId,
198
182
  ~logger,
183
+ ~requestStats: array<Source.requestStat>,
199
184
  ): queryResponse<array<ReorgDetection.blockDataWithTimestamp>> => {
200
185
  let body = makeRequestBody(~fromBlock, ~toBlock)
201
186
 
@@ -208,7 +193,7 @@ module BlockData = {
208
193
  },
209
194
  )
210
195
 
211
- Prometheus.SourceRequestCount.increment(~sourceName, ~chainId, ~method="getBlockHashes")
196
+ let timerRef = Performance.now()
212
197
  let maybeSuccessfulRes = switch await client.get(~query=body) {
213
198
  | exception exn =>
214
199
  reraisIfRateLimited(exn)
@@ -216,6 +201,9 @@ module BlockData = {
216
201
  | res if res.nextBlock <= fromBlock => None
217
202
  | res => Some(res)
218
203
  }
204
+ requestStats
205
+ ->Array.push({Source.method: "getBlockHashes", seconds: timerRef->Performance.secondsSince})
206
+ ->ignore
219
207
 
220
208
  // If the block is not found, retry the query. This can occur since replicas of hypersync might not have caught up yet
221
209
  switch maybeSuccessfulRes {
@@ -225,7 +213,15 @@ module BlockData = {
225
213
  `Block #${fromBlock->Int.toString} not found in HyperSync. HyperSync has multiple instances and it's possible that they drift independently slightly from the head. Indexing should continue correctly after retrying the query in ${delayMilliseconds->Int.toString}ms.`,
226
214
  )
227
215
  await Time.resolvePromiseAfterDelay(~delayMilliseconds)
228
- await queryBlockData(~client, ~fromBlock, ~toBlock, ~sourceName, ~chainId, ~logger)
216
+ await queryBlockData(
217
+ ~client,
218
+ ~fromBlock,
219
+ ~toBlock,
220
+ ~sourceName,
221
+ ~chainId,
222
+ ~logger,
223
+ ~requestStats,
224
+ )
229
225
  }
230
226
  | Some(res) =>
231
227
  switch res->convertResponse {
@@ -238,6 +234,7 @@ module BlockData = {
238
234
  ~sourceName,
239
235
  ~chainId,
240
236
  ~logger,
237
+ ~requestStats,
241
238
  )
242
239
  restRes->Result.map(rest => datas->Array.concat(rest))
243
240
  }
@@ -252,8 +249,9 @@ module BlockData = {
252
249
  ~sourceName,
253
250
  ~chainId,
254
251
  ~logger,
255
- ) => {
256
- switch blockNumbers->Array.get(0) {
252
+ ): (queryResponse<array<ReorgDetection.blockDataWithTimestamp>>, array<Source.requestStat>) => {
253
+ let requestStats = []
254
+ let result = switch blockNumbers->Array.get(0) {
257
255
  | None => Ok([])
258
256
  | Some(firstBlock) => {
259
257
  let fromBlock = ref(firstBlock)
@@ -281,6 +279,7 @@ module BlockData = {
281
279
  ~sourceName,
282
280
  ~chainId,
283
281
  ~logger,
282
+ ~requestStats,
284
283
  )
285
284
  let filtered = res->Result.map(datas => {
286
285
  datas->Array.filter(data => set->Utils.Set.delete(data.blockNumber))
@@ -295,10 +294,12 @@ module BlockData = {
295
294
  filtered
296
295
  }
297
296
  }
297
+ (result, requestStats)
298
298
  }
299
299
  }
300
300
 
301
- let queryBlockData = (~client, ~blockNumber, ~sourceName, ~chainId, ~logger) =>
301
+ let queryBlockData = (~client, ~blockNumber, ~sourceName, ~chainId, ~logger) => {
302
+ let requestStats = []
302
303
  BlockData.queryBlockData(
303
304
  ~client,
304
305
  ~fromBlock=blockNumber,
@@ -306,5 +307,7 @@ let queryBlockData = (~client, ~blockNumber, ~sourceName, ~chainId, ~logger) =>
306
307
  ~sourceName,
307
308
  ~chainId,
308
309
  ~logger,
309
- )->Promise.thenResolve(res => res->Result.map(res => res->Array.get(0)))
310
+ ~requestStats,
311
+ )->Promise.thenResolve(res => (res->Result.map(res => res->Array.get(0)), requestStats))
312
+ }
310
313
  let queryBlockDataMulti = BlockData.queryBlockDataMulti