{"version":3,"file":"mempoolApi-BJN9fGEd.cjs","sources":["../src/tbv/core/clients/vault-provider/auth/bip322Verify.ts","../src/tbv/core/clients/eth/protocol-params-validation.ts","../src/tbv/core/clients/eth/vault-registry-reader.ts","../src/tbv/core/clients/mempool/mempoolApi.ts"],"sourcesContent":["/**\n * BIP-322 \"simple\" signature verification for P2TR key-path and P2WPKH.\n *\n * Mirrors the Rust reference in\n * `btc-vault/crates/btc-signer/src/message.rs` (`verify_bip322_message`\n * and the P2WPKH arm of `verify_pop_witness`, both of which delegate to\n * the `bip322` crate 0.0.10's `verify_simple`).\n *\n * The algorithm:\n *\n *   1. Compute the BIP-322 tagged-hash of the message:\n *        m_hash = SHA256( SHA256(tag) || SHA256(tag) || message )\n *      where tag = \"BIP0322-signed-message\".\n *\n *   2. Build a virtual \"to_spend\" transaction with one input (prevout\n *      all-zero txid + 0xFFFFFFFF vout, scriptSig = `OP_0 PUSH32 m_hash`,\n *      sequence = 0) and one output (value 0, scriptPubKey = the signer's\n *      address: P2TR key-path-only, or P2WPKH of the compressed pubkey).\n *\n *   3. Build a \"to_sign\" transaction that spends to_spend[0] and has a\n *      single `OP_RETURN` output (value 0).\n *\n *   4. Compute the sighash of to_sign input 0: BIP-341 taproot for P2TR\n *      (SIGHASH_DEFAULT 0x00 unless the witness item carried a trailing\n *      SIGHASH_ALL 0x01 byte), BIP-143 with the standard P2WPKH\n *      scriptCode for P2WPKH (SIGHASH_ALL only).\n *\n *   5. Verify the signature: Schnorr against the **tweaked** output key\n *      `Q = P + tap_tweak(P) * G` for P2TR (no merkle root — key-path\n *      only), ECDSA against the compressed pubkey for P2WPKH.\n *\n * `bitcoinjs-lib` handles (2)–(4); `tiny-secp256k1-asmjs` provides\n * the tweak and the Schnorr/ECDSA verifies. Pulling in a full BIP-322\n * library would add a peer dep for what amounts to ~40 lines of glue.\n *\n * @module tbv/core/clients/vault-provider/auth/bip322Verify\n */\n\nimport * as ecc from \"@bitcoin-js/tiny-secp256k1-asmjs\";\nimport { script as bscript, payments, Transaction } from \"bitcoinjs-lib\";\n\nimport { sha256 } from \"@noble/hashes/sha2.js\";\nimport { Buffer } from \"buffer\";\n\n/** BIP-322 message tag (BIP-340 tagged-hash style). */\nconst BIP322_TAG = \"BIP0322-signed-message\";\n\n/** BIP-341 taproot-tweak tag. */\nconst TAPTWEAK_TAG = \"TapTweak\";\n\nconst X_ONLY_PUBKEY_SIZE = 32;\nconst SCHNORR_SIG_SIZE = 64;\n/** SEC1 compressed pubkey: 0x02/0x03 prefix + 32-byte x coordinate. */\nconst COMPRESSED_PUBKEY_SIZE = 33;\n/**\n * vaultd's P2WPKH BIP-322 verifier accepts ONLY 71/72-byte encoded\n * signatures — DER (70/71B) + sighash byte (`bip322` crate 0.0.10\n * `verify.rs:141-153`). A shorter (short-DER) signature fails ingestion\n * permanently, so this gate must be exactly as strict. Exported so\n * `verifyPopWitness` can pre-screen with a cause-naming error.\n */\nexport const P2WPKH_ENCODED_SIG_MIN = 71;\nexport const P2WPKH_ENCODED_SIG_MAX = 72;\n\n// NOTE: bitcoinjs-lib v6.x's `Transaction.addOutput` and its sighash\n// methods are typed for `Satoshi` (a UInt53 number), not `bigint`.\n// Passing `BigInt(0)` triggers a typeforce assertion in `addOutput`\n// (\"Expected property '1' of type Satoshi, got BigInt 0\") which the\n// verifiers' try/catch silently turns into `verify -> false`. Use\n// plain `0` everywhere.\nconst ZERO_SATS = 0;\n\n// Wire fields of the virtual to_spend/to_sign transactions (`bip322`\n// crate 0.0.10 `util.rs:18-85`).\nconst BIP322_TX_VERSION = 0;\nconst BIP322_TX_LOCKTIME = 0;\nconst BIP322_INPUT_SEQUENCE = 0;\n/** to_spend prevout: all-zero 32-byte txid at index 0xFFFFFFFF (`util.rs:18-85`). */\nconst TO_SPEND_PREVOUT_TXID_BYTES = 32;\nconst TO_SPEND_PREVOUT_INDEX = 0xffffffff;\n/** to_sign spends to_spend's only output (`util.rs:18-85`). */\nconst TO_SPEND_OUTPUT_INDEX = 0;\nconst OP_0 = 0x00;\n/** Direct push of the 32-byte tagged message hash. */\nconst OP_PUSHBYTES_32 = 0x20;\nconst OP_RETURN = 0x6a;\n\n/**\n * BIP-340 tagged hash: `SHA256( SHA256(tag) || SHA256(tag) || data )`.\n * Used for both BIP-322 message hashing and BIP-341 tap-tweak.\n */\nfunction taggedHash(tag: string, data: Uint8Array): Uint8Array {\n  const tagBytes = new TextEncoder().encode(tag);\n  const tagHash = sha256(tagBytes);\n  const preimage = new Uint8Array(tagHash.length * 2 + data.length);\n  preimage.set(tagHash, 0);\n  preimage.set(tagHash, tagHash.length);\n  preimage.set(data, tagHash.length * 2);\n  return sha256(preimage);\n}\n\n/**\n * Apply BIP-341 taproot tweak to an x-only pubkey with no merkle\n * root (key-path-only address).\n *\n * `tap_tweak = hash_TapTweak(P)`\n * `Q = P + tap_tweak * G` (x-only, even-Y parity)\n *\n * Returns the tweaked 32-byte x-only pubkey, or null if the tweak\n * produces a point-at-infinity or invalid result.\n */\nfunction tweakXOnlyKey(xOnly: Uint8Array): Uint8Array | null {\n  if (xOnly.length !== X_ONLY_PUBKEY_SIZE) return null;\n  const tweak = taggedHash(TAPTWEAK_TAG, xOnly);\n  const tweaked = ecc.xOnlyPointAddTweak(xOnly, tweak);\n  return tweaked ? tweaked.xOnlyPubkey : null;\n}\n\n/**\n * Build the BIP-322 virtual `to_sign` transaction for a signer\n * scriptPubKey (steps 1–3 above; `bip322` crate 0.0.10 `util.rs:18-85`:\n * both txs version 0, locktime 0, sequence 0, all values 0).\n */\nfunction buildToSignTransaction(\n  messageBytes: Uint8Array,\n  scriptPubKey: Buffer,\n): Transaction {\n  const messageHash = taggedHash(BIP322_TAG, messageBytes);\n\n  const toSpend = new Transaction();\n  toSpend.version = BIP322_TX_VERSION;\n  toSpend.locktime = BIP322_TX_LOCKTIME;\n  const scriptSig = Buffer.concat([\n    Buffer.from([OP_0, OP_PUSHBYTES_32]),\n    Buffer.from(messageHash),\n  ]);\n  toSpend.addInput(\n    Buffer.alloc(TO_SPEND_PREVOUT_TXID_BYTES, 0),\n    TO_SPEND_PREVOUT_INDEX,\n    BIP322_INPUT_SEQUENCE,\n    scriptSig,\n  );\n  toSpend.addOutput(scriptPubKey, ZERO_SATS);\n\n  const toSign = new Transaction();\n  toSign.version = BIP322_TX_VERSION;\n  toSign.locktime = BIP322_TX_LOCKTIME;\n  // Bitcoin txid in natural-byte (little-endian) form.\n  toSign.addInput(\n    toSpend.getHash(),\n    TO_SPEND_OUTPUT_INDEX,\n    BIP322_INPUT_SEQUENCE,\n  );\n  toSign.addOutput(Buffer.from([OP_RETURN]), ZERO_SATS);\n\n  return toSign;\n}\n\n/**\n * Verify a BIP-322 \"simple\" P2TR key-path signature over an arbitrary\n * byte message.\n *\n * @internal Consumed by `verifyServerIdentity` (VP auth) and\n * `verifyPopWitness` (PoP pre-registration check), and exposed so the\n * golden-vector test suite can pin the verifier independently.\n *\n * @param messageBytes - The bytes that were signed (e.g. a CBOR-encoded\n *                       payload). Not pre-hashed; this function applies\n *                       the BIP-322 tagged hash internally.\n * @param xOnlyPubkey  - 32-byte x-only pubkey of the signer (pre-tweak).\n * @param signature    - 64-byte raw Schnorr signature (BIP-340), as\n *                       emitted by a key-path witness. The trailing\n *                       sighash byte of a 65-byte witness item is not\n *                       part of it — pass it as `hashType` instead.\n * @param hashType     - BIP-341 sighash type the signature commits to.\n *                       `SIGHASH_DEFAULT` (0x00) for a 64-byte witness\n *                       item, `SIGHASH_ALL` (0x01) for a 65-byte one.\n * @returns `true` if the signature verifies against the address\n *          derived from `xOnlyPubkey`; `false` otherwise.\n */\nexport function verifyBip322Simple(\n  messageBytes: Uint8Array,\n  xOnlyPubkey: Uint8Array,\n  signature: Uint8Array,\n  hashType: number = Transaction.SIGHASH_DEFAULT,\n): boolean {\n  if (xOnlyPubkey.length !== X_ONLY_PUBKEY_SIZE) return false;\n  if (signature.length !== SCHNORR_SIG_SIZE) return false;\n  // Only the two types a BIP-322 witness may carry. SIGHASH_NONE/SINGLE and the\n  // ANYONECANPAY variants would verify here but are rejected downstream.\n  if (\n    hashType !== Transaction.SIGHASH_DEFAULT &&\n    hashType !== Transaction.SIGHASH_ALL\n  ) {\n    return false;\n  }\n\n  // Any exception from the underlying crypto libraries (e.g. the\n  // `Expected Point` error `tiny-secp256k1` throws when the supplied\n  // 32 bytes don't represent a valid x-coordinate on secp256k1) is\n  // treated as a verification failure rather than propagated — a\n  // verifier MUST return a boolean, not raise.\n  try {\n    // scriptPubKey for the signer's P2TR key-path-only address.\n    // bitcoinjs-lib's `payments.p2tr({ internalPubkey })` computes the\n    // tweak and produces the `OP_1 <tweaked_xonly>` output script.\n    const p2tr = payments.p2tr({\n      internalPubkey: Buffer.from(xOnlyPubkey),\n    });\n    if (!p2tr.output) return false;\n    const scriptPubKey = p2tr.output;\n\n    const toSign = buildToSignTransaction(messageBytes, scriptPubKey);\n\n    // Taproot sighash for to_sign input 0.\n    const sighash = toSign.hashForWitnessV1(\n      0,\n      [scriptPubKey],\n      [ZERO_SATS],\n      hashType,\n    );\n\n    // Tweak the x-only pubkey (no merkle root) and verify Schnorr.\n    const tweakedXOnly = tweakXOnlyKey(xOnlyPubkey);\n    if (!tweakedXOnly) return false;\n\n    return ecc.verifySchnorr(sighash, tweakedXOnly, signature);\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Verify a BIP-322 \"simple\" P2WPKH signature over an arbitrary byte\n * message, mirroring the verifier vaultd runs on a two-item PoP witness\n * (`bip322` crate 0.0.10 `verify.rs:102-186 verify_full_p2wpkh`).\n *\n * @internal Consumed by `verifyPopWitness` for Native SegWit software\n * wallets, and exposed so the BIP-322 official-vector test suite can pin\n * the verifier independently.\n *\n * @param compressedPubkey - 33-byte SEC1 compressed pubkey of the signer\n *                           (witness item 1). The address is derived from\n *                           it; network affects only bech32 encoding, not\n *                           script or sighash (`message.rs:125-127`).\n * @param encodedSignature - Witness item 0: DER signature with trailing\n *                           sighash byte, 71 or 72 bytes, SIGHASH_ALL only\n *                           (`verify.rs:141-161`).\n * @returns `true` if the signature verifies against the P2WPKH address of\n *          `compressedPubkey`; `false` otherwise.\n */\nexport function verifyBip322P2wpkhSimple(\n  messageBytes: Uint8Array,\n  compressedPubkey: Uint8Array,\n  encodedSignature: Uint8Array,\n): boolean {\n  if (compressedPubkey.length !== COMPRESSED_PUBKEY_SIZE) return false;\n  if (\n    encodedSignature.length < P2WPKH_ENCODED_SIG_MIN ||\n    encodedSignature.length > P2WPKH_ENCODED_SIG_MAX\n  ) {\n    return false;\n  }\n  // Any exception below (strict-DER decode, malformed pubkey) is a\n  // verification failure, not an error — a verifier returns a boolean.\n  try {\n    // Full curve-point parse, as `PublicKey::from_slice` (`verify.rs:82-83`).\n    if (!ecc.isPointCompressed(compressedPubkey)) return false;\n\n    // Strict DER decode, then SIGHASH_ALL only — deliberately NARROWER than\n    // `verify.rs:156-161` (its from_consensus maps more bytes to All); host-stricter is safe.\n    const { signature, hashType } = bscript.signature.decode(\n      Buffer.from(encodedSignature),\n    );\n    // decode tolerates non-minimal integers (bip66.js never bounds lenR/lenS at 33;\n    // fromDER truncates, script_signature.js:29-35) that vaultd's strict libsecp\n    // parse rejects (secp256k1-sys ecdsa_impl.h:127-136) — require the unique\n    // minimal encoding by re-encoding and byte-comparing.\n    if (\n      !bscript.signature\n        .encode(signature, hashType)\n        .equals(Buffer.from(encodedSignature))\n    ) {\n      return false;\n    }\n    if (hashType !== Transaction.SIGHASH_ALL) return false;\n\n    // scriptPubKey = OP_0 PUSH20 hash160(pubkey) (`message.rs:127 Address::p2wpkh`).\n    const p2wpkh = payments.p2wpkh({ pubkey: Buffer.from(compressedPubkey) });\n    if (!p2wpkh.output || !p2wpkh.hash) return false;\n\n    const toSign = buildToSignTransaction(messageBytes, p2wpkh.output);\n\n    // BIP-143 sighash with the standard P2WPKH scriptCode\n    // `OP_DUP OP_HASH160 <20B> OP_EQUALVERIFY OP_CHECKSIG` and value 0\n    // (`verify.rs:163-173 p2wpkh_signature_hash`; scriptCode template per\n    // bitcoinjs-lib's own P2WPKH signer, `src/psbt.js:1245-1255`).\n    const scriptCode = payments.p2pkh({ hash: p2wpkh.hash }).output;\n    if (!scriptCode) return false;\n    const sighash = toSign.hashForWitnessV0(0, scriptCode, ZERO_SATS, hashType);\n\n    // strict=true rejects high-S, as libsecp256k1's verify does\n    // (`verify.rs:180-182`; secp256k1 crate `ecdsa/mod.rs:194`).\n    return ecc.verify(sighash, compressedPubkey, signature, true);\n  } catch {\n    return false;\n  }\n}\n","/**\n * Validation for protocol parameters fetched from the ProtocolParams contract.\n *\n * These values feed Bitcoin script construction and deposit validation.\n * Invalid params must be caught before they reach transaction-building code,\n * since errors after wallet signing prompts are unrecoverable.\n *\n * The {@link ViemProtocolParamsReader} runs these on every read; consumers\n * implementing their own reader against the same `ProtocolParamsReader`\n * interface should call them too.\n */\n\nimport { assertValidVaultCoreVersion } from \"../../primitives/vaultCoreVersion\";\n\nimport type {\n  PegInConfiguration,\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/** Maximum valid value for basis points (100%) */\nconst MAX_BASIS_POINTS = 10000;\n\n/** Maximum value for a Solidity uint32. */\nconst UINT32_MAX = 4_294_967_295;\n\n/** Maximum valid value for a uint8 (e.g. maxHtlcOutputCount). */\nconst UINT8_MAX = 255;\n\n/**\n * Validate an `offchainParamsVersion` value sourced from a contract read.\n * `Number()` on a malformed payload yields `NaN` or a non-integer; both\n * silently break consumers that loop `1..version` or use the value as a\n * map key. Used by reader entry points that surface the version to JS.\n */\nexport function assertValidOffchainParamsVersion(version: number): void {\n  if (\n    !Number.isInteger(version) ||\n    version < 0 ||\n    version > UINT32_MAX\n  ) {\n    throw new Error(\n      `Invalid offchainParamsVersion from contract: must be a uint32, got ${version}`,\n    );\n  }\n}\n\n/**\n * Validate offchain params consistency and bounds.\n * @throws Error on invalid values to prevent constructing invalid Bitcoin scripts.\n */\nexport function validateOffchainParams(params: VersionedOffchainParams): void {\n  const errors: string[] = [];\n\n  if (params.timelockAssert <= 0n) {\n    errors.push(\n      `timelockAssert must be positive, got ${params.timelockAssert}`,\n    );\n  }\n  if (params.timelockAssert > BigInt(UINT16_MAX)) {\n    errors.push(\n      `timelockAssert ${params.timelockAssert} exceeds uint16 max (${UINT16_MAX})`,\n    );\n  }\n\n  if (params.timelockChallengeAssert <= 0n) {\n    errors.push(\n      `timelockChallengeAssert must be positive, got ${params.timelockChallengeAssert}`,\n    );\n  }\n\n  if (params.tRefund <= 0) {\n    errors.push(`tRefund must be positive, got ${params.tRefund}`);\n  }\n\n  if (params.tStale <= 0) {\n    errors.push(`tStale must be positive, got ${params.tStale}`);\n  }\n\n  if (params.securityCouncilKeys.length === 0) {\n    errors.push(\"securityCouncilKeys must not be empty\");\n  }\n\n  if (params.councilQuorum <= 0) {\n    errors.push(`councilQuorum must be positive, got ${params.councilQuorum}`);\n  }\n  if (params.councilQuorum > params.securityCouncilKeys.length) {\n    errors.push(\n      `councilQuorum (${params.councilQuorum}) exceeds securityCouncilKeys count (${params.securityCouncilKeys.length})`,\n    );\n  }\n\n  if (params.feeRate <= 0n) {\n    errors.push(`feeRate must be positive, got ${params.feeRate}`);\n  }\n\n  if (params.minPeginFeeRate <= 0n) {\n    errors.push(\n      `minPeginFeeRate must be positive, got ${params.minPeginFeeRate}`,\n    );\n  }\n\n  if (\n    !Number.isInteger(params.proverCircuitVersion) ||\n    params.proverCircuitVersion < 0 ||\n    params.proverCircuitVersion > UINT16_MAX\n  ) {\n    errors.push(\n      `proverCircuitVersion must be a uint16, got ${params.proverCircuitVersion}`,\n    );\n  }\n\n  if (\n    !Number.isInteger(params.minPrepeginDepth) ||\n    params.minPrepeginDepth <= 0 ||\n    params.minPrepeginDepth > UINT32_MAX\n  ) {\n    errors.push(\n      `minPrepeginDepth must be a uint32 in [1, ${UINT32_MAX}], got ${params.minPrepeginDepth}`,\n    );\n  }\n\n  if (params.babeTotalInstances <= 0) {\n    errors.push(\n      `babeTotalInstances must be positive, got ${params.babeTotalInstances}`,\n    );\n  }\n  if (params.babeInstancesToFinalize <= 0) {\n    errors.push(\n      `babeInstancesToFinalize must be positive, got ${params.babeInstancesToFinalize}`,\n    );\n  }\n  if (params.babeInstancesToFinalize > params.babeTotalInstances) {\n    errors.push(\n      `babeInstancesToFinalize (${params.babeInstancesToFinalize}) exceeds babeTotalInstances (${params.babeTotalInstances})`,\n    );\n  }\n\n  if (\n    params.minVpCommissionBps < 0 ||\n    params.minVpCommissionBps > MAX_BASIS_POINTS\n  ) {\n    errors.push(\n      `minVpCommissionBps must be in [0, ${MAX_BASIS_POINTS}], got ${params.minVpCommissionBps}`,\n    );\n  }\n\n  if (errors.length > 0) {\n    throw new Error(\n      `Invalid offchain protocol parameters: ${errors.join(\"; \")}`,\n    );\n  }\n}\n\n/**\n * Validate TBV protocol params returned from the contract.\n * @throws Error on invalid amounts or out-of-range bounded fields.\n */\nexport function validateTBVProtocolParams(params: TBVProtocolParams): void {\n  const errors: string[] = [];\n\n  if (params.minimumPegInAmount <= 0n) {\n    errors.push(\n      `minimumPegInAmount must be positive, got ${params.minimumPegInAmount}`,\n    );\n  }\n\n  if (params.maxPegInAmount < params.minimumPegInAmount) {\n    errors.push(\n      `maxPegInAmount (${params.maxPegInAmount}) must be >= minimumPegInAmount (${params.minimumPegInAmount})`,\n    );\n  }\n\n  if (params.pegInAckTimeout <= 0n) {\n    errors.push(\n      `pegInAckTimeout must be positive, got ${params.pegInAckTimeout}`,\n    );\n  }\n\n  if (params.pegInActivationTimeout <= 0n) {\n    errors.push(\n      `pegInActivationTimeout must be positive, got ${params.pegInActivationTimeout}`,\n    );\n  }\n\n  if (\n    !Number.isInteger(params.maxHtlcOutputCount) ||\n    params.maxHtlcOutputCount <= 0 ||\n    params.maxHtlcOutputCount > UINT8_MAX\n  ) {\n    errors.push(\n      `maxHtlcOutputCount must be an integer in [1, ${UINT8_MAX}], got ${params.maxHtlcOutputCount}`,\n    );\n  }\n\n  if (\n    typeof params.expiredPegInGraceBlocks !== \"bigint\" ||\n    params.expiredPegInGraceBlocks <= 0n\n  ) {\n    errors.push(\n      `expiredPegInGraceBlocks must be a positive bigint, got ${params.expiredPegInGraceBlocks}`,\n    );\n  }\n\n  if (errors.length > 0) {\n    throw new Error(`Invalid TBV protocol parameters: ${errors.join(\"; \")}`);\n  }\n}\n\n/**\n * Validate the full peg-in configuration after assembly.\n * Checks both TBV params and offchain params consistency, and the\n * top-level `offchainParamsVersion` (which originates from a separate\n * multicall result and so must be range-checked alongside the params it\n * names).\n */\nexport function validatePegInConfiguration(config: PegInConfiguration): void {\n  validateTBVProtocolParams(config);\n  validateOffchainParams(config.offchainParams);\n\n  if (\n    !Number.isInteger(config.offchainParamsVersion) ||\n    config.offchainParamsVersion < 0 ||\n    config.offchainParamsVersion > UINT32_MAX\n  ) {\n    throw new Error(\n      `Invalid peg-in configuration: offchainParamsVersion must be a uint32, got ${config.offchainParamsVersion}`,\n    );\n  }\n\n  // The contract enforces ≥ 1 (setter rejects 0); a 0 here means a\n  // mis-decoded read or a pre-vaultCoreVersion contract — fail closed.\n  assertValidVaultCoreVersion(\n    config.activeVaultCoreVersion,\n    \"ProtocolParams.activeVaultCoreVersion()\",\n  );\n}\n","/**\n * Concrete BTCVaultRegistry reader using viem's readContract.\n *\n * This is an optional utility — callers can use their own implementation\n * of the VaultRegistryReader interface.\n */\n\nimport type { Abi, Address, Hex, PublicClient } from \"viem\";\n\nimport { BTCVaultRegistryABI } from \"../../contracts/abis/BTCVaultRegistry.abi\";\nimport { BTCVaultRegistryKeyEpochsABI } from \"../../contracts/abis/BTCVaultRegistryKeyEpochs.abi\";\nimport { assertOnChainBtcPubkey } from \"./onChainBtcPubkey\";\nimport { assertValidOffchainParamsVersion } from \"./protocol-params-validation\";\nimport type {\n  KeyEpochs,\n  OnChainBtcPubkey,\n  VaultBasicInfo,\n  VaultData,\n  VaultProtocolInfo,\n  VaultRegistryReader,\n} from \"./types\";\n\n/**\n * Inclusive upper bound the BTCVaultRegistry contract enforces on a vault\n * provider's commission (the contract check is `< 10000`).\n */\nconst MAX_VP_COMMISSION_BPS = 9999;\n\n/** Raw `getBtcVaultBasicInfo` tuple as decoded by viem. */\ntype RawVaultBasicInfo = {\n  depositor: Address;\n  depositorBtcPubKey: Hex;\n  amount: bigint;\n  vaultProvider: Address;\n  status: number;\n  applicationEntryPoint: Address;\n  createdAt: bigint;\n};\n\n/** Raw `getBtcVaultProtocolInfo` tuple as decoded by viem. */\ntype RawVaultProtocolInfo = {\n  depositorSignedPeginTx: Hex;\n  universalChallengersVersion: number;\n  appVaultKeepersVersion: number;\n  offchainParamsVersion: number;\n  verifiedAt: bigint;\n  depositorWotsPkHash: Hex;\n  hashlock: Hex;\n  htlcVout: number;\n  depositorPopSignature: Hex;\n  prePeginTxHash: Hex;\n  vaultProviderCommissionBps: number;\n  claimExpiredUntil: bigint;\n  vaultCoreVersion: number;\n};\n\nfunction mapVaultBasicInfo(result: RawVaultBasicInfo): VaultBasicInfo {\n  return {\n    depositor: result.depositor,\n    depositorBtcPubKey: result.depositorBtcPubKey,\n    amount: result.amount,\n    vaultProvider: result.vaultProvider,\n    status: result.status,\n    applicationEntryPoint: result.applicationEntryPoint,\n    createdAt: result.createdAt,\n  };\n}\n\nfunction mapVaultProtocolInfo(result: RawVaultProtocolInfo): VaultProtocolInfo {\n  const offchainParamsVersion = Number(result.offchainParamsVersion);\n  assertValidOffchainParamsVersion(offchainParamsVersion);\n  return {\n    depositorSignedPeginTx: result.depositorSignedPeginTx,\n    universalChallengersVersion: result.universalChallengersVersion,\n    appVaultKeepersVersion: result.appVaultKeepersVersion,\n    offchainParamsVersion,\n    verifiedAt: result.verifiedAt,\n    depositorWotsPkHash: result.depositorWotsPkHash,\n    hashlock: result.hashlock,\n    htlcVout: result.htlcVout,\n    depositorPopSignature: result.depositorPopSignature,\n    prePeginTxHash: result.prePeginTxHash,\n    vaultProviderCommissionBps: result.vaultProviderCommissionBps,\n    claimExpiredUntil: result.claimExpiredUntil,\n    vaultCoreVersion: result.vaultCoreVersion,\n  };\n}\n\n/**\n * Exclusive upper bound for a `uint64` epoch.\n *\n * viem does not range-check a decoded `uint64`, so a misaligned decode can\n * hand back a value far larger than the field can hold. Rejecting those is\n * cheap defence in depth against a mis-decode of the extended ABI.\n *\n * The state this is load-bearing for is narrower than \"a registry that predates\n * RFC-006\". Against a *fully* pre-RFC-006 registry the path fails closed on its\n * own: `resolveParticipantKeysAtEpochs` goes on to call\n * `getOperationBtcKeyAtEpochOrGenesis` on ApplicationRegistry and\n * ProtocolParams, which do not exist there, so the multicall reverts and these\n * epochs are never used. The reachable gap is a registry that *has* the\n * operation-key getters but whose `BTCVaultProtocolInfo` struct is not\n * extended — there the tail-data epochs resolve with no error at all, and this\n * range check is the only thing looking at them.\n *\n * Even for that case it is only a backstop, and a weak one: a misaligned decode\n * can land on a small, plausible-looking integer this range accepts. Correctness\n * rests on only ever pointing at an RFC-006 registry, which is a deployment\n * precondition rather than something this call can establish — see\n * https://github.com/babylonlabs-io/babylon-toolkit/issues/2192 for where that\n * check is owned, and `BTCVaultRegistryKeyEpochs.abi.ts` for the decode hazard.\n */\nconst UINT64_EXCLUSIVE_UPPER_BOUND = 1n << 64n;\n\n/**\n * The epoch a vault provider's registration key is bonded at.\n *\n * A provider's operation-key history is append-only and every appended version\n * is stamped at epoch 1 or later, so epoch 0 always resolves to the key set at\n * registration. This is what lets `getOperationBtcKeyAtEpoch` stand in for the\n * removed `getVaultProviderBTCKey` getter.\n */\nconst VP_GENESIS_KEY_EPOCH = 0n;\n\nfunction assertEpochInRange(\n  value: bigint,\n  field: string,\n  vaultId: Hex,\n): bigint {\n  if (value < 0n || value >= UINT64_EXCLUSIVE_UPPER_BOUND) {\n    throw new Error(\n      `getBtcVaultProtocolInfo returned ${field}=${value} for vault ${vaultId}, ` +\n        `outside the uint64 range — the registry may predate RFC-006`,\n    );\n  }\n  return value;\n}\n\nfunction mapKeyEpochs(result: KeyEpochs, vaultId: Hex): KeyEpochs {\n  return {\n    vpKeyEpoch: assertEpochInRange(result.vpKeyEpoch, \"vpKeyEpoch\", vaultId),\n    appKeeperKeyEpoch: assertEpochInRange(\n      result.appKeeperKeyEpoch,\n      \"appKeeperKeyEpoch\",\n      vaultId,\n    ),\n    ucKeyEpoch: assertEpochInRange(result.ucKeyEpoch, \"ucKeyEpoch\", vaultId),\n  };\n}\n\n/**\n * Concrete vault registry reader using viem.\n *\n * Usage:\n * ```ts\n * const reader = new ViemVaultRegistryReader(publicClient, registryAddress);\n * const data = await reader.getVaultData(vaultId);\n * ```\n */\nexport class ViemVaultRegistryReader implements VaultRegistryReader {\n  constructor(\n    private publicClient: PublicClient,\n    private contractAddress: Address,\n  ) {}\n\n  /**\n   * Read the VP's **genesis** (registration) x-only BTC pubkey — the key bonded\n   * at version 0, which never moves when the operator rotates.\n   *\n   * Resolved as \"the operation key at epoch 0\" rather than through the\n   * dedicated `getVaultProviderBTCKey` getter, which\n   * https://github.com/babylonlabs-io/vault-contracts-aave-v4/pull/539 removes.\n   * Epoch 0 predates any rotation — appended versions are stamped at epoch 1 or\n   * later — so it resolves to the registration key, and the contracts team has\n   * confirmed that is a property we can rely on rather than an implementation\n   * detail. The devnet comparison behind that claim — both getters returning the\n   * identical key for a provider that *has* rotated, while\n   * `getCurrentOperationBtcKey` differed — is recorded in\n   * https://github.com/babylonlabs-io/babylon-toolkit/issues/2188.\n   *\n   * This makes the read RFC-006-only, where the removed getter also existed on a\n   * legacy registry. That costs nothing: every caller of this method already\n   * resolves participant keys through `OperationKeyReader`, so all of them\n   * require an RFC-006 registry regardless.\n   *\n   * Validates length, hex form, and secp256k1 curve membership before minting\n   * the brand. Returns 64-char lowercase hex without the `0x` prefix.\n   */\n  async getVaultProviderGenesisBtcPubKey(\n    vpAddress: Address,\n  ): Promise<OnChainBtcPubkey> {\n    const result = (await this.publicClient.readContract({\n      address: this.contractAddress,\n      abi: BTCVaultRegistryABI,\n      functionName: \"getOperationBtcKeyAtEpoch\",\n      args: [vpAddress, VP_GENESIS_KEY_EPOCH],\n    })) as Hex;\n    return assertOnChainBtcPubkey(\n      result,\n      `getOperationBtcKeyAtEpoch (vp=${vpAddress}, epoch=${VP_GENESIS_KEY_EPOCH})`,\n    );\n  }\n\n  /**\n   * Read a vault provider's *current* RFC-006 operation BTC key.\n   *\n   * Falls back on-chain to the registration key when the provider has never\n   * rotated, so this returns the same value as\n   * `getVaultProviderGenesisBtcPubKey` until the first rotation.\n   *\n   * This is the key the VP's server signs its BIP-322 auth tokens with — a\n   * live per-operator identity, not a per-vault binding, so the auth pin uses\n   * the current key rather than any vault's frozen epoch.\n   */\n  async getCurrentVaultProviderOperationBtcKey(\n    vpAddress: Address,\n  ): Promise<OnChainBtcPubkey> {\n    const result = (await this.publicClient.readContract({\n      address: this.contractAddress,\n      abi: BTCVaultRegistryABI,\n      functionName: \"getCurrentOperationBtcKey\",\n      args: [vpAddress],\n    })) as Hex;\n    return assertOnChainBtcPubkey(\n      result,\n      `getCurrentOperationBtcKey (vp=${vpAddress})`,\n    );\n  }\n\n  /**\n   * Read a vault's frozen RFC-006 operation-key epochs.\n   *\n   * Reads `getBtcVaultProtocolInfo` through the **extended** ABI, which is only\n   * valid against an RFC-006 registry: against one whose `BTCVaultProtocolInfo`\n   * struct is not extended this call does not fail for a populated vault, it\n   * silently returns three words of tail data as epochs. Nothing here can detect\n   * that, so the guarantee is a deployment one — every network this ships to has\n   * the RFC-006 getters, and mainnet is a fresh RFC-006 deploy.\n   *\n   * A registry missing the operation-key getters entirely is the *safer* of the\n   * two cases: `resolveParticipantKeysAtEpochs` reverts downstream and these\n   * epochs never reach key resolution. See {@link UINT64_EXCLUSIVE_UPPER_BOUND}\n   * for which state the range check actually guards, and\n   * `BTCVaultRegistryKeyEpochs.abi.ts` for the decode hazard.\n   */\n  async getVaultKeyEpochs(vaultId: Hex): Promise<KeyEpochs> {\n    const result = (await this.publicClient.readContract({\n      address: this.contractAddress,\n      abi: BTCVaultRegistryKeyEpochsABI,\n      functionName: \"getBtcVaultProtocolInfo\",\n      args: [vaultId],\n    })) as unknown as KeyEpochs;\n\n    return mapKeyEpochs(result, vaultId);\n  }\n\n  async getVaultKeyEpochsBatch(vaultIds: readonly Hex[]): Promise<KeyEpochs[]> {\n    if (vaultIds.length === 0) return [];\n\n    const results = await this.publicClient.multicall({\n      contracts: vaultIds.map((vaultId) => ({\n        address: this.contractAddress,\n        abi: BTCVaultRegistryKeyEpochsABI as Abi,\n        functionName: \"getBtcVaultProtocolInfo\" as const,\n        args: [vaultId] as const,\n      })),\n      allowFailure: false,\n    });\n\n    return results.map((info, i) =>\n      mapKeyEpochs(info as unknown as KeyEpochs, vaultIds[i]),\n    );\n  }\n\n  async getVaultBasicInfo(vaultId: Hex): Promise<VaultBasicInfo> {\n    const result = (await this.publicClient.readContract({\n      address: this.contractAddress,\n      abi: BTCVaultRegistryABI,\n      functionName: \"getBtcVaultBasicInfo\",\n      args: [vaultId],\n    })) as RawVaultBasicInfo;\n\n    return mapVaultBasicInfo(result);\n  }\n\n  async getVaultProtocolInfo(vaultId: Hex): Promise<VaultProtocolInfo> {\n    const result = (await this.publicClient.readContract({\n      address: this.contractAddress,\n      abi: BTCVaultRegistryABI,\n      functionName: \"getBtcVaultProtocolInfo\",\n      args: [vaultId],\n    })) as RawVaultProtocolInfo;\n\n    return mapVaultProtocolInfo(result);\n  }\n\n  async getProtocolInfoBatch(\n    vaultIds: readonly Hex[],\n  ): Promise<VaultProtocolInfo[]> {\n    if (vaultIds.length === 0) return [];\n\n    const results = await this.publicClient.multicall({\n      contracts: vaultIds.map((vaultId) => ({\n        address: this.contractAddress,\n        abi: BTCVaultRegistryABI as Abi,\n        functionName: \"getBtcVaultProtocolInfo\" as const,\n        args: [vaultId] as const,\n      })),\n      allowFailure: false,\n    });\n\n    return results.map((info, i) => {\n      const result = info as unknown as RawVaultProtocolInfo;\n      if (\n        !result.depositorSignedPeginTx ||\n        result.depositorSignedPeginTx === \"0x\"\n      ) {\n        // An empty record is not proof the vault is absent: a lagging RPC\n        // node returns HTTP 200 with a zero struct, so no retry below this\n        // layer can see it. Single-shot is only safe because the finality\n        // gate (`waitForPeginRegistrationDepth`) runs first on the deposit\n        // path — move this ahead of it and the read-after-write race returns.\n        // The vault app matches this message to render \"still confirming\".\n        throw new Error(\n          `Vault ${vaultIds[i]} not found on-chain or has no pegin transaction`,\n        );\n      }\n      return mapVaultProtocolInfo(result);\n    });\n  }\n\n  /**\n   * Read the protocol pegin fee (in wei) for a given vault provider.\n   * Mirrors the `getPegInFee(address)` view on BTCVaultRegistry.\n   */\n  async getPegInFee(vaultProvider: Address): Promise<bigint> {\n    return (await this.publicClient.readContract({\n      address: this.contractAddress,\n      abi: BTCVaultRegistryABI,\n      functionName: \"getPegInFee\",\n      args: [vaultProvider],\n    })) as bigint;\n  }\n\n  /**\n   * Read a vault provider's current commission in basis points from\n   * BTCVaultRegistry. The contract enforces `commissionBps < 10000`, so the\n   * legitimate range is `[0, 9999]`; anything outside indicates a wrong\n   * contract address or ABI drift and is surfaced as an error rather than\n   * trusted.\n   */\n  async getVaultProviderCommission(vaultProvider: Address): Promise<number> {\n    // viem infers `number` from the `uint16` return in the `as const` ABI.\n    const bps = await this.publicClient.readContract({\n      address: this.contractAddress,\n      abi: BTCVaultRegistryABI,\n      functionName: \"getVaultProviderCommission\",\n      args: [vaultProvider],\n    });\n\n    if (!Number.isInteger(bps) || bps < 0 || bps > MAX_VP_COMMISSION_BPS) {\n      throw new Error(\n        `getVaultProviderCommission returned ${bps} bps for ${vaultProvider}, ` +\n          `outside the protocol range [0, ${MAX_VP_COMMISSION_BPS}]`,\n      );\n    }\n\n    return bps;\n  }\n\n  async getVaultData(vaultId: Hex): Promise<VaultData> {\n    // One round-trip for both structs (hard-fail): they feed signing/refund/\n    // broadcast rebinds, so reading them in a single multicall also pins both\n    // to the same block — no basic/protocol skew across two `eth_call`s.\n    const [basicRaw, protocolRaw] = await this.publicClient.multicall({\n      contracts: [\n        {\n          address: this.contractAddress,\n          abi: BTCVaultRegistryABI,\n          functionName: \"getBtcVaultBasicInfo\",\n          args: [vaultId],\n        },\n        {\n          address: this.contractAddress,\n          abi: BTCVaultRegistryABI,\n          functionName: \"getBtcVaultProtocolInfo\",\n          args: [vaultId],\n        },\n      ],\n      allowFailure: false,\n    });\n\n    const basic = mapVaultBasicInfo(basicRaw);\n    const protocol = mapVaultProtocolInfo(protocolRaw);\n\n    if (\n      !protocol.depositorSignedPeginTx ||\n      protocol.depositorSignedPeginTx === \"0x\"\n    ) {\n      throw new Error(\n        `Vault ${vaultId} not found on-chain or has no pegin transaction`,\n      );\n    }\n\n    return { basic, protocol };\n  }\n\n}\n","/**\n * Mempool API Client\n *\n * Client for interacting with mempool.space API for Bitcoin network operations.\n * Used for broadcasting transactions and fetching UTXO data.\n *\n * @module clients/mempool/mempoolApi\n */\n\nimport { combineAbortSignals } from \"../../utils/abortSignals\";\nimport {\n  BITCOIN_ADDRESS_RE,\n  HEX_RE,\n  KNOWN_SCRIPT_PREFIXES,\n  TXID_RE,\n} from \"../../utils/validation\";\n\nimport type {\n  MempoolUTXO,\n  NetworkFees,\n  OutspendStatus,\n  TxInfo,\n  UtxoInfo,\n} from \"./types\";\n\n/** Maximum valid satoshi value: 21 million BTC × 10^8 sats/BTC */\nconst MAX_SATOSHIS = 21_000_000 * 1e8;\n\n/** Timeout for mempool API requests — prevents indefinite hangs from stalled endpoints */\nconst MEMPOOL_REQUEST_TIMEOUT_MS = 30_000;\n\n/**\n * Fetch wrapper with AbortController-based timeout.\n * Ensures all mempool API requests fail bounded rather than hanging indefinitely.\n */\nasync function fetchWithTimeout(\n  url: string,\n  options?: RequestInit,\n): Promise<Response> {\n  const controller = new AbortController();\n  const timeoutId = setTimeout(\n    () => controller.abort(),\n    MEMPOOL_REQUEST_TIMEOUT_MS,\n  );\n\n  // Compose timeout signal with any caller-supplied signal so both can cancel\n  const signals = [controller.signal, options?.signal].filter(\n    Boolean,\n  ) as AbortSignal[];\n  const combined = combineAbortSignals(signals);\n\n  try {\n    // Don't clear timeout here — let it cover body consumption by callers.\n    // For the same reason the composed signal keeps its listeners attached on\n    // the success path: detaching them would stop the timeout from aborting a\n    // stalled body read.\n    return await fetch(url, {\n      ...options,\n      signal: combined.signal,\n    });\n  } catch (error) {\n    clearTimeout(timeoutId);\n    combined.cleanup();\n    if (\n      error != null &&\n      typeof error === \"object\" &&\n      \"name\" in error &&\n      error.name === \"AbortError\"\n    ) {\n      throw new Error(\n        `Mempool API request timed out after ${MEMPOOL_REQUEST_TIMEOUT_MS}ms: ${url}`,\n      );\n    }\n    throw error;\n  }\n}\n\n/**\n * Maximum sane fee rate in sat/vByte.\n * The April 2024 Runes spike peaked around 1,805 sat/vB — 10,000 provides ample headroom.\n */\nconst MAX_FEE_RATE = 10_000;\n\nfunction isValidSatoshiValue(value: number): boolean {\n  return Number.isInteger(value) && value > 0 && value <= MAX_SATOSHIS;\n}\n\nfunction isValidFeeRate(value: number): boolean {\n  return Number.isInteger(value) && value > 0 && value <= MAX_FEE_RATE;\n}\n\nfunction isValidVout(vout: number, outputCount?: number): boolean {\n  if (!Number.isInteger(vout) || vout < 0) return false;\n  return outputCount === undefined || vout < outputCount;\n}\n\n\nfunction assertValidTxid(txid: string): void {\n  if (!TXID_RE.test(txid)) {\n    throw new Error(`Invalid transaction ID format: ${txid}`);\n  }\n}\n\nfunction assertValidAddress(address: string): void {\n  if (!BITCOIN_ADDRESS_RE.test(address)) {\n    throw new Error(`Invalid Bitcoin address format: ${address}`);\n  }\n}\n\nfunction assertValidScriptPubKey(scriptPubKey: string, context: string): void {\n  if (!HEX_RE.test(scriptPubKey)) {\n    throw new Error(\n      `Invalid scriptPubKey: not valid hex for ${context}`,\n    );\n  }\n  const matchesKnownType = KNOWN_SCRIPT_PREFIXES.some((prefix) =>\n    scriptPubKey.toLowerCase().startsWith(prefix),\n  );\n  if (!matchesKnownType) {\n    throw new Error(\n      `Unrecognized scriptPubKey type for ${context}: ` +\n        `prefix ${scriptPubKey.slice(0, 6)} does not match any known Bitcoin script type`,\n    );\n  }\n}\n\n/**\n * Default mempool API URLs by network.\n */\nexport const MEMPOOL_API_URLS = {\n  mainnet: \"https://mempool.space/api\",\n  testnet: \"https://mempool.space/testnet/api\",\n  signet: \"https://mempool.space/signet/api\",\n} as const;\n\n/**\n * Fetch wrapper with error handling.\n */\nasync function fetchApi<T>(\n  url: string,\n  options?: RequestInit,\n): Promise<T> {\n  try {\n    const response = await fetchWithTimeout(url, options);\n\n    if (!response.ok) {\n      const errorText = await response.text();\n      throw new Error(\n        `Mempool API error (${response.status}): ${errorText || response.statusText}`,\n      );\n    }\n\n    const contentType = response.headers.get(\"content-type\");\n    if (contentType?.includes(\"application/json\")) {\n      return (await response.json()) as T;\n    } else {\n      return (await response.text()) as T;\n    }\n  } catch (error) {\n    if (error instanceof Error) {\n      throw new Error(`Failed to fetch from mempool API: ${error.message}`);\n    }\n    throw new Error(\"Failed to fetch from mempool API: Unknown error\");\n  }\n}\n\n/**\n * Push a signed transaction to the Bitcoin network.\n *\n * @param txHex - The signed transaction hex string\n * @param apiUrl - Mempool API base URL\n * @returns The transaction ID\n * @throws Error if broadcasting fails\n */\nexport async function pushTx(txHex: string, apiUrl: string): Promise<string> {\n  try {\n    const response = await fetchWithTimeout(`${apiUrl}/tx`, {\n      method: \"POST\",\n      body: txHex,\n      headers: {\n        \"Content-Type\": \"text/plain\",\n      },\n    });\n\n    if (!response.ok) {\n      const errorText = await response.text();\n      // Try to extract error message from response using robust JSON parsing\n      let message: string | undefined;\n      try {\n        const errorJson = JSON.parse(errorText);\n        message = errorJson.message ?? errorJson.error;\n      } catch {\n        // Not JSON, use raw text\n        message = errorText;\n      }\n      throw new Error(\n        message || `Failed to broadcast transaction: ${response.statusText}`,\n      );\n    }\n\n    // Response is the transaction ID (plain text)\n    const txId = await response.text();\n    return txId;\n  } catch (error) {\n    if (error instanceof Error) {\n      throw new Error(`Failed to broadcast BTC transaction: ${error.message}`);\n    }\n    throw new Error(\"Failed to broadcast BTC transaction: Unknown error\");\n  }\n}\n\n/**\n * Get transaction information from mempool.\n *\n * @param txid - The transaction ID\n * @param apiUrl - Mempool API base URL\n * @returns Transaction information\n */\nexport async function getTxInfo(txid: string, apiUrl: string): Promise<TxInfo> {\n  assertValidTxid(txid);\n  return fetchApi<TxInfo>(`${apiUrl}/tx/${txid}`);\n}\n\n/**\n * Get the current block tip height.\n *\n * Source: mempool.space API — `GET /api/blocks/tip/height` returns the height\n * of the most recent block as a plain-text integer.\n *\n * @param apiUrl - Mempool API base URL\n * @returns The height of the most recent block\n * @throws Error if the response is not a whole number\n */\nexport async function getTipHeight(apiUrl: string): Promise<number> {\n  const raw = await fetchApi<string>(`${apiUrl}/blocks/tip/height`);\n  const trimmed = raw.trim();\n  if (!/^\\d+$/.test(trimmed)) {\n    throw new Error(\n      `Mempool API returned an invalid block tip height: \"${raw}\"`,\n    );\n  }\n  return Number.parseInt(trimmed, 10);\n}\n\n/**\n * Get the spend status of a specific transaction output.\n *\n * Calls the esplora-compatible `GET /tx/{txid}/outspend/{vout}` endpoint\n * (mempool.space backend, mempool/electrs `rest.rs`). Returns\n * `{ spent: false }` for an unspent output, or\n * `{ spent: true, txid, vin, status }` when the output has been spent.\n *\n * @param txid - The transaction id whose output is being checked (no 0x prefix)\n * @param vout - The output index\n * @param apiUrl - Mempool API base URL\n * @returns The output's spend status\n */\nexport async function getOutspend(\n  txid: string,\n  vout: number,\n  apiUrl: string,\n): Promise<OutspendStatus> {\n  assertValidTxid(txid);\n  if (!isValidVout(vout)) {\n    throw new Error(`Invalid vout ${vout} for transaction ${txid}`);\n  }\n  return fetchApi<OutspendStatus>(`${apiUrl}/tx/${txid}/outspend/${vout}`);\n}\n\n/**\n * Get the hex representation of a transaction.\n *\n * @param txid - The transaction ID\n * @param apiUrl - Mempool API base URL\n * @returns The transaction hex string\n * @throws Error if the request fails or transaction is not found\n */\nexport async function getTxHex(txid: string, apiUrl: string): Promise<string> {\n  assertValidTxid(txid);\n  try {\n    const response = await fetchWithTimeout(`${apiUrl}/tx/${txid}/hex`);\n\n    if (!response.ok) {\n      const errorText = await response.text();\n      throw new Error(\n        `Mempool API error (${response.status}): ${errorText || response.statusText}`,\n      );\n    }\n\n    return await response.text();\n  } catch (error) {\n    if (error instanceof Error) {\n      throw new Error(`Failed to get transaction hex for ${txid}: ${error.message}`);\n    }\n    throw new Error(`Failed to get transaction hex for ${txid}: Unknown error`);\n  }\n}\n\n/**\n * Get UTXO information for a specific transaction output.\n *\n * This is used for constructing PSBTs where we need the witnessUtxo data.\n * Only supports Taproot (P2TR) and native SegWit (P2WPKH, P2WSH) script types.\n *\n * @param txid - The transaction ID containing the UTXO\n * @param vout - The output index\n * @param apiUrl - Mempool API base URL\n * @returns UTXO information with value and scriptPubKey\n */\nexport async function getUtxoInfo(\n  txid: string,\n  vout: number,\n  apiUrl: string,\n): Promise<UtxoInfo> {\n  assertValidTxid(txid);\n  const txInfo = await getTxInfo(txid, apiUrl);\n\n  if (!isValidVout(vout, txInfo.vout.length)) {\n    throw new Error(\n      `Invalid vout ${vout} for transaction ${txid} (has ${txInfo.vout.length} outputs)`,\n    );\n  }\n\n  const output = txInfo.vout[vout];\n  if (!isValidSatoshiValue(output.value)) {\n    throw new Error(`Invalid UTXO value ${output.value} for ${txid}:${vout}`);\n  }\n  assertValidScriptPubKey(output.scriptpubkey, `${txid}:${vout}`);\n\n  return {\n    txid,\n    vout,\n    value: output.value,\n    scriptPubKey: output.scriptpubkey,\n  };\n}\n\n/**\n * Get all UTXOs for a Bitcoin address.\n *\n * @param address - The Bitcoin address\n * @param apiUrl - Mempool API base URL\n * @returns Array of UTXOs sorted by value (largest first)\n */\nexport async function getAddressUtxos(\n  address: string,\n  apiUrl: string,\n): Promise<MempoolUTXO[]> {\n  assertValidAddress(address);\n  try {\n    // Fetch UTXOs for the address\n    const utxos = await fetchApi<\n      {\n        txid: string;\n        vout: number;\n        value: number;\n        status: {\n          confirmed: boolean;\n        };\n      }[]\n    >(`${apiUrl}/address/${address}/utxo`);\n\n    // Fetch scriptPubKey for the address\n    const addressInfo = await fetchApi<{\n      isvalid: boolean;\n      scriptPubKey: string;\n    }>(`${apiUrl}/v1/validate-address/${address}`);\n\n    if (!addressInfo.isvalid) {\n      throw new Error(\n        `Invalid Bitcoin address: ${address}. Mempool API validation failed.`,\n      );\n    }\n    assertValidScriptPubKey(addressInfo.scriptPubKey, address);\n\n    // Validate UTXO fields from the listing endpoint.\n    // Per-UTXO cross-verification against /tx/{txid} is intentionally NOT done\n    // here — it would be expensive (N API calls) and redundant: the broadcast\n    // path already verifies each selected input via getUtxoInfo before signing.\n    // Both endpoints come from the same mempool API, so cross-checking one\n    // against the other on the same server does not add real security.\n    for (const utxo of utxos) {\n      assertValidTxid(utxo.txid);\n      if (!isValidVout(utxo.vout)) {\n        throw new Error(`Invalid vout ${utxo.vout} for ${utxo.txid}`);\n      }\n      if (!isValidSatoshiValue(utxo.value)) {\n        throw new Error(\n          `Invalid UTXO value ${utxo.value} for ${utxo.txid}:${utxo.vout}`,\n        );\n      }\n    }\n\n    // Sort by value (largest first) and map to our UTXO format\n    const sortedUTXOs = utxos.sort((a, b) => b.value - a.value);\n\n    return sortedUTXOs.map((utxo) => ({\n      txid: utxo.txid,\n      vout: utxo.vout,\n      value: utxo.value,\n      scriptPubKey: addressInfo.scriptPubKey,\n      confirmed: utxo.status.confirmed,\n    }));\n  } catch (error) {\n    if (error instanceof Error) {\n      throw new Error(\n        `Failed to get UTXOs for address ${address}: ${error.message}`,\n      );\n    }\n    throw new Error(\n      `Failed to get UTXOs for address ${address}: Unknown error`,\n    );\n  }\n}\n\n/**\n * Get the mempool API URL for a given network.\n *\n * @param network - Bitcoin network (mainnet, testnet, signet)\n * @returns The mempool API URL\n */\nexport function getMempoolApiUrl(\n  network: \"mainnet\" | \"testnet\" | \"signet\",\n): string {\n  return MEMPOOL_API_URLS[network];\n}\n\n/**\n * Transaction summary from address transactions endpoint.\n */\nexport interface AddressTx {\n  txid: string;\n  status: {\n    confirmed: boolean;\n    block_height?: number;\n  };\n}\n\n/**\n * Get recent transactions for a Bitcoin address.\n *\n * Returns the last 25 confirmed transactions plus any unconfirmed (mempool) transactions.\n * This is useful for checking if a specific transaction has been broadcast.\n *\n * @param address - The Bitcoin address\n * @param apiUrl - Mempool API base URL\n * @returns Array of recent transactions\n */\nexport async function getAddressTxs(\n  address: string,\n  apiUrl: string,\n): Promise<AddressTx[]> {\n  assertValidAddress(address);\n  return fetchApi<AddressTx[]>(`${apiUrl}/address/${address}/txs`);\n}\n\n/**\n * Fetches Bitcoin network fee recommendations from mempool.space API.\n *\n * @param apiUrl - Mempool API base URL\n * @returns Fee rates in sat/vbyte for different confirmation times\n * @throws Error if request fails or returns invalid data\n *\n * @see https://mempool.space/docs/api/rest#get-recommended-fees\n */\nexport async function getNetworkFees(apiUrl: string): Promise<NetworkFees> {\n  const response = await fetchWithTimeout(`${apiUrl}/v1/fees/recommended`);\n\n  if (!response.ok) {\n    throw new Error(\n      `Failed to fetch network fees: ${response.status} ${response.statusText}`,\n    );\n  }\n\n  const data = await response.json();\n\n  const feeFields = [\n    \"fastestFee\",\n    \"halfHourFee\",\n    \"hourFee\",\n    \"economyFee\",\n    \"minimumFee\",\n  ] as const;\n\n  for (const field of feeFields) {\n    if (!isValidFeeRate(data[field])) {\n      throw new Error(\n        `Invalid fee rate ${field}=${data[field]} from mempool API: expected a positive number ≤ ${MAX_FEE_RATE}`,\n      );\n    }\n  }\n\n  if (\n    data.minimumFee > data.economyFee ||\n    data.economyFee > data.hourFee ||\n    data.hourFee > data.halfHourFee ||\n    data.halfHourFee > data.fastestFee\n  ) {\n    throw new Error(\n      `Fee rate ordering violation from mempool API: expected ` +\n        `minimumFee (${data.minimumFee}) <= economyFee (${data.economyFee}) <= ` +\n        `hourFee (${data.hourFee}) <= halfHourFee (${data.halfHourFee}) <= ` +\n        `fastestFee (${data.fastestFee}).`,\n    );\n  }\n\n  return data as NetworkFees;\n}\n\n"],"names":["BIP322_TAG","TAPTWEAK_TAG","X_ONLY_PUBKEY_SIZE","SCHNORR_SIG_SIZE","COMPRESSED_PUBKEY_SIZE","P2WPKH_ENCODED_SIG_MIN","P2WPKH_ENCODED_SIG_MAX","ZERO_SATS","BIP322_TX_VERSION","BIP322_TX_LOCKTIME","BIP322_INPUT_SEQUENCE","TO_SPEND_PREVOUT_TXID_BYTES","TO_SPEND_PREVOUT_INDEX","TO_SPEND_OUTPUT_INDEX","OP_0","OP_PUSHBYTES_32","OP_RETURN","taggedHash","tag","data","tagBytes","tagHash","sha256","preimage","tweakXOnlyKey","xOnly","tweak","tweaked","ecc","buildToSignTransaction","messageBytes","scriptPubKey","messageHash","toSpend","Transaction","scriptSig","Buffer","toSign","verifyBip322Simple","xOnlyPubkey","signature","hashType","p2tr","payments","sighash","tweakedXOnly","verifyBip322P2wpkhSimple","compressedPubkey","encodedSignature","bscript","p2wpkh","scriptCode","UINT16_MAX","MAX_BASIS_POINTS","UINT32_MAX","UINT8_MAX","assertValidOffchainParamsVersion","version","validateOffchainParams","params","errors","validateTBVProtocolParams","validatePegInConfiguration","config","assertValidVaultCoreVersion","MAX_VP_COMMISSION_BPS","mapVaultBasicInfo","result","mapVaultProtocolInfo","offchainParamsVersion","UINT64_EXCLUSIVE_UPPER_BOUND","VP_GENESIS_KEY_EPOCH","assertEpochInRange","value","field","vaultId","mapKeyEpochs","ViemVaultRegistryReader","publicClient","contractAddress","vpAddress","BTCVaultRegistryABI","assertOnChainBtcPubkey","BTCVaultRegistryKeyEpochsABI","vaultIds","info","vaultProvider","bps","basicRaw","protocolRaw","basic","protocol","MAX_SATOSHIS","MEMPOOL_REQUEST_TIMEOUT_MS","fetchWithTimeout","url","options","controller","timeoutId","signals","combined","combineAbortSignals","error","MAX_FEE_RATE","isValidSatoshiValue","isValidFeeRate","isValidVout","vout","outputCount","assertValidTxid","txid","TXID_RE","assertValidAddress","address","BITCOIN_ADDRESS_RE","assertValidScriptPubKey","context","HEX_RE","KNOWN_SCRIPT_PREFIXES","prefix","MEMPOOL_API_URLS","fetchApi","response","errorText","contentType","pushTx","txHex","apiUrl","message","errorJson","getTxInfo","getTipHeight","raw","trimmed","getOutspend","getTxHex","getUtxoInfo","txInfo","output","getAddressUtxos","utxos","addressInfo","utxo","a","b","getMempoolApiUrl","network","getAddressTxs","getNetworkFees","feeFields"],"mappings":"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"}