envio 3.12.0 → 3.12.1

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 (48) hide show
  1. package/package.json +6 -6
  2. package/src/ChainFetching.res +7 -3
  3. package/src/ChainFetching.res.mjs +1 -1
  4. package/src/ChainState.res +12 -3
  5. package/src/ChainState.res.mjs +3 -3
  6. package/src/ChainState.resi +1 -1
  7. package/src/CrossChainState.res +1 -1
  8. package/src/CrossChainState.res.mjs +1 -1
  9. package/src/FetchState.res +51 -46
  10. package/src/FetchState.res.mjs +54 -36
  11. package/src/InMemoryTable.res +155 -67
  12. package/src/InMemoryTable.res.mjs +151 -60
  13. package/src/LoadLayer.res +57 -34
  14. package/src/LoadLayer.res.mjs +45 -62
  15. package/src/LoadLayer.resi +1 -1
  16. package/src/PgStorage.res +92 -62
  17. package/src/PgStorage.res.mjs +77 -50
  18. package/src/TestIndexer.res +9 -25
  19. package/src/TestIndexer.res.mjs +4 -3
  20. package/src/UserContext.res +13 -32
  21. package/src/UserContext.res.mjs +1 -7
  22. package/src/Utils.res +1 -4
  23. package/src/Utils.res.mjs +7 -16
  24. package/src/db/EntityFilter.res +487 -275
  25. package/src/db/EntityFilter.res.mjs +557 -309
  26. package/src/db/Table.res +21 -6
  27. package/src/db/Table.res.mjs +13 -4
  28. package/src/sources/BlockStore.res +7 -2
  29. package/src/sources/EvmHyperSyncSource.res +2 -0
  30. package/src/sources/EvmHyperSyncSource.res.mjs +2 -2
  31. package/src/sources/FuelHyperSyncSource.res +1 -0
  32. package/src/sources/FuelHyperSyncSource.res.mjs +1 -1
  33. package/src/sources/HyperSync.res +4 -0
  34. package/src/sources/HyperSync.res.mjs +4 -2
  35. package/src/sources/HyperSync.resi +1 -0
  36. package/src/sources/HyperSyncClient.res +3 -0
  37. package/src/sources/HyperSyncSSE.res +1 -1
  38. package/src/sources/HyperSyncSSE.res.mjs +4 -10
  39. package/src/sources/RpcSource.res +1 -0
  40. package/src/sources/RpcSource.res.mjs +1 -1
  41. package/src/sources/SimulateSource.res +1 -0
  42. package/src/sources/SimulateSource.res.mjs +1 -1
  43. package/src/sources/Source.res +7 -0
  44. package/src/sources/SourceManager.res +4 -3
  45. package/src/sources/SourceManager.res.mjs +2 -2
  46. package/src/sources/SvmHyperSyncClient.res +5 -0
  47. package/src/sources/SvmHyperSyncSource.res +3 -0
  48. package/src/sources/SvmHyperSyncSource.res.mjs +4 -2
package/src/db/Table.res CHANGED
@@ -331,18 +331,31 @@ let encodeIdsToJson = (table, ids: array<EntityId.t>): JSON.t =>
331
331
 
332
332
  // TODO: Test whether it should be passed via args and match the column type
333
333
 
334
- let getFieldByApiName = (table, apiFieldName) =>
335
- table.fields->Array.find(field =>
336
- switch field {
337
- | Field(f) => f->getApiFieldName
338
- | DerivedFrom({fieldName}) => fieldName
339
- } === apiFieldName
334
+ // Resolved once per table, because a getWhere looks up every field it filters
335
+ // on and scanning the array made that cost grow with the entity's width.
336
+ let fieldsByApiName: table => dict<fieldOrDerived> = Utils.WeakMap.memoize(table => {
337
+ let byApiName = Dict.make()
338
+ table.fields->Array.forEach(field =>
339
+ byApiName->Dict.set(
340
+ switch field {
341
+ | Field(f) => f->getApiFieldName
342
+ | DerivedFrom({fieldName}) => fieldName
343
+ },
344
+ field,
345
+ )
340
346
  )
347
+ byApiName
348
+ })
349
+
350
+ let getFieldByApiName = (table, apiFieldName) =>
351
+ table->fieldsByApiName->Utils.Dict.dangerouslyGetNonOption(apiFieldName)
341
352
 
342
353
  // Both schema instances are created once per field: rescript-schema compiles
343
354
  // and caches operations on the schema instance, so building S.array(fieldSchema)
344
355
  // per query would recompile the serializer on every call.
345
356
  type queryField = {
357
+ fieldType: fieldType,
358
+ isArray: bool,
346
359
  fieldSchema: S.t<unknown>,
347
360
  // Serializes the values array of an "in" filter
348
361
  arrayFieldSchema: S.t<unknown>,
@@ -363,6 +376,8 @@ let queryFields: table => dict<queryField> = Utils.WeakMap.memoize(table => {
363
376
  dict->Dict.set(
364
377
  field->getApiFieldName,
365
378
  {
379
+ fieldType: field.fieldType,
380
+ isArray: field.isArray,
366
381
  fieldSchema: field.fieldSchema,
367
382
  arrayFieldSchema: switch field.fieldType {
368
383
  | Bytea => Utils.Schema.bytesArray->S.toUnknown
@@ -296,12 +296,18 @@ function encodeIdsToJson(table, ids) {
296
296
  return S$RescriptSchema.reverseConvertToJsonOrThrow(ids, idsArraySchema(table));
297
297
  }
298
298
 
299
- function getFieldByApiName(table, apiFieldName) {
300
- return table.fields.find(field => {
299
+ let fieldsByApiName = Utils.$$WeakMap.memoize(table => {
300
+ let byApiName = {};
301
+ table.fields.forEach(field => {
301
302
  let tmp;
302
303
  tmp = field.TAG === "Field" ? getApiFieldName(field._0) : field._0.fieldName;
303
- return tmp === apiFieldName;
304
+ byApiName[tmp] = field;
304
305
  });
306
+ return byApiName;
307
+ });
308
+
309
+ function getFieldByApiName(table, apiFieldName) {
310
+ return fieldsByApiName(table)[apiFieldName];
305
311
  }
306
312
 
307
313
  let queryFields = Utils.$$WeakMap.memoize(table => {
@@ -315,6 +321,8 @@ let queryFields = Utils.$$WeakMap.memoize(table => {
315
321
  let tmp;
316
322
  tmp = typeof match !== "object" && match === "Bytea" ? Utils.Schema.bytesArray : S$RescriptSchema.array(field$1.fieldSchema);
317
323
  dict[getApiFieldName(field$1)] = {
324
+ fieldType: field$1.fieldType,
325
+ isArray: field$1.isArray,
318
326
  fieldSchema: field$1.fieldSchema,
319
327
  arrayFieldSchema: tmp,
320
328
  pgDbFieldName: getPgDbFieldName(field$1),
@@ -420,7 +428,7 @@ function toSqlParams(table, schema, pgSchema, chainIdModeOpt) {
420
428
  }
421
429
  }
422
430
  };
423
- let field = getFieldByApiName(table, location);
431
+ let field = fieldsByApiName(table)[location];
424
432
  let field$1;
425
433
  if (field !== undefined) {
426
434
  field$1 = field;
@@ -533,6 +541,7 @@ export {
533
541
  getIdSchema,
534
542
  idsArraySchema,
535
543
  encodeIdsToJson,
544
+ fieldsByApiName,
536
545
  getFieldByApiName,
537
546
  queryFields,
538
547
  makeRowsSchema,
@@ -142,8 +142,13 @@ external materialize: (
142
142
  // Hash of a stored block, if the store still holds it.
143
143
  @send external getHash: (t, int) => Null.t<string> = "getHash"
144
144
 
145
- // Unix timestamp of a stored block - exactly that block, on every ecosystem.
146
- @send external getTimestamp: (t, int) => Null.t<int> = "getTimestamp"
145
+ // Unix timestamp of a stored block - exactly that block, except for an SVM slot
146
+ // that produced none: with `allowSkippedSlot` the last real slot below it
147
+ // answers instead, which is what chain time is at a skipped slot. Only set it
148
+ // where the query covered every slot in its range, or a slot that was never
149
+ // asked about reads as one the chain skipped.
150
+ @send
151
+ external getTimestamp: (t, int, ~allowSkippedSlot: bool) => Null.t<int> = "getTimestamp"
147
152
 
148
153
  // Block numbers in `[fromBlock, belowBlock)` with a stored hash, ascending.
149
154
  @send
@@ -84,6 +84,7 @@ let make = (
84
84
  ~fromBlock,
85
85
  ~toBlock,
86
86
  ~addressSet,
87
+ ~includeAllBlocks,
87
88
  ~knownHeight,
88
89
  ~partitionId as _,
89
90
  ~selection: FetchState.selection,
@@ -104,6 +105,7 @@ let make = (
104
105
  ~registrationIndexes=selection.onEventRegistrations->Array.map(reg => reg.index),
105
106
  ~addressSet,
106
107
  ~clientFilteredContracts=selection.clientFilteredContracts,
108
+ ~includeAllBlocks,
107
109
  ) catch {
108
110
  | HyperSync.GetLogs.Error(WrongInstance) =>
109
111
  throw(Source.SourceBehindHead({blockNumber: fromBlock, requestStats: []}))
@@ -44,12 +44,12 @@ function make(param) {
44
44
  }
45
45
  };
46
46
  };
47
- let getItemsOrThrow = async (fromBlock, toBlock, addressSet, knownHeight, param, selection, itemsTarget, retry, param$1) => {
47
+ let getItemsOrThrow = async (fromBlock, toBlock, addressSet, includeAllBlocks, knownHeight, param, selection, itemsTarget, retry, param$1) => {
48
48
  let totalTimeRef = Performance.now();
49
49
  let startFetchingBatchTimeRef = Performance.now();
50
50
  let pageUnsafe;
51
51
  try {
52
- pageUnsafe = await HyperSync.GetLogs.query(client, fromBlock, toBlock, itemsTarget, selection.onEventRegistrations.map(reg => reg.index), addressSet, selection.clientFilteredContracts);
52
+ pageUnsafe = await HyperSync.GetLogs.query(client, fromBlock, toBlock, itemsTarget, selection.onEventRegistrations.map(reg => reg.index), addressSet, selection.clientFilteredContracts, includeAllBlocks);
53
53
  } catch (raw_exn) {
54
54
  let exn = Primitive_exceptions.internalToException(raw_exn);
55
55
  if (exn.RE_EXN_ID === HyperSync.GetLogs.$$Error) {
@@ -35,6 +35,7 @@ let make = ({chainId, endpointUrl, apiToken, onEventRegistrations, addressStore}
35
35
  ~fromBlock,
36
36
  ~toBlock,
37
37
  ~addressSet,
38
+ ~includeAllBlocks as _,
38
39
  ~knownHeight,
39
40
  ~partitionId as _,
40
41
  ~selection: FetchState.selection,
@@ -28,7 +28,7 @@ function make(param) {
28
28
  let exn = Primitive_exceptions.internalToException(raw_exn);
29
29
  client = ErrorHandling.mkLogAndRaise(undefined, "Failed to instantiate the HyperFuel client", exn);
30
30
  }
31
- let getItemsOrThrow = async (fromBlock, toBlock, addressSet, knownHeight, param, selection, param$1, retry, logger) => {
31
+ let getItemsOrThrow = async (fromBlock, toBlock, addressSet, param, knownHeight, param$1, selection, param$2, retry, logger) => {
32
32
  let totalTimeRef = Performance.now();
33
33
  let startFetchingBatchTimeRef = Performance.now();
34
34
  let pageUnsafe;
@@ -137,6 +137,7 @@ module GetLogs = {
137
137
  ~registrationIndexes,
138
138
  ~addressSet,
139
139
  ~clientFilteredContracts,
140
+ ~includeAllBlocks,
140
141
  ): logsQueryPage => {
141
142
  let query: HyperSyncClient.EventItems.query = {
142
143
  fromBlock,
@@ -144,6 +145,9 @@ module GetLogs = {
144
145
  ?maxNumLogs,
145
146
  registrationIndexes,
146
147
  clientFilteredContracts,
148
+ // Absent rather than false, so a range that wants only the blocks its
149
+ // logs came from sends the query it always sent.
150
+ includeAllBlocks: ?(includeAllBlocks ? Some(true) : None),
147
151
  }
148
152
 
149
153
  let (res, transactionStore, blockStore) = switch await client.getEventItems(
@@ -137,13 +137,15 @@ function extractMissingParams(exn) {
137
137
  }
138
138
  }
139
139
 
140
- async function query(client, fromBlock, toBlock, maxNumLogs, registrationIndexes, addressSet, clientFilteredContracts) {
140
+ async function query(client, fromBlock, toBlock, maxNumLogs, registrationIndexes, addressSet, clientFilteredContracts, includeAllBlocks) {
141
+ let query_includeAllBlocks = includeAllBlocks ? true : undefined;
141
142
  let query$1 = {
142
143
  fromBlock: fromBlock,
143
144
  toBlock: toBlock,
144
145
  maxNumLogs: maxNumLogs,
145
146
  registrationIndexes: registrationIndexes,
146
- clientFilteredContracts: clientFilteredContracts
147
+ clientFilteredContracts: clientFilteredContracts,
148
+ includeAllBlocks: query_includeAllBlocks
147
149
  };
148
150
  let match;
149
151
  try {
@@ -57,5 +57,6 @@ module GetLogs: {
57
57
  ~registrationIndexes: array<int>,
58
58
  ~addressSet: AddressSet.t,
59
59
  ~clientFilteredContracts: option<array<string>>,
60
+ ~includeAllBlocks: bool,
60
61
  ) => promise<logsQueryPage>
61
62
  }
@@ -262,6 +262,9 @@ module EventItems = {
262
262
  // depend on addresses (client-side filtering). None/empty means
263
263
  // every address-dependent contract is filtered server-side.
264
264
  clientFilteredContracts: option<array<string>>,
265
+ // Return a header for every block in the range, not only the ones a log
266
+ // landed on. Absent means only the blocks logs came from.
267
+ includeAllBlocks?: bool,
265
268
  }
266
269
 
267
270
  type item = {
@@ -25,7 +25,7 @@ let subscribe = (~hyperSyncUrl, ~apiToken, ~onHeight, ~onStatus) =>
25
25
  args.headers
26
26
  ->Option.getOr(Dict.make())
27
27
  ->Utils.Dict.merge(
28
- Dict.fromArray([("Authorization", `Bearer ${apiToken}`), ("User-Agent", userAgent)]),
28
+ dict{"Authorization": `Bearer ${apiToken}`, "User-Agent": userAgent},
29
29
  )
30
30
  EventSource.Fetch.fetch(url, ~args={...args, headers: headers})
31
31
  },
@@ -35,16 +35,10 @@ function subscribe(hyperSyncUrl, apiToken, onHeight, onStatus) {
35
35
  let userAgent = `hyperindex/` + Utils.EnvioPackage.value.version;
36
36
  let es = new Eventsource.EventSource(hyperSyncUrl + `/height/sse`, {
37
37
  fetch: (url, args) => {
38
- let headers = Utils.Dict.merge(Stdlib_Option.getOr(args.headers, {}), Object.fromEntries([
39
- [
40
- "Authorization",
41
- `Bearer ` + apiToken
42
- ],
43
- [
44
- "User-Agent",
45
- userAgent
46
- ]
47
- ]));
38
+ let headers = Utils.Dict.merge(Stdlib_Option.getOr(args.headers, {}), {
39
+ Authorization: `Bearer ` + apiToken,
40
+ "User-Agent": userAgent
41
+ });
48
42
  let newrecord = {...args};
49
43
  return fetch(url, (newrecord.headers = headers, newrecord));
50
44
  }
@@ -877,6 +877,7 @@ let make = (
877
877
  ~fromBlock,
878
878
  ~toBlock,
879
879
  ~addressSet,
880
+ ~includeAllBlocks as _,
880
881
  ~knownHeight,
881
882
  ~partitionId,
882
883
  ~selection: FetchState.selection,
@@ -874,7 +874,7 @@ function make(param) {
874
874
  Error: new Error()
875
875
  };
876
876
  }, lowercaseAddresses);
877
- let getItemsOrThrow = async (fromBlock, toBlock, addressSet, knownHeight, partitionId, selection, param, retry, param$1) => {
877
+ let getItemsOrThrow = async (fromBlock, toBlock, addressSet, param, knownHeight, partitionId, selection, param$1, retry, param$2) => {
878
878
  let startFetchingBatchTimeRef = Performance.now();
879
879
  let toBlock$1 = toBlock !== undefined ? Primitive_int.min(toBlock, knownHeight) : knownHeight;
880
880
  let firstBlockPromise = fromBlock > 0 && fromBlock <= toBlock$1 ? LazyLoader.get(blockLoader.contents, fromBlock).then(json => parseBlockInfo(json)) : Promise.resolve(undefined);
@@ -29,6 +29,7 @@ let make = (
29
29
  ~fromBlock,
30
30
  ~toBlock,
31
31
  ~addressSet,
32
+ ~includeAllBlocks as _,
32
33
  ~knownHeight as _,
33
34
  ~partitionId as _,
34
35
  ~selection: FetchState.selection,
@@ -27,7 +27,7 @@ function make(items, endBlock, chainId, addressStore, ecosystemOpt, transactionS
27
27
  height: reportedHeight,
28
28
  requestStats: []
29
29
  }),
30
- getItemsOrThrow: (fromBlock, toBlock, addressSet, param, param$1, selection, param$2, param$3, param$4) => {
30
+ getItemsOrThrow: (fromBlock, toBlock, addressSet, param, param$1, param$2, selection, param$3, param$4, param$5) => {
31
31
  let toBlockQueried = toBlock !== undefined ? toBlock : reportedHeight;
32
32
  let selectionRegistrationIndexes = new Set();
33
33
  selection.onEventRegistrations.forEach(reg => {
@@ -197,6 +197,13 @@ type t = {
197
197
  // straight to its Rust client, which builds the query's address filter from
198
198
  // it and gates every returned item against the chain-wide store.
199
199
  ~addressSet: AddressSet.t,
200
+ // Return a header for every block in the range, not only the ones an item
201
+ // landed on. The progress block's timestamp is what measures how far behind
202
+ // chain time the indexer is, and at the head that block often carries no
203
+ // item of its own. Only set once the chain is at the head, where the range
204
+ // is a handful of blocks; over a backfill range it would be a header per
205
+ // block for no gain.
206
+ ~includeAllBlocks: bool,
200
207
  ~knownHeight: int,
201
208
  ~partitionId: string,
202
209
  ~selection: FetchState.selection,
@@ -705,7 +705,7 @@ let waitForNewBlock = (sourceManager: t, ~knownHeight, ~isRealtime, ~reducedPoll
705
705
  logger->Logging.childTrace(
706
706
  reducedPolling
707
707
  ? `Waiting for new blocks with reduced polling (${(sourceManager.reducedPollingInterval / 1000)
708
- ->Int.toString}s). Chain is caught up, waiting for other chains to backfill.`
708
+ ->Int.toString}s) until the indexer enters realtime mode.`
709
709
  : "Initiating check for new blocks.",
710
710
  )
711
711
  sourceManager.waitingLogged = true
@@ -717,8 +717,8 @@ let waitForNewBlock = (sourceManager: t, ~knownHeight, ~isRealtime, ~reducedPoll
717
717
  // cadence the sources poll at and the level the closing line is logged at.
718
718
  let stalled = ref(false)
719
719
 
720
- // Use a much longer stall timeout when reduced polling is active
721
- // to avoid spurious stall warnings while waiting for other chains to backfill
720
+ // Use a much longer stall timeout when reduced polling is active, so a chain
721
+ // deliberately asking rarely doesn't report itself stalled between polls.
722
722
  let stallTimeout = if reducedPolling {
723
723
  sourceManager.reducedPollingInterval * 2
724
724
  } else if isRealtime {
@@ -948,6 +948,7 @@ let executeQuery = async (
948
948
  ~fromBlock=query.fromBlock,
949
949
  ~toBlock,
950
950
  ~addressSet=query.addresses,
951
+ ~includeAllBlocks=isRealtime,
951
952
  ~partitionId=query.partitionId,
952
953
  ~knownHeight,
953
954
  ~selection=query.selection->FetchState.narrowSelectionToRange(~toBlock),
@@ -537,7 +537,7 @@ function waitForNewBlock(sourceManager, knownHeight, isRealtime, reducedPolling)
537
537
  knownHeight: knownHeight
538
538
  });
539
539
  if (!sourceManager.waitingLogged) {
540
- Logging.childTrace(logger, reducedPolling ? `Waiting for new blocks with reduced polling (` + (sourceManager.reducedPollingInterval / 1000 | 0).toString() + `s). Chain is caught up, waiting for other chains to backfill.` : "Initiating check for new blocks.");
540
+ Logging.childTrace(logger, reducedPolling ? `Waiting for new blocks with reduced polling (` + (sourceManager.reducedPollingInterval / 1000 | 0).toString() + `s) until the indexer enters realtime mode.` : "Initiating check for new blocks.");
541
541
  sourceManager.waitingLogged = true;
542
542
  }
543
543
  let mainSources = getNextSources(sourceManager, isRealtime, undefined);
@@ -691,7 +691,7 @@ async function executeQuery(sourceManager, query, knownHeight, isRealtime) {
691
691
  retry: retry
692
692
  });
693
693
  try {
694
- let response = await source.getItemsOrThrow(query.fromBlock, toBlock, query.addresses, knownHeight, query.partitionId, FetchState.narrowSelectionToRange(query.selection, toBlock), query.itemsTarget, retry, logger$2);
694
+ let response = await source.getItemsOrThrow(query.fromBlock, toBlock, query.addresses, isRealtime, knownHeight, query.partitionId, FetchState.narrowSelectionToRange(query.selection, toBlock), query.itemsTarget, retry, logger$2);
695
695
  recordStatsInto(sourceState.requestStats, response.requestStats);
696
696
  validateResponseBlockStore("getItems", response.blockStore, undefined);
697
697
  sourceState.lastFailedAt = undefined;
@@ -143,6 +143,11 @@ module EventItems = {
143
143
  // depend on addresses (client-side filtering). None/empty means every
144
144
  // address-dependent program is filtered server-side.
145
145
  clientFilteredContracts: option<array<string>>,
146
+ // Return a block for every slot in the range, not only the ones an
147
+ // instruction landed on. Absent means only the slots instructions came
148
+ // from, which leaves a skipped slot indistinguishable from an unfetched
149
+ // one.
150
+ includeAllBlocks?: bool,
146
151
  }
147
152
 
148
153
  // NAPI encodes Rust `None` as `null`, never `undefined`, so an unselected
@@ -147,6 +147,7 @@ let make = (
147
147
  ~fromBlock,
148
148
  ~toBlock,
149
149
  ~addressSet,
150
+ ~includeAllBlocks,
150
151
  ~knownHeight,
151
152
  ~partitionId as _,
152
153
  ~selection: FetchState.selection,
@@ -163,6 +164,8 @@ let make = (
163
164
  maxNumInstructions: ?itemsTarget,
164
165
  registrationIndexes: selection.onEventRegistrations->Array.map(reg => reg.index),
165
166
  clientFilteredContracts: selection.clientFilteredContracts,
167
+ // Absent rather than false, so a backfill query is the one it always was.
168
+ includeAllBlocks: ?(includeAllBlocks ? Some(true) : None),
166
169
  }
167
170
 
168
171
  let (resp, transactionStore, blockStore) = try await client.getEventItems(
@@ -106,17 +106,19 @@ function make(param) {
106
106
  let chainId = param.chainId;
107
107
  let apiToken = HyperSync.requireApiToken(param.apiToken);
108
108
  let client = SvmHyperSyncClient.make(endpointUrl, apiToken, param.clientTimeoutMillis, undefined, undefined, SvmHyperSyncClient.Registration.fromOnEventRegistrations(onEventRegistrations), param.addressStore);
109
- let getItemsOrThrow = async (fromBlock, toBlock, addressSet, knownHeight, param, selection, itemsTarget, retry, param$1) => {
109
+ let getItemsOrThrow = async (fromBlock, toBlock, addressSet, includeAllBlocks, knownHeight, param, selection, itemsTarget, retry, param$1) => {
110
110
  let totalTimeRef = Performance.now();
111
111
  let pageFetchRef = Performance.now();
112
112
  let query_registrationIndexes = selection.onEventRegistrations.map(reg => reg.index);
113
113
  let query_clientFilteredContracts = selection.clientFilteredContracts;
114
+ let query_includeAllBlocks = includeAllBlocks ? true : undefined;
114
115
  let query = {
115
116
  fromSlot: fromBlock,
116
117
  toSlot: toBlock,
117
118
  maxNumInstructions: itemsTarget,
118
119
  registrationIndexes: query_registrationIndexes,
119
- clientFilteredContracts: query_clientFilteredContracts
120
+ clientFilteredContracts: query_clientFilteredContracts,
121
+ includeAllBlocks: query_includeAllBlocks
120
122
  };
121
123
  let match;
122
124
  try {