{"version":3,"file":"batchPoll-C9cZ5usJ.cjs","sources":["../src/tbv/core/clients/eth/contract-address-resolver.ts","../src/tbv/core/clients/eth/operation-key-reader.ts","../src/tbv/core/clients/eth/protocol-params-reader.ts","../src/tbv/core/clients/eth/signer-set-reader.ts","../src/tbv/core/clients/eth/types.ts","../src/tbv/core/clients/vault-provider/validators.ts","../src/tbv/core/clients/vault-provider/api.ts","../src/tbv/core/clients/vault-provider/auth/cbor.ts","../src/tbv/core/clients/vault-provider/auth/serverIdentity.ts","../src/tbv/core/clients/vault-provider/auth/gatedMethods.ts","../src/tbv/core/clients/vault-provider/auth/innerTokenClient.ts","../src/tbv/core/clients/vault-provider/auth/cborDecode.ts","../src/tbv/core/clients/vault-provider/auth/verifyDepositorCwt.ts","../src/tbv/core/clients/vault-provider/auth/tokenProvider.ts","../src/tbv/core/clients/vault-provider/auth/tokenRegistry.ts","../src/tbv/core/clients/vault-provider/auth/createAuthenticatedVpClient.ts","../src/tbv/core/clients/vault-provider/auth/primeVpAuth.ts","../src/tbv/core/clients/vault-provider/batchAttribution.ts","../src/tbv/core/clients/vault-provider/batchPoll.ts"],"sourcesContent":["/**\n * Contract Address Resolver\n *\n * Resolves ProtocolParams and ApplicationRegistry contract addresses\n * from the BTCVaultRegistry contract. These addresses are needed to\n * construct the SDK's contract readers.\n *\n * @module clients/eth/contract-address-resolver\n */\n\nimport type { Address, PublicClient } from \"viem\";\n\nimport { BTCVaultRegistryABI } from \"../../contracts/abis/BTCVaultRegistry.abi\";\n\nexport interface ProtocolAddresses {\n  /** Address of the ProtocolParams contract */\n  protocolParams: Address;\n  /** Address of the ApplicationRegistry contract */\n  applicationRegistry: Address;\n}\n\n/**\n * Resolve ProtocolParams and ApplicationRegistry addresses from BTCVaultRegistry.\n *\n * Uses a single multicall for atomicity and efficiency.\n *\n * @param publicClient - viem PublicClient instance\n * @param btcVaultRegistryAddress - Address of the BTCVaultRegistry contract\n * @returns Resolved contract addresses\n */\nexport async function resolveProtocolAddresses(\n  publicClient: PublicClient,\n  btcVaultRegistryAddress: Address,\n): Promise<ProtocolAddresses> {\n  const [protocolParams, applicationRegistry] = await publicClient.multicall({\n    contracts: [\n      {\n        address: btcVaultRegistryAddress,\n        abi: BTCVaultRegistryABI,\n        functionName: \"protocolParams\",\n      },\n      {\n        address: btcVaultRegistryAddress,\n        abi: BTCVaultRegistryABI,\n        functionName: \"applicationRegistry\",\n      },\n    ],\n    allowFailure: false,\n  });\n\n  return {\n    protocolParams: protocolParams as Address,\n    applicationRegistry: applicationRegistry as Address,\n  };\n}\n","/**\n * Concrete RFC-006 operation-key reader spanning all three registries.\n *\n * This is an optional utility — callers can use their own implementation of\n * the {@link OperationKeyReader} interface.\n */\n\nimport type { Abi, Address, Hex, PublicClient } from \"viem\";\n\nimport { ApplicationRegistryABI } from \"../../contracts/abis/ApplicationRegistry.abi\";\nimport { BTCVaultRegistryABI } from \"../../contracts/abis/BTCVaultRegistry.abi\";\nimport { ProtocolParamsABI } from \"../../contracts/abis/ProtocolParams.abi\";\nimport type {\n  KeyEpochs,\n  OperationKeyQuery,\n  OperationKeyReader,\n  RawOperationKeys,\n  RawPayoutScripts,\n} from \"./types\";\n\n/** Addresses of the three registries an operation-key resolution spans. */\nexport interface OperationKeyContracts {\n  btcVaultRegistry: Address;\n  applicationRegistry: Address;\n  protocolParams: Address;\n}\n\n/** One `multicall` entry. Loosely typed because the three ABIs differ. */\ntype Call = {\n  address: Address;\n  abi: Abi;\n  functionName: string;\n  args: readonly unknown[];\n};\n\n/**\n * Reject a multicall result that is not one-per-call.\n *\n * Every method here relies on positional alignment between calls and results,\n * so a short array does not fail — it silently hands back `undefined` for the\n * tail entries. Downstream that surfaces as a complaint about whichever\n * operator happens to occupy the missing slot, blaming a participant that is\n * perfectly fine for a read that came back incomplete. Assert the length where\n * the array arrives so the error names the real fault.\n */\nfunction assertMulticallLength(\n  actual: number,\n  expected: number,\n  label: string,\n): void {\n  if (actual !== expected) {\n    throw new Error(\n      `${label}: multicall returned ${actual} results for ${expected} calls, ` +\n        `so the results are not roster-aligned; refusing to use them`,\n    );\n  }\n}\n\n/**\n * Split a flat multicall result into VP / keepers / challengers.\n *\n * Every method below builds its calls in the same order — vault provider\n * first, then keepers in roster order, then challengers in roster order — so\n * the results stay index-aligned with `query.vaultKeepers` /\n * `query.universalChallengers`. That alignment is what lets the resolver pair\n * a resolved key back to its admin address; the sorted key arrays it exposes\n * are derived from those pairs, never the other way round.\n */\nfunction partition<T>(\n  results: readonly T[],\n  keeperCount: number,\n): { vaultProvider: T; vaultKeepers: T[]; universalChallengers: T[] } {\n  return {\n    vaultProvider: results[0],\n    vaultKeepers: results.slice(1, 1 + keeperCount),\n    universalChallengers: results.slice(1 + keeperCount),\n  };\n}\n\n/**\n * Reads RFC-006 operation keys and payout scripts.\n *\n * Usage:\n * ```ts\n * const reader = new ViemOperationKeyReader(publicClient, contracts);\n * const keys = await reader.getCurrentOperationKeys(query);\n * ```\n */\nexport class ViemOperationKeyReader implements OperationKeyReader {\n  constructor(\n    private publicClient: PublicClient,\n    private contracts: OperationKeyContracts,\n  ) {}\n\n  /**\n   * One multicall, `allowFailure: false`, so every key in the set is read at\n   * the same block. A rotation landing between two separate `eth_call`s would\n   * otherwise produce a mixed-epoch key set and a lock no counterparty agrees\n   * with.\n   */\n  private async readAll<T>(\n    calls: Call[],\n    keeperCount: number,\n    challengerCount: number,\n    label: string,\n  ) {\n    const results = (await this.publicClient.multicall({\n      contracts: calls,\n      allowFailure: false,\n    })) as readonly T[];\n\n    assertMulticallLength(\n      results.length,\n      1 + keeperCount + challengerCount,\n      label,\n    );\n\n    return partition(results, keeperCount);\n  }\n\n  async getCurrentOperationKeys(\n    query: OperationKeyQuery,\n  ): Promise<RawOperationKeys> {\n    const calls: Call[] = [\n      {\n        address: this.contracts.btcVaultRegistry,\n        abi: BTCVaultRegistryABI as Abi,\n        functionName: \"getCurrentOperationBtcKey\",\n        args: [query.vaultProviderEthAddress],\n      },\n      ...query.vaultKeepers.map((keeper) => ({\n        address: this.contracts.applicationRegistry,\n        abi: ApplicationRegistryABI as Abi,\n        functionName: \"getCurrentOperationBtcKey\",\n        args: [query.applicationEntryPoint, keeper.ethAddress],\n      })),\n      ...query.universalChallengers.map((challenger) => ({\n        address: this.contracts.protocolParams,\n        abi: ProtocolParamsABI as Abi,\n        functionName: \"getCurrentOperationBtcKey\",\n        args: [challenger.ethAddress],\n      })),\n    ];\n\n    return this.readAll<Hex>(\n      calls,\n      query.vaultKeepers.length,\n      query.universalChallengers.length,\n      \"getCurrentOperationKeys\",\n    );\n  }\n\n  async getOperationKeysAtEpochs(\n    query: OperationKeyQuery,\n    epochs: KeyEpochs,\n  ): Promise<RawOperationKeys> {\n    const calls: Call[] = [\n      // The VP takes the plain `AtEpoch` variant: it has no membership\n      // version, so its genesis (the registration key at version 0) is\n      // unambiguous and the contract resolves it internally.\n      {\n        address: this.contracts.btcVaultRegistry,\n        abi: BTCVaultRegistryABI as Abi,\n        functionName: \"getOperationBtcKeyAtEpoch\",\n        args: [query.vaultProviderEthAddress, epochs.vpKeyEpoch],\n      },\n      // Keepers and challengers take `...OrGenesis` with their roster key\n      // passed explicitly, because the correct genesis for them is their key\n      // in *this vault's frozen membership version*. An operator dropped from\n      // the current roster, or listed under a different key in an older\n      // version, would otherwise resolve against the wrong genesis.\n      ...query.vaultKeepers.map((keeper) => ({\n        address: this.contracts.applicationRegistry,\n        abi: ApplicationRegistryABI as Abi,\n        functionName: \"getOperationBtcKeyAtEpochOrGenesis\",\n        args: [\n          query.applicationEntryPoint,\n          keeper.ethAddress,\n          epochs.appKeeperKeyEpoch,\n          keeper.btcPubKey,\n        ],\n      })),\n      ...query.universalChallengers.map((challenger) => ({\n        address: this.contracts.protocolParams,\n        abi: ProtocolParamsABI as Abi,\n        functionName: \"getOperationBtcKeyAtEpochOrGenesis\",\n        args: [challenger.ethAddress, epochs.ucKeyEpoch, challenger.btcPubKey],\n      })),\n    ];\n\n    return this.readAll<Hex>(\n      calls,\n      query.vaultKeepers.length,\n      query.universalChallengers.length,\n      \"getOperationKeysAtEpochs\",\n    );\n  }\n\n  async getPayoutScriptsAtEpochs(\n    query: OperationKeyQuery,\n    epochs: KeyEpochs,\n  ): Promise<RawPayoutScripts> {\n    // Universal challengers are never claimers, so they have no payout script\n    // and no call here.\n    const results = (await this.publicClient.multicall({\n      contracts: [\n        {\n          address: this.contracts.btcVaultRegistry,\n          abi: BTCVaultRegistryABI as Abi,\n          functionName: \"getPayoutScriptAtEpoch\",\n          args: [query.vaultProviderEthAddress, epochs.vpKeyEpoch],\n        },\n        ...query.vaultKeepers.map((keeper) => ({\n          address: this.contracts.applicationRegistry,\n          abi: ApplicationRegistryABI as Abi,\n          functionName: \"getPayoutScriptAtEpoch\",\n          args: [\n            query.applicationEntryPoint,\n            keeper.ethAddress,\n            epochs.appKeeperKeyEpoch,\n          ],\n        })),\n      ],\n      allowFailure: false,\n    })) as readonly Hex[];\n\n    // Expected length is `1 + keepers`, with no challenger term — see the\n    // comment above on why universal challengers have no call here.\n    assertMulticallLength(\n      results.length,\n      1 + query.vaultKeepers.length,\n      \"getPayoutScriptsAtEpochs\",\n    );\n\n    return {\n      vaultProvider: results[0],\n      vaultKeepers: [...results.slice(1)],\n    };\n  }\n}\n","/**\n * Concrete ProtocolParams reader using viem's readContract and multicall.\n *\n * This is an optional utility — callers can use their own implementation\n * of the ProtocolParamsReader interface.\n */\n\nimport type { Abi, Address, Hex, PublicClient } from \"viem\";\n\nimport { ProtocolParamsABI } from \"../../contracts/abis/ProtocolParams.abi\";\nimport {\n  assertValidOffchainParamsVersion,\n  validateOffchainParams,\n  validatePegInConfiguration,\n  validateTBVProtocolParams,\n} from \"./protocol-params-validation\";\nimport type {\n  AllOffchainParamsData,\n  OnSkippedOffchainParamsVersion,\n  PegInConfiguration,\n  ProtocolParamsReader,\n  TBVProtocolParams,\n  VersionedOffchainParams,\n} from \"./types\";\n\n/**\n * Maximum value for a Solidity uint16.\n * PeginLogic.sol casts timelockAssert to uint16, so values above this are invalid.\n */\nconst UINT16_MAX = 65535;\n\n\n/**\n * Raw shape viem returns for VersionedOffchainParams struct.\n * viem resolves ABI struct outputs to named objects (not tuples).\n */\ninterface RawOffchainParams {\n  timelockAssert: bigint;\n  timelockChallengeAssert: bigint;\n  securityCouncilKeys: readonly Hex[];\n  councilQuorum: number;\n  feeRate: bigint;\n  babeTotalInstances: number;\n  babeInstancesToFinalize: number;\n  minVpCommissionBps: number;\n  tRefund: number;\n  tStale: number;\n  minPeginFeeRate: bigint;\n  proverCircuitVersion: number;\n  minPrepeginDepth: number;\n}\n\n/** Raw shape viem returns for TBVProtocolParams struct. */\ninterface RawTBVParams {\n  minimumPegInAmount: bigint;\n  maxPegInAmount: bigint;\n  pegInAckTimeout: bigint;\n  pegInActivationTimeout: bigint;\n  maxHtlcOutputCount: number;\n  expiredPegInGraceBlocks: bigint;\n}\n\n/** Map viem struct result to VersionedOffchainParams. */\nfunction mapOffchainParams(result: RawOffchainParams): VersionedOffchainParams {\n  return {\n    timelockAssert: result.timelockAssert,\n    timelockChallengeAssert: result.timelockChallengeAssert,\n    securityCouncilKeys: [...result.securityCouncilKeys],\n    councilQuorum: result.councilQuorum,\n    feeRate: result.feeRate,\n    babeTotalInstances: result.babeTotalInstances,\n    babeInstancesToFinalize: result.babeInstancesToFinalize,\n    minVpCommissionBps: result.minVpCommissionBps,\n    tRefund: result.tRefund,\n    tStale: result.tStale,\n    minPeginFeeRate: result.minPeginFeeRate,\n    proverCircuitVersion: result.proverCircuitVersion,\n    minPrepeginDepth: result.minPrepeginDepth,\n  };\n}\n\n/** Map viem struct result to TBVProtocolParams. */\nfunction mapTBVParams(result: RawTBVParams): TBVProtocolParams {\n  return {\n    minimumPegInAmount: result.minimumPegInAmount,\n    maxPegInAmount: result.maxPegInAmount,\n    pegInAckTimeout: result.pegInAckTimeout,\n    pegInActivationTimeout: result.pegInActivationTimeout,\n    maxHtlcOutputCount: result.maxHtlcOutputCount,\n    expiredPegInGraceBlocks: result.expiredPegInGraceBlocks,\n  };\n}\n\n/**\n * Derive timelockPegin from timelockAssert.\n *\n * Matches PeginLogic.sol: `uint16(timelockAssert)`.\n * The contract validates `timelockAssert <= type(uint16).max` on write,\n * but we enforce the same bound here to reject invalid values early\n * rather than silently truncating.\n *\n * @throws if timelockAssert exceeds uint16 max (65535)\n */\nfunction deriveTimelockPegin(timelockAssert: bigint): number {\n  if (timelockAssert > BigInt(UINT16_MAX)) {\n    throw new Error(\n      `timelockAssert value ${timelockAssert} exceeds uint16 max (${UINT16_MAX})`,\n    );\n  }\n  return Number(timelockAssert);\n}\n\n/**\n * Concrete protocol params reader using viem.\n *\n * Every read method runs the matching validator from\n * `protocol-params-validation` before returning, so callers don't have to\n * remember to validate.\n *\n * Usage:\n * ```ts\n * const reader = new ViemProtocolParamsReader(publicClient, protocolParamsAddress);\n * const config = await reader.getPegInConfiguration();\n * ```\n */\nexport class ViemProtocolParamsReader implements ProtocolParamsReader {\n  constructor(\n    private publicClient: PublicClient,\n    private contractAddress: Address,\n  ) {}\n\n  async getTBVProtocolParams(): Promise<TBVProtocolParams> {\n    const result = (await this.publicClient.readContract({\n      address: this.contractAddress,\n      abi: ProtocolParamsABI,\n      functionName: \"getTBVProtocolParams\",\n    })) as RawTBVParams;\n\n    const params = mapTBVParams(result);\n    validateTBVProtocolParams(params);\n    return params;\n  }\n\n  async getLatestOffchainParams(): Promise<VersionedOffchainParams> {\n    const result = (await this.publicClient.readContract({\n      address: this.contractAddress,\n      abi: ProtocolParamsABI,\n      functionName: \"getLatestOffchainParams\",\n    })) as RawOffchainParams;\n\n    const params = mapOffchainParams(result);\n    validateOffchainParams(params);\n    return params;\n  }\n\n  async getOffchainParamsByVersion(\n    version: number,\n  ): Promise<VersionedOffchainParams> {\n    const result = (await this.publicClient.readContract({\n      address: this.contractAddress,\n      abi: ProtocolParamsABI,\n      functionName: \"getOffchainParamsByVersion\",\n      args: [version],\n    })) as RawOffchainParams;\n\n    const params = mapOffchainParams(result);\n    validateOffchainParams(params);\n    return params;\n  }\n\n  async getLatestOffchainParamsVersion(): Promise<number> {\n    const raw = await this.publicClient.readContract({\n      address: this.contractAddress,\n      abi: ProtocolParamsABI,\n      functionName: \"latestOffchainParamsVersion\",\n    });\n    const version = Number(raw);\n    assertValidOffchainParamsVersion(version);\n    return version;\n  }\n\n  async getTimelockPeginByVersion(version: number): Promise<number> {\n    const params = await this.getOffchainParamsByVersion(version);\n    return deriveTimelockPegin(params.timelockAssert);\n  }\n\n  /**\n   * Returned as `bigint` with no `Number` narrowing: the registry compares it\n   * against `block.number`, so callers must do the same arithmetic the\n   * contract does. `0` is the documented \"disabled\" case and is returned as\n   * `0n`. A missing getter or a non-bigint payload throws — never coerced to\n   * `0`, which would fail open and skip the observation window.\n   *\n   * @throws If the deployment does not expose `peginActivationDelay()`, or\n   *   the decoded payload is not a `bigint`.\n   */\n  async getPeginActivationDelay(): Promise<bigint> {\n    const raw: unknown = await this.publicClient.readContract({\n      address: this.contractAddress,\n      abi: ProtocolParamsABI,\n      functionName: \"peginActivationDelay\",\n    });\n    if (typeof raw !== \"bigint\") {\n      throw new Error(\n        `Invalid peginActivationDelay from contract: must be a bigint, got ${typeof raw}`,\n      );\n    }\n    return raw;\n  }\n\n  /**\n   * Read TBV protocol params, latest offchain params, and the latest version\n   * label atomically via multicall. The version is paired with the params so\n   * that a governance update between separate reads cannot let JS build BTC\n   * scripts with version N params while the contract registers the vault\n   * under version N+1.\n   */\n  async getPegInConfiguration(): Promise<PegInConfiguration> {\n    const results = await this.publicClient.multicall({\n      contracts: [\n        {\n          address: this.contractAddress,\n          abi: ProtocolParamsABI,\n          functionName: \"getTBVProtocolParams\",\n        },\n        {\n          address: this.contractAddress,\n          abi: ProtocolParamsABI,\n          functionName: \"getLatestOffchainParams\",\n        },\n        {\n          address: this.contractAddress,\n          abi: ProtocolParamsABI,\n          functionName: \"latestOffchainParamsVersion\",\n        },\n        {\n          address: this.contractAddress,\n          abi: ProtocolParamsABI,\n          functionName: \"activeVaultCoreVersion\",\n        },\n      ],\n      allowFailure: false,\n    });\n\n    const tbvParams = mapTBVParams(results[0] as RawTBVParams);\n    const offchainParams = mapOffchainParams(results[1] as RawOffchainParams);\n    const offchainParamsVersion = Number(results[2]);\n    const activeVaultCoreVersion = Number(results[3]);\n\n    const config: PegInConfiguration = {\n      minimumPegInAmount: tbvParams.minimumPegInAmount,\n      maxPegInAmount: tbvParams.maxPegInAmount,\n      pegInAckTimeout: tbvParams.pegInAckTimeout,\n      pegInActivationTimeout: tbvParams.pegInActivationTimeout,\n      maxHtlcOutputCount: tbvParams.maxHtlcOutputCount,\n      expiredPegInGraceBlocks: tbvParams.expiredPegInGraceBlocks,\n      timelockPegin: deriveTimelockPegin(offchainParams.timelockAssert),\n      timelockRefund: offchainParams.tRefund,\n      minVpCommissionBps: offchainParams.minVpCommissionBps,\n      offchainParams,\n      offchainParamsVersion,\n      activeVaultCoreVersion,\n    };\n\n    validatePegInConfiguration(config);\n    return config;\n  }\n\n  /**\n   * Fetch every historical offchain params version in a single multicall.\n   * Iterates 1..latestVersion and calls `getOffchainParamsByVersion` for each.\n   * Versions whose payload fails validation are skipped (not included in the\n   * returned map) so a single bad historical version doesn't block the\n   * lookup of the rest.\n   *\n   * @param onSkippedVersion - optional observer invoked once per skipped\n   *   version. Use to log/telemeter without coupling the SDK to a logger.\n   */\n  async fetchAllOffchainParams(\n    onSkippedVersion?: OnSkippedOffchainParamsVersion,\n  ): Promise<AllOffchainParamsData> {\n    const latestVersion = await this.getLatestOffchainParamsVersion();\n    if (latestVersion === 0) {\n      return { byVersion: new Map(), latestVersion: 0 };\n    }\n\n    const versions = Array.from({ length: latestVersion }, (_, i) => i + 1);\n    const contracts = versions.map((v) => ({\n      address: this.contractAddress,\n      abi: ProtocolParamsABI as Abi,\n      functionName: \"getOffchainParamsByVersion\" as const,\n      args: [v] as const,\n    }));\n\n    const results = await this.publicClient.multicall({\n      contracts,\n      allowFailure: false,\n    });\n\n    const byVersion = new Map<number, VersionedOffchainParams>();\n    for (let i = 0; i < versions.length; i++) {\n      const params = mapOffchainParams(results[i] as RawOffchainParams);\n      try {\n        validateOffchainParams(params);\n        byVersion.set(versions[i], params);\n      } catch (error) {\n        // A malformed historical version mustn't block lookup of the rest.\n        // Surface the skip to the caller's observer if one was supplied.\n        onSkippedVersion?.(\n          versions[i],\n          error instanceof Error ? error : new Error(String(error)),\n        );\n      }\n    }\n\n    return { byVersion, latestVersion };\n  }\n}\n","/**\n * Concrete signer-set readers for vault keepers and universal challengers.\n *\n * These are optional utilities — callers can use their own implementations\n * of the VaultKeeperReader and UniversalChallengerReader interfaces.\n */\n\nimport type { Address, Hex, PublicClient } from \"viem\";\n\nimport { ApplicationRegistryABI } from \"../../contracts/abis/ApplicationRegistry.abi\";\nimport { ProtocolParamsABI } from \"../../contracts/abis/ProtocolParams.abi\";\nimport type {\n  AddressBTCKeyPair,\n  UniversalChallengerReader,\n  VaultKeeperReader,\n} from \"./types\";\n\n/** Map viem tuple array to AddressBTCKeyPair[]. */\nfunction mapKeyPairs(\n  result: readonly { ethAddress: Address; btcPubKey: Hex }[],\n): AddressBTCKeyPair[] {\n  return result.map((pair) => ({\n    ethAddress: pair.ethAddress,\n    btcPubKey: pair.btcPubKey,\n  }));\n}\n\n/**\n * Reads vault keepers from the ApplicationRegistry contract.\n *\n * Usage:\n * ```ts\n * const reader = new ViemVaultKeeperReader(publicClient, applicationRegistryAddress);\n * const keepers = await reader.getCurrentVaultKeepers(appEntryPoint);\n * ```\n */\nexport class ViemVaultKeeperReader implements VaultKeeperReader {\n  constructor(\n    private publicClient: PublicClient,\n    private contractAddress: Address,\n  ) {}\n\n  async getVaultKeepersByVersion(\n    appEntryPoint: Address,\n    version: number,\n  ): Promise<AddressBTCKeyPair[]> {\n    const result = (await this.publicClient.readContract({\n      address: this.contractAddress,\n      abi: ApplicationRegistryABI,\n      functionName: \"getVaultKeepersByVersion\",\n      args: [appEntryPoint, version],\n    })) as readonly { ethAddress: Address; btcPubKey: Hex }[];\n\n    return mapKeyPairs(result);\n  }\n\n  async getCurrentVaultKeepers(\n    appEntryPoint: Address,\n  ): Promise<AddressBTCKeyPair[]> {\n    const result = (await this.publicClient.readContract({\n      address: this.contractAddress,\n      abi: ApplicationRegistryABI,\n      functionName: \"getCurrentVaultKeepers\",\n      args: [appEntryPoint],\n    })) as readonly { ethAddress: Address; btcPubKey: Hex }[];\n\n    return mapKeyPairs(result);\n  }\n\n  async getCurrentVaultKeepersVersion(\n    appEntryPoint: Address,\n  ): Promise<number> {\n    const result = (await this.publicClient.readContract({\n      address: this.contractAddress,\n      abi: ApplicationRegistryABI,\n      functionName: \"getCurrentVaultKeepersVersion\",\n      args: [appEntryPoint],\n    })) as number;\n\n    return result;\n  }\n}\n\n/**\n * Reads universal challengers from the ProtocolParams contract.\n *\n * Usage:\n * ```ts\n * const reader = new ViemUniversalChallengerReader(publicClient, protocolParamsAddress);\n * const challengers = await reader.getCurrentUniversalChallengers();\n * ```\n */\nexport class ViemUniversalChallengerReader implements UniversalChallengerReader {\n  constructor(\n    private publicClient: PublicClient,\n    private contractAddress: Address,\n  ) {}\n\n  async getUniversalChallengersByVersion(\n    version: number,\n  ): Promise<AddressBTCKeyPair[]> {\n    const result = (await this.publicClient.readContract({\n      address: this.contractAddress,\n      abi: ProtocolParamsABI,\n      functionName: \"getUniversalChallengersByVersion\",\n      args: [version],\n    })) as readonly { ethAddress: Address; btcPubKey: Hex }[];\n\n    return mapKeyPairs(result);\n  }\n\n  async getCurrentUniversalChallengers(): Promise<AddressBTCKeyPair[]> {\n    const result = (await this.publicClient.readContract({\n      address: this.contractAddress,\n      abi: ProtocolParamsABI,\n      functionName: \"getCurrentUniversalChallengers\",\n    })) as readonly { ethAddress: Address; btcPubKey: Hex }[];\n\n    return mapKeyPairs(result);\n  }\n\n  async getLatestUniversalChallengersVersion(): Promise<number> {\n    const result = (await this.publicClient.readContract({\n      address: this.contractAddress,\n      abi: ProtocolParamsABI,\n      functionName: \"latestUniversalChallengersVersion\",\n    })) as number;\n\n    return result;\n  }\n}\n","/**\n * Types and interfaces for ETH contract readers.\n *\n * These are optional utilities — callers can use them or build their own.\n * Core service functions never import from this module.\n */\n\nimport type { Address, Hex } from \"viem\";\n\n// ============================================================================\n// Vault Registry Types\n// ============================================================================\n\ndeclare const onChainBtcPubkeyBrand: unique symbol;\n\n/**\n * 64-char lowercase hex (no `0x`) x-only BTC pubkey sourced from an on-chain\n * registry. Minted only by `assertOnChainBtcPubkey`, which is the shared\n * validator behind both producers:\n * {@link VaultRegistryReader.getVaultProviderGenesisBtcPubKey} (the fixed\n * registration key) and {@link OperationKeyReader} (RFC-006 operation keys,\n * resolved current or at a vault's frozen epoch).\n *\n * @stability frozen\n */\nexport type OnChainBtcPubkey = string & {\n  readonly [onChainBtcPubkeyBrand]: true;\n};\n\n/**\n * Mirrors `IBTCVaultRegistry.BTCVaultStatus` in BTCVaultRegistry.sol exactly.\n * Use this when consuming `status` from `getVaultBasicInfo` /\n * `getBtcVaultBasicInfo`.\n *\n * Do NOT confuse with the app-side `ContractStatus` enum\n * (`services/deposit/peginState.ts`) — that one is for the indexer and\n * extends this with values 5-7, reassigning 4 to LIQUIDATED. Reading an\n * on-chain status through `ContractStatus[n]` for labels will mislabel\n * Expired(4) as LIQUIDATED.\n */\nexport enum OnChainBtcVaultStatus {\n  PENDING = 0,\n  VERIFIED = 1,\n  ACTIVE = 2,\n  REDEEMED = 3,\n  EXPIRED = 4,\n}\n\n/** Basic vault info from BTCVaultRegistry.getBtcVaultBasicInfo */\nexport interface VaultBasicInfo {\n  depositor: Address;\n  depositorBtcPubKey: Hex;\n  amount: bigint;\n  vaultProvider: Address;\n  status: number;\n  applicationEntryPoint: Address;\n  createdAt: bigint;\n}\n\n/** Protocol info from BTCVaultRegistry.getBtcVaultProtocolInfo */\nexport interface VaultProtocolInfo {\n  depositorSignedPeginTx: Hex;\n  universalChallengersVersion: number;\n  appVaultKeepersVersion: number;\n  offchainParamsVersion: number;\n  /**\n   * ETH block number stamped at the Pending→Verified transition.\n   * Compared against `block.number` (inclusive:\n   * `block.number >= verifiedAt + peginActivationDelay`), never a unix timestamp.\n   */\n  verifiedAt: bigint;\n  depositorWotsPkHash: Hex;\n  hashlock: Hex;\n  htlcVout: number;\n  depositorPopSignature: Hex;\n  prePeginTxHash: Hex;\n  vaultProviderCommissionBps: number;\n  /** Block deadline (uint256) for depositor reclaim. TODO(#1690): wire to refund flow. */\n  claimExpiredUntil: bigint;\n  /** Vault core version (uint16) stamped at registration. VP-side gating only — see #1690. */\n  vaultCoreVersion: number;\n}\n\n/** Combined vault data (basic + protocol) */\nexport interface VaultData {\n  basic: VaultBasicInfo;\n  protocol: VaultProtocolInfo;\n}\n\n/**\n * RFC-006 operation-key epochs a vault froze at `submitPeginRequest`.\n *\n * Each registry keeps a monotonic epoch counter that every key/payout setter\n * pre-increments. A vault stamps the counters live at its creation, and every\n * participant resolves \"which key did this vault bond?\" by asking the registry\n * for the key whose appended version is the latest stamped `<=` this epoch. A\n * rotation after the vault was created therefore never moves its keys.\n *\n * `uint64` — kept as `bigint` end-to-end and passed straight back to the\n * `...AtEpoch` getters, never narrowed through `Number`.\n *\n * Only ever read through {@link VaultRegistryReader.getVaultKeyEpochs}, which\n * uses the extended ABI. See `BTCVaultRegistryKeyEpochs.abi.ts` for why that\n * read is quarantined to its own ABI.\n */\nexport interface KeyEpochs {\n  vpKeyEpoch: bigint;\n  appKeeperKeyEpoch: bigint;\n  ucKeyEpoch: bigint;\n}\n\n/** Interface for reading vault data from the BTCVaultRegistry contract. */\nexport interface VaultRegistryReader {\n  getVaultBasicInfo(vaultId: Hex): Promise<VaultBasicInfo>;\n  getVaultProtocolInfo(vaultId: Hex): Promise<VaultProtocolInfo>;\n  getProtocolInfoBatch(vaultIds: readonly Hex[]): Promise<VaultProtocolInfo[]>;\n  getVaultData(vaultId: Hex): Promise<VaultData>;\n  /**\n   * Read a vault provider's *genesis* (registration) BTC key — the key bonded\n   * at version 0, which never moves when the operator rotates.\n   *\n   * Used only as the genesis fallback for epoch-based resolution and as a\n   * candidate when cross-checking an indexer hint. Never the key to build a\n   * Bitcoin lock with; that comes from `OperationKeyReader`.\n   *\n   * Resolves via `getOperationBtcKeyAtEpoch` at epoch 0, so it requires an\n   * RFC-006 registry — as does every caller.\n   */\n  getVaultProviderGenesisBtcPubKey(\n    vpAddress: Address,\n  ): Promise<OnChainBtcPubkey>;\n  /** Read the protocol pegin fee (in wei) for a given vault provider. */\n  getPegInFee(vaultProvider: Address): Promise<bigint>;\n  /**\n   * Read a vault provider's current commission in basis points.\n   *\n   * Validates the contract-enforced `[0, 9999]` range — an out-of-range\n   * value signals a wrong contract address or ABI drift, not a real rate.\n   */\n  getVaultProviderCommission(vaultProvider: Address): Promise<number>;\n  /**\n   * Read a vault's frozen RFC-006 key epochs.\n   *\n   * Uses the extended `getBtcVaultProtocolInfo` ABI. Against a registry whose\n   * `BTCVaultProtocolInfo` struct is not extended this returns silent garbage\n   * for a populated vault rather than throwing, so it must only be called\n   * against an RFC-006 registry — a deployment invariant, not something this\n   * call can detect. A registry missing the operation-key getters altogether is\n   * the safer case: key resolution reverts downstream and these epochs are never\n   * used. See `BTCVaultRegistryKeyEpochs.abi.ts`.\n   */\n  getVaultKeyEpochs(vaultId: Hex): Promise<KeyEpochs>;\n  /** {@link getVaultKeyEpochs} for many vaults in one multicall. */\n  getVaultKeyEpochsBatch(vaultIds: readonly Hex[]): Promise<KeyEpochs[]>;\n  /**\n   * Read a vault provider's *current* RFC-006 operation BTC key — the key its\n   * server signs auth tokens with. Falls back to the registration key when the\n   * provider has never rotated.\n   */\n  getCurrentVaultProviderOperationBtcKey(\n    vpAddress: Address,\n  ): Promise<OnChainBtcPubkey>;\n}\n\n// ============================================================================\n// Protocol Params Types (from IProtocolParams.sol)\n// ============================================================================\n\n/**\n * TBV protocol parameters from the ProtocolParams contract.\n * Matches Solidity struct `IProtocolParams.TBVProtocolParams` exactly.\n *\n * All uint64 amounts use bigint (satoshi values can exceed 2^53).\n * uint8 uses number (bounded, max 255).\n */\nexport interface TBVProtocolParams {\n  minimumPegInAmount: bigint;\n  maxPegInAmount: bigint;\n  pegInAckTimeout: bigint;\n  pegInActivationTimeout: bigint;\n  maxHtlcOutputCount: number;\n  /**\n   * Number of blocks added to the activation deadline as a grace window\n   * during which a depositor may still reclaim an expired pegin via the\n   * HTLC preimage. Source: `IProtocolParams.TBVProtocolParams.expiredPegInGraceBlocks`.\n   */\n  expiredPegInGraceBlocks: bigint;\n}\n\n/**\n * Versioned offchain parameters from the ProtocolParams contract.\n * Matches Solidity struct `IProtocolParams.VersionedOffchainParams` exactly.\n *\n * bigint for: uint256 timelocks, uint64 fee rates/amounts.\n * number for: uint8/uint16/uint32 fields (bounded, safe for JS arithmetic).\n */\nexport interface VersionedOffchainParams {\n  timelockAssert: bigint;\n  timelockChallengeAssert: bigint;\n  securityCouncilKeys: Hex[];\n  councilQuorum: number;\n  feeRate: bigint;\n  babeTotalInstances: number;\n  babeInstancesToFinalize: number;\n  minVpCommissionBps: number;\n  tRefund: number;\n  tStale: number;\n  minPeginFeeRate: bigint;\n  proverCircuitVersion: number;\n  minPrepeginDepth: number;\n}\n\n/**\n * Combined peg-in configuration read atomically via multicall.\n * Prevents TOCTOU inconsistency if governance updates params between reads.\n */\nexport interface PegInConfiguration {\n  minimumPegInAmount: bigint;\n  maxPegInAmount: bigint;\n  pegInAckTimeout: bigint;\n  pegInActivationTimeout: bigint;\n  maxHtlcOutputCount: number;\n  expiredPegInGraceBlocks: bigint;\n  timelockPegin: number;\n  timelockRefund: number;\n  minVpCommissionBps: number;\n  offchainParams: VersionedOffchainParams;\n  /**\n   * Version label paired atomically with `offchainParams`.\n   * Read in the same multicall as the params struct so that, if a parameter\n   * update lands between separate reads, the script-construction code and\n   * the version label stay consistent.\n   */\n  offchainParamsVersion: number;\n  /**\n   * Currently-active vault core (tx-graph) version\n   * (`ProtocolParams.activeVaultCoreVersion()`, uint16 ≥ 1). Stamped onto\n   * every new vault at peg-in submission; fresh deposits must build this\n   * graph version. Read in the same multicall so a governance version bump\n   * can't land between reading the params and reading the version.\n   */\n  activeVaultCoreVersion: number;\n}\n\n/**\n * All offchain params snapshots indexed by version, plus the latest version\n * number known when the snapshot was taken. Used by consumers that need to\n * resolve any historical version (e.g. signing for an existing vault locked\n * to an older version).\n */\nexport interface AllOffchainParamsData {\n  byVersion: Map<number, VersionedOffchainParams>;\n  latestVersion: number;\n}\n\n/**\n * Optional observer invoked by `fetchAllOffchainParams` when a historical\n * version fails validation. Called once per skipped version so callers can\n * log/telemeter without coupling the SDK to a specific logger.\n */\nexport type OnSkippedOffchainParamsVersion = (\n  version: number,\n  error: Error,\n) => void;\n\n/** Interface for reading protocol parameters from the ProtocolParams contract. */\nexport interface ProtocolParamsReader {\n  getTBVProtocolParams(): Promise<TBVProtocolParams>;\n  getOffchainParamsByVersion(version: number): Promise<VersionedOffchainParams>;\n  getLatestOffchainParams(): Promise<VersionedOffchainParams>;\n  getLatestOffchainParamsVersion(): Promise<number>;\n  getTimelockPeginByVersion(version: number): Promise<number>;\n  getPegInConfiguration(): Promise<PegInConfiguration>;\n  /**\n   * Observation window enforced between a vault's final ACK and its\n   * activation, in ETH blocks measured from `verifiedAt`. `0` disables it.\n   *\n   * Deliberately its own read rather than a field on\n   * {@link PegInConfiguration}: the parameter is absent from deployments that\n   * predate it, so folding it into the shared multicall would make every\n   * protocol-param read fail wherever it is missing.\n   *\n   * @throws If the deployment does not expose `peginActivationDelay()`, or\n   *   the decoded payload is not a `bigint`.\n   */\n  getPeginActivationDelay(): Promise<bigint>;\n  fetchAllOffchainParams(\n    onSkippedVersion?: OnSkippedOffchainParamsVersion,\n  ): Promise<AllOffchainParamsData>;\n}\n\n// ============================================================================\n// Signer-Set Types (from BTCVaultTypes.sol)\n// ============================================================================\n\n/**\n * Matches Solidity struct `BTCVaultTypes.AddressBTCKeyPair` exactly.\n * Used for vault keepers and universal challengers.\n */\nexport interface AddressBTCKeyPair {\n  ethAddress: Address;\n  btcPubKey: Hex;\n}\n\n/** Interface for reading vault keepers from the ApplicationRegistry contract. */\nexport interface VaultKeeperReader {\n  getVaultKeepersByVersion(\n    appEntryPoint: Address,\n    version: number,\n  ): Promise<AddressBTCKeyPair[]>;\n  getCurrentVaultKeepers(appEntryPoint: Address): Promise<AddressBTCKeyPair[]>;\n  getCurrentVaultKeepersVersion(appEntryPoint: Address): Promise<number>;\n}\n\n/** Interface for reading universal challengers from the ProtocolParams contract. */\nexport interface UniversalChallengerReader {\n  getUniversalChallengersByVersion(\n    version: number,\n  ): Promise<AddressBTCKeyPair[]>;\n  getCurrentUniversalChallengers(): Promise<AddressBTCKeyPair[]>;\n  getLatestUniversalChallengersVersion(): Promise<number>;\n}\n\n// ============================================================================\n// RFC-006 Operation-Key Types\n// ============================================================================\n\n/**\n * The participants whose operation keys are being resolved, and the roster\n * they are resolved against.\n *\n * A roster entry's `ethAddress` is the operator's **admin** address — the\n * lookup key for its key history — and its `btcPubKey` is the operator's\n * **genesis** key. Both are needed: the `...AtEpochOrGenesis` getters take the\n * roster key explicitly because the correct genesis for a keeper/challenger is\n * its key in the vault's *frozen membership version*, which an operator that\n * was later dropped from the roster no longer has a current entry for.\n */\nexport interface OperationKeyQuery {\n  vaultProviderEthAddress: Address;\n  /**\n   * The VP's genesis (registration) key, from\n   * {@link VaultRegistryReader.getVaultProviderGenesisBtcPubKey}.\n   *\n   * The VP has no roster entry to carry a genesis key the way keepers and\n   * challengers do, so it is supplied here. Every call site already reads it:\n   * it is what the indexer hint is compared against, and what makes the VP's\n   * `rotated` flag mean the same thing as everyone else's.\n   */\n  vaultProviderGenesisBtcPubkey: Hex;\n  applicationEntryPoint: Address;\n  /** Keeper roster at the membership version being resolved against. */\n  vaultKeepers: readonly AddressBTCKeyPair[];\n  /** Challenger roster at the membership version being resolved against. */\n  universalChallengers: readonly AddressBTCKeyPair[];\n}\n\n/** Raw registry-returned operation keys, index-aligned with the query rosters. */\nexport interface RawOperationKeys {\n  vaultProvider: Hex;\n  vaultKeepers: Hex[];\n  universalChallengers: Hex[];\n}\n\n/**\n * Registry-returned payout scriptPubKeys, index-aligned with the query\n * rosters. `universalChallengers` has no counterpart: a UC is never a claimer,\n * so it has no payout script.\n */\nexport interface RawPayoutScripts {\n  vaultProvider: Hex;\n  vaultKeepers: Hex[];\n}\n\n/**\n * Reads RFC-006 operation keys and payout scripts across all three registries\n * (BTCVaultRegistry, ApplicationRegistry, ProtocolParams).\n *\n * Every method resolves the whole participant set in a **single** multicall so\n * the keys are pinned to one block. That atomicity is load-bearing: a rotation\n * landing between two `eth_call`s would yield a self-inconsistent key set that\n * builds a lock no counterparty agrees with.\n */\nexport interface OperationKeyReader {\n  /**\n   * Resolve every participant's *current* operation key.\n   *\n   * Used for new peg-ins and for the VP auth pin. Needs no epoch read at all —\n   * each registry's `getCurrentOperationBtcKey` resolves its own genesis\n   * fallback, so an operator that never rotated yields its registration key.\n   */\n  getCurrentOperationKeys(query: OperationKeyQuery): Promise<RawOperationKeys>;\n  /**\n   * Resolve every participant's operation key bonded at a vault's frozen\n   * epochs. Used for every existing-vault path (resume, payout, refund).\n   */\n  getOperationKeysAtEpochs(\n    query: OperationKeyQuery,\n    epochs: KeyEpochs,\n  ): Promise<RawOperationKeys>;\n  /**\n   * Resolve the VP's commission payout script and each keeper's payout script\n   * at a vault's frozen epochs.\n   *\n   * The registry backfills BIP-86 P2TR of the epoch's operation key for any\n   * operator that never called `setPayoutScript`, so this returns byte-identical\n   * results to local BIP-86 derivation until an operator registers a custom\n   * script.\n   */\n  getPayoutScriptsAtEpochs(\n    query: OperationKeyQuery,\n    epochs: KeyEpochs,\n  ): Promise<RawPayoutScripts>;\n}\n","/**\n * Runtime validation for vault provider RPC responses.\n *\n * All VP RPC methods return untyped JSON that TypeScript generics cast without\n * inspection. These validators check the critical top-level fields and\n * security-relevant values (status, txids, pubkeys). Optional progress\n * sub-fields (gc_data, ack_collection, claimer_graphs) are NOT validated\n * since they are informational and not used for signing or transaction\n * construction. Only `progress.presigning` sub-fields are checked.\n */\n\nimport { CHALLENGE_ASSERT_CONNECTORS_PER_CHALLENGER } from \"../../primitives/psbt/constants\";\nimport {\n  COMPRESSED_PUBKEY_HEX_LEN,\n  X_ONLY_PUBKEY_HEX_LEN,\n} from \"../../primitives/utils/bitcoin\";\nimport { HEX_RE } from \"../../utils/validation\";\n\nimport { DaemonStatus } from \"./types\";\nimport type {\n  BatchGetPeginStatusResponse,\n  BatchGetPegoutStatusResponse,\n  GetPeginStatusResponse,\n  GetPegoutStatusResponse,\n  RequestDepositorClaimerArtifactsResponse,\n  RequestDepositorPresignTransactionsResponse,\n} from \"./types\";\n\nconst DAEMON_STATUS_VALUES = new Set<string>(Object.values(DaemonStatus));\n\nconst VP_ERROR_PREVIEW_MAX_LEN = 200;\n\nfunction preview(value: unknown): string {\n  return (\n    JSON.stringify(value)?.slice(0, VP_ERROR_PREVIEW_MAX_LEN) ?? \"undefined\"\n  );\n}\n\nconst VP_VALIDATION_USER_MESSAGE =\n  \"The vault provider returned an unexpected response. Please try again or contact support.\";\n\n/**\n * Thrown when a VP RPC response fails runtime validation.\n *\n * `.message` is a user-facing string safe to display in the UI.\n * `.detail` contains the technical reason, suitable for logging.\n */\nexport class VpResponseValidationError extends Error {\n  readonly detail: string;\n\n  constructor(detail: string) {\n    super(VP_VALIDATION_USER_MESSAGE);\n    this.name = \"VpResponseValidationError\";\n    this.detail = detail;\n  }\n}\n\n/** Expected length (in hex chars) of a Bitcoin transaction ID (32 bytes). */\nconst TXID_HEX_LEN = 64;\n\nfunction isNonEmptyHex(value: unknown): value is string {\n  return typeof value === \"string\" && value.length > 0 && HEX_RE.test(value);\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n  return typeof value === \"string\" && value.length > 0;\n}\n\nfunction assertNonEmptyHex(value: unknown, field: string): void {\n  if (!isNonEmptyHex(value)) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"${field}\" must be a non-empty hex string, got ${preview(value)}`,\n    );\n  }\n}\n\nfunction assertNonEmptyString(value: unknown, field: string): void {\n  if (!isNonEmptyString(value)) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"${field}\" must be a non-empty string, got ${preview(value)}`,\n    );\n  }\n}\n\n/**\n * Accept both x-only (64-char) and compressed (66-char) pubkeys from VP responses.\n * The signing code normalizes to x-only via processPublicKeyToXOnly().\n */\nfunction assertBtcPubkey(value: unknown, field: string): void {\n  if (\n    !isNonEmptyHex(value) ||\n    (value.length !== X_ONLY_PUBKEY_HEX_LEN &&\n      value.length !== COMPRESSED_PUBKEY_HEX_LEN)\n  ) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"${field}\" must be a ${X_ONLY_PUBKEY_HEX_LEN} or ${COMPRESSED_PUBKEY_HEX_LEN}-char hex string (BTC pubkey), got ${preview(value)}`,\n    );\n  }\n}\n\n/**\n * Validate the optional presigning progress fields returned inside PeginProgressDetails.\n */\nfunction validatePresigningProgressFields(\n  progress: Record<string, unknown>,\n): void {\n  const presigning = progress.presigning;\n  if (presigning === undefined || presigning === null) return;\n  if (typeof presigning !== \"object\" || Array.isArray(presigning)) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"progress.presigning\" must be an object if present`,\n    );\n  }\n\n  const p = presigning as Record<string, unknown>;\n\n  if (\n    p.depositor_graph_created !== undefined &&\n    typeof p.depositor_graph_created !== \"boolean\"\n  ) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"progress.presigning.depositor_graph_created\" must be a boolean if present, got ${preview(p.depositor_graph_created)}`,\n    );\n  }\n\n  if (\n    p.vk_challenger_presigning_completed !== undefined &&\n    typeof p.vk_challenger_presigning_completed !== \"number\"\n  ) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"progress.presigning.vk_challenger_presigning_completed\" must be a number if present, got ${preview(p.vk_challenger_presigning_completed)}`,\n    );\n  }\n\n  if (\n    p.vk_challenger_presigning_total !== undefined &&\n    typeof p.vk_challenger_presigning_total !== \"number\"\n  ) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"progress.presigning.vk_challenger_presigning_total\" must be a number if present, got ${preview(p.vk_challenger_presigning_total)}`,\n    );\n  }\n}\n\n/**\n * Validate a getPeginStatus response.\n *\n * Throws if the status field is not a recognized DaemonStatus value.\n */\nexport function validateGetPeginStatusResponse(\n  response: unknown,\n): asserts response is GetPeginStatusResponse {\n  if (response === null || typeof response !== \"object\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: getPeginStatus response is not an object`,\n    );\n  }\n\n  const r = response as Record<string, unknown>;\n\n  if (!isNonEmptyHex(r.pegin_txid) || r.pegin_txid.length !== TXID_HEX_LEN) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"pegin_txid\" must be a ${TXID_HEX_LEN}-char hex string (txid), got ${preview(r.pegin_txid)}`,\n    );\n  }\n\n  if (typeof r.status !== \"string\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"status\" must be a string`,\n    );\n  }\n\n  if (!DAEMON_STATUS_VALUES.has(r.status)) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: unrecognized status \"${r.status}\". Expected one of: ${[...DAEMON_STATUS_VALUES].join(\", \")}`,\n    );\n  }\n\n  if (\n    r.progress === null ||\n    typeof r.progress !== \"object\" ||\n    Array.isArray(r.progress)\n  ) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"progress\" must be an object`,\n    );\n  }\n\n  validatePresigningProgressFields(r.progress as Record<string, unknown>);\n\n  if (typeof r.health_info !== \"string\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"health_info\" must be a string`,\n    );\n  }\n\n  if (r.last_error !== undefined && typeof r.last_error !== \"string\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"last_error\" must be a string if present, got ${preview(r.last_error)}`,\n    );\n  }\n}\n\n/**\n * Validate a requestDepositorPresignTransactions response.\n */\nexport function validateRequestDepositorPresignTransactionsResponse(\n  response: unknown,\n): asserts response is RequestDepositorPresignTransactionsResponse {\n  if (response === null || typeof response !== \"object\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: requestDepositorPresignTransactions response is not an object`,\n    );\n  }\n\n  const r = response as Record<string, unknown>;\n\n  if (!Array.isArray(r.txs)) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"txs\" must be an array`,\n    );\n  }\n\n  for (let i = 0; i < r.txs.length; i++) {\n    validateClaimerTransactions(r.txs[i], `txs[${i}]`);\n  }\n\n  if (r.depositor_graph === null || typeof r.depositor_graph !== \"object\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"depositor_graph\" must be an object`,\n    );\n  }\n\n  validateDepositorGraphTransactions(\n    r.depositor_graph as Record<string, unknown>,\n  );\n}\n\nfunction validateTransactionData(value: unknown, field: string): void {\n  if (value === null || typeof value !== \"object\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"${field}\" must be an object`,\n    );\n  }\n  const tx = value as Record<string, unknown>;\n  assertNonEmptyHex(tx.tx_hex, `${field}.tx_hex`);\n}\n\nfunction validateClaimerTransactions(value: unknown, field: string): void {\n  if (value === null || typeof value !== \"object\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"${field}\" must be an object`,\n    );\n  }\n\n  const tx = value as Record<string, unknown>;\n\n  assertBtcPubkey(tx.claimer_pubkey, `${field}.claimer_pubkey`);\n  validateTransactionData(tx.claim_tx, `${field}.claim_tx`);\n  validateTransactionData(tx.assert_tx, `${field}.assert_tx`);\n  validateTransactionData(tx.payout_tx, `${field}.payout_tx`);\n  assertNonEmptyString(tx.payout_psbt, `${field}.payout_psbt`);\n}\n\nfunction validateChallengeAssertConnectorData(\n  value: unknown,\n  field: string,\n): void {\n  if (value === null || typeof value !== \"object\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"${field}\" must be an object`,\n    );\n  }\n\n  const c = value as Record<string, unknown>;\n  assertNonEmptyString(c.wots_pks_json, `${field}.wots_pks_json`);\n  assertNonEmptyString(c.gc_wots_keys_json, `${field}.gc_wots_keys_json`);\n}\n\nfunction validatePresignDataPerChallenger(value: unknown, field: string): void {\n  if (value === null || typeof value !== \"object\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"${field}\" must be an object`,\n    );\n  }\n\n  const d = value as Record<string, unknown>;\n\n  assertBtcPubkey(d.challenger_pubkey, `${field}.challenger_pubkey`);\n  validateTransactionData(\n    d.challenge_assert_x_tx,\n    `${field}.challenge_assert_x_tx`,\n  );\n  validateTransactionData(\n    d.challenge_assert_y_tx,\n    `${field}.challenge_assert_y_tx`,\n  );\n  validateTransactionData(d.nopayout_tx, `${field}.nopayout_tx`);\n  assertNonEmptyString(d.nopayout_psbt, `${field}.nopayout_psbt`);\n\n  if (!Array.isArray(d.challenge_assert_connectors)) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"${field}.challenge_assert_connectors\" must be an array`,\n    );\n  }\n\n  if (\n    d.challenge_assert_connectors.length !==\n    CHALLENGE_ASSERT_CONNECTORS_PER_CHALLENGER\n  ) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"${field}.challenge_assert_connectors\" must have exactly ${CHALLENGE_ASSERT_CONNECTORS_PER_CHALLENGER} entries, got ${d.challenge_assert_connectors.length}`,\n    );\n  }\n\n  for (let i = 0; i < d.challenge_assert_connectors.length; i++) {\n    validateChallengeAssertConnectorData(\n      d.challenge_assert_connectors[i],\n      `${field}.challenge_assert_connectors[${i}]`,\n    );\n  }\n\n  if (!Array.isArray(d.output_label_hashes)) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"${field}.output_label_hashes\" must be an array`,\n    );\n  }\n\n  for (let i = 0; i < d.output_label_hashes.length; i++) {\n    assertNonEmptyHex(\n      d.output_label_hashes[i],\n      `${field}.output_label_hashes[${i}]`,\n    );\n  }\n}\n\n/**\n * Validate a requestDepositorClaimerArtifacts response.\n */\nexport function validateRequestDepositorClaimerArtifactsResponse(\n  response: unknown,\n): asserts response is RequestDepositorClaimerArtifactsResponse {\n  if (response === null || typeof response !== \"object\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: requestDepositorClaimerArtifacts response is not an object`,\n    );\n  }\n\n  const r = response as Record<string, unknown>;\n\n  if (!isNonEmptyString(r.tx_graph_json)) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"tx_graph_json\" must be a non-empty string, got ${preview(r.tx_graph_json)}`,\n    );\n  }\n\n  if (!isNonEmptyHex(r.verifying_key_hex)) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"verifying_key_hex\" must be a non-empty hex string, got ${preview(r.verifying_key_hex)}`,\n    );\n  }\n\n  if (\n    r.babe_sessions === null ||\n    typeof r.babe_sessions !== \"object\" ||\n    Array.isArray(r.babe_sessions)\n  ) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"babe_sessions\" must be an object`,\n    );\n  }\n\n  const sessionEntries = Object.entries(\n    r.babe_sessions as Record<string, unknown>,\n  );\n  if (sessionEntries.length === 0) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"babe_sessions\" must contain at least one challenger entry`,\n    );\n  }\n\n  for (const [key, session] of sessionEntries) {\n    assertBtcPubkey(key, `babe_sessions[\"${key}\"]`);\n    if (session === null || typeof session !== \"object\") {\n      throw new VpResponseValidationError(\n        `VP response validation failed: \"babe_sessions.${key}\" must be an object`,\n      );\n    }\n    const s = session as Record<string, unknown>;\n    if (!isNonEmptyHex(s.decryptor_artifacts_hex)) {\n      throw new VpResponseValidationError(\n        `VP response validation failed: \"babe_sessions.${key}.decryptor_artifacts_hex\" must be a non-empty hex string, got ${preview(s.decryptor_artifacts_hex)}`,\n      );\n    }\n  }\n}\n\n/**\n * Validate a single pegout status payload. Embedded by\n * `validateBatchGetPegoutStatusResponse`. Mirrors btc-vault\n * `crates/vaultd/src/rpc/server/pegout_status.rs::GetPegoutStatusResponse`.\n */\nexport function validateGetPegoutStatusResponse(\n  response: unknown,\n): asserts response is GetPegoutStatusResponse {\n  if (response === null || typeof response !== \"object\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: pegout status payload is not an object`,\n    );\n  }\n\n  const r = response as Record<string, unknown>;\n\n  if (!isNonEmptyHex(r.pegin_txid) || r.pegin_txid.length !== TXID_HEX_LEN) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"pegin_txid\" must be a ${TXID_HEX_LEN}-char hex string (txid), got ${preview(r.pegin_txid)}`,\n    );\n  }\n\n  if (typeof r.found !== \"boolean\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"found\" must be a boolean, got ${preview(r.found)}`,\n    );\n  }\n\n  // `claimer` is `Option<ClaimerPegoutStatus>` server-side; null when absent.\n  if (r.claimer !== null) {\n    if (typeof r.claimer !== \"object\") {\n      throw new VpResponseValidationError(\n        `VP response validation failed: \"claimer\" must be an object or null, got ${preview(r.claimer)}`,\n      );\n    }\n    validateClaimerPegoutStatus(r.claimer as Record<string, unknown>);\n  }\n\n  // `challengers: Vec<ChallengerStatus>` server-side; always present (possibly empty).\n  if (!Array.isArray(r.challengers)) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"challengers\" must be an array, got ${preview(r.challengers)}`,\n    );\n  }\n  for (let i = 0; i < r.challengers.length; i++) {\n    validateChallengerStatus(r.challengers[i], i);\n  }\n}\n\nfunction validateClaimerPegoutStatus(value: Record<string, unknown>): void {\n  assertNonEmptyString(value.status, \"claimer.status\");\n  if (typeof value.failed !== \"boolean\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"claimer.failed\" must be a boolean, got ${preview(value.failed)}`,\n    );\n  }\n  assertNonEmptyString(value.claim_txid, \"claimer.claim_txid\");\n  assertNonEmptyString(value.claimer_pubkey, \"claimer.claimer_pubkey\");\n  assertNonEmptyString(value.assert_txid, \"claimer.assert_txid\");\n  if (typeof value.created_at !== \"number\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"claimer.created_at\" must be a number, got ${preview(value.created_at)}`,\n    );\n  }\n  if (typeof value.updated_at !== \"number\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"claimer.updated_at\" must be a number, got ${preview(value.updated_at)}`,\n    );\n  }\n}\n\nfunction validateChallengerStatus(value: unknown, index: number): void {\n  if (value === null || typeof value !== \"object\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"challengers[${index}]\" must be an object, got ${preview(value)}`,\n    );\n  }\n  const c = value as Record<string, unknown>;\n  assertNonEmptyString(c.status, `challengers[${index}].status`);\n  assertNonEmptyString(c.claim_txid, `challengers[${index}].claim_txid`);\n  assertNonEmptyString(c.claimer_pubkey, `challengers[${index}].claimer_pubkey`);\n  assertNullableString(c.assert_txid, `challengers[${index}].assert_txid`);\n  assertNullableString(\n    c.challenge_assert_x_txid,\n    `challengers[${index}].challenge_assert_x_txid`,\n  );\n  assertNullableString(\n    c.challenge_assert_y_txid,\n    `challengers[${index}].challenge_assert_y_txid`,\n  );\n  assertNullableString(c.nopayout_txid, `challengers[${index}].nopayout_txid`);\n  if (typeof c.created_at !== \"number\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"challengers[${index}].created_at\" must be a number, got ${preview(c.created_at)}`,\n    );\n  }\n  if (typeof c.updated_at !== \"number\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"challengers[${index}].updated_at\" must be a number, got ${preview(c.updated_at)}`,\n    );\n  }\n}\n\nfunction assertNullableString(value: unknown, field: string): void {\n  if (value !== null && typeof value !== \"string\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"${field}\" must be a string or null, got ${preview(value)}`,\n    );\n  }\n}\n\n/**\n * Validate a `batchGetPeginStatus` response. Per-result envelope shape:\n * `{ pegin_txid, result: GetPeginStatusResponse | null, error: string | null }`.\n * The inner result (when non-null) is validated via the single-item validator.\n */\nexport function validateBatchGetPeginStatusResponse(\n  response: unknown,\n): asserts response is BatchGetPeginStatusResponse {\n  validateBatchEnvelope(response, \"batchGetPeginStatus\", (entry) => {\n    if (entry.result !== null) {\n      validateGetPeginStatusResponse(entry.result);\n    }\n  });\n}\n\n/** Validate a `batchGetPegoutStatus` response. Same envelope as peginStatus. */\nexport function validateBatchGetPegoutStatusResponse(\n  response: unknown,\n): asserts response is BatchGetPegoutStatusResponse {\n  validateBatchEnvelope(response, \"batchGetPegoutStatus\", (entry) => {\n    if (entry.result !== null) {\n      validateGetPegoutStatusResponse(entry.result);\n    }\n  });\n}\n\ninterface BatchResultEnvelope {\n  pegin_txid: string;\n  result: unknown;\n  error: string | null;\n}\n\nfunction validateBatchEnvelope(\n  response: unknown,\n  rpcName: string,\n  validateInnerResult: (entry: BatchResultEnvelope, index: number) => void,\n): void {\n  if (response === null || typeof response !== \"object\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: ${rpcName} response is not an object`,\n    );\n  }\n  const r = response as Record<string, unknown>;\n  if (!Array.isArray(r.results)) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"${rpcName}.results\" must be an array, got ${preview(r.results)}`,\n    );\n  }\n  for (let i = 0; i < r.results.length; i++) {\n    const entry = r.results[i];\n    if (entry === null || typeof entry !== \"object\") {\n      throw new VpResponseValidationError(\n        `VP response validation failed: \"${rpcName}.results[${i}]\" must be an object, got ${preview(entry)}`,\n      );\n    }\n    const e = entry as Record<string, unknown>;\n    if (\n      !isNonEmptyHex(e.pegin_txid) ||\n      e.pegin_txid.length !== TXID_HEX_LEN\n    ) {\n      throw new VpResponseValidationError(\n        `VP response validation failed: \"${rpcName}.results[${i}].pegin_txid\" must be a ${TXID_HEX_LEN}-char hex string, got ${preview(e.pegin_txid)}`,\n      );\n    }\n    if (e.error !== null && typeof e.error !== \"string\") {\n      throw new VpResponseValidationError(\n        `VP response validation failed: \"${rpcName}.results[${i}].error\" must be a string or null, got ${preview(e.error)}`,\n      );\n    }\n    // Exactly one of `result` / `error` must be populated. The server only\n    // ever sets one per item; treating both-null as a protocol violation\n    // surfaces server bugs early instead of letting them silently degrade.\n    if (e.result === null && e.error === null) {\n      throw new VpResponseValidationError(\n        `VP response validation failed: \"${rpcName}.results[${i}]\" has neither \"result\" nor \"error\" populated`,\n      );\n    }\n    if (e.result !== null && e.error !== null) {\n      throw new VpResponseValidationError(\n        `VP response validation failed: \"${rpcName}.results[${i}]\" has both \"result\" and \"error\" populated`,\n      );\n    }\n    validateInnerResult(e as unknown as BatchResultEnvelope, i);\n  }\n}\n\nfunction validateDepositorGraphTransactions(\n  graph: Record<string, unknown>,\n): void {\n  validateTransactionData(graph.claim_tx, \"depositor_graph.claim_tx\");\n  validateTransactionData(graph.assert_tx, \"depositor_graph.assert_tx\");\n  validateTransactionData(graph.payout_tx, \"depositor_graph.payout_tx\");\n  assertNonEmptyString(graph.payout_psbt, \"depositor_graph.payout_psbt\");\n\n  if (!Array.isArray(graph.challenger_presign_data)) {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"depositor_graph.challenger_presign_data\" must be an array`,\n    );\n  }\n\n  for (let i = 0; i < graph.challenger_presign_data.length; i++) {\n    validatePresignDataPerChallenger(\n      graph.challenger_presign_data[i],\n      `depositor_graph.challenger_presign_data[${i}]`,\n    );\n  }\n\n  if (typeof graph.offchain_params_version !== \"number\") {\n    throw new VpResponseValidationError(\n      `VP response validation failed: \"depositor_graph.offchain_params_version\" must be a number`,\n    );\n  }\n}\n","/**\n * JSON-RPC client for the Vault Provider API.\n *\n * Wraps {@link JsonRpcClient} with typed methods matching the\n * `vaultProvider_*` RPC namespace defined in the btc-vault pegin spec.\n *\n * Implements the narrow service interfaces (PeginStatusReader, WotsKeySubmitter,\n * PresignClient, ClaimerArtifactsReader) so it can be passed directly to\n * any deposit protocol service function.\n *\n * @see https://github.com/babylonlabs-io/btc-vault/blob/main/docs/pegin.md\n */\n\nimport type { PeginStatusReader, WotsKeySubmitter, PresignClient, ClaimerArtifactsReader } from \"../../services/deposit/interfaces\";\n\nimport {\n  type BearerTokenProvider,\n  JsonRpcClient,\n  type JsonRpcClientConfig,\n} from \"./json-rpc-client\";\nimport type {\n  BatchGetPeginStatusParams,\n  BatchGetPeginStatusResponse,\n  BatchGetPegoutStatusParams,\n  BatchGetPegoutStatusResponse,\n  GetPeginStatusParams,\n  GetPeginStatusResponse,\n  RequestDepositorClaimerArtifactsParams,\n  RequestDepositorClaimerArtifactsResponse,\n  RequestDepositorPresignTransactionsParams,\n  RequestDepositorPresignTransactionsResponse,\n  SubmitDepositorPresignaturesParams,\n  SubmitDepositorWotsKeyParams,\n} from \"./types\";\nimport {\n  validateBatchGetPeginStatusResponse,\n  validateBatchGetPegoutStatusResponse,\n  validateGetPeginStatusResponse,\n  validateRequestDepositorClaimerArtifactsResponse,\n  validateRequestDepositorPresignTransactionsResponse,\n} from \"./validators\";\n\nexport interface VaultProviderRpcClientOptions {\n  /** Timeout in milliseconds per request (default: 60000) */\n  timeout?: number;\n  /** Number of retry attempts for safe methods (default: 3) */\n  retries?: number;\n  /** Initial retry delay in milliseconds (default: 1000) */\n  retryDelay?: number;\n  /**\n   * Custom retry predicate. Default retries only the idempotent read\n   * methods: `getPeginStatus`, `batchGetPeginStatus`, `batchGetPegoutStatus`,\n   * `requestDepositorPresignTransactions`.\n   */\n  retryableFor?: (method: string) => boolean;\n  /** Custom headers. */\n  headers?: Record<string, string>;\n  /**\n   * Per-request bearer-token source. A non-null return attaches\n   * `Authorization: Bearer <token>`; `null` skips auth. Wire a\n   * {@link VpTokenProvider} for depositor-gated methods.\n   */\n  tokenProvider?: BearerTokenProvider;\n  /** Maximum response body size, in bytes, for typed JSON-RPC calls */\n  maxResponseBytes?: number;\n}\n\nconst DEFAULT_TIMEOUT_MS = 60_000;\n\n/**\n * Concrete VP RPC client implementing all service interfaces.\n *\n * Usage:\n * ```ts\n * const client = new VaultProviderRpcClient(\"https://vp.example.com/rpc\");\n * const status = await client.getPeginStatus({ pegin_txid: \"abc...\" });\n * ```\n */\nexport class VaultProviderRpcClient\n  implements PeginStatusReader, WotsKeySubmitter, PresignClient, ClaimerArtifactsReader\n{\n  private client: JsonRpcClient;\n\n  constructor(baseUrl: string, options?: VaultProviderRpcClientOptions) {\n    const config: JsonRpcClientConfig = {\n      baseUrl,\n      timeout: options?.timeout ?? DEFAULT_TIMEOUT_MS,\n      retries: options?.retries,\n      retryDelay: options?.retryDelay,\n      retryableFor: options?.retryableFor,\n      headers: options?.headers,\n      tokenProvider: options?.tokenProvider,\n      maxResponseBytes: options?.maxResponseBytes,\n    };\n    this.client = new JsonRpcClient(config);\n  }\n\n  /**\n   * Request the payout/claim/assert transactions that the depositor\n   * needs to pre-sign before the vault can be activated on Bitcoin.\n   */\n  async requestDepositorPresignTransactions(\n    params: RequestDepositorPresignTransactionsParams,\n    signal?: AbortSignal,\n  ): Promise<RequestDepositorPresignTransactionsResponse> {\n    const response = await this.client.call<\n      RequestDepositorPresignTransactionsParams,\n      unknown\n    >(\"vaultProvider_requestDepositorPresignTransactions\", params, signal);\n    validateRequestDepositorPresignTransactionsResponse(response);\n    return response;\n  }\n\n  /**\n   * Submit the depositor's pre-signatures for the payout transactions\n   * and the depositor-as-claimer graph.\n   */\n  async submitDepositorPresignatures(\n    params: SubmitDepositorPresignaturesParams,\n    signal?: AbortSignal,\n  ): Promise<void> {\n    return this.client.call<SubmitDepositorPresignaturesParams, void>(\n      \"vaultProvider_submitDepositorPresignatures\",\n      params,\n      signal,\n    );\n  }\n\n  /**\n   * Submit the depositor's WOTS public key to the vault provider.\n   * Called after the pegin is finalized on Ethereum, when the VP is in\n   * `PendingDepositorWotsPK` status.\n   */\n  async submitDepositorWotsKey(\n    params: SubmitDepositorWotsKeyParams,\n    signal?: AbortSignal,\n  ): Promise<void> {\n    return this.client.call<SubmitDepositorWotsKeyParams, void>(\n      \"vaultProvider_submitDepositorWotsKey\",\n      params,\n      signal,\n    );\n  }\n\n  /**\n   * Request the BaBe DecryptorArtifacts needed for the depositor to\n   * independently evaluate garbled circuits during a challenge.\n   */\n  async requestDepositorClaimerArtifacts(\n    params: RequestDepositorClaimerArtifactsParams,\n    signal?: AbortSignal,\n  ): Promise<RequestDepositorClaimerArtifactsResponse> {\n    const response = await this.client.call<\n      RequestDepositorClaimerArtifactsParams,\n      unknown\n    >(\"vaultProvider_requestDepositorClaimerArtifacts\", params, signal);\n    validateRequestDepositorClaimerArtifactsResponse(response);\n    return response;\n  }\n\n  /** Get the current pegin status from the vault provider daemon. */\n  async getPeginStatus(\n    params: GetPeginStatusParams,\n    signal?: AbortSignal,\n  ): Promise<GetPeginStatusResponse> {\n    const response = await this.client.call<GetPeginStatusParams, unknown>(\n      \"vaultProvider_getPeginStatus\",\n      params,\n      signal,\n    );\n    validateGetPeginStatusResponse(response);\n    return response;\n  }\n\n  /**\n   * Get pegin status for many txids in one round trip. Per-result envelope\n   * isolates per-pegin failures from the overall RPC. Caller must chunk\n   * inputs at `VP_BATCH_MAX_SIZE`.\n   */\n  async batchGetPeginStatus(\n    params: BatchGetPeginStatusParams,\n    signal?: AbortSignal,\n  ): Promise<BatchGetPeginStatusResponse> {\n    const response = await this.client.call<\n      BatchGetPeginStatusParams,\n      unknown\n    >(\"vaultProvider_batchGetPeginStatus\", params, signal);\n    validateBatchGetPeginStatusResponse(response);\n    return response;\n  }\n\n  /**\n   * Get pegout status for many txids in one round trip. Same per-result\n   * envelope semantics as `batchGetPeginStatus`.\n   */\n  async batchGetPegoutStatus(\n    params: BatchGetPegoutStatusParams,\n    signal?: AbortSignal,\n  ): Promise<BatchGetPegoutStatusResponse> {\n    const response = await this.client.call<\n      BatchGetPegoutStatusParams,\n      unknown\n    >(\"vaultProvider_batchGetPegoutStatus\", params, signal);\n    validateBatchGetPegoutStatusResponse(response);\n    return response;\n  }\n}\n","/**\n * Minimal CBOR encoder for the server-identity payload shape.\n *\n * We only need to encode one specific CBOR structure — the 3-tuple\n * `(SERVER_IDENTITY_DOMAIN, ephemeral_pubkey_bytes, expires_at_u64)` —\n * byte-for-byte identical to what the Rust `ciborium` crate produces\n * for the corresponding tuple, because that's the exact message the\n * VP signs with BIP-322.\n *\n * IMPORTANT encoding quirk: the Rust side passes the domain and\n * pubkey as `&[u8]` / `Vec<u8>` without a `#[serde(with = \"serde_bytes\")]`\n * attribute, so serde/ciborium encodes them as **CBOR arrays of u8**\n * (major type 4, one item per byte) — NOT as CBOR byte strings (major\n * type 2). A naive byte-string encoding would produce the wrong bytes\n * and signature verification would fail.\n *\n * Rather than pull in a full CBOR dependency for this one shape, we\n * implement the exact subset inline (~40 LOC) and pin it with golden\n * vectors against the Rust reference output.\n *\n * @module tbv/core/clients/vault-provider/auth/cbor\n */\n\n/**\n * Encode a small CBOR unsigned-integer \"head\" byte for major type\n * `major` (0..7) with argument `arg` (0..2^64-1).\n *\n * Returns the header bytes; the caller concatenates any trailing data\n * (e.g. array elements). Encoding rules:\n *   arg < 24         → single byte `(major << 5) | arg`\n *   arg < 256        → `(major << 5) | 24` + 1-byte arg\n *   arg < 65536      → `(major << 5) | 25` + 2-byte BE arg\n *   arg < 2^32       → `(major << 5) | 26` + 4-byte BE arg\n *   arg < 2^64       → `(major << 5) | 27` + 8-byte BE arg\n */\nfunction cborHead(major: number, arg: number | bigint): Uint8Array {\n  const tag = (major & 0x07) << 5;\n  const n = typeof arg === \"bigint\" ? arg : BigInt(arg);\n  if (n < 0n) throw new Error(\"cborHead: negative argument\");\n\n  if (n < 24n) return new Uint8Array([tag | Number(n)]);\n  if (n < 0x100n) return new Uint8Array([tag | 24, Number(n)]);\n  if (n < 0x10000n) {\n    const v = Number(n);\n    return new Uint8Array([tag | 25, (v >>> 8) & 0xff, v & 0xff]);\n  }\n  if (n < 0x1_0000_0000n) {\n    const v = Number(n);\n    return new Uint8Array([\n      tag | 26,\n      (v >>> 24) & 0xff,\n      (v >>> 16) & 0xff,\n      (v >>> 8) & 0xff,\n      v & 0xff,\n    ]);\n  }\n  // 8-byte BE for u64 range\n  const out = new Uint8Array(9);\n  out[0] = tag | 27;\n  for (let i = 7; i >= 0; i--) {\n    out[1 + i] = Number(n >> BigInt((7 - i) * 8)) & 0xff;\n  }\n  return out;\n}\n\nfunction concat(...parts: Uint8Array[]): Uint8Array {\n  const total = parts.reduce((s, p) => s + p.length, 0);\n  const out = new Uint8Array(total);\n  let offset = 0;\n  for (const p of parts) {\n    out.set(p, offset);\n    offset += p.length;\n  }\n  return out;\n}\n\n/**\n * Encode a `Vec<u8>` / `&[u8]` the way ciborium does by default — as a\n * CBOR array of u8 (major type 4), one element per byte.\n *\n * Each byte becomes a CBOR unsigned integer (major type 0): bytes\n * < 24 are encoded as single bytes, bytes 24..255 as `0x18 XX`.\n */\nfunction encodeBytesAsArrayOfU8(bytes: Uint8Array): Uint8Array {\n  const header = cborHead(4, bytes.length);\n  const items: Uint8Array[] = [header];\n  for (const b of bytes) {\n    items.push(cborHead(0, b));\n  }\n  return concat(...items);\n}\n\n/**\n * Encode the server-identity payload the Rust side signs:\n *\n *     ciborium::into_writer(\n *       &(SERVER_IDENTITY_DOMAIN, ephemeral_pubkey.serialize().to_vec(), expires_at),\n *       buf\n *     )\n *\n * Output bytes are byte-for-byte identical to the Rust reference,\n * pinned by the golden vector in the corresponding test file.\n *\n * @internal Exposed only for the golden-vector test that pins this\n * encoding against ciborium's output. Production callers reach this\n * via `verifyServerIdentity` from `./serverIdentity`.\n *\n * @param domain - Must be `\"btc-auth.server-identity.v1\"` (27 bytes)\n *                 — the constant from btc-vault's `server_identity.rs`.\n * @param ephemeralPubkeyCompressed - 33-byte SEC1-compressed pubkey.\n * @param expiresAt - Unix timestamp (seconds). Must be a safe integer.\n */\nexport function encodeServerIdentityPayload(\n  domain: Uint8Array,\n  ephemeralPubkeyCompressed: Uint8Array,\n  expiresAt: number,\n): Uint8Array {\n  if (!Number.isSafeInteger(expiresAt) || expiresAt < 0) {\n    throw new Error(\n      `encodeServerIdentityPayload: expires_at must be a non-negative safe integer, got ${expiresAt}`,\n    );\n  }\n  const arrayHeader = cborHead(4, 3); // 3-tuple encoded as array of 3\n  const domainBytes = encodeBytesAsArrayOfU8(domain);\n  const pubkeyBytes = encodeBytesAsArrayOfU8(ephemeralPubkeyCompressed);\n  const expiresAtBytes = cborHead(0, expiresAt);\n  return concat(arrayHeader, domainBytes, pubkeyBytes, expiresAtBytes);\n}\n","/**\n * Server-identity verification for the vault provider's\n * `auth_createDepositorToken` response.\n *\n * The VP returns a `ServerIdentityResponse` bundled with every issued\n * token:\n *\n *   - `server_pubkey`:    VP's persistent x-only pubkey (HEX, 32B)\n *   - `ephemeral_pubkey`: VP's ephemeral token-signing key (HEX, 33B compressed)\n *   - `expires_at`:       Unix timestamp when the ephemeral key expires\n *   - `signature`:        BIP-322 signature by the persistent key over\n *                         `(SERVER_IDENTITY_DOMAIN, ephemeral_pubkey, expires_at)`\n *\n * The FE pins `server_pubkey` against the on-chain `VaultProvider.btcPubKey`\n * it reads from the registry contract. A mismatch rejects the token.\n *\n * @module tbv/core/clients/vault-provider/auth/serverIdentity\n */\n\nimport * as ecc from \"@bitcoin-js/tiny-secp256k1-asmjs\";\n\nimport {\n  COMPRESSED_PUBKEY_HEX_LEN,\n  SCHNORR_SIG_HEX_LEN,\n  stripHexPrefix,\n  X_ONLY_PUBKEY_HEX_LEN,\n} from \"../../../primitives/utils/bitcoin\";\nimport { HEX_RE } from \"../../../utils/validation\";\n\nimport { verifyBip322Simple } from \"./bip322Verify\";\nimport { encodeServerIdentityPayload } from \"./cbor\";\n\n/**\n * Byte-string domain the btc-vault Rust reference passes as the first\n * element of the CBOR tuple signed over for server-identity proofs.\n * Must match `SERVER_IDENTITY_DOMAIN` in\n * `btc-vault/crates/btc-auth/src/server_identity.rs`.\n */\nconst SERVER_IDENTITY_DOMAIN = new TextEncoder().encode(\n  \"btc-auth.server-identity.v1\",\n);\n\n/**\n * Cap on `proof.expires_at - now`. Bounds how long a leaked VP\n * ephemeral key stays usable; the bearer token's own TTL does not\n * (different trust boundary). 2h = Rust ref VP's 1h rotation × 2 for\n * clock skew. Override per call via `maxLifetimeSecs`.\n */\nconst DEFAULT_MAX_PROOF_LIFETIME_SECS = 2 * 3600;\n\n/**\n * Wire representation from btc-vault's `ServerIdentityResponse`.\n */\nexport interface ServerIdentityResponse {\n  /** Hex-encoded x-only (32-byte) persistent server pubkey. */\n  server_pubkey: string;\n  /** Hex-encoded compressed (33-byte) ephemeral token-signing pubkey. */\n  ephemeral_pubkey: string;\n  /** Unix timestamp at which the ephemeral key expires. */\n  expires_at: number;\n  /** Hex-encoded 64-byte BIP-322 Schnorr signature. */\n  signature: string;\n}\n\nexport interface VerifyServerIdentityInput {\n  /** The proof returned by `auth_createDepositorToken`. */\n  proof: ServerIdentityResponse;\n  /**\n   * The x-only persistent server pubkey the FE expects (sourced from\n   * the on-chain `VaultProvider.btcPubKey` via the vault registry\n   * reader). 64-char lowercase hex, no `0x` prefix.\n   */\n  pinnedServerPubkey: string;\n  /** Current Unix timestamp in seconds. Injected for testability. */\n  now: number;\n  /** Cap on `proof.expires_at - now` (seconds). Defaults to {@link DEFAULT_MAX_PROOF_LIFETIME_SECS}. */\n  maxLifetimeSecs?: number;\n}\n\nexport class ServerIdentityError extends Error {\n  constructor(\n    message: string,\n    public readonly reason:\n      | \"pinned_pubkey_mismatch\"\n      | \"expired\"\n      | \"expires_too_far\"\n      | \"invalid_expires_at\"\n      | \"invalid_max_lifetime\"\n      | \"invalid_pubkey_encoding\"\n      | \"invalid_ephemeral_pubkey\"\n      | \"invalid_signature_encoding\"\n      | \"signature_verification_failed\",\n  ) {\n    super(message);\n    this.name = \"ServerIdentityError\";\n  }\n}\n\n/** Parse a lowercase-hex string to bytes. Expects even length, already validated. */\nfunction hexToBytes(hex: string): Uint8Array {\n  const out = new Uint8Array(hex.length / 2);\n  for (let i = 0; i < out.length; i++) {\n    out[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n  }\n  return out;\n}\n\n\n/**\n * Verify a server identity proof against a pinned server pubkey.\n *\n * Checks:\n *   1. `server_pubkey` matches the pin.\n *   2. `now < expires_at <= now + maxLifetimeSecs` (with integer guards).\n *   3. `ephemeral_pubkey` is a well-formed 33-byte compressed pubkey.\n *   4. `signature` is a well-formed 64-byte Schnorr hex string.\n *   5. The BIP-322 Schnorr signature cryptographically verifies\n *      against `server_pubkey` over the CBOR-encoded tuple\n *      `(SERVER_IDENTITY_DOMAIN, ephemeral_pubkey, expires_at)`.\n *\n * Step 5 is what actually binds the ephemeral key to the persistent\n * pubkey — without it, a TLS-MITM attacker who reads the pinned\n * pubkey from the on-chain registry could substitute an arbitrary\n * ephemeral pubkey paired with any lexically-valid signature.\n *\n * @throws ServerIdentityError on any validation failure.\n */\nexport function verifyServerIdentity(input: VerifyServerIdentityInput): void {\n  const { proof, pinnedServerPubkey, now } = input;\n  const maxLifetimeSecs =\n    input.maxLifetimeSecs ?? DEFAULT_MAX_PROOF_LIFETIME_SECS;\n\n  const pinned = stripHexPrefix(pinnedServerPubkey).toLowerCase();\n  if (pinned.length !== X_ONLY_PUBKEY_HEX_LEN || !HEX_RE.test(pinned)) {\n    throw new ServerIdentityError(\n      `pinnedServerPubkey must be 32-byte hex; got ${pinned.length} chars`,\n      \"invalid_pubkey_encoding\",\n    );\n  }\n\n  const actual = stripHexPrefix(proof.server_pubkey).toLowerCase();\n  if (actual.length !== X_ONLY_PUBKEY_HEX_LEN || !HEX_RE.test(actual)) {\n    throw new ServerIdentityError(\n      `server_pubkey must be 32-byte hex; got ${actual.length} chars`,\n      \"invalid_pubkey_encoding\",\n    );\n  }\n\n  if (actual !== pinned) {\n    throw new ServerIdentityError(\n      `server_pubkey does not match pinned value: expected ${pinned}, got ${actual}`,\n      \"pinned_pubkey_mismatch\",\n    );\n  }\n\n  // Validate both sides of the comparison are well-formed integers\n  // BEFORE comparing — untrusted JSON-RPC input can supply\n  // undefined/NaN/string values for `expires_at`, and relational\n  // comparisons with those silently evaluate to `false` (accepting the\n  // proof). Caller's `now` is injected but we still sanity-check it.\n  // Garbage data and \"valid but past\" both render the proof unusable\n  // but mean different things to a caller — keep the reasons distinct.\n  if (!Number.isSafeInteger(proof.expires_at)) {\n    throw new ServerIdentityError(\n      `expires_at must be a finite integer; got ${JSON.stringify(proof.expires_at)}`,\n      \"invalid_expires_at\",\n    );\n  }\n  if (!Number.isSafeInteger(now)) {\n    throw new ServerIdentityError(\n      `now must be a finite integer; got ${JSON.stringify(now)}`,\n      \"invalid_expires_at\",\n    );\n  }\n  if (proof.expires_at <= now) {\n    throw new ServerIdentityError(\n      `server identity proof expired at ${proof.expires_at}, now ${now}`,\n      \"expired\",\n    );\n  }\n  if (!Number.isSafeInteger(maxLifetimeSecs) || maxLifetimeSecs <= 0) {\n    throw new ServerIdentityError(\n      `maxLifetimeSecs must be a positive safe integer; got ${JSON.stringify(maxLifetimeSecs)}`,\n      \"invalid_max_lifetime\",\n    );\n  }\n  if (proof.expires_at - now > maxLifetimeSecs) {\n    throw new ServerIdentityError(\n      `server identity proof expires too far in the future: ` +\n        `expires_at=${proof.expires_at}, now=${now}, max lifetime=${maxLifetimeSecs}s`,\n      \"expires_too_far\",\n    );\n  }\n\n  const eph = stripHexPrefix(proof.ephemeral_pubkey).toLowerCase();\n  if (eph.length !== COMPRESSED_PUBKEY_HEX_LEN || !HEX_RE.test(eph)) {\n    throw new ServerIdentityError(\n      `ephemeral_pubkey must be 33-byte compressed hex; got ${eph.length} chars`,\n      \"invalid_ephemeral_pubkey\",\n    );\n  }\n  const prefix = eph.slice(0, 2);\n  if (prefix !== \"02\" && prefix !== \"03\") {\n    throw new ServerIdentityError(\n      `ephemeral_pubkey must be compressed (prefix 02/03); got ${prefix}`,\n      \"invalid_ephemeral_pubkey\",\n    );\n  }\n  // Curve validation. The BIP-322 signature attests to the byte string\n  // of `ephemeral_pubkey` only, not to its curve validity. Without\n  // this check, a server could sign a structurally-valid byte string\n  // that doesn't decode to a secp256k1 point — passing verification\n  // here and surfacing as an obscure crypto error later when the\n  // depositor tries to use the key. Reject up front.\n  const ephBytes = hexToBytes(eph);\n  if (!ecc.isPoint(ephBytes)) {\n    throw new ServerIdentityError(\n      \"ephemeral_pubkey is not a valid secp256k1 point\",\n      \"invalid_ephemeral_pubkey\",\n    );\n  }\n\n  const sig = stripHexPrefix(proof.signature).toLowerCase();\n  if (sig.length !== SCHNORR_SIG_HEX_LEN || !HEX_RE.test(sig)) {\n    throw new ServerIdentityError(\n      `signature must be 64-byte Schnorr hex; got ${sig.length} chars`,\n      \"invalid_signature_encoding\",\n    );\n  }\n\n  // Cryptographic verification of the BIP-322 signature over the\n  // CBOR-encoded payload. Without this, the ephemeral-key binding is\n  // unenforced and a TLS-MITM could substitute a fake ephemeral key\n  // alongside the real (publicly-readable) pinned pubkey.\n  const payload = encodeServerIdentityPayload(\n    SERVER_IDENTITY_DOMAIN,\n    hexToBytes(eph),\n    proof.expires_at,\n  );\n  const verified = verifyBip322Simple(payload, hexToBytes(actual), hexToBytes(sig));\n  if (!verified) {\n    throw new ServerIdentityError(\n      \"BIP-322 signature verification failed — ephemeral key is not attested by pinned server pubkey\",\n      \"signature_verification_failed\",\n    );\n  }\n}\n","/**\n * VP RPC methods that require `Authorization: Bearer <token>`.\n * Protocol invariant — must be kept in sync with the VP server.\n *\n * Split into two sets by the CWT subject the VP demands:\n *\n * - {@link AUTH_GATED_METHODS} — bearer minted by\n *   `auth_createDepositorToken` (Subject::VaultdJsonRpc). These run\n *   through the proxy's plain JSON-RPC forward path.\n * - {@link GRPC_AUTH_GATED_METHODS} — bearer minted by\n *   `auth_createDepositorTokenGrpc` (Subject::VaultdGrpc). The proxy\n *   translates these into gRPC calls to vaultd's daemon gRPC server,\n *   so a JSON-RPC-subject token would be rejected by\n *   `GrpcAuthInterceptor`.\n *\n * @stability frozen\n *\n * @module tbv/core/clients/vault-provider/auth/gatedMethods\n */\n\nexport const AUTH_GATED_METHODS: ReadonlySet<string> = new Set([\n  \"vaultProvider_submitDepositorWotsKey\",\n  \"vaultProvider_submitDepositorPresignatures\",\n  \"vaultProvider_requestDepositorPresignTransactions\",\n]);\n\nexport const GRPC_AUTH_GATED_METHODS: ReadonlySet<string> = new Set([\n  \"vaultProvider_requestDepositorClaimerArtifacts\",\n]);\n","/**\n * Shared internals for the unauthenticated token-issuing JSON-RPC\n * client. The \"inner\" client is dedicated to `auth_createDepositorToken`\n * — it MUST NOT carry a `tokenProvider`, else the JSON-RPC header\n * builder would recurse into token acquisition.\n *\n * @module tbv/core/clients/vault-provider/auth/innerTokenClient\n */\n\nimport { JsonRpcClient } from \"../json-rpc-client\";\n\nconst TOKEN_RPC_TIMEOUT_MS = 60_000;\n\nexport const TOKEN_ISSUE_METHOD = \"auth_createDepositorToken\";\n/**\n * gRPC-subject sibling of {@link TOKEN_ISSUE_METHOD}. The proxy bridges\n * this call to vaultd's `VaultProviderDepositorAuthService.CreateDepositorToken`\n * so the resulting CWT is bound to `Subject::VaultdGrpc` — required to\n * pass vaultd's `GrpcAuthInterceptor` on methods the proxy translates to\n * gRPC (currently just the artifact stream).\n */\nexport const GRPC_TOKEN_ISSUE_METHOD = \"auth_createDepositorTokenGrpc\";\n\nexport function buildInnerTokenClient(\n  baseUrl: string,\n  headers?: Record<string, string>,\n): JsonRpcClient {\n  return new JsonRpcClient({\n    baseUrl,\n    timeout: TOKEN_RPC_TIMEOUT_MS,\n    headers,\n    retryableFor: (method) =>\n      method === TOKEN_ISSUE_METHOD || method === GRPC_TOKEN_ISSUE_METHOD,\n  });\n}\n","/**\n * Minimal CBOR decoder — the read-side counterpart to {@link ./cbor}.\n *\n * Decodes only the subset needed to verify a vault-provider CWT bearer\n * token (RFC 8392) wrapped in a COSE Sign1 envelope (RFC 8152): tagged\n * values, definite-length arrays and maps, byte/text strings, and\n * unsigned/negative integers. Indefinite-length items, floats, and\n * big-number tags are intentionally rejected — the issuer\n * (btc-vault's `coset`/`ciborium` stack) never emits them for this\n * shape, so accepting them would only widen the parser's attack\n * surface.\n *\n * The decoder is a cursor over a single buffer. {@link CborReader.pos}\n * is public so callers can slice the exact encoded byte range of an\n * item (head + content) — required to reconstruct the COSE\n * `Sig_structure` byte-for-byte from the token's own protected-header\n * and payload byte strings.\n *\n * @module tbv/core/clients/vault-provider/auth/cborDecode\n */\n\n/** CBOR major types (the high 3 bits of the initial byte). */\nconst MAJOR_UNSIGNED_INT = 0;\nconst MAJOR_NEGATIVE_INT = 1;\nconst MAJOR_BYTE_STRING = 2;\nconst MAJOR_TEXT_STRING = 3;\nconst MAJOR_ARRAY = 4;\nconst MAJOR_MAP = 5;\nconst MAJOR_TAG = 6;\nconst MAJOR_SIMPLE = 7;\n\n/**\n * Smallest additional-info value that introduces a multi-byte argument\n * (24 ⇒ 1 byte, 25 ⇒ 2, 26 ⇒ 4, 27 ⇒ 8 — i.e. `1 << (info - 24)`).\n */\nconst ARG_IN_NEXT_1_BYTE = 24;\n/** Additional-info ≥ this (28..31) is reserved/indefinite — unsupported. */\nconst ARG_RESERVED_MIN = 28;\n\n/** Major-7 simple values we accept. */\nconst SIMPLE_FALSE = 20;\nconst SIMPLE_TRUE = 21;\nconst SIMPLE_NULL = 22;\n\n/**\n * Maximum CBOR nesting depth. Mirrors the issuer's recursion cap (256 in\n * btc-vault's `ciborium` stack). The COSE protected header is decoded\n * *before* the signature is verified, so without this bound a\n * malicious/MITM'd VP could send a deeply-nested blob and crash token\n * acquisition with an uncatchable stack overflow. Far below the JS call\n * stack limit, so it converts that DoS into a catchable decode error.\n */\nconst MAX_NESTING_DEPTH = 256;\n\n/** A decoded CBOR data item. Maps preserve key insertion order. */\nexport type CborValue =\n  | number\n  | bigint\n  | string\n  | Uint8Array\n  | boolean\n  | null\n  | CborValue[]\n  | Map<CborValue, CborValue>\n  | CborTagged;\n\n/** A CBOR tagged value (major type 6). */\nexport interface CborTagged {\n  tag: number;\n  value: CborValue;\n}\n\n/** Parsed initial-byte header: major type plus its decoded argument. */\nexport interface CborHead {\n  major: number;\n  /** The header argument (length, value, tag number, …) as a number. */\n  arg: number;\n}\n\nexport class CborDecodeError extends Error {\n  constructor(message: string) {\n    super(`CBOR decode: ${message}`);\n    this.name = \"CborDecodeError\";\n  }\n}\n\n/**\n * Cursor-based reader over a CBOR buffer. Not reusable across buffers —\n * construct one per decode.\n */\nexport class CborReader {\n  readonly buf: Uint8Array;\n  /** Current read offset. Public so callers can slice encoded sub-ranges. */\n  pos = 0;\n\n  constructor(buf: Uint8Array) {\n    this.buf = buf;\n  }\n\n  private nextByte(): number {\n    if (this.pos >= this.buf.length) {\n      throw new CborDecodeError(\"unexpected end of input\");\n    }\n    return this.buf[this.pos++];\n  }\n\n  /**\n   * Read an initial byte and its argument. Rejects indefinite-length\n   * and reserved additional-info encodings. Arguments wider than\n   * {@link Number.MAX_SAFE_INTEGER} are rejected — none of the token's\n   * lengths, tags, or timestamps approach that bound.\n   */\n  readHead(): CborHead {\n    const initial = this.nextByte();\n    const major = initial >> 5;\n    const info = initial & 0x1f;\n\n    if (info < ARG_IN_NEXT_1_BYTE) {\n      return { major, arg: info };\n    }\n    if (info >= ARG_RESERVED_MIN) {\n      throw new CborDecodeError(\n        `unsupported additional info ${info} (indefinite-length or reserved)`,\n      );\n    }\n\n    const byteCount = 1 << (info - ARG_IN_NEXT_1_BYTE);\n\n    let value = 0n;\n    for (let i = 0; i < byteCount; i++) {\n      value = (value << 8n) | BigInt(this.nextByte());\n    }\n    if (value > BigInt(Number.MAX_SAFE_INTEGER)) {\n      throw new CborDecodeError(`argument ${value} exceeds safe integer range`);\n    }\n    return { major, arg: Number(value) };\n  }\n\n  /** Read `length` raw bytes as a sub-array view into the backing buffer. */\n  private readBytes(length: number): Uint8Array {\n    if (this.pos + length > this.buf.length) {\n      throw new CborDecodeError(\"length overruns end of input\");\n    }\n    const slice = this.buf.subarray(this.pos, this.pos + length);\n    this.pos += length;\n    return slice;\n  }\n\n  /**\n   * Read a byte string (major type 2), returning its content bytes.\n   * Throws if the next item is not a byte string.\n   */\n  readByteString(): Uint8Array {\n    const head = this.readHead();\n    if (head.major !== MAJOR_BYTE_STRING) {\n      throw new CborDecodeError(\n        `expected byte string (major ${MAJOR_BYTE_STRING}), got major ${head.major}`,\n      );\n    }\n    return this.readBytes(head.arg);\n  }\n\n  /**\n   * Read the next complete data item as a decoded {@link CborValue}.\n   *\n   * `depth` tracks the current nesting level so a deeply-nested blob is\n   * rejected with a {@link CborDecodeError} rather than overflowing the\n   * native call stack (see {@link MAX_NESTING_DEPTH}).\n   */\n  readValue(depth = 0): CborValue {\n    if (depth > MAX_NESTING_DEPTH) {\n      throw new CborDecodeError(\n        `nesting exceeds maximum depth ${MAX_NESTING_DEPTH}`,\n      );\n    }\n    const head = this.readHead();\n    switch (head.major) {\n      case MAJOR_UNSIGNED_INT:\n        return head.arg;\n      case MAJOR_NEGATIVE_INT:\n        // RFC 8949 §3.1: the encoded argument n represents -1 - n.\n        return -1 - head.arg;\n      case MAJOR_BYTE_STRING:\n        return this.readBytes(head.arg);\n      case MAJOR_TEXT_STRING:\n        return new TextDecoder(\"utf-8\", { fatal: true }).decode(\n          this.readBytes(head.arg),\n        );\n      case MAJOR_ARRAY: {\n        const items: CborValue[] = [];\n        for (let i = 0; i < head.arg; i++) {\n          items.push(this.readValue(depth + 1));\n        }\n        return items;\n      }\n      case MAJOR_MAP: {\n        const map = new Map<CborValue, CborValue>();\n        for (let i = 0; i < head.arg; i++) {\n          const key = this.readValue(depth + 1);\n          const value = this.readValue(depth + 1);\n          map.set(key, value);\n        }\n        return map;\n      }\n      case MAJOR_TAG:\n        return { tag: head.arg, value: this.readValue(depth + 1) };\n      case MAJOR_SIMPLE:\n        if (head.arg === SIMPLE_FALSE) return false;\n        if (head.arg === SIMPLE_TRUE) return true;\n        if (head.arg === SIMPLE_NULL) return null;\n        throw new CborDecodeError(\n          `unsupported simple/float value ${head.arg}`,\n        );\n      default:\n        throw new CborDecodeError(`unsupported major type ${head.major}`);\n    }\n  }\n}\n\n/**\n * Decode a single CBOR item from `bytes`, rejecting any trailing bytes.\n *\n * Used to parse the COSE protected header and CWT claims set — both are\n * exactly one top-level item, so a valid prefix followed by extra bytes\n * is a malformed structure, not a benign tail. Strict consumption keeps\n * the parser from silently accepting a token a stricter CWT/COSE\n * consumer would interpret differently.\n */\nexport function decodeCbor(bytes: Uint8Array): CborValue {\n  const reader = new CborReader(bytes);\n  const value = reader.readValue();\n  if (reader.pos !== bytes.length) {\n    throw new CborDecodeError(\"trailing bytes after top-level item\");\n  }\n  return value;\n}\n","/**\n * Verify a vault-provider CWT bearer (RFC 8392 / COSE Sign1, ES256K): checks the\n * signature against the VP's attested ephemeral key (see {@link ./serverIdentity})\n * and binds `iss`/`sub`/`aud` to the pinned VP, subject, and depositor. TS port\n * of btc-vault `client.rs::validate_token_with_public_key_at_time`.\n *\n * Divergence from that reference: the FE does NOT clock-gate `nbf`/`iat`. The VP\n * server is the temporal authority and re-checks `nbf`/`exp` on every gated call;\n * re-checking `nbf` against the browser clock only bricked freshly minted tokens\n * on benign skew. `exp` (wide window) and the structural `iat <= exp` are kept.\n *\n * @module tbv/core/clients/vault-provider/auth/verifyDepositorCwt\n */\n\nimport * as ecc from \"@bitcoin-js/tiny-secp256k1-asmjs\";\nimport { sha256 } from \"@noble/hashes/sha2.js\";\n\nimport {\n  COMPRESSED_PUBKEY_HEX_LEN,\n  hexToUint8Array,\n  stripHexPrefix,\n  X_ONLY_PUBKEY_HEX_LEN,\n} from \"../../../primitives/utils/bitcoin\";\nimport { HEX_RE } from \"../../../utils/validation\";\n\nimport { CborReader, decodeCbor } from \"./cborDecode\";\n\n/** CWT `sub` value for JSON-RPC-subject tokens (`auth_createDepositorToken`). */\nexport const CWT_SUBJECT_JSONRPC = \"vaultd-jsonrpc\";\n/** CWT `sub` value for gRPC-subject tokens (`auth_createDepositorTokenGrpc`). */\nexport const CWT_SUBJECT_GRPC = \"vaultd-grpc\";\n\n/** CBOR tag wrapping a COSE_Sign1 structure (RFC 8152 §2). */\nconst COSE_SIGN1_TAG = 18;\n/** A COSE_Sign1 is a 4-element array: [protected, unprotected, payload, signature]. */\nconst COSE_SIGN1_ARRAY_LEN = 4;\n/** COSE algorithm id for ES256K (ECDSA w/ secp256k1 + SHA-256), RFC 8812. */\nconst COSE_ALG_ES256K = -47;\n/** COSE header label for the algorithm (RFC 8152 §3.1). */\nconst COSE_HEADER_LABEL_ALG = 1;\n/** ECDSA signature length in COSE compact (r‖s) form. */\nconst ECDSA_COMPACT_SIG_LEN = 64;\n\n/** CBOR major-type 4 (array) high bits, for the Sig_structure header. */\nconst CBOR_ARRAY_HEAD = 0x80;\n/** CBOR major-type 3 (text string) high bits, for the context string head. */\nconst CBOR_TEXT_STRING_HEAD = 0x60;\n/** CBOR encoding of an empty byte string (major type 2, length 0). */\nconst CBOR_EMPTY_BYTE_STRING = 0x40;\n\n/** CWT registered claim keys (RFC 8392 §4 / IANA CWT registry). */\nconst CWT_CLAIM_ISS = 1;\nconst CWT_CLAIM_SUB = 2;\nconst CWT_CLAIM_AUD = 3;\nconst CWT_CLAIM_EXP = 4;\nconst CWT_CLAIM_NBF = 5;\nconst CWT_CLAIM_IAT = 6;\nconst CWT_CLAIM_CTI = 7;\n\n/**\n * Context string for a COSE_Sign1 Sig_structure (RFC 8152 §4.4). 10\n * bytes, so it encodes with a single-byte CBOR text-string head.\n */\nconst SIG_STRUCTURE_CONTEXT = new TextEncoder().encode(\"Signature1\");\n\nexport type CwtVerificationReason =\n  | \"invalid_input\"\n  | \"invalid_token_structure\"\n  | \"unexpected_algorithm\"\n  | \"signature_verification_failed\"\n  | \"invalid_claims\"\n  | \"issuer_mismatch\"\n  | \"subject_mismatch\"\n  | \"audience_mismatch\"\n  | \"token_expired\"\n  | \"expiry_mismatch\"\n  | \"server_identity_expires_before_token\";\n\nexport class CwtVerificationError extends Error {\n  constructor(\n    message: string,\n    public readonly reason: CwtVerificationReason,\n  ) {\n    super(message);\n    this.name = \"CwtVerificationError\";\n  }\n}\n\nexport interface VerifyDepositorCwtInput {\n  /** Base64url (no padding) COSE Sign1 token from `auth_createDepositorToken`. */\n  token: string;\n  /**\n   * VP ephemeral token-signing pubkey (33-byte compressed hex) from the\n   * bundled `server_identity` proof — MUST already be verified by\n   * {@link verifyServerIdentity} before being passed here.\n   */\n  ephemeralPubkeyHex: string;\n  /** Pinned VP persistent x-only pubkey (on-chain). Asserted against the token `iss`. */\n  expectedIssuerXOnlyPubkey: string;\n  /** Expected `sub` — {@link CWT_SUBJECT_JSONRPC} or {@link CWT_SUBJECT_GRPC}. */\n  expectedSubject: string;\n  /** Depositor x-only pubkey. Asserted against the token `aud`. */\n  expectedAudienceXOnlyPubkey: string;\n  /** Outer wire `expires_at`. Must equal the token's `exp` exactly. */\n  responseExpiresAt: number;\n  /** `server_identity.expires_at`. Must be ≥ the token's `exp`. */\n  serverIdentityExpiresAt: number;\n  /** Current Unix time (seconds). Injected for testability. */\n  now: number;\n}\n\nexport interface VerifiedCwtClaims {\n  issuer: string;\n  subject: string;\n  audience: string;\n  expiresAt: number;\n  notBefore: number;\n  issuedAt: number;\n}\n\n/**\n * Verify a depositor CWT and return its claims, or throw\n * {@link CwtVerificationError}.\n *\n * Steps (mirroring the Rust reference; see the divergence note above):\n *   1. Decode the COSE Sign1 envelope and assert the protected header\n *      pins ES256K.\n *   2. Verify the ECDSA signature over the reconstructed Sig_structure\n *      against the (already server-identity-verified) ephemeral key.\n *   3. Decode the CWT claims and assert `iss`/`sub`/`aud` bindings, the\n *      structural `iat <= exp`, `exp` validity, `cti` presence, and the\n *      outer-vs-inner expiry cross-checks. `nbf`/`iat` are intentionally not\n *      clock-gated here (see the module note above).\n */\nexport function verifyDepositorCwt(\n  input: VerifyDepositorCwtInput,\n): VerifiedCwtClaims {\n  const expectedIssuer = normalizeXOnly(\n    input.expectedIssuerXOnlyPubkey,\n    \"expectedIssuerXOnlyPubkey\",\n  );\n  const expectedAudience = normalizeXOnly(\n    input.expectedAudienceXOnlyPubkey,\n    \"expectedAudienceXOnlyPubkey\",\n  );\n  const ephemeral = decodeCompressedPubkey(input.ephemeralPubkeyHex);\n\n  const tokenBytes = base64UrlToBytes(input.token);\n\n  // --- 1. COSE Sign1 structural decode -------------------------------\n  // Capture the exact encoded byte ranges of the protected header and\n  // payload so the Sig_structure can be rebuilt byte-for-byte from the\n  // token's own bytes (any re-encoding risks a non-canonical mismatch).\n  const reader = new CborReader(tokenBytes);\n  const tag = reader.readHead();\n  if (tag.major !== 6 || tag.arg !== COSE_SIGN1_TAG) {\n    throw new CwtVerificationError(\n      `token is not a COSE Sign1 tagged value (tag ${COSE_SIGN1_TAG})`,\n      \"invalid_token_structure\",\n    );\n  }\n  const array = reader.readHead();\n  if (array.major !== 4 || array.arg !== COSE_SIGN1_ARRAY_LEN) {\n    throw new CwtVerificationError(\n      `COSE Sign1 must be a ${COSE_SIGN1_ARRAY_LEN}-element array`,\n      \"invalid_token_structure\",\n    );\n  }\n\n  const protectedStart = reader.pos;\n  const protectedContent = reader.readByteString();\n  const protectedBstr = tokenBytes.subarray(protectedStart, reader.pos);\n\n  // Unprotected header map: present in the envelope but unused here.\n  reader.readValue();\n\n  const payloadStart = reader.pos;\n  const payloadContent = reader.readByteString();\n  const payloadBstr = tokenBytes.subarray(payloadStart, reader.pos);\n\n  const signature = reader.readByteString();\n  if (signature.length !== ECDSA_COMPACT_SIG_LEN) {\n    throw new CwtVerificationError(\n      `COSE signature must be ${ECDSA_COMPACT_SIG_LEN} bytes, got ${signature.length}`,\n      \"invalid_token_structure\",\n    );\n  }\n  // Reject anything after the COSE_Sign1 structure. The bearer we verify\n  // must be the exact bytes attached to authenticated calls; a stricter\n  // CWT/COSE consumer could interpret trailing bytes differently.\n  if (reader.pos !== tokenBytes.length) {\n    throw new CwtVerificationError(\n      \"COSE Sign1 token has trailing bytes after the signature\",\n      \"invalid_token_structure\",\n    );\n  }\n\n  // --- 2a. Algorithm pin --------------------------------------------\n  const alg = readProtectedAlgorithm(protectedContent);\n  if (alg !== COSE_ALG_ES256K) {\n    throw new CwtVerificationError(\n      `unexpected COSE algorithm ${alg} (expected ES256K ${COSE_ALG_ES256K})`,\n      \"unexpected_algorithm\",\n    );\n  }\n\n  // --- 2b. Signature verification -----------------------------------\n  const sigStructure = buildSigStructure(protectedBstr, payloadBstr);\n  const digest = sha256(sigStructure);\n  // strict = true enforces low-S, matching libsecp256k1's `verify_ecdsa`.\n  if (!ecc.verify(digest, ephemeral, signature, true)) {\n    throw new CwtVerificationError(\n      \"COSE signature does not verify against the server's ephemeral key\",\n      \"signature_verification_failed\",\n    );\n  }\n\n  // --- 3. Claims -----------------------------------------------------\n  const claims = decodeClaims(payloadContent);\n\n  const audience = claims.audience.toLowerCase();\n  if (audience.length !== X_ONLY_PUBKEY_HEX_LEN || !HEX_RE.test(audience)) {\n    throw new CwtVerificationError(\n      \"token `aud` is not a 32-byte x-only pubkey hex\",\n      \"invalid_claims\",\n    );\n  }\n  if (claims.issuedAt > claims.expiresAt) {\n    throw new CwtVerificationError(\n      `token iat (${claims.issuedAt}) is after exp (${claims.expiresAt})`,\n      \"invalid_claims\",\n    );\n  }\n\n  if (claims.issuer.toLowerCase() !== expectedIssuer) {\n    throw new CwtVerificationError(\n      `token issuer does not match pinned server pubkey: expected ${expectedIssuer}, got ${claims.issuer.toLowerCase()}`,\n      \"issuer_mismatch\",\n    );\n  }\n  if (claims.subject !== input.expectedSubject) {\n    throw new CwtVerificationError(\n      `token subject mismatch: expected ${input.expectedSubject}, got ${claims.subject}`,\n      \"subject_mismatch\",\n    );\n  }\n  if (audience !== expectedAudience) {\n    throw new CwtVerificationError(\n      `token audience does not match depositor pubkey: expected ${expectedAudience}, got ${audience}`,\n      \"audience_mismatch\",\n    );\n  }\n  // No nbf/iat clock-gate on purpose — the VP server is the temporal authority\n  // (re-checks nbf/exp per call). See the module-level divergence note.\n  if (claims.expiresAt <= input.now) {\n    throw new CwtVerificationError(\n      `token expired: exp ${claims.expiresAt} <= now ${input.now}`,\n      \"token_expired\",\n    );\n  }\n  if (input.responseExpiresAt !== claims.expiresAt) {\n    throw new CwtVerificationError(\n      `response expires_at (${input.responseExpiresAt}) does not equal token exp (${claims.expiresAt})`,\n      \"expiry_mismatch\",\n    );\n  }\n  if (input.serverIdentityExpiresAt < claims.expiresAt) {\n    throw new CwtVerificationError(\n      `server identity expires (${input.serverIdentityExpiresAt}) before token exp (${claims.expiresAt})`,\n      \"server_identity_expires_before_token\",\n    );\n  }\n\n  return {\n    issuer: claims.issuer,\n    subject: claims.subject,\n    audience,\n    expiresAt: claims.expiresAt,\n    notBefore: claims.notBefore,\n    issuedAt: claims.issuedAt,\n  };\n}\n\n/** Read the algorithm label from the COSE protected-header byte string. */\nfunction readProtectedAlgorithm(protectedContent: Uint8Array): number {\n  if (protectedContent.length === 0) {\n    throw new CwtVerificationError(\n      \"empty COSE protected header (no algorithm)\",\n      \"unexpected_algorithm\",\n    );\n  }\n  const header = decodeCbor(protectedContent);\n  if (!(header instanceof Map)) {\n    throw new CwtVerificationError(\n      \"COSE protected header is not a map\",\n      \"invalid_token_structure\",\n    );\n  }\n  const alg = header.get(COSE_HEADER_LABEL_ALG);\n  if (typeof alg !== \"number\") {\n    throw new CwtVerificationError(\n      \"COSE protected header missing integer algorithm label\",\n      \"unexpected_algorithm\",\n    );\n  }\n  return alg;\n}\n\n/**\n * Rebuild the COSE_Sign1 Sig_structure (RFC 8152 §4.4):\n *\n *   [ \"Signature1\", body_protected (bstr), external_aad = h'' , payload (bstr) ]\n *\n * `body_protected` and `payload` are spliced verbatim from the token's\n * own encoded byte strings, so the result is byte-identical to what the\n * issuer signed regardless of CBOR canonicalization choices.\n */\nfunction buildSigStructure(\n  protectedBstr: Uint8Array,\n  payloadBstr: Uint8Array,\n): Uint8Array {\n  return concatBytes(\n    Uint8Array.of(CBOR_ARRAY_HEAD | COSE_SIGN1_ARRAY_LEN),\n    Uint8Array.of(CBOR_TEXT_STRING_HEAD | SIG_STRUCTURE_CONTEXT.length),\n    SIG_STRUCTURE_CONTEXT,\n    protectedBstr,\n    Uint8Array.of(CBOR_EMPTY_BYTE_STRING),\n    payloadBstr,\n  );\n}\n\ninterface DecodedClaims {\n  issuer: string;\n  subject: string;\n  audience: string;\n  expiresAt: number;\n  notBefore: number;\n  issuedAt: number;\n}\n\n/** Decode and type-check the CWT registered claims from the payload. */\nfunction decodeClaims(payloadContent: Uint8Array): DecodedClaims {\n  const root = decodeCbor(payloadContent);\n  if (!(root instanceof Map)) {\n    throw new CwtVerificationError(\n      \"CWT claims root is not a map\",\n      \"invalid_claims\",\n    );\n  }\n  const cti = requireBytes(root, CWT_CLAIM_CTI, \"cti\");\n  if (cti.length === 0) {\n    throw new CwtVerificationError(\"token cti is empty\", \"invalid_claims\");\n  }\n  return {\n    issuer: requireString(root, CWT_CLAIM_ISS, \"iss\"),\n    subject: requireString(root, CWT_CLAIM_SUB, \"sub\"),\n    audience: requireString(root, CWT_CLAIM_AUD, \"aud\"),\n    expiresAt: requireTimestamp(root, CWT_CLAIM_EXP, \"exp\"),\n    notBefore: requireTimestamp(root, CWT_CLAIM_NBF, \"nbf\"),\n    issuedAt: requireTimestamp(root, CWT_CLAIM_IAT, \"iat\"),\n  };\n}\n\nfunction requireString(\n  claims: Map<unknown, unknown>,\n  key: number,\n  name: string,\n): string {\n  const value = claims.get(key);\n  if (typeof value !== \"string\") {\n    throw new CwtVerificationError(\n      `token claim ${name} is missing or not a text string`,\n      \"invalid_claims\",\n    );\n  }\n  return value;\n}\n\nfunction requireBytes(\n  claims: Map<unknown, unknown>,\n  key: number,\n  name: string,\n): Uint8Array {\n  const value = claims.get(key);\n  if (!(value instanceof Uint8Array)) {\n    throw new CwtVerificationError(\n      `token claim ${name} is missing or not a byte string`,\n      \"invalid_claims\",\n    );\n  }\n  return value;\n}\n\nfunction requireTimestamp(\n  claims: Map<unknown, unknown>,\n  key: number,\n  name: string,\n): number {\n  const value = claims.get(key);\n  if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < 0) {\n    throw new CwtVerificationError(\n      `token claim ${name} is missing or not a non-negative integer timestamp`,\n      \"invalid_claims\",\n    );\n  }\n  return value;\n}\n\n/** Validate and normalize a 32-byte x-only pubkey to lowercase hex. */\nfunction normalizeXOnly(pubkey: string, label: string): string {\n  const normalized = stripHexPrefix(pubkey).toLowerCase();\n  if (normalized.length !== X_ONLY_PUBKEY_HEX_LEN || !HEX_RE.test(normalized)) {\n    throw new CwtVerificationError(\n      `${label} must be 32-byte x-only hex; got ${normalized.length} chars`,\n      \"invalid_input\",\n    );\n  }\n  return normalized;\n}\n\n/** Validate a 33-byte compressed pubkey hex and return its bytes. */\nfunction decodeCompressedPubkey(pubkeyHex: string): Uint8Array {\n  const normalized = stripHexPrefix(pubkeyHex).toLowerCase();\n  const prefix = normalized.slice(0, 2);\n  if (\n    normalized.length !== COMPRESSED_PUBKEY_HEX_LEN ||\n    !HEX_RE.test(normalized) ||\n    (prefix !== \"02\" && prefix !== \"03\")\n  ) {\n    throw new CwtVerificationError(\n      \"ephemeralPubkeyHex must be 33-byte compressed pubkey hex (prefix 02/03)\",\n      \"invalid_input\",\n    );\n  }\n  return hexToUint8Array(normalized);\n}\n\nconst B64URL_LOOKUP = (() => {\n  const table = new Int16Array(128).fill(-1);\n  const alphabet =\n    \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";\n  for (let i = 0; i < alphabet.length; i++) {\n    table[alphabet.charCodeAt(i)] = i;\n  }\n  return table;\n})();\n\n/** Decode a base64url (no-padding) string to bytes. */\nfunction base64UrlToBytes(input: string): Uint8Array {\n  const len = input.length;\n  const fullGroups = Math.floor(len / 4);\n  const remainder = len % 4;\n  if (remainder === 1) {\n    throw new CwtVerificationError(\n      \"invalid base64url length\",\n      \"invalid_token_structure\",\n    );\n  }\n  const outLen = fullGroups * 3 + (remainder === 0 ? 0 : remainder - 1);\n  const out = new Uint8Array(outLen);\n\n  const sextet = (charCode: number): number => {\n    const value = charCode < 128 ? B64URL_LOOKUP[charCode] : -1;\n    if (value < 0) {\n      throw new CwtVerificationError(\n        \"invalid base64url character\",\n        \"invalid_token_structure\",\n      );\n    }\n    return value;\n  };\n\n  let inPos = 0;\n  let outPos = 0;\n  for (let g = 0; g < fullGroups; g++) {\n    const a = sextet(input.charCodeAt(inPos++));\n    const b = sextet(input.charCodeAt(inPos++));\n    const c = sextet(input.charCodeAt(inPos++));\n    const d = sextet(input.charCodeAt(inPos++));\n    out[outPos++] = (a << 2) | (b >> 4);\n    out[outPos++] = ((b & 0x0f) << 4) | (c >> 2);\n    out[outPos++] = ((c & 0x03) << 6) | d;\n  }\n  if (remainder === 2) {\n    const a = sextet(input.charCodeAt(inPos++));\n    const b = sextet(input.charCodeAt(inPos++));\n    out[outPos++] = (a << 2) | (b >> 4);\n  } else if (remainder === 3) {\n    const a = sextet(input.charCodeAt(inPos++));\n    const b = sextet(input.charCodeAt(inPos++));\n    const c = sextet(input.charCodeAt(inPos++));\n    out[outPos++] = (a << 2) | (b >> 4);\n    out[outPos++] = ((b & 0x0f) << 4) | (c >> 2);\n  }\n  return out;\n}\n\nfunction concatBytes(...parts: Uint8Array[]): Uint8Array {\n  const total = parts.reduce((sum, part) => sum + part.length, 0);\n  const out = new Uint8Array(total);\n  let offset = 0;\n  for (const part of parts) {\n    out.set(part, offset);\n    offset += part.length;\n  }\n  return out;\n}\n","/**\n * `VpTokenProvider` — caches CWT bearer tokens issued by the vault\n * provider's `auth_createDepositorToken` RPC, with lazy expiry check\n * and single-flight concurrent acquire.\n *\n * Usage:\n *\n * ```ts\n * const provider = new VpTokenProvider({\n *   client,\n *   peginTxid,\n *   authAnchorHex,\n *   pinnedServerPubkey,\n *   authGatedMethods,\n * });\n * const bearer = await provider.getToken(method); // null if not gated\n * ```\n *\n * The provider implements the `BearerTokenProvider` interface expected\n * by `JsonRpcClient`. Plug directly:\n *\n * ```ts\n * const client = new JsonRpcClient({ ..., tokenProvider: provider });\n * ```\n *\n * @module tbv/core/clients/vault-provider/auth/tokenProvider\n */\n\nimport type { OnChainBtcPubkey } from \"../../eth/types\";\nimport type { BearerTokenProvider, JsonRpcClient } from \"../json-rpc-client\";\nimport {\n  GRPC_TOKEN_ISSUE_METHOD,\n  TOKEN_ISSUE_METHOD,\n} from \"./innerTokenClient\";\nimport {\n  type ServerIdentityResponse,\n  verifyServerIdentity,\n} from \"./serverIdentity\";\nimport {\n  CWT_SUBJECT_GRPC,\n  CWT_SUBJECT_JSONRPC,\n  verifyDepositorCwt,\n} from \"./verifyDepositorCwt\";\n\n/**\n * Maximum reasonable `expires_at` value (seconds since epoch). Guards\n * against a bogus far-future timestamp that would lock the cache on a\n * bad token forever. Jan 1, 2100 in Unix seconds.\n */\nconst MAX_EXPIRES_AT_SECS = 4_102_444_800;\n\n/**\n * Default safety margin before `expires_at` — we treat a token as\n * expired this many seconds before its stated expiry so that in-flight\n * requests don't race the expiry boundary.\n */\nconst DEFAULT_REFRESH_SKEW_SECS = 30;\n\n/**\n * Wire response shape of `auth_createDepositorToken`.\n */\nexport interface CreateDepositorTokenResponse {\n  /** Base64url-encoded COSE Sign1 CWT bearer token. */\n  token: string;\n  /** Unix timestamp at which the token expires. */\n  expires_at: number;\n  /** Server identity proof bundled with every token response. */\n  server_identity: ServerIdentityResponse;\n}\n\nexport interface VpTokenProviderConfig {\n  client: JsonRpcClient;\n  /** Per-vault depositor-signed PegIn tx id. NOT shared across sibling vaults in a batch. */\n  peginTxid: string;\n  /** 64-char hex of the 32-byte OP_RETURN auth-anchor preimage. */\n  authAnchorHex: string;\n  /** Pinned VP pubkey from the on-chain registry; branded so indexer mirrors can't substitute. */\n  pinnedServerPubkey: OnChainBtcPubkey;\n  /**\n   * Depositor x-only pubkey (32-byte hex). Asserted against every\n   * issued token's CWT `aud` claim so a token minted for a different\n   * depositor — or mis-issued by a buggy/compromised VP — is rejected\n   * before it can authenticate a mutation.\n   */\n  expectedAudienceXOnlyPubkey: string;\n  /**\n   * Methods that need a JSON-RPC-subject bearer (minted via\n   * `auth_createDepositorToken`). Forwarded over plain HTTP JSON-RPC by\n   * the proxy. `getToken` returns `null` for any method outside this and\n   * {@link grpcGatedMethods}.\n   */\n  authGatedMethods: ReadonlySet<string>;\n  /**\n   * Methods that need a gRPC-subject bearer (minted via\n   * `auth_createDepositorTokenGrpc`). The proxy translates these into\n   * gRPC calls to vaultd; the JSON-RPC bearer is rejected with a\n   * `Subject` mismatch.\n   */\n  grpcGatedMethods: ReadonlySet<string>;\n  /** Default {@link DEFAULT_REFRESH_SKEW_SECS}. */\n  refreshSkewSecs?: number;\n  /** Clock source for testability. */\n  now?: () => number;\n}\n\ninterface CachedToken {\n  token: string;\n  expiresAt: number;\n}\n\n/**\n * Acquire, cache, and refresh VP bearer tokens.\n *\n * Implements {@link BearerTokenProvider}. Safe to pass directly into\n * `JsonRpcClient` as `tokenProvider`.\n */\nexport class VpTokenProvider implements BearerTokenProvider {\n  // `client` is the only mutable field — see `setClient`. The\n  // identity-bearing fields (peginTxid/authAnchorHex/pinnedServerPubkey)\n  // remain readonly and are checked against re-registration in the\n  // registry's `getOrCreate`.\n  private client: JsonRpcClient;\n  private readonly peginTxid: string;\n  private readonly authAnchorHex: string;\n  private readonly pinnedServerPubkey: OnChainBtcPubkey;\n  private readonly expectedAudienceXOnlyPubkey: string;\n  private readonly authGatedMethods: ReadonlySet<string>;\n  private readonly grpcGatedMethods: ReadonlySet<string>;\n  private readonly refreshSkewSecs: number;\n  private readonly now: () => number;\n\n  /** Cached JSON-RPC-subject bearer (auth_createDepositorToken). */\n  private cachedJsonRpc: CachedToken | null = null;\n  private inFlightJsonRpc: Promise<CachedToken> | null = null;\n  /** Cached gRPC-subject bearer (auth_createDepositorTokenGrpc). */\n  private cachedGrpc: CachedToken | null = null;\n  private inFlightGrpc: Promise<CachedToken> | null = null;\n\n  constructor(config: VpTokenProviderConfig) {\n    this.client = config.client;\n    this.peginTxid = config.peginTxid;\n    this.authAnchorHex = config.authAnchorHex;\n    this.pinnedServerPubkey = config.pinnedServerPubkey;\n    this.expectedAudienceXOnlyPubkey = config.expectedAudienceXOnlyPubkey;\n    this.authGatedMethods = config.authGatedMethods;\n    this.grpcGatedMethods = config.grpcGatedMethods;\n    this.refreshSkewSecs = config.refreshSkewSecs ?? DEFAULT_REFRESH_SKEW_SECS;\n    this.now = config.now ?? (() => Math.floor(Date.now() / 1000));\n  }\n\n  /**\n   * Return a bearer token for `method`, or `null` if `method` is not\n   * auth-gated.\n   *\n   * Routes by subject: `authGatedMethods` → JSON-RPC bearer (issued via\n   * `auth_createDepositorToken`); `grpcGatedMethods` → gRPC bearer\n   * (`auth_createDepositorTokenGrpc`). Either path acquires lazily and\n   * single-flights concurrent callers; the two cache slots are\n   * independent.\n   *\n   * Both token-issuing methods are hard-exempted from the gate — if\n   * either were ever included in the gated sets (caller misconfiguration)\n   * the provider would recurse into `acquireSingleFlight` from inside the\n   * JSON-RPC header builder before `inFlight` is assigned, defeating the\n   * single-flight guard. Returning `null` here breaks that recursion\n   * deterministically.\n   */\n  async getToken(method: string): Promise<string | null> {\n    if (method === TOKEN_ISSUE_METHOD || method === GRPC_TOKEN_ISSUE_METHOD) {\n      return null;\n    }\n\n    if (this.grpcGatedMethods.has(method)) {\n      return this.getTokenForSubject(\"grpc\");\n    }\n    if (this.authGatedMethods.has(method)) {\n      return this.getTokenForSubject(\"jsonrpc\");\n    }\n    return null;\n  }\n\n  /**\n   * Drop both cached tokens. Next `getToken` call re-acquires the slot\n   * that's actually needed. Called by `JsonRpcClient` on wire\n   * `auth_expired` responses; the client doesn't tell us which subject\n   * expired, so we evict both to stay correct under either.\n   *\n   * Worst case is one extra round-trip on the slot that was still fresh,\n   * which is cheaper than carrying a `Subject` argument through\n   * `BearerTokenProvider`.\n   */\n  invalidate(): void {\n    this.cachedJsonRpc = null;\n    this.cachedGrpc = null;\n    // Do NOT clear `inFlight*` — a concurrent acquire is still valid;\n    // the invalidator is saying \"the cached token is bad\", not \"any\n    // in-flight acquire is bad\". The in-flight acquire will populate\n    // a fresh `cached*` on completion.\n  }\n\n  private async getTokenForSubject(\n    subject: \"jsonrpc\" | \"grpc\",\n  ): Promise<string> {\n    const cached =\n      subject === \"grpc\" ? this.cachedGrpc : this.cachedJsonRpc;\n    if (cached && this.now() + this.refreshSkewSecs < cached.expiresAt) {\n      return cached.token;\n    }\n    const fresh = await this.acquireSingleFlight(subject);\n    return fresh.token;\n  }\n\n  /**\n   * Swap in a different transport for subsequent token-issuing calls.\n   * Used by the registry when a later caller registers the same\n   * `peginTxid` against a different `baseUrl` — the cached token\n   * (bound to identity, not transport) stays valid, but future\n   * refreshes hit the new URL. An in-flight acquire keeps using the\n   * old client (it captured the reference); next call uses the new.\n   */\n  setClient(client: JsonRpcClient): void {\n    this.client = client;\n  }\n\n  private acquireSingleFlight(\n    subject: \"jsonrpc\" | \"grpc\",\n  ): Promise<CachedToken> {\n    const existing =\n      subject === \"grpc\" ? this.inFlightGrpc : this.inFlightJsonRpc;\n    if (existing) return existing;\n\n    const issueMethod =\n      subject === \"grpc\" ? GRPC_TOKEN_ISSUE_METHOD : TOKEN_ISSUE_METHOD;\n\n    const p = (async () => {\n      try {\n        const response = await this.client.call<\n          { pegin_txid: string; auth_anchor: string },\n          CreateDepositorTokenResponse\n        >(issueMethod, {\n          pegin_txid: this.peginTxid,\n          auth_anchor: this.authAnchorHex,\n        });\n\n        verifyServerIdentity({\n          proof: response.server_identity,\n          pinnedServerPubkey: this.pinnedServerPubkey,\n          now: this.now(),\n        });\n\n        // Validate wire payload before caching so a malformed response\n        // from a compromised VP or proxy can't poison the cache with\n        // unusable values (non-string token, non-integer expiry, etc.).\n        if (typeof response.token !== \"string\" || response.token.length === 0) {\n          throw new Error(\n            `VpTokenProvider: invalid token in acquire response (expected non-empty string, got ${typeof response.token})`,\n          );\n        }\n        const now = this.now();\n        if (\n          !Number.isSafeInteger(response.expires_at) ||\n          response.expires_at <= now ||\n          response.expires_at > MAX_EXPIRES_AT_SECS\n        ) {\n          throw new Error(\n            `VpTokenProvider: invalid expires_at in acquire response (got ${JSON.stringify(response.expires_at)}; must be a safe integer in (${now}, ${MAX_EXPIRES_AT_SECS}])`,\n          );\n        }\n\n        // Cryptographically verify the token itself — not just the wire\n        // envelope. The COSE Sign1 signature is checked against the\n        // (server-identity-verified) ephemeral key, and the inner CWT\n        // claims are bound to this depositor (`aud`), this VP (`iss`),\n        // and this subject. Without this the bearer is an opaque blob the\n        // FE would attach to mutations on the VP's word alone.\n        verifyDepositorCwt({\n          token: response.token,\n          ephemeralPubkeyHex: response.server_identity.ephemeral_pubkey,\n          expectedIssuerXOnlyPubkey: this.pinnedServerPubkey,\n          expectedSubject:\n            subject === \"grpc\" ? CWT_SUBJECT_GRPC : CWT_SUBJECT_JSONRPC,\n          expectedAudienceXOnlyPubkey: this.expectedAudienceXOnlyPubkey,\n          responseExpiresAt: response.expires_at,\n          serverIdentityExpiresAt: response.server_identity.expires_at,\n          now,\n        });\n\n        const fresh: CachedToken = {\n          token: response.token,\n          expiresAt: response.expires_at,\n        };\n        if (subject === \"grpc\") {\n          this.cachedGrpc = fresh;\n        } else {\n          this.cachedJsonRpc = fresh;\n        }\n        return fresh;\n      } finally {\n        if (subject === \"grpc\") {\n          this.inFlightGrpc = null;\n        } else {\n          this.inFlightJsonRpc = null;\n        }\n      }\n    })();\n\n    if (subject === \"grpc\") {\n      this.inFlightGrpc = p;\n    } else {\n      this.inFlightJsonRpc = p;\n    }\n    return p;\n  }\n}\n","/**\n * In-memory registry of {@link VpTokenProvider} instances keyed by\n * the per-vault depositor-signed PegIn tx hash. Module-level\n * singleton, per-tab, never persisted.\n *\n * @module tbv/core/clients/vault-provider/auth/tokenRegistry\n */\n\nimport type { OnChainBtcPubkey } from \"../../eth/types\";\nimport type { JsonRpcClient } from \"../json-rpc-client\";\n\nimport { AUTH_GATED_METHODS, GRPC_AUTH_GATED_METHODS } from \"./gatedMethods\";\nimport { VpTokenProvider } from \"./tokenProvider\";\n\nexport interface VpTokenRegistryInput {\n  client: JsonRpcClient;\n  peginTxid: string;\n  authAnchorHex: string;\n  pinnedServerPubkey: OnChainBtcPubkey;\n  /** Depositor x-only pubkey (32-byte hex), asserted against each token's CWT `aud`. */\n  expectedAudienceXOnlyPubkey: string;\n}\n\ninterface RegistryEntry {\n  provider: VpTokenProvider;\n  authAnchorHex: string;\n  pinnedServerPubkey: OnChainBtcPubkey;\n  expectedAudienceXOnlyPubkey: string;\n}\n\nexport class VpTokenRegistry {\n  private readonly entries = new Map<string, RegistryEntry>();\n\n  /**\n   * Return the cached `VpTokenProvider` for `peginTxid` if one exists\n   * with matching `authAnchorHex` and `pinnedServerPubkey`, otherwise\n   * construct and cache a fresh provider. A mismatch on either throws —\n   * silent overwrite would mask derivation drift or VP pubkey rotation.\n   */\n  getOrCreate(input: VpTokenRegistryInput): VpTokenProvider {\n    const existing = this.entries.get(input.peginTxid);\n    if (existing) {\n      if (existing.authAnchorHex !== input.authAnchorHex) {\n        throw new Error(\n          `VpTokenRegistry: peginTxid ${input.peginTxid} already bound to authAnchorHex ${existing.authAnchorHex.slice(0, 8)}…; got ${input.authAnchorHex.slice(0, 8)}…`,\n        );\n      }\n      if (existing.pinnedServerPubkey !== input.pinnedServerPubkey) {\n        throw new Error(\n          `VpTokenRegistry: peginTxid ${input.peginTxid} already bound to pinnedServerPubkey ${existing.pinnedServerPubkey.slice(0, 8)}…; got ${input.pinnedServerPubkey.slice(0, 8)}…`,\n        );\n      }\n      if (\n        existing.expectedAudienceXOnlyPubkey !==\n        input.expectedAudienceXOnlyPubkey\n      ) {\n        throw new Error(\n          `VpTokenRegistry: peginTxid ${input.peginTxid} already bound to expectedAudienceXOnlyPubkey ${existing.expectedAudienceXOnlyPubkey.slice(0, 8)}…; got ${input.expectedAudienceXOnlyPubkey.slice(0, 8)}…`,\n        );\n      }\n      // Refresh the inner transport on every reuse so a VP URL\n      // change between calls doesn't leave the cached provider\n      // pinned to a dead URL for token refresh.\n      existing.provider.setClient(input.client);\n      return existing.provider;\n    }\n\n    const provider = new VpTokenProvider({\n      client: input.client,\n      peginTxid: input.peginTxid,\n      authAnchorHex: input.authAnchorHex,\n      pinnedServerPubkey: input.pinnedServerPubkey,\n      expectedAudienceXOnlyPubkey: input.expectedAudienceXOnlyPubkey,\n      authGatedMethods: AUTH_GATED_METHODS,\n      grpcGatedMethods: GRPC_AUTH_GATED_METHODS,\n    });\n    this.entries.set(input.peginTxid, {\n      provider,\n      authAnchorHex: input.authAnchorHex,\n      pinnedServerPubkey: input.pinnedServerPubkey,\n      expectedAudienceXOnlyPubkey: input.expectedAudienceXOnlyPubkey,\n    });\n    return provider;\n  }\n\n  /** Return the cached provider, or `undefined` if none. */\n  peek(peginTxid: string): VpTokenProvider | undefined {\n    return this.entries.get(peginTxid)?.provider;\n  }\n\n  /**\n   * Evict the entry for `peginTxid`. Idempotent. Called on terminal\n   * paths — activation success, user-cancel, or component unmount —\n   * so `authAnchorHex` doesn't outlive the deposit session.\n   */\n  release(peginTxid: string): void {\n    this.entries.delete(peginTxid);\n  }\n\n  /**\n   * Wipe every cached entry. Test-only escape hatch — not exposed on\n   * the public {@link VpTokenRegistryPublic} singleton type.\n   *\n   * @internal\n   */\n  clear(): void {\n    this.entries.clear();\n  }\n\n  get size(): number {\n    return this.entries.size;\n  }\n}\n\n/**\n * Public surface of the singleton — excludes the test-only `clear`\n * method.\n */\nexport interface VpTokenRegistryPublic {\n  getOrCreate(input: VpTokenRegistryInput): VpTokenProvider;\n  peek(peginTxid: string): VpTokenProvider | undefined;\n  release(peginTxid: string): void;\n  readonly size: number;\n}\n\nexport const vpTokenRegistry: VpTokenRegistryPublic = new VpTokenRegistry();\n","/**\n * Build a {@link VaultProviderRpcClient} that auto-attaches CWT\n * bearer tokens on auth-gated methods. Caller pre-derives both the\n * `authAnchorHex` (from the wallet) and the `pinnedServerPubkey`\n * (from the on-chain registry) and hands them in — the SDK has no\n * notion of wallets here.\n *\n * @module tbv/core/clients/vault-provider/auth/createAuthenticatedVpClient\n */\n\nimport { processPublicKeyToXOnly } from \"../../../primitives/utils/bitcoin\";\nimport type { OnChainBtcPubkey } from \"../../eth/types\";\nimport {\n  VaultProviderRpcClient,\n  type VaultProviderRpcClientOptions,\n} from \"../api\";\n\nimport { buildInnerTokenClient } from \"./innerTokenClient\";\nimport { vpTokenRegistry } from \"./tokenRegistry\";\n\nexport interface AuthenticatedVpClientConfig {\n  /** Base URL of the VP RPC endpoint (already proxied if applicable). */\n  baseUrl: string;\n  /** Per-vault depositor-signed PegIn tx id (registry cache key). */\n  peginTxid: string;\n  /** Already-derived 32-byte auth-anchor preimage (64-char hex, no `0x`). */\n  authAnchorHex: string;\n  /** On-chain VP pubkey, branded so it can only come from the registry reader. */\n  pinnedServerPubkey: OnChainBtcPubkey;\n  /**\n   * Depositor BTC pubkey (x-only or compressed hex). Normalized to\n   * x-only and asserted against every issued token's CWT `aud` claim.\n   */\n  depositorBtcPubkey: string;\n  /** Optional outer-client tunables (timeout, retries, headers, etc.). */\n  options?: VaultProviderRpcClientOptions;\n}\n\nexport function createAuthenticatedVpClient(\n  config: AuthenticatedVpClientConfig,\n): VaultProviderRpcClient {\n  const innerTokenClient = buildInnerTokenClient(\n    config.baseUrl,\n    config.options?.headers,\n  );\n\n  const tokenProvider = vpTokenRegistry.getOrCreate({\n    client: innerTokenClient,\n    peginTxid: config.peginTxid,\n    authAnchorHex: config.authAnchorHex,\n    pinnedServerPubkey: config.pinnedServerPubkey,\n    expectedAudienceXOnlyPubkey: processPublicKeyToXOnly(\n      config.depositorBtcPubkey,\n    ),\n  });\n\n  return new VaultProviderRpcClient(config.baseUrl, {\n    ...config.options,\n    tokenProvider,\n  });\n}\n","/**\n * Pre-populate {@link vpTokenRegistry} when the caller already has\n * both the auth-anchor preimage and the on-chain VP pubkey. Seeds\n * the cache for a `peginTxid` so a later `createAuthenticatedVpClient`\n * call reuses the cached `VpTokenProvider` instead of rebuilding it.\n *\n * @module tbv/core/clients/vault-provider/auth/primeVpAuth\n */\n\nimport { processPublicKeyToXOnly } from \"../../../primitives/utils/bitcoin\";\nimport type { OnChainBtcPubkey } from \"../../eth/types\";\n\nimport { buildInnerTokenClient } from \"./innerTokenClient\";\nimport { vpTokenRegistry } from \"./tokenRegistry\";\n\nexport interface PrimeVpAuthInput {\n  baseUrl: string;\n  peginTxid: string;\n  authAnchorHex: string;\n  pinnedServerPubkey: OnChainBtcPubkey;\n  /**\n   * Depositor BTC pubkey (x-only or compressed hex). Normalized to\n   * x-only and asserted against every issued token's CWT `aud` claim.\n   */\n  depositorBtcPubkey: string;\n  /** Optional headers forwarded to the inner token client (e.g. gateway auth). */\n  headers?: Record<string, string>;\n}\n\nexport function primeVpTokenRegistry(input: PrimeVpAuthInput): void {\n  vpTokenRegistry.getOrCreate({\n    client: buildInnerTokenClient(input.baseUrl, input.headers),\n    peginTxid: input.peginTxid,\n    authAnchorHex: input.authAnchorHex,\n    pinnedServerPubkey: input.pinnedServerPubkey,\n    expectedAudienceXOnlyPubkey: processPublicKeyToXOnly(\n      input.depositorBtcPubkey,\n    ),\n  });\n}\n","/**\n * Defensive helper for attributing per-item results in a VP batch RPC\n * response back to the requested txids. The server promises 1:1 ordered\n * results, but we don't trust that promise — a server bug could duplicate,\n * skip, or scramble items, and silent attribution-by-array-index would\n * mask the bug.\n *\n * Lowercases all txids on both sides to absorb case mismatch (the FE\n * strips `0x` but doesn't otherwise normalize).\n *\n * @module tbv/core/clients/vault-provider/batchAttribution\n */\n\n/** Per-item entry in a VP batch response. */\nexport interface BatchResultEntry<T> {\n  pegin_txid: string;\n  result: T | null;\n  error: string | null;\n}\n\n/** Output of {@link attributeBatchResults}. */\nexport interface BatchAttributionResult<T> {\n  /** Lowercase requested txid -> per-item envelope. */\n  byTxid: Map<string, { result: T | null; error: string | null }>;\n  /** Requested txids that did not appear in the response. */\n  missing: string[];\n  /** Echoed txids that were not in the request — logged + dropped. */\n  unexpected: string[];\n  /** Echoed txids that appeared more than once — first kept, rest dropped. */\n  duplicate: string[];\n}\n\n/**\n * Attribute batch results to requested txids defensively.\n *\n * Both `requestedTxids` and the echoed `pegin_txid` field on each result\n * are lowercased before lookup. Duplicates and unexpected echoes are\n * surfaced so callers can flag the affected items as errored rather than\n * silently overwriting state.\n *\n * `requestedTxids` may contain duplicates; they are de-duplicated for the\n * purposes of map keys (each unique txid becomes a single map entry).\n */\nexport function attributeBatchResults<T>(\n  requestedTxids: string[],\n  results: ReadonlyArray<BatchResultEntry<T>>,\n): BatchAttributionResult<T> {\n  const requestedSet = new Set<string>();\n  for (const txid of requestedTxids) {\n    requestedSet.add(txid.toLowerCase());\n  }\n\n  const byTxid = new Map<\n    string,\n    { result: T | null; error: string | null }\n  >();\n  const seen = new Set<string>();\n  const duplicate: string[] = [];\n  const unexpected: string[] = [];\n\n  for (const entry of results) {\n    const lower = entry.pegin_txid.toLowerCase();\n    if (!requestedSet.has(lower)) {\n      unexpected.push(lower);\n      continue;\n    }\n    if (seen.has(lower)) {\n      duplicate.push(lower);\n      continue;\n    }\n    seen.add(lower);\n    byTxid.set(lower, { result: entry.result, error: entry.error });\n  }\n\n  const missing: string[] = [];\n  for (const txid of requestedSet) {\n    if (!seen.has(txid)) missing.push(txid);\n  }\n\n  return { byTxid, missing, unexpected, duplicate };\n}\n","/**\n * Generic chunk + attribute + dispatch loop for VP batch RPCs.\n *\n * Wraps {@link attributeBatchResults} with chunking and per-callback\n * dispatch so the FE polling hooks (and any future SDK consumer) only\n * have to declare per-item handlers — chunking by `VP_BATCH_MAX_SIZE`,\n * lowercase txid normalization, missing/duplicate/unexpected\n * surfacing, and the duplicate-skip invariant in the byTxid loop are\n * all owned here.\n *\n * @module tbv/core/clients/vault-provider/batchPoll\n */\n\nimport {\n  attributeBatchResults,\n  type BatchResultEntry,\n} from \"./batchAttribution\";\nimport { VP_BATCH_MAX_SIZE } from \"./types\";\n\nexport interface BatchPollByProviderOptions<TItem, TResult> {\n  /** Items to poll for this provider, e.g. `DepositToPoll[]`. */\n  items: TItem[];\n  /** Extract the canonical txid for each item. Helper lowercases it. */\n  getTxid: (item: TItem) => string;\n  /**\n   * Per-chunk RPC call. Receives lowercased txids; returns the batch\n   * envelope. Caller wraps `rpcClient.batchGet*Status({ pegin_txids })`.\n   */\n  batchCall: (\n    txids: string[],\n  ) => Promise<{ results: ReadonlyArray<BatchResultEntry<TResult>> }>;\n  /**\n   * Handle a per-item envelope. Exactly one of `result` / `error` is\n   * populated (validator invariant). Caller decides UI state, logging,\n   * etc. Not invoked for txids surfaced via {@link onDuplicate}.\n   *\n   * Note: `envelope.pegin_txid` is the lowercased txid the helper\n   * sent in the request, not whatever case/encoding the server echoed.\n   */\n  onItem: (item: TItem, envelope: BatchResultEntry<TResult>) => void;\n  /** Server omitted this item from the response. */\n  onMissing: (item: TItem) => void;\n  /** Server returned this item more than once. Caller picks UI state. */\n  onDuplicate: (item: TItem) => void;\n  /**\n   * Optional aggregate signal for an entire chunk where the server\n   * returned duplicates. Fires once per chunk (only if `count > 0`)\n   * AFTER all per-item `onDuplicate` dispatches. Caller typically logs\n   * the count alongside the provider name.\n   */\n  onDuplicateBatch?: (count: number) => void;\n  /**\n   * The whole chunk's RPC call failed (transport or response\n   * validation). Receives the chunk and the error. Caller decides how\n   * to project that onto per-item state.\n   */\n  onWholeBatchError: (chunk: TItem[], error: unknown) => void;\n  /**\n   * Server returned txids that were not in the request. Caller\n   * typically logs the count for observability — there's no recovery\n   * action since the original request items are unaffected. Optional;\n   * defaults to no-op.\n   */\n  onUnexpected?: (echoedTxids: string[]) => void;\n  /**\n   * Maximum items per RPC call. Defaults to {@link VP_BATCH_MAX_SIZE}.\n   * Exposed for tests so chunking can be exercised without 50+\n   * fixtures.\n   */\n  batchSize?: number;\n}\n\nexport async function batchPollByProvider<TItem, TResult>(\n  options: BatchPollByProviderOptions<TItem, TResult>,\n): Promise<void> {\n  const {\n    items,\n    getTxid,\n    batchCall,\n    onItem,\n    onMissing,\n    onDuplicate,\n    onDuplicateBatch,\n    onWholeBatchError,\n    onUnexpected,\n    batchSize = VP_BATCH_MAX_SIZE,\n  } = options;\n\n  if (!Number.isInteger(batchSize) || batchSize <= 0) {\n    throw new Error(\n      `batchPollByProvider: batchSize must be a positive integer, got ${batchSize}`,\n    );\n  }\n\n  for (let i = 0; i < items.length; i += batchSize) {\n    const chunk = items.slice(i, i + batchSize);\n    const txidToItem = new Map<string, TItem>();\n    const txids: string[] = [];\n    for (const item of chunk) {\n      const lowerTxid = getTxid(item).toLowerCase();\n      txidToItem.set(lowerTxid, item);\n      txids.push(lowerTxid);\n    }\n\n    // Both the RPC call and attribution sit inside the same try/catch\n    // so a malformed-batch validator throw is routed through\n    // `onWholeBatchError` rather than aborting the polling pass.\n    let attribution;\n    try {\n      const response = await batchCall(txids);\n      attribution = attributeBatchResults<TResult>(txids, response.results);\n    } catch (error) {\n      onWholeBatchError(chunk, error);\n      continue;\n    }\n\n    if (onUnexpected && attribution.unexpected.length > 0) {\n      onUnexpected(attribution.unexpected);\n    }\n\n    const duplicateTxids = new Set(attribution.duplicate);\n    for (const txid of duplicateTxids) {\n      const item = txidToItem.get(txid);\n      if (item) onDuplicate(item);\n    }\n    if (onDuplicateBatch && duplicateTxids.size > 0) {\n      onDuplicateBatch(duplicateTxids.size);\n    }\n    for (const txid of attribution.missing) {\n      const item = txidToItem.get(txid);\n      if (item) onMissing(item);\n    }\n    for (const [txid, envelope] of attribution.byTxid) {\n      // Skip duplicates — already dispatched via onDuplicate above.\n      if (duplicateTxids.has(txid)) continue;\n      const item = txidToItem.get(txid);\n      if (!item) continue;\n      onItem(item, {\n        pegin_txid: txid,\n        result: envelope.result,\n        error: envelope.error,\n      });\n    }\n  }\n}\n"],"names":["resolveProtocolAddresses","publicClient","btcVaultRegistryAddress","protocolParams","applicationRegistry","BTCVaultRegistryABI","assertMulticallLength","actual","expected","label","partition","results","keeperCount","ViemOperationKeyReader","contracts","calls","challengerCount","query","keeper","ApplicationRegistryABI","challenger","ProtocolParamsABI","epochs","UINT16_MAX","mapOffchainParams","result","mapTBVParams","deriveTimelockPegin","timelockAssert","ViemProtocolParamsReader","contractAddress","params","validateTBVProtocolParams","validateOffchainParams","version","raw","assertValidOffchainParamsVersion","tbvParams","offchainParams","offchainParamsVersion","activeVaultCoreVersion","config","validatePegInConfiguration","onSkippedVersion","latestVersion","versions","_","i","v","byVersion","error","mapKeyPairs","pair","ViemVaultKeeperReader","appEntryPoint","ViemUniversalChallengerReader","OnChainBtcVaultStatus","DAEMON_STATUS_VALUES","DaemonStatus","VP_ERROR_PREVIEW_MAX_LEN","preview","value","_a","VP_VALIDATION_USER_MESSAGE","VpResponseValidationError","detail","__publicField","TXID_HEX_LEN","isNonEmptyHex","HEX_RE","isNonEmptyString","assertNonEmptyHex","field","assertNonEmptyString","assertBtcPubkey","X_ONLY_PUBKEY_HEX_LEN","COMPRESSED_PUBKEY_HEX_LEN","validatePresigningProgressFields","progress","presigning","p","validateGetPeginStatusResponse","response","r","validateRequestDepositorPresignTransactionsResponse","validateClaimerTransactions","validateDepositorGraphTransactions","validateTransactionData","tx","validateChallengeAssertConnectorData","c","validatePresignDataPerChallenger","d","CHALLENGE_ASSERT_CONNECTORS_PER_CHALLENGER","validateRequestDepositorClaimerArtifactsResponse","sessionEntries","key","session","validateGetPegoutStatusResponse","validateClaimerPegoutStatus","validateChallengerStatus","index","assertNullableString","validateBatchGetPeginStatusResponse","validateBatchEnvelope","entry","validateBatchGetPegoutStatusResponse","rpcName","validateInnerResult","e","graph","DEFAULT_TIMEOUT_MS","VaultProviderRpcClient","baseUrl","options","JsonRpcClient","signal","cborHead","major","arg","tag","out","concat","parts","total","s","offset","encodeBytesAsArrayOfU8","bytes","items","b","encodeServerIdentityPayload","domain","ephemeralPubkeyCompressed","expiresAt","arrayHeader","domainBytes","pubkeyBytes","expiresAtBytes","SERVER_IDENTITY_DOMAIN","DEFAULT_MAX_PROOF_LIFETIME_SECS","ServerIdentityError","message","reason","hexToBytes","hex","verifyServerIdentity","input","proof","pinnedServerPubkey","now","maxLifetimeSecs","pinned","stripHexPrefix","eph","prefix","ephBytes","ecc","sig","SCHNORR_SIG_HEX_LEN","payload","verifyBip322Simple","AUTH_GATED_METHODS","GRPC_AUTH_GATED_METHODS","TOKEN_RPC_TIMEOUT_MS","TOKEN_ISSUE_METHOD","GRPC_TOKEN_ISSUE_METHOD","buildInnerTokenClient","headers","method","MAJOR_UNSIGNED_INT","MAJOR_NEGATIVE_INT","MAJOR_BYTE_STRING","MAJOR_TEXT_STRING","MAJOR_ARRAY","MAJOR_MAP","MAJOR_TAG","MAJOR_SIMPLE","ARG_IN_NEXT_1_BYTE","ARG_RESERVED_MIN","SIMPLE_FALSE","SIMPLE_TRUE","SIMPLE_NULL","MAX_NESTING_DEPTH","CborDecodeError","CborReader","buf","initial","info","byteCount","length","slice","head","depth","map","decodeCbor","reader","CWT_SUBJECT_JSONRPC","CWT_SUBJECT_GRPC","COSE_SIGN1_TAG","COSE_SIGN1_ARRAY_LEN","COSE_ALG_ES256K","COSE_HEADER_LABEL_ALG","ECDSA_COMPACT_SIG_LEN","CBOR_ARRAY_HEAD","CBOR_TEXT_STRING_HEAD","CBOR_EMPTY_BYTE_STRING","CWT_CLAIM_ISS","CWT_CLAIM_SUB","CWT_CLAIM_AUD","CWT_CLAIM_EXP","CWT_CLAIM_NBF","CWT_CLAIM_IAT","CWT_CLAIM_CTI","SIG_STRUCTURE_CONTEXT","CwtVerificationError","verifyDepositorCwt","expectedIssuer","normalizeXOnly","expectedAudience","ephemeral","decodeCompressedPubkey","tokenBytes","base64UrlToBytes","array","protectedStart","protectedContent","protectedBstr","payloadStart","payloadContent","payloadBstr","signature","alg","readProtectedAlgorithm","sigStructure","buildSigStructure","digest","sha256","claims","decodeClaims","audience","header","concatBytes","root","requireBytes","requireString","requireTimestamp","name","pubkey","normalized","pubkeyHex","hexToUint8Array","B64URL_LOOKUP","table","alphabet","len","fullGroups","remainder","outLen","sextet","charCode","inPos","outPos","g","a","sum","part","MAX_EXPIRES_AT_SECS","DEFAULT_REFRESH_SKEW_SECS","VpTokenProvider","subject","cached","client","existing","issueMethod","fresh","VpTokenRegistry","provider","peginTxid","vpTokenRegistry","createAuthenticatedVpClient","innerTokenClient","tokenProvider","processPublicKeyToXOnly","primeVpTokenRegistry","attributeBatchResults","requestedTxids","requestedSet","txid","byTxid","seen","duplicate","unexpected","lower","missing","batchPollByProvider","getTxid","batchCall","onItem","onMissing","onDuplicate","onDuplicateBatch","onWholeBatchError","onUnexpected","batchSize","VP_BATCH_MAX_SIZE","chunk","txidToItem","txids","item","lowerTxid","attribution","duplicateTxids","envelope"],"mappings":"80BA8BA,eAAsBA,GACpBC,EACAC,EAC4B,CAC5B,KAAM,CAACC,EAAgBC,CAAmB,EAAI,MAAMH,EAAa,UAAU,CACzE,UAAW,CACT,CACE,QAASC,EACT,IAAKG,EAAAA,oBACL,aAAc,gBAAA,EAEhB,CACE,QAASH,EACT,IAAKG,EAAAA,oBACL,aAAc,qBAAA,CAChB,EAEF,aAAc,EAAA,CACf,EAED,MAAO,CACL,eAAAF,EACA,oBAAAC,CAAA,CAEJ,CCTA,SAASE,EACPC,EACAC,EACAC,EACM,CACN,GAAIF,IAAWC,EACb,MAAM,IAAI,MACR,GAAGC,CAAK,wBAAwBF,CAAM,gBAAgBC,CAAQ,qEAAA,CAIpE,CAYA,SAASE,GACPC,EACAC,EACoE,CACpE,MAAO,CACL,cAAeD,EAAQ,CAAC,EACxB,aAAcA,EAAQ,MAAM,EAAG,EAAIC,CAAW,EAC9C,qBAAsBD,EAAQ,MAAM,EAAIC,CAAW,CAAA,CAEvD,CAWO,MAAMC,EAAqD,CAChE,YACUZ,EACAa,EACR,CAFQ,KAAA,aAAAb,EACA,KAAA,UAAAa,CACP,CAQH,MAAc,QACZC,EACAH,EACAI,EACAP,EACA,CACA,MAAME,EAAW,MAAM,KAAK,aAAa,UAAU,CACjD,UAAWI,EACX,aAAc,EAAA,CACf,EAED,OAAAT,EACEK,EAAQ,OACR,EAAIC,EAAcI,EAClBP,CAAA,EAGKC,GAAUC,EAASC,CAAW,CACvC,CAEA,MAAM,wBACJK,EAC2B,CAC3B,MAAMF,EAAgB,CACpB,CACE,QAAS,KAAK,UAAU,iBACxB,IAAKV,EAAAA,oBACL,aAAc,4BACd,KAAM,CAACY,EAAM,uBAAuB,CAAA,EAEtC,GAAGA,EAAM,aAAa,IAAKC,IAAY,CACrC,QAAS,KAAK,UAAU,oBACxB,IAAKC,EAAAA,uBACL,aAAc,4BACd,KAAM,CAACF,EAAM,sBAAuBC,EAAO,UAAU,CAAA,EACrD,EACF,GAAGD,EAAM,qBAAqB,IAAKG,IAAgB,CACjD,QAAS,KAAK,UAAU,eACxB,IAAKC,EAAAA,kBACL,aAAc,4BACd,KAAM,CAACD,EAAW,UAAU,CAAA,EAC5B,CAAA,EAGJ,OAAO,KAAK,QACVL,EACAE,EAAM,aAAa,OACnBA,EAAM,qBAAqB,OAC3B,yBAAA,CAEJ,CAEA,MAAM,yBACJA,EACAK,EAC2B,CAC3B,MAAMP,EAAgB,CAIpB,CACE,QAAS,KAAK,UAAU,iBACxB,IAAKV,EAAAA,oBACL,aAAc,4BACd,KAAM,CAACY,EAAM,wBAAyBK,EAAO,UAAU,CAAA,EAOzD,GAAGL,EAAM,aAAa,IAAKC,IAAY,CACrC,QAAS,KAAK,UAAU,oBACxB,IAAKC,EAAAA,uBACL,aAAc,qCACd,KAAM,CACJF,EAAM,sBACNC,EAAO,WACPI,EAAO,kBACPJ,EAAO,SAAA,CACT,EACA,EACF,GAAGD,EAAM,qBAAqB,IAAKG,IAAgB,CACjD,QAAS,KAAK,UAAU,eACxB,IAAKC,EAAAA,kBACL,aAAc,qCACd,KAAM,CAACD,EAAW,WAAYE,EAAO,WAAYF,EAAW,SAAS,CAAA,EACrE,CAAA,EAGJ,OAAO,KAAK,QACVL,EACAE,EAAM,aAAa,OACnBA,EAAM,qBAAqB,OAC3B,0BAAA,CAEJ,CAEA,MAAM,yBACJA,EACAK,EAC2B,CAG3B,MAAMX,EAAW,MAAM,KAAK,aAAa,UAAU,CACjD,UAAW,CACT,CACE,QAAS,KAAK,UAAU,iBACxB,IAAKN,EAAAA,oBACL,aAAc,yBACd,KAAM,CAACY,EAAM,wBAAyBK,EAAO,UAAU,CAAA,EAEzD,GAAGL,EAAM,aAAa,IAAKC,IAAY,CACrC,QAAS,KAAK,UAAU,oBACxB,IAAKC,EAAAA,uBACL,aAAc,yBACd,KAAM,CACJF,EAAM,sBACNC,EAAO,WACPI,EAAO,iBAAA,CACT,EACA,CAAA,EAEJ,aAAc,EAAA,CACf,EAID,OAAAhB,EACEK,EAAQ,OACR,EAAIM,EAAM,aAAa,OACvB,0BAAA,EAGK,CACL,cAAeN,EAAQ,CAAC,EACxB,aAAc,CAAC,GAAGA,EAAQ,MAAM,CAAC,CAAC,CAAA,CAEtC,CACF,CClNA,MAAMY,EAAa,MAkCnB,SAASC,EAAkBC,EAAoD,CAC7E,MAAO,CACL,eAAgBA,EAAO,eACvB,wBAAyBA,EAAO,wBAChC,oBAAqB,CAAC,GAAGA,EAAO,mBAAmB,EACnD,cAAeA,EAAO,cACtB,QAASA,EAAO,QAChB,mBAAoBA,EAAO,mBAC3B,wBAAyBA,EAAO,wBAChC,mBAAoBA,EAAO,mBAC3B,QAASA,EAAO,QAChB,OAAQA,EAAO,OACf,gBAAiBA,EAAO,gBACxB,qBAAsBA,EAAO,qBAC7B,iBAAkBA,EAAO,gBAAA,CAE7B,CAGA,SAASC,EAAaD,EAAyC,CAC7D,MAAO,CACL,mBAAoBA,EAAO,mBAC3B,eAAgBA,EAAO,eACvB,gBAAiBA,EAAO,gBACxB,uBAAwBA,EAAO,uBAC/B,mBAAoBA,EAAO,mBAC3B,wBAAyBA,EAAO,uBAAA,CAEpC,CAYA,SAASE,EAAoBC,EAAgC,CAC3D,GAAIA,EAAiB,OAAOL,CAAU,EACpC,MAAM,IAAI,MACR,wBAAwBK,CAAc,wBAAwBL,CAAU,GAAA,EAG5E,OAAO,OAAOK,CAAc,CAC9B,CAeO,MAAMC,EAAyD,CACpE,YACU5B,EACA6B,EACR,CAFQ,KAAA,aAAA7B,EACA,KAAA,gBAAA6B,CACP,CAEH,MAAM,sBAAmD,CACvD,MAAML,EAAU,MAAM,KAAK,aAAa,aAAa,CACnD,QAAS,KAAK,gBACd,IAAKJ,EAAAA,kBACL,aAAc,sBAAA,CACf,EAEKU,EAASL,EAAaD,CAAM,EAClCO,OAAAA,EAAAA,0BAA0BD,CAAM,EACzBA,CACT,CAEA,MAAM,yBAA4D,CAChE,MAAMN,EAAU,MAAM,KAAK,aAAa,aAAa,CACnD,QAAS,KAAK,gBACd,IAAKJ,EAAAA,kBACL,aAAc,yBAAA,CACf,EAEKU,EAASP,EAAkBC,CAAM,EACvCQ,OAAAA,EAAAA,uBAAuBF,CAAM,EACtBA,CACT,CAEA,MAAM,2BACJG,EACkC,CAClC,MAAMT,EAAU,MAAM,KAAK,aAAa,aAAa,CACnD,QAAS,KAAK,gBACd,IAAKJ,EAAAA,kBACL,aAAc,6BACd,KAAM,CAACa,CAAO,CAAA,CACf,EAEKH,EAASP,EAAkBC,CAAM,EACvCQ,OAAAA,EAAAA,uBAAuBF,CAAM,EACtBA,CACT,CAEA,MAAM,gCAAkD,CACtD,MAAMI,EAAM,MAAM,KAAK,aAAa,aAAa,CAC/C,QAAS,KAAK,gBACd,IAAKd,EAAAA,kBACL,aAAc,6BAAA,CACf,EACKa,EAAU,OAAOC,CAAG,EAC1BC,OAAAA,EAAAA,iCAAiCF,CAAO,EACjCA,CACT,CAEA,MAAM,0BAA0BA,EAAkC,CAChE,MAAMH,EAAS,MAAM,KAAK,2BAA2BG,CAAO,EAC5D,OAAOP,EAAoBI,EAAO,cAAc,CAClD,CAYA,MAAM,yBAA2C,CAC/C,MAAMI,EAAe,MAAM,KAAK,aAAa,aAAa,CACxD,QAAS,KAAK,gBACd,IAAKd,EAAAA,kBACL,aAAc,sBAAA,CACf,EACD,GAAI,OAAOc,GAAQ,SACjB,MAAM,IAAI,MACR,qEAAqE,OAAOA,CAAG,EAAA,EAGnF,OAAOA,CACT,CASA,MAAM,uBAAqD,CACzD,MAAMxB,EAAU,MAAM,KAAK,aAAa,UAAU,CAChD,UAAW,CACT,CACE,QAAS,KAAK,gBACd,IAAKU,EAAAA,kBACL,aAAc,sBAAA,EAEhB,CACE,QAAS,KAAK,gBACd,IAAKA,EAAAA,kBACL,aAAc,yBAAA,EAEhB,CACE,QAAS,KAAK,gBACd,IAAKA,EAAAA,kBACL,aAAc,6BAAA,EAEhB,CACE,QAAS,KAAK,gBACd,IAAKA,EAAAA,kBACL,aAAc,wBAAA,CAChB,EAEF,aAAc,EAAA,CACf,EAEKgB,EAAYX,EAAaf,EAAQ,CAAC,CAAiB,EACnD2B,EAAiBd,EAAkBb,EAAQ,CAAC,CAAsB,EAClE4B,EAAwB,OAAO5B,EAAQ,CAAC,CAAC,EACzC6B,EAAyB,OAAO7B,EAAQ,CAAC,CAAC,EAE1C8B,EAA6B,CACjC,mBAAoBJ,EAAU,mBAC9B,eAAgBA,EAAU,eAC1B,gBAAiBA,EAAU,gBAC3B,uBAAwBA,EAAU,uBAClC,mBAAoBA,EAAU,mBAC9B,wBAAyBA,EAAU,wBACnC,cAAeV,EAAoBW,EAAe,cAAc,EAChE,eAAgBA,EAAe,QAC/B,mBAAoBA,EAAe,mBACnC,eAAAA,EACA,sBAAAC,EACA,uBAAAC,CAAA,EAGFE,OAAAA,EAAAA,2BAA2BD,CAAM,EAC1BA,CACT,CAYA,MAAM,uBACJE,EACgC,CAChC,MAAMC,EAAgB,MAAM,KAAK,+BAAA,EACjC,GAAIA,IAAkB,EACpB,MAAO,CAAE,UAAW,IAAI,IAAO,cAAe,CAAA,EAGhD,MAAMC,EAAW,MAAM,KAAK,CAAE,OAAQD,CAAA,EAAiB,CAACE,EAAGC,IAAMA,EAAI,CAAC,EAChEjC,EAAY+B,EAAS,IAAKG,IAAO,CACrC,QAAS,KAAK,gBACd,IAAK3B,EAAAA,kBACL,aAAc,6BACd,KAAM,CAAC2B,CAAC,CAAA,EACR,EAEIrC,EAAU,MAAM,KAAK,aAAa,UAAU,CAChD,UAAAG,EACA,aAAc,EAAA,CACf,EAEKmC,MAAgB,IACtB,QAASF,EAAI,EAAGA,EAAIF,EAAS,OAAQE,IAAK,CACxC,MAAMhB,EAASP,EAAkBb,EAAQoC,CAAC,CAAsB,EAChE,GAAI,CACFd,EAAAA,uBAAuBF,CAAM,EAC7BkB,EAAU,IAAIJ,EAASE,CAAC,EAAGhB,CAAM,CACnC,OAASmB,EAAO,CAGdP,GAAA,MAAAA,EACEE,EAASE,CAAC,EACVG,aAAiB,MAAQA,EAAQ,IAAI,MAAM,OAAOA,CAAK,CAAC,EAE5D,CACF,CAEA,MAAO,CAAE,UAAAD,EAAW,cAAAL,CAAA,CACtB,CACF,CC3SA,SAASO,EACP1B,EACqB,CACrB,OAAOA,EAAO,IAAK2B,IAAU,CAC3B,WAAYA,EAAK,WACjB,UAAWA,EAAK,SAAA,EAChB,CACJ,CAWO,MAAMC,EAAmD,CAC9D,YACUpD,EACA6B,EACR,CAFQ,KAAA,aAAA7B,EACA,KAAA,gBAAA6B,CACP,CAEH,MAAM,yBACJwB,EACApB,EAC8B,CAC9B,MAAMT,EAAU,MAAM,KAAK,aAAa,aAAa,CACnD,QAAS,KAAK,gBACd,IAAKN,EAAAA,uBACL,aAAc,2BACd,KAAM,CAACmC,EAAepB,CAAO,CAAA,CAC9B,EAED,OAAOiB,EAAY1B,CAAM,CAC3B,CAEA,MAAM,uBACJ6B,EAC8B,CAC9B,MAAM7B,EAAU,MAAM,KAAK,aAAa,aAAa,CACnD,QAAS,KAAK,gBACd,IAAKN,EAAAA,uBACL,aAAc,yBACd,KAAM,CAACmC,CAAa,CAAA,CACrB,EAED,OAAOH,EAAY1B,CAAM,CAC3B,CAEA,MAAM,8BACJ6B,EACiB,CAQjB,OAPgB,MAAM,KAAK,aAAa,aAAa,CACnD,QAAS,KAAK,gBACd,IAAKnC,EAAAA,uBACL,aAAc,gCACd,KAAM,CAACmC,CAAa,CAAA,CACrB,CAGH,CACF,CAWO,MAAMC,EAAmE,CAC9E,YACUtD,EACA6B,EACR,CAFQ,KAAA,aAAA7B,EACA,KAAA,gBAAA6B,CACP,CAEH,MAAM,iCACJI,EAC8B,CAC9B,MAAMT,EAAU,MAAM,KAAK,aAAa,aAAa,CACnD,QAAS,KAAK,gBACd,IAAKJ,EAAAA,kBACL,aAAc,mCACd,KAAM,CAACa,CAAO,CAAA,CACf,EAED,OAAOiB,EAAY1B,CAAM,CAC3B,CAEA,MAAM,gCAA+D,CACnE,MAAMA,EAAU,MAAM,KAAK,aAAa,aAAa,CACnD,QAAS,KAAK,gBACd,IAAKJ,EAAAA,kBACL,aAAc,gCAAA,CACf,EAED,OAAO8B,EAAY1B,CAAM,CAC3B,CAEA,MAAM,sCAAwD,CAO5D,OANgB,MAAM,KAAK,aAAa,aAAa,CACnD,QAAS,KAAK,gBACd,IAAKJ,EAAAA,kBACL,aAAc,mCAAA,CACf,CAGH,CACF,CC1FO,IAAKmC,IAAAA,IACVA,EAAAA,EAAA,QAAU,CAAA,EAAV,UACAA,EAAAA,EAAA,SAAW,CAAA,EAAX,WACAA,EAAAA,EAAA,OAAS,CAAA,EAAT,SACAA,EAAAA,EAAA,SAAW,CAAA,EAAX,WACAA,EAAAA,EAAA,QAAU,CAAA,EAAV,UALUA,IAAAA,IAAA,CAAA,CAAA,ECZZ,MAAMC,GAAuB,IAAI,IAAY,OAAO,OAAOC,EAAAA,YAAY,CAAC,EAElEC,GAA2B,IAEjC,SAASC,EAAQC,EAAwB,OACvC,QACEC,EAAA,KAAK,UAAUD,CAAK,IAApB,YAAAC,EAAuB,MAAM,EAAGH,MAA6B,WAEjE,CAEA,MAAMI,GACJ,2FAQK,MAAMC,UAAkC,KAAM,CAGnD,YAAYC,EAAgB,CAC1B,MAAMF,EAA0B,EAHzBG,EAAA,eAIP,KAAK,KAAO,4BACZ,KAAK,OAASD,CAChB,CACF,CAGA,MAAME,EAAe,GAErB,SAASC,EAAcP,EAAiC,CACtD,OAAO,OAAOA,GAAU,UAAYA,EAAM,OAAS,GAAKQ,EAAAA,OAAO,KAAKR,CAAK,CAC3E,CAEA,SAASS,GAAiBT,EAAiC,CACzD,OAAO,OAAOA,GAAU,UAAYA,EAAM,OAAS,CACrD,CAEA,SAASU,GAAkBV,EAAgBW,EAAqB,CAC9D,GAAI,CAACJ,EAAcP,CAAK,EACtB,MAAM,IAAIG,EACR,mCAAmCQ,CAAK,yCAAyCZ,EAAQC,CAAK,CAAC,EAAA,CAGrG,CAEA,SAASY,EAAqBZ,EAAgBW,EAAqB,CACjE,GAAI,CAACF,GAAiBT,CAAK,EACzB,MAAM,IAAIG,EACR,mCAAmCQ,CAAK,qCAAqCZ,EAAQC,CAAK,CAAC,EAAA,CAGjG,CAMA,SAASa,EAAgBb,EAAgBW,EAAqB,CAC5D,GACE,CAACJ,EAAcP,CAAK,GACnBA,EAAM,SAAWc,yBAChBd,EAAM,SAAWe,4BAEnB,MAAM,IAAIZ,EACR,mCAAmCQ,CAAK,eAAeG,EAAAA,qBAAqB,OAAOC,EAAAA,yBAAyB,sCAAsChB,EAAQC,CAAK,CAAC,EAAA,CAGtK,CAKA,SAASgB,GACPC,EACM,CACN,MAAMC,EAAaD,EAAS,WAC5B,GAAgCC,GAAe,KAAM,OACrD,GAAI,OAAOA,GAAe,UAAY,MAAM,QAAQA,CAAU,EAC5D,MAAM,IAAIf,EACR,mFAAA,EAIJ,MAAMgB,EAAID,EAEV,GACEC,EAAE,0BAA4B,QAC9B,OAAOA,EAAE,yBAA4B,UAErC,MAAM,IAAIhB,EACR,kHAAkHJ,EAAQoB,EAAE,uBAAuB,CAAC,EAAA,EAIxJ,GACEA,EAAE,qCAAuC,QACzC,OAAOA,EAAE,oCAAuC,SAEhD,MAAM,IAAIhB,EACR,4HAA4HJ,EAAQoB,EAAE,kCAAkC,CAAC,EAAA,EAI7K,GACEA,EAAE,iCAAmC,QACrC,OAAOA,EAAE,gCAAmC,SAE5C,MAAM,IAAIhB,EACR,wHAAwHJ,EAAQoB,EAAE,8BAA8B,CAAC,EAAA,CAGvK,CAOO,SAASC,GACdC,EAC4C,CAC5C,GAAIA,IAAa,MAAQ,OAAOA,GAAa,SAC3C,MAAM,IAAIlB,EACR,yEAAA,EAIJ,MAAMmB,EAAID,EAEV,GAAI,CAACd,EAAce,EAAE,UAAU,GAAKA,EAAE,WAAW,SAAWhB,EAC1D,MAAM,IAAIH,EACR,yDAAyDG,CAAY,gCAAgCP,EAAQuB,EAAE,UAAU,CAAC,EAAA,EAI9H,GAAI,OAAOA,EAAE,QAAW,SACtB,MAAM,IAAInB,EACR,0DAAA,EAIJ,GAAI,CAACP,GAAqB,IAAI0B,EAAE,MAAM,EACpC,MAAM,IAAInB,EACR,uDAAuDmB,EAAE,MAAM,uBAAuB,CAAC,GAAG1B,EAAoB,EAAE,KAAK,IAAI,CAAC,EAAA,EAI9H,GACE0B,EAAE,WAAa,MACf,OAAOA,EAAE,UAAa,UACtB,MAAM,QAAQA,EAAE,QAAQ,EAExB,MAAM,IAAInB,EACR,6DAAA,EAMJ,GAFAa,GAAiCM,EAAE,QAAmC,EAElE,OAAOA,EAAE,aAAgB,SAC3B,MAAM,IAAInB,EACR,+DAAA,EAIJ,GAAImB,EAAE,aAAe,QAAa,OAAOA,EAAE,YAAe,SACxD,MAAM,IAAInB,EACR,gFAAgFJ,EAAQuB,EAAE,UAAU,CAAC,EAAA,CAG3G,CAKO,SAASC,GACdF,EACiE,CACjE,GAAIA,IAAa,MAAQ,OAAOA,GAAa,SAC3C,MAAM,IAAIlB,EACR,8FAAA,EAIJ,MAAMmB,EAAID,EAEV,GAAI,CAAC,MAAM,QAAQC,EAAE,GAAG,EACtB,MAAM,IAAInB,EACR,uDAAA,EAIJ,QAASjB,EAAI,EAAGA,EAAIoC,EAAE,IAAI,OAAQpC,IAChCsC,GAA4BF,EAAE,IAAIpC,CAAC,EAAG,OAAOA,CAAC,GAAG,EAGnD,GAAIoC,EAAE,kBAAoB,MAAQ,OAAOA,EAAE,iBAAoB,SAC7D,MAAM,IAAInB,EACR,oEAAA,EAIJsB,GACEH,EAAE,eAAA,CAEN,CAEA,SAASI,EAAwB1B,EAAgBW,EAAqB,CACpE,GAAIX,IAAU,MAAQ,OAAOA,GAAU,SACrC,MAAM,IAAIG,EACR,mCAAmCQ,CAAK,qBAAA,EAI5CD,GADWV,EACU,OAAQ,GAAGW,CAAK,SAAS,CAChD,CAEA,SAASa,GAA4BxB,EAAgBW,EAAqB,CACxE,GAAIX,IAAU,MAAQ,OAAOA,GAAU,SACrC,MAAM,IAAIG,EACR,mCAAmCQ,CAAK,qBAAA,EAI5C,MAAMgB,EAAK3B,EAEXa,EAAgBc,EAAG,eAAgB,GAAGhB,CAAK,iBAAiB,EAC5De,EAAwBC,EAAG,SAAU,GAAGhB,CAAK,WAAW,EACxDe,EAAwBC,EAAG,UAAW,GAAGhB,CAAK,YAAY,EAC1De,EAAwBC,EAAG,UAAW,GAAGhB,CAAK,YAAY,EAC1DC,EAAqBe,EAAG,YAAa,GAAGhB,CAAK,cAAc,CAC7D,CAEA,SAASiB,GACP5B,EACAW,EACM,CACN,GAAIX,IAAU,MAAQ,OAAOA,GAAU,SACrC,MAAM,IAAIG,EACR,mCAAmCQ,CAAK,qBAAA,EAI5C,MAAMkB,EAAI7B,EACVY,EAAqBiB,EAAE,cAAe,GAAGlB,CAAK,gBAAgB,EAC9DC,EAAqBiB,EAAE,kBAAmB,GAAGlB,CAAK,oBAAoB,CACxE,CAEA,SAASmB,GAAiC9B,EAAgBW,EAAqB,CAC7E,GAAIX,IAAU,MAAQ,OAAOA,GAAU,SACrC,MAAM,IAAIG,EACR,mCAAmCQ,CAAK,qBAAA,EAI5C,MAAMoB,EAAI/B,EAcV,GAZAa,EAAgBkB,EAAE,kBAAmB,GAAGpB,CAAK,oBAAoB,EACjEe,EACEK,EAAE,sBACF,GAAGpB,CAAK,wBAAA,EAEVe,EACEK,EAAE,sBACF,GAAGpB,CAAK,wBAAA,EAEVe,EAAwBK,EAAE,YAAa,GAAGpB,CAAK,cAAc,EAC7DC,EAAqBmB,EAAE,cAAe,GAAGpB,CAAK,gBAAgB,EAE1D,CAAC,MAAM,QAAQoB,EAAE,2BAA2B,EAC9C,MAAM,IAAI5B,EACR,mCAAmCQ,CAAK,gDAAA,EAI5C,GACEoB,EAAE,4BAA4B,SAC9BC,6CAEA,MAAM,IAAI7B,EACR,mCAAmCQ,CAAK,mDAAmDqB,EAAAA,0CAA0C,iBAAiBD,EAAE,4BAA4B,MAAM,EAAA,EAI9L,QAAS7C,EAAI,EAAGA,EAAI6C,EAAE,4BAA4B,OAAQ7C,IACxD0C,GACEG,EAAE,4BAA4B7C,CAAC,EAC/B,GAAGyB,CAAK,gCAAgCzB,CAAC,GAAA,EAI7C,GAAI,CAAC,MAAM,QAAQ6C,EAAE,mBAAmB,EACtC,MAAM,IAAI5B,EACR,mCAAmCQ,CAAK,wCAAA,EAI5C,QAASzB,EAAI,EAAGA,EAAI6C,EAAE,oBAAoB,OAAQ7C,IAChDwB,GACEqB,EAAE,oBAAoB7C,CAAC,EACvB,GAAGyB,CAAK,wBAAwBzB,CAAC,GAAA,CAGvC,CAKO,SAAS+C,GACdZ,EAC8D,CAC9D,GAAIA,IAAa,MAAQ,OAAOA,GAAa,SAC3C,MAAM,IAAIlB,EACR,2FAAA,EAIJ,MAAMmB,EAAID,EAEV,GAAI,CAACZ,GAAiBa,EAAE,aAAa,EACnC,MAAM,IAAInB,EACR,kFAAkFJ,EAAQuB,EAAE,aAAa,CAAC,EAAA,EAI9G,GAAI,CAACf,EAAce,EAAE,iBAAiB,EACpC,MAAM,IAAInB,EACR,0FAA0FJ,EAAQuB,EAAE,iBAAiB,CAAC,EAAA,EAI1H,GACEA,EAAE,gBAAkB,MACpB,OAAOA,EAAE,eAAkB,UAC3B,MAAM,QAAQA,EAAE,aAAa,EAE7B,MAAM,IAAInB,EACR,kEAAA,EAIJ,MAAM+B,EAAiB,OAAO,QAC5BZ,EAAE,aAAA,EAEJ,GAAIY,EAAe,SAAW,EAC5B,MAAM,IAAI/B,EACR,2FAAA,EAIJ,SAAW,CAACgC,EAAKC,CAAO,IAAKF,EAAgB,CAE3C,GADArB,EAAgBsB,EAAK,kBAAkBA,CAAG,IAAI,EAC1CC,IAAY,MAAQ,OAAOA,GAAY,SACzC,MAAM,IAAIjC,EACR,iDAAiDgC,CAAG,qBAAA,EAGxD,MAAM,EAAIC,EACV,GAAI,CAAC7B,EAAc,EAAE,uBAAuB,EAC1C,MAAM,IAAIJ,EACR,iDAAiDgC,CAAG,iEAAiEpC,EAAQ,EAAE,uBAAuB,CAAC,EAAA,CAG7J,CACF,CAOO,SAASsC,GACdhB,EAC6C,CAC7C,GAAIA,IAAa,MAAQ,OAAOA,GAAa,SAC3C,MAAM,IAAIlB,EACR,uEAAA,EAIJ,MAAMmB,EAAID,EAEV,GAAI,CAACd,EAAce,EAAE,UAAU,GAAKA,EAAE,WAAW,SAAWhB,EAC1D,MAAM,IAAIH,EACR,yDAAyDG,CAAY,gCAAgCP,EAAQuB,EAAE,UAAU,CAAC,EAAA,EAI9H,GAAI,OAAOA,EAAE,OAAU,UACrB,MAAM,IAAInB,EACR,iEAAiEJ,EAAQuB,EAAE,KAAK,CAAC,EAAA,EAKrF,GAAIA,EAAE,UAAY,KAAM,CACtB,GAAI,OAAOA,EAAE,SAAY,SACvB,MAAM,IAAInB,EACR,2EAA2EJ,EAAQuB,EAAE,OAAO,CAAC,EAAA,EAGjGgB,GAA4BhB,EAAE,OAAkC,CAClE,CAGA,GAAI,CAAC,MAAM,QAAQA,EAAE,WAAW,EAC9B,MAAM,IAAInB,EACR,sEAAsEJ,EAAQuB,EAAE,WAAW,CAAC,EAAA,EAGhG,QAASpC,EAAI,EAAGA,EAAIoC,EAAE,YAAY,OAAQpC,IACxCqD,GAAyBjB,EAAE,YAAYpC,CAAC,EAAGA,CAAC,CAEhD,CAEA,SAASoD,GAA4BtC,EAAsC,CAEzE,GADAY,EAAqBZ,EAAM,OAAQ,gBAAgB,EAC/C,OAAOA,EAAM,QAAW,UAC1B,MAAM,IAAIG,EACR,0EAA0EJ,EAAQC,EAAM,MAAM,CAAC,EAAA,EAMnG,GAHAY,EAAqBZ,EAAM,WAAY,oBAAoB,EAC3DY,EAAqBZ,EAAM,eAAgB,wBAAwB,EACnEY,EAAqBZ,EAAM,YAAa,qBAAqB,EACzD,OAAOA,EAAM,YAAe,SAC9B,MAAM,IAAIG,EACR,6EAA6EJ,EAAQC,EAAM,UAAU,CAAC,EAAA,EAG1G,GAAI,OAAOA,EAAM,YAAe,SAC9B,MAAM,IAAIG,EACR,6EAA6EJ,EAAQC,EAAM,UAAU,CAAC,EAAA,CAG5G,CAEA,SAASuC,GAAyBvC,EAAgBwC,EAAqB,CACrE,GAAIxC,IAAU,MAAQ,OAAOA,GAAU,SACrC,MAAM,IAAIG,EACR,+CAA+CqC,CAAK,6BAA6BzC,EAAQC,CAAK,CAAC,EAAA,EAGnG,MAAM6B,EAAI7B,EAcV,GAbAY,EAAqBiB,EAAE,OAAQ,eAAeW,CAAK,UAAU,EAC7D5B,EAAqBiB,EAAE,WAAY,eAAeW,CAAK,cAAc,EACrE5B,EAAqBiB,EAAE,eAAgB,eAAeW,CAAK,kBAAkB,EAC7EC,EAAqBZ,EAAE,YAAa,eAAeW,CAAK,eAAe,EACvEC,EACEZ,EAAE,wBACF,eAAeW,CAAK,2BAAA,EAEtBC,EACEZ,EAAE,wBACF,eAAeW,CAAK,2BAAA,EAEtBC,EAAqBZ,EAAE,cAAe,eAAeW,CAAK,iBAAiB,EACvE,OAAOX,EAAE,YAAe,SAC1B,MAAM,IAAI1B,EACR,+CAA+CqC,CAAK,uCAAuCzC,EAAQ8B,EAAE,UAAU,CAAC,EAAA,EAGpH,GAAI,OAAOA,EAAE,YAAe,SAC1B,MAAM,IAAI1B,EACR,+CAA+CqC,CAAK,uCAAuCzC,EAAQ8B,EAAE,UAAU,CAAC,EAAA,CAGtH,CAEA,SAASY,EAAqBzC,EAAgBW,EAAqB,CACjE,GAAIX,IAAU,MAAQ,OAAOA,GAAU,SACrC,MAAM,IAAIG,EACR,mCAAmCQ,CAAK,mCAAmCZ,EAAQC,CAAK,CAAC,EAAA,CAG/F,CAOO,SAAS0C,GACdrB,EACiD,CACjDsB,GAAsBtB,EAAU,sBAAwBuB,GAAU,CAC5DA,EAAM,SAAW,MACnBxB,GAA+BwB,EAAM,MAAM,CAE/C,CAAC,CACH,CAGO,SAASC,GACdxB,EACkD,CAClDsB,GAAsBtB,EAAU,uBAAyBuB,GAAU,CAC7DA,EAAM,SAAW,MACnBP,GAAgCO,EAAM,MAAM,CAEhD,CAAC,CACH,CAQA,SAASD,GACPtB,EACAyB,EACAC,EACM,CACN,GAAI1B,IAAa,MAAQ,OAAOA,GAAa,SAC3C,MAAM,IAAIlB,EACR,kCAAkC2C,CAAO,4BAAA,EAG7C,MAAMxB,EAAID,EACV,GAAI,CAAC,MAAM,QAAQC,EAAE,OAAO,EAC1B,MAAM,IAAInB,EACR,mCAAmC2C,CAAO,mCAAmC/C,EAAQuB,EAAE,OAAO,CAAC,EAAA,EAGnG,QAAS,EAAI,EAAG,EAAIA,EAAE,QAAQ,OAAQ,IAAK,CACzC,MAAMsB,EAAQtB,EAAE,QAAQ,CAAC,EACzB,GAAIsB,IAAU,MAAQ,OAAOA,GAAU,SACrC,MAAM,IAAIzC,EACR,mCAAmC2C,CAAO,YAAY,CAAC,6BAA6B/C,EAAQ6C,CAAK,CAAC,EAAA,EAGtG,MAAMI,EAAIJ,EACV,GACE,CAACrC,EAAcyC,EAAE,UAAU,GAC3BA,EAAE,WAAW,SAAW1C,EAExB,MAAM,IAAIH,EACR,mCAAmC2C,CAAO,YAAY,CAAC,2BAA2BxC,CAAY,yBAAyBP,EAAQiD,EAAE,UAAU,CAAC,EAAA,EAGhJ,GAAIA,EAAE,QAAU,MAAQ,OAAOA,EAAE,OAAU,SACzC,MAAM,IAAI7C,EACR,mCAAmC2C,CAAO,YAAY,CAAC,0CAA0C/C,EAAQiD,EAAE,KAAK,CAAC,EAAA,EAMrH,GAAIA,EAAE,SAAW,MAAQA,EAAE,QAAU,KACnC,MAAM,IAAI7C,EACR,mCAAmC2C,CAAO,YAAY,CAAC,+CAAA,EAG3D,GAAIE,EAAE,SAAW,MAAQA,EAAE,QAAU,KACnC,MAAM,IAAI7C,EACR,mCAAmC2C,CAAO,YAAY,CAAC,4CAAA,EAG3DC,EAAoBC,EAAqC,CAAC,CAC5D,CACF,CAEA,SAASvB,GACPwB,EACM,CAMN,GALAvB,EAAwBuB,EAAM,SAAU,0BAA0B,EAClEvB,EAAwBuB,EAAM,UAAW,2BAA2B,EACpEvB,EAAwBuB,EAAM,UAAW,2BAA2B,EACpErC,EAAqBqC,EAAM,YAAa,6BAA6B,EAEjE,CAAC,MAAM,QAAQA,EAAM,uBAAuB,EAC9C,MAAM,IAAI9C,EACR,2FAAA,EAIJ,QAASjB,EAAI,EAAGA,EAAI+D,EAAM,wBAAwB,OAAQ/D,IACxD4C,GACEmB,EAAM,wBAAwB/D,CAAC,EAC/B,2CAA2CA,CAAC,GAAA,EAIhD,GAAI,OAAO+D,EAAM,yBAA4B,SAC3C,MAAM,IAAI9C,EACR,2FAAA,CAGN,CCziBA,MAAM+C,GAAqB,IAWpB,MAAMC,EAEb,CAGE,YAAYC,EAAiBC,EAAyC,CAF9DhD,EAAA,eAGN,MAAMzB,EAA8B,CAClC,QAAAwE,EACA,SAASC,GAAA,YAAAA,EAAS,UAAWH,GAC7B,QAASG,GAAA,YAAAA,EAAS,QAClB,WAAYA,GAAA,YAAAA,EAAS,WACrB,aAAcA,GAAA,YAAAA,EAAS,aACvB,QAASA,GAAA,YAAAA,EAAS,QAClB,cAAeA,GAAA,YAAAA,EAAS,cACxB,iBAAkBA,GAAA,YAAAA,EAAS,gBAAA,EAE7B,KAAK,OAAS,IAAIC,EAAAA,cAAc1E,CAAM,CACxC,CAMA,MAAM,oCACJV,EACAqF,EACsD,CACtD,MAAMlC,EAAW,MAAM,KAAK,OAAO,KAGjC,oDAAqDnD,EAAQqF,CAAM,EACrE,OAAAhC,GAAoDF,CAAQ,EACrDA,CACT,CAMA,MAAM,6BACJnD,EACAqF,EACe,CACf,OAAO,KAAK,OAAO,KACjB,6CACArF,EACAqF,CAAA,CAEJ,CAOA,MAAM,uBACJrF,EACAqF,EACe,CACf,OAAO,KAAK,OAAO,KACjB,uCACArF,EACAqF,CAAA,CAEJ,CAMA,MAAM,iCACJrF,EACAqF,EACmD,CACnD,MAAMlC,EAAW,MAAM,KAAK,OAAO,KAGjC,iDAAkDnD,EAAQqF,CAAM,EAClE,OAAAtB,GAAiDZ,CAAQ,EAClDA,CACT,CAGA,MAAM,eACJnD,EACAqF,EACiC,CACjC,MAAMlC,EAAW,MAAM,KAAK,OAAO,KACjC,+BACAnD,EACAqF,CAAA,EAEF,OAAAnC,GAA+BC,CAAQ,EAChCA,CACT,CAOA,MAAM,oBACJnD,EACAqF,EACsC,CACtC,MAAMlC,EAAW,MAAM,KAAK,OAAO,KAGjC,oCAAqCnD,EAAQqF,CAAM,EACrD,OAAAb,GAAoCrB,CAAQ,EACrCA,CACT,CAMA,MAAM,qBACJnD,EACAqF,EACuC,CACvC,MAAMlC,EAAW,MAAM,KAAK,OAAO,KAGjC,qCAAsCnD,EAAQqF,CAAM,EACtD,OAAAV,GAAqCxB,CAAQ,EACtCA,CACT,CACF,CC3KA,SAASmC,EAASC,EAAeC,EAAkC,CACjE,MAAMC,GAAOF,EAAQ,IAAS,EACxB,EAAI,OAAOC,GAAQ,SAAWA,EAAM,OAAOA,CAAG,EACpD,GAAI,EAAI,GAAI,MAAM,IAAI,MAAM,6BAA6B,EAEzD,GAAI,EAAI,IAAK,OAAO,IAAI,WAAW,CAACC,EAAM,OAAO,CAAC,CAAC,CAAC,EACpD,GAAI,EAAI,OAAQ,OAAO,IAAI,WAAW,CAACA,EAAM,GAAI,OAAO,CAAC,CAAC,CAAC,EAC3D,GAAI,EAAI,SAAU,CAChB,MAAMxE,EAAI,OAAO,CAAC,EAClB,OAAO,IAAI,WAAW,CAACwE,EAAM,GAAKxE,IAAM,EAAK,IAAMA,EAAI,GAAI,CAAC,CAC9D,CACA,GAAI,EAAI,aAAgB,CACtB,MAAMA,EAAI,OAAO,CAAC,EAClB,OAAO,IAAI,WAAW,CACpBwE,EAAM,GACLxE,IAAM,GAAM,IACZA,IAAM,GAAM,IACZA,IAAM,EAAK,IACZA,EAAI,GAAA,CACL,CACH,CAEA,MAAMyE,EAAM,IAAI,WAAW,CAAC,EAC5BA,EAAI,CAAC,EAAID,EAAM,GACf,QAASzE,EAAI,EAAGA,GAAK,EAAGA,IACtB0E,EAAI,EAAI1E,CAAC,EAAI,OAAO,GAAK,QAAQ,EAAIA,GAAK,CAAC,CAAC,EAAI,IAElD,OAAO0E,CACT,CAEA,SAASC,MAAUC,EAAiC,CAClD,MAAMC,EAAQD,EAAM,OAAO,CAACE,EAAG7C,IAAM6C,EAAI7C,EAAE,OAAQ,CAAC,EAC9CyC,EAAM,IAAI,WAAWG,CAAK,EAChC,IAAIE,EAAS,EACb,UAAW9C,KAAK2C,EACdF,EAAI,IAAIzC,EAAG8C,CAAM,EACjBA,GAAU9C,EAAE,OAEd,OAAOyC,CACT,CASA,SAASM,GAAuBC,EAA+B,CAE7D,MAAMC,EAAsB,CADbZ,EAAS,EAAGW,EAAM,MAAM,CACJ,EACnC,UAAWE,KAAKF,EACdC,EAAM,KAAKZ,EAAS,EAAGa,CAAC,CAAC,EAE3B,OAAOR,GAAO,GAAGO,CAAK,CACxB,CAsBO,SAASE,GACdC,EACAC,EACAC,EACY,CACZ,GAAI,CAAC,OAAO,cAAcA,CAAS,GAAKA,EAAY,EAClD,MAAM,IAAI,MACR,oFAAoFA,CAAS,EAAA,EAGjG,MAAMC,EAAclB,EAAS,EAAG,CAAC,EAC3BmB,EAAcT,GAAuBK,CAAM,EAC3CK,EAAcV,GAAuBM,CAAyB,EAC9DK,EAAiBrB,EAAS,EAAGiB,CAAS,EAC5C,OAAOZ,GAAOa,EAAaC,EAAaC,EAAaC,CAAc,CACrE,CCzFA,MAAMC,GAAyB,IAAI,YAAA,EAAc,OAC/C,6BACF,EAQMC,GAAkC,EAAI,KA+BrC,MAAMC,UAA4B,KAAM,CAC7C,YACEC,EACgBC,EAUhB,CACA,MAAMD,CAAO,EAXG,KAAA,OAAAC,EAYhB,KAAK,KAAO,qBACd,CACF,CAGA,SAASC,EAAWC,EAAyB,CAC3C,MAAMxB,EAAM,IAAI,WAAWwB,EAAI,OAAS,CAAC,EACzC,QAASlG,EAAI,EAAGA,EAAI0E,EAAI,OAAQ1E,IAC9B0E,EAAI1E,CAAC,EAAI,SAASkG,EAAI,MAAMlG,EAAI,EAAGA,EAAI,EAAI,CAAC,EAAG,EAAE,EAEnD,OAAO0E,CACT,CAsBO,SAASyB,GAAqBC,EAAwC,CAC3E,KAAM,CAAE,MAAAC,EAAO,mBAAAC,EAAoB,IAAAC,CAAA,EAAQH,EACrCI,EACJJ,EAAM,iBAAmBP,GAErBY,EAASC,EAAAA,eAAeJ,CAAkB,EAAE,YAAA,EAClD,GAAIG,EAAO,SAAW7E,EAAAA,uBAAyB,CAACN,EAAAA,OAAO,KAAKmF,CAAM,EAChE,MAAM,IAAIX,EACR,+CAA+CW,EAAO,MAAM,SAC5D,yBAAA,EAIJ,MAAMjJ,EAASkJ,EAAAA,eAAeL,EAAM,aAAa,EAAE,YAAA,EACnD,GAAI7I,EAAO,SAAWoE,EAAAA,uBAAyB,CAACN,EAAAA,OAAO,KAAK9D,CAAM,EAChE,MAAM,IAAIsI,EACR,0CAA0CtI,EAAO,MAAM,SACvD,yBAAA,EAIJ,GAAIA,IAAWiJ,EACb,MAAM,IAAIX,EACR,uDAAuDW,CAAM,SAASjJ,CAAM,GAC5E,wBAAA,EAWJ,GAAI,CAAC,OAAO,cAAc6I,EAAM,UAAU,EACxC,MAAM,IAAIP,EACR,4CAA4C,KAAK,UAAUO,EAAM,UAAU,CAAC,GAC5E,oBAAA,EAGJ,GAAI,CAAC,OAAO,cAAcE,CAAG,EAC3B,MAAM,IAAIT,EACR,qCAAqC,KAAK,UAAUS,CAAG,CAAC,GACxD,oBAAA,EAGJ,GAAIF,EAAM,YAAcE,EACtB,MAAM,IAAIT,EACR,oCAAoCO,EAAM,UAAU,SAASE,CAAG,GAChE,SAAA,EAGJ,GAAI,CAAC,OAAO,cAAcC,CAAe,GAAKA,GAAmB,EAC/D,MAAM,IAAIV,EACR,wDAAwD,KAAK,UAAUU,CAAe,CAAC,GACvF,sBAAA,EAGJ,GAAIH,EAAM,WAAaE,EAAMC,EAC3B,MAAM,IAAIV,EACR,mEACgBO,EAAM,UAAU,SAASE,CAAG,kBAAkBC,CAAe,IAC7E,iBAAA,EAIJ,MAAMG,EAAMD,EAAAA,eAAeL,EAAM,gBAAgB,EAAE,YAAA,EACnD,GAAIM,EAAI,SAAW9E,EAAAA,2BAA6B,CAACP,EAAAA,OAAO,KAAKqF,CAAG,EAC9D,MAAM,IAAIb,EACR,wDAAwDa,EAAI,MAAM,SAClE,0BAAA,EAGJ,MAAMC,EAASD,EAAI,MAAM,EAAG,CAAC,EAC7B,GAAIC,IAAW,MAAQA,IAAW,KAChC,MAAM,IAAId,EACR,2DAA2Dc,CAAM,GACjE,0BAAA,EASJ,MAAMC,EAAWZ,EAAWU,CAAG,EAC/B,GAAI,CAACG,GAAI,QAAQD,CAAQ,EACvB,MAAM,IAAIf,EACR,kDACA,0BAAA,EAIJ,MAAMiB,EAAML,EAAAA,eAAeL,EAAM,SAAS,EAAE,YAAA,EAC5C,GAAIU,EAAI,SAAWC,EAAAA,qBAAuB,CAAC1F,EAAAA,OAAO,KAAKyF,CAAG,EACxD,MAAM,IAAIjB,EACR,8CAA8CiB,EAAI,MAAM,SACxD,4BAAA,EAQJ,MAAME,EAAU7B,GACdQ,GACAK,EAAWU,CAAG,EACdN,EAAM,UAAA,EAGR,GAAI,CADaa,EAAAA,mBAAmBD,EAAShB,EAAWzI,CAAM,EAAGyI,EAAWc,CAAG,CAAC,EAE9E,MAAM,IAAIjB,EACR,gGACA,+BAAA,CAGN,CClOO,MAAMqB,OAA8C,IAAI,CAC7D,uCACA,6CACA,mDACF,CAAC,EAEYC,OAAmD,IAAI,CAClE,gDACF,CAAC,ECjBKC,GAAuB,IAEhBC,EAAqB,4BAQrBC,EAA0B,gCAEhC,SAASC,GACdtD,EACAuD,EACe,CACf,OAAO,IAAIrD,EAAAA,cAAc,CACvB,QAAAF,EACA,QAASmD,GACT,QAAAI,EACA,aAAeC,GACbA,IAAWJ,GAAsBI,IAAWH,CAAA,CAC/C,CACH,CCZA,MAAMI,GAAqB,EACrBC,GAAqB,EACrBC,EAAoB,EACpBC,GAAoB,EACpBC,GAAc,EACdC,GAAY,EACZC,GAAY,EACZC,GAAe,EAMfC,GAAqB,GAErBC,GAAmB,GAGnBC,GAAe,GACfC,GAAc,GACdC,GAAc,GAUdC,GAAoB,IA2BnB,MAAMC,UAAwB,KAAM,CACzC,YAAY1C,EAAiB,CAC3B,MAAM,gBAAgBA,CAAO,EAAE,EAC/B,KAAK,KAAO,iBACd,CACF,CAMO,MAAM2C,EAAW,CAKtB,YAAYC,EAAiB,CAJpBxH,EAAA,YAETA,EAAA,WAAM,GAGJ,KAAK,IAAMwH,CACb,CAEQ,UAAmB,CACzB,GAAI,KAAK,KAAO,KAAK,IAAI,OACvB,MAAM,IAAIF,EAAgB,yBAAyB,EAErD,OAAO,KAAK,IAAI,KAAK,KAAK,CAC5B,CAQA,UAAqB,CACnB,MAAMG,EAAU,KAAK,SAAA,EACfrE,EAAQqE,GAAW,EACnBC,EAAOD,EAAU,GAEvB,GAAIC,EAAOV,GACT,MAAO,CAAE,MAAA5D,EAAO,IAAKsE,CAAA,EAEvB,GAAIA,GAAQT,GACV,MAAM,IAAIK,EACR,+BAA+BI,CAAI,kCAAA,EAIvC,MAAMC,EAAY,GAAMD,EAAOV,GAE/B,IAAIrH,EAAQ,GACZ,QAASd,EAAI,EAAGA,EAAI8I,EAAW9I,IAC7Bc,EAASA,GAAS,GAAM,OAAO,KAAK,UAAU,EAEhD,GAAIA,EAAQ,OAAO,OAAO,gBAAgB,EACxC,MAAM,IAAI2H,EAAgB,YAAY3H,CAAK,6BAA6B,EAE1E,MAAO,CAAE,MAAAyD,EAAO,IAAK,OAAOzD,CAAK,CAAA,CACnC,CAGQ,UAAUiI,EAA4B,CAC5C,GAAI,KAAK,IAAMA,EAAS,KAAK,IAAI,OAC/B,MAAM,IAAIN,EAAgB,8BAA8B,EAE1D,MAAMO,EAAQ,KAAK,IAAI,SAAS,KAAK,IAAK,KAAK,IAAMD,CAAM,EAC3D,YAAK,KAAOA,EACLC,CACT,CAMA,gBAA6B,CAC3B,MAAMC,EAAO,KAAK,SAAA,EAClB,GAAIA,EAAK,QAAUpB,EACjB,MAAM,IAAIY,EACR,+BAA+BZ,CAAiB,gBAAgBoB,EAAK,KAAK,EAAA,EAG9E,OAAO,KAAK,UAAUA,EAAK,GAAG,CAChC,CASA,UAAUC,EAAQ,EAAc,CAC9B,GAAIA,EAAQV,GACV,MAAM,IAAIC,EACR,iCAAiCD,EAAiB,EAAA,EAGtD,MAAMS,EAAO,KAAK,SAAA,EAClB,OAAQA,EAAK,MAAA,CACX,KAAKtB,GACH,OAAOsB,EAAK,IACd,KAAKrB,GAEH,MAAO,GAAKqB,EAAK,IACnB,KAAKpB,EACH,OAAO,KAAK,UAAUoB,EAAK,GAAG,EAChC,KAAKnB,GACH,OAAO,IAAI,YAAY,QAAS,CAAE,MAAO,EAAA,CAAM,EAAE,OAC/C,KAAK,UAAUmB,EAAK,GAAG,CAAA,EAE3B,KAAKlB,GAAa,CAChB,MAAM7C,EAAqB,CAAA,EAC3B,QAAS,EAAI,EAAG,EAAI+D,EAAK,IAAK,IAC5B/D,EAAM,KAAK,KAAK,UAAUgE,EAAQ,CAAC,CAAC,EAEtC,OAAOhE,CACT,CACA,KAAK8C,GAAW,CACd,MAAMmB,MAAU,IAChB,QAAS,EAAI,EAAG,EAAIF,EAAK,IAAK,IAAK,CACjC,MAAMhG,EAAM,KAAK,UAAUiG,EAAQ,CAAC,EAC9BpI,EAAQ,KAAK,UAAUoI,EAAQ,CAAC,EACtCC,EAAI,IAAIlG,EAAKnC,CAAK,CACpB,CACA,OAAOqI,CACT,CACA,KAAKlB,GACH,MAAO,CAAE,IAAKgB,EAAK,IAAK,MAAO,KAAK,UAAUC,EAAQ,CAAC,CAAA,EACzD,KAAKhB,GACH,GAAIe,EAAK,MAAQZ,GAAc,MAAO,GACtC,GAAIY,EAAK,MAAQX,GAAa,MAAO,GACrC,GAAIW,EAAK,MAAQV,GAAa,OAAO,KACrC,MAAM,IAAIE,EACR,kCAAkCQ,EAAK,GAAG,EAAA,EAE9C,QACE,MAAM,IAAIR,EAAgB,0BAA0BQ,EAAK,KAAK,EAAE,CAAA,CAEtE,CACF,CAWO,SAASG,GAAWnE,EAA8B,CACvD,MAAMoE,EAAS,IAAIX,GAAWzD,CAAK,EAC7BnE,EAAQuI,EAAO,UAAA,EACrB,GAAIA,EAAO,MAAQpE,EAAM,OACvB,MAAM,IAAIwD,EAAgB,qCAAqC,EAEjE,OAAO3H,CACT,CC/MO,MAAMwI,GAAsB,iBAEtBC,GAAmB,cAG1BC,GAAiB,GAEjBC,EAAuB,EAEvBC,GAAkB,IAElBC,GAAwB,EAExBC,GAAwB,GAGxBC,GAAkB,IAElBC,GAAwB,GAExBC,GAAyB,GAGzBC,GAAgB,EAChBC,GAAgB,EAChBC,GAAgB,EAChBC,GAAgB,EAChBC,GAAgB,EAChBC,GAAgB,EAChBC,GAAgB,EAMhBC,GAAwB,IAAI,cAAc,OAAO,YAAY,EAe5D,MAAMC,UAA6B,KAAM,CAC9C,YACEzE,EACgBC,EAChB,CACA,MAAMD,CAAO,EAFG,KAAA,OAAAC,EAGhB,KAAK,KAAO,sBACd,CACF,CAgDO,SAASyE,GACdrE,EACmB,CACnB,MAAMsE,EAAiBC,GACrBvE,EAAM,0BACN,2BAAA,EAEIwE,EAAmBD,GACvBvE,EAAM,4BACN,6BAAA,EAEIyE,EAAYC,GAAuB1E,EAAM,kBAAkB,EAE3D2E,EAAaC,GAAiB5E,EAAM,KAAK,EAMzCiD,EAAS,IAAIX,GAAWqC,CAAU,EAClCtG,EAAM4E,EAAO,SAAA,EACnB,GAAI5E,EAAI,QAAU,GAAKA,EAAI,MAAQ+E,GACjC,MAAM,IAAIgB,EACR,+CAA+ChB,EAAc,IAC7D,yBAAA,EAGJ,MAAMyB,EAAQ5B,EAAO,SAAA,EACrB,GAAI4B,EAAM,QAAU,GAAKA,EAAM,MAAQxB,EACrC,MAAM,IAAIe,EACR,wBAAwBf,CAAoB,iBAC5C,yBAAA,EAIJ,MAAMyB,EAAiB7B,EAAO,IACxB8B,EAAmB9B,EAAO,eAAA,EAC1B+B,EAAgBL,EAAW,SAASG,EAAgB7B,EAAO,GAAG,EAGpEA,EAAO,UAAA,EAEP,MAAMgC,EAAehC,EAAO,IACtBiC,EAAiBjC,EAAO,eAAA,EACxBkC,EAAcR,EAAW,SAASM,EAAchC,EAAO,GAAG,EAE1DmC,EAAYnC,EAAO,eAAA,EACzB,GAAImC,EAAU,SAAW5B,GACvB,MAAM,IAAIY,EACR,0BAA0BZ,EAAqB,eAAe4B,EAAU,MAAM,GAC9E,yBAAA,EAMJ,GAAInC,EAAO,MAAQ0B,EAAW,OAC5B,MAAM,IAAIP,EACR,0DACA,yBAAA,EAKJ,MAAMiB,EAAMC,GAAuBP,CAAgB,EACnD,GAAIM,IAAQ/B,GACV,MAAM,IAAIc,EACR,6BAA6BiB,CAAG,qBAAqB/B,EAAe,IACpE,sBAAA,EAKJ,MAAMiC,EAAeC,GAAkBR,EAAeG,CAAW,EAC3DM,EAASC,GAAAA,OAAOH,CAAY,EAElC,GAAI,CAAC7E,GAAI,OAAO+E,EAAQhB,EAAWW,EAAW,EAAI,EAChD,MAAM,IAAIhB,EACR,oEACA,+BAAA,EAKJ,MAAMuB,EAASC,GAAaV,CAAc,EAEpCW,EAAWF,EAAO,SAAS,YAAA,EACjC,GAAIE,EAAS,SAAWrK,EAAAA,uBAAyB,CAACN,EAAAA,OAAO,KAAK2K,CAAQ,EACpE,MAAM,IAAIzB,EACR,iDACA,gBAAA,EAGJ,GAAIuB,EAAO,SAAWA,EAAO,UAC3B,MAAM,IAAIvB,EACR,cAAcuB,EAAO,QAAQ,mBAAmBA,EAAO,SAAS,IAChE,gBAAA,EAIJ,GAAIA,EAAO,OAAO,YAAA,IAAkBrB,EAClC,MAAM,IAAIF,EACR,8DAA8DE,CAAc,SAASqB,EAAO,OAAO,aAAa,GAChH,iBAAA,EAGJ,GAAIA,EAAO,UAAY3F,EAAM,gBAC3B,MAAM,IAAIoE,EACR,oCAAoCpE,EAAM,eAAe,SAAS2F,EAAO,OAAO,GAChF,kBAAA,EAGJ,GAAIE,IAAarB,EACf,MAAM,IAAIJ,EACR,4DAA4DI,CAAgB,SAASqB,CAAQ,GAC7F,mBAAA,EAKJ,GAAIF,EAAO,WAAa3F,EAAM,IAC5B,MAAM,IAAIoE,EACR,sBAAsBuB,EAAO,SAAS,WAAW3F,EAAM,GAAG,GAC1D,eAAA,EAGJ,GAAIA,EAAM,oBAAsB2F,EAAO,UACrC,MAAM,IAAIvB,EACR,wBAAwBpE,EAAM,iBAAiB,+BAA+B2F,EAAO,SAAS,IAC9F,iBAAA,EAGJ,GAAI3F,EAAM,wBAA0B2F,EAAO,UACzC,MAAM,IAAIvB,EACR,4BAA4BpE,EAAM,uBAAuB,uBAAuB2F,EAAO,SAAS,IAChG,sCAAA,EAIJ,MAAO,CACL,OAAQA,EAAO,OACf,QAASA,EAAO,QAChB,SAAAE,EACA,UAAWF,EAAO,UAClB,UAAWA,EAAO,UAClB,SAAUA,EAAO,QAAA,CAErB,CAGA,SAASL,GAAuBP,EAAsC,CACpE,GAAIA,EAAiB,SAAW,EAC9B,MAAM,IAAIX,EACR,6CACA,sBAAA,EAGJ,MAAM0B,EAAS9C,GAAW+B,CAAgB,EAC1C,GAAI,EAAEe,aAAkB,KACtB,MAAM,IAAI1B,EACR,qCACA,yBAAA,EAGJ,MAAMiB,EAAMS,EAAO,IAAIvC,EAAqB,EAC5C,GAAI,OAAO8B,GAAQ,SACjB,MAAM,IAAIjB,EACR,wDACA,sBAAA,EAGJ,OAAOiB,CACT,CAWA,SAASG,GACPR,EACAG,EACY,CACZ,OAAOY,GACL,WAAW,GAAGtC,GAAkBJ,CAAoB,EACpD,WAAW,GAAGK,GAAwBS,GAAsB,MAAM,EAClEA,GACAa,EACA,WAAW,GAAGrB,EAAsB,EACpCwB,CAAA,CAEJ,CAYA,SAASS,GAAaV,EAA2C,CAC/D,MAAMc,EAAOhD,GAAWkC,CAAc,EACtC,GAAI,EAAEc,aAAgB,KACpB,MAAM,IAAI5B,EACR,+BACA,gBAAA,EAIJ,GADY6B,GAAaD,EAAM9B,GAAe,KAAK,EAC3C,SAAW,EACjB,MAAM,IAAIE,EAAqB,qBAAsB,gBAAgB,EAEvE,MAAO,CACL,OAAQ8B,EAAcF,EAAMpC,GAAe,KAAK,EAChD,QAASsC,EAAcF,EAAMnC,GAAe,KAAK,EACjD,SAAUqC,EAAcF,EAAMlC,GAAe,KAAK,EAClD,UAAWqC,EAAiBH,EAAMjC,GAAe,KAAK,EACtD,UAAWoC,EAAiBH,EAAMhC,GAAe,KAAK,EACtD,SAAUmC,EAAiBH,EAAM/B,GAAe,KAAK,CAAA,CAEzD,CAEA,SAASiC,EACPP,EACA9I,EACAuJ,EACQ,CACR,MAAM1L,EAAQiL,EAAO,IAAI9I,CAAG,EAC5B,GAAI,OAAOnC,GAAU,SACnB,MAAM,IAAI0J,EACR,eAAegC,CAAI,mCACnB,gBAAA,EAGJ,OAAO1L,CACT,CAEA,SAASuL,GACPN,EACA9I,EACAuJ,EACY,CACZ,MAAM1L,EAAQiL,EAAO,IAAI9I,CAAG,EAC5B,GAAI,EAAEnC,aAAiB,YACrB,MAAM,IAAI0J,EACR,eAAegC,CAAI,mCACnB,gBAAA,EAGJ,OAAO1L,CACT,CAEA,SAASyL,EACPR,EACA9I,EACAuJ,EACQ,CACR,MAAM1L,EAAQiL,EAAO,IAAI9I,CAAG,EAC5B,GAAI,OAAOnC,GAAU,UAAY,CAAC,OAAO,cAAcA,CAAK,GAAKA,EAAQ,EACvE,MAAM,IAAI0J,EACR,eAAegC,CAAI,sDACnB,gBAAA,EAGJ,OAAO1L,CACT,CAGA,SAAS6J,GAAe8B,EAAgB/O,EAAuB,CAC7D,MAAMgP,EAAahG,EAAAA,eAAe+F,CAAM,EAAE,YAAA,EAC1C,GAAIC,EAAW,SAAW9K,EAAAA,uBAAyB,CAACN,EAAAA,OAAO,KAAKoL,CAAU,EACxE,MAAM,IAAIlC,EACR,GAAG9M,CAAK,oCAAoCgP,EAAW,MAAM,SAC7D,eAAA,EAGJ,OAAOA,CACT,CAGA,SAAS5B,GAAuB6B,EAA+B,CAC7D,MAAMD,EAAahG,EAAAA,eAAeiG,CAAS,EAAE,YAAA,EACvC/F,EAAS8F,EAAW,MAAM,EAAG,CAAC,EACpC,GACEA,EAAW,SAAW7K,EAAAA,2BACtB,CAACP,EAAAA,OAAO,KAAKoL,CAAU,GACtB9F,IAAW,MAAQA,IAAW,KAE/B,MAAM,IAAI4D,EACR,0EACA,eAAA,EAGJ,OAAOoC,EAAAA,gBAAgBF,CAAU,CACnC,CAEA,MAAMG,IAAiB,IAAM,CAC3B,MAAMC,EAAQ,IAAI,WAAW,GAAG,EAAE,KAAK,EAAE,EACnCC,EACJ,mEACF,QAAS/M,EAAI,EAAGA,EAAI+M,EAAS,OAAQ/M,IACnC8M,EAAMC,EAAS,WAAW/M,CAAC,CAAC,EAAIA,EAElC,OAAO8M,CACT,GAAA,EAGA,SAAS9B,GAAiB5E,EAA2B,CACnD,MAAM4G,EAAM5G,EAAM,OACZ6G,EAAa,KAAK,MAAMD,EAAM,CAAC,EAC/BE,EAAYF,EAAM,EACxB,GAAIE,IAAc,EAChB,MAAM,IAAI1C,EACR,2BACA,yBAAA,EAGJ,MAAM2C,EAASF,EAAa,GAAKC,IAAc,EAAI,EAAIA,EAAY,GAC7DxI,EAAM,IAAI,WAAWyI,CAAM,EAE3BC,EAAUC,GAA6B,CAC3C,MAAMvM,EAAQuM,EAAW,IAAMR,GAAcQ,CAAQ,EAAI,GACzD,GAAIvM,EAAQ,EACV,MAAM,IAAI0J,EACR,8BACA,yBAAA,EAGJ,OAAO1J,CACT,EAEA,IAAIwM,EAAQ,EACRC,EAAS,EACb,QAASC,EAAI,EAAGA,EAAIP,EAAYO,IAAK,CACnC,MAAMC,EAAIL,EAAOhH,EAAM,WAAWkH,GAAO,CAAC,EACpCnI,EAAIiI,EAAOhH,EAAM,WAAWkH,GAAO,CAAC,EACpC3K,EAAIyK,EAAOhH,EAAM,WAAWkH,GAAO,CAAC,EACpCzK,EAAIuK,EAAOhH,EAAM,WAAWkH,GAAO,CAAC,EAC1C5I,EAAI6I,GAAQ,EAAKE,GAAK,EAAMtI,GAAK,EACjCT,EAAI6I,GAAQ,GAAMpI,EAAI,KAAS,EAAMxC,GAAK,EAC1C+B,EAAI6I,GAAQ,GAAM5K,EAAI,IAAS,EAAKE,CACtC,CACA,GAAIqK,IAAc,EAAG,CACnB,MAAMO,EAAIL,EAAOhH,EAAM,WAAWkH,GAAO,CAAC,EACpCnI,EAAIiI,EAAOhH,EAAM,WAAWkH,GAAO,CAAC,EAC1C5I,EAAI6I,GAAQ,EAAKE,GAAK,EAAMtI,GAAK,CACnC,SAAW+H,IAAc,EAAG,CAC1B,MAAMO,EAAIL,EAAOhH,EAAM,WAAWkH,GAAO,CAAC,EACpCnI,EAAIiI,EAAOhH,EAAM,WAAWkH,GAAO,CAAC,EACpC3K,EAAIyK,EAAOhH,EAAM,WAAWkH,GAAO,CAAC,EAC1C5I,EAAI6I,GAAQ,EAAKE,GAAK,EAAMtI,GAAK,EACjCT,EAAI6I,GAAQ,GAAMpI,EAAI,KAAS,EAAMxC,GAAK,CAC5C,CACA,OAAO+B,CACT,CAEA,SAASyH,MAAevH,EAAiC,CACvD,MAAMC,EAAQD,EAAM,OAAO,CAAC8I,EAAKC,IAASD,EAAMC,EAAK,OAAQ,CAAC,EACxDjJ,EAAM,IAAI,WAAWG,CAAK,EAChC,IAAIE,EAAS,EACb,UAAW4I,KAAQ/I,EACjBF,EAAI,IAAIiJ,EAAM5I,CAAM,EACpBA,GAAU4I,EAAK,OAEjB,OAAOjJ,CACT,CCzcA,MAAMkJ,GAAsB,WAOtBC,GAA4B,GA4D3B,MAAMC,EAA+C,CAsB1D,YAAYpO,EAA+B,CAjBnCyB,EAAA,eACSA,EAAA,kBACAA,EAAA,sBACAA,EAAA,2BACAA,EAAA,oCACAA,EAAA,yBACAA,EAAA,yBACAA,EAAA,wBACAA,EAAA,YAGTA,EAAA,qBAAoC,MACpCA,EAAA,uBAA+C,MAE/CA,EAAA,kBAAiC,MACjCA,EAAA,oBAA4C,MAGlD,KAAK,OAASzB,EAAO,OACrB,KAAK,UAAYA,EAAO,UACxB,KAAK,cAAgBA,EAAO,cAC5B,KAAK,mBAAqBA,EAAO,mBACjC,KAAK,4BAA8BA,EAAO,4BAC1C,KAAK,iBAAmBA,EAAO,iBAC/B,KAAK,iBAAmBA,EAAO,iBAC/B,KAAK,gBAAkBA,EAAO,iBAAmBmO,GACjD,KAAK,IAAMnO,EAAO,MAAQ,IAAM,KAAK,MAAM,KAAK,MAAQ,GAAI,EAC9D,CAmBA,MAAM,SAASgI,EAAwC,CACrD,OAAIA,IAAWJ,GAAsBI,IAAWH,EACvC,KAGL,KAAK,iBAAiB,IAAIG,CAAM,EAC3B,KAAK,mBAAmB,MAAM,EAEnC,KAAK,iBAAiB,IAAIA,CAAM,EAC3B,KAAK,mBAAmB,SAAS,EAEnC,IACT,CAYA,YAAmB,CACjB,KAAK,cAAgB,KACrB,KAAK,WAAa,IAKpB,CAEA,MAAc,mBACZqG,EACiB,CACjB,MAAMC,EACJD,IAAY,OAAS,KAAK,WAAa,KAAK,cAC9C,OAAIC,GAAU,KAAK,IAAA,EAAQ,KAAK,gBAAkBA,EAAO,UAChDA,EAAO,OAEF,MAAM,KAAK,oBAAoBD,CAAO,GACvC,KACf,CAUA,UAAUE,EAA6B,CACrC,KAAK,OAASA,CAChB,CAEQ,oBACNF,EACsB,CACtB,MAAMG,EACJH,IAAY,OAAS,KAAK,aAAe,KAAK,gBAChD,GAAIG,EAAU,OAAOA,EAErB,MAAMC,EACJJ,IAAY,OAASxG,EAA0BD,EAE3CrF,GAAK,SAAY,CACrB,GAAI,CACF,MAAME,EAAW,MAAM,KAAK,OAAO,KAGjCgM,EAAa,CACb,WAAY,KAAK,UACjB,YAAa,KAAK,aAAA,CACnB,EAWD,GATAhI,GAAqB,CACnB,MAAOhE,EAAS,gBAChB,mBAAoB,KAAK,mBACzB,IAAK,KAAK,IAAA,CAAI,CACf,EAKG,OAAOA,EAAS,OAAU,UAAYA,EAAS,MAAM,SAAW,EAClE,MAAM,IAAI,MACR,sFAAsF,OAAOA,EAAS,KAAK,GAAA,EAG/G,MAAMoE,EAAM,KAAK,IAAA,EACjB,GACE,CAAC,OAAO,cAAcpE,EAAS,UAAU,GACzCA,EAAS,YAAcoE,GACvBpE,EAAS,WAAayL,GAEtB,MAAM,IAAI,MACR,gEAAgE,KAAK,UAAUzL,EAAS,UAAU,CAAC,gCAAgCoE,CAAG,KAAKqH,EAAmB,IAAA,EAUlKnD,GAAmB,CACjB,MAAOtI,EAAS,MAChB,mBAAoBA,EAAS,gBAAgB,iBAC7C,0BAA2B,KAAK,mBAChC,gBACE4L,IAAY,OAASxE,GAAmBD,GAC1C,4BAA6B,KAAK,4BAClC,kBAAmBnH,EAAS,WAC5B,wBAAyBA,EAAS,gBAAgB,WAClD,IAAAoE,CAAA,CACD,EAED,MAAM6H,EAAqB,CACzB,MAAOjM,EAAS,MAChB,UAAWA,EAAS,UAAA,EAEtB,OAAI4L,IAAY,OACd,KAAK,WAAaK,EAElB,KAAK,cAAgBA,EAEhBA,CACT,QAAA,CACML,IAAY,OACd,KAAK,aAAe,KAEpB,KAAK,gBAAkB,IAE3B,CACF,GAAA,EAEA,OAAIA,IAAY,OACd,KAAK,aAAe9L,EAEpB,KAAK,gBAAkBA,EAElBA,CACT,CACF,CC3RO,MAAMoM,EAAgB,CAAtB,cACYlN,EAAA,mBAAc,KAQ/B,YAAYiF,EAA8C,CACxD,MAAM8H,EAAW,KAAK,QAAQ,IAAI9H,EAAM,SAAS,EACjD,GAAI8H,EAAU,CACZ,GAAIA,EAAS,gBAAkB9H,EAAM,cACnC,MAAM,IAAI,MACR,8BAA8BA,EAAM,SAAS,mCAAmC8H,EAAS,cAAc,MAAM,EAAG,CAAC,CAAC,UAAU9H,EAAM,cAAc,MAAM,EAAG,CAAC,CAAC,GAAA,EAG/J,GAAI8H,EAAS,qBAAuB9H,EAAM,mBACxC,MAAM,IAAI,MACR,8BAA8BA,EAAM,SAAS,wCAAwC8H,EAAS,mBAAmB,MAAM,EAAG,CAAC,CAAC,UAAU9H,EAAM,mBAAmB,MAAM,EAAG,CAAC,CAAC,GAAA,EAG9K,GACE8H,EAAS,8BACT9H,EAAM,4BAEN,MAAM,IAAI,MACR,8BAA8BA,EAAM,SAAS,iDAAiD8H,EAAS,4BAA4B,MAAM,EAAG,CAAC,CAAC,UAAU9H,EAAM,4BAA4B,MAAM,EAAG,CAAC,CAAC,GAAA,EAMzM,OAAA8H,EAAS,SAAS,UAAU9H,EAAM,MAAM,EACjC8H,EAAS,QAClB,CAEA,MAAMI,EAAW,IAAIR,GAAgB,CACnC,OAAQ1H,EAAM,OACd,UAAWA,EAAM,UACjB,cAAeA,EAAM,cACrB,mBAAoBA,EAAM,mBAC1B,4BAA6BA,EAAM,4BACnC,iBAAkBe,GAClB,iBAAkBC,EAAA,CACnB,EACD,YAAK,QAAQ,IAAIhB,EAAM,UAAW,CAChC,SAAAkI,EACA,cAAelI,EAAM,cACrB,mBAAoBA,EAAM,mBAC1B,4BAA6BA,EAAM,2BAAA,CACpC,EACMkI,CACT,CAGA,KAAKC,EAAgD,OACnD,OAAOxN,EAAA,KAAK,QAAQ,IAAIwN,CAAS,IAA1B,YAAAxN,EAA6B,QACtC,CAOA,QAAQwN,EAAyB,CAC/B,KAAK,QAAQ,OAAOA,CAAS,CAC/B,CAQA,OAAc,CACZ,KAAK,QAAQ,MAAA,CACf,CAEA,IAAI,MAAe,CACjB,OAAO,KAAK,QAAQ,IACtB,CACF,CAaO,MAAMC,EAAyC,IAAIH,GCvFnD,SAASI,GACd/O,EACwB,OACxB,MAAMgP,EAAmBlH,GACvB9H,EAAO,SACPqB,EAAArB,EAAO,UAAP,YAAAqB,EAAgB,OAAA,EAGZ4N,EAAgBH,EAAgB,YAAY,CAChD,OAAQE,EACR,UAAWhP,EAAO,UAClB,cAAeA,EAAO,cACtB,mBAAoBA,EAAO,mBAC3B,4BAA6BkP,EAAAA,wBAC3BlP,EAAO,kBAAA,CACT,CACD,EAED,OAAO,IAAIuE,GAAuBvE,EAAO,QAAS,CAChD,GAAGA,EAAO,QACV,cAAAiP,CAAA,CACD,CACH,CC/BO,SAASE,GAAqBzI,EAA+B,CAClEoI,EAAgB,YAAY,CAC1B,OAAQhH,GAAsBpB,EAAM,QAASA,EAAM,OAAO,EAC1D,UAAWA,EAAM,UACjB,cAAeA,EAAM,cACrB,mBAAoBA,EAAM,mBAC1B,4BAA6BwI,EAAAA,wBAC3BxI,EAAM,kBAAA,CACR,CACD,CACH,CCIO,SAAS0I,GACdC,EACAnR,EAC2B,CAC3B,MAAMoR,MAAmB,IACzB,UAAWC,KAAQF,EACjBC,EAAa,IAAIC,EAAK,aAAa,EAGrC,MAAMC,MAAa,IAIbC,MAAW,IACXC,EAAsB,CAAA,EACtBC,EAAuB,CAAA,EAE7B,UAAW3L,KAAS9F,EAAS,CAC3B,MAAM0R,EAAQ5L,EAAM,WAAW,YAAA,EAC/B,GAAI,CAACsL,EAAa,IAAIM,CAAK,EAAG,CAC5BD,EAAW,KAAKC,CAAK,EACrB,QACF,CACA,GAAIH,EAAK,IAAIG,CAAK,EAAG,CACnBF,EAAU,KAAKE,CAAK,EACpB,QACF,CACAH,EAAK,IAAIG,CAAK,EACdJ,EAAO,IAAII,EAAO,CAAE,OAAQ5L,EAAM,OAAQ,MAAOA,EAAM,MAAO,CAChE,CAEA,MAAM6L,EAAoB,CAAA,EAC1B,UAAWN,KAAQD,EACZG,EAAK,IAAIF,CAAI,GAAGM,EAAQ,KAAKN,CAAI,EAGxC,MAAO,CAAE,OAAAC,EAAQ,QAAAK,EAAS,WAAAF,EAAY,UAAAD,CAAA,CACxC,CCRA,eAAsBI,GACpBrL,EACe,CACf,KAAM,CACJ,MAAAe,EACA,QAAAuK,EACA,UAAAC,EACA,OAAAC,EACA,UAAAC,EACA,YAAAC,EACA,iBAAAC,EACA,kBAAAC,EACA,aAAAC,EACA,UAAAC,EAAYC,EAAAA,iBAAA,EACV/L,EAEJ,GAAI,CAAC,OAAO,UAAU8L,CAAS,GAAKA,GAAa,EAC/C,MAAM,IAAI,MACR,kEAAkEA,CAAS,EAAA,EAI/E,QAASjQ,EAAI,EAAGA,EAAIkF,EAAM,OAAQlF,GAAKiQ,EAAW,CAChD,MAAME,EAAQjL,EAAM,MAAMlF,EAAGA,EAAIiQ,CAAS,EACpCG,MAAiB,IACjBC,EAAkB,CAAA,EACxB,UAAWC,KAAQH,EAAO,CACxB,MAAMI,EAAYd,EAAQa,CAAI,EAAE,YAAA,EAChCF,EAAW,IAAIG,EAAWD,CAAI,EAC9BD,EAAM,KAAKE,CAAS,CACtB,CAKA,IAAIC,EACJ,GAAI,CACF,MAAMrO,EAAW,MAAMuN,EAAUW,CAAK,EACtCG,EAAc1B,GAA+BuB,EAAOlO,EAAS,OAAO,CACtE,OAAShC,EAAO,CACd4P,EAAkBI,EAAOhQ,CAAK,EAC9B,QACF,CAEI6P,GAAgBQ,EAAY,WAAW,OAAS,GAClDR,EAAaQ,EAAY,UAAU,EAGrC,MAAMC,EAAiB,IAAI,IAAID,EAAY,SAAS,EACpD,UAAWvB,KAAQwB,EAAgB,CACjC,MAAMH,EAAOF,EAAW,IAAInB,CAAI,EAC5BqB,KAAkBA,CAAI,CAC5B,CACIR,GAAoBW,EAAe,KAAO,GAC5CX,EAAiBW,EAAe,IAAI,EAEtC,UAAWxB,KAAQuB,EAAY,QAAS,CACtC,MAAMF,EAAOF,EAAW,IAAInB,CAAI,EAC5BqB,KAAgBA,CAAI,CAC1B,CACA,SAAW,CAACrB,EAAMyB,CAAQ,IAAKF,EAAY,OAAQ,CAEjD,GAAIC,EAAe,IAAIxB,CAAI,EAAG,SAC9B,MAAMqB,EAAOF,EAAW,IAAInB,CAAI,EAC3BqB,GACLX,EAAOW,EAAM,CACX,WAAYrB,EACZ,OAAQyB,EAAS,OACjB,MAAOA,EAAS,KAAA,CACjB,CACH,CACF,CACF"}