@xyo-network/xl1-protocol-sdk 2.0.10 → 2.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +3 -6
  2. package/dist/neutral/ChainContextHelpers.d.ts.map +1 -1
  3. package/dist/neutral/CreatableProvider/AbstractCreatableProvider.d.ts +1 -1
  4. package/dist/neutral/config/Actor.d.ts +6 -6
  5. package/dist/neutral/config/Actors.d.ts +1 -1
  6. package/dist/neutral/config/Base.d.ts +1 -1
  7. package/dist/neutral/config/Config.d.ts +4 -4
  8. package/dist/neutral/config/HostActor.d.ts +6 -6
  9. package/dist/neutral/config/Log.d.ts +1 -1
  10. package/dist/neutral/context/Actor.d.ts +6 -6
  11. package/dist/neutral/context/HostActor.d.ts +6 -6
  12. package/dist/neutral/getFileConfig.d.ts +2 -2
  13. package/dist/neutral/index.d.ts +1 -1
  14. package/dist/neutral/index.d.ts.map +1 -1
  15. package/dist/neutral/index.mjs +348 -290
  16. package/dist/neutral/index.mjs.map +4 -4
  17. package/dist/neutral/model/CreatableProviderContext.zod.d.ts +6 -6
  18. package/dist/neutral/simple/block/SimpleBlockViewer.d.ts +13 -2
  19. package/dist/neutral/simple/block/SimpleBlockViewer.d.ts.map +1 -1
  20. package/dist/neutral/simple/mempool/SimpleMempoolRunner.d.ts.map +1 -1
  21. package/dist/neutral/simple/windowedBlock/SimpleWindowedBlockViewer.d.ts +33 -0
  22. package/dist/neutral/simple/windowedBlock/SimpleWindowedBlockViewer.d.ts.map +1 -1
  23. package/dist/neutral/summary/model/BlocksStepSummary.d.ts +26 -0
  24. package/dist/neutral/summary/model/BlocksStepSummary.d.ts.map +1 -0
  25. package/dist/neutral/summary/model/index.d.ts +1 -0
  26. package/dist/neutral/summary/model/index.d.ts.map +1 -1
  27. package/dist/neutral/summary/primitives/blocks/blocksMaxStep.d.ts +13 -0
  28. package/dist/neutral/summary/primitives/blocks/blocksMaxStep.d.ts.map +1 -0
  29. package/dist/neutral/summary/primitives/blocks/blocksStepSummaryFromRange.d.ts +13 -0
  30. package/dist/neutral/summary/primitives/blocks/blocksStepSummaryFromRange.d.ts.map +1 -0
  31. package/dist/neutral/summary/primitives/blocks/index.d.ts +3 -0
  32. package/dist/neutral/summary/primitives/blocks/index.d.ts.map +1 -0
  33. package/dist/neutral/summary/primitives/index.d.ts +1 -0
  34. package/dist/neutral/summary/primitives/index.d.ts.map +1 -1
  35. package/dist/neutral/test/index.mjs +218 -135
  36. package/dist/neutral/test/index.mjs.map +4 -4
  37. package/package.json +19 -20
  38. package/dist/neutral/driver/cache/LruCacheMap.d.ts +0 -15
  39. package/dist/neutral/driver/cache/LruCacheMap.d.ts.map +0 -1
  40. package/dist/neutral/driver/cache/index.d.ts +0 -2
  41. package/dist/neutral/driver/cache/index.d.ts.map +0 -1
  42. package/dist/neutral/driver/index.d.ts +0 -3
  43. package/dist/neutral/driver/index.d.ts.map +0 -1
  44. package/dist/neutral/driver/memory/MemoryMap.d.ts +0 -14
  45. package/dist/neutral/driver/memory/MemoryMap.d.ts.map +0 -1
  46. package/dist/neutral/driver/memory/index.d.ts +0 -2
  47. package/dist/neutral/driver/memory/index.d.ts.map +0 -1
@@ -889,91 +889,12 @@ var findEndBlockRecursive = async (viewer, startBlock, targetTimeMs, estimatedBl
889
889
 
890
890
  // src/ChainContextHelpers.ts
891
891
  import {
892
- isDefined as isDefined6,
892
+ isDefined as isDefined5,
893
893
  isObject,
894
894
  isUndefined as isUndefined2,
895
895
  timeBudget
896
896
  } from "@xylabs/sdk-js";
897
-
898
- // src/driver/cache/LruCacheMap.ts
899
- import { LRUCache } from "lru-cache";
900
- var LruCacheMap = class {
901
- lruCache;
902
- constructor(options) {
903
- this.lruCache = new LRUCache(options ?? { max: 5e3 });
904
- }
905
- clear() {
906
- this.lruCache.clear();
907
- }
908
- delete(id) {
909
- return this.lruCache.delete(id);
910
- }
911
- get(id) {
912
- return this.lruCache.get(id);
913
- }
914
- getMany(id) {
915
- const results = [];
916
- for (const key of id) {
917
- const value = this.lruCache.get(key);
918
- if (value !== void 0) {
919
- results.push(value);
920
- }
921
- }
922
- return results;
923
- }
924
- has(id) {
925
- return this.lruCache.has(id);
926
- }
927
- set(id, data) {
928
- this.lruCache.set(id, data);
929
- }
930
- setMany(entries) {
931
- for (const [key, value] of entries) {
932
- this.lruCache.set(key, value);
933
- }
934
- }
935
- };
936
-
937
- // src/driver/memory/MemoryMap.ts
938
- import { isDefined as isDefined5 } from "@xylabs/sdk-js";
939
- var MemoryMap = class {
940
- map;
941
- constructor() {
942
- this.map = /* @__PURE__ */ new Map();
943
- }
944
- clear() {
945
- this.map.clear();
946
- }
947
- delete(id) {
948
- return this.map.delete(id);
949
- }
950
- get(id) {
951
- return this.map.get(id);
952
- }
953
- getMany(ids) {
954
- const results = [];
955
- for (const id of ids) {
956
- const data = this.map.get(id);
957
- if (isDefined5(data)) {
958
- results.push(data);
959
- }
960
- }
961
- return results;
962
- }
963
- has(id) {
964
- return this.map.has(id);
965
- }
966
- set(id, data) {
967
- this.map.set(id, data);
968
- }
969
- setMany(entries) {
970
- for (const [key, value] of entries) {
971
- this.map.set(key, value);
972
- }
973
- }
974
- };
975
-
976
- // src/ChainContextHelpers.ts
897
+ import { LruCacheMap, MemoryMap } from "@xyo-network/xl1-driver-memory";
977
898
  function contextCache(context, name, create) {
978
899
  if (!isObject(context.caches)) {
979
900
  throw new Error("Context does not have an appropriate caches property");
@@ -991,7 +912,7 @@ async function withContextCacheResponse(context, name, key, func, { max = 1e4 }
991
912
  );
992
913
  const { timeBudgetLimit = 0 } = context;
993
914
  const cacheResult = await cache.get(key);
994
- if (isDefined6(cacheResult)) {
915
+ if (isDefined5(cacheResult)) {
995
916
  return cacheResult;
996
917
  }
997
918
  const result = timeBudgetLimit > 0 ? timeBudget(name, context.logger, func, timeBudgetLimit) : func();
@@ -1049,7 +970,7 @@ var hydrateBlock = async (context, hash, maxDepth = 1, minDepth = maxDepth) => {
1049
970
  // src/block/primitives/blockFromBlockNumber.ts
1050
971
  import {
1051
972
  asHash,
1052
- isDefined as isDefined7,
973
+ isDefined as isDefined6,
1053
974
  spanAsync
1054
975
  } from "@xylabs/sdk-js";
1055
976
  import { toSafeJsonString } from "@xylabs/sdk-js";
@@ -1064,7 +985,7 @@ async function blockFromBlockNumber(context, blockNumber) {
1064
985
  const { chainMap, head } = context;
1065
986
  return await withContextCacheResponse(context, "blockFromBlockNumber", cacheKey, async () => {
1066
987
  const [result] = await chainMap.get([head._hash]);
1067
- if (!isDefined7(result)) {
988
+ if (!isDefined6(result)) {
1068
989
  throw new Error(`Head block not found for hash: ${head._hash}`);
1069
990
  }
1070
991
  let currentBlock = asSignedBlockBoundWitnessWithStorageMeta(
@@ -1077,8 +998,8 @@ async function blockFromBlockNumber(context, blockNumber) {
1077
998
  while (currentBlock.block > blockNumber) {
1078
999
  let jumpHash = currentBlock.previous;
1079
1000
  let jumpBlockNumber = currentBlock.block - 1;
1080
- for (const [step, stepSize] of StepSizes2.entries()) {
1081
- const possibleJumpBlockNumber = currentBlock.block - currentBlock.block % stepSize - 1;
1001
+ for (const [step, stepSize3] of StepSizes2.entries()) {
1002
+ const possibleJumpBlockNumber = currentBlock.block - currentBlock.block % stepSize3 - 1;
1082
1003
  if (possibleJumpBlockNumber >= blockNumber && possibleJumpBlockNumber <= jumpBlockNumber) {
1083
1004
  jumpBlockNumber = possibleJumpBlockNumber;
1084
1005
  jumpHash = asHash(currentBlock.step_hashes?.at(step), () => `Step hash not found for step ${step} in block ${currentBlock.block}`);
@@ -1087,7 +1008,7 @@ async function blockFromBlockNumber(context, blockNumber) {
1087
1008
  const [newBlock] = await chainMap.get([
1088
1009
  asHash(jumpHash, () => `Jump hash not found for block number [${blockNumber}]: ${jumpBlockNumber} ${toSafeJsonString(currentBlock, 10)}`)
1089
1010
  ]);
1090
- if (!isDefined7(newBlock)) {
1011
+ if (!isDefined6(newBlock)) {
1091
1012
  throw new Error(`Block not found for jump hash: ${jumpHash}`);
1092
1013
  }
1093
1014
  currentBlock = asSignedBlockBoundWitnessWithStorageMeta(
@@ -1109,6 +1030,53 @@ async function blockFromBlockNumber(context, blockNumber) {
1109
1030
  }, { ...context, timeBudgetLimit: 500 });
1110
1031
  }
1111
1032
 
1033
+ // src/block/primitives/frames/calculateFramesFromRange.ts
1034
+ import { asXL1BlockNumber as asXL1BlockNumber3, stepSize } from "@xyo-network/xl1-protocol-lib";
1035
+ function calculateFramesFromRange(range, step) {
1036
+ const size = stepSize(step);
1037
+ let start = Math.trunc(range[0] / size) * size;
1038
+ const fitted = [];
1039
+ const remaining = [];
1040
+ if (start !== range[0]) {
1041
+ start += size;
1042
+ remaining.push([range[0], asXL1BlockNumber3(Math.min(start - 1, range[1]), true)]);
1043
+ }
1044
+ for (let i = start; i <= range[1]; i += size) {
1045
+ if (i + size - 1 <= range[1]) {
1046
+ fitted.push([
1047
+ asXL1BlockNumber3(i, { name: "calculateFramesFromRange A" }),
1048
+ asXL1BlockNumber3(Math.min(i + size - 1, range[1]), { name: "calculateFramesFromRange B" })
1049
+ ]);
1050
+ } else {
1051
+ remaining.push([asXL1BlockNumber3(i, { name: "calculateFramesFromRange C" }), range[1]]);
1052
+ }
1053
+ }
1054
+ return [fitted, remaining];
1055
+ }
1056
+
1057
+ // src/block/primitives/frames/deepCalculateFramesFromRange.ts
1058
+ import { StepSizes as StepSizes3 } from "@xyo-network/xl1-protocol-lib";
1059
+ function deepCalculateFramesFromRange(range, startingStep = StepSizes3.length - 1) {
1060
+ const fitted = [];
1061
+ let remaining = [range];
1062
+ const actualStartingStep = Math.min(startingStep, StepSizes3.length - 1);
1063
+ for (let step = actualStartingStep; step >= 0; step--) {
1064
+ const newRemaining = [];
1065
+ for (const range2 of remaining) {
1066
+ const [newFittedFrames, newRemainingFrames] = calculateFramesFromRange(range2, step);
1067
+ fitted.push(...newFittedFrames);
1068
+ newRemaining.push(...newRemainingFrames);
1069
+ }
1070
+ remaining = newRemaining;
1071
+ }
1072
+ for (const range2 of remaining) {
1073
+ for (let i = range2[0]; i <= range2[1]; i++) {
1074
+ fitted.push([i, i]);
1075
+ }
1076
+ }
1077
+ return fitted.toSorted((a, b) => a[0] - b[0]);
1078
+ }
1079
+
1112
1080
  // src/block/primitives/validateTransactionOpcodes.ts
1113
1081
  import {
1114
1082
  assertEx as assertEx9,
@@ -1278,22 +1246,106 @@ var ConfigZod = z18.extend(BaseConfigZod, {
1278
1246
  })
1279
1247
  }).check(z18.describe("The complete configuration for the protocol, including global settings and actor-specific overrides"));
1280
1248
 
1249
+ // src/summary/model/BlocksStepSummary.ts
1250
+ import { AsObjectFactory } from "@xylabs/sdk-js";
1251
+ import {
1252
+ asSchema,
1253
+ isPayloadOfSchemaType,
1254
+ isStorageMeta
1255
+ } from "@xyo-network/sdk-js";
1256
+ var BlocksStepSummarySchema = asSchema("network.xyo.step.summary.blocks", true);
1257
+ var isBlocksStepSummary = isPayloadOfSchemaType(BlocksStepSummarySchema);
1258
+ var asBlocksStepSummary = AsObjectFactory.create(isBlocksStepSummary);
1259
+ var isBlocksStepSummaryWithStorageMeta = (value) => {
1260
+ return isBlocksStepSummary(value) && isStorageMeta(value);
1261
+ };
1262
+ var asBlocksStepSummaryWithStorageMeta = AsObjectFactory.create(isBlocksStepSummaryWithStorageMeta);
1263
+
1264
+ // src/summary/primitives/blocks/blocksMaxStep.ts
1265
+ var blocksMaxStep = 3;
1266
+
1267
+ // src/summary/primitives/blocks/blocksStepSummaryFromRange.ts
1268
+ import { assertEx as assertEx11, spanRootAsync } from "@xylabs/sdk-js";
1269
+ import { isAnyPayload } from "@xyo-network/sdk-js";
1270
+ import { asXL1BlockNumber as asXL1BlockNumber4, StepSizes as StepSizes4 } from "@xyo-network/xl1-protocol-lib";
1271
+ function blocksStepSummaryKey(frameHeadHash, frameSize) {
1272
+ return `${frameHeadHash}|${frameSize}`;
1273
+ }
1274
+ async function blocksStepSummaryFromRange(context, semaphores, blockViewer, summaryMap, range) {
1275
+ const cacheKey = `${range[0]}|${range[1]}`;
1276
+ return await withContextCacheResponse(context, "blocksStepSummaryFromRange", cacheKey, async () => {
1277
+ return await spanRootAsync("blocksStepSummaryFromRange", async () => {
1278
+ const frameHead = assertEx11(
1279
+ await blockViewer.blockByNumber(range[1]),
1280
+ () => `Block not found for number: ${range[1]}`
1281
+ );
1282
+ const frameHeadHash = frameHead[0]._hash;
1283
+ const frameSize = range[1] - range[0] + 1;
1284
+ let result;
1285
+ if (frameSize === 1) {
1286
+ result = {
1287
+ schema: BlocksStepSummarySchema,
1288
+ hash: frameHeadHash,
1289
+ stepSize: -1,
1290
+ blocks: [frameHead]
1291
+ };
1292
+ } else {
1293
+ const step = StepSizes4.indexOf(asXL1BlockNumber4(frameSize, true));
1294
+ assertEx11(step !== -1, () => `Invalid step size: ${frameSize}. Must be one of ${StepSizes4.join(", ")}`);
1295
+ const key = blocksStepSummaryKey(frameHeadHash, frameSize);
1296
+ const summaryResult = await summaryMap.get(key);
1297
+ if (isAnyPayload(summaryResult)) {
1298
+ result = asBlocksStepSummary(summaryResult, { required: true });
1299
+ } else {
1300
+ await semaphores[step].acquire();
1301
+ try {
1302
+ const subRanges = deepCalculateFramesFromRange(range, step - 1);
1303
+ const subResults = await Promise.all(subRanges.map((subRange) => blocksStepSummaryFromRange(
1304
+ context,
1305
+ semaphores,
1306
+ blockViewer,
1307
+ summaryMap,
1308
+ subRange
1309
+ )));
1310
+ const blocks = subResults.flatMap((subResult) => subResult.blocks);
1311
+ result = {
1312
+ schema: BlocksStepSummarySchema,
1313
+ hash: frameHeadHash,
1314
+ stepSize: frameSize,
1315
+ blocks
1316
+ };
1317
+ await summaryMap.set(key, result);
1318
+ } finally {
1319
+ semaphores[step].release();
1320
+ }
1321
+ }
1322
+ }
1323
+ return result;
1324
+ }, { ...context, timeBudgetLimit: 500 });
1325
+ }, { max: 1e5 });
1326
+ }
1327
+
1281
1328
  // src/simple/block/SimpleBlockViewer.ts
1282
1329
  import {
1283
- assertEx as assertEx11,
1330
+ assertEx as assertEx12,
1284
1331
  exists,
1285
1332
  isUndefined as isUndefined3
1286
1333
  } from "@xylabs/sdk-js";
1334
+ import { LruCacheMap as LruCacheMap2 } from "@xyo-network/xl1-driver-memory";
1287
1335
  import {
1288
1336
  asSignedHydratedBlockWithHashMeta,
1289
1337
  asSignedHydratedBlockWithStorageMeta,
1290
- asXL1BlockNumber as asXL1BlockNumber3,
1338
+ asXL1BlockNumber as asXL1BlockNumber5,
1339
+ asXL1BlockRange as asXL1BlockRange4,
1291
1340
  BlockViewerMoniker,
1292
- FinalizationViewerMoniker
1341
+ FinalizationViewerMoniker,
1342
+ stepSize as stepSize2,
1343
+ StepSizes as StepSizes5
1293
1344
  } from "@xyo-network/xl1-protocol-lib";
1345
+ import { Semaphore } from "async-mutex";
1294
1346
 
1295
1347
  // src/utils/HydratedCache.ts
1296
- import { LRUCache as LRUCache2 } from "lru-cache";
1348
+ import { LRUCache } from "lru-cache";
1297
1349
  var HydratedCache = class {
1298
1350
  cache;
1299
1351
  context;
@@ -1301,7 +1353,7 @@ var HydratedCache = class {
1301
1353
  constructor(context, hydrateFunction, maxCount = 2e3, ttl = Number.MAX_SAFE_INTEGER) {
1302
1354
  this.context = context;
1303
1355
  this.hydrateFunction = hydrateFunction;
1304
- this.cache = new LRUCache2({ max: maxCount, ttl });
1356
+ this.cache = new LRUCache({ max: maxCount, ttl });
1305
1357
  }
1306
1358
  async get(hash) {
1307
1359
  const existing = this.cache.get(hash);
@@ -1321,8 +1373,10 @@ var SimpleBlockViewer = class extends AbstractCreatableProvider {
1321
1373
  moniker = SimpleBlockViewer.defaultMoniker;
1322
1374
  _store;
1323
1375
  finalizationViewer;
1324
- payloadCache = new LruCacheMap({ max: 1e4 });
1325
- signedHydratedBlockWithHashMetaCache = new LruCacheMap({ max: 2e3, ttl: 1e3 * 60 * 60 });
1376
+ payloadCache = new LruCacheMap2({ max: 1e4 });
1377
+ signedHydratedBlockWithHashMetaCache = new LruCacheMap2({ max: 2e3, ttl: 1e3 * 60 * 60 });
1378
+ _blockStepSemaphores = StepSizes5.map(() => new Semaphore(20));
1379
+ _blocksSummaryMap;
1326
1380
  _headPollHash;
1327
1381
  _headPollInProgress = false;
1328
1382
  _headPollTimer = null;
@@ -1330,6 +1384,10 @@ var SimpleBlockViewer = class extends AbstractCreatableProvider {
1330
1384
  get finalizedArchivist() {
1331
1385
  return this.params.finalizedArchivist;
1332
1386
  }
1387
+ get blocksSummaryMap() {
1388
+ this._blocksSummaryMap ??= this.params.blocksSummaryMap ?? new LruCacheMap2({ max: 32 });
1389
+ return this._blocksSummaryMap;
1390
+ }
1333
1391
  get headPollIntervalMs() {
1334
1392
  return this.params.headPollIntervalMs;
1335
1393
  }
@@ -1348,11 +1406,12 @@ var SimpleBlockViewer = class extends AbstractCreatableProvider {
1348
1406
  static async paramsHandler(params) {
1349
1407
  const headPollIntervalMs = params.headPollIntervalMs;
1350
1408
  if (headPollIntervalMs !== void 0) {
1351
- assertEx11(headPollIntervalMs >= MIN_HEAD_POLL_INTERVAL_MS, () => `headPollIntervalMs must be at least ${MIN_HEAD_POLL_INTERVAL_MS}ms`);
1409
+ assertEx12(headPollIntervalMs >= MIN_HEAD_POLL_INTERVAL_MS, () => `headPollIntervalMs must be at least ${MIN_HEAD_POLL_INTERVAL_MS}ms`);
1352
1410
  }
1353
1411
  return {
1354
1412
  ...await super.paramsHandler(params),
1355
- finalizedArchivist: assertEx11(params.finalizedArchivist, () => "finalizedArchivist is required"),
1413
+ blocksSummaryMap: params.blocksSummaryMap,
1414
+ finalizedArchivist: assertEx12(params.finalizedArchivist, () => "finalizedArchivist is required"),
1356
1415
  headPollIntervalMs
1357
1416
  };
1358
1417
  }
@@ -1381,8 +1440,8 @@ var SimpleBlockViewer = class extends AbstractCreatableProvider {
1381
1440
  }
1382
1441
  async blocksByHash(hash, limit = 50) {
1383
1442
  return await this.spanAsync("blocksByHash", async () => {
1384
- assertEx11(limit > 0, () => "limit must be greater than 0");
1385
- assertEx11(limit <= 100, () => "limit must be less than 100");
1443
+ assertEx12(limit > 0, () => "limit must be greater than 0");
1444
+ assertEx12(limit <= 100, () => "limit must be less than 100");
1386
1445
  const blocks = [];
1387
1446
  let current = await this.blockByHash(hash);
1388
1447
  while (current && blocks.length < limit) {
@@ -1396,8 +1455,8 @@ var SimpleBlockViewer = class extends AbstractCreatableProvider {
1396
1455
  }
1397
1456
  async blocksByNumber(blockNumber, limit = 50) {
1398
1457
  return await this.spanAsync("blocksByNumber", async () => {
1399
- assertEx11(limit > 0, () => "limit must be greater than 0");
1400
- assertEx11(limit <= 100, () => "limit must be less than 100");
1458
+ assertEx12(limit > 0, () => "limit must be greater than 0");
1459
+ assertEx12(limit <= 100, () => "limit must be less than 100");
1401
1460
  const chainContext = await this.getChainContextRead();
1402
1461
  if (isUndefined3(chainContext.head)) {
1403
1462
  return [];
@@ -1407,15 +1466,39 @@ var SimpleBlockViewer = class extends AbstractCreatableProvider {
1407
1466
  while (current && blocks.length < limit) {
1408
1467
  blocks.push(current);
1409
1468
  if (current[0].block === 0) break;
1410
- const previousNumber = asXL1BlockNumber3(current[0].block - 1, true);
1469
+ const previousNumber = asXL1BlockNumber5(current[0].block - 1, true);
1411
1470
  current = await this.blockByNumberWithContext(chainContext, previousNumber);
1412
1471
  }
1413
1472
  return blocks.map((b) => asSignedHydratedBlockWithHashMeta(b, true));
1414
1473
  }, this.context);
1415
1474
  }
1475
+ async blocksByStep(stepLevel, stepIndex) {
1476
+ return await this.spanAsync("blocksByStep", async () => {
1477
+ assertEx12(Number.isInteger(stepIndex) && stepIndex >= 0, () => "stepIndex must be a non-negative integer");
1478
+ const size = stepSize2(stepLevel);
1479
+ assertEx12(
1480
+ stepLevel <= blocksMaxStep,
1481
+ () => `blocksByStep does not support step levels above ${blocksMaxStep} (requested ${stepLevel})`
1482
+ );
1483
+ const chainContext = await this.getChainContextRead();
1484
+ if (isUndefined3(chainContext.head)) {
1485
+ return [];
1486
+ }
1487
+ const start = stepIndex * size;
1488
+ const end = Math.min(start + size - 1, chainContext.head.block);
1489
+ if (end < start) {
1490
+ return [];
1491
+ }
1492
+ const range = asXL1BlockRange4([start, end], { name: "blocksByStep" });
1493
+ const frames = deepCalculateFramesFromRange(range, blocksMaxStep);
1494
+ const summaries = await Promise.all(frames.map((frame) => blocksStepSummaryFromRange(this.context, this._blockStepSemaphores, this, this.blocksSummaryMap, frame)));
1495
+ const blocks = summaries.flatMap((summary) => summary.blocks);
1496
+ return blocks.map((b) => asSignedHydratedBlockWithHashMeta(b, true)).toReversed();
1497
+ }, this.context);
1498
+ }
1416
1499
  async chainId(blockNumber = "latest") {
1417
1500
  return await this.spanAsync("chainId", async () => {
1418
- return blockNumber === "latest" ? (await this.finalizationViewer.headBlock()).chain : assertEx11(await this.blockByNumber(blockNumber), () => `Block not found [${blockNumber}]`)[0].chain;
1501
+ return blockNumber === "latest" ? (await this.finalizationViewer.headBlock()).chain : assertEx12(await this.blockByNumber(blockNumber), () => `Block not found [${blockNumber}]`)[0].chain;
1419
1502
  }, this.context);
1420
1503
  }
1421
1504
  async createHandler() {
@@ -1443,9 +1526,9 @@ var SimpleBlockViewer = class extends AbstractCreatableProvider {
1443
1526
  remainingHashes = remainingHashes.filter((h) => !cachedHashes.has(h));
1444
1527
  const finalizedPayloads = remainingHashes.length > 0 ? await this.finalizedArchivist.get(remainingHashes) : [];
1445
1528
  const resultPayloads = [...cachedPayloads, ...finalizedPayloads.filter(exists)];
1446
- resultPayloads.map((payload) => {
1529
+ for (const payload of resultPayloads) {
1447
1530
  this.payloadCache.set(payload._hash, payload);
1448
- });
1531
+ }
1449
1532
  return resultPayloads;
1450
1533
  }
1451
1534
  async rate(range, timeUnit) {
@@ -1527,7 +1610,7 @@ SimpleBlockViewer = __decorateClass([
1527
1610
  ], SimpleBlockViewer);
1528
1611
 
1529
1612
  // src/simple/chainContractViewer/SimpleChainContractViewer.ts
1530
- import { assertEx as assertEx12 } from "@xylabs/sdk-js";
1613
+ import { assertEx as assertEx13 } from "@xylabs/sdk-js";
1531
1614
  import { ChainContractViewerMoniker, FinalizationViewerMoniker as FinalizationViewerMoniker2 } from "@xyo-network/xl1-protocol-lib";
1532
1615
  var SimpleChainContractViewer = class extends AbstractCreatableProvider {
1533
1616
  moniker = SimpleChainContractViewer.defaultMoniker;
@@ -1544,7 +1627,7 @@ var SimpleChainContractViewer = class extends AbstractCreatableProvider {
1544
1627
  let contractViewer = this;
1545
1628
  let forkedAtBlockNumber = await contractViewer.forkedAtBlockNumber();
1546
1629
  while (forkedAtBlockNumber !== null && blockNumber <= forkedAtBlockNumber) {
1547
- contractViewer = assertEx12(await contractViewer.forkedChainContractViewer());
1630
+ contractViewer = assertEx13(await contractViewer.forkedChainContractViewer());
1548
1631
  forkedAtBlockNumber = await contractViewer.forkedAtBlockNumber();
1549
1632
  chainId = await contractViewer.chainId();
1550
1633
  }
@@ -1585,7 +1668,7 @@ SimpleChainContractViewer = __decorateClass([
1585
1668
  ], SimpleChainContractViewer);
1586
1669
 
1587
1670
  // src/simple/finalization/SimpleFinalizationViewer.ts
1588
- import { assertEx as assertEx13 } from "@xylabs/sdk-js";
1671
+ import { assertEx as assertEx14 } from "@xylabs/sdk-js";
1589
1672
  import {
1590
1673
  asSignedHydratedBlockWithStorageMeta as asSignedHydratedBlockWithStorageMeta2,
1591
1674
  ChainContractViewerMoniker as ChainContractViewerMoniker2,
@@ -1614,7 +1697,7 @@ var SimpleFinalizationViewer = class extends AbstractCreatableProvider {
1614
1697
  static async paramsHandler(params) {
1615
1698
  return {
1616
1699
  ...await super.paramsHandler(params),
1617
- finalizedArchivist: assertEx13(params.finalizedArchivist, () => "finalizedArchivist is required")
1700
+ finalizedArchivist: assertEx14(params.finalizedArchivist, () => "finalizedArchivist is required")
1618
1701
  };
1619
1702
  }
1620
1703
  chainId() {
@@ -1622,18 +1705,18 @@ var SimpleFinalizationViewer = class extends AbstractCreatableProvider {
1622
1705
  }
1623
1706
  async createHandler() {
1624
1707
  await super.createHandler();
1625
- this._chainId = assertEx13(this.config.chain.id ?? (await findMostRecentBlock(this.params.finalizedArchivist))?.chain, () => "chain.id is required if empty archivist");
1708
+ this._chainId = assertEx14(this.config.chain.id ?? (await findMostRecentBlock(this.params.finalizedArchivist))?.chain, () => "chain.id is required if empty archivist");
1626
1709
  this._store = { chainMap: this.params.finalizedArchivist };
1627
1710
  }
1628
1711
  async head() {
1629
1712
  return await this.spanAsync("head", async () => {
1630
- const currentHead = assertEx13(await this.getCurrentHead(), () => "Could not find most recent block [currentBlock]");
1713
+ const currentHead = assertEx14(await this.getCurrentHead(), () => "Could not find most recent block [currentBlock]");
1631
1714
  const cache = this.hydratedBlockCache;
1632
1715
  const block = await cache.get(currentHead._hash);
1633
1716
  if (!block) {
1634
1717
  this.logger?.error(`Could not find current block with hash ${currentHead._hash}`);
1635
1718
  }
1636
- return assertEx13(block, () => "Could not find current block");
1719
+ return assertEx14(block, () => "Could not find current block");
1637
1720
  }, this.context);
1638
1721
  }
1639
1722
  async headBlock() {
@@ -1659,8 +1742,8 @@ var SimpleFinalizationViewer = class extends AbstractCreatableProvider {
1659
1742
  }
1660
1743
  async getCurrentHead() {
1661
1744
  const chainArchivist = this.finalizedArchivist;
1662
- const result = assertEx13(await findMostRecentBlock(chainArchivist), () => "Could not find most recent block [getCurrentHead]");
1663
- assertEx13(result?.chain === this._chainId, () => "Chain ID does not match head block chain ID");
1745
+ const result = assertEx14(await findMostRecentBlock(chainArchivist), () => "Could not find most recent block [getCurrentHead]");
1746
+ assertEx14(result?.chain === this._chainId, () => "Chain ID does not match head block chain ID");
1664
1747
  return result;
1665
1748
  }
1666
1749
  };
@@ -1672,16 +1755,16 @@ SimpleFinalizationViewer = __decorateClass([
1672
1755
  ], SimpleFinalizationViewer);
1673
1756
 
1674
1757
  // src/test/buildRandomChain.ts
1675
- import { asAddress as asAddress2, assertEx as assertEx16 } from "@xylabs/sdk-js";
1758
+ import { asAddress as asAddress2, assertEx as assertEx17 } from "@xylabs/sdk-js";
1676
1759
  import {
1677
1760
  Account as Account3,
1678
- asSchema as asSchema2,
1761
+ asSchema as asSchema3,
1679
1762
  IdSchema as IdSchema2,
1680
1763
  MemoryArchivist,
1681
1764
  PayloadBuilder as PayloadBuilder8
1682
1765
  } from "@xyo-network/sdk-js";
1683
1766
  import {
1684
- asXL1BlockNumber as asXL1BlockNumber7
1767
+ asXL1BlockNumber as asXL1BlockNumber9
1685
1768
  } from "@xyo-network/xl1-protocol-lib";
1686
1769
 
1687
1770
  // src/test/buildNextBlock.ts
@@ -1691,19 +1774,19 @@ import {
1691
1774
  } from "@xyo-network/xl1-protocol-lib";
1692
1775
 
1693
1776
  // src/test/buildBlock.ts
1694
- import { assertEx as assertEx14, isDefined as isDefined8 } from "@xylabs/sdk-js";
1777
+ import { assertEx as assertEx15, isDefined as isDefined7 } from "@xylabs/sdk-js";
1695
1778
  import {
1696
1779
  asAnyPayload as asAnyPayload3,
1697
1780
  BoundWitnessBuilder as BoundWitnessBuilder2,
1698
1781
  PayloadBuilder as PayloadBuilder4
1699
1782
  } from "@xyo-network/sdk-js";
1700
1783
  import {
1701
- asXL1BlockNumber as asXL1BlockNumber4,
1784
+ asXL1BlockNumber as asXL1BlockNumber6,
1702
1785
  AttoXL1,
1703
1786
  isBlockBoundWitness,
1704
1787
  rewardAddressFromStepIdentity,
1705
1788
  StepRewardFractions,
1706
- StepSizes as StepSizes3,
1789
+ StepSizes as StepSizes6,
1707
1790
  XL1_PROTOCOL_VERSION,
1708
1791
  XYO_STEP_REWARD_ADDRESS,
1709
1792
  XYO_ZERO_ADDRESS
@@ -1763,7 +1846,7 @@ function calculateCompletedStepReward(step, balance) {
1763
1846
  }
1764
1847
  async function buildBlock(options) {
1765
1848
  const previousBlockNumber = isBuildGenesisBlockOptions(options) ? -1 : options.previousBlockNumber;
1766
- const blockNumber = asXL1BlockNumber4(previousBlockNumber + 1, true);
1849
+ const blockNumber = asXL1BlockNumber6(previousBlockNumber + 1, true);
1767
1850
  const inStepHashes = isBuildNextBlockOptions(options) ? options.previousStepHashes : [];
1768
1851
  const previousBlockHash = isBuildNextBlockOptions(options) ? options.previousBlockHash : void 0;
1769
1852
  const stepRewardPoolBalance = isBuildNextBlockOptions(options) ? options.stepRewardPoolBalance : AttoXL1(0n);
@@ -1785,7 +1868,7 @@ async function buildBlock(options) {
1785
1868
  }
1786
1869
  }
1787
1870
  const completedStepRewardTransfers = [];
1788
- for (const [i, step] of StepSizes3.entries()) {
1871
+ for (const [i, step] of StepSizes6.entries()) {
1789
1872
  if (blockNumber < step) {
1790
1873
  break;
1791
1874
  }
@@ -1795,9 +1878,9 @@ async function buildBlock(options) {
1795
1878
  const completedStepReward = calculateCompletedStepReward(i, stepRewardPoolBalance);
1796
1879
  completedStepRewardTransfers.push(createTransferPayload(chainStepRewardAddress, { [completedStepRewardHolderAddress]: completedStepReward }));
1797
1880
  }
1798
- step_hashes.push(assertEx14(previousBlockHash, () => `Previous block hash is required for step ${step} at block ${blockNumber}`));
1881
+ step_hashes.push(assertEx15(previousBlockHash, () => `Previous block hash is required for step ${step} at block ${blockNumber}`));
1799
1882
  } else {
1800
- if (isDefined8(inStepHashes.at(i))) {
1883
+ if (isDefined7(inStepHashes.at(i))) {
1801
1884
  step_hashes.push(inStepHashes[i]);
1802
1885
  }
1803
1886
  }
@@ -1818,7 +1901,7 @@ async function buildBlock(options) {
1818
1901
  step_hashes,
1819
1902
  protocol
1820
1903
  }).meta({ $epoch: Date.now(), $signatures: [] }).signers(signers).payloads(await PayloadBuilder4.addStorageMeta(payloads)).build();
1821
- assertEx14(isBlockBoundWitness(bw), () => "Build of BlockBoundWitness failed");
1904
+ assertEx15(isBlockBoundWitness(bw), () => "Build of BlockBoundWitness failed");
1822
1905
  return [await PayloadBuilder4.addStorageMeta(bw), txPayloads.map((p) => asAnyPayload3(p, true))];
1823
1906
  }
1824
1907
 
@@ -1839,16 +1922,16 @@ async function buildNextBlock(previousBlock, txs, blockPayloads, signers, chainS
1839
1922
  }
1840
1923
 
1841
1924
  // src/test/buildRandomGenesisBlock.ts
1842
- import { asAddress, assertEx as assertEx15 } from "@xylabs/sdk-js";
1925
+ import { asAddress, assertEx as assertEx16 } from "@xylabs/sdk-js";
1843
1926
  import {
1844
1927
  Account as Account2,
1845
1928
  asAnyPayload as asAnyPayload4,
1846
- asSchema,
1929
+ asSchema as asSchema2,
1847
1930
  IdSchema,
1848
1931
  PayloadBuilder as PayloadBuilder5
1849
1932
  } from "@xyo-network/sdk-js";
1850
1933
  import {
1851
- asXL1BlockNumber as asXL1BlockNumber5
1934
+ asXL1BlockNumber as asXL1BlockNumber7
1852
1935
  } from "@xyo-network/xl1-protocol-lib";
1853
1936
 
1854
1937
  // src/test/buildGenesisBlock.ts
@@ -1866,7 +1949,7 @@ async function buildGenesisBlock(chainId, txs, blockPayloads, signers, chainStep
1866
1949
  }
1867
1950
 
1868
1951
  // src/test/buildRandomGenesisBlock.ts
1869
- var TestChainId = assertEx15(asAddress("c5fe2e6F6841Cbab12d8C0618Be2DF8C6156cC44"));
1952
+ var TestChainId = assertEx16(asAddress("c5fe2e6F6841Cbab12d8C0618Be2DF8C6156cC44"));
1870
1953
 
1871
1954
  // src/test/createGenesisBlock.ts
1872
1955
  import { PayloadBuilder as PayloadBuilder7 } from "@xyo-network/sdk-js";
@@ -1883,7 +1966,7 @@ import {
1883
1966
  // src/test/createProducerChainStakeIntentTransaction.ts
1884
1967
  import { PayloadBuilder as PayloadBuilder6 } from "@xyo-network/sdk-js";
1885
1968
  import {
1886
- asXL1BlockNumber as asXL1BlockNumber6,
1969
+ asXL1BlockNumber as asXL1BlockNumber8,
1887
1970
  ChainStakeIntentSchema,
1888
1971
  defaultTransactionFees as defaultTransactionFees2
1889
1972
  } from "@xyo-network/xl1-protocol-lib";
@@ -1919,7 +2002,7 @@ var createGenesisBlock = async (initialBlockProducer, nextContractAddress, genes
1919
2002
  };
1920
2003
 
1921
2004
  // src/test/buildRandomChain.ts
1922
- var TestGenesisBlockRewardAddress = assertEx16(asAddress2("fa7f0bb865a4bfff3d5e2c726d3e063297014da9"));
2005
+ var TestGenesisBlockRewardAddress = assertEx17(asAddress2("fa7f0bb865a4bfff3d5e2c726d3e063297014da9"));
1923
2006
  var buildRandomChain = async (blockProducer, count = 10, previousBlock, chainId, transactionAccount, receiverAddresses) => {
1924
2007
  const chainIdToUse = chainId ?? TestChainId;
1925
2008
  const blocks = [];
@@ -1943,20 +2026,20 @@ var buildRandomChain = async (blockProducer, count = 10, previousBlock, chainId,
1943
2026
  saltCounter += 1;
1944
2027
  const payloads = [new PayloadBuilder8({ schema: IdSchema2 }).fields({ salt: `${Date.now()}-${saltCounter}` }).build()];
1945
2028
  saltCounter += 1;
1946
- const additionalPrivatePayloads = remaining % 2 === 0 ? [new PayloadBuilder8({ schema: asSchema2("network.xyo.private", true) }).fields({ salt: `${Date.now()}-${saltCounter}` }).build()] : [];
2029
+ const additionalPrivatePayloads = remaining % 2 === 0 ? [new PayloadBuilder8({ schema: asSchema3("network.xyo.private", true) }).fields({ salt: `${Date.now()}-${saltCounter}` }).build()] : [];
1947
2030
  const txs = [];
1948
2031
  for (const receiverAddress of resolvedReceiverAddresses) {
1949
2032
  txs.push(await buildRandomTransaction(
1950
2033
  chainIdToUse,
1951
2034
  [...payloads, ...additionalPrivatePayloads],
1952
2035
  transactionAccountToUse,
1953
- asXL1BlockNumber7(Math.max(count - remaining - 1e3, 0), true),
1954
- asXL1BlockNumber7(count - remaining + 1e3, true),
1955
- [asSchema2("network.xyo.private", true)],
2036
+ asXL1BlockNumber9(Math.max(count - remaining - 1e3, 0), true),
2037
+ asXL1BlockNumber9(count - remaining + 1e3, true),
2038
+ [asSchema3("network.xyo.private", true)],
1956
2039
  receiverAddress
1957
2040
  ));
1958
2041
  }
1959
- const previousBlock2 = assertEx16(lastBlock?.[0], () => new Error("No last block"));
2042
+ const previousBlock2 = assertEx17(lastBlock?.[0], () => new Error("No last block"));
1960
2043
  const block = await buildNextBlock(previousBlock2, txs, [], [blockProducer], transactionAccountToUse.address);
1961
2044
  blocks.push(block);
1962
2045
  remaining = remaining - 1;