var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __decorateClass = (decorators, target, key, kind) => {
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
  for (var i = decorators.length - 1, decorator; i >= 0; i--)
    if (decorator = decorators[i])
      result = (kind ? decorator(target, key, result) : decorator(result)) || result;
  if (kind && result) __defProp(target, key, result);
  return result;
};
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);

// src/modules/rest-block-viewer/chainLayout.ts
import {
  asChainManifest,
  CHAIN_LAYOUT_VERSION,
  ChainManifestSchema,
  ChainManifestZod,
  createChainManifest,
  isChainManifest,
  toChainManifest
} from "@xyo-network/xl1-protocol/network-model";

// src/modules/rest-block-viewer/indexLayout.ts
import {
  asIndexHead,
  asIndexManifest,
  createIndexHead,
  createIndexManifest,
  createIndexManifestFamilies,
  INDEX_LAYOUT_VERSION,
  IndexHeadSchema,
  IndexHeadZod,
  IndexManifestSchema,
  IndexManifestZod,
  isIndexHead,
  isIndexManifest,
  toIndexHead,
  toIndexManifest
} from "@xyo-network/xl1-protocol/network-model";

// src/modules/rest-block-viewer/paths.ts
import {
  blockHashPath,
  blockNumberPath,
  headPath,
  indexHeadPath,
  indexManifestPath,
  indexSummaryPath,
  manifestPath,
  payloadPath
} from "@xyo-network/xl1-protocol/network-model";

// src/modules/rest-block-viewer/RestBlockViewer.ts
import {
  assertEx,
  exists,
  isDefined
} from "@ariestools/sdk";
import { WithHashMetaPayloadZodLoose } from "@xyo-network/sdk";
import {
  asBlocksStepSummary,
  asSignedHydratedBlockWithHashMeta,
  asXL1BlockNumber,
  BlockViewerMoniker,
  ChainStateViewerMoniker,
  IndexViewerMoniker
} from "@xyo-network/xl1-protocol/protocol-lib";
import { LruCacheMap } from "#driver-memory";
import {
  AbstractCreatableProvider,
  calculateBlockRate,
  calculateStepSizeRate,
  calculateTimeRate,
  creatableProvider,
  resolveRestConnectionEndpoint
} from "#protocol-sdk";
var MIN_HEAD_POLL_INTERVAL_MS = 5e3;
var CURRENT_BLOCK_CACHE_TTL_MS = 1e3;
var CURRENT_BLOCK_CACHE_KEY = "head";
var PayloadFileZod = WithHashMetaPayloadZodLoose;
var RestBlockViewer = class extends AbstractCreatableProvider {
  moniker = RestBlockViewer.defaultMoniker;
  blockByHashCache = new LruCacheMap({ max: 2e3 });
  // single-flight maps: concurrent identical requests share one in-flight fetch instead of each
  // missing the value cache and fetching separately; entries clear as soon as the fetch settles
  blockByHashInFlight = /* @__PURE__ */ new Map();
  blockByNumberCache = new LruCacheMap({ max: 2e3 });
  blockByNumberInFlight = /* @__PURE__ */ new Map();
  currentBlockCache = new LruCacheMap({ max: 1, ttl: CURRENT_BLOCK_CACHE_TTL_MS });
  payloadCache = new LruCacheMap({ max: 1e4 });
  stepCache = new LruCacheMap({ max: 4 });
  _chainStateViewer;
  _headPollHash;
  _headPollInProgress = false;
  _headPollTimer = null;
  _indexViewer;
  get finalizedBaseUrl() {
    return this.params.finalizedBaseUrl;
  }
  get fetchFn() {
    return this.params.fetchFn ?? this.context.fetchFn ?? fetch.bind(globalThis);
  }
  get headPollIntervalMs() {
    return this.params.headPollIntervalMs;
  }
  static async paramsHandler(params) {
    const headPollIntervalMs = params.headPollIntervalMs;
    if (headPollIntervalMs !== void 0) {
      assertEx(headPollIntervalMs >= MIN_HEAD_POLL_INTERVAL_MS, () => `headPollIntervalMs must be at least ${MIN_HEAD_POLL_INTERVAL_MS}ms`);
    }
    const moniker = this.defaultMoniker;
    const finalizedBaseUrl = isDefined(params.finalizedBaseUrl) && params.finalizedBaseUrl !== "" ? params.finalizedBaseUrl : resolveRestConnectionEndpoint(
      assertEx(params.context?.config, () => "Context config is required to resolve REST block endpoint"),
      moniker
    );
    return {
      ...await super.paramsHandler(params),
      fetchFn: params.fetchFn,
      finalizedBaseUrl: finalizedBaseUrl.replace(/\/+$/, ""),
      headPollIntervalMs
    };
  }
  async blockByHash(hash) {
    return await this.spanAsync("blockByHash", async () => {
      const cached = this.blockByHashCache.get(hash);
      if (cached) return cached;
      const inFlight = this.blockByHashInFlight.get(hash);
      if (inFlight) return await inFlight;
      const promise = (async () => {
        const parsed = await this.fetchJson(blockHashPath(hash));
        return parsed === void 0 ? null : this.cacheBlock(parsed);
      })();
      this.blockByHashInFlight.set(hash, promise);
      try {
        return await promise;
      } finally {
        this.blockByHashInFlight.delete(hash);
      }
    }, { ...this.context, timeBudgetLimit: 100 });
  }
  async blockByNumber(blockNumber) {
    return await this.spanAsync("blockByNumber", async () => {
      const cached = this.blockByNumberCache.get(blockNumber);
      if (cached) return cached;
      const inFlight = this.blockByNumberInFlight.get(blockNumber);
      if (inFlight) return await inFlight;
      const promise = (async () => {
        const parsed = await this.fetchJson(blockNumberPath(blockNumber));
        return parsed === void 0 ? null : this.cacheBlock(parsed);
      })();
      this.blockByNumberInFlight.set(blockNumber, promise);
      try {
        return await promise;
      } finally {
        this.blockByNumberInFlight.delete(blockNumber);
      }
    }, { ...this.context, timeBudgetLimit: 100 });
  }
  async blocksByHash(hash, limit = 50) {
    return await this.spanAsync("blocksByHash", async () => {
      assertEx(limit > 0, () => "limit must be greater than 0");
      assertEx(limit <= 100, () => "limit must be less than 100");
      const blocks = [];
      let current = await this.blockByHash(hash);
      while (current && blocks.length < limit) {
        blocks.push(current);
        const previousHash = current[0].previous;
        if (previousHash === null) break;
        current = await this.blockByHash(previousHash);
      }
      return blocks;
    }, { ...this.context, timeBudgetLimit: 300 });
  }
  async blocksByNumber(blockNumber, limit = 50) {
    return await this.spanAsync("blocksByNumber", async () => {
      assertEx(limit > 0, () => "limit must be greater than 0");
      assertEx(limit <= 100, () => "limit must be less than 100");
      const blocks = [];
      let current = await this.blockByNumber(blockNumber);
      while (current && blocks.length < limit) {
        blocks.push(current);
        if (current[0].block === 0) break;
        current = await this.blockByNumber(asXL1BlockNumber(current[0].block - 1, true));
      }
      return blocks;
    }, this.context);
  }
  async blocksByStep(stepLevel, stepIndex) {
    return await this.spanAsync("blocksByStep", async () => {
      const cacheKey = `${stepLevel}|${stepIndex}`;
      const cached = this.stepCache.get(cacheKey);
      if (cached) return cached;
      const parsed = await this._indexViewer.stepSummary("blocks", stepLevel, stepIndex);
      if (parsed === null) return [];
      const summary = asBlocksStepSummary(parsed, { required: true });
      const blocks = summary.blocks.map((b) => asSignedHydratedBlockWithHashMeta(b, true)).toReversed();
      this.stepCache.set(cacheKey, blocks);
      return blocks;
    }, this.context);
  }
  async chainId(blockNumber = "latest") {
    return await this.spanAsync("chainId", async () => {
      if (blockNumber === "latest") {
        const block2 = await this.currentBlock();
        return block2[0].chain;
      }
      const block = assertEx(await this.blockByNumber(blockNumber), () => `Block not found [${blockNumber}]`);
      return block[0].chain;
    }, this.context);
  }
  async createHandler() {
    await super.createHandler();
    this._chainStateViewer = await this.locator.getInstance(ChainStateViewerMoniker);
    this._indexViewer = await this.locator.getInstance(IndexViewerMoniker);
  }
  async currentBlock() {
    return await this.spanAsync("currentBlock", async () => {
      const cached = this.currentBlockCache.get(CURRENT_BLOCK_CACHE_KEY);
      if (cached) return await cached;
      const promise = this.fetchCurrentBlock();
      this.currentBlockCache.set(CURRENT_BLOCK_CACHE_KEY, promise);
      try {
        return await promise;
      } catch (error) {
        this.currentBlockCache.delete(CURRENT_BLOCK_CACHE_KEY);
        throw error;
      }
    }, this.context);
  }
  async currentBlockHash() {
    const block = await this.currentBlock();
    return block[0]._hash;
  }
  async currentBlockNumber() {
    const block = await this.currentBlock();
    return block[0].block;
  }
  async payloadByHash(hash) {
    const [payload] = await this.payloadsByHash([hash]);
    return payload ?? null;
  }
  async payloadsByHash(hashes) {
    return await this.spanAsync("payloadsByHash", async () => {
      const results = await Promise.all(hashes.map(async (hash) => {
        const cached = this.payloadCache.get(hash);
        if (cached) return cached;
        const parsed = await this.fetchJson(payloadPath(hash));
        if (parsed === void 0) return;
        const payload = PayloadFileZod.parse(parsed);
        this.payloadCache.set(hash, payload);
        return payload;
      }));
      return results.filter(exists);
    }, this.context);
  }
  async rate(range, timeUnit) {
    return await calculateBlockRate(this, range, timeUnit);
  }
  async stepSizeRate(start, stepIndex, count = 1, timeUnit) {
    return await calculateStepSizeRate(this, start, stepIndex, count, timeUnit);
  }
  async timeDurationRate(timeConfig, startBlockNumber, timeUnit, toleranceMs, maxAttempts) {
    return await calculateTimeRate(this, timeConfig, startBlockNumber, timeUnit, toleranceMs, maxAttempts);
  }
  async startHandler() {
    await super.startHandler();
    if (this.headPollIntervalMs === void 0) return;
    await this.pollHead(false);
    this.startHeadPolling();
  }
  async stopHandler() {
    this.stopHeadPolling();
    this._headPollHash = void 0;
    await super.stopHandler();
  }
  /** Validates a parsed block file and populates both block caches. */
  cacheBlock(parsed) {
    const block = asSignedHydratedBlockWithHashMeta(parsed, true);
    this.blockByHashCache.set(block[0]._hash, block);
    this.blockByNumberCache.set(block[0].block, block);
    return block;
  }
  /** The head is ChainStateViewer's question; delegate, then seed the immutable block caches. */
  async fetchCurrentBlock() {
    return this.cacheBlock(await this._chainStateViewer.currentBlock());
  }
  async fetchJson(path) {
    const response = await this.fetchFn(`${this.finalizedBaseUrl}/${path}`);
    if (response.status === 404) return void 0;
    assertEx(response.ok, () => `Request failed [${response.status}] for ${path}`);
    return await response.json();
  }
  async pollHead(emitOnChange) {
    if (this._headPollInProgress) return;
    this._headPollInProgress = true;
    try {
      const block = await this.currentBlock();
      const hash = block[0]._hash;
      if (this._headPollHash === void 0) {
        this._headPollHash = hash;
        return;
      }
      if (hash !== this._headPollHash) {
        this._headPollHash = hash;
        if (emitOnChange) {
          await this.emit("headUpdated", { block });
        }
      }
    } catch (ex) {
      this.logger?.error("Error polling block head", ex);
    } finally {
      this._headPollInProgress = false;
    }
  }
  startHeadPolling() {
    if (this.headPollIntervalMs === void 0) return;
    this.stopHeadPolling();
    this._headPollTimer = setInterval(() => {
      void this.pollHead(true);
    }, this.headPollIntervalMs);
  }
  stopHeadPolling() {
    if (!this._headPollTimer) {
      return;
    }
    clearInterval(this._headPollTimer);
    this._headPollTimer = null;
  }
};
__publicField(RestBlockViewer, "connectionTypes", ["rest"]);
__publicField(RestBlockViewer, "defaultMoniker", BlockViewerMoniker);
__publicField(RestBlockViewer, "dependencies", [ChainStateViewerMoniker, IndexViewerMoniker]);
__publicField(RestBlockViewer, "monikers", [BlockViewerMoniker]);
__publicField(RestBlockViewer, "surface", "node");
RestBlockViewer = __decorateClass([
  creatableProvider()
], RestBlockViewer);

// src/modules/rest-block-viewer/RestChainContractViewer.ts
import {
  assertEx as assertEx2,
  isDefined as isDefined2
} from "@ariestools/sdk";
import { asChainContractManifest, chainContractPath } from "@xyo-network/xl1-protocol/network-model";
import { ChainContractViewerMoniker, FinalizationViewerMoniker } from "@xyo-network/xl1-protocol/protocol-lib";
import {
  AbstractCreatableProvider as AbstractCreatableProvider2,
  creatableProvider as creatableProvider2,
  resolveRestConnectionEndpoint as resolveRestConnectionEndpoint2
} from "#protocol-sdk";
var RestChainContractViewer = class extends AbstractCreatableProvider2 {
  moniker = RestChainContractViewer.defaultMoniker;
  _finalizationViewer;
  _manifestPromise;
  get contractBaseUrl() {
    return this.params.contractBaseUrl;
  }
  get fetchFn() {
    return this.params.fetchFn ?? this.context.fetchFn ?? fetch.bind(globalThis);
  }
  static async paramsHandler(params) {
    const moniker = this.defaultMoniker;
    const contractBaseUrl = isDefined2(params.contractBaseUrl) && params.contractBaseUrl !== "" ? params.contractBaseUrl : resolveRestConnectionEndpoint2(
      assertEx2(params.context?.config, () => "Context config is required to resolve REST chain-contract endpoint"),
      moniker
    );
    return {
      ...await super.paramsHandler(params),
      contractBaseUrl: contractBaseUrl.replace(/\/+$/, ""),
      fetchFn: params.fetchFn
    };
  }
  async chainId() {
    return await this._finalizationViewer.chainId();
  }
  async chainIdAtBlockNumber(blockNumber) {
    if (blockNumber === "latest") return await this.chainId();
    let chainId = await this.chainId();
    let contractViewer = this;
    let forkedAtBlockNumber = await contractViewer.forkedAtBlockNumber();
    while (forkedAtBlockNumber !== null && blockNumber <= forkedAtBlockNumber) {
      contractViewer = assertEx2(
        await contractViewer.forkedChainContractViewer(),
        () => "Block predates a fork boundary but no forked chain-contract viewer is available"
      );
      forkedAtBlockNumber = await contractViewer.forkedAtBlockNumber();
      chainId = await contractViewer.chainId();
    }
    return chainId;
  }
  async createHandler() {
    await super.createHandler();
    this._finalizationViewer = await this.locator.getInstance(FinalizationViewerMoniker);
  }
  async forkedAtBlockNumber() {
    return (await this.manifest()).forkedAtBlockNumber ?? null;
  }
  async forkedAtHash() {
    return (await this.manifest()).forkedAtHash ?? null;
  }
  /** Fork-chain traversal isn't supported over REST yet — the ancestor chain's own bucket isn't known here. */
  forkedChainContractViewer() {
    return Promise.resolve(null);
  }
  async forkedChainId() {
    return (await this.manifest()).forkedChainId ?? null;
  }
  async minWithdrawalBlocks() {
    return (await this.manifest()).minWithdrawalBlocks;
  }
  async rewardsContract() {
    return (await this.manifest()).rewardsContract;
  }
  async stakingTokenAddress() {
    return (await this.manifest()).stakingTokenAddress;
  }
  async fetchManifest() {
    const response = await this.fetchFn(`${this.contractBaseUrl}/${chainContractPath()}`);
    assertEx2(response.ok, () => `Chain-contract manifest not found [${response.status}]`);
    const parsed = await response.json();
    return asChainContractManifest(parsed, true);
  }
  async manifest() {
    this._manifestPromise ??= this.fetchManifest();
    return await this._manifestPromise;
  }
};
__publicField(RestChainContractViewer, "connectionTypes", ["rest"]);
__publicField(RestChainContractViewer, "defaultMoniker", ChainContractViewerMoniker);
__publicField(RestChainContractViewer, "dependencies", [FinalizationViewerMoniker]);
__publicField(RestChainContractViewer, "monikers", [ChainContractViewerMoniker]);
__publicField(RestChainContractViewer, "surface", "node");
RestChainContractViewer = __decorateClass([
  creatableProvider2()
], RestChainContractViewer);

// src/modules/rest-block-viewer/RestChainStateViewer.ts
import { assertEx as assertEx3, isDefined as isDefined3 } from "@ariestools/sdk";
import { asSignedHydratedBlockWithHashMeta as asSignedHydratedBlockWithHashMeta2, ChainStateViewerMoniker as ChainStateViewerMoniker2 } from "@xyo-network/xl1-protocol/protocol-lib";
import {
  AbstractCreatableProvider as AbstractCreatableProvider3,
  creatableProvider as creatableProvider3,
  resolveRestConnectionEndpoint as resolveRestConnectionEndpoint3
} from "#protocol-sdk";
var MIN_HEAD_POLL_INTERVAL_MS2 = 5e3;
var RestChainStateViewer = class extends AbstractCreatableProvider3 {
  moniker = RestChainStateViewer.defaultMoniker;
  _headPollHash;
  _headPollInProgress = false;
  _headPollTimer = null;
  get chainStateBaseUrl() {
    return this.params.chainStateBaseUrl;
  }
  get fetchFn() {
    return this.params.fetchFn ?? this.context.fetchFn ?? fetch.bind(globalThis);
  }
  get headPollIntervalMs() {
    return this.params.headPollIntervalMs;
  }
  static async paramsHandler(params) {
    const headPollIntervalMs = params.headPollIntervalMs;
    if (headPollIntervalMs !== void 0) {
      assertEx3(headPollIntervalMs >= MIN_HEAD_POLL_INTERVAL_MS2, () => `headPollIntervalMs must be at least ${MIN_HEAD_POLL_INTERVAL_MS2}ms`);
    }
    const moniker = this.defaultMoniker;
    const chainStateBaseUrl = isDefined3(params.chainStateBaseUrl) && params.chainStateBaseUrl !== "" ? params.chainStateBaseUrl : resolveRestConnectionEndpoint3(
      assertEx3(params.context?.config, () => "Context config is required to resolve REST chain-state endpoint"),
      moniker
    );
    return {
      ...await super.paramsHandler(params),
      chainStateBaseUrl: chainStateBaseUrl.replace(/\/+$/, ""),
      fetchFn: params.fetchFn,
      headPollIntervalMs
    };
  }
  async currentBlock() {
    return await this.spanAsync("currentBlock", async () => {
      const response = await this.fetchFn(`${this.chainStateBaseUrl}/${headPath()}`);
      assertEx3(response.ok, () => `Head not found [${response.status}]`);
      return asSignedHydratedBlockWithHashMeta2(await response.json(), true);
    }, this.context);
  }
  async currentBlockHash() {
    const block = await this.currentBlock();
    return block[0]._hash;
  }
  async currentBlockNumber() {
    const block = await this.currentBlock();
    return block[0].block;
  }
  /** The published head, or undefined when no head pointer has been published yet. */
  async tryCurrentBlock() {
    const response = await this.fetchFn(`${this.chainStateBaseUrl}/${headPath()}`);
    if (response.status === 404) return void 0;
    assertEx3(response.ok, () => `Head request failed [${response.status}]`);
    return asSignedHydratedBlockWithHashMeta2(await response.json(), true);
  }
  async startHandler() {
    await super.startHandler();
    if (this.headPollIntervalMs === void 0) return;
    await this.pollHead(false);
    this.startHeadPolling();
  }
  async stopHandler() {
    this.stopHeadPolling();
    this._headPollHash = void 0;
    await super.stopHandler();
  }
  async pollHead(emitOnChange) {
    if (this._headPollInProgress) return;
    this._headPollInProgress = true;
    try {
      const block = await this.currentBlock();
      const hash = block[0]._hash;
      if (this._headPollHash === void 0) {
        this._headPollHash = hash;
        return;
      }
      if (hash !== this._headPollHash) {
        this._headPollHash = hash;
        if (emitOnChange) {
          await this.emit("headUpdated", { block });
        }
      }
    } catch (ex) {
      this.logger?.error("Error polling block head", ex);
    } finally {
      this._headPollInProgress = false;
    }
  }
  startHeadPolling() {
    if (this.headPollIntervalMs === void 0) return;
    this.stopHeadPolling();
    this._headPollTimer = setInterval(() => {
      void this.pollHead(true);
    }, this.headPollIntervalMs);
  }
  stopHeadPolling() {
    if (!this._headPollTimer) {
      return;
    }
    clearInterval(this._headPollTimer);
    this._headPollTimer = null;
  }
};
__publicField(RestChainStateViewer, "connectionTypes", ["rest"]);
__publicField(RestChainStateViewer, "defaultMoniker", ChainStateViewerMoniker2);
__publicField(RestChainStateViewer, "dependencies", []);
__publicField(RestChainStateViewer, "monikers", [ChainStateViewerMoniker2]);
__publicField(RestChainStateViewer, "surface", "node");
RestChainStateViewer = __decorateClass([
  creatableProvider3()
], RestChainStateViewer);

// src/modules/rest-block-viewer/RestFinalizationViewer.ts
import { ChainStateViewerMoniker as ChainStateViewerMoniker3, FinalizationViewerMoniker as FinalizationViewerMoniker2 } from "@xyo-network/xl1-protocol/protocol-lib";
import { AbstractCreatableProvider as AbstractCreatableProvider4, creatableProvider as creatableProvider4 } from "#protocol-sdk";
var RestFinalizationViewer = class extends AbstractCreatableProvider4 {
  moniker = RestFinalizationViewer.defaultMoniker;
  _chainStateViewer;
  async chainId() {
    const headBlock = await this.headBlock();
    return headBlock.chain;
  }
  async createHandler() {
    await super.createHandler();
    this._chainStateViewer = await this.locator.getInstance(ChainStateViewerMoniker3);
  }
  async head() {
    return await this._chainStateViewer.currentBlock();
  }
  async headBlock() {
    const head = await this.head();
    return head[0];
  }
  async headHash() {
    const headBlock = await this.headBlock();
    return headBlock._hash;
  }
  async headNumber() {
    const headBlock = await this.headBlock();
    return headBlock.block;
  }
};
__publicField(RestFinalizationViewer, "connectionTypes", ["rest"]);
__publicField(RestFinalizationViewer, "defaultMoniker", FinalizationViewerMoniker2);
__publicField(RestFinalizationViewer, "dependencies", [ChainStateViewerMoniker3]);
__publicField(RestFinalizationViewer, "monikers", [FinalizationViewerMoniker2]);
__publicField(RestFinalizationViewer, "surface", "node");
RestFinalizationViewer = __decorateClass([
  creatableProvider4()
], RestFinalizationViewer);

// src/modules/rest-block-viewer/RestIndexViewer.ts
import { assertEx as assertEx4, isDefined as isDefined4 } from "@ariestools/sdk";
import { IndexViewerMoniker as IndexViewerMoniker2, stepSize } from "@xyo-network/xl1-protocol/protocol-lib";
import { LruCacheMap as LruCacheMap2 } from "#driver-memory";
import {
  AbstractCreatableProvider as AbstractCreatableProvider5,
  balancesMaxStep,
  blocksMaxStep,
  creatableProvider as creatableProvider5,
  resolveRestConnectionEndpoint as resolveRestConnectionEndpoint4,
  schemasMaxStep,
  transfersMaxStep
} from "#protocol-sdk";
var MAX_STEP_BY_FAMILY = {
  balances: balancesMaxStep,
  blocks: blocksMaxStep,
  schemas: schemasMaxStep,
  transfers: transfersMaxStep
};
var RestIndexViewer = class extends AbstractCreatableProvider5 {
  moniker = RestIndexViewer.defaultMoniker;
  summaryCaches = {
    balances: new LruCacheMap2({ max: 1e4 }),
    blocks: new LruCacheMap2({ max: 1e4 }),
    schemas: new LruCacheMap2({ max: 1e4 }),
    transfers: new LruCacheMap2({ max: 1e4 })
  };
  get indexBaseUrl() {
    return this.params.indexBaseUrl;
  }
  get fetchFn() {
    return this.params.fetchFn ?? this.context.fetchFn ?? fetch.bind(globalThis);
  }
  static async paramsHandler(params) {
    const moniker = this.defaultMoniker;
    const indexBaseUrl = isDefined4(params.indexBaseUrl) && params.indexBaseUrl !== "" ? params.indexBaseUrl : resolveRestConnectionEndpoint4(
      assertEx4(params.context?.config, () => "Context config is required to resolve REST index endpoint"),
      moniker
    );
    return {
      ...await super.paramsHandler(params),
      fetchFn: params.fetchFn,
      indexBaseUrl: indexBaseUrl.replace(/\/+$/, "")
    };
  }
  /** The published summary for a completed step in the given family, or null when not (yet) published. */
  async stepSummary(family, stepLevel, stepIndex) {
    return await this.spanAsync("stepSummary", async () => {
      assertEx4(Number.isSafeInteger(stepIndex) && stepIndex >= 0, () => "stepIndex must be a non-negative integer");
      stepSize(stepLevel);
      const maxStep = MAX_STEP_BY_FAMILY[family];
      assertEx4(
        stepLevel <= maxStep,
        () => `stepSummary does not support step levels above ${maxStep} for family "${family}" (requested ${stepLevel})`
      );
      const cache = this.summaryCaches[family];
      const cacheKey = `${stepLevel}|${stepIndex}`;
      const cached = cache.get(cacheKey);
      if (cached !== void 0) return cached;
      const response = await this.fetchFn(`${this.indexBaseUrl}/${indexSummaryPath(family, stepLevel, stepIndex)}`);
      if (response.status === 404) return null;
      assertEx4(response.ok, () => `Request failed [${response.status}] for ${family} step ${stepLevel}/${stepIndex}`);
      const summary = await response.json();
      cache.set(cacheKey, summary);
      return summary;
    }, this.context);
  }
};
__publicField(RestIndexViewer, "connectionTypes", ["rest"]);
__publicField(RestIndexViewer, "defaultMoniker", IndexViewerMoniker2);
__publicField(RestIndexViewer, "dependencies", []);
__publicField(RestIndexViewer, "monikers", [IndexViewerMoniker2]);
RestIndexViewer = __decorateClass([
  creatableProvider5()
], RestIndexViewer);
export {
  CHAIN_LAYOUT_VERSION,
  ChainManifestSchema,
  ChainManifestZod,
  INDEX_LAYOUT_VERSION,
  IndexHeadSchema,
  IndexHeadZod,
  IndexManifestSchema,
  IndexManifestZod,
  RestBlockViewer,
  RestChainContractViewer,
  RestChainStateViewer,
  RestFinalizationViewer,
  RestIndexViewer,
  asChainManifest,
  asIndexHead,
  asIndexManifest,
  blockHashPath,
  blockNumberPath,
  createChainManifest,
  createIndexHead,
  createIndexManifest,
  createIndexManifestFamilies,
  headPath,
  indexHeadPath,
  indexManifestPath,
  indexSummaryPath,
  isChainManifest,
  isIndexHead,
  isIndexManifest,
  manifestPath,
  payloadPath,
  toChainManifest,
  toIndexHead,
  toIndexManifest
};
//# sourceMappingURL=rest-block-viewer.mjs.map
