envio 3.0.0-alpha.11 → 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.
package/evm.schema.json CHANGED
@@ -458,6 +458,15 @@
458
458
  ],
459
459
  "format": "uint32",
460
460
  "minimum": 0
461
+ },
462
+ "polling_interval": {
463
+ "description": "How frequently (in milliseconds) to check for new blocks in realtime. Default is 1000ms. Note: Setting this higher than block time does not reduce RPC usage as every block is still fetched to check for reorgs.",
464
+ "type": [
465
+ "integer",
466
+ "null"
467
+ ],
468
+ "format": "uint32",
469
+ "minimum": 0
461
470
  }
462
471
  },
463
472
  "additionalProperties": false,
@@ -553,6 +562,15 @@
553
562
  ],
554
563
  "format": "uint32",
555
564
  "minimum": 0
565
+ },
566
+ "polling_interval": {
567
+ "description": "How frequently (in milliseconds) to check for new blocks in realtime. Default is 1000ms. Note: Setting this higher than block time does not reduce RPC usage as every block is still fetched to check for reorgs.",
568
+ "type": [
569
+ "integer",
570
+ "null"
571
+ ],
572
+ "format": "uint32",
573
+ "minimum": 0
556
574
  }
557
575
  },
558
576
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "envio",
3
- "version": "v3.0.0-alpha.11",
3
+ "version": "v3.0.0-alpha.12",
4
4
  "type": "module",
5
5
  "description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
6
6
  "bin": "./bin.js",
@@ -29,10 +29,10 @@
29
29
  "node": ">=22.0.0"
30
30
  },
31
31
  "optionalDependencies": {
32
- "envio-linux-x64": "v3.0.0-alpha.11",
33
- "envio-linux-arm64": "v3.0.0-alpha.11",
34
- "envio-darwin-x64": "v3.0.0-alpha.11",
35
- "envio-darwin-arm64": "v3.0.0-alpha.11"
32
+ "envio-linux-x64": "v3.0.0-alpha.12",
33
+ "envio-linux-arm64": "v3.0.0-alpha.12",
34
+ "envio-darwin-x64": "v3.0.0-alpha.12",
35
+ "envio-darwin-arm64": "v3.0.0-alpha.12"
36
36
  },
37
37
  "dependencies": {
38
38
  "@clickhouse/client": "1.12.1",
package/src/Batch.res CHANGED
@@ -6,6 +6,7 @@ open Utils.UnsafeIntOperators
6
6
  type chainAfterBatch = {
7
7
  batchSize: int,
8
8
  progressBlockNumber: int,
9
+ sourceBlockNumber: int,
9
10
  totalEventsProcessed: int,
10
11
  fetchState: FetchState.t,
11
12
  isProgressAtHeadWhenBatchCreated: bool,
@@ -108,6 +109,7 @@ let getProgressedChainsById = {
108
109
  {
109
110
  batchSize,
110
111
  progressBlockNumber: progressBlockNumberAfterBatch,
112
+ sourceBlockNumber: chainBeforeBatch.sourceBlockNumber,
111
113
  totalEventsProcessed: chainBeforeBatch.totalEventsProcessed + batchSize,
112
114
  fetchState: fetchStateAfterBatch,
113
115
  isProgressAtHeadWhenBatchCreated: progressBlockNumberAfterBatch >=
package/src/Batch.res.mjs CHANGED
@@ -62,6 +62,7 @@ function getChainAfterBatchIfProgressed(chainBeforeBatch, progressBlockNumberAft
62
62
  return {
63
63
  batchSize: batchSize,
64
64
  progressBlockNumber: progressBlockNumberAfterBatch,
65
+ sourceBlockNumber: chainBeforeBatch.sourceBlockNumber,
65
66
  totalEventsProcessed: chainBeforeBatch.totalEventsProcessed + batchSize,
66
67
  fetchState: fetchStateAfterBatch,
67
68
  isProgressAtHeadWhenBatchCreated: progressBlockNumberAfterBatch >= chainBeforeBatch.sourceBlockNumber
package/src/Config.res CHANGED
@@ -8,6 +8,7 @@ type sourceSyncOptions = {
8
8
  backoffMillis?: int,
9
9
  queryTimeoutMillis?: int,
10
10
  fallbackStallTimeout?: int,
11
+ pollingInterval?: int,
11
12
  }
12
13
 
13
14
  type contract = {
@@ -65,6 +66,7 @@ type sourceSync = {
65
66
  backoffMillis: int,
66
67
  queryTimeoutMillis: int,
67
68
  fallbackStallTimeout: int,
69
+ pollingInterval: int,
68
70
  }
69
71
 
70
72
  type multichain = | @as("ordered") Ordered | @as("unordered") Unordered
@@ -109,6 +111,7 @@ let rpcConfigSchema = S.schema(s =>
109
111
  "backoffMillis": s.matches(S.option(S.int)),
110
112
  "fallbackStallTimeout": s.matches(S.option(S.int)),
111
113
  "queryTimeoutMillis": s.matches(S.option(S.int)),
114
+ "pollingInterval": s.matches(S.option(S.int)),
112
115
  }
113
116
  )
114
117
 
@@ -323,6 +326,7 @@ let fromPublic = (
323
326
  let backoffMillis = rpcConfig["backoffMillis"]
324
327
  let queryTimeoutMillis = rpcConfig["queryTimeoutMillis"]
325
328
  let fallbackStallTimeout = rpcConfig["fallbackStallTimeout"]
329
+ let pollingInterval = rpcConfig["pollingInterval"]
326
330
  let hasSyncConfig =
327
331
  initialBlockInterval->Option.isSome ||
328
332
  backoffMultiplicative->Option.isSome ||
@@ -330,7 +334,8 @@ let fromPublic = (
330
334
  intervalCeiling->Option.isSome ||
331
335
  backoffMillis->Option.isSome ||
332
336
  queryTimeoutMillis->Option.isSome ||
333
- fallbackStallTimeout->Option.isSome
337
+ fallbackStallTimeout->Option.isSome ||
338
+ pollingInterval->Option.isSome
334
339
  let syncConfig: option<sourceSyncOptions> = if hasSyncConfig {
335
340
  Some({
336
341
  ?initialBlockInterval,
@@ -340,6 +345,7 @@ let fromPublic = (
340
345
  ?backoffMillis,
341
346
  ?queryTimeoutMillis,
342
347
  ?fallbackStallTimeout,
348
+ ?pollingInterval,
343
349
  })
344
350
  } else {
345
351
  None
@@ -30,7 +30,8 @@ var rpcConfigSchema = S$RescriptSchema.schema(function (s) {
30
30
  intervalCeiling: s.m(S$RescriptSchema.option(S$RescriptSchema.$$int)),
31
31
  backoffMillis: s.m(S$RescriptSchema.option(S$RescriptSchema.$$int)),
32
32
  fallbackStallTimeout: s.m(S$RescriptSchema.option(S$RescriptSchema.$$int)),
33
- queryTimeoutMillis: s.m(S$RescriptSchema.option(S$RescriptSchema.$$int))
33
+ queryTimeoutMillis: s.m(S$RescriptSchema.option(S$RescriptSchema.$$int)),
34
+ pollingInterval: s.m(S$RescriptSchema.option(S$RescriptSchema.$$int))
34
35
  };
35
36
  });
36
37
 
@@ -235,7 +236,8 @@ function fromPublic(publicConfigJson, codegenChainsOpt, maxAddrInPartitionOpt, u
235
236
  var backoffMillis = rpcConfig.backoffMillis;
236
237
  var queryTimeoutMillis = rpcConfig.queryTimeoutMillis;
237
238
  var fallbackStallTimeout = rpcConfig.fallbackStallTimeout;
238
- var hasSyncConfig = Belt_Option.isSome(initialBlockInterval) || Belt_Option.isSome(backoffMultiplicative) || Belt_Option.isSome(accelerationAdditive) || Belt_Option.isSome(intervalCeiling) || Belt_Option.isSome(backoffMillis) || Belt_Option.isSome(queryTimeoutMillis) || Belt_Option.isSome(fallbackStallTimeout);
239
+ var pollingInterval = rpcConfig.pollingInterval;
240
+ var hasSyncConfig = Belt_Option.isSome(initialBlockInterval) || Belt_Option.isSome(backoffMultiplicative) || Belt_Option.isSome(accelerationAdditive) || Belt_Option.isSome(intervalCeiling) || Belt_Option.isSome(backoffMillis) || Belt_Option.isSome(queryTimeoutMillis) || Belt_Option.isSome(fallbackStallTimeout) || Belt_Option.isSome(pollingInterval);
239
241
  var syncConfig = hasSyncConfig ? ({
240
242
  initialBlockInterval: initialBlockInterval,
241
243
  backoffMultiplicative: backoffMultiplicative,
@@ -243,7 +245,8 @@ function fromPublic(publicConfigJson, codegenChainsOpt, maxAddrInPartitionOpt, u
243
245
  intervalCeiling: intervalCeiling,
244
246
  backoffMillis: backoffMillis,
245
247
  queryTimeoutMillis: queryTimeoutMillis,
246
- fallbackStallTimeout: fallbackStallTimeout
248
+ fallbackStallTimeout: fallbackStallTimeout,
249
+ pollingInterval: pollingInterval
247
250
  }) : undefined;
248
251
  return {
249
252
  url: rpcConfig.url,
@@ -159,7 +159,6 @@ let updateChainMetadataTable = (
159
159
  chainsData->Js.Dict.set(
160
160
  cf.chainConfig.id->Belt.Int.toString,
161
161
  {
162
- blockHeight: cf.fetchState.knownHeight,
163
162
  firstEventBlockNumber: cf.firstEventBlockNumber->Js.Null.fromOption,
164
163
  isHyperSync: (cf.sourceManager->SourceManager.getActiveSource).poweredByHyperSync,
165
164
  latestFetchedBlockNumber: cf.fetchState->FetchState.bufferBlockNumber,
@@ -127,7 +127,6 @@ function updateChainMetadataTable(cm, persistence, throttler) {
127
127
  chainsData[String(cf.chainConfig.id)] = {
128
128
  first_event_block: Js_null.fromOption(cf.firstEventBlockNumber),
129
129
  buffer_block: FetchState.bufferBlockNumber(cf.fetchState),
130
- source_block: cf.fetchState.knownHeight,
131
130
  ready_at: Js_null.fromOption(cf.timestampCaughtUpToHeadOrEndblock),
132
131
  _is_hyper_sync: SourceManager.getActiveSource(cf.sourceManager).poweredByHyperSync,
133
132
  _num_batches_fetched: cf.numBatchesFetched
package/src/PgStorage.res CHANGED
@@ -933,6 +933,7 @@ let rec writeBatch = async (
933
933
  ): InternalTable.Chains.progressedChain => {
934
934
  chainId: chainAfterBatch.fetchState.chainId,
935
935
  progressBlockNumber: chainAfterBatch.progressBlockNumber,
936
+ sourceBlockNumber: chainAfterBatch.sourceBlockNumber,
936
937
  totalEventsProcessed: chainAfterBatch.totalEventsProcessed,
937
938
  }),
938
939
  ),
@@ -635,6 +635,7 @@ async function writeBatch(sql, batch, rawEvents, pgSchema, rollbackTargetCheckpo
635
635
  return {
636
636
  chainId: chainAfterBatch.fetchState.chainId,
637
637
  progressBlockNumber: chainAfterBatch.progressBlockNumber,
638
+ sourceBlockNumber: chainAfterBatch.sourceBlockNumber,
638
639
  totalEventsProcessed: chainAfterBatch.totalEventsProcessed
639
640
  };
640
641
  })));
@@ -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
 
@@ -183,30 +183,30 @@ module GetBlockHeight = {
183
183
  module GetTransactionByHash = {
184
184
  let transactionSchema = S.object((s): Internal.evmTransactionFields => {
185
185
  // We already know the data so ignore the fields
186
- // blockHash: ?s.field("blockHash", S.option(S.string)),
187
- // blockNumber: ?s.field("blockNumber", S.option(hexIntSchema)),
188
- // chainId: ?s.field("chainId", S.option(hexIntSchema)),
189
- from: ?s.field("from", S.option(S.string->(Utils.magic: S.t<string> => S.t<Address.t>))),
190
- to: ?s.field("to", S.option(S.string->(Utils.magic: S.t<string> => S.t<Address.t>))),
191
- gas: ?s.field("gas", S.option(hexBigintSchema)),
192
- gasPrice: ?s.field("gasPrice", S.option(hexBigintSchema)),
193
- hash: ?s.field("hash", S.option(S.string)),
194
- input: ?s.field("input", S.option(S.string)),
195
- nonce: ?s.field("nonce", S.option(hexBigintSchema)),
196
- transactionIndex: ?s.field("transactionIndex", S.option(hexIntSchema)),
197
- value: ?s.field("value", S.option(hexBigintSchema)),
198
- type_: ?s.field("type", S.option(hexIntSchema)),
186
+ // blockHash: ?s.field("blockHash", S.nullable(S.string)),
187
+ // blockNumber: ?s.field("blockNumber", S.nullable(hexIntSchema)),
188
+ // chainId: ?s.field("chainId", S.nullable(hexIntSchema)),
189
+ from: ?s.field("from", S.nullable(S.string->(Utils.magic: S.t<string> => S.t<Address.t>))),
190
+ to: ?s.field("to", S.nullable(S.string->(Utils.magic: S.t<string> => S.t<Address.t>))),
191
+ gas: ?s.field("gas", S.nullable(hexBigintSchema)),
192
+ gasPrice: ?s.field("gasPrice", S.nullable(hexBigintSchema)),
193
+ hash: ?s.field("hash", S.nullable(S.string)),
194
+ input: ?s.field("input", S.nullable(S.string)),
195
+ nonce: ?s.field("nonce", S.nullable(hexBigintSchema)),
196
+ transactionIndex: ?s.field("transactionIndex", S.nullable(hexIntSchema)),
197
+ value: ?s.field("value", S.nullable(hexBigintSchema)),
198
+ type_: ?s.field("type", S.nullable(hexIntSchema)),
199
199
  // Signature fields - optional for ZKSync EIP-712 compatibility
200
- v: ?s.field("v", S.option(S.string)),
201
- r: ?s.field("r", S.option(S.string)),
202
- s: ?s.field("s", S.option(S.string)),
203
- yParity: ?s.field("yParity", S.option(S.string)),
200
+ v: ?s.field("v", S.nullable(S.string)),
201
+ r: ?s.field("r", S.nullable(S.string)),
202
+ s: ?s.field("s", S.nullable(S.string)),
203
+ yParity: ?s.field("yParity", S.nullable(S.string)),
204
204
  // EIP-1559 fields
205
- maxPriorityFeePerGas: ?s.field("maxPriorityFeePerGas", S.option(hexBigintSchema)),
206
- maxFeePerGas: ?s.field("maxFeePerGas", S.option(hexBigintSchema)),
205
+ maxPriorityFeePerGas: ?s.field("maxPriorityFeePerGas", S.nullable(hexBigintSchema)),
206
+ maxFeePerGas: ?s.field("maxFeePerGas", S.nullable(hexBigintSchema)),
207
207
  // EIP-4844 blob fields
208
- maxFeePerBlobGas: ?s.field("maxFeePerBlobGas", S.option(hexBigintSchema)),
209
- blobVersionedHashes: ?s.field("blobVersionedHashes", S.option(S.array(S.string))),
208
+ maxFeePerBlobGas: ?s.field("maxFeePerBlobGas", S.nullable(hexBigintSchema)),
209
+ blobVersionedHashes: ?s.field("blobVersionedHashes", S.nullable(S.array(S.string))),
210
210
  // TODO: Fields to add:
211
211
  // pub access_list: Option<Vec<AccessList>>,
212
212
  // pub authorization_list: Option<Vec<Authorization>>,
@@ -189,24 +189,24 @@ var GetBlockHeight = {
189
189
 
190
190
  var transactionSchema = S$RescriptSchema.object(function (s) {
191
191
  return {
192
- from: s.f("from", S$RescriptSchema.option(S$RescriptSchema.string)),
193
- to: s.f("to", S$RescriptSchema.option(S$RescriptSchema.string)),
194
- gas: s.f("gas", S$RescriptSchema.option(hexBigintSchema)),
195
- gasPrice: s.f("gasPrice", S$RescriptSchema.option(hexBigintSchema)),
196
- hash: s.f("hash", S$RescriptSchema.option(S$RescriptSchema.string)),
197
- input: s.f("input", S$RescriptSchema.option(S$RescriptSchema.string)),
198
- nonce: s.f("nonce", S$RescriptSchema.option(hexBigintSchema)),
199
- transactionIndex: s.f("transactionIndex", S$RescriptSchema.option(hexIntSchema)),
200
- value: s.f("value", S$RescriptSchema.option(hexBigintSchema)),
201
- v: s.f("v", S$RescriptSchema.option(S$RescriptSchema.string)),
202
- r: s.f("r", S$RescriptSchema.option(S$RescriptSchema.string)),
203
- s: s.f("s", S$RescriptSchema.option(S$RescriptSchema.string)),
204
- yParity: s.f("yParity", S$RescriptSchema.option(S$RescriptSchema.string)),
205
- maxPriorityFeePerGas: s.f("maxPriorityFeePerGas", S$RescriptSchema.option(hexBigintSchema)),
206
- maxFeePerGas: s.f("maxFeePerGas", S$RescriptSchema.option(hexBigintSchema)),
207
- maxFeePerBlobGas: s.f("maxFeePerBlobGas", S$RescriptSchema.option(hexBigintSchema)),
208
- blobVersionedHashes: s.f("blobVersionedHashes", S$RescriptSchema.option(S$RescriptSchema.array(S$RescriptSchema.string))),
209
- type: s.f("type", S$RescriptSchema.option(hexIntSchema))
192
+ from: s.f("from", S$RescriptSchema.nullable(S$RescriptSchema.string)),
193
+ to: s.f("to", S$RescriptSchema.nullable(S$RescriptSchema.string)),
194
+ gas: s.f("gas", S$RescriptSchema.nullable(hexBigintSchema)),
195
+ gasPrice: s.f("gasPrice", S$RescriptSchema.nullable(hexBigintSchema)),
196
+ hash: s.f("hash", S$RescriptSchema.nullable(S$RescriptSchema.string)),
197
+ input: s.f("input", S$RescriptSchema.nullable(S$RescriptSchema.string)),
198
+ nonce: s.f("nonce", S$RescriptSchema.nullable(hexBigintSchema)),
199
+ transactionIndex: s.f("transactionIndex", S$RescriptSchema.nullable(hexIntSchema)),
200
+ value: s.f("value", S$RescriptSchema.nullable(hexBigintSchema)),
201
+ v: s.f("v", S$RescriptSchema.nullable(S$RescriptSchema.string)),
202
+ r: s.f("r", S$RescriptSchema.nullable(S$RescriptSchema.string)),
203
+ s: s.f("s", S$RescriptSchema.nullable(S$RescriptSchema.string)),
204
+ yParity: s.f("yParity", S$RescriptSchema.nullable(S$RescriptSchema.string)),
205
+ maxPriorityFeePerGas: s.f("maxPriorityFeePerGas", S$RescriptSchema.nullable(hexBigintSchema)),
206
+ maxFeePerGas: s.f("maxFeePerGas", S$RescriptSchema.nullable(hexBigintSchema)),
207
+ maxFeePerBlobGas: s.f("maxFeePerBlobGas", S$RescriptSchema.nullable(hexBigintSchema)),
208
+ blobVersionedHashes: s.f("blobVersionedHashes", S$RescriptSchema.nullable(S$RescriptSchema.array(S$RescriptSchema.string))),
209
+ type: s.f("type", S$RescriptSchema.nullable(hexIntSchema))
210
210
  };
211
211
  });
212
212
 
@@ -16,49 +16,50 @@ let getKnownBlock = (provider, blockNumber) =>
16
16
  }
17
17
  )
18
18
 
19
- let rec getKnownBlockWithBackoff = async (
19
+ let getKnownBlockWithBackoff = async (
20
20
  ~provider,
21
21
  ~sourceName,
22
22
  ~chain,
23
23
  ~blockNumber,
24
24
  ~backoffMsOnFailure,
25
25
  ~lowercaseAddresses: bool,
26
- ) =>
27
- switch await getKnownBlock(provider, blockNumber) {
28
- | exception err =>
29
- Logging.warn({
30
- "err": err->Utils.prettifyExn,
31
- "msg": `Issue while running fetching batch of events from the RPC. Will wait ${backoffMsOnFailure->Belt.Int.toString}ms and try again.`,
32
- "source": sourceName,
33
- "chainId": chain->ChainMap.Chain.toChainId,
34
- "type": "EXPONENTIAL_BACKOFF",
35
- })
36
- await Time.resolvePromiseAfterDelay(~delayMilliseconds=backoffMsOnFailure)
37
- await getKnownBlockWithBackoff(
38
- ~provider,
39
- ~sourceName,
40
- ~chain,
41
- ~blockNumber,
42
- ~backoffMsOnFailure=backoffMsOnFailure * 2,
43
- ~lowercaseAddresses,
44
- )
45
- | result =>
46
- if lowercaseAddresses {
26
+ ) => {
27
+ let currentBackoff = ref(backoffMsOnFailure)
28
+ let result = ref(None)
29
+
30
+ while result.contents->Option.isNone {
31
+ Prometheus.SourceRequestCount.increment(~sourceName, ~chainId=chain->ChainMap.Chain.toChainId)
32
+ switch await getKnownBlock(provider, blockNumber) {
33
+ | exception err =>
34
+ Logging.warn({
35
+ "err": err->Utils.prettifyExn,
36
+ "msg": `Issue while running fetching batch of events from the RPC. Will wait ${currentBackoff.contents->Belt.Int.toString}ms and try again.`,
37
+ "source": sourceName,
38
+ "chainId": chain->ChainMap.Chain.toChainId,
39
+ "type": "EXPONENTIAL_BACKOFF",
40
+ })
41
+ await Time.resolvePromiseAfterDelay(~delayMilliseconds=currentBackoff.contents)
42
+ currentBackoff := currentBackoff.contents * 2
43
+ | block =>
47
44
  // NOTE: this is wasteful if these fields are not selected in the users config.
48
45
  // There might be a better way to do this based on the block schema.
49
46
  // However this is not extremely expensive and good enough for now (only on rpc sync also).
50
-
51
- {
52
- ...result,
53
- // Mutation would be cheaper,
54
- // BUT "result" is an Ethers.js Block object,
55
- // which has the fields as readonly.
56
- miner: result.miner->Address.Evm.fromAddressLowercaseOrThrow,
57
- }
58
- } else {
59
- result
47
+ // Mutation would be cheaper,
48
+ // BUT "block" is an Ethers.js Block object,
49
+ // which has the fields as readonly.
50
+ result :=
51
+ Some({
52
+ ...block,
53
+ miner: if lowercaseAddresses {
54
+ block.miner->Address.Evm.fromAddressLowercaseOrThrow
55
+ } else {
56
+ block.miner->Address.Evm.fromAddressOrThrow
57
+ },
58
+ })
60
59
  }
61
60
  }
61
+ result.contents->Option.getExn
62
+ }
62
63
  let getSuggestedBlockIntervalFromExn = {
63
64
  // Unknown provider: "retry with the range 123-456"
64
65
  let suggestedRangeRegExp = %re(`/retry with the range (\d+)-(\d+)/`)
@@ -505,8 +506,7 @@ let make = (
505
506
 
506
507
  let makeBlockLoader = () =>
507
508
  LazyLoader.make(
508
- ~loaderFn=blockNumber => {
509
- Prometheus.SourceRequestCount.increment(~sourceName=name, ~chainId=chain->ChainMap.Chain.toChainId)
509
+ ~loaderFn=blockNumber =>
510
510
  getKnownBlockWithBackoff(
511
511
  ~provider,
512
512
  ~sourceName=name,
@@ -514,8 +514,7 @@ let make = (
514
514
  ~backoffMsOnFailure=1000,
515
515
  ~blockNumber,
516
516
  ~lowercaseAddresses,
517
- )
518
- },
517
+ ),
519
518
  ~onError=(am, ~exn) => {
520
519
  Logging.error({
521
520
  "err": exn->Utils.prettifyExn,
@@ -682,7 +681,7 @@ let make = (
682
681
  let routedAddress = if lowercaseAddresses {
683
682
  log.address->Address.Evm.fromAddressLowercaseOrThrow
684
683
  } else {
685
- log.address
684
+ log.address->Address.Evm.fromAddressOrThrow
686
685
  }
687
686
 
688
687
  switch eventRouter->EventRouter.get(
@@ -804,7 +803,7 @@ let make = (
804
803
  sourceFor,
805
804
  chain,
806
805
  poweredByHyperSync: false,
807
- pollingInterval: 1000,
806
+ pollingInterval: syncConfig.pollingInterval,
808
807
  getBlockHashes,
809
808
  getHeightOrThrow: () => {
810
809
  Prometheus.SourceRequestCount.increment(~sourceName=name, ~chainId=chain->ChainMap.Chain.toChainId)
@@ -40,40 +40,47 @@ function getKnownBlock(provider, blockNumber) {
40
40
  }
41
41
 
42
42
  async function getKnownBlockWithBackoff(provider, sourceName, chain, blockNumber, backoffMsOnFailure, lowercaseAddresses) {
43
+ var currentBackoff = backoffMsOnFailure;
43
44
  var result;
44
- try {
45
- result = await getKnownBlock(provider, blockNumber);
46
- }
47
- catch (raw_err){
48
- var err = Caml_js_exceptions.internalToOCamlException(raw_err);
49
- Logging.warn({
50
- err: Utils.prettifyExn(err),
51
- msg: "Issue while running fetching batch of events from the RPC. Will wait " + String(backoffMsOnFailure) + "ms and try again.",
52
- source: sourceName,
53
- chainId: chain,
54
- type: "EXPONENTIAL_BACKOFF"
55
- });
56
- await Time.resolvePromiseAfterDelay(backoffMsOnFailure);
57
- return await getKnownBlockWithBackoff(provider, sourceName, chain, blockNumber, (backoffMsOnFailure << 1), lowercaseAddresses);
58
- }
59
- if (lowercaseAddresses) {
60
- return {
61
- _difficulty: result._difficulty,
62
- difficulty: result.difficulty,
63
- extraData: result.extraData,
64
- gasLimit: result.gasLimit,
65
- gasUsed: result.gasUsed,
66
- hash: result.hash,
67
- miner: Address.Evm.fromAddressLowercaseOrThrow(result.miner),
68
- nonce: result.nonce,
69
- number: result.number,
70
- parentHash: result.parentHash,
71
- timestamp: result.timestamp,
72
- transactions: result.transactions
73
- };
74
- } else {
75
- return result;
76
- }
45
+ while(Belt_Option.isNone(result)) {
46
+ Prometheus.SourceRequestCount.increment(sourceName, chain);
47
+ var exit = 0;
48
+ var block;
49
+ try {
50
+ block = await getKnownBlock(provider, blockNumber);
51
+ exit = 1;
52
+ }
53
+ catch (raw_err){
54
+ var err = Caml_js_exceptions.internalToOCamlException(raw_err);
55
+ Logging.warn({
56
+ err: Utils.prettifyExn(err),
57
+ msg: "Issue while running fetching batch of events from the RPC. Will wait " + String(currentBackoff) + "ms and try again.",
58
+ source: sourceName,
59
+ chainId: chain,
60
+ type: "EXPONENTIAL_BACKOFF"
61
+ });
62
+ await Time.resolvePromiseAfterDelay(currentBackoff);
63
+ currentBackoff = (currentBackoff << 1);
64
+ }
65
+ if (exit === 1) {
66
+ result = {
67
+ _difficulty: block._difficulty,
68
+ difficulty: block.difficulty,
69
+ extraData: block.extraData,
70
+ gasLimit: block.gasLimit,
71
+ gasUsed: block.gasUsed,
72
+ hash: block.hash,
73
+ miner: lowercaseAddresses ? Address.Evm.fromAddressLowercaseOrThrow(block.miner) : Address.Evm.fromAddressOrThrow(block.miner),
74
+ nonce: block.nonce,
75
+ number: block.number,
76
+ parentHash: block.parentHash,
77
+ timestamp: block.timestamp,
78
+ transactions: block.transactions
79
+ };
80
+ }
81
+
82
+ };
83
+ return Belt_Option.getExn(result);
77
84
  }
78
85
 
79
86
  var suggestedRangeRegExp = /retry with the range (\d+)-(\d+)/;
@@ -525,7 +532,6 @@ function make(param) {
525
532
  };
526
533
  var makeBlockLoader = function () {
527
534
  return LazyLoader.make((function (blockNumber) {
528
- Prometheus.SourceRequestCount.increment(name, chain);
529
535
  return getKnownBlockWithBackoff(provider, name, chain, blockNumber, 1000, lowercaseAddresses);
530
536
  }), (function (am, exn) {
531
537
  Logging.error({
@@ -640,7 +646,7 @@ function make(param) {
640
646
  var maybeDecodedEvent = param[1];
641
647
  var log = param[0];
642
648
  var topic0 = Belt_Option.getWithDefault(Belt_Array.get(log.topics, 0), "0x0");
643
- var routedAddress = lowercaseAddresses ? Address.Evm.fromAddressLowercaseOrThrow(log.address) : log.address;
649
+ var routedAddress = lowercaseAddresses ? Address.Evm.fromAddressLowercaseOrThrow(log.address) : Address.Evm.fromAddressOrThrow(log.address);
644
650
  var eventConfig = EventRouter.get(eventRouter, EventRouter.getEvmEventId(topic0, log.topics.length), routedAddress, log.blockNumber, indexingContracts);
645
651
  if (eventConfig !== undefined && !(maybeDecodedEvent === null || maybeDecodedEvent === undefined)) {
646
652
  return Caml_option.some((async function () {
@@ -742,7 +748,7 @@ function make(param) {
742
748
  sourceFor: param.sourceFor,
743
749
  chain: chain,
744
750
  poweredByHyperSync: false,
745
- pollingInterval: 1000,
751
+ pollingInterval: syncConfig.pollingInterval,
746
752
  getBlockHashes: getBlockHashes,
747
753
  getHeightOrThrow: (function () {
748
754
  Prometheus.SourceRequestCount.increment(name, chain);