{"version":3,"file":"bitcoin-m84N5a8o.cjs","sources":["../src/tbv/core/primitives/utils/bitcoin.ts"],"sourcesContent":["/**\n * Bitcoin Utilities\n *\n * Common pure utility functions for Bitcoin operations including:\n * - Public key conversions (x-only format)\n * - Hex string manipulation\n * - Uint8Array conversions and validation\n * - Address derivation and validation\n *\n * All functions are pure (no side effects) and work in Node.js, browsers,\n * and serverless environments.\n *\n * @module primitives/utils/bitcoin\n */\n\nimport { networks, payments } from \"bitcoinjs-lib\";\nimport { Buffer } from \"buffer\";\n\nimport type { Network } from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport type { Hex } from \"viem\";\n\n/**\n * BIP-341 Tapscript leaf version for script-path spends.\n * @see https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki\n * @see Rust: bitcoin::taproot::LeafVersion::TapScript\n */\nexport const TAPSCRIPT_LEAF_VERSION = 0xc0;\n\n/**\n * Hex-string length of a 32-byte BIP-340 x-only public key (taproot,\n * Schnorr). Doubles the byte count: `2 * 32 = 64`.\n */\nexport const X_ONLY_PUBKEY_HEX_LEN = 64;\n\n/**\n * Hex-string length of a 33-byte SEC1-compressed secp256k1 public key\n * (`0x02` or `0x03` prefix + 32-byte x-coordinate). `2 * 33 = 66`.\n */\nexport const COMPRESSED_PUBKEY_HEX_LEN = 66;\n\n/**\n * Hex-string length of a 65-byte SEC1-uncompressed secp256k1 public\n * key (`0x04` prefix + 32-byte x + 32-byte y). `2 * 65 = 130`.\n */\nconst UNCOMPRESSED_PUBKEY_HEX_LEN = 130;\n\n/**\n * Hex-string length of a 64-byte BIP-340 Schnorr signature. `2 * 64 = 128`.\n */\nexport const SCHNORR_SIG_HEX_LEN = 128;\n\n/**\n * Strip \"0x\" prefix from hex string if present.\n *\n * Bitcoin expects plain hex (no \"0x\" prefix), but frontend often uses\n * Ethereum-style \"0x\"-prefixed hex.\n *\n * @param hex - Hex string with or without \"0x\" prefix\n * @returns Hex string without \"0x\" prefix\n */\nexport function stripHexPrefix(hex: string): string {\n  return hex.startsWith(\"0x\") || hex.startsWith(\"0X\") ? hex.slice(2) : hex;\n}\n\n/**\n * Ensure \"0x\" prefix on a hex string, returning viem's Hex type.\n *\n * Ethereum/viem APIs expect `0x`-prefixed hex, but Bitcoin tooling\n * typically omits the prefix. This normalises either form.\n *\n * @param hex - Hex string with or without \"0x\" prefix\n * @returns `0x`-prefixed hex string typed as viem Hex\n */\nexport function ensureHexPrefix(hex: string): Hex {\n  if (hex.startsWith(\"0x\")) return hex as Hex;\n  if (hex.startsWith(\"0X\")) return `0x${hex.slice(2)}` as Hex;\n  return `0x${hex}` as Hex;\n}\n\n/**\n * Convert hex string to Uint8Array.\n *\n * @param hex - Hex string (with or without 0x prefix)\n * @returns Uint8Array\n * @throws If hex is invalid\n */\nexport function hexToUint8Array(hex: string): Uint8Array {\n  const cleanHex = stripHexPrefix(hex);\n  if (!isValidHexRaw(cleanHex)) {\n    throw new Error(`Invalid hex string: ${hex}`);\n  }\n  const bytes = new Uint8Array(cleanHex.length / 2);\n  for (let i = 0; i < cleanHex.length; i += 2) {\n    bytes[i / 2] = parseInt(cleanHex.slice(i, i + 2), 16);\n  }\n  return bytes;\n}\n\n/**\n * Convert Uint8Array to hex string (without 0x prefix).\n *\n * @param bytes - Uint8Array to convert\n * @returns Hex string without 0x prefix\n */\nexport function uint8ArrayToHex(bytes: Uint8Array): string {\n  return Array.from(bytes)\n    .map((b) => b.toString(16).padStart(2, \"0\"))\n    .join(\"\");\n}\n\n/**\n * Read the prevout txid (big-endian hex) from a bitcoinjs-lib transaction input.\n *\n * bitcoinjs-lib stores `hash` in little-endian internal byte order; txids are\n * displayed in big-endian, so the bytes must be reversed before hex-encoding.\n *\n * @param input - Transaction input with a `hash` field (Buffer or Uint8Array)\n * @returns Prevout txid as a hex string (big-endian, no 0x prefix)\n */\nexport function inputTxidHex(input: { hash: Buffer | Uint8Array }): string {\n  return uint8ArrayToHex(new Uint8Array(input.hash).slice().reverse());\n}\n\n/**\n * Convert a 33-byte public key to 32-byte x-only format (removes first byte).\n *\n * Used for Taproot/Schnorr signatures which only need the x-coordinate.\n * If the input is already 32 bytes, returns it unchanged.\n *\n * @param pubKey - 33-byte or 32-byte public key\n * @returns 32-byte x-only public key\n */\nexport function toXOnly(pubKey: Uint8Array): Uint8Array {\n  return pubKey.length === 32 ? pubKey : pubKey.slice(1, 33);\n}\n\n/**\n * Internal helper: Validate hex string format without stripping prefix\n *\n * @internal\n * @param hex - Hex string (must already have prefix stripped)\n * @returns true if valid hex string\n */\nfunction isValidHexRaw(hex: string): boolean {\n  return /^[0-9a-fA-F]*$/.test(hex) && hex.length % 2 === 0;\n}\n\n/**\n * Process and convert a public key to x-only format (32 bytes hex).\n *\n * Handles:\n * - 0x prefix removal\n * - Hex character validation\n * - Length validation\n * - Conversion to x-only format\n *\n * Accepts:\n * - 64 hex chars (32 bytes) - already x-only\n * - 66 hex chars (33 bytes) - compressed pubkey\n * - 130 hex chars (65 bytes) - uncompressed pubkey\n *\n * @param publicKeyHex - Public key in hex format (with or without 0x prefix)\n * @returns X-only public key as 32 bytes hex string (without 0x prefix)\n * @throws If public key format is invalid or contains invalid hex characters\n */\nexport function processPublicKeyToXOnly(publicKeyHex: string): string {\n  // Remove '0x' prefix if present\n  const cleanHex = stripHexPrefix(publicKeyHex);\n\n  // Validate hex characters early to prevent silent failures\n  if (!isValidHexRaw(cleanHex)) {\n    throw new Error(`Invalid hex characters in public key: ${publicKeyHex}`);\n  }\n\n  // If already 64 chars (32 bytes), it's already x-only format\n  if (cleanHex.length === X_ONLY_PUBKEY_HEX_LEN) {\n    return cleanHex;\n  }\n\n  // Validate public key length (compressed SEC1 or uncompressed SEC1)\n  if (\n    cleanHex.length !== COMPRESSED_PUBKEY_HEX_LEN &&\n    cleanHex.length !== UNCOMPRESSED_PUBKEY_HEX_LEN\n  ) {\n    throw new Error(\n      `Invalid public key length: ${cleanHex.length} (expected ${X_ONLY_PUBKEY_HEX_LEN}, ${COMPRESSED_PUBKEY_HEX_LEN}, or ${UNCOMPRESSED_PUBKEY_HEX_LEN} hex chars)`,\n    );\n  }\n\n  const pubkeyBytes = hexToUint8Array(cleanHex);\n  return uint8ArrayToHex(toXOnly(pubkeyBytes));\n}\n\n/**\n * Normalize a public key to the one form two keys can be compared in:\n * lowercase x-only hex, no `0x`.\n *\n * `processPublicKeyToXOnly` returns already-x-only input untouched, so it\n * preserves case on that path — comparing its output directly is a latent\n * false mismatch for any source that serves uppercase hex. Every comparison\n * site therefore has to pair it with `.toLowerCase()`, and that pairing is\n * what this function exists to stop people re-deriving by hand.\n *\n * @param publicKeyHex - x-only, compressed, or uncompressed key, `0x` optional\n * @throws If the key is not valid hex or has an unexpected length\n */\nexport function canonicalizeBtcPubkey(publicKeyHex: string): string {\n  return processPublicKeyToXOnly(publicKeyHex).toLowerCase();\n}\n\n/**\n * Validate hex string format.\n *\n * Checks that the string contains only valid hexadecimal characters (0-9, a-f, A-F)\n * and has an even length (since each byte is represented by 2 hex characters).\n *\n * @param hex - String to validate (with or without 0x prefix)\n * @returns true if valid hex string\n */\nexport function isValidHex(hex: string): boolean {\n  const cleanHex = stripHexPrefix(hex);\n  return isValidHexRaw(cleanHex);\n}\n\n/**\n * Result of validating a wallet public key against an expected depositor public key.\n */\nexport interface WalletPubkeyValidationResult {\n  /** Wallet's raw public key (as returned by wallet, may be compressed) */\n  walletPubkeyRaw: string;\n  /** Wallet's public key in x-only format (32 bytes, 64 hex chars) */\n  walletPubkeyXOnly: string;\n  /** The validated depositor public key (x-only format) */\n  depositorPubkey: string;\n}\n\n/**\n * Validate that a wallet's public key matches the expected depositor public key.\n *\n * This function:\n * 1. Converts the wallet pubkey to x-only format\n * 2. Validates the wallet x-only pubkey matches the expected depositor pubkey\n *    (case-insensitive)\n *\n * @param walletPubkeyRaw - Raw public key from wallet (may be compressed 66 chars or x-only 64 chars)\n * @param expectedDepositorPubkey - Expected depositor public key (x-only).\n *   Required: omitting it would degrade this check to a self-comparison.\n * @returns Validation result with both pubkey formats\n * @throws If `expectedDepositorPubkey` is missing/empty\n * @throws If wallet pubkey doesn't match expected depositor pubkey\n */\nexport function validateWalletPubkey(\n  walletPubkeyRaw: string,\n  expectedDepositorPubkey: string,\n): WalletPubkeyValidationResult {\n  if (!expectedDepositorPubkey) {\n    throw new Error(\n      \"validateWalletPubkey requires expectedDepositorPubkey. Pass the on-chain registered depositor pubkey to avoid a self-comparison.\",\n    );\n  }\n\n  const walletPubkeyXOnly = processPublicKeyToXOnly(walletPubkeyRaw);\n  const depositorPubkey = expectedDepositorPubkey;\n\n  if (walletPubkeyXOnly.toLowerCase() !== depositorPubkey.toLowerCase()) {\n    throw new Error(\n      `Wallet public key does not match vault depositor. ` +\n        `Expected: ${depositorPubkey}, Got: ${walletPubkeyXOnly}. ` +\n        `Please connect the wallet that was used to create this vault.`,\n    );\n  }\n\n  return { walletPubkeyRaw, walletPubkeyXOnly, depositorPubkey };\n}\n\n// ============================================================================\n// BTC formatting\n// ============================================================================\n\nconst SATOSHIS_PER_BTC = 100_000_000n;\n\n/**\n * Format satoshis as a human-readable BTC string with trailing zeros removed.\n */\nexport function formatSatoshisToBtc(satoshis: bigint): string {\n  if (satoshis < 0n) {\n    return `-${formatSatoshisToBtc(-satoshis)}`;\n  }\n  const whole = satoshis / SATOSHIS_PER_BTC;\n  const fraction = satoshis % SATOSHIS_PER_BTC;\n  let fractionStr = fraction.toString().padStart(8, \"0\");\n  fractionStr = fractionStr.replace(/0+$/, \"\");\n  return fractionStr.length > 0 ? `${whole}.${fractionStr}` : whole.toString();\n}\n\n// ============================================================================\n// Address derivation and validation\n// ============================================================================\n\n/**\n * Assert that the ECC library has been initialized via `initEccLib(ecc)`.\n *\n * The consuming application must call `initEccLib(ecc)` from `bitcoinjs-lib`\n * once at startup before using any SDK function that involves Taproot / P2TR\n * operations. This guard provides a clear error message when that step was\n * missed, instead of letting bitcoinjs-lib throw its generic\n * \"No ECC Library provided\" error deep in a call stack.\n */\nexport function assertEccInitialized(): void {\n  try {\n    payments.p2tr({ internalPubkey: Buffer.alloc(32, 1) });\n  } catch (e) {\n    if (e instanceof Error && e.message.includes(\"No ECC Library provided\")) {\n      throw new Error(\n        \"ECC library not initialized. \" +\n          'You must call initEccLib(ecc) from \"bitcoinjs-lib\" before using the SDK. ' +\n          \"See the ts-sdk README for setup instructions.\",\n      );\n    }\n    // Any other error means ECC is loaded (e.g. invalid key is fine — ECC worked).\n  }\n}\n\n/**\n * Map SDK network type to bitcoinjs-lib Network object.\n *\n * @param network - Network type (\"bitcoin\", \"testnet\", \"signet\", \"regtest\")\n * @returns bitcoinjs-lib Network object\n */\nexport function getNetwork(network: Network): networks.Network {\n  switch (network) {\n    case \"bitcoin\":\n      return networks.bitcoin;\n    case \"testnet\":\n    case \"signet\":\n      return networks.testnet;\n    case \"regtest\":\n      return networks.regtest;\n    default:\n      throw new Error(`Unknown network: ${network}`);\n  }\n}\n\n/**\n * Derive a Taproot (P2TR) address from a public key.\n *\n * @param publicKeyHex - Compressed (66 hex) or x-only (64 hex) public key\n * @param network - Bitcoin network\n * @returns Taproot address (bc1p... / tb1p... / bcrt1p...)\n */\nexport function deriveTaprootAddress(\n  publicKeyHex: string,\n  network: Network,\n): string {\n  assertEccInitialized();\n  const xOnly = hexToUint8Array(processPublicKeyToXOnly(publicKeyHex));\n  const { address } = payments.p2tr({\n    internalPubkey: Buffer.from(xOnly),\n    network: getNetwork(network),\n  });\n  if (!address) {\n    throw new Error(\"Failed to derive taproot address from public key\");\n  }\n  return address;\n}\n\n/**\n * Strip `0x` prefixes and lex-sort an array of x-only public keys.\n *\n * Used to produce the canonical (Rust-parity) keeper / challenger ordering\n * the protocol expects in payout and refund signing contexts.\n *\n * @param pubkeys - Array of x-only public keys (with or without `0x` prefix)\n * @returns Lex-sorted array of pubkeys with `0x` prefix stripped\n */\nexport function getSortedXOnlyPubkeys(pubkeys: string[]): string[] {\n  return pubkeys.map(stripHexPrefix).sort();\n}\n\n/**\n * Derive the BIP-86 P2TR scriptPubKey (`0x`-prefixed hex) from an x-only\n * public key.\n *\n * Matches Rust `Bip86KeyConnector::generate_taproot_script_pubkey`: a\n * keypath-only P2TR output with no script tree. Used to compute the expected\n * payout address for vault keeper claimers, whose payout goes to their own\n * BIP-86 address rather than the depositor's registered payout address.\n *\n * Network-agnostic: P2TR scriptPubKey bytes are `OP_1 <32-byte tweaked-key>`\n * regardless of network.\n *\n * @param xOnlyPubkeyHex - X-only public key (64 hex chars, with or without `0x` prefix)\n * @returns `0x`-prefixed P2TR scriptPubKey hex\n * @throws If `xOnlyPubkeyHex` is not exactly 64 hex chars after prefix stripping\n */\nexport function deriveBip86ScriptPubKeyHex(xOnlyPubkeyHex: string): string {\n  assertEccInitialized();\n  const cleanHex = stripHexPrefix(xOnlyPubkeyHex);\n  if (!/^[0-9a-fA-F]{64}$/.test(cleanHex)) {\n    throw new Error(\n      \"Invalid x-only pubkey: must be 64 hex characters (32 bytes, no 0x prefix)\",\n    );\n  }\n  const { output } = payments.p2tr({\n    internalPubkey: Buffer.from(cleanHex, \"hex\"),\n  });\n  if (!output) {\n    throw new Error(\"Failed to derive BIP-86 P2TR scriptPubKey\");\n  }\n  return `0x${output.toString(\"hex\")}`;\n}\n\n/**\n * Derive a Native SegWit (P2WPKH) address from a compressed public key.\n *\n * @param publicKeyHex - Compressed public key (66 hex chars, with or without 0x prefix)\n * @param network - Bitcoin network\n * @returns Native SegWit address (bc1q... / tb1q... / bcrt1q...)\n * @throws If publicKeyHex is not a compressed public key (66 hex chars)\n */\nexport function deriveNativeSegwitAddress(\n  publicKeyHex: string,\n  network: Network,\n): string {\n  const cleanHex = stripHexPrefix(publicKeyHex);\n  if (cleanHex.length !== 66) {\n    throw new Error(\n      `Native SegWit requires a compressed public key (66 hex chars), got ${cleanHex.length}`,\n    );\n  }\n  const { address } = payments.p2wpkh({\n    pubkey: Buffer.from(hexToUint8Array(cleanHex)),\n    network: getNetwork(network),\n  });\n  if (!address) {\n    throw new Error(\"Failed to derive native segwit address from public key\");\n  }\n  return address;\n}\n\n/**\n * Validate that a BTC address was derived from the given public key.\n *\n * Derives Taproot (P2TR) and Native SegWit (P2WPKH) addresses from the\n * public key and checks if the provided address matches any of them.\n *\n * P2WPKH derivation requires the full compressed key with explicit y-parity.\n * When only an x-only key is supplied, the y-parity is unknown and trying\n * both `02|x` and `03|x` would let an opposite-parity P2WPKH address — a\n * script the caller does NOT control — pass validation. We fail closed for\n * P2WPKH in that case; P2TR (which depends only on the x-coordinate) is\n * still validated and remains the supported path for Taproot wallets.\n *\n * @param address - BTC address to validate\n * @param publicKeyHex - Public key from the wallet (x-only 64 or compressed 66 hex chars)\n * @param network - Bitcoin network\n * @returns true if the address matches the public key\n */\nexport function isAddressFromPublicKey(\n  address: string,\n  publicKeyHex: string,\n  network: Network,\n): boolean {\n  const cleanHex = stripHexPrefix(publicKeyHex);\n\n  // P2TR — works with both x-only and compressed keys\n  try {\n    if (address === deriveTaprootAddress(cleanHex, network)) {\n      return true;\n    }\n  } catch {\n    // derivation failed, continue\n  }\n\n  // P2WPKH — only attempt when the caller supplied a parity-bearing\n  // compressed key. An x-only input is fail-closed here on purpose.\n  if (cleanHex.length === COMPRESSED_PUBKEY_HEX_LEN) {\n    try {\n      if (address === deriveNativeSegwitAddress(cleanHex, network)) {\n        return true;\n      }\n    } catch {\n      // derivation failed, continue\n    }\n  }\n\n  return false;\n}\n"],"names":["TAPSCRIPT_LEAF_VERSION","X_ONLY_PUBKEY_HEX_LEN","COMPRESSED_PUBKEY_HEX_LEN","UNCOMPRESSED_PUBKEY_HEX_LEN","SCHNORR_SIG_HEX_LEN","stripHexPrefix","hex","ensureHexPrefix","hexToUint8Array","cleanHex","isValidHexRaw","bytes","i","uint8ArrayToHex","b","inputTxidHex","input","toXOnly","pubKey","processPublicKeyToXOnly","publicKeyHex","pubkeyBytes","canonicalizeBtcPubkey","isValidHex","validateWalletPubkey","walletPubkeyRaw","expectedDepositorPubkey","walletPubkeyXOnly","depositorPubkey","SATOSHIS_PER_BTC","formatSatoshisToBtc","satoshis","whole","fractionStr","assertEccInitialized","payments","Buffer","getNetwork","network","networks","deriveTaprootAddress","xOnly","address","getSortedXOnlyPubkeys","pubkeys","deriveBip86ScriptPubKeyHex","xOnlyPubkeyHex","output","deriveNativeSegwitAddress","isAddressFromPublicKey"],"mappings":"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"}