envio 3.0.0-alpha.10 → 3.0.0-alpha.12

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 (40) hide show
  1. package/evm.schema.json +18 -0
  2. package/index.d.ts +13 -0
  3. package/package.json +5 -5
  4. package/src/Batch.res +2 -0
  5. package/src/Batch.res.mjs +1 -0
  6. package/src/ChainManager.res +3 -1
  7. package/src/ChainManager.res.mjs +1 -1
  8. package/src/Config.res +7 -1
  9. package/src/Config.res.mjs +6 -3
  10. package/src/Env.res +1 -0
  11. package/src/Env.res.mjs +4 -1
  12. package/src/GlobalState.res +0 -1
  13. package/src/GlobalState.res.mjs +0 -1
  14. package/src/PgStorage.res +2 -1
  15. package/src/PgStorage.res.mjs +2 -1
  16. package/src/Prometheus.res +12 -0
  17. package/src/Prometheus.res.mjs +45 -30
  18. package/src/TestIndexer.res +76 -4
  19. package/src/TestIndexer.res.mjs +144 -100
  20. package/src/Utils.res +22 -0
  21. package/src/Utils.res.mjs +18 -0
  22. package/src/db/InternalTable.res +5 -3
  23. package/src/db/InternalTable.res.mjs +6 -4
  24. package/src/sources/EvmChain.res +3 -0
  25. package/src/sources/EvmChain.res.mjs +2 -1
  26. package/src/sources/HyperFuelSource.res +5 -1
  27. package/src/sources/HyperFuelSource.res.mjs +5 -1
  28. package/src/sources/HyperSync.res +12 -3
  29. package/src/sources/HyperSync.res.mjs +9 -7
  30. package/src/sources/HyperSync.resi +4 -0
  31. package/src/sources/HyperSyncHeightStream.res +3 -1
  32. package/src/sources/HyperSyncHeightStream.res.mjs +3 -1
  33. package/src/sources/HyperSyncSource.res +10 -3
  34. package/src/sources/HyperSyncSource.res.mjs +8 -4
  35. package/src/sources/Rpc.res +21 -21
  36. package/src/sources/Rpc.res.mjs +18 -18
  37. package/src/sources/RpcSource.res +51 -56
  38. package/src/sources/RpcSource.res.mjs +50 -53
  39. package/src/sources/Svm.res +15 -2
  40. package/src/sources/Svm.res.mjs +7 -1
@@ -253,6 +253,34 @@ function validateBlockRange(chainId, configChain, processChainConfig, progressBl
253
253
 
254
254
  }
255
255
 
256
+ function makeEntityGet(state, entityConfig) {
257
+ return function (entityId) {
258
+ if (state.processInProgress) {
259
+ Js_exn.raiseError("Cannot call " + entityConfig.name + ".get() while indexer.process() is running. Wait for process() to complete before accessing entities directly.");
260
+ }
261
+ var entityDict = Belt_Option.getWithDefault(Js_dict.get(state.entities, entityConfig.name), {});
262
+ return Promise.resolve(Js_dict.get(entityDict, entityId));
263
+ };
264
+ }
265
+
266
+ function makeEntitySet(state, entityConfig) {
267
+ return function (entity) {
268
+ if (state.processInProgress) {
269
+ Js_exn.raiseError("Cannot call " + entityConfig.name + ".set() while indexer.process() is running. Wait for process() to complete before modifying entities directly.");
270
+ }
271
+ var dict = Js_dict.get(state.entities, entityConfig.name);
272
+ var entityDict;
273
+ if (dict !== undefined) {
274
+ entityDict = dict;
275
+ } else {
276
+ var dict$1 = {};
277
+ state.entities[entityConfig.name] = dict$1;
278
+ entityDict = dict$1;
279
+ }
280
+ entityDict[entity.id] = entity;
281
+ };
282
+ }
283
+
256
284
  function makeCreateTestIndexer(config, workerPath, allEntities) {
257
285
  return function () {
258
286
  var entities = {};
@@ -268,111 +296,125 @@ function makeCreateTestIndexer(config, workerPath, allEntities) {
268
296
  entityConfigs: entityConfigs,
269
297
  processChanges: []
270
298
  };
271
- return {
272
- process: (function (processConfig) {
273
- if (state.processInProgress) {
274
- Js_exn.raiseError("createTestIndexer process is already running. Only one process call is allowed at a time");
275
- }
276
- var chains = processConfig.chains;
277
- var chainKeys = Object.keys(chains);
278
- var n = chainKeys.length;
279
- if (n !== 0) {
280
- if (n !== 1) {
281
- Js_exn.raiseError("createTestIndexer does not support processing multiple chains at once. Found " + String(n) + " chains defined");
299
+ var entityOpsDict = {};
300
+ Belt_Array.forEach(allEntities, (function (entityConfig) {
301
+ if (entityConfig.name !== InternalTable.DynamicContractRegistry.name) {
302
+ entityOpsDict[entityConfig.name] = {
303
+ get: makeEntityGet(state, entityConfig),
304
+ set: makeEntitySet(state, entityConfig)
305
+ };
306
+ return ;
307
+ }
308
+
309
+ }));
310
+ var result = {};
311
+ Belt_Array.forEach(Js_dict.entries(entityOpsDict), (function (param) {
312
+ result[param[0]] = param[1];
313
+ }));
314
+ result["process"] = (function (processConfig) {
315
+ if (state.processInProgress) {
316
+ Js_exn.raiseError("createTestIndexer process is already running. Only one process call is allowed at a time");
317
+ }
318
+ var chains = processConfig.chains;
319
+ var chainKeys = Object.keys(chains);
320
+ var n = chainKeys.length;
321
+ if (n !== 0) {
322
+ if (n !== 1) {
323
+ Js_exn.raiseError("createTestIndexer does not support processing multiple chains at once. Found " + String(n) + " chains defined");
324
+ }
325
+
326
+ } else {
327
+ Js_exn.raiseError("createTestIndexer requires exactly one chain to be defined");
328
+ }
329
+ Belt_Array.forEach(chainKeys, (function (chainIdStr) {
330
+ var chainId = Belt_Option.getWithDefault(Belt_Int.fromString(chainIdStr), 0);
331
+ var chain = ChainMap.Chain.makeUnsafe(chainId);
332
+ var configChain = ChainMap.get(config.chainMap, chain);
333
+ var processChainConfig = chains[chainIdStr];
334
+ var progressBlock = Js_dict.get(state.progressBlockByChain, chainIdStr);
335
+ validateBlockRange(chainIdStr, configChain, processChainConfig, progressBlock);
336
+ }));
337
+ state.processChanges = [];
338
+ var dynamicContractsByChain = {};
339
+ var dcDict = Js_dict.get(state.entities, InternalTable.DynamicContractRegistry.name);
340
+ if (dcDict !== undefined) {
341
+ Belt_Array.forEach(Js_dict.values(dcDict), (function (entity) {
342
+ var chainIdStr = String(entity.chain_id);
343
+ var arr = Js_dict.get(dynamicContractsByChain, chainIdStr);
344
+ var contracts;
345
+ if (arr !== undefined) {
346
+ contracts = arr;
347
+ } else {
348
+ var arr$1 = [];
349
+ dynamicContractsByChain[chainIdStr] = arr$1;
350
+ contracts = arr$1;
282
351
  }
283
-
284
- } else {
285
- Js_exn.raiseError("createTestIndexer requires exactly one chain to be defined");
286
- }
287
- Belt_Array.forEach(chainKeys, (function (chainIdStr) {
288
- var chainId = Belt_Option.getWithDefault(Belt_Int.fromString(chainIdStr), 0);
289
- var chain = ChainMap.Chain.makeUnsafe(chainId);
290
- var configChain = ChainMap.get(config.chainMap, chain);
291
- var processChainConfig = chains[chainIdStr];
292
- var progressBlock = Js_dict.get(state.progressBlockByChain, chainIdStr);
293
- validateBlockRange(chainIdStr, configChain, processChainConfig, progressBlock);
294
- }));
295
- state.processChanges = [];
296
- var dynamicContractsByChain = {};
297
- var dcDict = Js_dict.get(state.entities, InternalTable.DynamicContractRegistry.name);
298
- if (dcDict !== undefined) {
299
- Belt_Array.forEach(Js_dict.values(dcDict), (function (entity) {
300
- var chainIdStr = String(entity.chain_id);
301
- var arr = Js_dict.get(dynamicContractsByChain, chainIdStr);
302
- var contracts;
303
- if (arr !== undefined) {
304
- contracts = arr;
305
- } else {
306
- var arr$1 = [];
307
- dynamicContractsByChain[chainIdStr] = arr$1;
308
- contracts = arr$1;
309
- }
310
- contracts.push(toIndexingContract(entity));
311
- }));
312
- }
313
- var initialState = makeInitialState(config, chains, dynamicContractsByChain);
314
- return new Promise((function (resolve, reject) {
315
- var workerDataObj = {
316
- processConfig: JSON.parse(Js_json.serializeExn(processConfig)),
317
- initialState: initialState
318
- };
319
- var workerData = JSON.parse(Js_json.serializeExn(workerDataObj));
320
- var worker;
321
- try {
322
- worker = new Worker_threads.Worker(workerPath, {
323
- workerData: workerData
352
+ contracts.push(toIndexingContract(entity));
353
+ }));
354
+ }
355
+ var initialState = makeInitialState(config, chains, dynamicContractsByChain);
356
+ return new Promise((function (resolve, reject) {
357
+ var workerDataObj = {
358
+ processConfig: JSON.parse(Js_json.serializeExn(processConfig)),
359
+ initialState: initialState
360
+ };
361
+ var workerData = JSON.parse(Js_json.serializeExn(workerDataObj));
362
+ var worker;
363
+ try {
364
+ worker = new Worker_threads.Worker(workerPath, {
365
+ workerData: workerData
366
+ });
367
+ }
368
+ catch (raw_exn){
369
+ var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
370
+ reject(exn);
371
+ throw exn;
372
+ }
373
+ state.processInProgress = true;
374
+ worker.on("message", (function (msg) {
375
+ var respond = function (data) {
376
+ worker.postMessage({
377
+ id: msg.id,
378
+ payload: {
379
+ type: "response",
380
+ data: data
381
+ }
324
382
  });
383
+ };
384
+ var match = msg.payload;
385
+ switch (match.type) {
386
+ case "loadByIds" :
387
+ return respond(handleLoadByIds(state, match.tableName, match.ids));
388
+ case "loadByField" :
389
+ return respond(handleLoadByField(state, match.tableName, match.fieldName, match.fieldValue, match.operator));
390
+ case "writeBatch" :
391
+ handleWriteBatch(state, match.updatedEntities, match.checkpointIds, match.checkpointChainIds, match.checkpointBlockNumbers, match.checkpointBlockHashes, match.checkpointEventsProcessed);
392
+ return respond(null);
393
+
325
394
  }
326
- catch (raw_exn){
327
- var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
328
- reject(exn);
329
- throw exn;
395
+ }));
396
+ worker.on("error", (function (err) {
397
+ state.processInProgress = false;
398
+ worker.terminate();
399
+ reject(err);
400
+ }));
401
+ worker.on("exit", (function (code) {
402
+ state.processInProgress = false;
403
+ if (code !== 0) {
404
+ return reject(new Error("Worker exited with code " + String(code)));
405
+ } else {
406
+ Belt_Array.forEach(chainKeys, (function (chainIdStr) {
407
+ var processChainConfig = chains[chainIdStr];
408
+ state.progressBlockByChain[chainIdStr] = processChainConfig.endBlock;
409
+ }));
410
+ return resolve({
411
+ changes: state.processChanges
412
+ });
330
413
  }
331
- state.processInProgress = true;
332
- worker.on("message", (function (msg) {
333
- var respond = function (data) {
334
- worker.postMessage({
335
- id: msg.id,
336
- payload: {
337
- type: "response",
338
- data: data
339
- }
340
- });
341
- };
342
- var match = msg.payload;
343
- switch (match.type) {
344
- case "loadByIds" :
345
- return respond(handleLoadByIds(state, match.tableName, match.ids));
346
- case "loadByField" :
347
- return respond(handleLoadByField(state, match.tableName, match.fieldName, match.fieldValue, match.operator));
348
- case "writeBatch" :
349
- handleWriteBatch(state, match.updatedEntities, match.checkpointIds, match.checkpointChainIds, match.checkpointBlockNumbers, match.checkpointBlockHashes, match.checkpointEventsProcessed);
350
- return respond(null);
351
-
352
- }
353
- }));
354
- worker.on("error", (function (err) {
355
- state.processInProgress = false;
356
- worker.terminate();
357
- reject(err);
358
- }));
359
- worker.on("exit", (function (code) {
360
- state.processInProgress = false;
361
- if (code !== 0) {
362
- return reject(new Error("Worker exited with code " + String(code)));
363
- } else {
364
- Belt_Array.forEach(chainKeys, (function (chainIdStr) {
365
- var processChainConfig = chains[chainIdStr];
366
- state.progressBlockByChain[chainIdStr] = processChainConfig.endBlock;
367
- }));
368
- return resolve({
369
- changes: state.processChanges
370
- });
371
- }
372
- }));
373
414
  }));
374
- })
375
- };
415
+ }));
416
+ });
417
+ return result;
376
418
  };
377
419
  }
378
420
 
@@ -406,6 +448,8 @@ export {
406
448
  handleWriteBatch ,
407
449
  makeInitialState ,
408
450
  validateBlockRange ,
451
+ makeEntityGet ,
452
+ makeEntitySet ,
409
453
  makeCreateTestIndexer ,
410
454
  initTestWorker ,
411
455
  }
package/src/Utils.res CHANGED
@@ -435,6 +435,28 @@ String.replaceAll("the cat and the dog", "the", "this") == "this cat and this do
435
435
  external replaceAll: (string, string, string) => string = "replaceAll"
436
436
  }
437
437
 
438
+ module Url = {
439
+ /**
440
+ Extracts the hostname from a URL string.
441
+ Returns None if the URL doesn't have a valid http:// or https:// protocol.
442
+ */
443
+ let getHostFromUrl = (url: string) => {
444
+ // Regular expression requiring protocol and capturing hostname
445
+ // - (https?:\/\/) : Required http:// or https:// (capturing group)
446
+ // - ([^\/?]+) : Capture hostname (one or more characters that aren't / or ?)
447
+ // - .* : Match rest of the string
448
+ let regex = %re("/https?:\/\/([^\/?]+).*/")
449
+ switch Js.Re.exec_(regex, url) {
450
+ | Some(result) =>
451
+ switch Js.Re.captures(result)->Belt.Array.get(1) {
452
+ | Some(host) => host->Js.Nullable.toOption
453
+ | None => None
454
+ }
455
+ | None => None
456
+ }
457
+ }
458
+ }
459
+
438
460
  module Result = {
439
461
  let forEach = (result, fn) => {
440
462
  switch result {
package/src/Utils.res.mjs CHANGED
@@ -389,6 +389,23 @@ var $$String = {
389
389
  capitalize: capitalize
390
390
  };
391
391
 
392
+ function getHostFromUrl(url) {
393
+ var regex = /https?:\/\/([^\/?]+).*/;
394
+ var result = regex.exec(url);
395
+ if (result === null) {
396
+ return ;
397
+ }
398
+ var host = Belt_Array.get(result, 1);
399
+ if (host !== undefined) {
400
+ return Caml_option.nullable_to_opt(Caml_option.valFromOption(host));
401
+ }
402
+
403
+ }
404
+
405
+ var Url = {
406
+ getHostFromUrl: getHostFromUrl
407
+ };
408
+
392
409
  function forEach$1(result, fn) {
393
410
  if (result.TAG === "Ok") {
394
411
  fn(result._0);
@@ -643,6 +660,7 @@ export {
643
660
  UnsafeIntOperators ,
644
661
  $$Array$1 as $$Array,
645
662
  $$String ,
663
+ Url ,
646
664
  Result ,
647
665
  unwrapResultExn ,
648
666
  Schema ,
@@ -74,6 +74,7 @@ module Chains = {
74
74
  type progressFields = [
75
75
  | #progress_block
76
76
  | #events_processed
77
+ | #source_block
77
78
  ]
78
79
 
79
80
  type field = [
@@ -108,7 +109,6 @@ module Chains = {
108
109
  type metaFields = {
109
110
  @as("first_event_block") firstEventBlockNumber: Js.null<int>,
110
111
  @as("buffer_block") latestFetchedBlockNumber: int,
111
- @as("source_block") blockHeight: int,
112
112
  @as("ready_at")
113
113
  timestampCaughtUpToHeadOrEndblock: Js.null<Js.Date.t>,
114
114
  @as("_is_hyper_sync") isHyperSync: bool,
@@ -122,6 +122,7 @@ module Chains = {
122
122
  @as("max_reorg_depth") maxReorgDepth: int,
123
123
  @as("progress_block") progressBlockNumber: int,
124
124
  @as("events_processed") numEventsProcessed: int,
125
+ @as("source_block") blockHeight: int,
125
126
  ...metaFields,
126
127
  }
127
128
 
@@ -212,7 +213,6 @@ VALUES ${valuesRows->Js.Array2.joinWith(",\n ")};`,
212
213
 
213
214
  // Fields that can be updated outside of the batch transaction
214
215
  let metaFields: array<field> = [
215
- #source_block,
216
216
  #buffer_block,
217
217
  #first_event_block,
218
218
  #ready_at,
@@ -279,7 +279,7 @@ FROM "${pgSchema}"."${table.tableName}" as chains;`
279
279
  ->(Utils.magic: promise<array<unknown>> => promise<array<rawInitialState>>)
280
280
  }
281
281
 
282
- let progressFields: array<progressFields> = [#progress_block, #events_processed]
282
+ let progressFields: array<progressFields> = [#progress_block, #events_processed, #source_block]
283
283
 
284
284
  let makeProgressFieldsUpdateQuery = (~pgSchema) => {
285
285
  let setClauses = Belt.Array.mapWithIndex(progressFields, (index, field) => {
@@ -320,6 +320,7 @@ WHERE "id" = $1;`
320
320
  type progressedChain = {
321
321
  chainId: int,
322
322
  progressBlockNumber: int,
323
+ sourceBlockNumber: int,
323
324
  totalEventsProcessed: int,
324
325
  }
325
326
 
@@ -341,6 +342,7 @@ WHERE "id" = $1;`
341
342
  switch field {
342
343
  | #progress_block => data.progressBlockNumber->(Utils.magic: int => unknown)
343
344
  | #events_processed => data.totalEventsProcessed->(Utils.magic: int => unknown)
345
+ | #source_block => data.sourceBlockNumber->(Utils.magic: int => unknown)
344
346
  },
345
347
  )
346
348
  ->ignore
@@ -101,9 +101,9 @@ function initialFromConfig(chainConfig) {
101
101
  max_reorg_depth: chainConfig.maxReorgDepth,
102
102
  progress_block: -1,
103
103
  events_processed: 0,
104
+ source_block: 0,
104
105
  first_event_block: null,
105
106
  buffer_block: -1,
106
- source_block: 0,
107
107
  ready_at: null,
108
108
  _is_hyper_sync: false,
109
109
  _num_batches_fetched: 0
@@ -143,7 +143,6 @@ function makeInitialValuesQuery(pgSchema, chainConfigs) {
143
143
  }
144
144
 
145
145
  var metaFields = [
146
- "source_block",
147
146
  "buffer_block",
148
147
  "first_event_block",
149
148
  "ready_at",
@@ -169,7 +168,8 @@ function getInitialState(sql, pgSchema) {
169
168
 
170
169
  var progressFields = [
171
170
  "progress_block",
172
- "events_processed"
171
+ "events_processed",
172
+ "source_block"
173
173
  ];
174
174
 
175
175
  function makeProgressFieldsUpdateQuery(pgSchema) {
@@ -202,7 +202,9 @@ function setProgressedChains(sql, pgSchema, progressedChains) {
202
202
  var params = [];
203
203
  params.push(data.chainId);
204
204
  progressFields.forEach(function (field) {
205
- params.push(field === "progress_block" ? data.progressBlockNumber : data.totalEventsProcessed);
205
+ params.push(field === "source_block" ? data.sourceBlockNumber : (
206
+ field === "progress_block" ? data.progressBlockNumber : data.totalEventsProcessed
207
+ ));
206
208
  });
207
209
  promises.push(sql.unsafe(query, params, {prepare: true}));
208
210
  });
@@ -15,6 +15,7 @@ let getSyncConfig = (
15
15
  ?backoffMillis,
16
16
  ?queryTimeoutMillis,
17
17
  ?fallbackStallTimeout,
18
+ ?pollingInterval,
18
19
  }: Config.sourceSyncOptions,
19
20
  ): Config.sourceSync => {
20
21
  let queryTimeoutMillis = queryTimeoutMillis->Option.getWithDefault(20_000)
@@ -39,6 +40,8 @@ let getSyncConfig = (
39
40
  // How long to wait before cancelling an RPC request
40
41
  queryTimeoutMillis,
41
42
  fallbackStallTimeout: fallbackStallTimeout->Option.getWithDefault(queryTimeoutMillis / 2),
43
+ // How frequently to check for new blocks in realtime (default: 1000ms)
44
+ pollingInterval: pollingInterval->Option.getWithDefault(1000),
42
45
  }
43
46
  }
44
47
 
@@ -16,7 +16,8 @@ function getSyncConfig(param) {
16
16
  intervalCeiling: Belt_Option.getWithDefault(Env.Configurable.SyncConfig.intervalCeiling, Belt_Option.getWithDefault(param.intervalCeiling, 10000)),
17
17
  backoffMillis: Belt_Option.getWithDefault(param.backoffMillis, 5000),
18
18
  queryTimeoutMillis: queryTimeoutMillis,
19
- fallbackStallTimeout: Belt_Option.getWithDefault(param.fallbackStallTimeout, queryTimeoutMillis / 2 | 0)
19
+ fallbackStallTimeout: Belt_Option.getWithDefault(param.fallbackStallTimeout, queryTimeoutMillis / 2 | 0),
20
+ pollingInterval: Belt_Option.getWithDefault(param.pollingInterval, 1000)
20
21
  };
21
22
  }
22
23
 
@@ -235,6 +235,7 @@ let make = ({chain, endpointUrl}: options): t => {
235
235
  let startFetchingBatchTimeRef = Hrtime.makeTimer()
236
236
 
237
237
  //fetch batch
238
+ Prometheus.SourceRequestCount.increment(~sourceName=name, ~chainId=chain->ChainMap.Chain.toChainId)
238
239
  let pageUnsafe = try await HyperFuel.GetLogs.query(
239
240
  ~serverUrl=endpointUrl,
240
241
  ~fromBlock,
@@ -496,7 +497,10 @@ let make = ({chain, endpointUrl}: options): t => {
496
497
  getBlockHashes,
497
498
  pollingInterval: 100,
498
499
  poweredByHyperSync: true,
499
- getHeightOrThrow: () => HyperFuel.heightRoute->Rest.fetch((), ~client=jsonApiClient),
500
+ getHeightOrThrow: () => {
501
+ Prometheus.SourceRequestCount.increment(~sourceName=name, ~chainId=chain->ChainMap.Chain.toChainId)
502
+ HyperFuel.heightRoute->Rest.fetch((), ~client=jsonApiClient)
503
+ },
500
504
  getItemsOrThrow,
501
505
  }
502
506
  }
@@ -9,6 +9,7 @@ import * as $$Promise from "../bindings/Promise.res.mjs";
9
9
  import * as HyperFuel from "./HyperFuel.res.mjs";
10
10
  import * as HyperSync from "./HyperSync.res.mjs";
11
11
  import * as Belt_Array from "rescript/lib/es6/belt_Array.js";
12
+ import * as Prometheus from "../Prometheus.res.mjs";
12
13
  import * as Belt_Option from "rescript/lib/es6/belt_Option.js";
13
14
  import * as EventRouter from "./EventRouter.res.mjs";
14
15
  import * as ErrorHandling from "../ErrorHandling.res.mjs";
@@ -185,6 +186,7 @@ function memoGetSelectionConfig(chain) {
185
186
  function make(param) {
186
187
  var endpointUrl = param.endpointUrl;
187
188
  var chain = param.chain;
189
+ var name = "HyperFuel";
188
190
  var getSelectionConfig = memoGetSelectionConfig(chain);
189
191
  var getItemsOrThrow = async function (fromBlock, toBlock, addressesByContractName, indexingContracts, knownHeight, param, selection, retry, logger) {
190
192
  var mkLogAndRaise = function (extra, extra$1) {
@@ -194,6 +196,7 @@ function make(param) {
194
196
  var selectionConfig = getSelectionConfig(selection);
195
197
  var recieptsSelection = selectionConfig.getRecieptsSelection(addressesByContractName);
196
198
  var startFetchingBatchTimeRef = Hrtime.makeTimer();
199
+ Prometheus.SourceRequestCount.increment(name, chain);
197
200
  var pageUnsafe;
198
201
  try {
199
202
  pageUnsafe = await HyperFuel.GetLogs.query(endpointUrl, fromBlock, toBlock, recieptsSelection);
@@ -421,13 +424,14 @@ function make(param) {
421
424
  };
422
425
  var jsonApiClient = Rest.client(endpointUrl, undefined);
423
426
  return {
424
- name: "HyperFuel",
427
+ name: name,
425
428
  sourceFor: "Sync",
426
429
  chain: chain,
427
430
  poweredByHyperSync: true,
428
431
  pollingInterval: 100,
429
432
  getBlockHashes: getBlockHashes,
430
433
  getHeightOrThrow: (function () {
434
+ Prometheus.SourceRequestCount.increment(name, chain);
431
435
  return Rest.$$fetch(HyperFuel.heightRoute, undefined, jsonApiClient);
432
436
  }),
433
437
  getItemsOrThrow: getItemsOrThrow
@@ -245,6 +245,8 @@ module BlockData = {
245
245
  ~apiToken,
246
246
  ~fromBlock,
247
247
  ~toBlock,
248
+ ~sourceName,
249
+ ~chainId,
248
250
  ~logger,
249
251
  ): queryResponse<array<ReorgDetection.blockDataWithTimestamp>> => {
250
252
  let body = makeRequestBody(~fromBlock, ~toBlock)
@@ -258,6 +260,7 @@ module BlockData = {
258
260
  },
259
261
  )
260
262
 
263
+ Prometheus.SourceRequestCount.increment(~sourceName, ~chainId)
261
264
  let maybeSuccessfulRes = switch await Time.retryAsyncWithExponentialBackOff(() =>
262
265
  HyperSyncJsonApi.queryRoute->Rest.fetch(
263
266
  {
@@ -281,7 +284,7 @@ module BlockData = {
281
284
  `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.`,
282
285
  )
283
286
  await Time.resolvePromiseAfterDelay(~delayMilliseconds)
284
- await queryBlockData(~serverUrl, ~apiToken, ~fromBlock, ~toBlock, ~logger)
287
+ await queryBlockData(~serverUrl, ~apiToken, ~fromBlock, ~toBlock, ~sourceName, ~chainId, ~logger)
285
288
  }
286
289
  | Some(res) =>
287
290
  switch res->convertResponse {
@@ -292,6 +295,8 @@ module BlockData = {
292
295
  ~apiToken,
293
296
  ~fromBlock=res.nextBlock,
294
297
  ~toBlock,
298
+ ~sourceName,
299
+ ~chainId,
295
300
  ~logger,
296
301
  )
297
302
  restRes->Result.map(rest => datas->Array.concat(rest))
@@ -301,7 +306,7 @@ module BlockData = {
301
306
  }
302
307
  }
303
308
 
304
- let queryBlockDataMulti = async (~serverUrl, ~apiToken, ~blockNumbers, ~logger) => {
309
+ let queryBlockDataMulti = async (~serverUrl, ~apiToken, ~blockNumbers, ~sourceName, ~chainId, ~logger) => {
305
310
  switch blockNumbers->Array.get(0) {
306
311
  | None => Ok([])
307
312
  | Some(firstBlock) => {
@@ -328,6 +333,8 @@ module BlockData = {
328
333
  ~toBlock=toBlock.contents,
329
334
  ~serverUrl,
330
335
  ~apiToken,
336
+ ~sourceName,
337
+ ~chainId,
331
338
  ~logger,
332
339
  )
333
340
  let filtered = res->Result.map(datas => {
@@ -346,12 +353,14 @@ module BlockData = {
346
353
  }
347
354
  }
348
355
 
349
- let queryBlockData = (~serverUrl, ~apiToken, ~blockNumber, ~logger) =>
356
+ let queryBlockData = (~serverUrl, ~apiToken, ~blockNumber, ~sourceName, ~chainId, ~logger) =>
350
357
  BlockData.queryBlockData(
351
358
  ~serverUrl,
352
359
  ~apiToken,
353
360
  ~fromBlock=blockNumber,
354
361
  ~toBlock=blockNumber,
362
+ ~sourceName,
363
+ ~chainId,
355
364
  ~logger,
356
365
  )->Promise.thenResolve(res => res->Result.map(res => res->Array.get(0)))
357
366
  let queryBlockDataMulti = BlockData.queryBlockDataMulti
@@ -7,6 +7,7 @@ import * as $$BigInt from "../bindings/BigInt.res.mjs";
7
7
  import * as Js_exn from "rescript/lib/es6/js_exn.js";
8
8
  import * as Logging from "../Logging.res.mjs";
9
9
  import * as Belt_Array from "rescript/lib/es6/belt_Array.js";
10
+ import * as Prometheus from "../Prometheus.res.mjs";
10
11
  import * as Belt_Option from "rescript/lib/es6/belt_Option.js";
11
12
  import * as Belt_Result from "rescript/lib/es6/belt_Result.js";
12
13
  import * as Caml_option from "rescript/lib/es6/caml_option.js";
@@ -226,13 +227,14 @@ function convertResponse(res) {
226
227
  })));
227
228
  }
228
229
 
229
- async function queryBlockData(serverUrl, apiToken, fromBlock, toBlock, logger) {
230
+ async function queryBlockData(serverUrl, apiToken, fromBlock, toBlock, sourceName, chainId, logger) {
230
231
  var body = makeRequestBody$1(fromBlock, toBlock);
231
232
  var logger$1 = Logging.createChildFrom(logger, {
232
233
  logType: "HyperSync get block hash query",
233
234
  fromBlock: fromBlock,
234
235
  toBlock: toBlock
235
236
  });
237
+ Prometheus.SourceRequestCount.increment(sourceName, chainId);
236
238
  var maybeSuccessfulRes;
237
239
  var exit = 0;
238
240
  var res;
@@ -260,7 +262,7 @@ async function queryBlockData(serverUrl, apiToken, fromBlock, toBlock, logger) {
260
262
  return err;
261
263
  }
262
264
  var datas = err._0;
263
- var restRes = await queryBlockData(serverUrl, apiToken, maybeSuccessfulRes.nextBlock, toBlock, logger$1);
265
+ var restRes = await queryBlockData(serverUrl, apiToken, maybeSuccessfulRes.nextBlock, toBlock, sourceName, chainId, logger$1);
264
266
  return Belt_Result.map(restRes, (function (rest) {
265
267
  return Belt_Array.concat(datas, rest);
266
268
  }));
@@ -270,10 +272,10 @@ async function queryBlockData(serverUrl, apiToken, fromBlock, toBlock, logger) {
270
272
  });
271
273
  Logging.childInfo(logger$2, "Block #" + String(fromBlock) + " 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 " + String(100) + "ms.");
272
274
  await Time.resolvePromiseAfterDelay(100);
273
- return await queryBlockData(serverUrl, apiToken, fromBlock, toBlock, logger$2);
275
+ return await queryBlockData(serverUrl, apiToken, fromBlock, toBlock, sourceName, chainId, logger$2);
274
276
  }
275
277
 
276
- async function queryBlockDataMulti(serverUrl, apiToken, blockNumbers, logger) {
278
+ async function queryBlockDataMulti(serverUrl, apiToken, blockNumbers, sourceName, chainId, logger) {
277
279
  var firstBlock = Belt_Array.get(blockNumbers, 0);
278
280
  if (firstBlock === undefined) {
279
281
  return {
@@ -297,7 +299,7 @@ async function queryBlockDataMulti(serverUrl, apiToken, blockNumbers, logger) {
297
299
  if ((toBlock - fromBlock | 0) > 1000) {
298
300
  Js_exn.raiseError("Invalid block data request. Range of block numbers is too large. Max range is 1000. Requested range: " + String(fromBlock) + "-" + String(toBlock));
299
301
  }
300
- var res = await queryBlockData(serverUrl, apiToken, fromBlock, toBlock, logger);
302
+ var res = await queryBlockData(serverUrl, apiToken, fromBlock, toBlock, sourceName, chainId, logger);
301
303
  var filtered = Belt_Result.map(res, (function (datas) {
302
304
  return Belt_Array.keep(datas, (function (data) {
303
305
  return set.delete(data.blockNumber);
@@ -309,8 +311,8 @@ async function queryBlockDataMulti(serverUrl, apiToken, blockNumbers, logger) {
309
311
  return filtered;
310
312
  }
311
313
 
312
- function queryBlockData$1(serverUrl, apiToken, blockNumber, logger) {
313
- return queryBlockData(serverUrl, apiToken, blockNumber, blockNumber, logger).then(function (res) {
314
+ function queryBlockData$1(serverUrl, apiToken, blockNumber, sourceName, chainId, logger) {
315
+ return queryBlockData(serverUrl, apiToken, blockNumber, blockNumber, sourceName, chainId, logger).then(function (res) {
314
316
  return Belt_Result.map(res, (function (res) {
315
317
  return Belt_Array.get(res, 0);
316
318
  }));
@@ -56,6 +56,8 @@ let queryBlockData: (
56
56
  ~serverUrl: string,
57
57
  ~apiToken: string,
58
58
  ~blockNumber: int,
59
+ ~sourceName: string,
60
+ ~chainId: int,
59
61
  ~logger: Pino.t,
60
62
  ) => promise<queryResponse<option<ReorgDetection.blockDataWithTimestamp>>>
61
63
 
@@ -63,6 +65,8 @@ let queryBlockDataMulti: (
63
65
  ~serverUrl: string,
64
66
  ~apiToken: string,
65
67
  ~blockNumbers: array<int>,
68
+ ~sourceName: string,
69
+ ~chainId: int,
66
70
  ~logger: Pino.t,
67
71
  ) => promise<queryResponse<array<ReorgDetection.blockDataWithTimestamp>>>
68
72