@xyo-network/xl1-cli 5.1.1 → 5.2.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/dist/cli-min.mjs CHANGED
@@ -66368,7 +66368,7 @@ config$1(en_default());
66368
66368
  //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js
66369
66369
  var zod_default = external_exports;
66370
66370
  //#endregion
66371
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-protocol@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4._fbc42be6f32cdaed5463bdb0247640b5/node_modules/@xyo-network/xl1-protocol/dist/neutral/protocol-model.mjs
66371
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-protocol@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4._8d90734bf06d8373d67780d6e09d467a/node_modules/@xyo-network/xl1-protocol/dist/neutral/protocol-model.mjs
66372
66372
  var ExchangeOutcomeSchema$1 = asSchema$1("network.xyo.exchange.outcome", true);
66373
66373
  var isExchangeOutcome$1 = isPayloadOfZodType$1(/* @__PURE__ */ object$5({
66374
66374
  /** Hash of the ExchangeTerms payload this outcome settles */
@@ -67254,7 +67254,7 @@ var TransactionRejectionSchema$1 = asSchema$1("network.xyo.transaction.rejection
67254
67254
  var isTransactionRejection$1 = isPayloadOfSchemaType$1(TransactionRejectionSchema$1);
67255
67255
  AsObjectFactory.create(isTransactionRejection$1);
67256
67256
  //#endregion
67257
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-protocol@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4._fbc42be6f32cdaed5463bdb0247640b5/node_modules/@xyo-network/xl1-protocol/dist/neutral/protocol-lib.mjs
67257
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-protocol@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4._8d90734bf06d8373d67780d6e09d467a/node_modules/@xyo-network/xl1-protocol/dist/neutral/protocol-lib.mjs
67258
67258
  function derivedReceiveAddress(address, scope) {
67259
67259
  return toAddress(keccak256(new TextEncoder().encode(isDefined$1(scope) ? `${scope}|${address}` : address)).slice(-40), { prefix: false });
67260
67260
  }
@@ -67290,6 +67290,20 @@ var NetworkStakeRewardsIndexPublishRunnerMoniker = "NetworkStakeRewardsIndexPubl
67290
67290
  var SystemStatusRunnerMoniker = "SystemStatusRunner";
67291
67291
  var SystemStatusViewerMoniker$1 = "SystemStatusViewer";
67292
67292
  var SystemStatusPublisherMoniker = "SystemStatusPublisher";
67293
+ var FinalizedBlockStreamMoniker$1 = "FinalizedBlockStream";
67294
+ var FinalizedBlockStreamDesyncError$1 = class extends Error {
67295
+ /** The block whose `previous` did not match, when it could be fetched. */
67296
+ block;
67297
+ /** The hash the walk expected the next block's `previous` to be. */
67298
+ expectedPrevious;
67299
+ constructor(expectedPrevious, block) {
67300
+ const found = block ? `found ${block[0].previous} at block ${block[0].block}` : "no block found";
67301
+ super(`FinalizedBlockStream desynced: expected previous ${expectedPrevious}, ${found}`);
67302
+ this.name = "FinalizedBlockStreamDesyncError";
67303
+ this.expectedPrevious = expectedPrevious;
67304
+ this.block = block;
67305
+ }
67306
+ };
67293
67307
  var BlocksStepSummarySchema$1 = asSchema$1("network.xyo.step.summary.blocks", true);
67294
67308
  var isBlocksStepSummary$1 = isPayloadOfSchemaType$1(BlocksStepSummarySchema$1);
67295
67309
  var asBlocksStepSummary$1 = AsObjectFactory.create(isBlocksStepSummary$1);
@@ -67498,7 +67512,7 @@ var TransactionValidationViewerMoniker$1 = "TransactionValidationViewer";
67498
67512
  var WindowedBlockViewerMoniker$1 = "WindowedBlockViewer";
67499
67513
  var XyoViewerMoniker$1 = "XyoViewer";
67500
67514
  //#endregion
67501
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-protocol@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4._fbc42be6f32cdaed5463bdb0247640b5/node_modules/@xyo-network/xl1-protocol/dist/neutral/network-model.mjs
67515
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-protocol@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4._8d90734bf06d8373d67780d6e09d467a/node_modules/@xyo-network/xl1-protocol/dist/neutral/network-model.mjs
67502
67516
  var local_default = "<svg id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 256 256\"><g style=\"opacity:.5;\"><path d=\"M154.71,97c.46,2.59,2.5,4.62,5.1,5.05l14.05,2.34,31.71-46.17c4.57-6.65-3.62-14.62-10.14-9.87l-43.68,31.83,2.97,16.82Z\" style=\"fill:#f47f00;\"/><path d=\"M173.86,151.62l-14.05,2.34c-2.6.43-4.64,2.45-5.1,5.05l-2.97,16.82,43.68,31.83c6.52,4.75,14.71-3.21,10.14-9.87l-31.71-46.17Z\" style=\"fill:#f47f00;\"/><path d=\"M82.14,104.38l14.05-2.34c2.6-.43,4.64-2.45,5.1-5.05l2.97-16.82-43.68-31.83c-6.52-4.75-14.71,3.21-10.14,9.87l31.71,46.17Z\" style=\"fill:#f47f00;\"/><path d=\"M101.29,159c-.46-2.59-2.5-4.62-5.1-5.05l-14.05-2.34-31.71,46.17c-4.57,6.65,3.62,14.62,10.14,9.87l43.68-31.83-2.97-16.82Z\" style=\"fill:#f47f00;\"/></g><path d=\"M107.33,104l15.94-90.32c.93-5.3,8.53-5.3,9.47,0l15.94,90.32c.35,2.01,1.94,3.57,3.95,3.91l92.24,15.35c5.36.89,5.36,8.59,0,9.49l-92.24,15.35c-2.01.33-3.59,1.9-3.95,3.91l-15.94,90.32c-.93,5.3-8.53,5.3-9.47,0l-15.94-90.32c-.35-2.01-1.94-3.57-3.95-3.91l-92.24-15.35c-5.36-.89-5.36-8.59,0-9.49l92.24-15.35c2.01-.33,3.59-1.9,3.95-3.91Z\" style=\"fill:#f47f00;\"/></svg>";
67503
67517
  var mainnet_default = "<svg id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 256 256\"><path d=\"M154.71,97c.46,2.59,2.5,4.62,5.1,5.05l14.05,2.34,31.71-46.17c4.57-6.65-3.62-14.62-10.14-9.87l-43.68,31.83,2.97,16.82Z\" style=\"fill:#8d8fc6;\"/><path d=\"M173.86,151.62l-14.05,2.34c-2.6.43-4.64,2.45-5.1,5.05l-2.97,16.82,43.68,31.83c6.52,4.75,14.71-3.21,10.14-9.87l-31.71-46.17Z\" style=\"fill:#eb407a;\"/><path d=\"M82.14,104.38l14.05-2.34c2.6-.43,4.64-2.45,5.1-5.05l2.97-16.82-43.68-31.83c-6.52-4.75-14.71,3.21-10.14,9.87l31.71,46.17Z\" style=\"fill:#579fd6;\"/><path d=\"M101.29,159c-.46-2.59-2.5-4.62-5.1-5.05l-14.05-2.34-31.71,46.17c-4.57,6.65,3.62,14.62,10.14,9.87l43.68-31.83-2.97-16.82Z\" style=\"fill:#f27046;\"/><path d=\"M107.33,104l15.94-90.32c.93-5.3,8.53-5.3,9.47,0l15.94,90.32c.35,2.01,1.94,3.57,3.95,3.91l92.24,15.35c5.36.89,5.36,8.59,0,9.49l-92.24,15.35c-2.01.33-3.59,1.9-3.95,3.91l-15.94,90.32c-.93,5.3-8.53,5.3-9.47,0l-15.94-90.32c-.35-2.01-1.94-3.57-3.95-3.91l-92.24-15.35c-5.36-.89-5.36-8.59,0-9.49l92.24-15.35c2.01-.33,3.59-1.9,3.95-3.91Z\" style=\"fill:#572aff;\"/></svg>";
67504
67518
  var testnet_default = "<svg id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 256 256\"><g style=\"opacity:.5;\"><path d=\"M154.71,97c.46,2.59,2.5,4.62,5.1,5.05l14.05,2.34,31.71-46.17c4.57-6.65-3.62-14.62-10.14-9.87l-43.68,31.83,2.97,16.82Z\" style=\"fill:#579fd6;\"/><path d=\"M173.86,151.62l-14.05,2.34c-2.6.43-4.64,2.45-5.1,5.05l-2.97,16.82,43.68,31.83c6.52,4.75,14.71-3.21,10.14-9.87l-31.71-46.17Z\" style=\"fill:#579fd6;\"/><path d=\"M82.14,104.38l14.05-2.34c2.6-.43,4.64-2.45,5.1-5.05l2.97-16.82-43.68-31.83c-6.52-4.75-14.71,3.21-10.14,9.87l31.71,46.17Z\" style=\"fill:#579fd6;\"/><path d=\"M101.29,159c-.46-2.59-2.5-4.62-5.1-5.05l-14.05-2.34-31.71,46.17c-4.57,6.65,3.62,14.62,10.14,9.87l43.68-31.83-2.97-16.82Z\" style=\"fill:#579fd6;\"/></g><path d=\"M107.33,104l15.94-90.32c.93-5.3,8.53-5.3,9.47,0l15.94,90.32c.35,2.01,1.94,3.57,3.95,3.91l92.24,15.35c5.36.89,5.36,8.59,0,9.49l-92.24,15.35c-2.01.33-3.59,1.9-3.95,3.91l-15.94,90.32c-.93,5.3-8.53,5.3-9.47,0l-15.94-90.32c-.35-2.01-1.94-3.57-3.95-3.91l-92.24-15.35c-5.36-.89-5.36-8.59,0-9.49l92.24-15.35c2.01-.33,3.59-1.9,3.95-3.91Z\" style=\"fill:#579fd6;\"/></svg>";
@@ -68148,7 +68162,7 @@ function admissionShadowHeadPath() {
68148
68162
  return "admission/shadow/head.json";
68149
68163
  }
68150
68164
  //#endregion
68151
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-protocol@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4._fbc42be6f32cdaed5463bdb0247640b5/node_modules/@xyo-network/xl1-protocol/dist/neutral/schema.mjs
68165
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-protocol@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4._8d90734bf06d8373d67780d6e09d467a/node_modules/@xyo-network/xl1-protocol/dist/neutral/schema.mjs
68152
68166
  var asRequiredStrings = (required) => {
68153
68167
  if (typeof required === "string") return [required];
68154
68168
  if (!Array.isArray(required)) return [];
@@ -68384,7 +68398,7 @@ var TransferPayloadJsonSchema = {
68384
68398
  };
68385
68399
  var TransferPayloadJsonSchemaPayload = new PayloadBuilder$1({ schema: SchemaSchema$1 }).fields({ definition: TransferPayloadJsonSchema }).build();
68386
68400
  //#endregion
68387
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-protocol@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4._fbc42be6f32cdaed5463bdb0247640b5/node_modules/@xyo-network/xl1-protocol/dist/neutral/validation.mjs
68401
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-protocol@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4._8d90734bf06d8373d67780d6e09d467a/node_modules/@xyo-network/xl1-protocol/dist/neutral/validation.mjs
68388
68402
  function maxTransactionFeeCost(tx) {
68389
68403
  const { base, gasLimit, priority } = tx.fees;
68390
68404
  return hexToBigInt(base) + hexToBigInt(priority) + hexToBigInt(gasLimit);
@@ -68630,7 +68644,7 @@ var validateTransaction = async (context, tx, additionalValidators) => {
68630
68644
  }
68631
68645
  };
68632
68646
  //#endregion
68633
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_f803ff54f950c092c4a357d77886b418/node_modules/@xyo-network/xl1-sdk/dist/neutral/driver-memory.mjs
68647
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_3a01f3229f2daa942444e08696345b23/node_modules/@xyo-network/xl1-sdk/dist/neutral/driver-memory.mjs
68634
68648
  var LruCacheMap$1 = class {
68635
68649
  lruCache;
68636
68650
  /** Creates an instance with the supplied configuration. */
@@ -71814,7 +71828,7 @@ var require_ExplorerSync = /* @__PURE__ */ __commonJSMin(((exports) => {
71814
71828
  exports.ExplorerSync = ExplorerSync;
71815
71829
  }));
71816
71830
  //#endregion
71817
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_f803ff54f950c092c4a357d77886b418/node_modules/@xyo-network/xl1-sdk/dist/node/protocol-sdk.mjs
71831
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_3a01f3229f2daa942444e08696345b23/node_modules/@xyo-network/xl1-sdk/dist/node/protocol-sdk.mjs
71818
71832
  var import_dist = (/* @__PURE__ */ __commonJSMin(((exports) => {
71819
71833
  Object.defineProperty(exports, "__esModule", { value: true });
71820
71834
  exports.defaultLoadersSync = exports.defaultLoaders = exports.globalConfigSearchPlacesSync = exports.globalConfigSearchPlaces = exports.getDefaultSearchPlacesSync = exports.getDefaultSearchPlaces = exports.cosmiconfigSync = exports.cosmiconfig = void 0;
@@ -73065,21 +73079,47 @@ function blocksToChains$1(blocks) {
73065
73079
  }
73066
73080
  return chains;
73067
73081
  }
73068
- function toValidUncle$1(_context, finalizedWindowedChain, possibleUncle) {
73082
+ function toValidUncle$1(_context, finalizedWindowedChain, possibleUncle, onReject) {
73069
73083
  const finalizedWindowStartBlockNumber = finalizedWindowedChain.at(0)?.[0].block ?? -1;
73070
73084
  const finalizedHead = assertEx$1(finalizedWindowedChain.at(-1), () => "finalizedWindowedChain is empty");
73085
+ const tip = assertEx$1(possibleUncle.at(-1), () => "possibleUncle is empty");
73086
+ const reject = (reason, offendingTransactionHashes) => {
73087
+ onReject?.({
73088
+ blockHash: tip[0]._hash,
73089
+ blockNumber: tip[0].block,
73090
+ offendingTransactionHashes,
73091
+ reason
73092
+ });
73093
+ };
73071
73094
  const prunedPossibleUncle = possibleUncle.filter((b) => b[0].block > finalizedHead[0].block);
73072
- if (prunedPossibleUncle.length === 0) return;
73073
- if (prunedPossibleUncle[0][0].block !== finalizedHead[0].block + 1) return;
73074
- if (prunedPossibleUncle[0][0].previous !== finalizedHead[0]._hash) return;
73095
+ if (prunedPossibleUncle.length === 0) {
73096
+ reject("behind-finalized-head");
73097
+ return;
73098
+ }
73099
+ if (prunedPossibleUncle[0][0].block !== finalizedHead[0].block + 1) {
73100
+ reject("block-number-mismatch");
73101
+ return;
73102
+ }
73103
+ if (prunedPossibleUncle[0][0].previous !== finalizedHead[0]._hash) {
73104
+ reject("previous-hash-mismatch");
73105
+ return;
73106
+ }
73075
73107
  const allUncleTransactions = prunedPossibleUncle.flatMap((b) => b[1]).filter(isTransactionBoundWitness$1);
73076
73108
  const allFinalizedTransactions = finalizedWindowedChain.flatMap((b) => b[1]).filter(isTransactionBoundWitness$1);
73077
- if (allUncleTransactions.some((tx) => tx.nbf < finalizedWindowStartBlockNumber)) return;
73078
- if (allUncleTransactions.some((tx) => allFinalizedTransactions.some((finalTx) => finalTx._hash === tx._hash))) return;
73109
+ const txsBeforeWindow = allUncleTransactions.filter((tx) => tx.nbf < finalizedWindowStartBlockNumber);
73110
+ if (txsBeforeWindow.length > 0) {
73111
+ reject("tx-before-window", txsBeforeWindow.map((tx) => tx._hash));
73112
+ return;
73113
+ }
73114
+ const txsInWindow = allUncleTransactions.filter((tx) => allFinalizedTransactions.some((finalTx) => finalTx._hash === tx._hash));
73115
+ if (txsInWindow.length > 0) {
73116
+ reject("tx-already-finalized", txsInWindow.map((tx) => tx._hash));
73117
+ return;
73118
+ }
73079
73119
  return prunedPossibleUncle;
73080
73120
  }
73081
- function findUncles$1(context, finalizedWindowedChain, blocks) {
73082
- return blocksToChains$1(blocks).map((chain) => toValidUncle$1(context, finalizedWindowedChain, chain)).filter(exists$1);
73121
+ function findUncles$1(context, finalizedWindowedChain, blocks, onReject) {
73122
+ return blocksToChains$1(blocks).map((chain) => toValidUncle$1(context, finalizedWindowedChain, chain, onReject)).filter(exists$1);
73083
73123
  }
73084
73124
  var ValidationConfigZod$1 = object$3({
73085
73125
  signerAuthorizations: array$1(SignerAuthorizationZod$1).default([]).register(globalRegistry, {
@@ -73933,6 +73973,21 @@ async function buildUnsignedTransaction(chain, onChainPayloads, offChainPayloads
73933
73973
  }
73934
73974
  var DEFAULT_CONFIRMATION_ATTEMPTS = 20;
73935
73975
  var DEFAULT_DELAY_BETWEEN_ATTEMPTS = 1e3;
73976
+ var TransactionConfirmationTimeoutError = class extends Error {
73977
+ /** Number of confirmation attempts made before giving up. */
73978
+ attempts;
73979
+ /** Marks the negative result as inconclusive: the transaction may still be pending or included later. */
73980
+ inconclusive = true;
73981
+ /** Hash of the transaction whose confirmation timed out. */
73982
+ txHash;
73983
+ /** Creates an instance for the given transaction and attempt count. */
73984
+ constructor(txHash, attempts) {
73985
+ super(`Transaction ${txHash} not confirmed after ${attempts} attempts \u2014 inconclusive: the transaction may still be pending or included later`);
73986
+ this.name = "TransactionConfirmationTimeoutError";
73987
+ this.attempts = attempts;
73988
+ this.txHash = txHash;
73989
+ }
73990
+ };
73936
73991
  var assertNotExpired = async (viewer, txHash, exp, options) => {
73937
73992
  const head = await viewer.currentBlockNumber();
73938
73993
  if (head > exp) {
@@ -73953,8 +74008,8 @@ var confirmSubmittedTransaction = async (viewer, txHash, options) => {
73953
74008
  if (isNumber(exp)) await assertNotExpired(viewer, txHash, exp, options);
73954
74009
  attempts++;
73955
74010
  if (attempts > maxAttempts) {
73956
- options?.logger?.error(`\u26A0\uFE0F Transaction not confirmed after ${maxAttempts} attempts`);
73957
- throw new Error(`Transaction ${txHash} not confirmed after ${maxAttempts} attempts`);
74011
+ options?.logger?.error(`\u26A0\uFE0F Transaction not confirmed after ${maxAttempts} attempts (inconclusive \u2014 it may still be pending)`);
74012
+ throw new TransactionConfirmationTimeoutError(txHash, maxAttempts);
73958
74013
  }
73959
74014
  options?.logger?.debug(`Transaction not confirmed yet, attempt ${attempts}. Retrying...`, txHash);
73960
74015
  await delay$2(attemptDelay);
@@ -75206,6 +75261,7 @@ var SimpleBlockValidationViewer$1 = class extends AbstractCreatableProvider$1 {
75206
75261
  state: true,
75207
75262
  head: void 0
75208
75263
  };
75264
+ if (config !== void 0 && value !== true && state !== true) this.logger?.warn("validateBlocks called with a config that selects no validators (neither value nor state is true) — every block will report valid");
75209
75265
  const blocksWithMeta = await Promise.all(blocks.map((b) => Promise.all([PayloadBuilder$1.addHashMeta(b[0]), PayloadBuilder$1.addHashMeta(b[1])])));
75210
75266
  let head;
75211
75267
  if (isChainQualifiedHeadConfig$1(config)) {
@@ -75254,18 +75310,30 @@ var SimpleBlockValidationViewer$1 = class extends AbstractCreatableProvider$1 {
75254
75310
  }
75255
75311
  async doValidateState(blocks, chainIdAtBlockNumber) {
75256
75312
  const windowedUncleChain = await this.updateWindowedChainCache();
75257
- const uncles = findUncles$1(this.context, windowedUncleChain, blocks);
75313
+ const rejections = [];
75314
+ const uncles = findUncles$1(this.context, windowedUncleChain, blocks, (rejection) => rejections.push(rejection));
75258
75315
  if (uncles.length !== 1) {
75259
- this.logger?.warn(`Unexpected uncle count during block validation [uncles=${uncles.length}, blocks=${blocks.length}]`);
75316
+ const rejectionSummary = rejections.map((r) => `${r.blockNumber} [${r.blockHash}]: ${r.reason}${(r.offendingTransactionHashes?.length ?? 0) > 0 ? ` (tx ${r.offendingTransactionHashes?.join(", ")})` : ""}`).join("; ");
75317
+ this.logger?.warn(`Unexpected uncle count during block validation [uncles=${uncles.length}, blocks=${blocks.length}]` + (rejectionSummary.length > 0 ? ` \u2014 rejected: ${rejectionSummary}` : ""));
75260
75318
  this.logger?.debug(JSON.stringify({
75261
75319
  uncles,
75262
75320
  blocks: blocks.length
75263
75321
  }, null, 2));
75264
75322
  this.logger?.debug(JSON.stringify(windowedUncleChain, null, 2));
75265
- return blocks.map((block) => [new HydratedBlockValidationError$1(block[0]._hash, block, "Unexpected uncle count during state validation", {
75266
- uncles: uncles.length,
75267
- blocks: blocks.length
75268
- })]);
75323
+ return blocks.map((block) => {
75324
+ const rejection = rejections.find((r) => r.blockHash === block[0]._hash);
75325
+ const offendingTransactionHashes = rejection?.offendingTransactionHashes ?? [];
75326
+ if (rejection && offendingTransactionHashes.length > 0) return offendingTransactionHashes.map((txHash) => new HydratedBlockValidationError$1(txHash, block, `Uncle rejected during state validation: ${rejection.reason}`, {
75327
+ blockHash: rejection.blockHash,
75328
+ hash: txHash,
75329
+ reason: rejection.reason
75330
+ }));
75331
+ return [new HydratedBlockValidationError$1(block[0]._hash, block, `Unexpected uncle count during state validation${rejection ? `: ${rejection.reason}` : ""}`, {
75332
+ reason: rejection?.reason,
75333
+ uncles: uncles.length,
75334
+ blocks: blocks.length
75335
+ })];
75336
+ });
75269
75337
  }
75270
75338
  const validateState = assertEx$1(this.validators.blockStateValidator, () => "No block state validator registered");
75271
75339
  return await Promise.all(uncles[0].map(async (block) => {
@@ -76102,6 +76170,303 @@ __publicField$25(SimpleFinalizationViewer$1, "monikers", [FinalizationViewerMoni
76102
76170
  /** Read, write, or mixed capability surface exposed by the provider. */
76103
76171
  __publicField$25(SimpleFinalizationViewer$1, "surface", "node");
76104
76172
  SimpleFinalizationViewer$1 = __decorateClass$26([creatableProvider$1()], SimpleFinalizationViewer$1);
76173
+ var MIN_POLL_INTERVAL_MS$1 = 5e3;
76174
+ var DEFAULT_POLL_INTERVAL_MS$1 = 1e4;
76175
+ var DEFAULT_FETCH_WINDOW$1 = StepSizes$1[2];
76176
+ var MAX_FETCH_WINDOW$1 = StepSizes$1[3];
76177
+ var SimpleFinalizedBlockStreamOptionsZod$1 = object$3({
76178
+ /**
76179
+ * Hot-surface resume checkpoint: emit blocks strictly after this hash, as a
76180
+ * verified splice (the first emission's `previous` must equal it — mismatch
76181
+ * emits `desynced` at startup rather than delivering a diverged chain).
76182
+ * Omitted, the stream starts at the current head, delivered as the first
76183
+ * `nextBlock`.
76184
+ */
76185
+ after: optional$1(HashZod),
76186
+ /**
76187
+ * Upper bound on blocks fetched per `blocksByNumber` window during a walk.
76188
+ * The window adapts to the lag (never fetching past the head) and grows up to
76189
+ * this cap on deep replays, letting REST-backed viewers tile each window from
76190
+ * step rollup files. Capped at the largest served rollup (`StepSizes[3]`);
76191
+ * raise toward it for indexer-style deep replays, lower it to bound memory.
76192
+ */
76193
+ fetchWindow: number$1().int().positive().max(MAX_FETCH_WINDOW$1).default(DEFAULT_FETCH_WINDOW$1),
76194
+ /**
76195
+ * Hot-surface catch-up bound: when the head is further ahead than this, a
76196
+ * `gap` is announced and delivery resumes `maxCatchUp` blocks behind head.
76197
+ * The cold `blocks()` surface ignores this — it never gaps.
76198
+ */
76199
+ maxCatchUp: number$1().int().positive().default(StepSizes$1[1]),
76200
+ /** Head poll cadence shared by the hot surface and all `blocks()` iterations. */
76201
+ pollIntervalMs: number$1().min(MIN_POLL_INTERVAL_MS$1).default(DEFAULT_POLL_INTERVAL_MS$1)
76202
+ });
76203
+ function cursorFromBlock$1(block) {
76204
+ return {
76205
+ block: block[0].block,
76206
+ hash: block[0]._hash
76207
+ };
76208
+ }
76209
+ var SimpleFinalizedBlockStream$1 = class extends AbstractCreatableProvider$1 {
76210
+ /** Moniker implemented by this provider instance. */
76211
+ moniker = FinalizedBlockStreamMoniker$1;
76212
+ _blockViewer;
76213
+ _cursor;
76214
+ _finalizationViewer;
76215
+ _head;
76216
+ _headWaiters = [];
76217
+ _hotLoop;
76218
+ _isLive = false;
76219
+ _options;
76220
+ _pollInProgress = false;
76221
+ _pollTimer = null;
76222
+ _stopping = false;
76223
+ _terminal = false;
76224
+ /** Last position delivered on the hot surface, or `undefined` before the first. */
76225
+ get cursor() {
76226
+ return this._cursor;
76227
+ }
76228
+ /** True once the hot surface has caught up to the live head. */
76229
+ get isLive() {
76230
+ return this._isLive;
76231
+ }
76232
+ get options() {
76233
+ this._options ??= SimpleFinalizedBlockStreamOptionsZod$1.parse(this.config.options);
76234
+ return this._options;
76235
+ }
76236
+ /** Validates the provider options at create time. */
76237
+ static async paramsHandler(params = {}) {
76238
+ const handled = await super.paramsHandler(params);
76239
+ SimpleFinalizedBlockStreamOptionsZod$1.parse(handled.context.config.options);
76240
+ return handled;
76241
+ }
76242
+ /**
76243
+ * Cold, per-caller iteration: replay from `after`, then follow the head.
76244
+ * Gapless by construction — the caller paces the walk. Throws
76245
+ * `FinalizedBlockStreamDesyncError` on any continuity failure, including a
76246
+ * failed resume splice; other (transient) fetch errors also throw, and the
76247
+ * caller resumes from its own checkpoint.
76248
+ */
76249
+ async *blocks(options) {
76250
+ let cursor;
76251
+ if (isDefined$1(options?.after)) cursor = await this.resolveCheckpoint(options.after);
76252
+ else {
76253
+ const head = await this.currentHead();
76254
+ yield {
76255
+ block: head,
76256
+ head: head[0].block
76257
+ };
76258
+ cursor = cursorFromBlock$1(head);
76259
+ }
76260
+ while (!this._stopping) {
76261
+ const headNumber = (await this.currentHead())[0].block;
76262
+ if (cursor.block >= headNumber) {
76263
+ await this.waitForHeadAdvance();
76264
+ continue;
76265
+ }
76266
+ for (const block of await this.nextBlocks(cursor, headNumber)) {
76267
+ cursor = this.advanceCursor(cursor, block);
76268
+ yield {
76269
+ block,
76270
+ head: headNumber
76271
+ };
76272
+ if (this._stopping) return;
76273
+ }
76274
+ }
76275
+ }
76276
+ /** Creates the provider instance after its dependencies and configuration have resolved. */
76277
+ async createHandler() {
76278
+ await super.createHandler();
76279
+ const injected = this.params.viewers;
76280
+ this._blockViewer = injected?.blocks ?? assertEx$1(await this.locator.getInstance("BlockViewer"), () => "BlockViewer instance is required");
76281
+ this._finalizationViewer = injected?.finalization ?? assertEx$1(await this.locator.getInstance("FinalizationViewer"), () => "FinalizationViewer instance is required");
76282
+ }
76283
+ /** Starts the head poll and the hot delivery loop. */
76284
+ async startHandler() {
76285
+ await super.startHandler();
76286
+ this._stopping = false;
76287
+ this._terminal = false;
76288
+ await this.pollHead();
76289
+ this._pollTimer = setInterval(() => {
76290
+ this.pollHead();
76291
+ }, this.options.pollIntervalMs);
76292
+ this._hotLoop = this.runHot();
76293
+ }
76294
+ /** Stops the poll, ends the hot loop, and emits the terminal `stopped` event. */
76295
+ async stopHandler() {
76296
+ this._stopping = true;
76297
+ if (this._pollTimer) {
76298
+ clearInterval(this._pollTimer);
76299
+ this._pollTimer = null;
76300
+ }
76301
+ this.releaseHeadWaiters();
76302
+ await this._hotLoop;
76303
+ this._hotLoop = void 0;
76304
+ if (!this._terminal) {
76305
+ this._terminal = true;
76306
+ await this.emitSerial("stopped", { cursor: this._cursor });
76307
+ }
76308
+ this._head = void 0;
76309
+ await super.stopHandler();
76310
+ }
76311
+ /**
76312
+ * Verifies continuity and advances a cursor to the delivered block. A
76313
+ * `previous` mismatch on the expected block number is a data-integrity
76314
+ * fault; a wrong/missing block number is a transient fetch problem.
76315
+ */
76316
+ advanceCursor(cursor, block) {
76317
+ assertEx$1(block[0].block === cursor.block + 1, () => `FinalizedBlockStream: expected block ${cursor.block + 1}, fetched ${block[0].block}`);
76318
+ if (block[0].previous !== cursor.hash) throw new FinalizedBlockStreamDesyncError$1(cursor.hash, block);
76319
+ return cursorFromBlock$1(block);
76320
+ }
76321
+ /** One hot-loop step: bound the lag (announcing a `gap`), deliver the next window, mark live. */
76322
+ async advanceHot() {
76323
+ const head = await this.currentHead();
76324
+ const headNumber = head[0].block;
76325
+ const cursor = assertEx$1(this._cursor);
76326
+ if (cursor.block >= headNumber) {
76327
+ await this.markLive(head);
76328
+ await this.waitForHeadAdvance();
76329
+ return;
76330
+ }
76331
+ if (headNumber - cursor.block > this.options.maxCatchUp) {
76332
+ await this.announceGap(cursor, headNumber);
76333
+ return;
76334
+ }
76335
+ for (const block of await this.nextBlocks(cursor, headNumber)) {
76336
+ if (this._stopping) return;
76337
+ this._cursor = this.advanceCursor(assertEx$1(this._cursor), block);
76338
+ await this.emitSerial("nextBlock", {
76339
+ block,
76340
+ head: headNumber
76341
+ });
76342
+ }
76343
+ if (assertEx$1(this._cursor).block >= headNumber) await this.markLive(head);
76344
+ }
76345
+ /** Announces a hot-surface gap and splices the shared cursor to `maxCatchUp` behind head. */
76346
+ async announceGap(cursor, headNumber) {
76347
+ const resumeNumber = asXL1BlockNumber$1(headNumber - this.options.maxCatchUp + 1, true);
76348
+ const resumeBlock = assertEx$1(await this._blockViewer.blockByNumber(resumeNumber), () => `FinalizedBlockStream: gap resume block ${resumeNumber} unavailable`);
76349
+ const skipped = [asXL1BlockNumber$1(cursor.block + 1, true), asXL1BlockNumber$1(resumeNumber - 1, true)];
76350
+ this._isLive = false;
76351
+ await this.emitSerial("gap", {
76352
+ before: cursor,
76353
+ resumedAt: cursorFromBlock$1(resumeBlock),
76354
+ skipped
76355
+ });
76356
+ this._cursor = {
76357
+ block: asXL1BlockNumber$1(resumeNumber - 1, true),
76358
+ hash: assertEx$1(resumeBlock[0].previous, () => "FinalizedBlockStream: gap resume block has no previous")
76359
+ };
76360
+ }
76361
+ /** Returns the last polled head, fetching once when no poll has landed yet. */
76362
+ async currentHead() {
76363
+ if (this._head) return this._head;
76364
+ this._head ??= await this._finalizationViewer.head();
76365
+ return this._head;
76366
+ }
76367
+ /** Initializes the hot cursor: verified splice from `after`, or head-first delivery. */
76368
+ async initHotCursor() {
76369
+ const { after } = this.options;
76370
+ if (isDefined$1(after)) {
76371
+ this._cursor = await this.resolveCheckpoint(after);
76372
+ return;
76373
+ }
76374
+ const head = await this.currentHead();
76375
+ this._cursor = cursorFromBlock$1(head);
76376
+ await this.emitSerial("nextBlock", {
76377
+ block: head,
76378
+ head: head[0].block
76379
+ });
76380
+ await this.markLive(head);
76381
+ }
76382
+ /** Marks the hot surface live, emitting the transition once. */
76383
+ async markLive(head) {
76384
+ if (this._isLive) return;
76385
+ this._isLive = true;
76386
+ await this.emitSerial("live", { head: cursorFromBlock$1(head) });
76387
+ }
76388
+ /**
76389
+ * Fetches the ordered run of blocks after `cursor`, up to one window. Order
76390
+ * is normalized here; continuity is verified per block by `advanceCursor`.
76391
+ */
76392
+ async nextBlocks(cursor, headNumber) {
76393
+ const hi = asXL1BlockNumber$1(Math.min(cursor.block + this.options.fetchWindow, headNumber), true);
76394
+ const run = (await this._blockViewer.blocksByNumber(hi, hi - cursor.block)).filter((block) => block[0].block > cursor.block).toSorted((a, b) => a[0].block - b[0].block);
76395
+ assertEx$1(run.length > 0, () => `FinalizedBlockStream: no blocks fetched in (${cursor.block}, ${hi}]`);
76396
+ return run;
76397
+ }
76398
+ /** Polls the finalized head, releasing all cursor walks blocked on head growth. */
76399
+ async pollHead() {
76400
+ if (this._pollInProgress) return;
76401
+ this._pollInProgress = true;
76402
+ try {
76403
+ const head = await this._finalizationViewer.head();
76404
+ if (head[0]._hash !== this._head?.[0]._hash) {
76405
+ this._head = head;
76406
+ this.releaseHeadWaiters();
76407
+ }
76408
+ } catch (ex) {
76409
+ this.logger?.error("FinalizedBlockStream: error polling head", ex);
76410
+ } finally {
76411
+ this._pollInProgress = false;
76412
+ }
76413
+ }
76414
+ releaseHeadWaiters() {
76415
+ const waiters = this._headWaiters.splice(0);
76416
+ for (const release of waiters) release();
76417
+ }
76418
+ /** Resolves a checkpoint hash to a cursor, or throws the desync error a missing checkpoint implies. */
76419
+ async resolveCheckpoint(after) {
76420
+ const checkpoint = await this._blockViewer.blockByHash(after);
76421
+ if (!checkpoint) throw new FinalizedBlockStreamDesyncError$1(after);
76422
+ return cursorFromBlock$1(checkpoint);
76423
+ }
76424
+ /**
76425
+ * The hot delivery loop. Transient errors are logged and retried on the next
76426
+ * head advance; a continuity failure emits the terminal `desynced` event.
76427
+ */
76428
+ async runHot() {
76429
+ try {
76430
+ await this.initHotCursor();
76431
+ while (!this._stopping) try {
76432
+ await this.advanceHot();
76433
+ } catch (ex) {
76434
+ if (ex instanceof FinalizedBlockStreamDesyncError$1) throw ex;
76435
+ if (this._stopping) return;
76436
+ this.logger?.error("FinalizedBlockStream: hot loop error, retrying on next head", ex);
76437
+ await this.waitForHeadAdvance();
76438
+ }
76439
+ } catch (ex) {
76440
+ if (ex instanceof FinalizedBlockStreamDesyncError$1 && !this._terminal) {
76441
+ this._terminal = true;
76442
+ await this.emitSerial("desynced", {
76443
+ block: ex.block,
76444
+ expectedPrevious: ex.expectedPrevious
76445
+ });
76446
+ return;
76447
+ }
76448
+ this.logger?.error("FinalizedBlockStream: hot loop terminated", ex);
76449
+ }
76450
+ }
76451
+ /** Suspends until the polled head changes or the stream stops. */
76452
+ waitForHeadAdvance() {
76453
+ if (this._stopping) return Promise.resolve();
76454
+ return new Promise((resolve) => {
76455
+ this._headWaiters.push(resolve);
76456
+ });
76457
+ }
76458
+ };
76459
+ /** Connection kinds supported by this provider. */
76460
+ __publicField$25(SimpleFinalizedBlockStream$1, "connectionTypes", ["none"]);
76461
+ /** Primary moniker used to resolve this provider. */
76462
+ __publicField$25(SimpleFinalizedBlockStream$1, "defaultMoniker", FinalizedBlockStreamMoniker$1);
76463
+ /** Provider monikers that must resolve before this provider can be created. */
76464
+ __publicField$25(SimpleFinalizedBlockStream$1, "dependencies", [BlockViewerMoniker$1, FinalizationViewerMoniker$1]);
76465
+ /** Provider monikers implemented by this provider class. */
76466
+ __publicField$25(SimpleFinalizedBlockStream$1, "monikers", [FinalizedBlockStreamMoniker$1]);
76467
+ /** Read, write, or mixed capability surface exposed by the provider. */
76468
+ __publicField$25(SimpleFinalizedBlockStream$1, "surface", "node");
76469
+ SimpleFinalizedBlockStream$1 = __decorateClass$26([creatableProvider$1()], SimpleFinalizedBlockStream$1);
76105
76470
  var SimpleXyoGatewayRunner = class _SimpleXyoGatewayRunner extends AbstractCreatableProvider$1 {
76106
76471
  /** Connection kinds supported by this provider. */
76107
76472
  static connectionTypes = ["none"];
@@ -76345,6 +76710,83 @@ var nextPruneCursor$1 = (batch, pruneHashes, cursor) => {
76345
76710
  const pruneSet = new Set(pruneHashes);
76346
76711
  return batch.findLast((bundle3) => !pruneSet.has(bundle3._hash))?._sequence ?? cursor;
76347
76712
  };
76713
+ async function simpleBlockValidationCheck$1(payloads, context) {
76714
+ return (await Promise.all(payloads.map(async (payload) => {
76715
+ return [isPayloadBundle$1(payload) ? await bundledPayloadToHydratedBlock$1(payload) : void 0, payload];
76716
+ }))).map(([block, bundle3]) => evaluateBlockCandidate$1(block, bundle3, context));
76717
+ }
76718
+ async function simpleTransactionValidationCheck$1(payloads, context) {
76719
+ const transactionBundles = await Promise.all(payloads.map(async (payload) => {
76720
+ return [isPayloadBundle$1(payload) ? await bundledPayloadToHydratedTransaction$1(payload) : void 0, payload];
76721
+ }));
76722
+ return Promise.all(transactionBundles.map(async ([transaction, bundle3]) => {
76723
+ return evaluateTransactionCandidate$1(transaction, bundle3, context);
76724
+ }));
76725
+ }
76726
+ function evaluateBlockCandidate$1(block, bundle3, { chainId, headNumber, logger }) {
76727
+ const typeCheckPassed = isSignedHydratedBlockWithHashMeta$1(block);
76728
+ const chainIdPassed = typeCheckPassed && block[0].chain === chainId;
76729
+ const blockNumberPassed = typeCheckPassed && block[0].block > headNumber;
76730
+ const validationPassed = typeCheckPassed && chainIdPassed && blockNumberPassed;
76731
+ if (!validationPassed) logFailedBlockCheck$1({
76732
+ block,
76733
+ blockNumberPassed,
76734
+ bundle: bundle3,
76735
+ chainIdPassed,
76736
+ headNumber,
76737
+ logger,
76738
+ typeCheckPassed
76739
+ });
76740
+ return [validationPassed ? block : void 0, bundle3];
76741
+ }
76742
+ async function evaluateTransactionCandidate$1(transaction, bundle3, { chainId, headNumber, logger, maxExpAhead }) {
76743
+ const typeCheckPassed = isSignedHydratedTransactionWithHashMeta$1(transaction);
76744
+ const chainIdPassed = typeCheckPassed && transaction[0].chain === chainId;
76745
+ const expPassed = typeCheckPassed && transaction[0].exp > headNumber && transaction[0].exp <= headNumber + maxExpAhead;
76746
+ const opcodeCheckPassed = await checkTransactionOpcodes$1(transaction, bundle3, logger);
76747
+ const validationPassed = typeCheckPassed && chainIdPassed && expPassed && opcodeCheckPassed;
76748
+ if (!validationPassed) logFailedTransactionCheck$1({
76749
+ bundle: bundle3,
76750
+ chainIdPassed,
76751
+ expPassed,
76752
+ headNumber,
76753
+ logger,
76754
+ opcodeCheckPassed,
76755
+ transaction,
76756
+ typeCheckPassed
76757
+ });
76758
+ return [validationPassed ? transaction : void 0, bundle3];
76759
+ }
76760
+ async function checkTransactionOpcodes$1(transaction, bundle3, logger) {
76761
+ try {
76762
+ await validateTransactionsOpcodes$1(transaction === void 0 ? [] : [transaction]);
76763
+ return true;
76764
+ } catch (error) {
76765
+ const message = error instanceof Error ? error.message : String(error);
76766
+ logger?.debug(`Opcode validation failed for transaction ${bundle3._hash} during simpleValidationCheck`);
76767
+ logger?.debug(` - error: ${message}`);
76768
+ return false;
76769
+ }
76770
+ }
76771
+ function logFailedBlockCheck$1({ block, blockNumberPassed, bundle: bundle3, chainIdPassed, headNumber, logger, typeCheckPassed }) {
76772
+ if (chainIdPassed && typeCheckPassed && !blockNumberPassed) {
76773
+ logger?.debug(`Pruning stale block candidate bundle ${bundle3._hash} during simpleValidationCheck (candidate height ${block?.[0].block} <= finalized head ${headNumber} \u2014 routine GC of a finalized or superseded candidate)`);
76774
+ return;
76775
+ }
76776
+ logger?.debug(`Pruning block bundle ${bundle3._hash} during simpleValidationCheck`);
76777
+ logger?.debug(` - chainId match: ${chainIdPassed}`);
76778
+ logger?.debug(` - blockNumber check: ${blockNumberPassed} [head=${headNumber} candidate=${block?.[0].block}]`);
76779
+ logger?.debug(` - typeCheck: ${typeCheckPassed}`);
76780
+ logger?.debug(` - bundle hash: ${bundle3._hash}`);
76781
+ }
76782
+ function logFailedTransactionCheck$1({ bundle: bundle3, chainIdPassed, expPassed, headNumber, logger, opcodeCheckPassed, transaction, typeCheckPassed }) {
76783
+ logger?.debug(`Pruning transaction bundle ${bundle3._hash} during simpleValidationCheck`);
76784
+ logger?.debug(` - chainId match: ${chainIdPassed}`);
76785
+ logger?.debug(` - exp check: ${expPassed} [head=${headNumber} exp=${transaction?.[0].exp}]`);
76786
+ logger?.debug(` - opcode check: ${opcodeCheckPassed}`);
76787
+ logger?.debug(` - typeCheck: ${typeCheckPassed}`);
76788
+ logger?.debug(` - bundle hash: ${bundle3._hash}`);
76789
+ }
76348
76790
  var DEFAULT_SYNC_INTERVAL$1 = 3e4;
76349
76791
  var DEFAULT_SYNC_LIMIT$1 = 100;
76350
76792
  var ENFORCE_CAP_BATCH_SIZE$1 = 1e3;
@@ -76477,7 +76919,11 @@ var SimpleMempoolRunner$1 = class extends AbstractCreatableProvider$1 {
76477
76919
  }
76478
76920
  while (batch.length > 0 && pruned < maxPrune && total < maxCheck) {
76479
76921
  batches += 1;
76480
- const blocksAndBundles = await this.simpleBlockValidationCheck(batch);
76922
+ const blocksAndBundles = await simpleBlockValidationCheck$1(batch, {
76923
+ chainId: await this.chainContractViewer.chainId(),
76924
+ headNumber: await this.finalizationViewer.headNumber(),
76925
+ logger: this.logger
76926
+ });
76481
76927
  const blocks = blocksAndBundles.map(([b]) => b);
76482
76928
  const bundles = blocksAndBundles.map(([_, p]) => p);
76483
76929
  const valid = blocks.map((b) => !!b);
@@ -76491,9 +76937,10 @@ var SimpleMempoolRunner$1 = class extends AbstractCreatableProvider$1 {
76491
76937
  state: true
76492
76938
  }))),
76493
76939
  isValidated: isSignedHydratedBlockWithHashMeta$1,
76494
- onInvalid: ({ bundle: bundle3, result }) => {
76495
- const errors = result;
76940
+ onInvalid: async ({ bundle: bundle3, item, result }) => {
76941
+ const errors = isSignedHydratedBlockWithHashMeta$1(result) ? [] : result;
76496
76942
  this.logger?.info(`[SimpleMempoolRunner] prunePendingBlocks deleting block ${bundle3._hash} (validation: ${errors.at(0)?.message ?? "failed simple/full check"})`);
76943
+ await this.routeRejectedBlock(item, errors);
76497
76944
  }
76498
76945
  });
76499
76946
  const pruneHashes = invalidBundleHashes$1(bundles, valid);
@@ -76529,7 +76976,12 @@ var SimpleMempoolRunner$1 = class extends AbstractCreatableProvider$1 {
76529
76976
  }
76530
76977
  while (batch.length > 0 && pruned < maxPrune && total < maxCheck) {
76531
76978
  batches += 1;
76532
- const transactionsAndBundles = await this.simpleTransactionValidationCheck(batch);
76979
+ const transactionsAndBundles = await simpleTransactionValidationCheck$1(batch, {
76980
+ chainId: await this.chainContractViewer.chainId(),
76981
+ headNumber: await this.finalizationViewer.headNumber(),
76982
+ logger: this.logger,
76983
+ maxExpAhead: this.maxExpAhead
76984
+ });
76533
76985
  const transactions = transactionsAndBundles.map(([t]) => t);
76534
76986
  const bundles = transactionsAndBundles.map(([_, p]) => p);
76535
76987
  const valid = transactions.map((t) => !!t);
@@ -76689,6 +77141,20 @@ var SimpleMempoolRunner$1 = class extends AbstractCreatableProvider$1 {
76689
77141
  if (isDemotionAware$1(this._mempoolViewer)) return this._mempoolViewer.getEvictionPriorityOrder(bundleHashesOldestFirst);
76690
77142
  return bundleHashesOldestFirst;
76691
77143
  }
77144
+ async routeRejectedBlock(block, errors) {
77145
+ if (!this._deadLetterQueueRunner) return;
77146
+ const rejectionErrors = errors.map((e) => ({
77147
+ hash: e.hash ?? block[0]._hash,
77148
+ name: e.name ?? "BlockValidationError",
77149
+ message: String(e.message ?? e)
77150
+ }));
77151
+ await this._deadLetterQueueRunner.rejectBlock({
77152
+ schema: BlockRejectionSchema$1,
77153
+ block,
77154
+ errors: rejectionErrors,
77155
+ rejector: "mempool"
77156
+ });
77157
+ }
76692
77158
  async routeRejectedTransaction(transaction, errors) {
76693
77159
  if (!this._deadLetterQueueRunner) return;
76694
77160
  const rejectionErrors = errors.map((e) => ({
@@ -76703,60 +77169,6 @@ var SimpleMempoolRunner$1 = class extends AbstractCreatableProvider$1 {
76703
77169
  rejector: "mempool"
76704
77170
  });
76705
77171
  }
76706
- async simpleBlockValidationCheck(payloads) {
76707
- const headNumber = await this.finalizationViewer.headNumber();
76708
- const chainId = await this.chainContractViewer.chainId();
76709
- return (await Promise.all(payloads.map(async (p) => {
76710
- return [isPayloadBundle$1(p) ? await bundledPayloadToHydratedBlock$1(p) : void 0, p];
76711
- }))).map(([block, bundle3]) => {
76712
- const blockCheckPassed = !!block;
76713
- const chainIdPassed = blockCheckPassed ? block[0].chain === chainId : false;
76714
- const blockNumberPassed = blockCheckPassed ? block[0].block > headNumber : false;
76715
- const typeCheckPassed = blockCheckPassed ? isSignedHydratedBlockWithHashMeta$1(block) : false;
76716
- const validationPassed = blockCheckPassed && chainIdPassed && blockNumberPassed && typeCheckPassed;
76717
- const validatedBlock = validationPassed ? block : void 0;
76718
- if (!validationPassed) {
76719
- this.logger?.debug(`Pruning block bundle ${bundle3._hash} during simpleValidationCheck`);
76720
- this.logger?.debug(` - chainId match: ${chainIdPassed}`);
76721
- this.logger?.debug(` - blockNumber check: ${blockNumberPassed} [${headNumber}|${block?.[0].block}]`);
76722
- this.logger?.debug(` - typeCheck: ${typeCheckPassed}`);
76723
- this.logger?.debug(` - bundle hash: ${bundle3._hash}`);
76724
- }
76725
- return [validatedBlock, bundle3];
76726
- });
76727
- }
76728
- async simpleTransactionValidationCheck(payloads) {
76729
- const headNumber = await this.finalizationViewer.headNumber();
76730
- const chainId = await this.chainContractViewer.chainId();
76731
- const transactionBundles = await Promise.all(payloads.map(async (p) => {
76732
- return [isPayloadBundle$1(p) ? await bundledPayloadToHydratedTransaction$1(p) : void 0, p];
76733
- }));
76734
- return await Promise.all(transactionBundles.map(async ([transaction, bundle3]) => {
76735
- const transactionCheckPassed = !!transaction;
76736
- const chainIdPassed = transactionCheckPassed ? transaction[0].chain === chainId : false;
76737
- const expPassed = transactionCheckPassed ? transaction[0].exp > headNumber && transaction[0].exp <= headNumber + this.maxExpAhead : false;
76738
- const typeCheckPassed = transactionCheckPassed ? isSignedHydratedTransactionWithHashMeta$1(transaction) : false;
76739
- let opcodeCheckPassed = false;
76740
- try {
76741
- await validateTransactionsOpcodes$1(transaction ? [transaction] : []);
76742
- opcodeCheckPassed = true;
76743
- } catch (e) {
76744
- this.logger?.debug(`Opcode validation failed for transaction ${bundle3._hash} during simpleValidationCheck`);
76745
- this.logger?.debug(` - error: ${e.message}`);
76746
- }
76747
- const validationPassed = transactionCheckPassed && chainIdPassed && expPassed && typeCheckPassed && opcodeCheckPassed;
76748
- const validatedTransaction = validationPassed ? transaction : void 0;
76749
- if (!validationPassed) {
76750
- this.logger?.debug(`Pruning block bundle ${bundle3._hash} during simpleValidationCheck`);
76751
- this.logger?.debug(` - chainId match: ${chainIdPassed}`);
76752
- this.logger?.debug(` - exp check: ${expPassed}`);
76753
- this.logger?.debug(` - opcode check: ${opcodeCheckPassed}`);
76754
- this.logger?.debug(` - typeCheck: ${typeCheckPassed}`);
76755
- this.logger?.debug(` - bundle hash: ${bundle3._hash}`);
76756
- }
76757
- return [validatedTransaction, bundle3];
76758
- }));
76759
- }
76760
77172
  async syncBlocksFrom(external) {
76761
77173
  const externalBlocks = await external.pendingBlocks({ limit: this.syncLimit });
76762
77174
  if (externalBlocks.length === 0) return;
@@ -76803,6 +77215,11 @@ __publicField$25(SimpleMempoolRunner$1, "monikers", [MempoolRunnerMoniker$1]);
76803
77215
  /** Read, write, or mixed capability surface exposed by the provider. */
76804
77216
  __publicField$25(SimpleMempoolRunner$1, "surface", "node");
76805
77217
  SimpleMempoolRunner$1 = __decorateClass$26([creatableProvider$1()], SimpleMempoolRunner$1);
77218
+ async function resolveHashCursor$1(archivist, providedCursor) {
77219
+ if (!isHash(providedCursor)) return void 0;
77220
+ const [payload] = await archivist.get([providedCursor]);
77221
+ return isDefined$1(payload) ? payload._sequence : void 0;
77222
+ }
76806
77223
  var SimpleMempoolViewerOptionsZod$1 = object$3({
76807
77224
  demotionThreshold: number$1().default(3),
76808
77225
  handoutStatsTtlBlocks: number$1().default(1e3),
@@ -76870,11 +77287,7 @@ var SimpleMempoolViewer$1 = class extends AbstractCreatableProvider$1 {
76870
77287
  }
76871
77288
  /** Returns the pending blocks result exposed by this provider. */
76872
77289
  async pendingBlocks({ cursor: providedCursor } = {}) {
76873
- let cursor;
76874
- if (isHash(providedCursor)) {
76875
- const [p] = await this.pendingBlocksArchivist.get([providedCursor]);
76876
- if (isDefined$1(p)) cursor = p._sequence;
76877
- }
77290
+ const cursor = await resolveHashCursor$1(this.pendingBlocksArchivist, providedCursor);
76878
77291
  const filteredBundles = (await this.pendingBlocksArchivist.next({
76879
77292
  order: "desc",
76880
77293
  limit: 100,
@@ -76884,11 +77297,8 @@ var SimpleMempoolViewer$1 = class extends AbstractCreatableProvider$1 {
76884
77297
  }
76885
77298
  /** Returns the pending transactions result exposed by this provider. */
76886
77299
  async pendingTransactions({ cursor: providedCursor, limit = 100 } = {}) {
76887
- let cursor;
76888
- if (isHash(providedCursor)) {
76889
- const [p] = await this.pendingTransactionsArchivist.get([providedCursor]);
76890
- if (isDefined$1(p)) cursor = p._sequence;
76891
- }
77300
+ await this.windowedBlockViewer.sync?.();
77301
+ const cursor = await resolveHashCursor$1(this.pendingTransactionsArchivist, providedCursor);
76892
77302
  this.logger?.debug(`Fetching pending transactions from cursor: ${cursor}`);
76893
77303
  const bundles = await this.pendingTransactionsArchivist.next({
76894
77304
  order: "asc",
@@ -78055,7 +78465,9 @@ var SimpleWindowedBlockViewer$1 = class extends AbstractCreatableProvider$1 {
78055
78465
  _blockNumberMap;
78056
78466
  _blockViewer;
78057
78467
  _chain = [];
78468
+ _inFlightSync = null;
78058
78469
  _options;
78470
+ _queuedSync = null;
78059
78471
  _syncMutex = new Mutex();
78060
78472
  _timerId = null;
78061
78473
  _transactionHashMap;
@@ -78163,6 +78575,32 @@ var SimpleWindowedBlockViewer$1 = class extends AbstractCreatableProvider$1 {
78163
78575
  await super.stopHandler();
78164
78576
  this.stopPoll();
78165
78577
  }
78578
+ /**
78579
+ * Synchronizes the in-memory window with the backing block viewer immediately, waiting for any
78580
+ * in-flight sync to complete first. Callers whose correctness depends on seeing the latest
78581
+ * finalized blocks (e.g. mempool inclusion checks) must call this rather than rely on the
78582
+ * background poll, whose interval is far coarser than block finalization.
78583
+ *
78584
+ * Concurrent callers are coalesced: a caller arriving while a sync runs joins one shared
78585
+ * follow-up pass (which starts after the running pass and therefore observes every block
78586
+ * finalized before the caller arrived) instead of enqueuing its own. Without this, N
78587
+ * concurrent callers — the handout path is reachable per producer tick and over RPC — would
78588
+ * execute N sequential backing reads behind the sync mutex.
78589
+ */
78590
+ async sync() {
78591
+ if (this._inFlightSync === null) {
78592
+ const run = this.runSync().finally(() => {
78593
+ if (this._inFlightSync === run) this._inFlightSync = null;
78594
+ });
78595
+ this._inFlightSync = run;
78596
+ return await run;
78597
+ }
78598
+ this._queuedSync ??= this._inFlightSync.then(() => {
78599
+ this._queuedSync = null;
78600
+ return this.sync();
78601
+ });
78602
+ return await this._queuedSync;
78603
+ }
78166
78604
  addBlock(block) {
78167
78605
  this._chain.push(block);
78168
78606
  this._blockHashMap.set(block[0]._hash, block);
@@ -78176,18 +78614,8 @@ var SimpleWindowedBlockViewer$1 = class extends AbstractCreatableProvider$1 {
78176
78614
  for (const tx of transactionsFromHydratedBlock$1(removedBlock)) this._transactionHashMap.delete(tx._hash);
78177
78615
  }
78178
78616
  }
78179
- startPoll() {
78180
- this._timerId = setInterval(() => {
78181
- this.sync();
78182
- }, this.syncInterval);
78183
- }
78184
- stopPoll() {
78185
- if (this._timerId) clearInterval(this._timerId);
78186
- this._timerId = null;
78187
- }
78188
- async sync() {
78189
- if (this._syncMutex.isLocked()) return;
78190
- return await this._syncMutex.runExclusive(async () => {
78617
+ async runSync() {
78618
+ await this._syncMutex.runExclusive(async () => {
78191
78619
  try {
78192
78620
  let cursor = await this._blockViewer.currentBlock();
78193
78621
  const previousHead = this._chain.length > 0 ? await this.currentBlockHash() : null;
@@ -78203,6 +78631,19 @@ var SimpleWindowedBlockViewer$1 = class extends AbstractCreatableProvider$1 {
78203
78631
  }
78204
78632
  });
78205
78633
  }
78634
+ startPoll() {
78635
+ this._timerId = setInterval(() => {
78636
+ this.syncIfIdle();
78637
+ }, this.syncInterval);
78638
+ }
78639
+ stopPoll() {
78640
+ if (this._timerId) clearInterval(this._timerId);
78641
+ this._timerId = null;
78642
+ }
78643
+ async syncIfIdle() {
78644
+ if (this._syncMutex.isLocked()) return;
78645
+ await this.sync();
78646
+ }
78206
78647
  };
78207
78648
  /** Connection kinds supported by this provider. */
78208
78649
  __publicField$25(SimpleWindowedBlockViewer$1, "connectionTypes", [
@@ -81798,7 +82239,7 @@ function getOriginalId$1(rawRequest) {
81798
82239
  return [void 0, false];
81799
82240
  }
81800
82241
  //#endregion
81801
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_f803ff54f950c092c4a357d77886b418/node_modules/@xyo-network/xl1-sdk/dist/neutral/rpc.mjs
82242
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_3a01f3229f2daa942444e08696345b23/node_modules/@xyo-network/xl1-sdk/dist/neutral/rpc.mjs
81802
82243
  var __defProp$26 = Object.defineProperty;
81803
82244
  var __getOwnPropDesc$25 = Object.getOwnPropertyDescriptor;
81804
82245
  var __defNormalProp$24 = (obj, key, value) => key in obj ? __defProp$26(obj, key, {
@@ -84340,7 +84781,7 @@ var createRpcDispatchMiddleware = (schemas, handlers, options) => async ({ reque
84340
84781
  }
84341
84782
  };
84342
84783
  //#endregion
84343
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_f803ff54f950c092c4a357d77886b418/node_modules/@xyo-network/xl1-sdk/dist/neutral/rest-block-viewer.mjs
84784
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_3a01f3229f2daa942444e08696345b23/node_modules/@xyo-network/xl1-sdk/dist/neutral/rest-block-viewer.mjs
84344
84785
  var __defProp$25 = Object.defineProperty;
84345
84786
  var __getOwnPropDesc$24 = Object.getOwnPropertyDescriptor;
84346
84787
  var __defNormalProp$23 = (obj, key, value) => key in obj ? __defProp$25(obj, key, {
@@ -105003,7 +105444,7 @@ var StakedXyoChainV2__factory = class extends ContractFactory {
105003
105444
  }
105004
105445
  };
105005
105446
  //#endregion
105006
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_f803ff54f950c092c4a357d77886b418/node_modules/@xyo-network/xl1-sdk/dist/neutral/providers.mjs
105447
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_3a01f3229f2daa942444e08696345b23/node_modules/@xyo-network/xl1-sdk/dist/neutral/providers.mjs
105007
105448
  var __defProp$23 = Object.defineProperty;
105008
105449
  var __getOwnPropDesc$23 = Object.getOwnPropertyDescriptor;
105009
105450
  var __defNormalProp$22 = (obj, key, value) => key in obj ? __defProp$23(obj, key, {
@@ -105957,6 +106398,179 @@ __publicField$22(EvmStakeViewer$1, "monikers", [StakeViewerMoniker$1]);
105957
106398
  /** Read, write, or mixed capability surface exposed by the provider. */
105958
106399
  __publicField$22(EvmStakeViewer$1, "surface", "node");
105959
106400
  EvmStakeViewer$1 = __decorateClass$23([creatableProvider$1()], EvmStakeViewer$1);
106401
+ var DEFAULT_HEAD_POLL_INTERVAL_MS$2 = 5e3;
106402
+ var RestNetworkStakeStepRewardsByPositionViewerOptionsZod$1 = object$3({
106403
+ headPollIntervalMs: number$1().min(5e3).default(DEFAULT_HEAD_POLL_INTERVAL_MS$2),
106404
+ policyId: NetworkStakeRewardsPolicyIdZod.default(NETWORK_STAKE_REWARDS_UNMULTIPLIED_POLICY)
106405
+ });
106406
+ var RestNetworkStakeStepRewardsByPositionViewer$1 = class extends AbstractCreatableProvider$1 {
106407
+ moniker = RestNetworkStakeStepRewardsByPositionViewer$1.defaultMoniker;
106408
+ currentHead;
106409
+ headPollIntervalMs = DEFAULT_HEAD_POLL_INTERVAL_MS$2;
106410
+ headPromise;
106411
+ lastSuccessfulHeadAt;
106412
+ manifestPromise;
106413
+ policyId = NETWORK_STAKE_REWARDS_UNMULTIPLIED_POLICY;
106414
+ snapshotPromises = /* @__PURE__ */ new Map();
106415
+ stepPromises = /* @__PURE__ */ new Map();
106416
+ get baseUrl() {
106417
+ const connection = RestNetworkStakeStepRewardsByPositionViewer$1.requireBoundConnection(this.config);
106418
+ const config = connection.config;
106419
+ if (config.type !== "rest") throw new Error(`Connection "${connection.name}" must be a rest connection`);
106420
+ return assertEx$1(config.baseUrl, () => `Connection "${connection.name}" requires a rest baseUrl`);
106421
+ }
106422
+ get fetchFn() {
106423
+ return this.context.fetchFn ?? fetch.bind(globalThis);
106424
+ }
106425
+ /** Returns the policy bonus. The unmultiplied-v1 index has no multipliers, so bonus is zero. */
106426
+ async bonus(options = {}) {
106427
+ const total = await this.total(options);
106428
+ return Object.fromEntries(Object.keys(total).map((key) => [Number(key), asAttoXL1$1(0n)]));
106429
+ }
106430
+ /** Claimed rewards are not part of the earned-reward index. */
106431
+ claimed(_options) {
106432
+ throw new Error("Method [claimed] not implemented.");
106433
+ }
106434
+ /** Creates the provider instance after validating its REST binding and options. */
106435
+ async createHandler() {
106436
+ await super.createHandler();
106437
+ RestNetworkStakeStepRewardsByPositionViewer$1.requireBoundConnection(this.config);
106438
+ const options = RestNetworkStakeStepRewardsByPositionViewerOptionsZod$1.parse(this.config.options);
106439
+ this.headPollIntervalMs = options.headPollIntervalMs;
106440
+ this.policyId = options.policyId;
106441
+ }
106442
+ /** Base-v1 total and earned rewards are identical. */
106443
+ async earned(options = {}) {
106444
+ return await this.total(options);
106445
+ }
106446
+ /** Returns rewards by requested position from the durable index. */
106447
+ async total({ range, positions } = {}) {
106448
+ if (!isArray(positions)) return {};
106449
+ const head = await this.getHead();
106450
+ const resolvedRange = asXL1BlockRange$1(range ?? [0, head.processedThroughBlock], { name: "RestNetworkStakeStepRewardsByPositionViewer" });
106451
+ const result = {};
106452
+ for (const position of positions) result[position] = (await this.totalForPosition(position, resolvedRange))[0];
106453
+ return result;
106454
+ }
106455
+ /** Returns one position's cumulative reward and the range's emitted reward pool. */
106456
+ async totalForPosition(position, range) {
106457
+ const head = await this.getHead();
106458
+ this.assertPublishedRange(range, head);
106459
+ if (head.positionCount === 0) return [asAttoXL1$1(0n), asAttoXL1$1(0n)];
106460
+ this.assertPosition(position, head);
106461
+ if (range[0] === 0 && range[1] >= head.processedThroughBlock) {
106462
+ const snapshot = await this.getSnapshot(head);
106463
+ return [asAttoXL1$1(BigInt(snapshot.positionRewards[String(position)] ?? "0")), asAttoXL1$1(BigInt(snapshot.totalReward))];
106464
+ }
106465
+ const steps = await this.stepsForRange(range, head);
106466
+ return [asAttoXL1$1(steps.reduce((sum, step) => sum + BigInt(step.positionRewards[String(position)] ?? "0"), 0n)), asAttoXL1$1(steps.reduce((sum, step) => sum + BigInt(step.totalReward), 0n))];
106467
+ }
106468
+ /** Returns the emitted reward pool for one indexed step. */
106469
+ async totalForStep(step) {
106470
+ const head = await this.getHead();
106471
+ this.assertPublishedStep(step, head);
106472
+ return asAttoXL1$1(BigInt((await this.getStep(step)).totalReward));
106473
+ }
106474
+ /** Returns one position's allocation and emitted pool for one indexed step. */
106475
+ async totalForStepForPosition(step, position) {
106476
+ const head = await this.getHead();
106477
+ this.assertPosition(position, head);
106478
+ this.assertPublishedStep(step, head);
106479
+ const record = await this.getStep(step);
106480
+ return [asAttoXL1$1(BigInt(record.positionRewards[String(position)] ?? "0")), asAttoXL1$1(BigInt(record.totalReward))];
106481
+ }
106482
+ /** Unclaimed rewards require redemption state and are not part of this index. */
106483
+ unclaimed(_options) {
106484
+ throw new Error("Method [unclaimed] not implemented.");
106485
+ }
106486
+ assertPosition(position, head) {
106487
+ assertEx$1(Number.isSafeInteger(position) && position >= 0 && position < head.positionCount, () => `Position ${position} is outside rewards index positionCount ${head.positionCount}`);
106488
+ }
106489
+ assertPublishedRange(range, head) {
106490
+ assertEx$1(range[1] <= head.processedThroughBlock, () => `Reward range ends at ${range[1]}, beyond index watermark ${head.processedThroughBlock}`);
106491
+ }
106492
+ assertPublishedStep(step, head) {
106493
+ assertEx$1(step.block <= head.processedThroughBlock, () => `Reward step ${step.block}|${step.step} is beyond index watermark ${head.processedThroughBlock}`);
106494
+ }
106495
+ async fetchJson(path) {
106496
+ const response = await this.fetchFn(`${this.baseUrl.replace(/\/$/, "")}/${path}`);
106497
+ if (!response.ok) throw new Error(`Network stake rewards index request failed [${response.status}] for ${path}`);
106498
+ return await response.json();
106499
+ }
106500
+ async getHead() {
106501
+ const now = Date.now();
106502
+ const elapsed = this.lastSuccessfulHeadAt === void 0 ? void 0 : now - this.lastSuccessfulHeadAt;
106503
+ if (this.currentHead !== void 0 && elapsed !== void 0 && elapsed >= 0 && elapsed < this.headPollIntervalMs) return this.currentHead;
106504
+ this.headPromise ??= this.syncHead().finally(() => {
106505
+ this.headPromise = void 0;
106506
+ });
106507
+ return await this.headPromise;
106508
+ }
106509
+ async getManifest() {
106510
+ this.manifestPromise ??= this.fetchJson(networkStakeRewardsIndexManifestPath(this.policyId)).then((value) => asNetworkStakeRewardsIndexManifest(value, true)).catch((error) => {
106511
+ this.manifestPromise = void 0;
106512
+ throw error;
106513
+ });
106514
+ return await this.manifestPromise;
106515
+ }
106516
+ async getSnapshot(head) {
106517
+ const { snapshotHash } = head;
106518
+ let promise = this.snapshotPromises.get(snapshotHash);
106519
+ if (promise === void 0) {
106520
+ const path = networkStakeRewardsIndexSnapshotPath(this.policyId, snapshotHash);
106521
+ promise = this.fetchJson(path).then(async (value) => {
106522
+ const snapshot = asNetworkStakeRewardsIndexSnapshot(value, true);
106523
+ assertEx$1(await PayloadBuilder$1.hash(snapshot) === snapshotHash, () => `Rewards snapshot hash mismatch: ${path}`);
106524
+ return snapshot;
106525
+ });
106526
+ this.snapshotPromises.set(snapshotHash, promise);
106527
+ }
106528
+ try {
106529
+ const snapshot = await promise;
106530
+ assertEx$1(snapshot.policyId === this.policyId, () => "Rewards snapshot policy mismatch");
106531
+ assertEx$1(snapshot.stepCount === head.stepCount, () => "Rewards snapshot step count mismatch");
106532
+ return snapshot;
106533
+ } catch (error) {
106534
+ this.snapshotPromises.delete(snapshotHash);
106535
+ throw error;
106536
+ }
106537
+ }
106538
+ async getStep(step) {
106539
+ const path = networkStakeRewardsIndexStepPath(this.policyId, step);
106540
+ let promise = this.stepPromises.get(path);
106541
+ if (promise === void 0) {
106542
+ promise = this.fetchJson(path).then((value) => asNetworkStakeRewardsIndexStep(value, true));
106543
+ this.stepPromises.set(path, promise);
106544
+ }
106545
+ try {
106546
+ const record = await promise;
106547
+ assertEx$1(record.policyId === this.policyId, () => "Rewards step policy mismatch");
106548
+ assertEx$1(record.step.block === step.block && record.step.step === step.step, () => "Rewards step identity mismatch");
106549
+ return record;
106550
+ } catch (error) {
106551
+ this.stepPromises.delete(path);
106552
+ throw error;
106553
+ }
106554
+ }
106555
+ async stepsForRange(range, head) {
106556
+ const steps = blockRangeSteps(range, (await this.getManifest()).stepLevels).filter((step) => step.block <= head.processedThroughBlock);
106557
+ return await Promise.all(steps.map(async (step) => await this.getStep(step)));
106558
+ }
106559
+ async syncHead() {
106560
+ assertEx$1((await this.getManifest()).policyId === this.policyId, () => "Rewards manifest policy mismatch");
106561
+ const head = asNetworkStakeRewardsIndexHead(await this.fetchJson(networkStakeRewardsIndexHeadPath(this.policyId)), true);
106562
+ assertEx$1(head.policyId === this.policyId, () => "Rewards head policy mismatch");
106563
+ this.currentHead = head;
106564
+ this.lastSuccessfulHeadAt = Date.now();
106565
+ return head;
106566
+ }
106567
+ };
106568
+ __publicField$22(RestNetworkStakeStepRewardsByPositionViewer$1, "connectionTypes", ["rest"]);
106569
+ __publicField$22(RestNetworkStakeStepRewardsByPositionViewer$1, "defaultMoniker", NetworkStakeStepRewardsByPositionViewerMoniker$1);
106570
+ __publicField$22(RestNetworkStakeStepRewardsByPositionViewer$1, "dependencies", []);
106571
+ __publicField$22(RestNetworkStakeStepRewardsByPositionViewer$1, "monikers", [NetworkStakeStepRewardsByPositionViewerMoniker$1]);
106572
+ __publicField$22(RestNetworkStakeStepRewardsByPositionViewer$1, "surface", "node");
106573
+ RestNetworkStakeStepRewardsByPositionViewer$1 = __decorateClass$23([creatableProvider$1()], RestNetworkStakeStepRewardsByPositionViewer$1);
105960
106574
  var SimpleDeadLetterQueueRunner$1 = class extends AbstractCreatableProvider$1 {
105961
106575
  /** Moniker implemented by this provider instance. */
105962
106576
  moniker = SimpleDeadLetterQueueRunner$1.defaultMoniker;
@@ -107353,181 +107967,8 @@ __publicField$22(RestChainParamsViewer$1, "monikers", [ChainParamsViewerMoniker]
107353
107967
  /** Read, write, or mixed capability surface exposed by the provider. */
107354
107968
  __publicField$22(RestChainParamsViewer$1, "surface", "node");
107355
107969
  RestChainParamsViewer$1 = __decorateClass$23([creatableProvider$1()], RestChainParamsViewer$1);
107356
- var DEFAULT_HEAD_POLL_INTERVAL_MS2$1 = 5e3;
107357
- var RestNetworkStakeStepRewardsByPositionViewerOptionsZod$1 = object$3({
107358
- headPollIntervalMs: number$1().min(5e3).default(DEFAULT_HEAD_POLL_INTERVAL_MS2$1),
107359
- policyId: NetworkStakeRewardsPolicyIdZod.default(NETWORK_STAKE_REWARDS_UNMULTIPLIED_POLICY)
107360
- });
107361
- var RestNetworkStakeStepRewardsByPositionViewer$1 = class extends AbstractCreatableProvider$1 {
107362
- moniker = RestNetworkStakeStepRewardsByPositionViewer$1.defaultMoniker;
107363
- currentHead;
107364
- headPollIntervalMs = DEFAULT_HEAD_POLL_INTERVAL_MS2$1;
107365
- headPromise;
107366
- lastSuccessfulHeadAt;
107367
- manifestPromise;
107368
- policyId = NETWORK_STAKE_REWARDS_UNMULTIPLIED_POLICY;
107369
- snapshotPromises = /* @__PURE__ */ new Map();
107370
- stepPromises = /* @__PURE__ */ new Map();
107371
- get baseUrl() {
107372
- const connection = RestNetworkStakeStepRewardsByPositionViewer$1.requireBoundConnection(this.config);
107373
- const config = connection.config;
107374
- if (config.type !== "rest") throw new Error(`Connection "${connection.name}" must be a rest connection`);
107375
- return assertEx$1(config.baseUrl, () => `Connection "${connection.name}" requires a rest baseUrl`);
107376
- }
107377
- get fetchFn() {
107378
- return this.context.fetchFn ?? fetch.bind(globalThis);
107379
- }
107380
- /** Returns the policy bonus. The unmultiplied-v1 index has no multipliers, so bonus is zero. */
107381
- async bonus(options = {}) {
107382
- const total = await this.total(options);
107383
- return Object.fromEntries(Object.keys(total).map((key) => [Number(key), asAttoXL1$1(0n)]));
107384
- }
107385
- /** Claimed rewards are not part of the earned-reward index. */
107386
- claimed(_options) {
107387
- throw new Error("Method [claimed] not implemented.");
107388
- }
107389
- /** Creates the provider instance after validating its REST binding and options. */
107390
- async createHandler() {
107391
- await super.createHandler();
107392
- RestNetworkStakeStepRewardsByPositionViewer$1.requireBoundConnection(this.config);
107393
- const options = RestNetworkStakeStepRewardsByPositionViewerOptionsZod$1.parse(this.config.options);
107394
- this.headPollIntervalMs = options.headPollIntervalMs;
107395
- this.policyId = options.policyId;
107396
- }
107397
- /** Base-v1 total and earned rewards are identical. */
107398
- async earned(options = {}) {
107399
- return await this.total(options);
107400
- }
107401
- /** Returns rewards by requested position from the durable index. */
107402
- async total({ range, positions } = {}) {
107403
- if (!isArray(positions)) return {};
107404
- const head = await this.getHead();
107405
- const resolvedRange = asXL1BlockRange$1(range ?? [0, head.processedThroughBlock], { name: "RestNetworkStakeStepRewardsByPositionViewer" });
107406
- const result = {};
107407
- for (const position of positions) result[position] = (await this.totalForPosition(position, resolvedRange))[0];
107408
- return result;
107409
- }
107410
- /** Returns one position's cumulative reward and the range's emitted reward pool. */
107411
- async totalForPosition(position, range) {
107412
- const head = await this.getHead();
107413
- this.assertPublishedRange(range, head);
107414
- if (head.positionCount === 0) return [asAttoXL1$1(0n), asAttoXL1$1(0n)];
107415
- this.assertPosition(position, head);
107416
- if (range[0] === 0 && range[1] >= head.processedThroughBlock) {
107417
- const snapshot = await this.getSnapshot(head);
107418
- return [asAttoXL1$1(BigInt(snapshot.positionRewards[String(position)] ?? "0")), asAttoXL1$1(BigInt(snapshot.totalReward))];
107419
- }
107420
- const steps = await this.stepsForRange(range, head);
107421
- return [asAttoXL1$1(steps.reduce((sum, step) => sum + BigInt(step.positionRewards[String(position)] ?? "0"), 0n)), asAttoXL1$1(steps.reduce((sum, step) => sum + BigInt(step.totalReward), 0n))];
107422
- }
107423
- /** Returns the emitted reward pool for one indexed step. */
107424
- async totalForStep(step) {
107425
- const head = await this.getHead();
107426
- this.assertPublishedStep(step, head);
107427
- return asAttoXL1$1(BigInt((await this.getStep(step)).totalReward));
107428
- }
107429
- /** Returns one position's allocation and emitted pool for one indexed step. */
107430
- async totalForStepForPosition(step, position) {
107431
- const head = await this.getHead();
107432
- this.assertPosition(position, head);
107433
- this.assertPublishedStep(step, head);
107434
- const record = await this.getStep(step);
107435
- return [asAttoXL1$1(BigInt(record.positionRewards[String(position)] ?? "0")), asAttoXL1$1(BigInt(record.totalReward))];
107436
- }
107437
- /** Unclaimed rewards require redemption state and are not part of this index. */
107438
- unclaimed(_options) {
107439
- throw new Error("Method [unclaimed] not implemented.");
107440
- }
107441
- assertPosition(position, head) {
107442
- assertEx$1(Number.isSafeInteger(position) && position >= 0 && position < head.positionCount, () => `Position ${position} is outside rewards index positionCount ${head.positionCount}`);
107443
- }
107444
- assertPublishedRange(range, head) {
107445
- assertEx$1(range[1] <= head.processedThroughBlock, () => `Reward range ends at ${range[1]}, beyond index watermark ${head.processedThroughBlock}`);
107446
- }
107447
- assertPublishedStep(step, head) {
107448
- assertEx$1(step.block <= head.processedThroughBlock, () => `Reward step ${step.block}|${step.step} is beyond index watermark ${head.processedThroughBlock}`);
107449
- }
107450
- async fetchJson(path) {
107451
- const response = await this.fetchFn(`${this.baseUrl.replace(/\/$/, "")}/${path}`);
107452
- if (!response.ok) throw new Error(`Network stake rewards index request failed [${response.status}] for ${path}`);
107453
- return await response.json();
107454
- }
107455
- async getHead() {
107456
- const now = Date.now();
107457
- const elapsed = this.lastSuccessfulHeadAt === void 0 ? void 0 : now - this.lastSuccessfulHeadAt;
107458
- if (this.currentHead !== void 0 && elapsed !== void 0 && elapsed >= 0 && elapsed < this.headPollIntervalMs) return this.currentHead;
107459
- this.headPromise ??= this.syncHead().finally(() => {
107460
- this.headPromise = void 0;
107461
- });
107462
- return await this.headPromise;
107463
- }
107464
- async getManifest() {
107465
- this.manifestPromise ??= this.fetchJson(networkStakeRewardsIndexManifestPath(this.policyId)).then((value) => asNetworkStakeRewardsIndexManifest(value, true)).catch((error) => {
107466
- this.manifestPromise = void 0;
107467
- throw error;
107468
- });
107469
- return await this.manifestPromise;
107470
- }
107471
- async getSnapshot(head) {
107472
- const { snapshotHash } = head;
107473
- let promise = this.snapshotPromises.get(snapshotHash);
107474
- if (promise === void 0) {
107475
- const path = networkStakeRewardsIndexSnapshotPath(this.policyId, snapshotHash);
107476
- promise = this.fetchJson(path).then(async (value) => {
107477
- const snapshot = asNetworkStakeRewardsIndexSnapshot(value, true);
107478
- assertEx$1(await PayloadBuilder$1.hash(snapshot) === snapshotHash, () => `Rewards snapshot hash mismatch: ${path}`);
107479
- return snapshot;
107480
- });
107481
- this.snapshotPromises.set(snapshotHash, promise);
107482
- }
107483
- try {
107484
- const snapshot = await promise;
107485
- assertEx$1(snapshot.policyId === this.policyId, () => "Rewards snapshot policy mismatch");
107486
- assertEx$1(snapshot.stepCount === head.stepCount, () => "Rewards snapshot step count mismatch");
107487
- return snapshot;
107488
- } catch (error) {
107489
- this.snapshotPromises.delete(snapshotHash);
107490
- throw error;
107491
- }
107492
- }
107493
- async getStep(step) {
107494
- const path = networkStakeRewardsIndexStepPath(this.policyId, step);
107495
- let promise = this.stepPromises.get(path);
107496
- if (promise === void 0) {
107497
- promise = this.fetchJson(path).then((value) => asNetworkStakeRewardsIndexStep(value, true));
107498
- this.stepPromises.set(path, promise);
107499
- }
107500
- try {
107501
- const record = await promise;
107502
- assertEx$1(record.policyId === this.policyId, () => "Rewards step policy mismatch");
107503
- assertEx$1(record.step.block === step.block && record.step.step === step.step, () => "Rewards step identity mismatch");
107504
- return record;
107505
- } catch (error) {
107506
- this.stepPromises.delete(path);
107507
- throw error;
107508
- }
107509
- }
107510
- async stepsForRange(range, head) {
107511
- const steps = blockRangeSteps(range, (await this.getManifest()).stepLevels).filter((step) => step.block <= head.processedThroughBlock);
107512
- return await Promise.all(steps.map(async (step) => await this.getStep(step)));
107513
- }
107514
- async syncHead() {
107515
- assertEx$1((await this.getManifest()).policyId === this.policyId, () => "Rewards manifest policy mismatch");
107516
- const head = asNetworkStakeRewardsIndexHead(await this.fetchJson(networkStakeRewardsIndexHeadPath(this.policyId)), true);
107517
- assertEx$1(head.policyId === this.policyId, () => "Rewards head policy mismatch");
107518
- this.currentHead = head;
107519
- this.lastSuccessfulHeadAt = Date.now();
107520
- return head;
107521
- }
107522
- };
107523
- __publicField$22(RestNetworkStakeStepRewardsByPositionViewer$1, "connectionTypes", ["rest"]);
107524
- __publicField$22(RestNetworkStakeStepRewardsByPositionViewer$1, "defaultMoniker", NetworkStakeStepRewardsByPositionViewerMoniker$1);
107525
- __publicField$22(RestNetworkStakeStepRewardsByPositionViewer$1, "dependencies", []);
107526
- __publicField$22(RestNetworkStakeStepRewardsByPositionViewer$1, "monikers", [NetworkStakeStepRewardsByPositionViewerMoniker$1]);
107527
- __publicField$22(RestNetworkStakeStepRewardsByPositionViewer$1, "surface", "node");
107528
- RestNetworkStakeStepRewardsByPositionViewer$1 = __decorateClass$23([creatableProvider$1()], RestNetworkStakeStepRewardsByPositionViewer$1);
107529
107970
  //#endregion
107530
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_f803ff54f950c092c4a357d77886b418/node_modules/@xyo-network/xl1-sdk/dist/neutral/gateway.mjs
107971
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_3a01f3229f2daa942444e08696345b23/node_modules/@xyo-network/xl1-sdk/dist/neutral/gateway.mjs
107531
107972
  async function witnessPreviousStep(gateway, options) {
107532
107973
  const { addToChain = false, step = 2, transactionOptions, witness: witnessOption } = options ?? {};
107533
107974
  const size = stepSize$1(step);
@@ -107554,7 +107995,7 @@ async function witnessPreviousStep(gateway, options) {
107554
107995
  return { witness };
107555
107996
  }
107556
107997
  //#endregion
107557
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_f803ff54f950c092c4a357d77886b418/node_modules/@xyo-network/xl1-sdk/dist/neutral/wrappers.mjs
107998
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_3a01f3229f2daa942444e08696345b23/node_modules/@xyo-network/xl1-sdk/dist/neutral/wrappers.mjs
107558
107999
  function parseHexOrBigInt(value) {
107559
108000
  return AttoXL1$1(typeof value === "bigint" ? value : hexToBigInt(value));
107560
108001
  }
@@ -109102,26 +109543,23 @@ function createInstalledActorRegistry() {
109102
109543
  return createInstalledActorRegistry$1();
109103
109544
  }
109104
109545
  var DEFAULT_LMDB_CONNECTION$1 = "local-store";
109105
- var DEFAULT_MONGO_CONNECTION$1 = "chain-mongo";
109106
- var DEFAULT_MEMORY_CONNECTION$1 = "memory";
109107
- function isBindableStoreType$1(type) {
109108
- return type === "lmdb" || type === "memory" || type === "mongo";
109546
+ var DEFAULT_MONGO_CONNECTION = "chain-mongo";
109547
+ function isStoreConnectionType(type) {
109548
+ return type === "lmdb" || type === "mongo";
109109
109549
  }
109110
- function connectionProfiles$1(config) {
109111
- const merged = { ...config.connections };
109112
- if (!Object.hasOwn(merged, DEFAULT_MEMORY_CONNECTION$1)) merged[DEFAULT_MEMORY_CONNECTION$1] = { type: "memory" };
109113
- return merged;
109550
+ function isBindableStoreType(type) {
109551
+ return isStoreConnectionType(type) || type === "memory";
109114
109552
  }
109115
- function storeConnectionName$1(profiles) {
109116
- const localStore = profiles[DEFAULT_LMDB_CONNECTION$1];
109117
- if (localStore !== void 0 && isBindableStoreType$1(localStore.type)) return DEFAULT_LMDB_CONNECTION$1;
109118
- if (profiles[DEFAULT_MONGO_CONNECTION$1]?.type === "mongo") return DEFAULT_MONGO_CONNECTION$1;
109119
- for (const [name, connection] of Object.entries(profiles)) if (isBindableStoreType$1(connection.type)) return name;
109553
+ function localChainStoreConnectionName(connections) {
109554
+ const localStore = connections[DEFAULT_LMDB_CONNECTION$1];
109555
+ if (localStore !== void 0 && isBindableStoreType(localStore.type)) return DEFAULT_LMDB_CONNECTION$1;
109556
+ if (connections["chain-mongo"]?.type === "mongo") return DEFAULT_MONGO_CONNECTION;
109557
+ for (const [name, connection] of Object.entries(connections)) if (connection !== void 0 && isStoreConnectionType(connection.type)) return name;
109120
109558
  }
109121
109559
  function resolveMongoConnection(config) {
109122
- const profiles = connectionProfiles$1(config);
109123
- const name = storeConnectionName$1(profiles);
109124
- const connection = name === void 0 ? void 0 : profiles[name];
109560
+ const connections = config.connections ?? {};
109561
+ const name = localChainStoreConnectionName(connections);
109562
+ const connection = name === void 0 ? void 0 : connections[name];
109125
109563
  if (connection?.type !== "mongo") return void 0;
109126
109564
  return connection;
109127
109565
  }
@@ -115918,7 +116356,7 @@ __publicField$19(MemoryArchivist, "labels", {
115918
116356
  });
115919
116357
  MemoryArchivist = __decorateClass$19([creatableModule()], MemoryArchivist);
115920
116358
  //#endregion
115921
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-protocol@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4._d1eafcd2dfc50c437c3d55abb854ddad/node_modules/@xyo-network/xl1-protocol/dist/neutral/protocol-model.mjs
116359
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-protocol@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4._8a6486617e91c015a37921faa069ed7b/node_modules/@xyo-network/xl1-protocol/dist/neutral/protocol-model.mjs
115922
116360
  var ExchangeOutcomeSchema = asSchema("network.xyo.exchange.outcome", true);
115923
116361
  var isExchangeOutcome = isPayloadOfZodType(/* @__PURE__ */ object$5({
115924
116362
  /** Hash of the ExchangeTerms payload this outcome settles */
@@ -116743,6 +117181,20 @@ var FinalizationRunnerMoniker = "FinalizationRunner";
116743
117181
  var MempoolRunnerMoniker = "MempoolRunner";
116744
117182
  var DEFAULT_MAX_EXP_AHEAD = 1e3;
116745
117183
  var SystemStatusViewerMoniker = "SystemStatusViewer";
117184
+ var FinalizedBlockStreamMoniker = "FinalizedBlockStream";
117185
+ var FinalizedBlockStreamDesyncError = class extends Error {
117186
+ /** The block whose `previous` did not match, when it could be fetched. */
117187
+ block;
117188
+ /** The hash the walk expected the next block's `previous` to be. */
117189
+ expectedPrevious;
117190
+ constructor(expectedPrevious, block) {
117191
+ const found = block ? `found ${block[0].previous} at block ${block[0].block}` : "no block found";
117192
+ super(`FinalizedBlockStream desynced: expected previous ${expectedPrevious}, ${found}`);
117193
+ this.name = "FinalizedBlockStreamDesyncError";
117194
+ this.expectedPrevious = expectedPrevious;
117195
+ this.block = block;
117196
+ }
117197
+ };
116746
117198
  var BlocksStepSummarySchema = asSchema("network.xyo.step.summary.blocks", true);
116747
117199
  var isBlocksStepSummary = isPayloadOfSchemaType(BlocksStepSummarySchema);
116748
117200
  var asBlocksStepSummary = AsObjectFactory.create(isBlocksStepSummary);
@@ -116904,7 +117356,7 @@ new import_ajv.Ajv({
116904
117356
  strict: true
116905
117357
  });
116906
117358
  //#endregion
116907
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_d668443a8314bbcb6b4d304ca8d635e8/node_modules/@xyo-network/xl1-sdk/dist/neutral/driver-memory.mjs
117359
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_a771cefd6e9eb69efc5a95a989caf2a3/node_modules/@xyo-network/xl1-sdk/dist/neutral/driver-memory.mjs
116908
117360
  var LruCacheMap = class {
116909
117361
  lruCache;
116910
117362
  /** Creates an instance with the supplied configuration. */
@@ -116986,7 +117438,7 @@ var MemoryMap = class {
116986
117438
  }
116987
117439
  };
116988
117440
  //#endregion
116989
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_d668443a8314bbcb6b4d304ca8d635e8/node_modules/@xyo-network/xl1-sdk/dist/node/protocol-sdk.mjs
117441
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_a771cefd6e9eb69efc5a95a989caf2a3/node_modules/@xyo-network/xl1-sdk/dist/node/protocol-sdk.mjs
116990
117442
  var __defProp$18 = Object.defineProperty;
116991
117443
  var __getOwnPropDesc$18 = Object.getOwnPropertyDescriptor;
116992
117444
  var __defNormalProp$18 = (obj, key, value) => key in obj ? __defProp$18(obj, key, {
@@ -117854,21 +118306,47 @@ function blocksToChains(blocks) {
117854
118306
  }
117855
118307
  return chains;
117856
118308
  }
117857
- function toValidUncle(_context, finalizedWindowedChain, possibleUncle) {
118309
+ function toValidUncle(_context, finalizedWindowedChain, possibleUncle, onReject) {
117858
118310
  const finalizedWindowStartBlockNumber = finalizedWindowedChain.at(0)?.[0].block ?? -1;
117859
118311
  const finalizedHead = assertEx$1(finalizedWindowedChain.at(-1), () => "finalizedWindowedChain is empty");
118312
+ const tip = assertEx$1(possibleUncle.at(-1), () => "possibleUncle is empty");
118313
+ const reject = (reason, offendingTransactionHashes) => {
118314
+ onReject?.({
118315
+ blockHash: tip[0]._hash,
118316
+ blockNumber: tip[0].block,
118317
+ offendingTransactionHashes,
118318
+ reason
118319
+ });
118320
+ };
117860
118321
  const prunedPossibleUncle = possibleUncle.filter((b) => b[0].block > finalizedHead[0].block);
117861
- if (prunedPossibleUncle.length === 0) return;
117862
- if (prunedPossibleUncle[0][0].block !== finalizedHead[0].block + 1) return;
117863
- if (prunedPossibleUncle[0][0].previous !== finalizedHead[0]._hash) return;
118322
+ if (prunedPossibleUncle.length === 0) {
118323
+ reject("behind-finalized-head");
118324
+ return;
118325
+ }
118326
+ if (prunedPossibleUncle[0][0].block !== finalizedHead[0].block + 1) {
118327
+ reject("block-number-mismatch");
118328
+ return;
118329
+ }
118330
+ if (prunedPossibleUncle[0][0].previous !== finalizedHead[0]._hash) {
118331
+ reject("previous-hash-mismatch");
118332
+ return;
118333
+ }
117864
118334
  const allUncleTransactions = prunedPossibleUncle.flatMap((b) => b[1]).filter(isTransactionBoundWitness);
117865
118335
  const allFinalizedTransactions = finalizedWindowedChain.flatMap((b) => b[1]).filter(isTransactionBoundWitness);
117866
- if (allUncleTransactions.some((tx) => tx.nbf < finalizedWindowStartBlockNumber)) return;
117867
- if (allUncleTransactions.some((tx) => allFinalizedTransactions.some((finalTx) => finalTx._hash === tx._hash))) return;
118336
+ const txsBeforeWindow = allUncleTransactions.filter((tx) => tx.nbf < finalizedWindowStartBlockNumber);
118337
+ if (txsBeforeWindow.length > 0) {
118338
+ reject("tx-before-window", txsBeforeWindow.map((tx) => tx._hash));
118339
+ return;
118340
+ }
118341
+ const txsInWindow = allUncleTransactions.filter((tx) => allFinalizedTransactions.some((finalTx) => finalTx._hash === tx._hash));
118342
+ if (txsInWindow.length > 0) {
118343
+ reject("tx-already-finalized", txsInWindow.map((tx) => tx._hash));
118344
+ return;
118345
+ }
117868
118346
  return prunedPossibleUncle;
117869
118347
  }
117870
- function findUncles(context, finalizedWindowedChain, blocks) {
117871
- return blocksToChains(blocks).map((chain) => toValidUncle(context, finalizedWindowedChain, chain)).filter(exists$1);
118348
+ function findUncles(context, finalizedWindowedChain, blocks, onReject) {
118349
+ return blocksToChains(blocks).map((chain) => toValidUncle(context, finalizedWindowedChain, chain, onReject)).filter(exists$1);
117872
118350
  }
117873
118351
  var ValidationConfigZod = object$3({
117874
118352
  signerAuthorizations: array$1(SignerAuthorizationZod).default([]).register(globalRegistry, {
@@ -119366,6 +119844,7 @@ var SimpleBlockValidationViewer = class extends AbstractCreatableProvider {
119366
119844
  state: true,
119367
119845
  head: void 0
119368
119846
  };
119847
+ if (config !== void 0 && value !== true && state !== true) this.logger?.warn("validateBlocks called with a config that selects no validators (neither value nor state is true) — every block will report valid");
119369
119848
  const blocksWithMeta = await Promise.all(blocks.map((b) => Promise.all([PayloadBuilder.addHashMeta(b[0]), PayloadBuilder.addHashMeta(b[1])])));
119370
119849
  let head;
119371
119850
  if (isChainQualifiedHeadConfig(config)) {
@@ -119414,18 +119893,30 @@ var SimpleBlockValidationViewer = class extends AbstractCreatableProvider {
119414
119893
  }
119415
119894
  async doValidateState(blocks, chainIdAtBlockNumber) {
119416
119895
  const windowedUncleChain = await this.updateWindowedChainCache();
119417
- const uncles = findUncles(this.context, windowedUncleChain, blocks);
119896
+ const rejections = [];
119897
+ const uncles = findUncles(this.context, windowedUncleChain, blocks, (rejection) => rejections.push(rejection));
119418
119898
  if (uncles.length !== 1) {
119419
- this.logger?.warn(`Unexpected uncle count during block validation [uncles=${uncles.length}, blocks=${blocks.length}]`);
119899
+ const rejectionSummary = rejections.map((r) => `${r.blockNumber} [${r.blockHash}]: ${r.reason}${(r.offendingTransactionHashes?.length ?? 0) > 0 ? ` (tx ${r.offendingTransactionHashes?.join(", ")})` : ""}`).join("; ");
119900
+ this.logger?.warn(`Unexpected uncle count during block validation [uncles=${uncles.length}, blocks=${blocks.length}]` + (rejectionSummary.length > 0 ? ` \u2014 rejected: ${rejectionSummary}` : ""));
119420
119901
  this.logger?.debug(JSON.stringify({
119421
119902
  uncles,
119422
119903
  blocks: blocks.length
119423
119904
  }, null, 2));
119424
119905
  this.logger?.debug(JSON.stringify(windowedUncleChain, null, 2));
119425
- return blocks.map((block) => [new HydratedBlockValidationError(block[0]._hash, block, "Unexpected uncle count during state validation", {
119426
- uncles: uncles.length,
119427
- blocks: blocks.length
119428
- })]);
119906
+ return blocks.map((block) => {
119907
+ const rejection = rejections.find((r) => r.blockHash === block[0]._hash);
119908
+ const offendingTransactionHashes = rejection?.offendingTransactionHashes ?? [];
119909
+ if (rejection && offendingTransactionHashes.length > 0) return offendingTransactionHashes.map((txHash) => new HydratedBlockValidationError(txHash, block, `Uncle rejected during state validation: ${rejection.reason}`, {
119910
+ blockHash: rejection.blockHash,
119911
+ hash: txHash,
119912
+ reason: rejection.reason
119913
+ }));
119914
+ return [new HydratedBlockValidationError(block[0]._hash, block, `Unexpected uncle count during state validation${rejection ? `: ${rejection.reason}` : ""}`, {
119915
+ reason: rejection?.reason,
119916
+ uncles: uncles.length,
119917
+ blocks: blocks.length
119918
+ })];
119919
+ });
119429
119920
  }
119430
119921
  const validateState = assertEx$1(this.validators.blockStateValidator, () => "No block state validator registered");
119431
119922
  return await Promise.all(uncles[0].map(async (block) => {
@@ -120262,6 +120753,303 @@ __publicField$18(SimpleFinalizationViewer, "monikers", [FinalizationViewerMonike
120262
120753
  /** Read, write, or mixed capability surface exposed by the provider. */
120263
120754
  __publicField$18(SimpleFinalizationViewer, "surface", "node");
120264
120755
  SimpleFinalizationViewer = __decorateClass$18([creatableProvider()], SimpleFinalizationViewer);
120756
+ var MIN_POLL_INTERVAL_MS = 5e3;
120757
+ var DEFAULT_POLL_INTERVAL_MS = 1e4;
120758
+ var DEFAULT_FETCH_WINDOW = StepSizes[2];
120759
+ var MAX_FETCH_WINDOW = StepSizes[3];
120760
+ var SimpleFinalizedBlockStreamOptionsZod = object$3({
120761
+ /**
120762
+ * Hot-surface resume checkpoint: emit blocks strictly after this hash, as a
120763
+ * verified splice (the first emission's `previous` must equal it — mismatch
120764
+ * emits `desynced` at startup rather than delivering a diverged chain).
120765
+ * Omitted, the stream starts at the current head, delivered as the first
120766
+ * `nextBlock`.
120767
+ */
120768
+ after: optional$1(HashZod),
120769
+ /**
120770
+ * Upper bound on blocks fetched per `blocksByNumber` window during a walk.
120771
+ * The window adapts to the lag (never fetching past the head) and grows up to
120772
+ * this cap on deep replays, letting REST-backed viewers tile each window from
120773
+ * step rollup files. Capped at the largest served rollup (`StepSizes[3]`);
120774
+ * raise toward it for indexer-style deep replays, lower it to bound memory.
120775
+ */
120776
+ fetchWindow: number$1().int().positive().max(MAX_FETCH_WINDOW).default(DEFAULT_FETCH_WINDOW),
120777
+ /**
120778
+ * Hot-surface catch-up bound: when the head is further ahead than this, a
120779
+ * `gap` is announced and delivery resumes `maxCatchUp` blocks behind head.
120780
+ * The cold `blocks()` surface ignores this — it never gaps.
120781
+ */
120782
+ maxCatchUp: number$1().int().positive().default(StepSizes[1]),
120783
+ /** Head poll cadence shared by the hot surface and all `blocks()` iterations. */
120784
+ pollIntervalMs: number$1().min(MIN_POLL_INTERVAL_MS).default(DEFAULT_POLL_INTERVAL_MS)
120785
+ });
120786
+ function cursorFromBlock(block) {
120787
+ return {
120788
+ block: block[0].block,
120789
+ hash: block[0]._hash
120790
+ };
120791
+ }
120792
+ var SimpleFinalizedBlockStream = class extends AbstractCreatableProvider {
120793
+ /** Moniker implemented by this provider instance. */
120794
+ moniker = FinalizedBlockStreamMoniker;
120795
+ _blockViewer;
120796
+ _cursor;
120797
+ _finalizationViewer;
120798
+ _head;
120799
+ _headWaiters = [];
120800
+ _hotLoop;
120801
+ _isLive = false;
120802
+ _options;
120803
+ _pollInProgress = false;
120804
+ _pollTimer = null;
120805
+ _stopping = false;
120806
+ _terminal = false;
120807
+ /** Last position delivered on the hot surface, or `undefined` before the first. */
120808
+ get cursor() {
120809
+ return this._cursor;
120810
+ }
120811
+ /** True once the hot surface has caught up to the live head. */
120812
+ get isLive() {
120813
+ return this._isLive;
120814
+ }
120815
+ get options() {
120816
+ this._options ??= SimpleFinalizedBlockStreamOptionsZod.parse(this.config.options);
120817
+ return this._options;
120818
+ }
120819
+ /** Validates the provider options at create time. */
120820
+ static async paramsHandler(params = {}) {
120821
+ const handled = await super.paramsHandler(params);
120822
+ SimpleFinalizedBlockStreamOptionsZod.parse(handled.context.config.options);
120823
+ return handled;
120824
+ }
120825
+ /**
120826
+ * Cold, per-caller iteration: replay from `after`, then follow the head.
120827
+ * Gapless by construction — the caller paces the walk. Throws
120828
+ * `FinalizedBlockStreamDesyncError` on any continuity failure, including a
120829
+ * failed resume splice; other (transient) fetch errors also throw, and the
120830
+ * caller resumes from its own checkpoint.
120831
+ */
120832
+ async *blocks(options) {
120833
+ let cursor;
120834
+ if (isDefined$1(options?.after)) cursor = await this.resolveCheckpoint(options.after);
120835
+ else {
120836
+ const head = await this.currentHead();
120837
+ yield {
120838
+ block: head,
120839
+ head: head[0].block
120840
+ };
120841
+ cursor = cursorFromBlock(head);
120842
+ }
120843
+ while (!this._stopping) {
120844
+ const headNumber = (await this.currentHead())[0].block;
120845
+ if (cursor.block >= headNumber) {
120846
+ await this.waitForHeadAdvance();
120847
+ continue;
120848
+ }
120849
+ for (const block of await this.nextBlocks(cursor, headNumber)) {
120850
+ cursor = this.advanceCursor(cursor, block);
120851
+ yield {
120852
+ block,
120853
+ head: headNumber
120854
+ };
120855
+ if (this._stopping) return;
120856
+ }
120857
+ }
120858
+ }
120859
+ /** Creates the provider instance after its dependencies and configuration have resolved. */
120860
+ async createHandler() {
120861
+ await super.createHandler();
120862
+ const injected = this.params.viewers;
120863
+ this._blockViewer = injected?.blocks ?? assertEx$1(await this.locator.getInstance("BlockViewer"), () => "BlockViewer instance is required");
120864
+ this._finalizationViewer = injected?.finalization ?? assertEx$1(await this.locator.getInstance("FinalizationViewer"), () => "FinalizationViewer instance is required");
120865
+ }
120866
+ /** Starts the head poll and the hot delivery loop. */
120867
+ async startHandler() {
120868
+ await super.startHandler();
120869
+ this._stopping = false;
120870
+ this._terminal = false;
120871
+ await this.pollHead();
120872
+ this._pollTimer = setInterval(() => {
120873
+ this.pollHead();
120874
+ }, this.options.pollIntervalMs);
120875
+ this._hotLoop = this.runHot();
120876
+ }
120877
+ /** Stops the poll, ends the hot loop, and emits the terminal `stopped` event. */
120878
+ async stopHandler() {
120879
+ this._stopping = true;
120880
+ if (this._pollTimer) {
120881
+ clearInterval(this._pollTimer);
120882
+ this._pollTimer = null;
120883
+ }
120884
+ this.releaseHeadWaiters();
120885
+ await this._hotLoop;
120886
+ this._hotLoop = void 0;
120887
+ if (!this._terminal) {
120888
+ this._terminal = true;
120889
+ await this.emitSerial("stopped", { cursor: this._cursor });
120890
+ }
120891
+ this._head = void 0;
120892
+ await super.stopHandler();
120893
+ }
120894
+ /**
120895
+ * Verifies continuity and advances a cursor to the delivered block. A
120896
+ * `previous` mismatch on the expected block number is a data-integrity
120897
+ * fault; a wrong/missing block number is a transient fetch problem.
120898
+ */
120899
+ advanceCursor(cursor, block) {
120900
+ assertEx$1(block[0].block === cursor.block + 1, () => `FinalizedBlockStream: expected block ${cursor.block + 1}, fetched ${block[0].block}`);
120901
+ if (block[0].previous !== cursor.hash) throw new FinalizedBlockStreamDesyncError(cursor.hash, block);
120902
+ return cursorFromBlock(block);
120903
+ }
120904
+ /** One hot-loop step: bound the lag (announcing a `gap`), deliver the next window, mark live. */
120905
+ async advanceHot() {
120906
+ const head = await this.currentHead();
120907
+ const headNumber = head[0].block;
120908
+ const cursor = assertEx$1(this._cursor);
120909
+ if (cursor.block >= headNumber) {
120910
+ await this.markLive(head);
120911
+ await this.waitForHeadAdvance();
120912
+ return;
120913
+ }
120914
+ if (headNumber - cursor.block > this.options.maxCatchUp) {
120915
+ await this.announceGap(cursor, headNumber);
120916
+ return;
120917
+ }
120918
+ for (const block of await this.nextBlocks(cursor, headNumber)) {
120919
+ if (this._stopping) return;
120920
+ this._cursor = this.advanceCursor(assertEx$1(this._cursor), block);
120921
+ await this.emitSerial("nextBlock", {
120922
+ block,
120923
+ head: headNumber
120924
+ });
120925
+ }
120926
+ if (assertEx$1(this._cursor).block >= headNumber) await this.markLive(head);
120927
+ }
120928
+ /** Announces a hot-surface gap and splices the shared cursor to `maxCatchUp` behind head. */
120929
+ async announceGap(cursor, headNumber) {
120930
+ const resumeNumber = asXL1BlockNumber(headNumber - this.options.maxCatchUp + 1, true);
120931
+ const resumeBlock = assertEx$1(await this._blockViewer.blockByNumber(resumeNumber), () => `FinalizedBlockStream: gap resume block ${resumeNumber} unavailable`);
120932
+ const skipped = [asXL1BlockNumber(cursor.block + 1, true), asXL1BlockNumber(resumeNumber - 1, true)];
120933
+ this._isLive = false;
120934
+ await this.emitSerial("gap", {
120935
+ before: cursor,
120936
+ resumedAt: cursorFromBlock(resumeBlock),
120937
+ skipped
120938
+ });
120939
+ this._cursor = {
120940
+ block: asXL1BlockNumber(resumeNumber - 1, true),
120941
+ hash: assertEx$1(resumeBlock[0].previous, () => "FinalizedBlockStream: gap resume block has no previous")
120942
+ };
120943
+ }
120944
+ /** Returns the last polled head, fetching once when no poll has landed yet. */
120945
+ async currentHead() {
120946
+ if (this._head) return this._head;
120947
+ this._head ??= await this._finalizationViewer.head();
120948
+ return this._head;
120949
+ }
120950
+ /** Initializes the hot cursor: verified splice from `after`, or head-first delivery. */
120951
+ async initHotCursor() {
120952
+ const { after } = this.options;
120953
+ if (isDefined$1(after)) {
120954
+ this._cursor = await this.resolveCheckpoint(after);
120955
+ return;
120956
+ }
120957
+ const head = await this.currentHead();
120958
+ this._cursor = cursorFromBlock(head);
120959
+ await this.emitSerial("nextBlock", {
120960
+ block: head,
120961
+ head: head[0].block
120962
+ });
120963
+ await this.markLive(head);
120964
+ }
120965
+ /** Marks the hot surface live, emitting the transition once. */
120966
+ async markLive(head) {
120967
+ if (this._isLive) return;
120968
+ this._isLive = true;
120969
+ await this.emitSerial("live", { head: cursorFromBlock(head) });
120970
+ }
120971
+ /**
120972
+ * Fetches the ordered run of blocks after `cursor`, up to one window. Order
120973
+ * is normalized here; continuity is verified per block by `advanceCursor`.
120974
+ */
120975
+ async nextBlocks(cursor, headNumber) {
120976
+ const hi = asXL1BlockNumber(Math.min(cursor.block + this.options.fetchWindow, headNumber), true);
120977
+ const run = (await this._blockViewer.blocksByNumber(hi, hi - cursor.block)).filter((block) => block[0].block > cursor.block).toSorted((a, b) => a[0].block - b[0].block);
120978
+ assertEx$1(run.length > 0, () => `FinalizedBlockStream: no blocks fetched in (${cursor.block}, ${hi}]`);
120979
+ return run;
120980
+ }
120981
+ /** Polls the finalized head, releasing all cursor walks blocked on head growth. */
120982
+ async pollHead() {
120983
+ if (this._pollInProgress) return;
120984
+ this._pollInProgress = true;
120985
+ try {
120986
+ const head = await this._finalizationViewer.head();
120987
+ if (head[0]._hash !== this._head?.[0]._hash) {
120988
+ this._head = head;
120989
+ this.releaseHeadWaiters();
120990
+ }
120991
+ } catch (ex) {
120992
+ this.logger?.error("FinalizedBlockStream: error polling head", ex);
120993
+ } finally {
120994
+ this._pollInProgress = false;
120995
+ }
120996
+ }
120997
+ releaseHeadWaiters() {
120998
+ const waiters = this._headWaiters.splice(0);
120999
+ for (const release of waiters) release();
121000
+ }
121001
+ /** Resolves a checkpoint hash to a cursor, or throws the desync error a missing checkpoint implies. */
121002
+ async resolveCheckpoint(after) {
121003
+ const checkpoint = await this._blockViewer.blockByHash(after);
121004
+ if (!checkpoint) throw new FinalizedBlockStreamDesyncError(after);
121005
+ return cursorFromBlock(checkpoint);
121006
+ }
121007
+ /**
121008
+ * The hot delivery loop. Transient errors are logged and retried on the next
121009
+ * head advance; a continuity failure emits the terminal `desynced` event.
121010
+ */
121011
+ async runHot() {
121012
+ try {
121013
+ await this.initHotCursor();
121014
+ while (!this._stopping) try {
121015
+ await this.advanceHot();
121016
+ } catch (ex) {
121017
+ if (ex instanceof FinalizedBlockStreamDesyncError) throw ex;
121018
+ if (this._stopping) return;
121019
+ this.logger?.error("FinalizedBlockStream: hot loop error, retrying on next head", ex);
121020
+ await this.waitForHeadAdvance();
121021
+ }
121022
+ } catch (ex) {
121023
+ if (ex instanceof FinalizedBlockStreamDesyncError && !this._terminal) {
121024
+ this._terminal = true;
121025
+ await this.emitSerial("desynced", {
121026
+ block: ex.block,
121027
+ expectedPrevious: ex.expectedPrevious
121028
+ });
121029
+ return;
121030
+ }
121031
+ this.logger?.error("FinalizedBlockStream: hot loop terminated", ex);
121032
+ }
121033
+ }
121034
+ /** Suspends until the polled head changes or the stream stops. */
121035
+ waitForHeadAdvance() {
121036
+ if (this._stopping) return Promise.resolve();
121037
+ return new Promise((resolve) => {
121038
+ this._headWaiters.push(resolve);
121039
+ });
121040
+ }
121041
+ };
121042
+ /** Connection kinds supported by this provider. */
121043
+ __publicField$18(SimpleFinalizedBlockStream, "connectionTypes", ["none"]);
121044
+ /** Primary moniker used to resolve this provider. */
121045
+ __publicField$18(SimpleFinalizedBlockStream, "defaultMoniker", FinalizedBlockStreamMoniker);
121046
+ /** Provider monikers that must resolve before this provider can be created. */
121047
+ __publicField$18(SimpleFinalizedBlockStream, "dependencies", [BlockViewerMoniker, FinalizationViewerMoniker]);
121048
+ /** Provider monikers implemented by this provider class. */
121049
+ __publicField$18(SimpleFinalizedBlockStream, "monikers", [FinalizedBlockStreamMoniker]);
121050
+ /** Read, write, or mixed capability surface exposed by the provider. */
121051
+ __publicField$18(SimpleFinalizedBlockStream, "surface", "node");
121052
+ SimpleFinalizedBlockStream = __decorateClass$18([creatableProvider()], SimpleFinalizedBlockStream);
120265
121053
  var SimpleIndexViewer = class extends AbstractCreatableProvider {
120266
121054
  /** Moniker implemented by this provider instance. */
120267
121055
  moniker = SimpleIndexViewer.defaultMoniker;
@@ -120435,6 +121223,83 @@ var nextPruneCursor = (batch, pruneHashes, cursor) => {
120435
121223
  const pruneSet = new Set(pruneHashes);
120436
121224
  return batch.findLast((bundle3) => !pruneSet.has(bundle3._hash))?._sequence ?? cursor;
120437
121225
  };
121226
+ async function simpleBlockValidationCheck(payloads, context) {
121227
+ return (await Promise.all(payloads.map(async (payload) => {
121228
+ return [isPayloadBundle(payload) ? await bundledPayloadToHydratedBlock(payload) : void 0, payload];
121229
+ }))).map(([block, bundle3]) => evaluateBlockCandidate(block, bundle3, context));
121230
+ }
121231
+ async function simpleTransactionValidationCheck(payloads, context) {
121232
+ const transactionBundles = await Promise.all(payloads.map(async (payload) => {
121233
+ return [isPayloadBundle(payload) ? await bundledPayloadToHydratedTransaction(payload) : void 0, payload];
121234
+ }));
121235
+ return Promise.all(transactionBundles.map(async ([transaction, bundle3]) => {
121236
+ return evaluateTransactionCandidate(transaction, bundle3, context);
121237
+ }));
121238
+ }
121239
+ function evaluateBlockCandidate(block, bundle3, { chainId, headNumber, logger }) {
121240
+ const typeCheckPassed = isSignedHydratedBlockWithHashMeta(block);
121241
+ const chainIdPassed = typeCheckPassed && block[0].chain === chainId;
121242
+ const blockNumberPassed = typeCheckPassed && block[0].block > headNumber;
121243
+ const validationPassed = typeCheckPassed && chainIdPassed && blockNumberPassed;
121244
+ if (!validationPassed) logFailedBlockCheck({
121245
+ block,
121246
+ blockNumberPassed,
121247
+ bundle: bundle3,
121248
+ chainIdPassed,
121249
+ headNumber,
121250
+ logger,
121251
+ typeCheckPassed
121252
+ });
121253
+ return [validationPassed ? block : void 0, bundle3];
121254
+ }
121255
+ async function evaluateTransactionCandidate(transaction, bundle3, { chainId, headNumber, logger, maxExpAhead }) {
121256
+ const typeCheckPassed = isSignedHydratedTransactionWithHashMeta(transaction);
121257
+ const chainIdPassed = typeCheckPassed && transaction[0].chain === chainId;
121258
+ const expPassed = typeCheckPassed && transaction[0].exp > headNumber && transaction[0].exp <= headNumber + maxExpAhead;
121259
+ const opcodeCheckPassed = await checkTransactionOpcodes(transaction, bundle3, logger);
121260
+ const validationPassed = typeCheckPassed && chainIdPassed && expPassed && opcodeCheckPassed;
121261
+ if (!validationPassed) logFailedTransactionCheck({
121262
+ bundle: bundle3,
121263
+ chainIdPassed,
121264
+ expPassed,
121265
+ headNumber,
121266
+ logger,
121267
+ opcodeCheckPassed,
121268
+ transaction,
121269
+ typeCheckPassed
121270
+ });
121271
+ return [validationPassed ? transaction : void 0, bundle3];
121272
+ }
121273
+ async function checkTransactionOpcodes(transaction, bundle3, logger) {
121274
+ try {
121275
+ await validateTransactionsOpcodes(transaction === void 0 ? [] : [transaction]);
121276
+ return true;
121277
+ } catch (error) {
121278
+ const message = error instanceof Error ? error.message : String(error);
121279
+ logger?.debug(`Opcode validation failed for transaction ${bundle3._hash} during simpleValidationCheck`);
121280
+ logger?.debug(` - error: ${message}`);
121281
+ return false;
121282
+ }
121283
+ }
121284
+ function logFailedBlockCheck({ block, blockNumberPassed, bundle: bundle3, chainIdPassed, headNumber, logger, typeCheckPassed }) {
121285
+ if (chainIdPassed && typeCheckPassed && !blockNumberPassed) {
121286
+ logger?.debug(`Pruning stale block candidate bundle ${bundle3._hash} during simpleValidationCheck (candidate height ${block?.[0].block} <= finalized head ${headNumber} \u2014 routine GC of a finalized or superseded candidate)`);
121287
+ return;
121288
+ }
121289
+ logger?.debug(`Pruning block bundle ${bundle3._hash} during simpleValidationCheck`);
121290
+ logger?.debug(` - chainId match: ${chainIdPassed}`);
121291
+ logger?.debug(` - blockNumber check: ${blockNumberPassed} [head=${headNumber} candidate=${block?.[0].block}]`);
121292
+ logger?.debug(` - typeCheck: ${typeCheckPassed}`);
121293
+ logger?.debug(` - bundle hash: ${bundle3._hash}`);
121294
+ }
121295
+ function logFailedTransactionCheck({ bundle: bundle3, chainIdPassed, expPassed, headNumber, logger, opcodeCheckPassed, transaction, typeCheckPassed }) {
121296
+ logger?.debug(`Pruning transaction bundle ${bundle3._hash} during simpleValidationCheck`);
121297
+ logger?.debug(` - chainId match: ${chainIdPassed}`);
121298
+ logger?.debug(` - exp check: ${expPassed} [head=${headNumber} exp=${transaction?.[0].exp}]`);
121299
+ logger?.debug(` - opcode check: ${opcodeCheckPassed}`);
121300
+ logger?.debug(` - typeCheck: ${typeCheckPassed}`);
121301
+ logger?.debug(` - bundle hash: ${bundle3._hash}`);
121302
+ }
120438
121303
  var DEFAULT_SYNC_INTERVAL = 3e4;
120439
121304
  var DEFAULT_SYNC_LIMIT = 100;
120440
121305
  var ENFORCE_CAP_BATCH_SIZE = 1e3;
@@ -120567,7 +121432,11 @@ var SimpleMempoolRunner = class extends AbstractCreatableProvider {
120567
121432
  }
120568
121433
  while (batch.length > 0 && pruned < maxPrune && total < maxCheck) {
120569
121434
  batches += 1;
120570
- const blocksAndBundles = await this.simpleBlockValidationCheck(batch);
121435
+ const blocksAndBundles = await simpleBlockValidationCheck(batch, {
121436
+ chainId: await this.chainContractViewer.chainId(),
121437
+ headNumber: await this.finalizationViewer.headNumber(),
121438
+ logger: this.logger
121439
+ });
120571
121440
  const blocks = blocksAndBundles.map(([b]) => b);
120572
121441
  const bundles = blocksAndBundles.map(([_, p]) => p);
120573
121442
  const valid = blocks.map((b) => !!b);
@@ -120581,9 +121450,10 @@ var SimpleMempoolRunner = class extends AbstractCreatableProvider {
120581
121450
  state: true
120582
121451
  }))),
120583
121452
  isValidated: isSignedHydratedBlockWithHashMeta,
120584
- onInvalid: ({ bundle: bundle3, result }) => {
120585
- const errors = result;
121453
+ onInvalid: async ({ bundle: bundle3, item, result }) => {
121454
+ const errors = isSignedHydratedBlockWithHashMeta(result) ? [] : result;
120586
121455
  this.logger?.info(`[SimpleMempoolRunner] prunePendingBlocks deleting block ${bundle3._hash} (validation: ${errors.at(0)?.message ?? "failed simple/full check"})`);
121456
+ await this.routeRejectedBlock(item, errors);
120587
121457
  }
120588
121458
  });
120589
121459
  const pruneHashes = invalidBundleHashes(bundles, valid);
@@ -120619,7 +121489,12 @@ var SimpleMempoolRunner = class extends AbstractCreatableProvider {
120619
121489
  }
120620
121490
  while (batch.length > 0 && pruned < maxPrune && total < maxCheck) {
120621
121491
  batches += 1;
120622
- const transactionsAndBundles = await this.simpleTransactionValidationCheck(batch);
121492
+ const transactionsAndBundles = await simpleTransactionValidationCheck(batch, {
121493
+ chainId: await this.chainContractViewer.chainId(),
121494
+ headNumber: await this.finalizationViewer.headNumber(),
121495
+ logger: this.logger,
121496
+ maxExpAhead: this.maxExpAhead
121497
+ });
120623
121498
  const transactions = transactionsAndBundles.map(([t]) => t);
120624
121499
  const bundles = transactionsAndBundles.map(([_, p]) => p);
120625
121500
  const valid = transactions.map((t) => !!t);
@@ -120779,6 +121654,20 @@ var SimpleMempoolRunner = class extends AbstractCreatableProvider {
120779
121654
  if (isDemotionAware(this._mempoolViewer)) return this._mempoolViewer.getEvictionPriorityOrder(bundleHashesOldestFirst);
120780
121655
  return bundleHashesOldestFirst;
120781
121656
  }
121657
+ async routeRejectedBlock(block, errors) {
121658
+ if (!this._deadLetterQueueRunner) return;
121659
+ const rejectionErrors = errors.map((e) => ({
121660
+ hash: e.hash ?? block[0]._hash,
121661
+ name: e.name ?? "BlockValidationError",
121662
+ message: String(e.message ?? e)
121663
+ }));
121664
+ await this._deadLetterQueueRunner.rejectBlock({
121665
+ schema: BlockRejectionSchema,
121666
+ block,
121667
+ errors: rejectionErrors,
121668
+ rejector: "mempool"
121669
+ });
121670
+ }
120782
121671
  async routeRejectedTransaction(transaction, errors) {
120783
121672
  if (!this._deadLetterQueueRunner) return;
120784
121673
  const rejectionErrors = errors.map((e) => ({
@@ -120793,60 +121682,6 @@ var SimpleMempoolRunner = class extends AbstractCreatableProvider {
120793
121682
  rejector: "mempool"
120794
121683
  });
120795
121684
  }
120796
- async simpleBlockValidationCheck(payloads) {
120797
- const headNumber = await this.finalizationViewer.headNumber();
120798
- const chainId = await this.chainContractViewer.chainId();
120799
- return (await Promise.all(payloads.map(async (p) => {
120800
- return [isPayloadBundle(p) ? await bundledPayloadToHydratedBlock(p) : void 0, p];
120801
- }))).map(([block, bundle3]) => {
120802
- const blockCheckPassed = !!block;
120803
- const chainIdPassed = blockCheckPassed ? block[0].chain === chainId : false;
120804
- const blockNumberPassed = blockCheckPassed ? block[0].block > headNumber : false;
120805
- const typeCheckPassed = blockCheckPassed ? isSignedHydratedBlockWithHashMeta(block) : false;
120806
- const validationPassed = blockCheckPassed && chainIdPassed && blockNumberPassed && typeCheckPassed;
120807
- const validatedBlock = validationPassed ? block : void 0;
120808
- if (!validationPassed) {
120809
- this.logger?.debug(`Pruning block bundle ${bundle3._hash} during simpleValidationCheck`);
120810
- this.logger?.debug(` - chainId match: ${chainIdPassed}`);
120811
- this.logger?.debug(` - blockNumber check: ${blockNumberPassed} [${headNumber}|${block?.[0].block}]`);
120812
- this.logger?.debug(` - typeCheck: ${typeCheckPassed}`);
120813
- this.logger?.debug(` - bundle hash: ${bundle3._hash}`);
120814
- }
120815
- return [validatedBlock, bundle3];
120816
- });
120817
- }
120818
- async simpleTransactionValidationCheck(payloads) {
120819
- const headNumber = await this.finalizationViewer.headNumber();
120820
- const chainId = await this.chainContractViewer.chainId();
120821
- const transactionBundles = await Promise.all(payloads.map(async (p) => {
120822
- return [isPayloadBundle(p) ? await bundledPayloadToHydratedTransaction(p) : void 0, p];
120823
- }));
120824
- return await Promise.all(transactionBundles.map(async ([transaction, bundle3]) => {
120825
- const transactionCheckPassed = !!transaction;
120826
- const chainIdPassed = transactionCheckPassed ? transaction[0].chain === chainId : false;
120827
- const expPassed = transactionCheckPassed ? transaction[0].exp > headNumber && transaction[0].exp <= headNumber + this.maxExpAhead : false;
120828
- const typeCheckPassed = transactionCheckPassed ? isSignedHydratedTransactionWithHashMeta(transaction) : false;
120829
- let opcodeCheckPassed = false;
120830
- try {
120831
- await validateTransactionsOpcodes(transaction ? [transaction] : []);
120832
- opcodeCheckPassed = true;
120833
- } catch (e) {
120834
- this.logger?.debug(`Opcode validation failed for transaction ${bundle3._hash} during simpleValidationCheck`);
120835
- this.logger?.debug(` - error: ${e.message}`);
120836
- }
120837
- const validationPassed = transactionCheckPassed && chainIdPassed && expPassed && typeCheckPassed && opcodeCheckPassed;
120838
- const validatedTransaction = validationPassed ? transaction : void 0;
120839
- if (!validationPassed) {
120840
- this.logger?.debug(`Pruning block bundle ${bundle3._hash} during simpleValidationCheck`);
120841
- this.logger?.debug(` - chainId match: ${chainIdPassed}`);
120842
- this.logger?.debug(` - exp check: ${expPassed}`);
120843
- this.logger?.debug(` - opcode check: ${opcodeCheckPassed}`);
120844
- this.logger?.debug(` - typeCheck: ${typeCheckPassed}`);
120845
- this.logger?.debug(` - bundle hash: ${bundle3._hash}`);
120846
- }
120847
- return [validatedTransaction, bundle3];
120848
- }));
120849
- }
120850
121685
  async syncBlocksFrom(external) {
120851
121686
  const externalBlocks = await external.pendingBlocks({ limit: this.syncLimit });
120852
121687
  if (externalBlocks.length === 0) return;
@@ -120893,6 +121728,11 @@ __publicField$18(SimpleMempoolRunner, "monikers", [MempoolRunnerMoniker]);
120893
121728
  /** Read, write, or mixed capability surface exposed by the provider. */
120894
121729
  __publicField$18(SimpleMempoolRunner, "surface", "node");
120895
121730
  SimpleMempoolRunner = __decorateClass$18([creatableProvider()], SimpleMempoolRunner);
121731
+ async function resolveHashCursor(archivist, providedCursor) {
121732
+ if (!isHash(providedCursor)) return void 0;
121733
+ const [payload] = await archivist.get([providedCursor]);
121734
+ return isDefined$1(payload) ? payload._sequence : void 0;
121735
+ }
120896
121736
  var SimpleMempoolViewerOptionsZod = object$3({
120897
121737
  demotionThreshold: number$1().default(3),
120898
121738
  handoutStatsTtlBlocks: number$1().default(1e3),
@@ -120960,11 +121800,7 @@ var SimpleMempoolViewer = class extends AbstractCreatableProvider {
120960
121800
  }
120961
121801
  /** Returns the pending blocks result exposed by this provider. */
120962
121802
  async pendingBlocks({ cursor: providedCursor } = {}) {
120963
- let cursor;
120964
- if (isHash(providedCursor)) {
120965
- const [p] = await this.pendingBlocksArchivist.get([providedCursor]);
120966
- if (isDefined$1(p)) cursor = p._sequence;
120967
- }
121803
+ const cursor = await resolveHashCursor(this.pendingBlocksArchivist, providedCursor);
120968
121804
  const filteredBundles = (await this.pendingBlocksArchivist.next({
120969
121805
  order: "desc",
120970
121806
  limit: 100,
@@ -120974,11 +121810,8 @@ var SimpleMempoolViewer = class extends AbstractCreatableProvider {
120974
121810
  }
120975
121811
  /** Returns the pending transactions result exposed by this provider. */
120976
121812
  async pendingTransactions({ cursor: providedCursor, limit = 100 } = {}) {
120977
- let cursor;
120978
- if (isHash(providedCursor)) {
120979
- const [p] = await this.pendingTransactionsArchivist.get([providedCursor]);
120980
- if (isDefined$1(p)) cursor = p._sequence;
120981
- }
121813
+ await this.windowedBlockViewer.sync?.();
121814
+ const cursor = await resolveHashCursor(this.pendingTransactionsArchivist, providedCursor);
120982
121815
  this.logger?.debug(`Fetching pending transactions from cursor: ${cursor}`);
120983
121816
  const bundles = await this.pendingTransactionsArchivist.next({
120984
121817
  order: "asc",
@@ -122104,7 +122937,9 @@ var SimpleWindowedBlockViewer = class extends AbstractCreatableProvider {
122104
122937
  _blockNumberMap;
122105
122938
  _blockViewer;
122106
122939
  _chain = [];
122940
+ _inFlightSync = null;
122107
122941
  _options;
122942
+ _queuedSync = null;
122108
122943
  _syncMutex = new Mutex();
122109
122944
  _timerId = null;
122110
122945
  _transactionHashMap;
@@ -122212,6 +123047,32 @@ var SimpleWindowedBlockViewer = class extends AbstractCreatableProvider {
122212
123047
  await super.stopHandler();
122213
123048
  this.stopPoll();
122214
123049
  }
123050
+ /**
123051
+ * Synchronizes the in-memory window with the backing block viewer immediately, waiting for any
123052
+ * in-flight sync to complete first. Callers whose correctness depends on seeing the latest
123053
+ * finalized blocks (e.g. mempool inclusion checks) must call this rather than rely on the
123054
+ * background poll, whose interval is far coarser than block finalization.
123055
+ *
123056
+ * Concurrent callers are coalesced: a caller arriving while a sync runs joins one shared
123057
+ * follow-up pass (which starts after the running pass and therefore observes every block
123058
+ * finalized before the caller arrived) instead of enqueuing its own. Without this, N
123059
+ * concurrent callers — the handout path is reachable per producer tick and over RPC — would
123060
+ * execute N sequential backing reads behind the sync mutex.
123061
+ */
123062
+ async sync() {
123063
+ if (this._inFlightSync === null) {
123064
+ const run = this.runSync().finally(() => {
123065
+ if (this._inFlightSync === run) this._inFlightSync = null;
123066
+ });
123067
+ this._inFlightSync = run;
123068
+ return await run;
123069
+ }
123070
+ this._queuedSync ??= this._inFlightSync.then(() => {
123071
+ this._queuedSync = null;
123072
+ return this.sync();
123073
+ });
123074
+ return await this._queuedSync;
123075
+ }
122215
123076
  addBlock(block) {
122216
123077
  this._chain.push(block);
122217
123078
  this._blockHashMap.set(block[0]._hash, block);
@@ -122225,18 +123086,8 @@ var SimpleWindowedBlockViewer = class extends AbstractCreatableProvider {
122225
123086
  for (const tx of transactionsFromHydratedBlock(removedBlock)) this._transactionHashMap.delete(tx._hash);
122226
123087
  }
122227
123088
  }
122228
- startPoll() {
122229
- this._timerId = setInterval(() => {
122230
- this.sync();
122231
- }, this.syncInterval);
122232
- }
122233
- stopPoll() {
122234
- if (this._timerId) clearInterval(this._timerId);
122235
- this._timerId = null;
122236
- }
122237
- async sync() {
122238
- if (this._syncMutex.isLocked()) return;
122239
- return await this._syncMutex.runExclusive(async () => {
123089
+ async runSync() {
123090
+ await this._syncMutex.runExclusive(async () => {
122240
123091
  try {
122241
123092
  let cursor = await this._blockViewer.currentBlock();
122242
123093
  const previousHead = this._chain.length > 0 ? await this.currentBlockHash() : null;
@@ -122252,6 +123103,19 @@ var SimpleWindowedBlockViewer = class extends AbstractCreatableProvider {
122252
123103
  }
122253
123104
  });
122254
123105
  }
123106
+ startPoll() {
123107
+ this._timerId = setInterval(() => {
123108
+ this.syncIfIdle();
123109
+ }, this.syncInterval);
123110
+ }
123111
+ stopPoll() {
123112
+ if (this._timerId) clearInterval(this._timerId);
123113
+ this._timerId = null;
123114
+ }
123115
+ async syncIfIdle() {
123116
+ if (this._syncMutex.isLocked()) return;
123117
+ await this.sync();
123118
+ }
122255
123119
  };
122256
123120
  /** Connection kinds supported by this provider. */
122257
123121
  __publicField$18(SimpleWindowedBlockViewer, "connectionTypes", [
@@ -123269,7 +124133,7 @@ function getOriginalId(rawRequest) {
123269
124133
  return [void 0, false];
123270
124134
  }
123271
124135
  //#endregion
123272
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_d668443a8314bbcb6b4d304ca8d635e8/node_modules/@xyo-network/xl1-sdk/dist/neutral/rpc.mjs
124136
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_a771cefd6e9eb69efc5a95a989caf2a3/node_modules/@xyo-network/xl1-sdk/dist/neutral/rpc.mjs
123273
124137
  var __defProp$17 = Object.defineProperty;
123274
124138
  var __getOwnPropDesc$17 = Object.getOwnPropertyDescriptor;
123275
124139
  var __defNormalProp$17 = (obj, key, value) => key in obj ? __defProp$17(obj, key, {
@@ -224588,7 +225452,7 @@ var BaseMongoSdk = class {
224588
225452
  }
224589
225453
  };
224590
225454
  //#endregion
224591
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-driver-mongodb@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zo_13d35ab58c6839187ab33de3996ce7b7/node_modules/@xyo-network/xl1-driver-mongodb/dist/neutral/index.mjs
225455
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-driver-mongodb@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zo_c6dcb1b9a06ee930febaf04848b7a277/node_modules/@xyo-network/xl1-driver-mongodb/dist/neutral/index.mjs
224592
225456
  var __defProp$15 = Object.defineProperty;
224593
225457
  var __getOwnPropDesc$15 = Object.getOwnPropertyDescriptor;
224594
225458
  var __defNormalProp$15 = (obj, key, value) => key in obj ? __defProp$15(obj, key, {
@@ -227822,7 +228686,12 @@ var ChainFinalizer = class extends Base {
227822
228686
  this.windowedFinalizedChain = [...this.windowedFinalizedChain, ...chain].slice(-this.maxWindowSize);
227823
228687
  }
227824
228688
  };
227825
- var ChainHeadSelector = class extends ChainFinalizer {
228689
+ var ChainHeadSelector = class _ChainHeadSelector extends ChainFinalizer {
228690
+ /**
228691
+ * How long uncle selection may go without a single qualifying candidate (while candidates are
228692
+ * present) before a warning is emitted; also the minimum interval between repeat warnings.
228693
+ */
228694
+ static SilentUncleRejectionWarnAfterMs = 5e3;
227826
228695
  admission;
227827
228696
  allowedProducers;
227828
228697
  backoffMs;
@@ -227848,6 +228717,7 @@ var ChainHeadSelector = class extends ChainFinalizer {
227848
228717
  const proposedBlocks = await this.admit(allProposedBlocks, allowed);
227849
228718
  this.windowedFinalizedChain = await getWindowedChain$1(this.context, this.blockViewer, this.maxWindowSize, this.windowedFinalizedChain);
227850
228719
  const uncles = findUncles$1(this.context, this.windowedFinalizedChain, proposedBlocks);
228720
+ this.reportSilentUncleRejections(proposedBlocks, uncles.length);
227851
228721
  return findBestUncle(this.windowedFinalizedChain, uncles, {
227852
228722
  backoffMs: this.backoffMs,
227853
228723
  minCandidates: this.minCandidates
@@ -227918,6 +228788,32 @@ var ChainHeadSelector = class extends ChainFinalizer {
227918
228788
  });
227919
228789
  } catch {}
227920
228790
  }
228791
+ /**
228792
+ * Surfaces the otherwise-silent case where candidates are continuously present but none
228793
+ * qualifies as an uncle — without this, the only signal of a stalled selector is an endless
228794
+ * "No new blocks found N to N" while rejected candidates cycle through the pool. Zero-qualify
228795
+ * moments are routine in healthy operation (a just-finalized candidate lingers until the pool
228796
+ * GC), so this warns only after candidates have been failing continuously for
228797
+ * SilentUncleRejectionWarnAfterMs — an idle (candidate-free) tick resets the clock — then
228798
+ * rate-limits to one warn per that interval. State lives in context.singletons because a
228799
+ * fresh ChainHeadSelector is constructed on every finalization tick.
228800
+ */
228801
+ reportSilentUncleRejections(proposedBlocks, uncleCount) {
228802
+ const singletons = this.context.singletons;
228803
+ const stateKey = "ChainHeadSelector:uncleSelectionHealth";
228804
+ const now = Date.now();
228805
+ const state = singletons[stateKey] ?? { lastWarnedAt: 0 };
228806
+ singletons[stateKey] = state;
228807
+ if (uncleCount > 0 || proposedBlocks.length === 0) {
228808
+ state.unqualifiedSince = void 0;
228809
+ return;
228810
+ }
228811
+ state.unqualifiedSince ??= now;
228812
+ if (now - state.unqualifiedSince < _ChainHeadSelector.SilentUncleRejectionWarnAfterMs) return;
228813
+ if (now - state.lastWarnedAt < _ChainHeadSelector.SilentUncleRejectionWarnAfterMs) return;
228814
+ state.lastWarnedAt = now;
228815
+ this.context.logger?.warn(`findBestHead: candidates have failed uncle qualification continuously for ${now - state.unqualifiedSince}ms \u2014 ${proposedBlocks.length} pending candidate(s): ` + proposedBlocks.map((b) => `${b[0].block} [${b[0]._hash}]`).join(", "));
228816
+ }
227921
228817
  };
227922
228818
  asSchema$1("network.xyo.chain.summary.producers", true);
227923
228819
  asSchema$1("network.xyo.chain.summary.staked.intent", true);
@@ -228072,7 +228968,7 @@ var STAKE_EVENT_NAMES$1 = /* @__PURE__ */ new Set([
228072
228968
  "StakeRemoved",
228073
228969
  "StakeWithdrawn"
228074
228970
  ]);
228075
- var DEFAULT_HEAD_POLL_INTERVAL_MS = 5e3;
228971
+ var DEFAULT_HEAD_POLL_INTERVAL_MS$1 = 5e3;
228076
228972
  var MIN_HEAD_POLL_INTERVAL_MS = 5e3;
228077
228973
  var RestStakeEventsViewerOptionsZod = object$3({ headPollIntervalMs: number$1().optional() });
228078
228974
  var RestStakeEventsViewer = class extends AbstractCreatableProvider$1 {
@@ -228080,7 +228976,7 @@ var RestStakeEventsViewer = class extends AbstractCreatableProvider$1 {
228080
228976
  completeFrames = /* @__PURE__ */ new Map();
228081
228977
  contractInterface = new Interface(IAddressStakingEvents__factory2.abi);
228082
228978
  currentHead;
228083
- headPollIntervalMs = DEFAULT_HEAD_POLL_INTERVAL_MS;
228979
+ headPollIntervalMs = DEFAULT_HEAD_POLL_INTERVAL_MS$1;
228084
228980
  lastSuccessfulSyncAt;
228085
228981
  manifestPromise;
228086
228982
  positionCountCheckpoints = [];
@@ -228104,7 +229000,7 @@ var RestStakeEventsViewer = class extends AbstractCreatableProvider$1 {
228104
229000
  RestStakeEventsViewer.requireBoundConnection(this.config);
228105
229001
  const { headPollIntervalMs } = RestStakeEventsViewerOptionsZod.parse(this.config.options);
228106
229002
  if (headPollIntervalMs !== void 0) assertEx$1(headPollIntervalMs >= MIN_HEAD_POLL_INTERVAL_MS, () => `headPollIntervalMs must be at least ${MIN_HEAD_POLL_INTERVAL_MS}ms`);
228107
- this.headPollIntervalMs = headPollIntervalMs ?? DEFAULT_HEAD_POLL_INTERVAL_MS;
229003
+ this.headPollIntervalMs = headPollIntervalMs ?? DEFAULT_HEAD_POLL_INTERVAL_MS$1;
228108
229004
  }
228109
229005
  async positionCount(range) {
228110
229006
  await this.sync();
@@ -230079,7 +230975,7 @@ var SimpleBlockRunner = class extends AbstractCreatableProvider$1 {
230079
230975
  moniker = SimpleBlockRunner.defaultMoniker;
230080
230976
  _blockRewardDiviner;
230081
230977
  _deadLetterQueueRunner;
230082
- _excludedTransactionHashes = /* @__PURE__ */ new Set();
230978
+ _excludedTransactionHashes = /* @__PURE__ */ new Map();
230083
230979
  _lastRedeclarationBlock;
230084
230980
  _rejectedTransactionsArchivist;
230085
230981
  _account;
@@ -230089,6 +230985,7 @@ var SimpleBlockRunner = class extends AbstractCreatableProvider$1 {
230089
230985
  _blockValidationViewer;
230090
230986
  _chainParamsViewer;
230091
230987
  _finalizationViewer;
230988
+ _lastRejectedBuildAt = 0;
230092
230989
  /** Cache of the last candidate this runner signed; the mempool is the source of truth. */
230093
230990
  _lastSignedCandidate;
230094
230991
  _mempoolViewer;
@@ -230203,10 +231100,13 @@ var SimpleBlockRunner = class extends AbstractCreatableProvider$1 {
230203
231100
  const shouldValidateBalances = validateBalances ?? this.params.validateBalances ?? true;
230204
231101
  return await this.spanAsync("proposeNextValidBlock", async () => {
230205
231102
  try {
231103
+ if (this.isWithinRejectedBuildBackoff(force)) return;
230206
231104
  const { block: previousBlock } = assertEx$1(asBlockBoundWitness$1(head), () => "Invalid head block");
230207
231105
  const nextBlock = previousBlock + 1;
230208
231106
  const chainId = await this.finalizationViewer.chainId();
230209
- const pendingTransactions = (await this.mempoolViewer.pendingTransactions({ limit: SimpleBlockRunner.DefaultBlockSize })).filter((tx) => !this._excludedTransactionHashes.has(tx[0]._hash));
231107
+ const pendingTransactionsRaw = await this.mempoolViewer.pendingTransactions({ limit: SimpleBlockRunner.DefaultBlockSize });
231108
+ this.evictStaleExclusions(previousBlock);
231109
+ const pendingTransactions = pendingTransactionsRaw.filter((tx) => !this._excludedTransactionHashes.has(tx[0]._hash));
230210
231110
  const nextBlockTransactions = await this.rejectWrongChainTransactions(pendingTransactions, chainId);
230211
231111
  this.logger?.log(`Pending Tx Count ${nextBlockTransactions.length}`);
230212
231112
  const nonTxPayloads = [];
@@ -230216,10 +231116,7 @@ var SimpleBlockRunner = class extends AbstractCreatableProvider$1 {
230216
231116
  const rewardTransferPayloads = await this.getBlockRewardTransfers(nextBlock);
230217
231117
  nonTxPayloads.push(...rewardTransferPayloads);
230218
231118
  const transactionTransfers = await generateTransactionFeeTransfers(this.address, nextBlockTransactions);
230219
- const timeStart = Date.now();
230220
231119
  const timePayload = await this.generateTimePayload();
230221
- const timeDuration = Date.now() - timeStart;
230222
- if (timeDuration > 100) this.logger?.warn(`[Slow] Generated time payload in ${timeDuration}ms`);
230223
231120
  const [initialFundedTransactions, initialFundedTransfers] = await this.filterByFunded(head, nextBlockTransactions, transactionTransfers, shouldValidateBalances);
230224
231121
  const stepRewardPoolBalance = (await this.accountBalanceViewer.accountBalances([XYO_STEP_REWARD_ADDRESS]))[String(XYO_STEP_REWARD_ADDRESS)];
230225
231122
  const { block: proposedBlock, errors: proposedErrors } = await this.runBuildValidateRetryLoop({
@@ -230231,14 +231128,31 @@ var SimpleBlockRunner = class extends AbstractCreatableProvider$1 {
230231
231128
  initialFundedTransactions,
230232
231129
  initialFundedTransfers
230233
231130
  });
230234
- if (isSignedHydratedBlockWithHashMeta$1(proposedBlock)) return proposedBlock;
230235
- if (proposedBlock !== void 0) await this.rejectExhaustedBlock(proposedBlock, proposedErrors);
231131
+ return await this.commitProposedBlock(proposedBlock, proposedErrors);
230236
231132
  } catch (error) {
230237
231133
  this.logger?.error(`Error proposing next valid block: ${error.message}`);
230238
231134
  throw error;
230239
231135
  }
230240
231136
  }, this.context);
230241
231137
  }
231138
+ addTransferOutflow(outflow, payload) {
231139
+ let result = outflow;
231140
+ for (const [to, amount] of Object.entries(payload.transfers)) {
231141
+ if (to === payload.from) continue;
231142
+ result += hexToBigInt(amount ?? "00");
231143
+ }
231144
+ return result;
231145
+ }
231146
+ async commitProposedBlock(proposedBlock, proposedErrors) {
231147
+ if (proposedErrors.length === 0 && isSignedHydratedBlockWithHashMeta$1(proposedBlock)) {
231148
+ this._lastRejectedBuildAt = 0;
231149
+ return proposedBlock;
231150
+ }
231151
+ if (proposedBlock !== void 0) {
231152
+ this._lastRejectedBuildAt = Date.now();
231153
+ await this.rejectExhaustedBlock(proposedBlock, proposedErrors);
231154
+ }
231155
+ }
230242
231156
  /**
230243
231157
  * Compute the cumulative outflow a single tx would charge to its `from`
230244
231158
  * address, using the same rule as `BlockCumulativeBalanceValidator`:
@@ -230248,14 +231162,6 @@ var SimpleBlockRunner = class extends AbstractCreatableProvider$1 {
230248
231162
  * reject, which would otherwise wedge the chain because the producer's
230249
231163
  * `_lastProducedBlock` cache mutes retries.
230250
231164
  */
230251
- addTransferOutflow(outflow, payload) {
230252
- let result = outflow;
230253
- for (const [to, amount] of Object.entries(payload.transfers)) {
230254
- if (to === payload.from) continue;
230255
- result += hexToBigInt(amount ?? "00");
230256
- }
230257
- return result;
230258
- }
230259
231165
  computeTransactionOutflow(tx) {
230260
231166
  const [bw, payloads] = tx;
230261
231167
  const { base, gasLimit, priority } = bw.fees;
@@ -230269,6 +231175,14 @@ var SimpleBlockRunner = class extends AbstractCreatableProvider$1 {
230269
231175
  }
230270
231176
  return outflow;
230271
231177
  }
231178
+ /**
231179
+ * Drops head-relative ('block-balance') exclusions once the head has advanced past the height
231180
+ * they were recorded at — the sender's funding is re-evaluated by filterByFunded at the new
231181
+ * head. Deterministic ('tx-invalid') exclusions are kept for the process lifetime.
231182
+ */
231183
+ evictStaleExclusions(headBlock) {
231184
+ for (const [hash, entry] of this._excludedTransactionHashes) if (entry.reason === "block-balance" && headBlock > entry.excludedAtBlock) this._excludedTransactionHashes.delete(hash);
231185
+ }
230272
231186
  async filterByFunded(head, txs, transfers, validateBalances = false) {
230273
231187
  const fundedTransfers = [];
230274
231188
  const fundedTransactions = [];
@@ -230298,7 +231212,11 @@ var SimpleBlockRunner = class extends AbstractCreatableProvider$1 {
230298
231212
  return [fundedTransactions, fundedTransfers];
230299
231213
  }
230300
231214
  async generateTimePayload() {
230301
- return await this.timeSyncViewer.currentTimePayload();
231215
+ const timeStart = Date.now();
231216
+ const timePayload = await this.timeSyncViewer.currentTimePayload();
231217
+ const timeDuration = Date.now() - timeStart;
231218
+ if (timeDuration > 100) this.logger?.warn(`[Slow] Generated time payload in ${timeDuration}ms`);
231219
+ return timePayload;
230302
231220
  }
230303
231221
  /**
230304
231222
  * Check if a heartbeat block is required based on network activity.
@@ -230310,6 +231228,11 @@ var SimpleBlockRunner = class extends AbstractCreatableProvider$1 {
230310
231228
  if (isDefined$1(epoch) && Date.now() - epoch > this.heartbeatInterval) return true;
230311
231229
  return false;
230312
231230
  }
231231
+ isWithinRejectedBuildBackoff(force) {
231232
+ if (force || Date.now() - this._lastRejectedBuildAt >= SimpleBlockRunner.RejectedBuildBackoffMs) return false;
231233
+ this.logger?.debug("Skipping block production during rejected-build backoff");
231234
+ return true;
231235
+ }
230313
231236
  /**
230314
231237
  * The hash of this producer's own earlier candidate at the same height and parent, if any.
230315
231238
  *
@@ -230404,7 +231327,11 @@ var SimpleBlockRunner = class extends AbstractCreatableProvider$1 {
230404
231327
  ];
230405
231328
  this.logger?.info(`Building block ${head.block + 1}${attempt > 0 ? ` (retry ${attempt})` : ""}`);
230406
231329
  lastBlock = await buildNextBlock(head, candidateTransactions, blockPayloads, [this.account], XYO_STEP_REWARD_ADDRESS, stepRewardPoolBalance, void 0, chainId, supersedes);
230407
- const validated = await this.blockValidationViewer.validateBlock(lastBlock, { head: head._hash });
231330
+ const validated = await this.blockValidationViewer.validateBlock(lastBlock, {
231331
+ value: true,
231332
+ state: true,
231333
+ head: head._hash
231334
+ });
230408
231335
  if (isSignedHydratedBlockWithHashMeta$1(validated)) {
230409
231336
  this._lastSignedCandidate = {
230410
231337
  block: validated[0].block,
@@ -230423,7 +231350,10 @@ var SimpleBlockRunner = class extends AbstractCreatableProvider$1 {
230423
231350
  errors: validated
230424
231351
  });
230425
231352
  if (offendingHashes.length === 0 || reason === "unknown") break;
230426
- for (const offendingHash of offendingHashes) this._excludedTransactionHashes.add(offendingHash);
231353
+ for (const offendingHash of offendingHashes) this._excludedTransactionHashes.set(offendingHash, {
231354
+ excludedAtBlock: head.block,
231355
+ reason
231356
+ });
230427
231357
  const offendingSet = new Set(offendingHashes);
230428
231358
  candidateTransactions = candidateTransactions.filter((tx) => !offendingSet.has(tx[0]._hash));
230429
231359
  const remainingFromAddresses = new Set(candidateTransactions.map((tx) => tx[0].from));
@@ -230436,6 +231366,12 @@ var SimpleBlockRunner = class extends AbstractCreatableProvider$1 {
230436
231366
  };
230437
231367
  }
230438
231368
  };
231369
+ /**
231370
+ * Minimum time between build attempts after a fully-rejected build (validation exhausted with
231371
+ * no attributable transaction to exclude). Such a build fails identically until external state
231372
+ * changes, so retrying at the production tick rate only churns build → validate → DLQ.
231373
+ */
231374
+ __publicField$11(SimpleBlockRunner, "RejectedBuildBackoffMs", 1e3);
230439
231375
  __publicField$11(SimpleBlockRunner, "connectionTypes", [
230440
231376
  "lmdb",
230441
231377
  "mongo",
@@ -232388,6 +233324,8 @@ var ProducerActor = class extends ChainActor {
232388
233324
  _blockViewer;
232389
233325
  _chainContractViewer;
232390
233326
  _chainId;
233327
+ _fastCandidateRecoveriesForHead = 0;
233328
+ _lastCandidateGoneCheckTime = 0;
232391
233329
  _lastHeadChangeTime;
232392
233330
  _lastHeadHash;
232393
233331
  _mempoolRunner;
@@ -232453,6 +233391,8 @@ var ProducerActor = class extends ChainActor {
232453
233391
  this._lastProducedBlock = void 0;
232454
233392
  this._lastHeadHash = void 0;
232455
233393
  this._lastHeadChangeTime = void 0;
233394
+ this._fastCandidateRecoveriesForHead = 0;
233395
+ this._lastCandidateGoneCheckTime = 0;
232456
233396
  this.registerTimer("BlockProductionTimer", async () => {
232457
233397
  await this.produceBlock();
232458
233398
  }, 2e3, this.blockProductionCheckInterval);
@@ -232463,6 +233403,25 @@ var ProducerActor = class extends ChainActor {
232463
233403
  calculateBlocksUntilProducerDeclarationExpiration(currentBlock) {
232464
233404
  return (this._lastRedeclarationIntent?.exp ?? currentBlock) - currentBlock;
232465
233405
  }
233406
+ /**
233407
+ * Whether the last produced candidate has vanished from the pending-block pool while the head
233408
+ * has not advanced — i.e. the mempool pruned it after downstream validation rejected it. The
233409
+ * probe runs at most once per CandidateGoneCheckIntervalMs while a candidate stands on an
233410
+ * unchanged head (one pendingBlocks read per probe); only POSITIVE recoveries — probes that
233411
+ * find the candidate gone — are capped at MaxFastCandidateRecoveriesPerHead per head, so a
233412
+ * persistently-rejected producer backs off to the stale-head resubmission threshold instead of
233413
+ * churning rebuilds forever.
233414
+ */
233415
+ async lastCandidateDropped(now) {
233416
+ const lastProduced = this._lastProducedBlock;
233417
+ if (isUndefined$1(lastProduced)) return false;
233418
+ if (this._fastCandidateRecoveriesForHead >= ProducerActor.MaxFastCandidateRecoveriesPerHead) return false;
233419
+ if (now - this._lastCandidateGoneCheckTime < ProducerActor.CandidateGoneCheckIntervalMs) return false;
233420
+ this._lastCandidateGoneCheckTime = now;
233421
+ const pendingBlocks = await this.mempoolViewer.pendingBlocks();
233422
+ if (pendingBlocks.some((candidate) => candidate[0]._hash === lastProduced[0]._hash)) return false;
233423
+ return pendingBlocks.length < ProducerActor.CandidateGoneScanLimit;
233424
+ }
232466
233425
  async produceBlock() {
232467
233426
  this._producerActorBlockProductionChecks.add(1, this._metricAttributes);
232468
233427
  await this.spanAsync("produceBlock", async () => {
@@ -232470,40 +233429,7 @@ var ProducerActor = class extends ChainActor {
232470
233429
  this.logger?.debug("Skipping block production, previous production still in progress");
232471
233430
  return;
232472
233431
  }
232473
- await this._produceBlockMutex.runExclusive(async () => {
232474
- const [head] = await this.blockViewer.currentBlock();
232475
- const headHash = head._hash;
232476
- const currentTime = Date.now();
232477
- if (this._lastHeadHash !== headHash) {
232478
- const lastHeadHashHex = isDefined$1(this._lastHeadHash) ? `0x${this._lastHeadHash}` : "undefined";
232479
- const currentHeadHashHex = `0x${headHash}`;
232480
- this.logger?.log(`Found updated head ${lastHeadHashHex} -> ${currentHeadHashHex}`);
232481
- this._lastHeadHash = headHash;
232482
- this._lastHeadChangeTime = currentTime;
232483
- }
232484
- const timeSinceHeadChange = isDefined$1(this._lastHeadChangeTime) ? currentTime - this._lastHeadChangeTime : 0;
232485
- const shouldSubmit = this._lastProducedBlock?.[0].previous !== headHash;
232486
- const shouldResubmit = timeSinceHeadChange > this.headResubmissionThreshold;
232487
- if (!(shouldSubmit || shouldResubmit)) {
232488
- this.logger?.debug("No block submission required at this time.");
232489
- return;
232490
- }
232491
- if (shouldResubmit) {
232492
- this.logger?.log(`Resubmitting block due to stale head. Head ${toFormattedBlockReference(head)} unchanged for ${timeSinceHeadChange}ms`);
232493
- this._lastHeadChangeTime = currentTime;
232494
- }
232495
- this._producerActorBlockProductionAttempts.add(1, this._metricAttributes);
232496
- const nextBlock = await this.blockRunner.produceNextBlock(head);
232497
- if (nextBlock) {
232498
- const displayBlockNumber = toFormattedBlockReference(nextBlock[0]);
232499
- this.logger?.log("Produced block:", displayBlockNumber);
232500
- this._producerActorBlocksProduced.add(1, this._metricAttributes);
232501
- if ((await this.mempoolRunner.submitBlocks([nextBlock])).length === 0) this.logger?.error(`Submit dropped block ${displayBlockNumber} silently \u2014 archivist accepted 0 of 1 (hash ${nextBlock[0]._hash})`);
232502
- else this.logger?.log("Published block:", displayBlockNumber);
232503
- this._producerActorBlocksPublished.add(1, this._metricAttributes);
232504
- this._lastProducedBlock = nextBlock;
232505
- } else this.logger?.log("No block produced for submission.");
232506
- });
233432
+ await this._produceBlockMutex.runExclusive(() => this.produceBlockExclusive());
232507
233433
  }, {
232508
233434
  ...this.context,
232509
233435
  timeBudgetLimit: 1e3
@@ -232568,8 +233494,73 @@ var ProducerActor = class extends ChainActor {
232568
233494
  }
232569
233495
  return true;
232570
233496
  }
233497
+ async produceBlockExclusive() {
233498
+ const [head] = await this.blockViewer.currentBlock();
233499
+ const headHash = head._hash;
233500
+ const currentTime = Date.now();
233501
+ this.recordHeadChange(headHash, currentTime);
233502
+ const timeSinceHeadChange = isDefined$1(this._lastHeadChangeTime) ? currentTime - this._lastHeadChangeTime : 0;
233503
+ const shouldSubmit = this._lastProducedBlock?.[0].previous !== headHash;
233504
+ const shouldResubmit = timeSinceHeadChange > this.headResubmissionThreshold;
233505
+ const shouldRecoverDroppedCandidate = !shouldSubmit && !shouldResubmit && await this.lastCandidateDropped(currentTime);
233506
+ if (!(shouldSubmit || shouldResubmit || shouldRecoverDroppedCandidate)) {
233507
+ this.logger?.debug("No block submission required at this time.");
233508
+ return;
233509
+ }
233510
+ if (shouldResubmit) {
233511
+ this.logger?.log(`Resubmitting block due to stale head. Head ${toFormattedBlockReference(head)} unchanged for ${timeSinceHeadChange}ms`);
233512
+ this._lastHeadChangeTime = currentTime;
233513
+ }
233514
+ if (shouldRecoverDroppedCandidate) this.recoverDroppedCandidate();
233515
+ await this.publishNextBlock(head, currentTime);
233516
+ }
233517
+ async publishNextBlock(head, currentTime) {
233518
+ this._producerActorBlockProductionAttempts.add(1, this._metricAttributes);
233519
+ const nextBlock = await this.blockRunner.produceNextBlock(head);
233520
+ if (!nextBlock) {
233521
+ this.logger?.log("No block produced for submission.");
233522
+ return;
233523
+ }
233524
+ const displayBlockNumber = toFormattedBlockReference(nextBlock[0]);
233525
+ this.logger?.log("Produced block:", displayBlockNumber);
233526
+ this._producerActorBlocksProduced.add(1, this._metricAttributes);
233527
+ if ((await this.mempoolRunner.submitBlocks([nextBlock])).length === 0) {
233528
+ this.logger?.error(`Submit dropped block ${displayBlockNumber} silently \u2014 archivist accepted 0 of 1 (hash ${nextBlock[0]._hash})`);
233529
+ return;
233530
+ }
233531
+ this.logger?.log("Published block:", displayBlockNumber);
233532
+ this._producerActorBlocksPublished.add(1, this._metricAttributes);
233533
+ this._lastProducedBlock = nextBlock;
233534
+ this._lastCandidateGoneCheckTime = currentTime;
233535
+ }
233536
+ recordHeadChange(headHash, currentTime) {
233537
+ if (this._lastHeadHash === headHash) return;
233538
+ const lastHeadHashHex = isDefined$1(this._lastHeadHash) ? `0x${this._lastHeadHash}` : "undefined";
233539
+ this.logger?.log(`Found updated head ${lastHeadHashHex} -> 0x${headHash}`);
233540
+ this._lastHeadHash = headHash;
233541
+ this._lastHeadChangeTime = currentTime;
233542
+ this._fastCandidateRecoveriesForHead = 0;
233543
+ }
233544
+ recoverDroppedCandidate() {
233545
+ const lastProduced = this._lastProducedBlock;
233546
+ if (isUndefined$1(lastProduced)) return;
233547
+ this._fastCandidateRecoveriesForHead += 1;
233548
+ this.logger?.warn(`Last produced candidate ${toFormattedBlockReference(lastProduced[0])} is no longer pending (pruned or rejected); resuming production (recovery ${this._fastCandidateRecoveriesForHead}/${ProducerActor.MaxFastCandidateRecoveriesPerHead} for this head)`);
233549
+ this._lastProducedBlock = void 0;
233550
+ }
232571
233551
  };
232572
233552
  /**
233553
+ * Minimum time in milliseconds between checks of whether the last produced
233554
+ * candidate is still in the pending-block pool. Bounds the cost of the
233555
+ * dropped-candidate recovery probe (a pendingBlocks read per check).
233556
+ */
233557
+ __publicField$7(ProducerActor, "CandidateGoneCheckIntervalMs", 1e3);
233558
+ /**
233559
+ * The mempool viewer's fixed pendingBlocks page size. A probe that sees a full page cannot
233560
+ * prove the candidate is gone and must treat it as still pending.
233561
+ */
233562
+ __publicField$7(ProducerActor, "CandidateGoneScanLimit", 100);
233563
+ /**
232573
233564
  * The default interval time (in MS) between block production attempts.
232574
233565
  */
232575
233566
  __publicField$7(ProducerActor, "DefaultBlockProductionCheckInterval", DEFAULT_BLOCK_PRODUCTION_CHECK_INTERVAL);
@@ -232589,6 +233580,13 @@ __publicField$7(ProducerActor, "DefaultBlockProductionCheckInterval", DEFAULT_BL
232589
233580
  */
232590
233581
  __publicField$7(ProducerActor, "HeadResubmissionThresholdMs", 3e4);
232591
233582
  /**
233583
+ * Maximum number of dropped-candidate recoveries per head before deferring to
233584
+ * the stale-head resubmission threshold. A producer whose candidates are
233585
+ * persistently rejected (e.g. not on the allow-list) must back off rather
233586
+ * than churn rebuild/reject cycles at the recovery cadence forever.
233587
+ */
233588
+ __publicField$7(ProducerActor, "MaxFastCandidateRecoveriesPerHead", 3);
233589
+ /**
232592
233590
  * The window (in blocks) before expiration to attempt redeclaration of producer intent.
232593
233591
  */
232594
233592
  __publicField$7(ProducerActor, "RedeclarationWindow", 1e3);
@@ -240910,7 +241908,7 @@ function withDeprecationWarning$1(module, host, options = {}) {
240910
241908
  return module;
240911
241909
  }
240912
241910
  //#endregion
240913
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_f803ff54f950c092c4a357d77886b418/node_modules/@xyo-network/xl1-sdk/dist/node/providers.mjs
241911
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-sdk@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@4.4.3__@o_3a01f3229f2daa942444e08696345b23/node_modules/@xyo-network/xl1-sdk/dist/node/providers.mjs
240914
241912
  var __defProp$3 = Object.defineProperty;
240915
241913
  var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
240916
241914
  var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, {
@@ -241864,6 +242862,179 @@ __publicField$3(EvmStakeViewer, "monikers", [StakeViewerMoniker$1]);
241864
242862
  /** Read, write, or mixed capability surface exposed by the provider. */
241865
242863
  __publicField$3(EvmStakeViewer, "surface", "node");
241866
242864
  EvmStakeViewer = __decorateClass$3([creatableProvider$1()], EvmStakeViewer);
242865
+ var DEFAULT_HEAD_POLL_INTERVAL_MS = 5e3;
242866
+ var RestNetworkStakeStepRewardsByPositionViewerOptionsZod = object$3({
242867
+ headPollIntervalMs: number$1().min(5e3).default(DEFAULT_HEAD_POLL_INTERVAL_MS),
242868
+ policyId: NetworkStakeRewardsPolicyIdZod.default(NETWORK_STAKE_REWARDS_UNMULTIPLIED_POLICY)
242869
+ });
242870
+ var RestNetworkStakeStepRewardsByPositionViewer = class extends AbstractCreatableProvider$1 {
242871
+ moniker = RestNetworkStakeStepRewardsByPositionViewer.defaultMoniker;
242872
+ currentHead;
242873
+ headPollIntervalMs = DEFAULT_HEAD_POLL_INTERVAL_MS;
242874
+ headPromise;
242875
+ lastSuccessfulHeadAt;
242876
+ manifestPromise;
242877
+ policyId = NETWORK_STAKE_REWARDS_UNMULTIPLIED_POLICY;
242878
+ snapshotPromises = /* @__PURE__ */ new Map();
242879
+ stepPromises = /* @__PURE__ */ new Map();
242880
+ get baseUrl() {
242881
+ const connection = RestNetworkStakeStepRewardsByPositionViewer.requireBoundConnection(this.config);
242882
+ const config = connection.config;
242883
+ if (config.type !== "rest") throw new Error(`Connection "${connection.name}" must be a rest connection`);
242884
+ return assertEx$1(config.baseUrl, () => `Connection "${connection.name}" requires a rest baseUrl`);
242885
+ }
242886
+ get fetchFn() {
242887
+ return this.context.fetchFn ?? fetch.bind(globalThis);
242888
+ }
242889
+ /** Returns the policy bonus. The unmultiplied-v1 index has no multipliers, so bonus is zero. */
242890
+ async bonus(options = {}) {
242891
+ const total = await this.total(options);
242892
+ return Object.fromEntries(Object.keys(total).map((key) => [Number(key), asAttoXL1$1(0n)]));
242893
+ }
242894
+ /** Claimed rewards are not part of the earned-reward index. */
242895
+ claimed(_options) {
242896
+ throw new Error("Method [claimed] not implemented.");
242897
+ }
242898
+ /** Creates the provider instance after validating its REST binding and options. */
242899
+ async createHandler() {
242900
+ await super.createHandler();
242901
+ RestNetworkStakeStepRewardsByPositionViewer.requireBoundConnection(this.config);
242902
+ const options = RestNetworkStakeStepRewardsByPositionViewerOptionsZod.parse(this.config.options);
242903
+ this.headPollIntervalMs = options.headPollIntervalMs;
242904
+ this.policyId = options.policyId;
242905
+ }
242906
+ /** Base-v1 total and earned rewards are identical. */
242907
+ async earned(options = {}) {
242908
+ return await this.total(options);
242909
+ }
242910
+ /** Returns rewards by requested position from the durable index. */
242911
+ async total({ range, positions } = {}) {
242912
+ if (!isArray(positions)) return {};
242913
+ const head = await this.getHead();
242914
+ const resolvedRange = asXL1BlockRange$1(range ?? [0, head.processedThroughBlock], { name: "RestNetworkStakeStepRewardsByPositionViewer" });
242915
+ const result = {};
242916
+ for (const position of positions) result[position] = (await this.totalForPosition(position, resolvedRange))[0];
242917
+ return result;
242918
+ }
242919
+ /** Returns one position's cumulative reward and the range's emitted reward pool. */
242920
+ async totalForPosition(position, range) {
242921
+ const head = await this.getHead();
242922
+ this.assertPublishedRange(range, head);
242923
+ if (head.positionCount === 0) return [asAttoXL1$1(0n), asAttoXL1$1(0n)];
242924
+ this.assertPosition(position, head);
242925
+ if (range[0] === 0 && range[1] >= head.processedThroughBlock) {
242926
+ const snapshot = await this.getSnapshot(head);
242927
+ return [asAttoXL1$1(BigInt(snapshot.positionRewards[String(position)] ?? "0")), asAttoXL1$1(BigInt(snapshot.totalReward))];
242928
+ }
242929
+ const steps = await this.stepsForRange(range, head);
242930
+ return [asAttoXL1$1(steps.reduce((sum, step) => sum + BigInt(step.positionRewards[String(position)] ?? "0"), 0n)), asAttoXL1$1(steps.reduce((sum, step) => sum + BigInt(step.totalReward), 0n))];
242931
+ }
242932
+ /** Returns the emitted reward pool for one indexed step. */
242933
+ async totalForStep(step) {
242934
+ const head = await this.getHead();
242935
+ this.assertPublishedStep(step, head);
242936
+ return asAttoXL1$1(BigInt((await this.getStep(step)).totalReward));
242937
+ }
242938
+ /** Returns one position's allocation and emitted pool for one indexed step. */
242939
+ async totalForStepForPosition(step, position) {
242940
+ const head = await this.getHead();
242941
+ this.assertPosition(position, head);
242942
+ this.assertPublishedStep(step, head);
242943
+ const record = await this.getStep(step);
242944
+ return [asAttoXL1$1(BigInt(record.positionRewards[String(position)] ?? "0")), asAttoXL1$1(BigInt(record.totalReward))];
242945
+ }
242946
+ /** Unclaimed rewards require redemption state and are not part of this index. */
242947
+ unclaimed(_options) {
242948
+ throw new Error("Method [unclaimed] not implemented.");
242949
+ }
242950
+ assertPosition(position, head) {
242951
+ assertEx$1(Number.isSafeInteger(position) && position >= 0 && position < head.positionCount, () => `Position ${position} is outside rewards index positionCount ${head.positionCount}`);
242952
+ }
242953
+ assertPublishedRange(range, head) {
242954
+ assertEx$1(range[1] <= head.processedThroughBlock, () => `Reward range ends at ${range[1]}, beyond index watermark ${head.processedThroughBlock}`);
242955
+ }
242956
+ assertPublishedStep(step, head) {
242957
+ assertEx$1(step.block <= head.processedThroughBlock, () => `Reward step ${step.block}|${step.step} is beyond index watermark ${head.processedThroughBlock}`);
242958
+ }
242959
+ async fetchJson(path) {
242960
+ const response = await this.fetchFn(`${this.baseUrl.replace(/\/$/, "")}/${path}`);
242961
+ if (!response.ok) throw new Error(`Network stake rewards index request failed [${response.status}] for ${path}`);
242962
+ return await response.json();
242963
+ }
242964
+ async getHead() {
242965
+ const now = Date.now();
242966
+ const elapsed = this.lastSuccessfulHeadAt === void 0 ? void 0 : now - this.lastSuccessfulHeadAt;
242967
+ if (this.currentHead !== void 0 && elapsed !== void 0 && elapsed >= 0 && elapsed < this.headPollIntervalMs) return this.currentHead;
242968
+ this.headPromise ??= this.syncHead().finally(() => {
242969
+ this.headPromise = void 0;
242970
+ });
242971
+ return await this.headPromise;
242972
+ }
242973
+ async getManifest() {
242974
+ this.manifestPromise ??= this.fetchJson(networkStakeRewardsIndexManifestPath(this.policyId)).then((value) => asNetworkStakeRewardsIndexManifest(value, true)).catch((error) => {
242975
+ this.manifestPromise = void 0;
242976
+ throw error;
242977
+ });
242978
+ return await this.manifestPromise;
242979
+ }
242980
+ async getSnapshot(head) {
242981
+ const { snapshotHash } = head;
242982
+ let promise = this.snapshotPromises.get(snapshotHash);
242983
+ if (promise === void 0) {
242984
+ const path = networkStakeRewardsIndexSnapshotPath(this.policyId, snapshotHash);
242985
+ promise = this.fetchJson(path).then(async (value) => {
242986
+ const snapshot = asNetworkStakeRewardsIndexSnapshot(value, true);
242987
+ assertEx$1(await PayloadBuilder$1.hash(snapshot) === snapshotHash, () => `Rewards snapshot hash mismatch: ${path}`);
242988
+ return snapshot;
242989
+ });
242990
+ this.snapshotPromises.set(snapshotHash, promise);
242991
+ }
242992
+ try {
242993
+ const snapshot = await promise;
242994
+ assertEx$1(snapshot.policyId === this.policyId, () => "Rewards snapshot policy mismatch");
242995
+ assertEx$1(snapshot.stepCount === head.stepCount, () => "Rewards snapshot step count mismatch");
242996
+ return snapshot;
242997
+ } catch (error) {
242998
+ this.snapshotPromises.delete(snapshotHash);
242999
+ throw error;
243000
+ }
243001
+ }
243002
+ async getStep(step) {
243003
+ const path = networkStakeRewardsIndexStepPath(this.policyId, step);
243004
+ let promise = this.stepPromises.get(path);
243005
+ if (promise === void 0) {
243006
+ promise = this.fetchJson(path).then((value) => asNetworkStakeRewardsIndexStep(value, true));
243007
+ this.stepPromises.set(path, promise);
243008
+ }
243009
+ try {
243010
+ const record = await promise;
243011
+ assertEx$1(record.policyId === this.policyId, () => "Rewards step policy mismatch");
243012
+ assertEx$1(record.step.block === step.block && record.step.step === step.step, () => "Rewards step identity mismatch");
243013
+ return record;
243014
+ } catch (error) {
243015
+ this.stepPromises.delete(path);
243016
+ throw error;
243017
+ }
243018
+ }
243019
+ async stepsForRange(range, head) {
243020
+ const steps = blockRangeSteps(range, (await this.getManifest()).stepLevels).filter((step) => step.block <= head.processedThroughBlock);
243021
+ return await Promise.all(steps.map(async (step) => await this.getStep(step)));
243022
+ }
243023
+ async syncHead() {
243024
+ assertEx$1((await this.getManifest()).policyId === this.policyId, () => "Rewards manifest policy mismatch");
243025
+ const head = asNetworkStakeRewardsIndexHead(await this.fetchJson(networkStakeRewardsIndexHeadPath(this.policyId)), true);
243026
+ assertEx$1(head.policyId === this.policyId, () => "Rewards head policy mismatch");
243027
+ this.currentHead = head;
243028
+ this.lastSuccessfulHeadAt = Date.now();
243029
+ return head;
243030
+ }
243031
+ };
243032
+ __publicField$3(RestNetworkStakeStepRewardsByPositionViewer, "connectionTypes", ["rest"]);
243033
+ __publicField$3(RestNetworkStakeStepRewardsByPositionViewer, "defaultMoniker", NetworkStakeStepRewardsByPositionViewerMoniker$1);
243034
+ __publicField$3(RestNetworkStakeStepRewardsByPositionViewer, "dependencies", []);
243035
+ __publicField$3(RestNetworkStakeStepRewardsByPositionViewer, "monikers", [NetworkStakeStepRewardsByPositionViewerMoniker$1]);
243036
+ __publicField$3(RestNetworkStakeStepRewardsByPositionViewer, "surface", "node");
243037
+ RestNetworkStakeStepRewardsByPositionViewer = __decorateClass$3([creatableProvider$1()], RestNetworkStakeStepRewardsByPositionViewer);
241867
243038
  var SimpleDeadLetterQueueRunner = class extends AbstractCreatableProvider$1 {
241868
243039
  /** Moniker implemented by this provider instance. */
241869
243040
  moniker = SimpleDeadLetterQueueRunner.defaultMoniker;
@@ -243260,181 +244431,8 @@ __publicField$3(RestChainParamsViewer, "monikers", [ChainParamsViewerMoniker]);
243260
244431
  /** Read, write, or mixed capability surface exposed by the provider. */
243261
244432
  __publicField$3(RestChainParamsViewer, "surface", "node");
243262
244433
  RestChainParamsViewer = __decorateClass$3([creatableProvider$1()], RestChainParamsViewer);
243263
- var DEFAULT_HEAD_POLL_INTERVAL_MS2 = 5e3;
243264
- var RestNetworkStakeStepRewardsByPositionViewerOptionsZod = object$3({
243265
- headPollIntervalMs: number$1().min(5e3).default(DEFAULT_HEAD_POLL_INTERVAL_MS2),
243266
- policyId: NetworkStakeRewardsPolicyIdZod.default(NETWORK_STAKE_REWARDS_UNMULTIPLIED_POLICY)
243267
- });
243268
- var RestNetworkStakeStepRewardsByPositionViewer = class extends AbstractCreatableProvider$1 {
243269
- moniker = RestNetworkStakeStepRewardsByPositionViewer.defaultMoniker;
243270
- currentHead;
243271
- headPollIntervalMs = DEFAULT_HEAD_POLL_INTERVAL_MS2;
243272
- headPromise;
243273
- lastSuccessfulHeadAt;
243274
- manifestPromise;
243275
- policyId = NETWORK_STAKE_REWARDS_UNMULTIPLIED_POLICY;
243276
- snapshotPromises = /* @__PURE__ */ new Map();
243277
- stepPromises = /* @__PURE__ */ new Map();
243278
- get baseUrl() {
243279
- const connection = RestNetworkStakeStepRewardsByPositionViewer.requireBoundConnection(this.config);
243280
- const config = connection.config;
243281
- if (config.type !== "rest") throw new Error(`Connection "${connection.name}" must be a rest connection`);
243282
- return assertEx$1(config.baseUrl, () => `Connection "${connection.name}" requires a rest baseUrl`);
243283
- }
243284
- get fetchFn() {
243285
- return this.context.fetchFn ?? fetch.bind(globalThis);
243286
- }
243287
- /** Returns the policy bonus. The unmultiplied-v1 index has no multipliers, so bonus is zero. */
243288
- async bonus(options = {}) {
243289
- const total = await this.total(options);
243290
- return Object.fromEntries(Object.keys(total).map((key) => [Number(key), asAttoXL1$1(0n)]));
243291
- }
243292
- /** Claimed rewards are not part of the earned-reward index. */
243293
- claimed(_options) {
243294
- throw new Error("Method [claimed] not implemented.");
243295
- }
243296
- /** Creates the provider instance after validating its REST binding and options. */
243297
- async createHandler() {
243298
- await super.createHandler();
243299
- RestNetworkStakeStepRewardsByPositionViewer.requireBoundConnection(this.config);
243300
- const options = RestNetworkStakeStepRewardsByPositionViewerOptionsZod.parse(this.config.options);
243301
- this.headPollIntervalMs = options.headPollIntervalMs;
243302
- this.policyId = options.policyId;
243303
- }
243304
- /** Base-v1 total and earned rewards are identical. */
243305
- async earned(options = {}) {
243306
- return await this.total(options);
243307
- }
243308
- /** Returns rewards by requested position from the durable index. */
243309
- async total({ range, positions } = {}) {
243310
- if (!isArray(positions)) return {};
243311
- const head = await this.getHead();
243312
- const resolvedRange = asXL1BlockRange$1(range ?? [0, head.processedThroughBlock], { name: "RestNetworkStakeStepRewardsByPositionViewer" });
243313
- const result = {};
243314
- for (const position of positions) result[position] = (await this.totalForPosition(position, resolvedRange))[0];
243315
- return result;
243316
- }
243317
- /** Returns one position's cumulative reward and the range's emitted reward pool. */
243318
- async totalForPosition(position, range) {
243319
- const head = await this.getHead();
243320
- this.assertPublishedRange(range, head);
243321
- if (head.positionCount === 0) return [asAttoXL1$1(0n), asAttoXL1$1(0n)];
243322
- this.assertPosition(position, head);
243323
- if (range[0] === 0 && range[1] >= head.processedThroughBlock) {
243324
- const snapshot = await this.getSnapshot(head);
243325
- return [asAttoXL1$1(BigInt(snapshot.positionRewards[String(position)] ?? "0")), asAttoXL1$1(BigInt(snapshot.totalReward))];
243326
- }
243327
- const steps = await this.stepsForRange(range, head);
243328
- return [asAttoXL1$1(steps.reduce((sum, step) => sum + BigInt(step.positionRewards[String(position)] ?? "0"), 0n)), asAttoXL1$1(steps.reduce((sum, step) => sum + BigInt(step.totalReward), 0n))];
243329
- }
243330
- /** Returns the emitted reward pool for one indexed step. */
243331
- async totalForStep(step) {
243332
- const head = await this.getHead();
243333
- this.assertPublishedStep(step, head);
243334
- return asAttoXL1$1(BigInt((await this.getStep(step)).totalReward));
243335
- }
243336
- /** Returns one position's allocation and emitted pool for one indexed step. */
243337
- async totalForStepForPosition(step, position) {
243338
- const head = await this.getHead();
243339
- this.assertPosition(position, head);
243340
- this.assertPublishedStep(step, head);
243341
- const record = await this.getStep(step);
243342
- return [asAttoXL1$1(BigInt(record.positionRewards[String(position)] ?? "0")), asAttoXL1$1(BigInt(record.totalReward))];
243343
- }
243344
- /** Unclaimed rewards require redemption state and are not part of this index. */
243345
- unclaimed(_options) {
243346
- throw new Error("Method [unclaimed] not implemented.");
243347
- }
243348
- assertPosition(position, head) {
243349
- assertEx$1(Number.isSafeInteger(position) && position >= 0 && position < head.positionCount, () => `Position ${position} is outside rewards index positionCount ${head.positionCount}`);
243350
- }
243351
- assertPublishedRange(range, head) {
243352
- assertEx$1(range[1] <= head.processedThroughBlock, () => `Reward range ends at ${range[1]}, beyond index watermark ${head.processedThroughBlock}`);
243353
- }
243354
- assertPublishedStep(step, head) {
243355
- assertEx$1(step.block <= head.processedThroughBlock, () => `Reward step ${step.block}|${step.step} is beyond index watermark ${head.processedThroughBlock}`);
243356
- }
243357
- async fetchJson(path) {
243358
- const response = await this.fetchFn(`${this.baseUrl.replace(/\/$/, "")}/${path}`);
243359
- if (!response.ok) throw new Error(`Network stake rewards index request failed [${response.status}] for ${path}`);
243360
- return await response.json();
243361
- }
243362
- async getHead() {
243363
- const now = Date.now();
243364
- const elapsed = this.lastSuccessfulHeadAt === void 0 ? void 0 : now - this.lastSuccessfulHeadAt;
243365
- if (this.currentHead !== void 0 && elapsed !== void 0 && elapsed >= 0 && elapsed < this.headPollIntervalMs) return this.currentHead;
243366
- this.headPromise ??= this.syncHead().finally(() => {
243367
- this.headPromise = void 0;
243368
- });
243369
- return await this.headPromise;
243370
- }
243371
- async getManifest() {
243372
- this.manifestPromise ??= this.fetchJson(networkStakeRewardsIndexManifestPath(this.policyId)).then((value) => asNetworkStakeRewardsIndexManifest(value, true)).catch((error) => {
243373
- this.manifestPromise = void 0;
243374
- throw error;
243375
- });
243376
- return await this.manifestPromise;
243377
- }
243378
- async getSnapshot(head) {
243379
- const { snapshotHash } = head;
243380
- let promise = this.snapshotPromises.get(snapshotHash);
243381
- if (promise === void 0) {
243382
- const path = networkStakeRewardsIndexSnapshotPath(this.policyId, snapshotHash);
243383
- promise = this.fetchJson(path).then(async (value) => {
243384
- const snapshot = asNetworkStakeRewardsIndexSnapshot(value, true);
243385
- assertEx$1(await PayloadBuilder$1.hash(snapshot) === snapshotHash, () => `Rewards snapshot hash mismatch: ${path}`);
243386
- return snapshot;
243387
- });
243388
- this.snapshotPromises.set(snapshotHash, promise);
243389
- }
243390
- try {
243391
- const snapshot = await promise;
243392
- assertEx$1(snapshot.policyId === this.policyId, () => "Rewards snapshot policy mismatch");
243393
- assertEx$1(snapshot.stepCount === head.stepCount, () => "Rewards snapshot step count mismatch");
243394
- return snapshot;
243395
- } catch (error) {
243396
- this.snapshotPromises.delete(snapshotHash);
243397
- throw error;
243398
- }
243399
- }
243400
- async getStep(step) {
243401
- const path = networkStakeRewardsIndexStepPath(this.policyId, step);
243402
- let promise = this.stepPromises.get(path);
243403
- if (promise === void 0) {
243404
- promise = this.fetchJson(path).then((value) => asNetworkStakeRewardsIndexStep(value, true));
243405
- this.stepPromises.set(path, promise);
243406
- }
243407
- try {
243408
- const record = await promise;
243409
- assertEx$1(record.policyId === this.policyId, () => "Rewards step policy mismatch");
243410
- assertEx$1(record.step.block === step.block && record.step.step === step.step, () => "Rewards step identity mismatch");
243411
- return record;
243412
- } catch (error) {
243413
- this.stepPromises.delete(path);
243414
- throw error;
243415
- }
243416
- }
243417
- async stepsForRange(range, head) {
243418
- const steps = blockRangeSteps(range, (await this.getManifest()).stepLevels).filter((step) => step.block <= head.processedThroughBlock);
243419
- return await Promise.all(steps.map(async (step) => await this.getStep(step)));
243420
- }
243421
- async syncHead() {
243422
- assertEx$1((await this.getManifest()).policyId === this.policyId, () => "Rewards manifest policy mismatch");
243423
- const head = asNetworkStakeRewardsIndexHead(await this.fetchJson(networkStakeRewardsIndexHeadPath(this.policyId)), true);
243424
- assertEx$1(head.policyId === this.policyId, () => "Rewards head policy mismatch");
243425
- this.currentHead = head;
243426
- this.lastSuccessfulHeadAt = Date.now();
243427
- return head;
243428
- }
243429
- };
243430
- __publicField$3(RestNetworkStakeStepRewardsByPositionViewer, "connectionTypes", ["rest"]);
243431
- __publicField$3(RestNetworkStakeStepRewardsByPositionViewer, "defaultMoniker", NetworkStakeStepRewardsByPositionViewerMoniker$1);
243432
- __publicField$3(RestNetworkStakeStepRewardsByPositionViewer, "dependencies", []);
243433
- __publicField$3(RestNetworkStakeStepRewardsByPositionViewer, "monikers", [NetworkStakeStepRewardsByPositionViewerMoniker$1]);
243434
- __publicField$3(RestNetworkStakeStepRewardsByPositionViewer, "surface", "node");
243435
- RestNetworkStakeStepRewardsByPositionViewer = __decorateClass$3([creatableProvider$1()], RestNetworkStakeStepRewardsByPositionViewer);
243436
244434
  //#endregion
243437
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-s3-providers@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@_4205ae6dac1e18bd0f69855afce06c53/node_modules/@xyo-network/xl1-s3-providers/dist/node/index.mjs
244435
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-s3-providers@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod@_ce56e55bbf1d84b2b77d13465e8b0d29/node_modules/@xyo-network/xl1-s3-providers/dist/node/index.mjs
243438
244436
  var __defProp$2 = Object.defineProperty;
243439
244437
  var __getOwnPropDesc$2 = Object.getOwnPropertyDescriptor;
243440
244438
  var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, {
@@ -246045,6 +247043,7 @@ async function initFinalizationArchivistIfNeeded(archivist, config, account, opt
246045
247043
  const genesisAccount = await Account$1.random();
246046
247044
  const chainId2 = possibleChainId ?? toAddress(genesisAccount.address);
246047
247045
  possibleChainId = chainId2;
247046
+ options.logger?.info(`No head found in chain store \u2014 creating genesis block for chain [${chainId2}]`);
246048
247047
  if (!config.chain.genesisRewardAddress) {
246049
247048
  const accounts = await buildInsecureGenesisRewardAccounts();
246050
247049
  options.logger?.warn(formatInsecureGenesisRewardWarning(accounts));
@@ -246061,23 +247060,16 @@ function ownStoreArchivist(runtimeResourceOwner, lease) {
246061
247060
  runtimeResourceOwner.add(async () => await lease.release());
246062
247061
  return lease.archivist;
246063
247062
  }
246064
- var DEFAULT_LMDB_CONNECTION2 = "local-store";
246065
- var DEFAULT_MONGO_CONNECTION = "chain-mongo";
246066
- function isStoreConnectionType(type) {
246067
- return type === "lmdb" || type === "mongo";
246068
- }
246069
- function isBindableStoreType(type) {
246070
- return isStoreConnectionType(type) || type === "memory";
246071
- }
246072
247063
  function storeConnectionName(connections) {
246073
247064
  const profiles = connections;
246074
- const localStore = profiles[DEFAULT_LMDB_CONNECTION2];
246075
- if (localStore !== void 0 && isBindableStoreType(localStore.type)) return DEFAULT_LMDB_CONNECTION2;
246076
- if (profiles[DEFAULT_MONGO_CONNECTION]?.type === "mongo") return DEFAULT_MONGO_CONNECTION;
247065
+ const localStore = profiles[DEFAULT_LMDB_CONNECTION$1];
247066
+ if (localStore !== void 0 && isBindableStoreType(localStore.type)) return DEFAULT_LMDB_CONNECTION$1;
247067
+ if (profiles["chain-mongo"]?.type === "mongo") return DEFAULT_MONGO_CONNECTION;
247068
+ for (const [name, connection] of Object.entries(profiles)) if (isStoreConnectionType(connection.type)) return name;
246077
247069
  for (const [name, connection] of Object.entries(profiles)) if (isBindableStoreType(connection.type)) return name;
246078
247070
  }
246079
247071
  function shouldSkipLocalNodeBoot(config) {
246080
- return resolveStoreConnection(config) === void 0;
247072
+ return localChainStoreConnectionName(config.connections ?? {}) === void 0;
246081
247073
  }
246082
247074
  function resolveStoreConnection(config) {
246083
247075
  const profiles = connectionProfiles(config);
@@ -246676,7 +247668,7 @@ async function tryParseConfig(options) {
246676
247668
  return finalize ? finalizeConfig(section) : section;
246677
247669
  }
246678
247670
  //#endregion
246679
- //#region ../../node_modules/.pnpm/@xyo-network+xl1-system-status@5.2.3_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod_c6ee099c6748fee22caff53c55e7c439/node_modules/@xyo-network/xl1-system-status/dist/node/index.mjs
247671
+ //#region ../../node_modules/.pnpm/@xyo-network+xl1-system-status@5.3.1_@ariestools+sdk@8.1.9_@opentelemetry+api@1.9.1_zod_53421f1300494c9cc1ceb6d1caea9317/node_modules/@xyo-network/xl1-system-status/dist/node/index.mjs
246680
247672
  function resolveStatusProbe(status, url) {
246681
247673
  switch (url) {
246682
247674
  case "/healthz": {
@@ -247860,8 +248852,8 @@ $0 <command> [options]`).parserConfiguration({
247860
248852
  }
247861
248853
  }).help().alias("help", "h").version(fullVersion2);
247862
248854
  }
247863
- var version = isDefined$1("5.1.1") ? "5.1.1" : "unknown";
247864
- var gitHash = isDefined$1("ff4b080df") ? "ff4b080df" : "";
248855
+ var version = isDefined$1("5.2.0") ? "5.2.0" : "unknown";
248856
+ var gitHash = isDefined$1("eb511295a") ? "eb511295a" : "";
247865
248857
  var fullVersion = gitHash.length > 0 ? `${version} (${gitHash})` : version;
247866
248858
  var mapXl1CliFailure = createSysExitFailureMapper();
247867
248859
  var defaultDependencies2 = {