envio 2.31.0 → 2.31.1-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "envio",
3
- "version": "v2.31.0",
3
+ "version": "v2.31.1-rc.0",
4
4
  "description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
5
5
  "bin": "./bin.js",
6
6
  "main": "./index.js",
@@ -25,10 +25,10 @@
25
25
  },
26
26
  "homepage": "https://envio.dev",
27
27
  "optionalDependencies": {
28
- "envio-linux-x64": "v2.31.0",
29
- "envio-linux-arm64": "v2.31.0",
30
- "envio-darwin-x64": "v2.31.0",
31
- "envio-darwin-arm64": "v2.31.0"
28
+ "envio-linux-x64": "v2.31.1-rc.0",
29
+ "envio-linux-arm64": "v2.31.1-rc.0",
30
+ "envio-darwin-x64": "v2.31.1-rc.0",
31
+ "envio-darwin-arm64": "v2.31.1-rc.0"
32
32
  },
33
33
  "dependencies": {
34
34
  "@envio-dev/hypersync-client": "0.6.6",
@@ -37,8 +37,6 @@ let reorgDetectedToLogParams = (reorgDetected: reorgDetected, ~shouldRollbackOnR
37
37
  }
38
38
 
39
39
  type reorgResult = NoReorg | ReorgDetected(reorgDetected)
40
- type validBlockError = NotFound | AlreadyReorgedHashes
41
- type validBlockResult = result<blockDataWithTimestamp, validBlockError>
42
40
 
43
41
  type t = {
44
42
  // Whether to rollback on reorg
@@ -186,14 +184,13 @@ let registerReorgGuard = (
186
184
  }
187
185
 
188
186
  /**
189
- Returns the latest block data which matches block number and hashes in the provided array
190
- If it doesn't exist in the reorg threshold it returns None or the latest scanned block outside of the reorg threshold
187
+ Returns the latest block number which matches block number and hashes in the provided array
188
+ If it doesn't exist in the reorg threshold it returns NotFound
191
189
  */
192
190
  let getLatestValidScannedBlock = (
193
191
  self: t,
194
192
  ~blockNumbersAndHashes: array<blockDataWithTimestamp>,
195
193
  ~currentBlockHeight,
196
- ~skipReorgDuplicationCheck=false,
197
194
  ) => {
198
195
  let verifiedDataByBlockNumber = Js.Dict.empty()
199
196
  for idx in 0 to blockNumbersAndHashes->Array.length - 1 {
@@ -201,68 +198,38 @@ let getLatestValidScannedBlock = (
201
198
  verifiedDataByBlockNumber->Js.Dict.set(blockData.blockNumber->Int.toString, blockData)
202
199
  }
203
200
 
204
- /*
205
- Let's say we indexed block X with hash A.
206
- The next query we got the block X with hash B.
207
- We assume that the hash A is reorged since we received it earlier than B.
208
- So when we try to detect the reorg depth, we consider hash A as already invalid,
209
- and retry the block hashes query if we receive one. (since it could come from a different instance and cause a double reorg)
210
- But the assumption that A is reorged might be wrong sometimes,
211
- for example if we got B from instance which didn't handle a reorg A.
212
- Theoretically, it's possible with high partition concurrency.
213
- So to handle this and prevent entering an infinite loop,
214
- we can skip the reorg duplication check if we're sure that the block hashes query
215
- is not coming from a different instance. (let's say we tried several times)
216
- */
217
- let isAlreadyReorgedResponse = skipReorgDuplicationCheck
218
- ? false
219
- : switch self.detectedReorgBlock {
220
- | Some(detectedReorgBlock) =>
221
- switch verifiedDataByBlockNumber->Utils.Dict.dangerouslyGetNonOption(
222
- detectedReorgBlock.blockNumber->Int.toString,
223
- ) {
224
- | Some(verifiedBlockData) => verifiedBlockData.blockHash === detectedReorgBlock.blockHash
225
- | None => false
226
- }
227
- | None => false
228
- }
201
+ let dataByBlockNumber = self->getDataByBlockNumberCopyInThreshold(~currentBlockHeight)
202
+ // Js engine automatically orders numeric object keys
203
+ let ascBlockNumberKeys = dataByBlockNumber->Js.Dict.keys
229
204
 
230
- if isAlreadyReorgedResponse {
231
- Error(AlreadyReorgedHashes)
232
- } else {
233
- let dataByBlockNumber = self->getDataByBlockNumberCopyInThreshold(~currentBlockHeight)
234
- // Js engine automatically orders numeric object keys
235
- let ascBlockNumberKeys = dataByBlockNumber->Js.Dict.keys
236
-
237
- let getPrevScannedBlock = idx =>
238
- switch ascBlockNumberKeys
239
- ->Belt.Array.get(idx - 1)
240
- ->Option.flatMap(key => {
241
- // We should already validate that the block number is verified at the point
242
- verifiedDataByBlockNumber->Utils.Dict.dangerouslyGetNonOption(key)
243
- }) {
244
- | Some(data) => Ok(data)
245
- | None => Error(NotFound)
205
+ let getPrevScannedBlockNumber = idx =>
206
+ ascBlockNumberKeys
207
+ ->Belt.Array.get(idx - 1)
208
+ ->Option.flatMap(key => {
209
+ // We should already validate that the block number is verified at the point
210
+ switch verifiedDataByBlockNumber->Utils.Dict.dangerouslyGetNonOption(key) {
211
+ | Some(v) => Some(v.blockNumber)
212
+ | None => None
246
213
  }
214
+ })
247
215
 
248
- let rec loop = idx => {
249
- switch ascBlockNumberKeys->Belt.Array.get(idx) {
250
- | Some(blockNumberKey) =>
251
- let scannedBlock = dataByBlockNumber->Js.Dict.unsafeGet(blockNumberKey)
252
- switch verifiedDataByBlockNumber->Utils.Dict.dangerouslyGetNonOption(blockNumberKey) {
253
- | None =>
254
- Js.Exn.raiseError(
255
- `Unexpected case. Couldn't find verified hash for block number ${blockNumberKey}`,
256
- )
257
- | Some(verifiedBlockData) if verifiedBlockData.blockHash === scannedBlock.blockHash =>
258
- loop(idx + 1)
259
- | Some(_) => getPrevScannedBlock(idx)
260
- }
261
- | None => getPrevScannedBlock(idx)
216
+ let rec loop = idx => {
217
+ switch ascBlockNumberKeys->Belt.Array.get(idx) {
218
+ | Some(blockNumberKey) =>
219
+ let scannedBlock = dataByBlockNumber->Js.Dict.unsafeGet(blockNumberKey)
220
+ switch verifiedDataByBlockNumber->Utils.Dict.dangerouslyGetNonOption(blockNumberKey) {
221
+ | None =>
222
+ Js.Exn.raiseError(
223
+ `Unexpected case. Couldn't find verified hash for block number ${blockNumberKey}`,
224
+ )
225
+ | Some(verifiedBlockData) if verifiedBlockData.blockHash === scannedBlock.blockHash =>
226
+ loop(idx + 1)
227
+ | Some(_) => getPrevScannedBlockNumber(idx)
262
228
  }
229
+ | None => getPrevScannedBlockNumber(idx)
263
230
  }
264
- loop(0)
265
231
  }
232
+ loop(0)
266
233
  }
267
234
 
268
235
  /**
@@ -303,11 +270,22 @@ let rollbackToValidBlockNumber = (
303
270
  }
304
271
  }
305
272
 
306
- let getThresholdBlockNumbers = (self: t, ~currentBlockHeight) => {
307
- let dataByBlockNumberCopyInThreshold =
308
- self->getDataByBlockNumberCopyInThreshold(~currentBlockHeight)
273
+ let getThresholdBlockNumbersBelowBlock = (self: t, ~blockNumber: int, ~currentBlockHeight) => {
274
+ let arr = []
275
+
276
+ // Js engine automatically orders numeric object keys
277
+ let ascBlockNumberKeys = self.dataByBlockNumber->Js.Dict.keys
278
+ let thresholdBlockNumber = currentBlockHeight - self.maxReorgDepth
309
279
 
310
- dataByBlockNumberCopyInThreshold->Js.Dict.values->Js.Array2.map(v => v.blockNumber)
280
+ for idx in 0 to ascBlockNumberKeys->Array.length - 1 {
281
+ let blockNumberKey = ascBlockNumberKeys->Js.Array2.unsafe_get(idx)
282
+ let scannedBlock = self.dataByBlockNumber->Js.Dict.unsafeGet(blockNumberKey)
283
+ let isInReorgThreshold = scannedBlock.blockNumber >= thresholdBlockNumber
284
+ if isInReorgThreshold && scannedBlock.blockNumber < blockNumber {
285
+ arr->Array.push(scannedBlock.blockNumber)
286
+ }
287
+ }
288
+ arr
311
289
  }
312
290
 
313
291
  let getHashByBlockNumber = (reorgDetection: t, ~blockNumber) => {
@@ -2,7 +2,6 @@
2
2
  'use strict';
3
3
 
4
4
  var Js_exn = require("rescript/lib/js/js_exn.js");
5
- var Js_dict = require("rescript/lib/js/js_dict.js");
6
5
  var Belt_Array = require("rescript/lib/js/belt_Array.js");
7
6
  var Belt_Option = require("rescript/lib/js/belt_Option.js");
8
7
 
@@ -109,63 +108,37 @@ function registerReorgGuard(self, reorgGuard, currentBlockHeight) {
109
108
  }
110
109
  }
111
110
 
112
- function getLatestValidScannedBlock(self, blockNumbersAndHashes, currentBlockHeight, skipReorgDuplicationCheckOpt) {
113
- var skipReorgDuplicationCheck = skipReorgDuplicationCheckOpt !== undefined ? skipReorgDuplicationCheckOpt : false;
111
+ function getLatestValidScannedBlock(self, blockNumbersAndHashes, currentBlockHeight) {
114
112
  var verifiedDataByBlockNumber = {};
115
113
  for(var idx = 0 ,idx_finish = blockNumbersAndHashes.length; idx < idx_finish; ++idx){
116
114
  var blockData = blockNumbersAndHashes[idx];
117
115
  verifiedDataByBlockNumber[String(blockData.blockNumber)] = blockData;
118
116
  }
119
- var isAlreadyReorgedResponse;
120
- if (skipReorgDuplicationCheck) {
121
- isAlreadyReorgedResponse = false;
122
- } else {
123
- var detectedReorgBlock = self.detectedReorgBlock;
124
- if (detectedReorgBlock !== undefined) {
125
- var verifiedBlockData = verifiedDataByBlockNumber[String(detectedReorgBlock.blockNumber)];
126
- isAlreadyReorgedResponse = verifiedBlockData !== undefined ? verifiedBlockData.blockHash === detectedReorgBlock.blockHash : false;
127
- } else {
128
- isAlreadyReorgedResponse = false;
129
- }
130
- }
131
- if (isAlreadyReorgedResponse) {
132
- return {
133
- TAG: "Error",
134
- _0: "AlreadyReorgedHashes"
135
- };
136
- }
137
117
  var dataByBlockNumber = getDataByBlockNumberCopyInThreshold(self, currentBlockHeight);
138
118
  var ascBlockNumberKeys = Object.keys(dataByBlockNumber);
139
- var getPrevScannedBlock = function (idx) {
140
- var data = Belt_Option.flatMap(Belt_Array.get(ascBlockNumberKeys, idx - 1 | 0), (function (key) {
141
- return verifiedDataByBlockNumber[key];
142
- }));
143
- if (data !== undefined) {
144
- return {
145
- TAG: "Ok",
146
- _0: data
147
- };
148
- } else {
149
- return {
150
- TAG: "Error",
151
- _0: "NotFound"
152
- };
153
- }
119
+ var getPrevScannedBlockNumber = function (idx) {
120
+ return Belt_Option.flatMap(Belt_Array.get(ascBlockNumberKeys, idx - 1 | 0), (function (key) {
121
+ var v = verifiedDataByBlockNumber[key];
122
+ if (v !== undefined) {
123
+ return v.blockNumber;
124
+ }
125
+
126
+ }));
154
127
  };
155
128
  var _idx = 0;
156
129
  while(true) {
157
130
  var idx$1 = _idx;
158
131
  var blockNumberKey = Belt_Array.get(ascBlockNumberKeys, idx$1);
159
132
  if (blockNumberKey === undefined) {
160
- return getPrevScannedBlock(idx$1);
133
+ return getPrevScannedBlockNumber(idx$1);
161
134
  }
162
135
  var scannedBlock = dataByBlockNumber[blockNumberKey];
163
- var verifiedBlockData$1 = verifiedDataByBlockNumber[blockNumberKey];
164
- if (verifiedBlockData$1 === undefined) {
136
+ var verifiedBlockData = verifiedDataByBlockNumber[blockNumberKey];
137
+ if (verifiedBlockData === undefined) {
165
138
  return Js_exn.raiseError("Unexpected case. Couldn't find verified hash for block number " + blockNumberKey);
166
139
  }
167
- if (verifiedBlockData$1.blockHash !== scannedBlock.blockHash) {
168
- return getPrevScannedBlock(idx$1);
140
+ if (verifiedBlockData.blockHash !== scannedBlock.blockHash) {
141
+ return getPrevScannedBlockNumber(idx$1);
169
142
  }
170
143
  _idx = idx$1 + 1 | 0;
171
144
  continue ;
@@ -202,11 +175,20 @@ function rollbackToValidBlockNumber(param, blockNumber) {
202
175
  };
203
176
  }
204
177
 
205
- function getThresholdBlockNumbers(self, currentBlockHeight) {
206
- var dataByBlockNumberCopyInThreshold = getDataByBlockNumberCopyInThreshold(self, currentBlockHeight);
207
- return Js_dict.values(dataByBlockNumberCopyInThreshold).map(function (v) {
208
- return v.blockNumber;
209
- });
178
+ function getThresholdBlockNumbersBelowBlock(self, blockNumber, currentBlockHeight) {
179
+ var arr = [];
180
+ var ascBlockNumberKeys = Object.keys(self.dataByBlockNumber);
181
+ var thresholdBlockNumber = currentBlockHeight - self.maxReorgDepth | 0;
182
+ for(var idx = 0 ,idx_finish = ascBlockNumberKeys.length; idx < idx_finish; ++idx){
183
+ var blockNumberKey = ascBlockNumberKeys[idx];
184
+ var scannedBlock = self.dataByBlockNumber[blockNumberKey];
185
+ var isInReorgThreshold = scannedBlock.blockNumber >= thresholdBlockNumber;
186
+ if (isInReorgThreshold && scannedBlock.blockNumber < blockNumber) {
187
+ arr.push(scannedBlock.blockNumber);
188
+ }
189
+
190
+ }
191
+ return arr;
210
192
  }
211
193
 
212
194
  function getHashByBlockNumber(reorgDetection, blockNumber) {
@@ -224,6 +206,6 @@ exports.getDataByBlockNumberCopyInThreshold = getDataByBlockNumberCopyInThreshol
224
206
  exports.registerReorgGuard = registerReorgGuard;
225
207
  exports.getLatestValidScannedBlock = getLatestValidScannedBlock;
226
208
  exports.rollbackToValidBlockNumber = rollbackToValidBlockNumber;
227
- exports.getThresholdBlockNumbers = getThresholdBlockNumbers;
209
+ exports.getThresholdBlockNumbersBelowBlock = getThresholdBlockNumbersBelowBlock;
228
210
  exports.getHashByBlockNumber = getHashByBlockNumber;
229
211
  /* No side effect */
@@ -522,35 +522,38 @@ let make = (
522
522
  },
523
523
  )
524
524
 
525
- let blockLoader = LazyLoader.make(
526
- ~loaderFn=blockNumber =>
527
- getKnownBlockWithBackoff(
528
- ~provider,
529
- ~sourceName=name,
530
- ~chain,
531
- ~backoffMsOnFailure=1000,
532
- ~blockNumber,
533
- ~lowercaseAddresses,
534
- ),
535
- ~onError=(am, ~exn) => {
536
- Logging.error({
537
- "err": exn->Utils.prettifyExn,
538
- "msg": `EE1100: Top level promise timeout reached. Please review other errors or warnings in the code. This function will retry in ${(am._retryDelayMillis / 1000)
539
- ->Belt.Int.toString} seconds. It is highly likely that your indexer isn't syncing on one or more chains currently. Also take a look at the "suggestedFix" in the metadata of this command`,
540
- "source": name,
541
- "chainId": chain->ChainMap.Chain.toChainId,
542
- "metadata": {
543
- {
544
- "asyncTaskName": "blockLoader: fetching block data - `getBlock` rpc call",
545
- "suggestedFix": "This likely means the RPC url you are using is not responding correctly. Please try another RPC endipoint.",
546
- }
547
- },
548
- })
549
- },
550
- )
525
+ let makeBlockLoader = () =>
526
+ LazyLoader.make(
527
+ ~loaderFn=blockNumber =>
528
+ getKnownBlockWithBackoff(
529
+ ~provider,
530
+ ~sourceName=name,
531
+ ~chain,
532
+ ~backoffMsOnFailure=1000,
533
+ ~blockNumber,
534
+ ~lowercaseAddresses,
535
+ ),
536
+ ~onError=(am, ~exn) => {
537
+ Logging.error({
538
+ "err": exn->Utils.prettifyExn,
539
+ "msg": `EE1100: Top level promise timeout reached. Please review other errors or warnings in the code. This function will retry in ${(am._retryDelayMillis / 1000)
540
+ ->Belt.Int.toString} seconds. It is highly likely that your indexer isn't syncing on one or more chains currently. Also take a look at the "suggestedFix" in the metadata of this command`,
541
+ "source": name,
542
+ "chainId": chain->ChainMap.Chain.toChainId,
543
+ "metadata": {
544
+ {
545
+ "asyncTaskName": "blockLoader: fetching block data - `getBlock` rpc call",
546
+ "suggestedFix": "This likely means the RPC url you are using is not responding correctly. Please try another RPC endipoint.",
547
+ }
548
+ },
549
+ })
550
+ },
551
+ )
552
+
553
+ let blockLoader = ref(makeBlockLoader())
551
554
 
552
555
  let getEventBlockOrThrow = makeThrowingGetEventBlock(~getBlock=blockNumber =>
553
- blockLoader->LazyLoader.get(blockNumber)
556
+ blockLoader.contents->LazyLoader.get(blockNumber)
554
557
  )
555
558
  let getEventTransactionOrThrow = makeThrowingGetEventTransaction(
556
559
  ~getTransactionFields=Ethers.JsonRpcProvider.makeGetTransactionFields(
@@ -625,7 +628,7 @@ let make = (
625
628
 
626
629
  let firstBlockParentPromise =
627
630
  fromBlock > 0
628
- ? blockLoader->LazyLoader.get(fromBlock - 1)->Promise.thenResolve(res => res->Some)
631
+ ? blockLoader.contents->LazyLoader.get(fromBlock - 1)->Promise.thenResolve(res => res->Some)
629
632
  : Promise.resolve(None)
630
633
 
631
634
  let {getLogSelectionOrThrow} = getSelectionConfig(selection)
@@ -636,7 +639,7 @@ let make = (
636
639
  ~toBlock=suggestedToBlock,
637
640
  ~addresses,
638
641
  ~topicQuery,
639
- ~loadBlock=blockNumber => blockLoader->LazyLoader.get(blockNumber),
642
+ ~loadBlock=blockNumber => blockLoader.contents->LazyLoader.get(blockNumber),
640
643
  ~syncConfig,
641
644
  ~provider,
642
645
  ~mutSuggestedBlockIntervals,
@@ -873,8 +876,13 @@ let make = (
873
876
  }
874
877
 
875
878
  let getBlockHashes = (~blockNumbers, ~logger as _currentlyUnusedLogger) => {
879
+ // Clear cache by creating a fresh LazyLoader
880
+ // This is important, since we call this
881
+ // function when a reorg is detected
882
+ blockLoader := makeBlockLoader()
883
+
876
884
  blockNumbers
877
- ->Array.map(blockNum => blockLoader->LazyLoader.get(blockNum))
885
+ ->Array.map(blockNum => blockLoader.contents->LazyLoader.get(blockNum))
878
886
  ->Promise.all
879
887
  ->Promise.thenResolve(blocks => {
880
888
  blocks
@@ -533,22 +533,27 @@ function make(param) {
533
533
  }
534
534
  });
535
535
  }), undefined, undefined, undefined, undefined);
536
- var blockLoader = LazyLoader.make((function (blockNumber) {
537
- return getKnownBlockWithBackoff(provider, name, chain, blockNumber, 1000, lowercaseAddresses);
538
- }), (function (am, exn) {
539
- Logging.error({
540
- err: Utils.prettifyExn(exn),
541
- msg: "EE1100: Top level promise timeout reached. Please review other errors or warnings in the code. This function will retry in " + String(am._retryDelayMillis / 1000 | 0) + " seconds. It is highly likely that your indexer isn't syncing on one or more chains currently. Also take a look at the \"suggestedFix\" in the metadata of this command",
542
- source: name,
543
- chainId: chain,
544
- metadata: {
545
- asyncTaskName: "blockLoader: fetching block data - `getBlock` rpc call",
546
- suggestedFix: "This likely means the RPC url you are using is not responding correctly. Please try another RPC endipoint."
547
- }
548
- });
549
- }), undefined, undefined, undefined, undefined);
536
+ var makeBlockLoader = function () {
537
+ return LazyLoader.make((function (blockNumber) {
538
+ return getKnownBlockWithBackoff(provider, name, chain, blockNumber, 1000, lowercaseAddresses);
539
+ }), (function (am, exn) {
540
+ Logging.error({
541
+ err: Utils.prettifyExn(exn),
542
+ msg: "EE1100: Top level promise timeout reached. Please review other errors or warnings in the code. This function will retry in " + String(am._retryDelayMillis / 1000 | 0) + " seconds. It is highly likely that your indexer isn't syncing on one or more chains currently. Also take a look at the \"suggestedFix\" in the metadata of this command",
543
+ source: name,
544
+ chainId: chain,
545
+ metadata: {
546
+ asyncTaskName: "blockLoader: fetching block data - `getBlock` rpc call",
547
+ suggestedFix: "This likely means the RPC url you are using is not responding correctly. Please try another RPC endipoint."
548
+ }
549
+ });
550
+ }), undefined, undefined, undefined, undefined);
551
+ };
552
+ var blockLoader = {
553
+ contents: makeBlockLoader()
554
+ };
550
555
  var getEventBlockOrThrow = makeThrowingGetEventBlock(function (blockNumber) {
551
- return LazyLoader.get(blockLoader, blockNumber);
556
+ return LazyLoader.get(blockLoader.contents, blockNumber);
552
557
  });
553
558
  var getEventTransactionOrThrow = makeThrowingGetEventTransaction(Ethers.JsonRpcProvider.makeGetTransactionFields((function (__x) {
554
559
  return LazyLoader.get(transactionLoader, __x);
@@ -601,13 +606,13 @@ function make(param) {
601
606
  var suggestedBlockInterval = maxSuggestedBlockInterval !== undefined ? maxSuggestedBlockInterval : Belt_Option.getWithDefault(mutSuggestedBlockIntervals[partitionId], syncConfig.initialBlockInterval);
602
607
  var toBlock$1 = toBlock !== undefined && toBlock < currentBlockHeight ? toBlock : currentBlockHeight;
603
608
  var suggestedToBlock = Caml.int_max(Caml.int_min((fromBlock + suggestedBlockInterval | 0) - 1 | 0, toBlock$1), fromBlock);
604
- var firstBlockParentPromise = fromBlock > 0 ? LazyLoader.get(blockLoader, fromBlock - 1 | 0).then(function (res) {
609
+ var firstBlockParentPromise = fromBlock > 0 ? LazyLoader.get(blockLoader.contents, fromBlock - 1 | 0).then(function (res) {
605
610
  return res;
606
611
  }) : Promise.resolve(undefined);
607
612
  var match = getSelectionConfig(selection);
608
613
  var match$1 = match.getLogSelectionOrThrow(addressesByContractName);
609
614
  var match$2 = await getNextPage(fromBlock, suggestedToBlock, match$1.addresses, match$1.topicQuery, (function (blockNumber) {
610
- return LazyLoader.get(blockLoader, blockNumber);
615
+ return LazyLoader.get(blockLoader.contents, blockNumber);
611
616
  }), syncConfig, provider, mutSuggestedBlockIntervals, partitionId);
612
617
  var latestFetchedBlock = match$2.latestFetchedBlock;
613
618
  var logs = match$2.logs;
@@ -784,8 +789,9 @@ function make(param) {
784
789
  };
785
790
  };
786
791
  var getBlockHashes = function (blockNumbers, _currentlyUnusedLogger) {
792
+ blockLoader.contents = makeBlockLoader();
787
793
  return $$Promise.$$catch(Promise.all(Belt_Array.map(blockNumbers, (function (blockNum) {
788
- return LazyLoader.get(blockLoader, blockNum);
794
+ return LazyLoader.get(blockLoader.contents, blockNum);
789
795
  }))).then(function (blocks) {
790
796
  return {
791
797
  TAG: "Ok",