{"version":3,"file":"signPsbtsWithFallback-C5cVgYhh.cjs","sources":["../src/tbv/core/managers/pegin/assertAuthAnchorOpReturn.ts","../src/tbv/core/services/htlc/index.ts","../src/tbv/core/deposit-terms/depositTerms.ts","../src/tbv/core/managers/PayoutManager.ts","../src/tbv/core/managers/pegin/signPsbtsWithFallback.ts"],"sourcesContent":["/**\n * Structural verifier for the auth-anchor OP_RETURN in a funded\n * Pre-PegIn transaction.\n *\n * @module managers/pegin/assertAuthAnchorOpReturn\n */\n\nimport * as bitcoin from \"bitcoinjs-lib\";\n\nimport { stripHexPrefix } from \"../../primitives/utils/bitcoin\";\n\n/** OP_RETURN opcode. */\nconst OP_RETURN = 0x6a;\n/** Push-32-bytes opcode (raw push, not OP_PUSHDATA1). */\nconst OP_PUSH32 = 0x20;\n/** Encoded length of a standard OP_RETURN script with a 32-byte payload. */\nconst OP_RETURN_PUSH32_SCRIPT_LEN = 1 + 1 + 32;\n\n/**\n * Verify the broadcast Pre-PegIn carries the expected OP_RETURN\n * commitment to the auth anchor.\n *\n * The OP_RETURN sits at `vout = vaultCount` (right after the per-vault\n * HTLC outputs and before the depositor-claim/change outputs) and\n * pushes the 32-byte `SHA256(authAnchor)`. The script encoding is\n * exactly `OP_RETURN || PUSH32 || <32 bytes>` (34 bytes). A\n * non-conformant WASM build that omitted the OP_RETURN, swapped its\n * position, or changed its push payload would let the depositor\n * obtain a valid bearer token for a Pre-PegIn whose on-chain\n * commitment doesn't actually bind the anchor — degrading the auth\n * from on-chain-bound to a shared secret. Fail closed.\n *\n * @throws If the OP_RETURN is missing, mis-located, mis-encoded, or\n *         pushes a payload other than `expectedAuthAnchorHashHex`.\n */\nexport function assertAuthAnchorOpReturn(\n  fundedPrePeginTxHex: string,\n  vaultCount: number,\n  expectedAuthAnchorHashHex: string,\n): void {\n  const cleanHex = stripHexPrefix(fundedPrePeginTxHex);\n  const tx = bitcoin.Transaction.fromHex(cleanHex);\n\n  if (tx.outs.length <= vaultCount) {\n    throw new Error(\n      `Pre-PegIn auth-anchor OP_RETURN missing: tx has ${tx.outs.length} ` +\n        `outputs, expected at least ${vaultCount + 1} (vault outputs + OP_RETURN)`,\n    );\n  }\n\n  const opReturnOutput = tx.outs[vaultCount];\n  const script = opReturnOutput.script;\n  if (\n    script.length !== OP_RETURN_PUSH32_SCRIPT_LEN ||\n    script[0] !== OP_RETURN ||\n    script[1] !== OP_PUSH32\n  ) {\n    throw new Error(\n      `Pre-PegIn auth-anchor OP_RETURN at vout ${vaultCount} has unexpected ` +\n        `script encoding (got ${script.length}-byte script with prefix ` +\n        `0x${script.slice(0, Math.min(2, script.length)).toString(\"hex\")}; ` +\n        `expected ${OP_RETURN_PUSH32_SCRIPT_LEN}-byte OP_RETURN + PUSH32 layout)`,\n    );\n  }\n\n  const pushedHex = script.slice(2).toString(\"hex\").toLowerCase();\n  if (pushedHex !== expectedAuthAnchorHashHex.toLowerCase()) {\n    throw new Error(\n      `Pre-PegIn auth-anchor OP_RETURN payload mismatch at vout ${vaultCount}: ` +\n        `tx pushes ${pushedHex}, expected ${expectedAuthAnchorHashHex}`,\n    );\n  }\n\n  if (opReturnOutput.value !== 0) {\n    throw new Error(\n      `Pre-PegIn auth-anchor OP_RETURN at vout ${vaultCount} has non-zero ` +\n        `value ${opReturnOutput.value}; OP_RETURN outputs must be 0-value`,\n    );\n  }\n}\n\n/**\n * Scan a funded Pre-PegIn transaction for its auth-anchor commitment\n * (an `OP_RETURN || PUSH32 || <32 bytes>` output with value 0).\n *\n * Returns `{ vout, hash }` when exactly one such output is found.\n * Returns `undefined` when:\n *   - the hex is unparseable,\n *   - no matching output exists (legacy non-auth-anchored Pre-PegIn),\n *   - more than one matching output exists (ambiguous / malformed).\n *\n * Used by the refund orchestrator to (a) locate the on-chain anchor\n * regardless of how many HTLCs preceded it and (b) detect multi-vault\n * funded transactions structurally: the single-vault refund path\n * reconstructs only one hashlock and expects the anchor at vout 1, so\n * any other vout signals a layout this call cannot safely refund.\n */\nexport function findAuthAnchorOpReturn(\n  fundedPrePeginTxHex: string,\n): { vout: number; hash: string } | undefined {\n  let tx: bitcoin.Transaction;\n  try {\n    tx = bitcoin.Transaction.fromHex(stripHexPrefix(fundedPrePeginTxHex));\n  } catch {\n    return undefined;\n  }\n\n  const hits: { vout: number; hash: string }[] = [];\n  for (let i = 0; i < tx.outs.length; i++) {\n    const output = tx.outs[i];\n    const script = output.script;\n    if (\n      script.length === OP_RETURN_PUSH32_SCRIPT_LEN &&\n      script[0] === OP_RETURN &&\n      script[1] === OP_PUSH32 &&\n      output.value === 0\n    ) {\n      hits.push({\n        vout: i,\n        hash: script.slice(2).toString(\"hex\").toLowerCase(),\n      });\n    }\n  }\n\n  return hits.length === 1 ? hits[0] : undefined;\n}\n","/**\n * HTLC Secret / Hashlock Utilities\n *\n * Pure functions for computing and validating SHA-256 hashlocks used in the\n * vault deposit protocol's HTLC (Hash Time Lock Contract).\n *\n * The SDK does NOT generate secrets — that is the caller's responsibility.\n * Today callers use `crypto.getRandomValues(32)`; when the `deriveContextHash`\n * wallet API ships, callers will use `wallet.deriveContextHash(\"babylon-btc-vault\", ctx)`.\n * These utilities work identically regardless of how the secret was produced.\n *\n * On-chain contract validation (BTCVaultRegistry.activateVaultWithSecret):\n *   if (sha256(abi.encodePacked(s)) != hashlock) revert InvalidSecret();\n *\n * @module htlc\n */\n\nimport { sha256 } from \"@noble/hashes/sha2.js\";\nimport type { Hex } from \"viem\";\n\n/** Expected hex length for a 0x-prefixed bytes32 value. */\nconst HEX_BYTES32_LENGTH = 66; // \"0x\" + 64 hex chars\n\n/**\n * Decode a 0x-prefixed hex string to bytes, with strict validation.\n * @throws if the input is not a valid 0x-prefixed hex string\n */\nfunction hexToBytes(hex: Hex): Uint8Array {\n  if (!hex.startsWith(\"0x\") && !hex.startsWith(\"0X\")) {\n    throw new Error(\"Expected 0x-prefixed hex string\");\n  }\n  const clean = hex.slice(2);\n  if (clean.length % 2 !== 0) {\n    throw new Error(`Hex string has odd length: ${clean.length}`);\n  }\n  if (!/^[0-9a-fA-F]*$/.test(clean)) {\n    throw new Error(\"Hex string contains non-hex characters\");\n  }\n  const bytes = new Uint8Array(clean.length / 2);\n  for (let i = 0; i < bytes.length; i++) {\n    bytes[i] = parseInt(clean.slice(i * 2, i * 2 + 2), 16);\n  }\n  return bytes;\n}\n\n/**\n * Encode a Uint8Array as a 0x-prefixed lowercase hex string.\n */\nfunction bytesToHex(bytes: Uint8Array): Hex {\n  return `0x${Array.from(bytes)\n    .map((b) => b.toString(16).padStart(2, \"0\"))\n    .join(\"\")}`;\n}\n\n/**\n * Validate that a value is a 0x-prefixed bytes32 (exactly 32 bytes).\n * @throws if the value is not exactly 32 bytes\n */\nfunction assertBytes32(value: Hex, label: string): void {\n  if (value.length !== HEX_BYTES32_LENGTH) {\n    throw new Error(\n      `${label} must be exactly 32 bytes (${HEX_BYTES32_LENGTH} hex chars with 0x prefix), got ${value.length}`,\n    );\n  }\n}\n\n/**\n * Compute the SHA-256 hashlock from a secret preimage.\n *\n * Matches the on-chain validation: `sha256(abi.encodePacked(s))` where `s` is a `bytes32`.\n * `abi.encodePacked(bytes32)` is just the raw 32 bytes — no ABI padding.\n *\n * @param secret - 0x-prefixed bytes32 secret (66 hex chars)\n * @returns 0x-prefixed bytes32 SHA-256 hash\n * @throws if secret is not exactly 32 bytes\n */\nexport function computeHashlock(secret: Hex): Hex {\n  assertBytes32(secret, \"Secret\");\n  const secretBytes = hexToBytes(secret);\n  const hash = sha256(secretBytes);\n  return bytesToHex(hash);\n}\n\n/**\n * Validate that a secret's SHA-256 hash matches the expected hashlock.\n *\n * Use this for client-side pre-validation before sending the activation\n * transaction to avoid wasting gas on a contract revert.\n *\n * @param secret - 0x-prefixed bytes32 secret (66 hex chars)\n * @param hashlock - 0x-prefixed bytes32 expected hashlock from the vault\n * @returns true if SHA-256(secret) matches the hashlock\n * @throws if secret or hashlock is not exactly 32 bytes\n */\nexport function validateSecretAgainstHashlock(\n  secret: Hex,\n  hashlock: Hex,\n): boolean {\n  assertBytes32(secret, \"Secret\");\n  assertBytes32(hashlock, \"Hashlock\");\n  // Validate hashlock is valid hex (secret is validated inside computeHashlock)\n  hexToBytes(hashlock);\n\n  const computed = computeHashlock(secret);\n  return computed.toLowerCase() === hashlock.toLowerCase();\n}\n","import type { BitcoinWallet } from \"../../../shared/wallets/interfaces\";\n\n// Field docs use /** */ so they survive into the emitted .d.ts — the published\n// package is the only contract the external provider author (#2109) sees.\n\nexport interface DepositTermsVaultGroup {\n  /** 0-based; equals the group's position (groups are ascending by vout). */\n  readonly htlcVout: number;\n  /** x-only hex (64 chars), as validated on-chain upstream. */\n  readonly vaultProviderBtcPubkey: string;\n  /** sats */\n  readonly peginAmount: bigint;\n  /**\n   * sats; the MAXIMUM commission the depositor accepts —\n   * floor(peginAmount * maxAcceptableCommissionBps / 10_000), the same\n   * ceiling the registration calldata carries. An approving wallet MUST\n   * enforce the VP payout commission output `<= commissionFee` (e.g. the\n   * Ledger vault app does, firmware >= c8db53e), and every commission the\n   * contract admits stays under this ceiling (floor is monotonic in bps),\n   * so no contract-admitted deposit can be refused at payout. The actual\n   * stamped commission may be lower. Display the quoted value in UI, not this.\n   */\n  readonly commissionFee: bigint;\n  /** sats; the same value for every vault. */\n  readonly depositorClaimValue: bigint;\n  /**\n   * sats; the cap an approving wallet enforces on the PegIn tx fee. Equals\n   * the graph's exact (minimum) PegIn fee, which is deterministic — so the\n   * cap is satisfied exact-by-construction.\n   */\n  readonly peginMaxFee: bigint;\n}\n\n/**\n * Field names follow btc-vault vocabulary (the protocol source of truth);\n * a device-wire encoder maps them to its intent fields (e.g. the Ledger TLV:\n * protocolFeeRate -> base_fee_rate, timelockPegin -> pegin_csv_timelock,\n * timelockAssert -> payout_timelock, peginAmount -> vault_amount).\n */\nexport interface DepositTerms {\n  /**\n   * btc-vault tx-graph version (`vaultCoreVersion`) these terms describe —\n   * the vault's stamped on-chain version for resumes, the chain's\n   * `activeVaultCoreVersion` for fresh deposits. It selects the PegIn shape\n   * an approving wallet must expect: v1 = 2 outputs, no anchor; v2/v3 = TRUC\n   * nVersion 3, 3 outputs with a 240-sat P2A anchor at vout 2, and an\n   * Assert OP_RETURN marker that raises the claim value\n   * (btc-vault `transactions/pegin.rs`, `assert_marker.rs`). A provider that\n   * supports only one shape MUST reject the others here rather than\n   * mis-validating the PSBTs later.\n   */\n  vaultCoreVersion: number;\n  /**\n   * sat/vB; the tx-graph fee rate (protocolFeeRate), NOT the mempool funding\n   * rate. Approving wallets bound each payout's fee against this rate —\n   * pass the exact graph rate, not an inflated ceiling.\n   */\n  protocolFeeRate: bigint;\n  /** Vault-UTXO CSV timelock (blocks). */\n  timelockPegin: number;\n  /**\n   * btc-vault `timelock_assert` (t2) — the CSV on Assert output 0. Its own\n   * param, though production derives it and `timelockPegin` from one value.\n   */\n  timelockAssert: number;\n  /** HTLC refund CSV timelock (blocks). */\n  timelockRefund: number;\n  /**\n   * 64-char hex in display order. A device-wire encoder may need the\n   * little-endian form — some hardware byte-compares it against\n   * PSBT_IN_PREVIOUS_TXID rather than recomputing the txid.\n   */\n  prepeginTxid: string;\n  /** sats; the funded Pre-PegIn fee (an approving wallet caps the signed fee at this). */\n  prepeginMaxFee: bigint;\n  /**\n   * x-only hex. Sorted ascending by the upstream on-chain validation\n   * (validateOnChainParticipantKeys); the builder passes them through\n   * unasserted — approving devices may reject unsorted lists at load.\n   */\n  vaultKeeperBtcPubkeys: readonly string[];\n  /**\n   * x-only hex, sorted ascending upstream independently of vaultKeeperBtcPubkeys (same\n   * pass-through contract). Universal challengers only — the full graph\n   * challenger set is vaultKeeperBtcPubkeys ∪ universalChallengerBtcPubkeys (vault keepers are the local\n   * challengers).\n   */\n  universalChallengerBtcPubkeys: readonly string[];\n  /** Per-vault groups, ordered by ascending htlcVout. */\n  vaults: readonly DepositTermsVaultGroup[];\n}\n\n/**\n * Implemented only by depositor-approval wallets (e.g. a Ledger vault\n * provider). Provider obligations:\n *\n * - Envelope: validate terms against the device's envelope BEFORE the\n *   ceremony, rejecting with the shape `{ name: \"DepositTermsRejectedError\",\n *   reason: \"device-envelope\", message }` (matched structurally, not by class).\n * - Idempotence: a byte-equal re-approval MUST be a no-op while the\n *   device-side approval is live; anything that invalidates it (a later\n *   `deriveContextHash`, a signing failure) MUST clear the memo.\n *\n * Seam invariant: any derive invalidates a prior approval, so the SDK\n * re-approves after every derive and before the next terms-bound signature.\n * The re-approval sites are `PeginManager.preparePegin`,\n * `runDepositorPresignFlow`, and `signAndBroadcast` (the Pre-PegIn broadcast,\n * which re-derives before approving unless `holdsApprovedDepositTerms`\n * reports the byte-equal intent still live — see `ensurePrePeginTermsApproval`).\n */\nexport interface DepositTermsApprover {\n  approveDepositTerms(terms: DepositTerms): Promise<void>;\n  /**\n   * OPTIONAL fast-path probe: can the Pre-PegIn signature for exactly these\n   * terms proceed under the connection's held approval without a new\n   * ceremony? MUST report false once that Pre-PegIn was signed (one-shot),\n   * MUST answer from host state without device I/O, MUST return false on any\n   * doubt, and MUST never throw. A stale true fails closed at the next\n   * signature — this is a UX optimization, never an authorization.\n   */\n  holdsApprovedDepositTerms?(terms: DepositTerms): Promise<boolean>;\n  /**\n   * OPTIONAL validate-only pre-check (#2110): reject terms the device\n   * envelope would refuse, with the same `{ name:\n   * \"DepositTermsRejectedError\", reason: \"device-envelope\", message }` shape\n   * as `approveDepositTerms`, WITHOUT any device I/O and WITHOUT touching a\n   * held approval — the SDK calls it before the first derive screen, so a\n   * side effect here would cost or invalidate a physical ceremony. Success\n   * is NOT an approval: `approveDepositTerms` still runs its own envelope\n   * gate before the ceremony. Callers may pass provisional terms whose\n   * `prepeginTxid` is a placeholder (the real txid exists only post-derive),\n   * so implementations MUST NOT validate or bind `prepeginTxid` here.\n   */\n  validateDepositTerms?(terms: DepositTerms): Promise<void>;\n}\n\n/**\n * Where Pre-PegIn change must pay. Approval (policy) wallets sign key-path\n * under a wallet policy whose change branch the device alone can derive and\n * mark internal — the receive address is NOT acceptable change\n * (`process_in_outs.c:114-117` @ e400d8d8).\n *\n * Separate from {@link DepositTermsApprover} because only the Pre-PegIn build\n * needs it: the presign/payout ceremonies approve terms without ever creating\n * change, so they must not require a wallet to implement this.\n *\n * MUST be stable across a deposit flow: the app reads it to build the tx and\n * `preparePegin` re-reads it to verify, so mid-flow rotation fails that gate.\n */\nexport interface PrePeginChangeSource {\n  getChangeAddress(): Promise<string>;\n}\n\n/** Probes {@link DepositTermsApprover.approveDepositTerms}. */\nexport function supportsDepositApproval(\n  wallet: BitcoinWallet,\n): wallet is BitcoinWallet & DepositTermsApprover {\n  return (\n    typeof (wallet as Partial<DepositTermsApprover>).approveDepositTerms ===\n    \"function\"\n  );\n}\n\n/**\n * The wallet's change address, for the one caller that needs it.\n *\n * Narrowing on `approveDepositTerms` alone cannot promise this method, so\n * calling it off the narrowed value would die on `is not a function` in the\n * middle of `preparePegin`, after the pubkey read. Ask here instead and fail\n * with something a provider author can act on.\n *\n * @throws If the wallet cannot report a change address.\n */\nexport async function requireChangeAddress(\n  wallet: BitcoinWallet,\n): Promise<string> {\n  const changeSource = wallet as Partial<PrePeginChangeSource>;\n  if (typeof changeSource.getChangeAddress !== \"function\") {\n    throw new Error(\n      \"Approval wallet does not implement getChangeAddress; it must expose its change branch, \" +\n        \"because the signing device accepts Pre-PegIn change only there.\",\n    );\n  }\n  return changeSource.getChangeAddress();\n}\n\n/**\n * Spreadable forward of the approval capability for wallet-wrapper objects.\n * Object spread drops prototype methods, so every `{...wallet}` wrapper site\n * must re-attach the capability explicitly: `...forwardDepositApproval(wallet)`.\n */\nexport function forwardDepositApproval(\n  wallet: BitcoinWallet,\n): Partial<DepositTermsApprover & PrePeginChangeSource> {\n  if (!supportsDepositApproval(wallet)) {\n    return {};\n  }\n  const holdsApprovedDepositTerms = wallet.holdsApprovedDepositTerms;\n  const validateDepositTerms = wallet.validateDepositTerms;\n  const getChangeAddress = (wallet as Partial<PrePeginChangeSource>)\n    .getChangeAddress;\n  return {\n    approveDepositTerms: (terms) => wallet.approveDepositTerms(terms),\n    // All optional in the seam: forward only what the provider implements, so\n    // wrapper consumers can keep probing by typeof.\n    ...(typeof getChangeAddress === \"function\"\n      ? { getChangeAddress: () => getChangeAddress.call(wallet) }\n      : {}),\n    ...(typeof holdsApprovedDepositTerms === \"function\"\n      ? {\n          holdsApprovedDepositTerms: (terms: DepositTerms) =>\n            holdsApprovedDepositTerms.call(wallet, terms),\n        }\n      : {}),\n    ...(typeof validateDepositTerms === \"function\"\n      ? {\n          validateDepositTerms: (terms: DepositTerms) =>\n            validateDepositTerms.call(wallet, terms),\n        }\n      : {}),\n  };\n}\n\nexport interface BuildDepositTermsInputs {\n  /** btc-vault tx-graph version the graph is built under. */\n  vaultCoreVersion: number;\n  protocolFeeRate: bigint;\n  timelockPegin: number;\n  /** btc-vault `timelock_assert` (t2) — its own param; NOT derived from timelockPegin here. */\n  timelockAssert: number;\n  timelockRefund: number;\n  prepeginTxid: string;\n  prepeginMaxFee: bigint;\n  vaultProviderBtcPubkey: string;\n  vaultKeeperBtcPubkeys: readonly string[];\n  universalChallengerBtcPubkeys: readonly string[];\n  /** Ceiling bps, not the quote — see {@link DepositTermsVaultGroup.commissionFee}. */\n  maxAcceptableCommissionBps: number;\n  peginAmounts: readonly bigint[];\n  depositorClaimValue: bigint;\n  peginMaxFee: bigint;\n}\n","/**\n * Payout Manager\n *\n * High-level manager that orchestrates the payout signing flow by coordinating\n * SDK primitives ({@link buildPayoutPsbt}, {@link extractPayoutSignature})\n * with a user-provided Bitcoin wallet.\n *\n * The Payout transaction references the Assert transaction (input 1).\n *\n * @see {@link PeginManager} - For Steps 1–4 of the peg-in flow\n * @see {@link buildPayoutPsbt} - Lower-level primitive for custom implementations\n * @see {@link extractPayoutSignature} - Extract signatures from signed PSBTs\n *\n * @module managers/PayoutManager\n */\n\nimport type { BitcoinWallet, SignPsbtOptions } from \"../../../shared/wallets\";\nimport {\n  assertPsbtUnsignedTxMatches,\n  assertScriptPathSchnorrSignature,\n  buildPayoutPsbt,\n  extractPayoutSignature,\n  validateWalletPubkey,\n  type Network,\n} from \"../primitives\";\nimport { createTaprootScriptPathSignOptions } from \"../utils/signing\";\n\n/** Payout PSBTs are signed by the depositor on input 0 (Taproot script-path). */\nconst PAYOUT_SIGNED_INPUT_INDEX = 0;\n\n/**\n * Configuration for the PayoutManager.\n */\nexport interface PayoutManagerConfig {\n  /**\n   * Bitcoin network to use for transactions.\n   */\n  network: Network;\n\n  /**\n   * Bitcoin wallet for signing payout transactions.\n   */\n  btcWallet: BitcoinWallet;\n}\n\n/**\n * Base parameters shared by both payout transaction types.\n */\ninterface SignPayoutBaseParams {\n  /**\n   * Vault core (tx-graph) version the vault was registered under — the\n   * vault's stamped on-chain `vaultCoreVersion`. Forwarded to\n   * {@link buildPayoutPsbt} to derive the matching graph's payout scripts.\n   */\n  vaultCoreVersion: number;\n\n  /**\n   * Peg-in transaction hex.\n   * The original transaction that created the vault output being spent.\n   */\n  peginTxHex: string;\n\n  /**\n   * Vault provider's BTC public key (x-only, 64-char hex).\n   */\n  vaultProviderBtcPubkey: string;\n\n  /**\n   * Vault keeper BTC public keys (x-only, 64-char hex).\n   */\n  vaultKeeperBtcPubkeys: string[];\n\n  /**\n   * Universal challenger BTC public keys (x-only, 64-char hex).\n   */\n  universalChallengerBtcPubkeys: string[];\n\n  /**\n   * CSV timelock in blocks for the PegIn output.\n   */\n  timelockPegin: number;\n  /** btc-vault `timelock_assert`; payout input 1's sequence. */\n  timelockAssert: number;\n\n  /**\n   * Depositor's BTC public key (x-only, 64-char hex). This MUST be the\n   * key registered on-chain for the vault — typically read from\n   * `BTCVaultRegistry.getBtcVaultBasicInfo(...).depositorBtcPubKey`.\n   *\n   * Required: omitting it would degrade `validateWalletPubkey` to a\n   * self-comparison, allowing the wrong wallet to produce a signature\n   * over a script tree that doesn't match the on-chain UTXO.\n   */\n  depositorBtcPubkey: string;\n\n  /**\n   * The on-chain registered depositor payout scriptPubKey (hex, with or without 0x prefix).\n   * Used to validate that the VP-provided payout transaction actually pays to the\n   * correct depositor payout address before signing.\n   */\n  registeredPayoutScriptPubKey: string;\n\n  /**\n   * The claimer's x-only BTC public key for this payout (64-char hex, no prefix).\n   * Forwarded to {@link buildPayoutPsbt} for per-role output validation.\n   */\n  claimerBtcPubkey: string;\n\n  /**\n   * VP commission in basis points (`1..=9999`). Forwarded to {@link buildPayoutPsbt}.\n   */\n  commissionBps: number;\n\n  /**\n   * Version-locked tx-graph fee rate (sat/vB) the graph was built with.\n   * Forwarded to {@link buildPayoutPsbt} for the fee band.\n   */\n  protocolFeeRate: bigint;\n\n  /**\n   * Security council member x-only pubkeys (hex); forwarded to\n   * {@link buildPayoutPsbt} to rebuild the Assert:0 payout leaf and to size the\n   * fee floor (see PayoutParams).\n   */\n  councilMembers: string[];\n\n  /** M-of-N council quorum; shapes the Assert:0 council leaf (see PayoutParams). */\n  councilQuorum: number;\n\n  /**\n   * RFC-006 resolved payout destinations, keyed by lowercased x-only operation\n   * pubkey. Forwarded verbatim to {@link buildPayoutPsbt}; every VK claimer\n   * must be present.\n   */\n  vkClaimerPayoutScriptPubKeys: Readonly<Record<string, string>>;\n  /** RFC-006 VP commission destination. Forwarded to {@link buildPayoutPsbt}. */\n  vpCommissionScriptPubKey: string;\n}\n\n/**\n * Parameters for signing a Payout transaction.\n *\n * Payout is used in the challenge path after Assert, when the claimer proves validity.\n * Input 1 references the Assert transaction.\n */\nexport interface SignPayoutParams extends SignPayoutBaseParams {\n  /**\n   * Payout transaction hex (unsigned).\n   * This is the transaction from the vault provider that needs depositor signature.\n   */\n  payoutTxHex: string;\n\n  /**\n   * Assert transaction hex.\n   * Payout input 1 references Assert output 0.\n   */\n  assertTxHex: string;\n}\n\n/**\n * Result of signing a payout transaction.\n */\nexport interface PayoutSignatureResult {\n  /**\n   * 64-byte Schnorr signature (128 hex characters).\n   */\n  signature: string;\n\n  /**\n   * Depositor's BTC public key used for signing.\n   */\n  depositorBtcPubkey: string;\n}\n\n/**\n * High-level manager for payout transaction signing.\n *\n * @remarks\n * After registering your peg-in on Ethereum (Step 3), the vault provider prepares\n * claim/payout transaction pairs. You must sign each payout transaction using this\n * manager and submit the signatures to the vault provider's RPC API.\n *\n * **What happens internally:**\n * 1. Validates your wallet's public key matches the vault's depositor\n * 2. Builds an unsigned PSBT with taproot script path spend info\n * 3. Signs input 0 (the vault UTXO) with your wallet\n * 4. Extracts the 64-byte Schnorr signature\n *\n * **Note:** The payout transaction has 2 inputs. PayoutManager only signs input 0\n * (from the peg-in tx). Input 1 (from the assert tx) is signed by the vault provider.\n *\n * @see {@link PeginManager} - For the complete peg-in flow context\n * @see {@link buildPayoutPsbt} - Lower-level primitive used internally\n * @see {@link extractPayoutSignature} - Signature extraction primitive\n */\nexport class PayoutManager {\n  private readonly config: PayoutManagerConfig;\n\n  /**\n   * Creates a new PayoutManager instance.\n   *\n   * @param config - Manager configuration including wallet\n   */\n  constructor(config: PayoutManagerConfig) {\n    this.config = config;\n  }\n\n  /**\n   * Signs a Payout transaction and extracts the Schnorr signature.\n   *\n   * Flow:\n   * 1. Vault provider submits Claim transaction\n   * 2. Claimer submits Assert transaction to prove validity\n   * 3. Payout can be executed (references Assert tx)\n   *\n   * This method orchestrates the following steps:\n   * 1. Get wallet's public key and convert to x-only format\n   * 2. Validate wallet pubkey matches on-chain depositor pubkey (if provided)\n   * 3. Build unsigned PSBT using primitives\n   * 4. Sign PSBT via btcWallet.signPsbt()\n   * 5. Extract 64-byte Schnorr signature using primitives\n   *\n   * The returned signature can be submitted to the vault provider API.\n   *\n   * @param params - Payout signing parameters\n   * @returns Signature result with 64-byte Schnorr signature and depositor pubkey\n   * @throws Error if wallet pubkey doesn't match depositor pubkey\n   * @throws Error if wallet operations fail or signature extraction fails\n   */\n  async signPayoutTransaction(\n    params: SignPayoutParams,\n  ): Promise<PayoutSignatureResult> {\n    // Validate wallet pubkey matches depositor and get both formats\n    const walletPubkeyRaw = await this.config.btcWallet.getPublicKeyHex();\n    const { depositorPubkey } = validateWalletPubkey(\n      walletPubkeyRaw,\n      params.depositorBtcPubkey,\n    );\n\n    // Build unsigned PSBT for Payout (uses Assert tx). Per-role output\n    // validation happens inside buildPayoutPsbt against the resolved input\n    // values.\n    const payoutPsbt = await buildPayoutPsbt({\n      vaultCoreVersion: params.vaultCoreVersion,\n      payoutTxHex: params.payoutTxHex,\n      peginTxHex: params.peginTxHex,\n      assertTxHex: params.assertTxHex,\n      depositorBtcPubkey: depositorPubkey,\n      vaultProviderBtcPubkey: params.vaultProviderBtcPubkey,\n      vaultKeeperBtcPubkeys: params.vaultKeeperBtcPubkeys,\n      universalChallengerBtcPubkeys: params.universalChallengerBtcPubkeys,\n      timelockPegin: params.timelockPegin,\n      timelockAssert: params.timelockAssert,\n      network: this.config.network,\n      claimerBtcPubkey: params.claimerBtcPubkey,\n      registeredPayoutScriptPubKey: params.registeredPayoutScriptPubKey,\n      commissionBps: params.commissionBps,\n      protocolFeeRate: params.protocolFeeRate,\n      councilMembers: params.councilMembers,\n      councilQuorum: params.councilQuorum,\n      vkClaimerPayoutScriptPubKeys: params.vkClaimerPayoutScriptPubKeys,\n      vpCommissionScriptPubKey: params.vpCommissionScriptPubKey,\n    });\n\n    // Sign PSBT via wallet (Taproot script-path spend, input 0 only)\n    const signedPsbtHex = await this.config.btcWallet.signPsbt(\n      payoutPsbt.psbtHex,\n      createTaprootScriptPathSignOptions(walletPubkeyRaw, 1),\n    );\n\n    assertPsbtUnsignedTxMatches({\n      requestedPsbtHex: payoutPsbt.psbtHex,\n      returnedPsbtHex: signedPsbtHex,\n    });\n\n    // Extract Schnorr signature\n    const signature = extractPayoutSignature(signedPsbtHex, depositorPubkey);\n    // Critical Path #7: verify the signature against a sighash recomputed from\n    // the PSBT we built, not the wallet-returned one.\n    assertScriptPathSchnorrSignature({\n      requestedPsbtHex: payoutPsbt.psbtHex,\n      signatureHex: signature,\n      signerXOnlyPubkeyHex: depositorPubkey,\n      inputIndex: PAYOUT_SIGNED_INPUT_INDEX,\n    });\n\n    return {\n      signature,\n      depositorBtcPubkey: depositorPubkey,\n    };\n  }\n\n  /**\n   * Gets the configured Bitcoin network.\n   *\n   * @returns The Bitcoin network (mainnet, testnet, signet, regtest)\n   */\n  getNetwork(): Network {\n    return this.config.network;\n  }\n\n  /**\n   * Checks if the wallet supports batch signing (signPsbts).\n   *\n   * @returns true if batch signing is supported\n   */\n  supportsBatchSigning(): boolean {\n    return typeof this.config.btcWallet.signPsbts === \"function\";\n  }\n\n  /**\n   * Batch signs multiple payout transactions (1 per claimer).\n   * This allows signing all transactions with a single wallet interaction.\n   *\n   * @param transactions - Array of payout params to sign\n   * @returns Array of signature results matching input order\n   * @throws Error if wallet doesn't support batch signing\n   * @throws Error if any signing operation fails\n   */\n  async signPayoutTransactionsBatch(transactions: SignPayoutParams[]): Promise<\n    Array<{\n      payoutSignature: string;\n      depositorBtcPubkey: string;\n    }>\n  > {\n    if (!this.supportsBatchSigning()) {\n      throw new Error(\n        \"Wallet does not support batch signing (signPsbts method not available)\",\n      );\n    }\n\n    // Get wallet pubkey once\n    const walletPubkeyRaw = await this.config.btcWallet.getPublicKeyHex();\n\n    // Build all PSBTs (1 per claimer)\n    const psbtsToSign: string[] = [];\n    const signOptions: SignPsbtOptions[] = [];\n    const depositorPubkeys: string[] = [];\n\n    for (const tx of transactions) {\n      // Validate wallet pubkey matches depositor\n      const { depositorPubkey } = validateWalletPubkey(\n        walletPubkeyRaw,\n        tx.depositorBtcPubkey,\n      );\n      depositorPubkeys.push(depositorPubkey);\n\n      // Build Payout PSBT (output validation runs inside buildPayoutPsbt\n      // against resolved input values).\n      const payoutPsbt = await buildPayoutPsbt({\n        vaultCoreVersion: tx.vaultCoreVersion,\n        payoutTxHex: tx.payoutTxHex,\n        peginTxHex: tx.peginTxHex,\n        assertTxHex: tx.assertTxHex,\n        depositorBtcPubkey: depositorPubkey,\n        vaultProviderBtcPubkey: tx.vaultProviderBtcPubkey,\n        vaultKeeperBtcPubkeys: tx.vaultKeeperBtcPubkeys,\n        universalChallengerBtcPubkeys: tx.universalChallengerBtcPubkeys,\n        timelockPegin: tx.timelockPegin,\n        timelockAssert: tx.timelockAssert,\n        network: this.config.network,\n        claimerBtcPubkey: tx.claimerBtcPubkey,\n        registeredPayoutScriptPubKey: tx.registeredPayoutScriptPubKey,\n        commissionBps: tx.commissionBps,\n        protocolFeeRate: tx.protocolFeeRate,\n        councilMembers: tx.councilMembers,\n        councilQuorum: tx.councilQuorum,\n        vkClaimerPayoutScriptPubKeys: tx.vkClaimerPayoutScriptPubKeys,\n        vpCommissionScriptPubKey: tx.vpCommissionScriptPubKey,\n      });\n      psbtsToSign.push(payoutPsbt.psbtHex);\n      signOptions.push(createTaprootScriptPathSignOptions(walletPubkeyRaw, 1));\n    }\n\n    // Batch sign all PSBTs with single wallet interaction\n    const signedPsbts = await this.config.btcWallet.signPsbts!(\n      psbtsToSign,\n      signOptions,\n    );\n\n    // Validate that wallet returned the expected number of signed PSBTs\n    if (signedPsbts.length !== transactions.length) {\n      throw new Error(\n        `Expected ${transactions.length} signed PSBTs but received ${signedPsbts.length}`,\n      );\n    }\n\n    // Extract signatures from signed PSBTs\n    const results: Array<{\n      payoutSignature: string;\n      depositorBtcPubkey: string;\n    }> = [];\n\n    for (let i = 0; i < transactions.length; i++) {\n      const depositorPubkey = depositorPubkeys[i];\n      assertPsbtUnsignedTxMatches({\n        requestedPsbtHex: psbtsToSign[i],\n        returnedPsbtHex: signedPsbts[i],\n      });\n      const payoutSignature = extractPayoutSignature(\n        signedPsbts[i],\n        depositorPubkey,\n      );\n      assertScriptPathSchnorrSignature({\n        requestedPsbtHex: psbtsToSign[i],\n        signatureHex: payoutSignature,\n        signerXOnlyPubkeyHex: depositorPubkey,\n        inputIndex: PAYOUT_SIGNED_INPUT_INDEX,\n      });\n\n      results.push({\n        payoutSignature,\n        depositorBtcPubkey: depositorPubkey,\n      });\n    }\n\n    return results;\n  }\n}\n","/**\n * Wallet-signing helper that routes a lone PSBT to `signPsbt`, prefers native\n * `signPsbts` for real batches, and falls back to sequential `signPsbt` for\n * wallets that don't implement batch signing.\n *\n * @module managers/pegin/signPsbtsWithFallback\n */\n\nimport type {\n  BitcoinWallet,\n  SignPsbtOptions,\n} from \"../../../../shared/wallets\";\n\n/**\n * Sign one or more PSBTs against a wallet.\n *\n * A single PSBT is always signed via `signPsbt`, never the batch endpoint: it's\n * one wallet interaction either way, and `signPsbt` is the universally-required\n * wallet method (batch `signPsbts` is optional), so single-sign is the portable\n * choice — some integrations (notably MPC / institutional wallets) prefer it.\n * For a real batch (>1), wallets exposing native `signPsbts` (e.g. UniSat) sign\n * in one interaction; others loop `signPsbt`.\n *\n * @throws If native `signPsbts` returns a different number of signed PSBTs\n *         than were submitted.\n */\nexport async function signPsbtsWithFallback(\n  wallet: BitcoinWallet,\n  psbtsHexes: string[],\n  options?: SignPsbtOptions[],\n): Promise<string[]> {\n  if (psbtsHexes.length === 1) {\n    return [await wallet.signPsbt(psbtsHexes[0], options?.[0])];\n  }\n\n  if (typeof wallet.signPsbts === \"function\") {\n    const signedPsbts = await wallet.signPsbts(psbtsHexes, options);\n    if (signedPsbts.length !== psbtsHexes.length) {\n      throw new Error(\n        `Expected ${psbtsHexes.length} signed PSBTs but received ${signedPsbts.length}`,\n      );\n    }\n    return signedPsbts;\n  }\n\n  const signedPsbts: string[] = [];\n  for (let i = 0; i < psbtsHexes.length; i++) {\n    signedPsbts.push(await wallet.signPsbt(psbtsHexes[i], options?.[i]));\n  }\n  return signedPsbts;\n}\n"],"names":["OP_RETURN","OP_PUSH32","OP_RETURN_PUSH32_SCRIPT_LEN","assertAuthAnchorOpReturn","fundedPrePeginTxHex","vaultCount","expectedAuthAnchorHashHex","cleanHex","stripHexPrefix","tx","bitcoin","opReturnOutput","script","pushedHex","findAuthAnchorOpReturn","hits","i","output","HEX_BYTES32_LENGTH","hexToBytes","hex","clean","bytes","bytesToHex","b","assertBytes32","value","label","computeHashlock","secret","secretBytes","hash","sha256","validateSecretAgainstHashlock","hashlock","supportsDepositApproval","wallet","requireChangeAddress","changeSource","forwardDepositApproval","holdsApprovedDepositTerms","validateDepositTerms","getChangeAddress","terms","PAYOUT_SIGNED_INPUT_INDEX","PayoutManager","config","__publicField","params","walletPubkeyRaw","depositorPubkey","validateWalletPubkey","payoutPsbt","buildPayoutPsbt","signedPsbtHex","createTaprootScriptPathSignOptions","assertPsbtUnsignedTxMatches","signature","extractPayoutSignature","assertScriptPathSchnorrSignature","transactions","psbtsToSign","signOptions","depositorPubkeys","signedPsbts","results","payoutSignature","signPsbtsWithFallback","psbtsHexes","options"],"mappings":"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"}