{
  "version": 3,
  "sources": ["../src/index.ts", "../src/error/index.ts", "../src/utils/btc.ts", "../src/constants/keys.ts", "../src/utils/staking/index.ts", "../src/constants/internalPubkey.ts", "../src/constants/unbonding.ts", "../src/staking/psbt.ts", "../src/constants/transaction.ts", "../src/utils/utxo/findInputUTXO.ts", "../src/utils/utxo/getScriptType.ts", "../src/utils/utxo/getPsbtInputFields.ts", "../src/staking/stakingScript.ts", "../src/staking/transactions.ts", "../src/constants/dustSat.ts", "../src/utils/fee/index.ts", "../src/constants/fee.ts", "../src/utils/fee/utils.ts", "../src/constants/psbt.ts", "../src/staking/index.ts", "../src/staking/manager.ts", "../src/constants/registry.ts", "../src/utils/index.ts", "../src/utils/babylon.ts", "../src/utils/staking/param.ts", "../src/staking/observable/observableStakingScript.ts", "../src/staking/observable/index.ts", "../src/types/params.ts"],
  "sourcesContent": ["export { Staking, StakingScriptData } from \"./staking\";\nexport type { StakingScripts } from \"./staking\";\nexport * from \"./staking/manager\";\nexport {\n  ObservableStaking,\n  ObservableStakingScriptData,\n} from \"./staking/observable\";\nexport * from \"./staking/transactions\";\nexport * from \"./types\";\nexport * from \"./utils/btc\";\nexport {\n  getBabylonParamByBtcHeight,\n  getBabylonParamByVersion,\n} from \"./utils/staking/param\";\nexport * from \"./utils/utxo/findInputUTXO\";\nexport * from \"./utils/utxo/getPsbtInputFields\";\nexport * from \"./utils/utxo/getScriptType\";\n\n// BitGo-specific exports\nexport * from \"./utils/babylon\";\nexport * from \"./utils/staking\";\n", "export enum StakingErrorCode {\n  UNKNOWN_ERROR = \"UNKNOWN_ERROR\",\n  INVALID_INPUT = \"INVALID_INPUT\",\n  INVALID_OUTPUT = \"INVALID_OUTPUT\",\n  SCRIPT_FAILURE = \"SCRIPT_FAILURE\",\n  BUILD_TRANSACTION_FAILURE = \"BUILD_TRANSACTION_FAILURE\",\n  INVALID_PARAMS = \"INVALID_PARAMS\",\n}\n\nexport class StakingError extends Error {\n  public code: StakingErrorCode;\n  constructor(code: StakingErrorCode, message?: string) {\n    super(message);\n    this.code = code;\n  }\n\n  // Static method to safely handle unknown errors\n  static fromUnknown(\n    error: unknown, code: StakingErrorCode, fallbackMsg?: string\n  ): StakingError {\n    if (error instanceof StakingError) {\n      return error;\n    }\n\n    if (error instanceof Error) {\n      return new StakingError(code, error.message);\n    }\n    return new StakingError(code, fallbackMsg);\n  }\n}", "import * as ecc from \"@bitcoin-js/tiny-secp256k1-asmjs\";\nimport { address, initEccLib, networks } from \"bitcoinjs-lib\";\nimport { NO_COORD_PK_BYTE_LENGTH } from \"../constants/keys\";\n\n// Initialize elliptic curve library\nexport const initBTCCurve = () => {\n  initEccLib(ecc);\n};\n\n/**\n * Check whether the given address is a valid Bitcoin address.\n *\n * @param {string} btcAddress - The Bitcoin address to check.\n * @param {object} network - The Bitcoin network (e.g., bitcoin.networks.bitcoin).\n * @returns {boolean} - True if the address is valid, otherwise false.\n */\nexport const isValidBitcoinAddress = (\n  btcAddress: string,\n  network: networks.Network,\n): boolean => {\n  try {\n    return !!address.toOutputScript(btcAddress, network);\n  } catch (error) {\n    return false;\n  }\n};\n\n/**\n * Check whether the given address is a Taproot address.\n *\n * @param {string} taprootAddress - The Bitcoin bech32 encoded address to check.\n * @param {object} network - The Bitcoin network (e.g., bitcoin.networks.bitcoin).\n * @returns {boolean} - True if the address is a Taproot address, otherwise false.\n */\nexport const isTaproot = (\n  taprootAddress: string,\n  network: networks.Network,\n): boolean => {\n  try {\n    const decoded = address.fromBech32(taprootAddress);\n    if (decoded.version !== 1) {\n      return false;\n    }\n\n    // Compare network properties instead of object reference\n    // The bech32 is hardcoded in the bitcoinjs-lib library.\n    // https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/ts_src/networks.ts#L36\n    if (network.bech32 === networks.bitcoin.bech32) {\n      // Check if address starts with \"bc1p\"\n      return taprootAddress.startsWith(\"bc1p\");\n    } else if (network.bech32 === networks.testnet.bech32) {\n      // signet, regtest and testnet taproot addresses start with \"tb1p\" or \"sb1p\"\n      return (\n        taprootAddress.startsWith(\"tb1p\") || taprootAddress.startsWith(\"sb1p\")\n      );\n    }\n    return false;\n  } catch (error) {\n    return false;\n  }\n};\n\n/**\n * Check whether the given address is a Native SegWit address.\n *\n * @param {string} segwitAddress - The Bitcoin bech32 encoded address to check.\n * @param {object} network - The Bitcoin network (e.g., bitcoin.networks.bitcoin).\n * @returns {boolean} - True if the address is a Native SegWit address, otherwise false.\n */\nexport const isNativeSegwit = (\n  segwitAddress: string,\n  network: networks.Network,\n): boolean => {\n  try {\n    const decoded = address.fromBech32(segwitAddress);\n    if (decoded.version !== 0) {\n      return false;\n    }\n\n    // Compare network properties instead of object reference\n    // The bech32 is hardcoded in the bitcoinjs-lib library.\n    // https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/ts_src/networks.ts#L36\n    if (network.bech32 === networks.bitcoin.bech32) {\n      // Check if address starts with \"bc1q\"\n      return segwitAddress.startsWith(\"bc1q\");\n    } else if (network.bech32 === networks.testnet.bech32) {\n      // testnet native segwit addresses start with \"tb1q\"\n      return segwitAddress.startsWith(\"tb1q\");\n    }\n    return false;\n  } catch (error) {\n    return false;\n  }\n};\n\n/**\n * Check whether the given public key is a valid public key without a coordinate.\n *\n * @param {string} pkWithNoCoord - public key without the coordinate.\n * @returns {boolean} - True if the public key without the coordinate is valid, otherwise false.\n */\nexport const isValidNoCoordPublicKey = (pkWithNoCoord: string): boolean => {\n  try {\n    const keyBuffer = Buffer.from(pkWithNoCoord, \"hex\");\n    return validateNoCoordPublicKeyBuffer(keyBuffer);\n  } catch (error) {\n    return false;\n  }\n};\n\n/**\n * Get the public key without the coordinate.\n *\n * @param {string} pkHex - The public key in hex, with or without the coordinate.\n * @returns {string} - The public key without the coordinate in hex.\n * @throws {Error} - If the public key is invalid.\n */\nexport const getPublicKeyNoCoord = (pkHex: string): string => {\n  const publicKey = Buffer.from(pkHex, \"hex\");\n\n  const publicKeyNoCoordBuffer =\n    publicKey.length === NO_COORD_PK_BYTE_LENGTH\n      ? publicKey\n      : publicKey.subarray(1, 33);\n\n  // Validate the public key without coordinate\n  if (!validateNoCoordPublicKeyBuffer(publicKeyNoCoordBuffer)) {\n    throw new Error(\"Invalid public key without coordinate\");\n  }\n\n  return publicKeyNoCoordBuffer.toString(\"hex\");\n};\n\nconst validateNoCoordPublicKeyBuffer = (pkBuffer: Buffer): boolean => {\n  if (pkBuffer.length !== NO_COORD_PK_BYTE_LENGTH) {\n    return false;\n  }\n\n  // Try both compressed forms: y-coordinate even (0x02) and y-coordinate odd (0x03)\n  const compressedKeyEven = Buffer.concat([Buffer.from([0x02]), pkBuffer]);\n  const compressedKeyOdd = Buffer.concat([Buffer.from([0x03]), pkBuffer]);\n\n  return ecc.isPoint(compressedKeyEven) || ecc.isPoint(compressedKeyOdd);\n};\n\n/**\n * Convert a transaction id to a hash. in buffer format.\n *\n * @param {string} txId - The transaction id.\n * @returns {Buffer} - The transaction hash.\n */\nexport const transactionIdToHash = (txId: string): Buffer => {\n  if (txId === \"\") {\n    throw new Error(\"Transaction id cannot be empty\");\n  }\n  return Buffer.from(txId, \"hex\").reverse();\n};\n", "// NO_COORD_PK_BYTE_LENGTH is the length of a BTC public key without the coordinate in bytes.\nexport const NO_COORD_PK_BYTE_LENGTH = 32;", "import { address, networks, payments, Transaction } from \"bitcoinjs-lib\";\nimport { Taptree } from \"bitcoinjs-lib/src/types\";\nimport { internalPubkey } from \"../../constants/internalPubkey\";\nimport { MIN_UNBONDING_OUTPUT_VALUE } from \"../../constants/unbonding\";\nimport { StakingError, StakingErrorCode } from \"../../error\";\nimport { StakingParams } from \"../../types/params\";\nimport { TransactionOutput } from \"../../types/psbtOutputs\";\nimport { UTXO } from \"../../types/UTXO\";\nimport { isValidNoCoordPublicKey } from \"../btc\";\n\nexport interface OutputInfo {\n  scriptPubKey: Buffer;\n  outputAddress: string;\n}\n\n/**\n * Build the staking output for the transaction which contains p2tr output\n * with staking scripts.\n *\n * @param {StakingScripts} scripts - The staking scripts.\n * @param {networks.Network} network - The Bitcoin network.\n * @param {number} amount - The amount to stake.\n * @returns {TransactionOutput[]} - The staking transaction outputs.\n * @throws {Error} - If the staking output cannot be built.\n */\nexport const buildStakingTransactionOutputs = (\n  scripts: {\n    timelockScript: Buffer;\n    unbondingScript: Buffer;\n    slashingScript: Buffer;\n    dataEmbedScript?: Buffer;\n  },\n  network: networks.Network,\n  amount: number,\n): TransactionOutput[] => {\n  const stakingOutputInfo = deriveStakingOutputInfo(scripts, network);\n  const transactionOutputs: { scriptPubKey: Buffer; value: number }[] = [\n    {\n      scriptPubKey: stakingOutputInfo.scriptPubKey,\n      value: amount,\n    },\n  ];\n  if (scripts.dataEmbedScript) {\n    // Add the data embed output to the transaction\n    transactionOutputs.push({\n      scriptPubKey: scripts.dataEmbedScript,\n      value: 0,\n    });\n  }\n  return transactionOutputs;\n};\n\n/**\n * Derive the staking output address from the staking scripts.\n *\n * @param {StakingScripts} scripts - The staking scripts.\n * @param {networks.Network} network - The Bitcoin network.\n * @returns {StakingOutput} - The staking output address and scriptPubKey.\n * @throws {StakingError} - If the staking output address cannot be derived.\n */\nexport const deriveStakingOutputInfo = (\n  scripts: {\n    timelockScript: Buffer;\n    unbondingScript: Buffer;\n    slashingScript: Buffer;\n  },\n  network: networks.Network,\n) => {\n  // Build outputs\n  const scriptTree: Taptree = [\n    {\n      output: scripts.slashingScript,\n    },\n    [{ output: scripts.unbondingScript }, { output: scripts.timelockScript }],\n  ];\n\n  // Create an pay-2-taproot (p2tr) output using the staking script\n  const stakingOutput = payments.p2tr({\n    internalPubkey,\n    scriptTree,\n    network,\n  });\n\n  if (!stakingOutput.address) {\n    throw new StakingError(\n      StakingErrorCode.INVALID_OUTPUT,\n      \"Failed to build staking output\",\n    );\n  }\n\n  return {\n    outputAddress: stakingOutput.address,\n    scriptPubKey: address.toOutputScript(stakingOutput.address, network),\n  };\n};\n\n/**\n * Derive the unbonding output address and scriptPubKey from the staking scripts.\n *\n * @param {StakingScripts} scripts - The staking scripts.\n * @param {networks.Network} network - The Bitcoin network.\n * @returns {OutputInfo} - The unbonding output address and scriptPubKey.\n * @throws {StakingError} - If the unbonding output address cannot be derived.\n */\nexport const deriveUnbondingOutputInfo = (\n  scripts: {\n    unbondingTimelockScript: Buffer;\n    slashingScript: Buffer;\n  },\n  network: networks.Network,\n) => {\n  const outputScriptTree: Taptree = [\n    {\n      output: scripts.slashingScript,\n    },\n    { output: scripts.unbondingTimelockScript },\n  ];\n\n  const unbondingOutput = payments.p2tr({\n    internalPubkey,\n    scriptTree: outputScriptTree,\n    network,\n  });\n\n  if (!unbondingOutput.address) {\n    throw new StakingError(\n      StakingErrorCode.INVALID_OUTPUT,\n      \"Failed to build unbonding output\",\n    );\n  }\n\n  return {\n    outputAddress: unbondingOutput.address,\n    scriptPubKey: address.toOutputScript(unbondingOutput.address, network),\n  };\n};\n\n/**\n * Derive the slashing output address and scriptPubKey from the staking scripts.\n *\n * @param {StakingScripts} scripts - The unbonding timelock scripts, we use the\n * unbonding timelock script as the timelock of the slashing transaction.\n * This is due to slashing tx timelock is the same as the unbonding timelock.\n * @param {networks.Network} network - The Bitcoin network.\n * @returns {OutputInfo} - The slashing output address and scriptPubKey.\n * @throws {StakingError} - If the slashing output address cannot be derived.\n */\nexport const deriveSlashingOutput = (\n  scripts: {\n    unbondingTimelockScript: Buffer;\n  },\n  network: networks.Network,\n) => {\n  const slashingOutput = payments.p2tr({\n    internalPubkey,\n    scriptTree: { output: scripts.unbondingTimelockScript },\n    network,\n  });\n  const slashingOutputAddress = slashingOutput.address;\n\n  if (!slashingOutputAddress) {\n    throw new StakingError(\n      StakingErrorCode.INVALID_OUTPUT,\n      \"Failed to build slashing output address\",\n    );\n  }\n\n  return {\n    outputAddress: slashingOutputAddress,\n    scriptPubKey: address.toOutputScript(slashingOutputAddress, network),\n  };\n};\n\n/**\n * Find the matching output index for the given transaction.\n *\n * @param {Transaction} tx - The transaction.\n * @param {string} outputAddress - The output address.\n * @param {networks.Network} network - The Bitcoin network.\n * @returns {number} - The output index.\n * @throws {Error} - If the matching output is not found.\n */\nexport const findMatchingTxOutputIndex = (\n  tx: Transaction,\n  outputAddress: string,\n  network: networks.Network,\n) => {\n  const index = tx.outs.findIndex((output) => {\n    try {\n      return address.fromOutputScript(output.script, network) === outputAddress;\n    } catch (error) {\n      return false;\n    }\n  });\n\n  if (index === -1) {\n    throw new StakingError(\n      StakingErrorCode.INVALID_OUTPUT,\n      `Matching output not found for address: ${outputAddress}`,\n    );\n  }\n\n  return index;\n};\n\n/**\n * Validate the staking transaction input data.\n *\n * @param {number} stakingAmountSat - The staking amount in satoshis.\n * @param {number} timelock - The staking time in blocks.\n * @param {StakingParams} params - The staking parameters.\n * @param {UTXO[]} inputUTXOs - The input UTXOs.\n * @param {number} feeRate - The Bitcoin fee rate in sat/vbyte\n * @throws {StakingError} - If the input data is invalid.\n */\nexport const validateStakingTxInputData = (\n  stakingAmountSat: number,\n  timelock: number,\n  params: StakingParams,\n  inputUTXOs: UTXO[],\n  feeRate: number,\n) => {\n  if (\n    stakingAmountSat < params.minStakingAmountSat ||\n    stakingAmountSat > params.maxStakingAmountSat\n  ) {\n    throw new StakingError(\n      StakingErrorCode.INVALID_INPUT,\n      \"Invalid staking amount\",\n    );\n  }\n\n  if (\n    timelock < params.minStakingTimeBlocks ||\n    timelock > params.maxStakingTimeBlocks\n  ) {\n    throw new StakingError(StakingErrorCode.INVALID_INPUT, \"Invalid timelock\");\n  }\n\n  if (inputUTXOs.length == 0) {\n    throw new StakingError(\n      StakingErrorCode.INVALID_INPUT,\n      \"No input UTXOs provided\",\n    );\n  }\n  if (feeRate <= 0) {\n    throw new StakingError(StakingErrorCode.INVALID_INPUT, \"Invalid fee rate\");\n  }\n};\n\n/**\n * Validate the staking parameters.\n * Extend this method to add additional validation for staking parameters based\n * on the staking type.\n * @param {StakingParams} params - The staking parameters.\n * @throws {StakingError} - If the parameters are invalid.\n */\nexport const validateParams = (params: StakingParams) => {\n  // Check covenant public keys\n  if (params.covenantNoCoordPks.length == 0) {\n    throw new StakingError(\n      StakingErrorCode.INVALID_PARAMS,\n      \"Could not find any covenant public keys\",\n    );\n  }\n  if (params.covenantNoCoordPks.length < params.covenantQuorum) {\n    throw new StakingError(\n      StakingErrorCode.INVALID_PARAMS,\n      \"Covenant public keys must be greater than or equal to the quorum\",\n    );\n  }\n  params.covenantNoCoordPks.forEach((pk) => {\n    if (!isValidNoCoordPublicKey(pk)) {\n      throw new StakingError(\n        StakingErrorCode.INVALID_PARAMS,\n        \"Covenant public key should contains no coordinate\",\n      );\n    }\n  });\n  // Check other parameters\n  if (params.unbondingTime <= 0) {\n    throw new StakingError(\n      StakingErrorCode.INVALID_PARAMS,\n      \"Unbonding time must be greater than 0\",\n    );\n  }\n  if (params.unbondingFeeSat <= 0) {\n    throw new StakingError(\n      StakingErrorCode.INVALID_PARAMS,\n      \"Unbonding fee must be greater than 0\",\n    );\n  }\n  if (params.maxStakingAmountSat < params.minStakingAmountSat) {\n    throw new StakingError(\n      StakingErrorCode.INVALID_PARAMS,\n      \"Max staking amount must be greater or equal to min staking amount\",\n    );\n  }\n  if (\n    params.minStakingAmountSat <\n    params.unbondingFeeSat + MIN_UNBONDING_OUTPUT_VALUE\n  ) {\n    throw new StakingError(\n      StakingErrorCode.INVALID_PARAMS,\n      `Min staking amount must be greater than unbonding fee plus ${MIN_UNBONDING_OUTPUT_VALUE}`,\n    );\n  }\n  if (params.maxStakingTimeBlocks < params.minStakingTimeBlocks) {\n    throw new StakingError(\n      StakingErrorCode.INVALID_PARAMS,\n      \"Max staking time must be greater or equal to min staking time\",\n    );\n  }\n  if (params.minStakingTimeBlocks <= 0) {\n    throw new StakingError(\n      StakingErrorCode.INVALID_PARAMS,\n      \"Min staking time must be greater than 0\",\n    );\n  }\n  if (params.covenantQuorum <= 0) {\n    throw new StakingError(\n      StakingErrorCode.INVALID_PARAMS,\n      \"Covenant quorum must be greater than 0\",\n    );\n  }\n  if (params.slashing) {\n    if (params.slashing.slashingRate <= 0) {\n      throw new StakingError(\n        StakingErrorCode.INVALID_PARAMS,\n        \"Slashing rate must be greater than 0\",\n      );\n    }\n    if (params.slashing.slashingRate > 1) {\n      throw new StakingError(\n        StakingErrorCode.INVALID_PARAMS,\n        \"Slashing rate must be less or equal to 1\",\n      );\n    }\n    if (params.slashing.slashingPkScriptHex.length == 0) {\n      throw new StakingError(\n        StakingErrorCode.INVALID_PARAMS,\n        \"Slashing public key script is missing\",\n      );\n    }\n    if (params.slashing.minSlashingTxFeeSat <= 0) {\n      throw new StakingError(\n        StakingErrorCode.INVALID_PARAMS,\n        \"Minimum slashing transaction fee must be greater than 0\",\n      );\n    }\n  }\n};\n\n/**\n * Validate the staking timelock.\n *\n * @param {number} stakingTimelock - The staking timelock.\n * @param {StakingParams} params - The staking parameters.\n * @throws {StakingError} - If the staking timelock is invalid.\n */\nexport const validateStakingTimelock = (\n  stakingTimelock: number,\n  params: StakingParams,\n) => {\n  if (\n    stakingTimelock < params.minStakingTimeBlocks ||\n    stakingTimelock > params.maxStakingTimeBlocks\n  ) {\n    throw new StakingError(\n      StakingErrorCode.INVALID_INPUT,\n      \"Staking transaction timelock is out of range\",\n    );\n  }\n};\n\n/**\n * toBuffers converts an array of strings to an array of buffers.\n *\n * @param {string[]} inputs - The input strings.\n * @returns {Buffer[]} - The buffers.\n * @throws {StakingError} - If the values cannot be converted to buffers.\n */\nexport const toBuffers = (inputs: string[]): Buffer[] => {\n  try {\n    return inputs.map((i) => Buffer.from(i, \"hex\"));\n  } catch (error) {\n    throw StakingError.fromUnknown(\n      error,\n      StakingErrorCode.INVALID_INPUT,\n      \"Cannot convert values to buffers\",\n    );\n  }\n};\n", "// internalPubkey denotes an unspendable internal public key to be used for the taproot output\nconst key =\n  \"0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0\";\nexport const internalPubkey = Buffer.from(key, \"hex\").subarray(1, 33); // Do a subarray(1, 33) to get the public coordinate\n", "// minimum unbonding output value to avoid the unbonding output value being\n// less than Bitcoin dust\nexport const MIN_UNBONDING_OUTPUT_VALUE = 1000;", "import { Psbt, Transaction, networks, payments } from \"bitcoinjs-lib\";\nimport { Taptree } from \"bitcoinjs-lib/src/types\";\nimport { internalPubkey } from \"../constants/internalPubkey\";\nimport { NO_COORD_PK_BYTE_LENGTH } from \"../constants/keys\";\nimport { REDEEM_VERSION } from \"../constants/transaction\";\nimport { UTXO } from \"../types/UTXO\";\nimport { deriveUnbondingOutputInfo } from \"../utils/staking\";\nimport { findInputUTXO } from \"../utils/utxo/findInputUTXO\";\nimport { getPsbtInputFields } from \"../utils/utxo/getPsbtInputFields\";\n\n/**\n * Convert a staking transaction to a PSBT.\n *\n * @param {Transaction} stakingTx - The staking transaction to convert to PSBT.\n * @param {networks.Network} network - The network to use for the PSBT.\n * @param {UTXO[]} inputUTXOs - The UTXOs to be used as inputs for the staking\n * transaction.\n * @param {Buffer} [publicKeyNoCoord] - The public key of staker (optional)\n * @returns {Psbt} - The PSBT for the staking transaction.\n * @throws {Error} If unable to create PSBT from transaction\n */\nexport const stakingPsbt = (\n  stakingTx: Transaction,\n  network: networks.Network,\n  inputUTXOs: UTXO[],\n  publicKeyNoCoord?: Buffer,\n): Psbt => {\n  if (publicKeyNoCoord && publicKeyNoCoord.length !== NO_COORD_PK_BYTE_LENGTH) {\n    throw new Error(\"Invalid public key\");\n  }\n\n  const psbt = new Psbt({ network });\n\n  if (stakingTx.version !== undefined) psbt.setVersion(stakingTx.version);\n  if (stakingTx.locktime !== undefined) psbt.setLocktime(stakingTx.locktime);\n\n  stakingTx.ins.forEach((input) => {\n    const inputUTXO = findInputUTXO(inputUTXOs, input);\n    const psbtInputData = getPsbtInputFields(inputUTXO, publicKeyNoCoord);\n\n    psbt.addInput({\n      hash: input.hash,\n      index: input.index,\n      sequence: input.sequence,\n      ...psbtInputData,\n    });\n  });\n\n  stakingTx.outs.forEach((o) => {\n    psbt.addOutput({ script: o.script, value: o.value });\n  });\n\n  return psbt;\n};\n\nexport const unbondingPsbt = (\n  scripts: {\n    unbondingScript: Buffer;\n    timelockScript: Buffer;\n    slashingScript: Buffer;\n    unbondingTimelockScript: Buffer;\n  },\n  unbondingTx: Transaction,\n  stakingTx: Transaction,\n  network: networks.Network,\n): Psbt => {\n  if (unbondingTx.outs.length !== 1) {\n    throw new Error(\"Unbonding transaction must have exactly one output\");\n  }\n  if (unbondingTx.ins.length !== 1) {\n    throw new Error(\"Unbonding transaction must have exactly one input\");\n  }\n\n  validateUnbondingOutput(scripts, unbondingTx, network);\n\n  const psbt = new Psbt({ network });\n\n  if (unbondingTx.version !== undefined) {\n    psbt.setVersion(unbondingTx.version);\n  }\n  if (unbondingTx.locktime !== undefined) {\n    psbt.setLocktime(unbondingTx.locktime);\n  }\n\n  const input = unbondingTx.ins[0];\n  const outputIndex = input.index;\n\n  // Build input tapleaf script\n  const inputScriptTree: Taptree = [\n    { output: scripts.slashingScript },\n    [{ output: scripts.unbondingScript }, { output: scripts.timelockScript }],\n  ];\n\n  // This is the tapleaf we are actually spending\n  const inputRedeem = {\n    output: scripts.unbondingScript,\n    redeemVersion: REDEEM_VERSION,\n  };\n\n  // Create a P2TR payment that includes scriptTree + redeem\n  const p2tr = payments.p2tr({\n    internalPubkey,\n    scriptTree: inputScriptTree,\n    redeem: inputRedeem,\n    network,\n  });\n\n  const inputTapLeafScript = {\n    leafVersion: inputRedeem.redeemVersion,\n    script: inputRedeem.output,\n    controlBlock: p2tr.witness![p2tr.witness!.length - 1],\n  };\n\n  psbt.addInput({\n    hash: input.hash,\n    index: input.index,\n    sequence: input.sequence,\n    tapInternalKey: internalPubkey,\n    witnessUtxo: {\n      value: stakingTx.outs[outputIndex].value,\n      script: stakingTx.outs[outputIndex].script,\n    },\n    tapLeafScript: [inputTapLeafScript],\n  });\n\n  psbt.addOutput({\n    script: unbondingTx.outs[0].script,\n    value: unbondingTx.outs[0].value,\n  });\n\n  return psbt;\n};\n\n/**\n * Validate the unbonding output for a given unbonding transaction.\n *\n * @param {Object} scripts - The scripts to use for the unbonding output.\n * @param {Transaction} unbondingTx - The unbonding transaction.\n * @param {networks.Network} network - The network to use for the unbonding output.\n */\nconst validateUnbondingOutput = (\n  scripts: {\n    slashingScript: Buffer;\n    unbondingTimelockScript: Buffer;\n  },\n  unbondingTx: Transaction,\n  network: networks.Network,\n) => {\n  const unbondingOutputInfo = deriveUnbondingOutputInfo(scripts, network);\n  if (\n    unbondingOutputInfo.scriptPubKey.toString(\"hex\") !==\n    unbondingTx.outs[0].script.toString(\"hex\")\n  ) {\n    throw new Error(\n      \"Unbonding output script does not match the expected\" +\n        \" script while building psbt\",\n    );\n  }\n};\n", "export const REDEEM_VERSION = 192;", "import { Input } from \"bitcoinjs-lib/src/transaction\";\n\nimport { UTXO } from \"../../types/UTXO\";\nimport { transactionIdToHash } from \"../btc\";\n\nexport const findInputUTXO = (inputUTXOs: UTXO[], input: Input): UTXO => {\n  const inputUTXO = inputUTXOs.find(\n    (u) =>\n      transactionIdToHash(u.txid).toString(\"hex\") ===\n        input.hash.toString(\"hex\") && u.vout === input.index,\n  );\n  if (!inputUTXO) {\n    throw new Error(\n      `Input UTXO not found for txid: ${Buffer.from(input.hash).reverse().toString(\"hex\")} ` +\n        `and vout: ${input.index}`,\n    );\n  }\n  return inputUTXO;\n};\n", "import { payments } from \"bitcoinjs-lib\";\n\n/**\n * Supported Bitcoin script types\n */\nexport enum BitcoinScriptType {\n  // Pay to Public Key Hash\n  P2PKH = \"pubkeyhash\",\n  // Pay to Script Hash\n  P2SH = \"scripthash\",\n  // Pay to Witness Public Key Hash\n  P2WPKH = \"witnesspubkeyhash\",\n  // Pay to Witness Script Hash\n  P2WSH = \"witnessscripthash\",\n  // Pay to Taproot\n  P2TR = \"taproot\",\n}\n\n/**\n * Determines the type of Bitcoin script.\n *\n * This function tries to parse the script using different Bitcoin payment types and returns\n * a string identifier for the script type.\n *\n * @param script - The raw script as a Buffer\n * @returns {BitcoinScriptType} The identified script type\n * @throws {Error} If the script cannot be identified as any known type\n */\n\nexport const getScriptType = (script: Buffer): BitcoinScriptType => {\n  try {\n    payments.p2pkh({ output: script });\n    return BitcoinScriptType.P2PKH;\n  } catch {}\n  try {\n    payments.p2sh({ output: script });\n    return BitcoinScriptType.P2SH;\n  } catch {}\n  try {\n    payments.p2wpkh({ output: script });\n    return BitcoinScriptType.P2WPKH;\n  } catch {}\n  try {\n    payments.p2wsh({ output: script });\n    return BitcoinScriptType.P2WSH;\n  } catch {}\n  try {\n    payments.p2tr({ output: script });\n    return BitcoinScriptType.P2TR;\n  } catch {}\n\n  throw new Error(\"Unknown script type\");\n};\n", "import { PsbtInputExtended } from \"bip174/src/lib/interfaces\";\n\nimport { UTXO } from \"../../types\";\nimport { BitcoinScriptType, getScriptType } from \"./getScriptType\";\n\n/**\n * Determines and constructs the correct PSBT input fields for a given UTXO based on its script type.\n * This function handles different Bitcoin script types (P2PKH, P2SH, P2WPKH, P2WSH, P2TR) and returns\n * the appropriate PSBT input fields required for that UTXO.\n *\n * @param {UTXO} utxo - The unspent transaction output to process\n * @param {Buffer} [publicKeyNoCoord] - The public of the staker (optional).\n * @returns {object} PSBT input fields object containing the necessary data\n * @throws {Error} If required input data is missing or if an unsupported script type is provided\n */\n\nexport const getPsbtInputFields = (\n  utxo: UTXO,\n  publicKeyNoCoord?: Buffer,\n): PsbtInputExtended => {\n  const scriptPubKey = Buffer.from(utxo.scriptPubKey, \"hex\");\n  const type = getScriptType(scriptPubKey);\n\n  switch (type) {\n    case BitcoinScriptType.P2PKH: {\n      if (!utxo.rawTxHex) {\n        throw new Error(\"Missing rawTxHex for legacy P2PKH input\");\n      }\n      return { nonWitnessUtxo: Buffer.from(utxo.rawTxHex, \"hex\") };\n    }\n    case BitcoinScriptType.P2SH: {\n      if (!utxo.rawTxHex) {\n        throw new Error(\"Missing rawTxHex for P2SH input\");\n      }\n      if (!utxo.redeemScript) {\n        throw new Error(\"Missing redeemScript for P2SH input\");\n      }\n      return {\n        nonWitnessUtxo: Buffer.from(utxo.rawTxHex, \"hex\"),\n        redeemScript: Buffer.from(utxo.redeemScript, \"hex\"),\n      };\n    }\n    case BitcoinScriptType.P2WPKH: {\n      return {\n        witnessUtxo: {\n          script: scriptPubKey,\n          value: utxo.value,\n        },\n      };\n    }\n    case BitcoinScriptType.P2WSH: {\n      if (!utxo.witnessScript) {\n        throw new Error(\"Missing witnessScript for P2WSH input\");\n      }\n      return {\n        witnessUtxo: {\n          script: scriptPubKey,\n          value: utxo.value,\n        },\n        witnessScript: Buffer.from(utxo.witnessScript, \"hex\"),\n      };\n    }\n    case BitcoinScriptType.P2TR: {\n      return {\n        witnessUtxo: {\n          script: scriptPubKey,\n          value: utxo.value,\n        },\n        // this is needed only if the wallet is in taproot mode\n        ...(publicKeyNoCoord && { tapInternalKey: publicKeyNoCoord }),\n      };\n    }\n    default:\n      throw new Error(`Unsupported script type: ${type}`);\n  }\n};\n", "import { opcodes, script } from \"bitcoinjs-lib\";\nimport { NO_COORD_PK_BYTE_LENGTH } from \"../constants/keys\";\n\nexport const MAGIC_BYTES_LEN = 4;\n\n// Represents the staking scripts used in BTC staking.\nexport interface StakingScripts {\n  timelockScript: Buffer;\n  unbondingScript: Buffer;\n  slashingScript: Buffer;\n  unbondingTimelockScript: Buffer;\n}\n\n// StakingScriptData is a class that holds the data required for the BTC Staking Script\n// and exposes methods for converting it into useful formats\nexport class StakingScriptData {\n  stakerKey: Buffer;\n  finalityProviderKeys: Buffer[];\n  covenantKeys: Buffer[];\n  covenantThreshold: number;\n  stakingTimeLock: number;\n  unbondingTimeLock: number;\n\n  constructor(\n    // The `stakerKey` is the public key of the staker without the coordinate bytes.\n    stakerKey: Buffer,\n    // A list of public keys without the coordinate bytes corresponding to the finality providers\n    // the stake will be delegated to.\n    // Currently, Babylon does not support restaking, so this should contain only a single item.\n    finalityProviderKeys: Buffer[],\n    // A list of the public keys without the coordinate bytes corresponding to\n    // the covenant emulators.\n    // This is a parameter of the Babylon system and should be retrieved from there.\n    covenantKeys: Buffer[],\n    // The number of covenant emulator signatures required for a transaction\n    // to be valid.\n    // This is a parameter of the Babylon system and should be retrieved from there.\n    covenantThreshold: number,\n    // The staking period denoted as a number of BTC blocks.\n    stakingTimelock: number,\n    // The unbonding period denoted as a number of BTC blocks.\n    // This value should be more than equal than the minimum unbonding time of the\n    // Babylon system.\n    unbondingTimelock: number,\n  ) {\n    if (\n      !stakerKey ||\n      !finalityProviderKeys ||\n      !covenantKeys ||\n      !covenantThreshold ||\n      !stakingTimelock ||\n      !unbondingTimelock\n    ) {\n      throw new Error(\"Missing required input values\");\n    }\n    this.stakerKey = stakerKey;\n    this.finalityProviderKeys = finalityProviderKeys;\n    this.covenantKeys = covenantKeys;\n    this.covenantThreshold = covenantThreshold;\n    this.stakingTimeLock = stakingTimelock;\n    this.unbondingTimeLock = unbondingTimelock;\n\n    // Run the validate method to check if the provided script data is valid\n    if (!this.validate()) {\n      throw new Error(\"Invalid script data provided\");\n    }\n  }\n\n  /**\n   * Validates the staking script.\n   * @returns {boolean} Returns true if the staking script is valid, otherwise false.\n   */\n  validate(): boolean {\n    // check that staker key is the correct length\n    if (this.stakerKey.length != NO_COORD_PK_BYTE_LENGTH) {\n      return false;\n    }\n    // check that finalityProvider keys are the correct length\n    if (\n      this.finalityProviderKeys.some(\n        (finalityProviderKey) => finalityProviderKey.length != NO_COORD_PK_BYTE_LENGTH,\n      )\n    ) {\n      return false;\n    }\n    // check that covenant keys are the correct length\n    if (\n      this.covenantKeys.some((covenantKey) => covenantKey.length != NO_COORD_PK_BYTE_LENGTH)\n    ) {\n      return false;\n    }\n\n    // Check whether we have any duplicate keys\n    const allPks = [\n      this.stakerKey,\n      ...this.finalityProviderKeys,\n      ...this.covenantKeys,\n    ];\n    const allPksSet = new Set(allPks);\n    if (allPks.length !== allPksSet.size) {\n      return false;\n    }\n\n    // check that the threshold is above 0 and less than or equal to\n    // the size of the covenant emulators set\n    if (\n      this.covenantThreshold <= 0 ||\n      this.covenantThreshold > this.covenantKeys.length\n    ) {\n      return false;\n    }\n\n    // check that maximum value for staking time is not greater than uint16 and above 0\n    if (this.stakingTimeLock <= 0 || this.stakingTimeLock > 65535) {\n      return false;\n    }\n\n    // check that maximum value for unbonding time is not greater than uint16 and above 0\n    if (this.unbondingTimeLock <= 0 || this.unbondingTimeLock > 65535) {\n      return false;\n    }\n\n    return true;\n  }\n\n  // The staking script allows for multiple finality provider public keys\n  // to support (re)stake to multiple finality providers\n  // Covenant members are going to have multiple keys\n\n  /**\n   * Builds a timelock script.\n   * @param timelock - The timelock value to encode in the script.\n   * @returns {Buffer} containing the compiled timelock script.\n   */\n  buildTimelockScript(timelock: number): Buffer {\n    return script.compile([\n      this.stakerKey,\n      opcodes.OP_CHECKSIGVERIFY,\n      script.number.encode(timelock),\n      opcodes.OP_CHECKSEQUENCEVERIFY,\n    ]);\n  }\n\n  /**\n   * Builds the staking timelock script.\n   * Only holder of private key for given pubKey can spend after relative lock time\n   * Creates the timelock script in the form:\n   *    <stakerPubKey>\n   *    OP_CHECKSIGVERIFY\n   *    <stakingTimeBlocks>\n   *    OP_CHECKSEQUENCEVERIFY\n   * @returns {Buffer} The staking timelock script.\n   */\n  buildStakingTimelockScript(): Buffer {\n    return this.buildTimelockScript(this.stakingTimeLock);\n  }\n\n  /**\n   * Builds the unbonding timelock script.\n   * Creates the unbonding timelock script in the form:\n   *    <stakerPubKey>\n   *    OP_CHECKSIGVERIFY\n   *    <unbondingTimeBlocks>\n   *    OP_CHECKSEQUENCEVERIFY\n   * @returns {Buffer} The unbonding timelock script.\n   */\n  buildUnbondingTimelockScript(): Buffer {\n    return this.buildTimelockScript(this.unbondingTimeLock);\n  }\n\n  /**\n   * Builds the unbonding script in the form:\n   *    buildSingleKeyScript(stakerPk, true) ||\n   *    buildMultiKeyScript(covenantPks, covenantThreshold, false)\n   *    || means combining the scripts\n   * @returns {Buffer} The unbonding script.\n   */\n  buildUnbondingScript(): Buffer {\n    return Buffer.concat([\n      this.buildSingleKeyScript(this.stakerKey, true),\n      this.buildMultiKeyScript(\n        this.covenantKeys,\n        this.covenantThreshold,\n        false,\n      ),\n    ]);\n  }\n\n  /**\n   * Builds the slashing script for staking in the form:\n   *    buildSingleKeyScript(stakerPk, true) ||\n   *    buildMultiKeyScript(finalityProviderPKs, 1, true) ||\n   *    buildMultiKeyScript(covenantPks, covenantThreshold, false)\n   *    || means combining the scripts\n   * The slashing script is a combination of single-key and multi-key scripts.\n   * The single-key script is used for staker key verification.\n   * The multi-key script is used for finality provider key verification and covenant key verification.\n   * @returns {Buffer} The slashing script as a Buffer.\n   */\n  buildSlashingScript(): Buffer {\n    return Buffer.concat([\n      this.buildSingleKeyScript(this.stakerKey, true),\n      this.buildMultiKeyScript(\n        this.finalityProviderKeys,\n        // The threshold is always 1 as we only need one\n        // finalityProvider signature to perform slashing\n        // (only one finalityProvider performs an offence)\n        1,\n        // OP_VERIFY/OP_CHECKSIGVERIFY is added at the end\n        true,\n      ),\n      this.buildMultiKeyScript(\n        this.covenantKeys,\n        this.covenantThreshold,\n        // No need to add verify since covenants are at the end of the script\n        false,\n      ),\n    ]);\n  }\n  /**\n   * Builds the staking scripts.\n   * @returns {StakingScripts} The staking scripts.\n   */\n  buildScripts(): StakingScripts {\n    return {\n      timelockScript: this.buildStakingTimelockScript(),\n      unbondingScript: this.buildUnbondingScript(),\n      slashingScript: this.buildSlashingScript(),\n      unbondingTimelockScript: this.buildUnbondingTimelockScript(),\n    };\n  }\n\n  // buildSingleKeyScript and buildMultiKeyScript allow us to reuse functionality\n  // for creating Bitcoin scripts for the unbonding script and the slashing script\n\n  /**\n   * Builds a single key script in the form:\n   * buildSingleKeyScript creates a single key script\n   *    <pk> OP_CHECKSIGVERIFY (if withVerify is true)\n   *    <pk> OP_CHECKSIG (if withVerify is false)\n   * @param pk - The public key buffer.\n   * @param withVerify - A boolean indicating whether to include the OP_CHECKSIGVERIFY opcode.\n   * @returns The compiled script buffer.\n   */\n  buildSingleKeyScript(pk: Buffer, withVerify: boolean): Buffer {\n    // Check public key length\n    if (pk.length != NO_COORD_PK_BYTE_LENGTH) {\n      throw new Error(\"Invalid key length\");\n    }\n    return script.compile([\n      pk,\n      withVerify ? opcodes.OP_CHECKSIGVERIFY : opcodes.OP_CHECKSIG,\n    ]);\n  }\n\n  /**\n   * Builds a multi-key script in the form:\n   *    <pk1> OP_CHEKCSIG <pk2> OP_CHECKSIGADD <pk3> OP_CHECKSIGADD ... <pkN> OP_CHECKSIGADD <threshold> OP_NUMEQUAL\n   *    <withVerify -> OP_NUMEQUALVERIFY>\n   * It validates whether provided keys are unique and the threshold is not greater than number of keys\n   * If there is only one key provided it will return single key sig script\n   * @param pks - An array of public keys.\n   * @param threshold - The required number of valid signers.\n   * @param withVerify - A boolean indicating whether to include the OP_VERIFY opcode.\n   * @returns The compiled multi-key script as a Buffer.\n   * @throws {Error} If no keys are provided, if the required number of valid signers is greater than the number of provided keys, or if duplicate keys are provided.\n   */\n  buildMultiKeyScript(\n    pks: Buffer[],\n    threshold: number,\n    withVerify: boolean,\n  ): Buffer {\n    // Verify that pks is not empty\n    if (!pks || pks.length === 0) {\n      throw new Error(\"No keys provided\");\n    }\n    // Check buffer object have expected lengths like checking pks.length\n    if (pks.some((pk) => pk.length != NO_COORD_PK_BYTE_LENGTH)) {\n      throw new Error(\"Invalid key length\");\n    }\n    // Verify that threshold <= len(pks)\n    if (threshold > pks.length) {\n      throw new Error(\n        \"Required number of valid signers is greater than number of provided keys\",\n      );\n    }\n    if (pks.length === 1) {\n      return this.buildSingleKeyScript(pks[0], withVerify);\n    }\n    // keys must be sorted\n    const sortedPks = [...pks].sort(Buffer.compare);\n    // verify there are no duplicates\n    for (let i = 0; i < sortedPks.length - 1; ++i) {\n      if (sortedPks[i].equals(sortedPks[i + 1])) {\n        throw new Error(\"Duplicate keys provided\");\n      }\n    }\n    const scriptElements = [sortedPks[0], opcodes.OP_CHECKSIG];\n    for (let i = 1; i < sortedPks.length; i++) {\n      scriptElements.push(sortedPks[i]);\n      scriptElements.push(opcodes.OP_CHECKSIGADD);\n    }\n    scriptElements.push(script.number.encode(threshold));\n    if (withVerify) {\n      scriptElements.push(opcodes.OP_NUMEQUALVERIFY);\n    } else {\n      scriptElements.push(opcodes.OP_NUMEQUAL);\n    }\n    return script.compile(scriptElements);\n  }\n}\n", "import { Psbt, Transaction, networks, payments, script, address, opcodes } from \"bitcoinjs-lib\";\nimport { Taptree } from \"bitcoinjs-lib/src/types\";\n\nimport { BTC_DUST_SAT } from \"../constants/dustSat\";\nimport { internalPubkey } from \"../constants/internalPubkey\";\nimport { UTXO } from \"../types/UTXO\";\nimport { PsbtResult, TransactionResult } from \"../types/transaction\";\nimport { isValidBitcoinAddress, transactionIdToHash } from \"../utils/btc\";\nimport { getStakingTxInputUTXOsAndFees, getWithdrawTxFee } from \"../utils/fee\";\nimport { inputValueSum } from \"../utils/fee/utils\";\nimport { buildStakingTransactionOutputs, deriveUnbondingOutputInfo } from \"../utils/staking\";\nimport { NON_RBF_SEQUENCE, TRANSACTION_VERSION } from \"../constants/psbt\";\nimport { CovenantSignature } from \"../types/covenantSignatures\";\nimport { REDEEM_VERSION } from \"../constants/transaction\";\n\n// https://bips.xyz/370\nconst BTC_LOCKTIME_HEIGHT_TIME_CUTOFF = 500000000;\nconst BTC_SLASHING_FRACTION_DIGITS = 4;\n\n/**\n * Constructs an unsigned BTC Staking transaction in psbt format.\n *\n * Outputs:\n * - psbt:\n *   - The first output corresponds to the staking script with the specified amount.\n *   - The second output corresponds to the change from spending the amount and the transaction fee.\n *   - If a data embed script is provided, it will be added as the second output, and the fee will be the third output.\n * - fee: The total fee amount for the transaction.\n *\n * Inputs:\n * - scripts:\n *   - timelockScript, unbondingScript, slashingScript: Scripts for different transaction types.\n *   - dataEmbedScript: Optional data embed script.\n * - amount: Amount to stake.\n * - changeAddress: Address to send the change to.\n * - inputUTXOs: All available UTXOs from the wallet.\n * - network: Bitcoin network.\n * - feeRate: Fee rate in satoshis per byte.\n * - publicKeyNoCoord: Public key if the wallet is in taproot mode.\n * - lockHeight: Optional block height locktime to set for the transaction (i.e., not mined until the block height).\n *\n * @param {Object} scripts - Scripts used to construct the taproot output.\n * such as timelockScript, unbondingScript, slashingScript, and dataEmbedScript.\n * @param {number} amount - The amount to stake.\n * @param {string} changeAddress - The address to send the change to.\n * @param {UTXO[]} inputUTXOs - All available UTXOs from the wallet.\n * @param {networks.Network} network - The Bitcoin network.\n * @param {number} feeRate - The fee rate in satoshis per byte.\n * @param {number} [lockHeight] - The optional block height locktime.\n * @returns {TransactionResult} - An object containing the unsigned transaction and fee\n * @throws Will throw an error if the amount or fee rate is less than or equal\n * to 0, if the change address is invalid, or if the public key is invalid.\n */\nexport function stakingTransaction(\n  scripts: {\n    timelockScript: Buffer;\n    unbondingScript: Buffer;\n    slashingScript: Buffer;\n    dataEmbedScript?: Buffer;\n  },\n  amount: number,\n  changeAddress: string,\n  inputUTXOs: UTXO[],\n  network: networks.Network,\n  feeRate: number,\n  lockHeight?: number,\n): TransactionResult {\n  // Check that amount and fee are bigger than 0\n  if (amount <= 0 || feeRate <= 0) {\n    throw new Error(\"Amount and fee rate must be bigger than 0\");\n  }\n\n  // Check whether the change address is a valid Bitcoin address.\n  if (!isValidBitcoinAddress(changeAddress, network)) {\n    throw new Error(\"Invalid change address\");\n  }\n\n  // Build outputs and estimate the fee\n  const stakingOutputs = buildStakingTransactionOutputs(scripts, network, amount);\n  const { selectedUTXOs, fee } = getStakingTxInputUTXOsAndFees(\n    inputUTXOs,\n    amount,\n    feeRate,\n    stakingOutputs,\n  );\n\n  const tx = new Transaction();\n  tx.version = TRANSACTION_VERSION;\n  \n  for (let i = 0; i < selectedUTXOs.length; ++i) {\n    const input = selectedUTXOs[i];\n    tx.addInput(\n      transactionIdToHash(input.txid),\n      input.vout,\n      NON_RBF_SEQUENCE,\n    );\n  }\n\n  stakingOutputs.forEach((o) => {\n    tx.addOutput(o.scriptPubKey, o.value);\n  });\n\n  // Add a change output only if there's any amount leftover from the inputs\n  const inputsSum = inputValueSum(selectedUTXOs);\n  // Check if the change amount is above the dust limit, and if so, add it as a change output\n  if (inputsSum - (amount + fee) > BTC_DUST_SAT) {\n    tx.addOutput(\n      address.toOutputScript(changeAddress, network),\n      inputsSum - (amount + fee),\n    );\n  }\n\n  // Set the locktime field if provided. If not provided, the locktime will be set to 0 by default\n  // Only height based locktime is supported\n  if (lockHeight) {\n    if (lockHeight >= BTC_LOCKTIME_HEIGHT_TIME_CUTOFF) {\n      throw new Error(\"Invalid lock height\");\n    }\n    tx.locktime = lockHeight;\n  }\n\n  return {\n    transaction: tx,\n    fee,\n  };\n}\n\n/**\n * Constructs a withdrawal transaction for manually unbonded delegation.\n *\n * This transaction spends the unbonded output from the staking transaction.\n *\n * Inputs:\n * - scripts: Scripts used to construct the taproot output.\n *   - unbondingTimelockScript: Script for the unbonding timelock condition.\n *   - slashingScript: Script for the slashing condition.\n * - unbondingTx: The unbonding transaction.\n * - withdrawalAddress: The address to send the withdrawn funds to.\n * - network: The Bitcoin network.\n * - feeRate: The fee rate for the transaction in satoshis per byte.\n *\n * Returns:\n * - psbt: The partially signed transaction (PSBT).\n *\n * @param {Object} scripts - The scripts used in the transaction.\n * @param {Transaction} unbondingTx - The unbonding transaction.\n * @param {string} withdrawalAddress - The address to send the withdrawn funds to.\n * @param {networks.Network} network - The Bitcoin network.\n * @param {number} feeRate - The fee rate for the transaction in satoshis per byte.\n * @returns {PsbtResult} An object containing the partially signed transaction (PSBT).\n */\nexport function withdrawEarlyUnbondedTransaction(\n  scripts: {\n    unbondingTimelockScript: Buffer;\n    slashingScript: Buffer;\n  },\n  unbondingTx: Transaction,\n  withdrawalAddress: string,\n  network: networks.Network,\n  feeRate: number,\n): PsbtResult {\n  const scriptTree: Taptree = [\n    {\n      output: scripts.slashingScript,\n    },\n    { output: scripts.unbondingTimelockScript },\n  ];\n\n  return withdrawalTransaction(\n    {\n      timelockScript: scripts.unbondingTimelockScript,\n    },\n    scriptTree,\n    unbondingTx,\n    withdrawalAddress,\n    network,\n    feeRate,\n    0, // unbonding always has a single output\n  );\n}\n\n/**\n * Constructs a withdrawal transaction for naturally unbonded delegation.\n *\n * This transaction spends the unbonded output from the staking transaction when the timelock has expired.\n *\n * Inputs:\n * - scripts: Scripts used to construct the taproot output.\n *   - timelockScript: Script for the timelock condition.\n *   - slashingScript: Script for the slashing condition.\n *   - unbondingScript: Script for the unbonding condition.\n * - tx: The original staking transaction.\n * - withdrawalAddress: The address to send the withdrawn funds to.\n * - network: The Bitcoin network.\n * - feeRate: The fee rate for the transaction in satoshis per byte.\n * - outputIndex: The index of the output to be spent in the original transaction (default is 0).\n *\n * Returns:\n * - psbt: The partially signed transaction (PSBT).\n *\n * @param {Object} scripts - The scripts used in the transaction.\n * @param {Transaction} tx - The original staking transaction.\n * @param {string} withdrawalAddress - The address to send the withdrawn funds to.\n * @param {networks.Network} network - The Bitcoin network.\n * @param {number} feeRate - The fee rate for the transaction in satoshis per byte.\n * @param {number} [outputIndex=0] - The index of the output to be spent in the original transaction.\n * @returns {PsbtResult} An object containing the partially signed transaction (PSBT).\n */\nexport function withdrawTimelockUnbondedTransaction(\n  scripts: {\n    timelockScript: Buffer;\n    slashingScript: Buffer;\n    unbondingScript: Buffer;\n  },\n  tx: Transaction,\n  withdrawalAddress: string,\n  network: networks.Network,\n  feeRate: number,\n  outputIndex: number = 0,\n): PsbtResult {\n  const scriptTree: Taptree = [\n    {\n      output: scripts.slashingScript,\n    },\n    [{ output: scripts.unbondingScript }, { output: scripts.timelockScript }],\n  ];\n\n  return withdrawalTransaction(\n    scripts,\n    scriptTree,\n    tx,\n    withdrawalAddress,\n    network,\n    feeRate,\n    outputIndex,\n  );\n}\n\n/**\n * Constructs a withdrawal transaction for a slashing transaction.\n *\n * This transaction spends the output from the slashing transaction.\n *\n * @param {Object} scripts - The unbondingTimelockScript\n * We use the unbonding timelock script as the timelock of the slashing transaction.\n * This is due to slashing tx timelock is the same as the unbonding timelock.\n * @param {Transaction} slashingTx - The slashing transaction.\n * @param {string} withdrawalAddress - The address to send the withdrawn funds to.\n * @param {networks.Network} network - The Bitcoin network.\n * @param {number} feeRate - The fee rate for the transaction in satoshis per byte.\n * @param {number} outputIndex - The index of the output to be spent in the original transaction.\n * @returns {PsbtResult} An object containing the partially signed transaction (PSBT).\n */\nexport function withdrawSlashingTransaction(\n  scripts: {\n    unbondingTimelockScript: Buffer;\n  },\n  slashingTx: Transaction,\n  withdrawalAddress: string,\n  network: networks.Network,\n  feeRate: number,\n  outputIndex: number,\n): PsbtResult {\n  const scriptTree: Taptree = { output: scripts.unbondingTimelockScript };\n\n  return withdrawalTransaction(\n    {\n      timelockScript: scripts.unbondingTimelockScript,\n    },\n    scriptTree,\n    slashingTx,\n    withdrawalAddress,\n    network,\n    feeRate,\n    outputIndex,\n  );\n}\n\n// withdrawalTransaction generates a transaction that\n// spends the staking output of the staking transaction\nfunction withdrawalTransaction(\n  scripts: {\n    timelockScript: Buffer;\n  },\n  scriptTree: Taptree,\n  tx: Transaction,\n  withdrawalAddress: string,\n  network: networks.Network,\n  feeRate: number,\n  outputIndex: number = 0,\n): PsbtResult {\n  // Check that withdrawal feeRate is bigger than 0\n  if (feeRate <= 0) {\n    throw new Error(\"Withdrawal feeRate must be bigger than 0\");\n  }\n\n  // Check that outputIndex is bigger or equal to 0\n  if (outputIndex < 0) {\n    throw new Error(\"Output index must be bigger or equal to 0\");\n  }\n\n  // position of time in the timelock script\n  const timePosition = 2;\n  const decompiled = script.decompile(scripts.timelockScript);\n\n  if (!decompiled) {\n    throw new Error(\"Timelock script is not valid\");\n  }\n\n  let timelock = 0;\n\n  // if the timelock is a buffer, it means it's a number bigger than 16 blocks\n  if (typeof decompiled[timePosition] !== \"number\") {\n    const timeBuffer = decompiled[timePosition] as Buffer;\n    timelock = script.number.decode(timeBuffer);\n  } else {\n    // in case timelock is <= 16 it will be a number, not a buffer\n    const wrap = decompiled[timePosition] % 16;\n    timelock = wrap === 0 ? 16 : wrap;\n  }\n\n  const redeem = {\n    output: scripts.timelockScript,\n    redeemVersion: REDEEM_VERSION,\n  };\n\n  const p2tr = payments.p2tr({\n    internalPubkey,\n    scriptTree,\n    redeem,\n    network,\n  });\n\n  const tapLeafScript = {\n    leafVersion: redeem.redeemVersion,\n    script: redeem.output,\n    controlBlock: p2tr.witness![p2tr.witness!.length - 1],\n  };\n\n  const psbt = new Psbt({ network });\n\n  // only transactions with version 2 can trigger OP_CHECKSEQUENCEVERIFY\n  // https://github.com/btcsuite/btcd/blob/master/txscript/opcode.go#L1174\n  psbt.setVersion(TRANSACTION_VERSION);\n\n  psbt.addInput({\n    hash: tx.getHash(),\n    index: outputIndex,\n    tapInternalKey: internalPubkey,\n    witnessUtxo: {\n      value: tx.outs[outputIndex].value,\n      script: tx.outs[outputIndex].script,\n    },\n    tapLeafScript: [tapLeafScript],\n    sequence: timelock,\n  });\n\n  const estimatedFee = getWithdrawTxFee(feeRate);\n  const outputValue = tx.outs[outputIndex].value - estimatedFee;\n  if (outputValue < 0) {\n    throw new Error(\n      \"Not enough funds to cover the fee for withdrawal transaction\",\n    );\n  }\n  if (outputValue < BTC_DUST_SAT) {\n    throw new Error(\"Output value is less than dust limit\");\n  }\n  psbt.addOutput({\n    address: withdrawalAddress,\n    value: outputValue,\n  });\n\n  // Withdraw transaction has no time-based restrictions and can be included \n  // in the next block immediately.\n  psbt.setLocktime(0);\n\n  return {\n    psbt,\n    fee: estimatedFee,\n  };\n}\n\n/**\n * Constructs a slashing transaction for a staking output without prior unbonding.\n *\n * This transaction spends the staking output of the staking transaction and distributes the funds\n * according to the specified slashing rate.\n *\n * Outputs:\n * - The first output sends `input * slashing_rate` funds to the slashing address.\n * - The second output sends `input * (1 - slashing_rate) - fee` funds back to the user's address.\n *\n * Inputs:\n * - scripts: Scripts used to construct the taproot output.\n *   - slashingScript: Script for the slashing condition.\n *   - timelockScript: Script for the timelock condition.\n *   - unbondingScript: Script for the unbonding condition.\n *   - unbondingTimelockScript: Script for the unbonding timelock condition.\n * - transaction: The original staking transaction.\n * - slashingAddress: The address to send the slashed funds to.\n * - slashingRate: The rate at which the funds are slashed (0 < slashingRate < 1).\n * - minimumFee: The minimum fee for the transaction in satoshis.\n * - network: The Bitcoin network.\n * - outputIndex: The index of the output to be spent in the original transaction (default is 0).\n *\n * @param {Object} scripts - The scripts used in the transaction.\n * @param {Transaction} stakingTransaction - The original staking transaction.\n * @param {string} slashingPkScriptHex - The public key script to send the slashed funds to.\n * @param {number} slashingRate - The rate at which the funds are slashed.\n * @param {number} minimumFee - The minimum fee for the transaction in satoshis.\n * @param {networks.Network} network - The Bitcoin network.\n * @param {number} [outputIndex=0] - The index of the output to be spent in the original transaction.\n * @returns {{ psbt: Psbt }} An object containing the partially signed transaction (PSBT).\n */\nexport function slashTimelockUnbondedTransaction(\n  scripts: {\n    slashingScript: Buffer;\n    timelockScript: Buffer;\n    unbondingScript: Buffer;\n    unbondingTimelockScript: Buffer;\n  },\n  stakingTransaction: Transaction,\n  slashingPkScriptHex: string,\n  slashingRate: number,\n  minimumFee: number,\n  network: networks.Network,\n  outputIndex: number = 0,\n): { psbt: Psbt } {\n  const slashingScriptTree: Taptree = [\n    {\n      output: scripts.slashingScript,\n    },\n    [{ output: scripts.unbondingScript }, { output: scripts.timelockScript }],\n  ];\n  return slashingTransaction(\n    {\n      unbondingTimelockScript: scripts.unbondingTimelockScript,\n      slashingScript: scripts.slashingScript,\n    },\n    slashingScriptTree,\n    stakingTransaction,\n    slashingPkScriptHex,\n    slashingRate,\n    minimumFee,\n    network,\n    outputIndex,\n  );\n}\n\n/**\n * Constructs a slashing transaction for an early unbonded transaction.\n *\n * This transaction spends the staking output of the staking transaction and distributes the funds\n * according to the specified slashing rate.\n *\n * Transaction outputs:\n * - The first output sends `input * slashing_rate` funds to the slashing address.\n * - The second output sends `input * (1 - slashing_rate) - fee` funds back to the user's address.\n *\n * @param {Object} scripts - The scripts used in the transaction. e.g slashingScript, unbondingTimelockScript\n * @param {Transaction} unbondingTx - The unbonding transaction.\n * @param {string} slashingPkScriptHex - The public key script to send the slashed funds to.\n * @param {number} slashingRate - The rate at which the funds are slashed.\n * @param {number} minimumSlashingFee - The minimum fee for the transaction in satoshis.\n * @param {networks.Network} network - The Bitcoin network.\n * @returns {{ psbt: Psbt }} An object containing the partially signed transaction (PSBT).\n */\nexport function slashEarlyUnbondedTransaction(\n  scripts: {\n    slashingScript: Buffer;\n    unbondingTimelockScript: Buffer;\n  },\n  unbondingTx: Transaction,\n  slashingPkScriptHex: string,\n  slashingRate: number,\n  minimumSlashingFee: number,\n  network: networks.Network,\n): { psbt: Psbt } {\n  const unbondingScriptTree: Taptree = [\n    {\n      output: scripts.slashingScript,\n    },\n    {\n      output: scripts.unbondingTimelockScript,\n    },\n  ];\n  return slashingTransaction(\n    {\n      unbondingTimelockScript: scripts.unbondingTimelockScript,\n      slashingScript: scripts.slashingScript,\n    },\n    unbondingScriptTree,\n    unbondingTx,\n    slashingPkScriptHex,\n    slashingRate,\n    minimumSlashingFee,\n    network,\n    0, // unbonding always has a single output\n  );\n}\n\n/**\n * Constructs a slashing transaction for an on-demand unbonding.\n *\n * This transaction spends the staking output of the staking transaction and distributes the funds\n * according to the specified slashing rate.\n *\n * Transaction outputs:\n * - The first output sends `input * slashing_rate` funds to the slashing address.\n * - The second output sends `input * (1 - slashing_rate) - fee` funds back to the user's address.\n *\n * @param {Object} scripts - The scripts used in the transaction. e.g slashingScript, unbondingTimelockScript\n * @param {Transaction} transaction - The original staking/unbonding transaction.\n * @param {string} slashingPkScriptHex - The public key script to send the slashed funds to.\n * @param {number} slashingRate - The rate at which the funds are slashed. Two decimal places, otherwise it will be rounded down.\n * @param {number} minimumFee - The minimum fee for the transaction in satoshis.\n * @param {networks.Network} network - The Bitcoin network.\n * @param {number} [outputIndex=0] - The index of the output to be spent in the original transaction.\n * @returns {{ psbt: Psbt }} An object containing the partially signed transaction (PSBT).\n */\nfunction slashingTransaction(\n  scripts: {\n    unbondingTimelockScript: Buffer;\n    slashingScript: Buffer;\n  },\n  scriptTree: Taptree,\n  transaction: Transaction,\n  slashingPkScriptHex: string,\n  slashingRate: number,\n  minimumFee: number,\n  network: networks.Network,\n  outputIndex: number = 0,\n): {\n  psbt: Psbt;\n} {\n  // Check that slashing rate and minimum fee are bigger than 0\n  if (slashingRate <= 0 || slashingRate >= 1) {\n    throw new Error(\"Slashing rate must be between 0 and 1\");\n  }\n  // Round the slashing rate to two decimal places\n  slashingRate = parseFloat(slashingRate.toFixed(BTC_SLASHING_FRACTION_DIGITS));\n  // Minimum fee must be a postive integer\n  if (minimumFee <= 0 || !Number.isInteger(minimumFee)) {\n    throw new Error(\"Minimum fee must be a positve integer\");\n  }\n\n  // Check that outputIndex is bigger or equal to 0\n  if (outputIndex < 0 || !Number.isInteger(outputIndex)) {\n    throw new Error(\"Output index must be an integer bigger or equal to 0\");\n  }\n\n  // Check that outputIndex is within the bounds of the transaction\n  if (!transaction.outs[outputIndex]) {\n    throw new Error(\"Output index is out of range\");\n  }\n\n  const redeem = {\n    output: scripts.slashingScript,\n    redeemVersion: REDEEM_VERSION,\n  };\n\n  const p2tr = payments.p2tr({\n    internalPubkey,\n    scriptTree,\n    redeem,\n    network,\n  });\n\n  const tapLeafScript = {\n    leafVersion: redeem.redeemVersion,\n    script: redeem.output,\n    controlBlock: p2tr.witness![p2tr.witness!.length - 1],\n  };\n\n  const stakingAmount = transaction.outs[outputIndex].value;\n  // Slashing rate is a percentage of the staking amount, rounded down to\n  // the nearest integer to avoid sending decimal satoshis\n  const slashingAmount = Math.round(stakingAmount * slashingRate);\n\n  // Compute the slashing output\n  const slashingOutput = Buffer.from(slashingPkScriptHex, \"hex\");\n\n  // If OP_RETURN is not included, the slashing amount must be greater than the\n  // dust limit.\n  if (opcodes.OP_RETURN != slashingOutput[0]) {\n    if (slashingAmount <= BTC_DUST_SAT) {\n      throw new Error(\"Slashing amount is less than dust limit\");\n    }  \n  }\n\n  const userFunds = stakingAmount - slashingAmount - minimumFee;\n  if (userFunds <= BTC_DUST_SAT) {\n    throw new Error(\"User funds are less than dust limit\");\n  }\n \n  const psbt = new Psbt({ network });\n  psbt.setVersion(TRANSACTION_VERSION);\n\n  psbt.addInput({\n    hash: transaction.getHash(),\n    index: outputIndex,\n    tapInternalKey: internalPubkey,\n    witnessUtxo: {\n      value: stakingAmount,\n      script: transaction.outs[outputIndex].script,\n    },\n    tapLeafScript: [tapLeafScript],\n    // not RBF-able\n    sequence: NON_RBF_SEQUENCE,\n  });\n\n  // Add the slashing output\n  psbt.addOutput({\n    script: slashingOutput,\n    value: slashingAmount,\n  });\n\n  // Change output contains unbonding timelock script\n  const changeOutput = payments.p2tr({\n    internalPubkey,\n    scriptTree: { output: scripts.unbondingTimelockScript },\n    network,\n  });\n  // Add the change output\n  psbt.addOutput({\n    address: changeOutput.address!,\n    value: userFunds,\n  });\n\n  // Slashing transaction has no time-based restrictions and can be included \n  // in the next block immediately.\n  psbt.setLocktime(0);\n\n  return { psbt };\n}\n\nexport function unbondingTransaction(\n  scripts: {\n    unbondingTimelockScript: Buffer;\n    slashingScript: Buffer;\n  },\n  stakingTx: Transaction,\n  unbondingFee: number,\n  network: networks.Network,\n  outputIndex: number = 0,\n): TransactionResult {\n  // Check that transaction fee is bigger than 0\n  if (unbondingFee <= 0) {\n    throw new Error(\"Unbonding fee must be bigger than 0\");\n  }\n\n  // Check that outputIndex is bigger or equal to 0\n  if (outputIndex < 0) {\n    throw new Error(\"Output index must be bigger or equal to 0\");\n  }\n\n  const tx = new Transaction();\n  tx.version = TRANSACTION_VERSION;\n\n  tx.addInput(\n    stakingTx.getHash(),\n    outputIndex,\n    NON_RBF_SEQUENCE, // not RBF-able\n  );\n\n  const unbondingOutputInfo = deriveUnbondingOutputInfo(scripts, network);\n\n  const outputValue = stakingTx.outs[outputIndex].value - unbondingFee;\n  if (outputValue < BTC_DUST_SAT) {\n    throw new Error(\"Output value is less than dust limit for unbonding transaction\");\n  }\n  // Add the unbonding output\n  if (!unbondingOutputInfo.outputAddress) {\n    throw new Error(\"Unbonding output address is not defined\");\n  }\n  tx.addOutput(\n    unbondingOutputInfo.scriptPubKey,\n    outputValue,\n  );\n\n  // Unbonding transaction has no time-based restrictions and can be included \n  // in the next block immediately.\n  tx.locktime = 0;\n\n  return {\n    transaction: tx,\n    fee: unbondingFee,\n  };\n}\n\n// This function attaches covenant signatures as the transaction's witness\n// Note that the witness script expects exactly covenantQuorum number of signatures\n// to match the covenant parameters.\nexport const createCovenantWitness = (\n  originalWitness: Buffer[],\n  paramsCovenants: Buffer[],\n  covenantSigs: CovenantSignature[],\n  covenantQuorum: number,\n) => {\n  if (covenantSigs.length < covenantQuorum) {\n    throw new Error(\n      `Not enough covenant signatures. Required: ${covenantQuorum}, `\n      + `got: ${covenantSigs.length}`\n    );\n  }\n  // Verify all btcPkHex from covenantSigs exist in paramsCovenants\n  for (const sig of covenantSigs) {\n    const btcPkHexBuf = Buffer.from(sig.btcPkHex, \"hex\");\n    if (!paramsCovenants.some(covenant => covenant.equals(btcPkHexBuf))) {\n      throw new Error(\n        `Covenant signature public key ${sig.btcPkHex} not found in params covenants`\n      );\n    }\n  }\n  // We only take exactly covenantQuorum number of signatures, even if more are provided.\n  // Including extra signatures will cause the unbonding transaction to fail validation.\n  // This is because the witness script expects exactly covenantQuorum number of signatures\n  // to match the covenant parameters.\n  const covenantSigsBuffers = covenantSigs\n    .slice(0, covenantQuorum)\n    .map((sig) => ({\n      btcPkHex: Buffer.from(sig.btcPkHex, \"hex\"),\n      sigHex: Buffer.from(sig.sigHex, \"hex\"),\n    }));\n\n  // we need covenant from params to be sorted in reverse order\n  const paramsCovenantsSorted = [...paramsCovenants]\n    .sort(Buffer.compare)\n    .reverse();\n\n  const composedCovenantSigs = paramsCovenantsSorted.map((covenant) => {\n    // in case there's covenant with this btc_pk_hex we return the sig\n    // otherwise we return empty Buffer\n    const covenantSig = covenantSigsBuffers.find(\n      (sig) => sig.btcPkHex.compare(covenant) === 0,\n    );\n    return covenantSig?.sigHex || Buffer.alloc(0);\n  });\n\n  return [...composedCovenantSigs, ...originalWitness];\n};\n", "export const BTC_DUST_SAT = 546;\n", "import { script as bitcoinScript } from \"bitcoinjs-lib\";\nimport { BTC_DUST_SAT } from \"../../constants/dustSat\";\nimport {\n  LOW_RATE_ESTIMATION_ACCURACY_BUFFER,\n  MAX_NON_LEGACY_OUTPUT_SIZE,\n  OP_RETURN_OUTPUT_VALUE_SIZE,\n  OP_RETURN_VALUE_SERIALIZE_SIZE,\n  P2TR_INPUT_SIZE,\n  TX_BUFFER_SIZE_OVERHEAD,\n  WALLET_RELAY_FEE_RATE_THRESHOLD,\n  WITHDRAW_TX_BUFFER_SIZE,\n} from \"../../constants/fee\";\nimport { UTXO } from \"../../types/UTXO\";\nimport {\n  TransactionOutput,\n} from \"../../types/psbtOutputs\";\nimport {\n  getEstimatedChangeOutputSize,\n  getInputSizeByScript,\n  isOP_RETURN,\n} from \"./utils\";\n\n/**\n * Selects UTXOs and calculates the fee for a staking transaction.\n * This method selects the highest value UTXOs from all available UTXOs to\n * cover the staking amount and the transaction fees.\n * The formula used is:\n *\n * totalFee = (inputSize + outputSize) * feeRate + buffer\n * where outputSize may or may not include the change output size depending on the remaining value.\n *\n * @param availableUTXOs - All available UTXOs from the wallet.\n * @param stakingAmount - The amount to stake.\n * @param feeRate - The fee rate in satoshis per byte.\n * @param outputs - The outputs in the transaction.\n * @returns An object containing the selected UTXOs and the fee.\n * @throws Will throw an error if there are insufficient funds or if the fee cannot be calculated.\n */\nexport const getStakingTxInputUTXOsAndFees = (\n  availableUTXOs: UTXO[],\n  stakingAmount: number,\n  feeRate: number,\n  outputs: TransactionOutput[],\n): {\n  selectedUTXOs: UTXO[];\n  fee: number;\n} => {\n  if (availableUTXOs.length === 0) {\n    throw new Error(\"Insufficient funds\");\n  }\n\n  const validUTXOs = availableUTXOs.filter((utxo) => {\n    const script = Buffer.from(utxo.scriptPubKey, \"hex\");\n    return !!bitcoinScript.decompile(script);\n  });\n\n  if (validUTXOs.length === 0) {\n    throw new Error(\"Insufficient funds: no valid UTXOs available for staking\");\n  }\n\n  // Sort available UTXOs from highest to lowest value\n  const sortedUTXOs = validUTXOs.sort((a, b) => b.value - a.value);\n\n  const selectedUTXOs: UTXO[] = [];\n  let accumulatedValue = 0;\n  let estimatedFee = 0;\n\n  for (const utxo of sortedUTXOs) {\n    selectedUTXOs.push(utxo);\n    accumulatedValue += utxo.value;\n\n    // Calculate the fee for the current set of UTXOs and outputs\n    const estimatedSize = getEstimatedSize(selectedUTXOs, outputs);\n    estimatedFee = estimatedSize * feeRate + rateBasedTxBufferFee(feeRate);\n    // Check if there will be any change left after the staking amount and fee.\n    // If there is, a change output needs to be added, which also comes with an additional fee.\n    if (accumulatedValue - (stakingAmount + estimatedFee) > BTC_DUST_SAT) {\n      estimatedFee += getEstimatedChangeOutputSize() * feeRate;\n    }\n    if (accumulatedValue >= stakingAmount + estimatedFee) {\n      break;\n    }\n  }\n\n  if (accumulatedValue < stakingAmount + estimatedFee) {\n    throw new Error(\n      \"Insufficient funds: unable to gather enough UTXOs to cover the staking amount and fees\",\n    );\n  }\n\n  return {\n    selectedUTXOs,\n    fee: estimatedFee,\n  };\n};\n\n\n/**\n * Calculates the estimated fee for a withdrawal transaction.\n * The fee calculation is based on estimated constants for input size,\n * output size, and additional overhead specific to withdrawal transactions.\n * Due to the slightly larger size of withdrawal transactions, an additional\n * buffer is included to account for this difference.\n *\n * @param feeRate - The fee rate in satoshis per vbyte.\n * @returns The estimated fee for a withdrawal transaction in satoshis.\n */\nexport const getWithdrawTxFee = (feeRate: number): number => {\n  const inputSize = P2TR_INPUT_SIZE;\n  const outputSize = getEstimatedChangeOutputSize();\n  return (\n    feeRate *\n      (inputSize +\n        outputSize +\n        TX_BUFFER_SIZE_OVERHEAD +\n        WITHDRAW_TX_BUFFER_SIZE) +\n    rateBasedTxBufferFee(feeRate)\n  );\n};\n\n\n/**\n * Calculates the estimated transaction size using a heuristic formula which\n * includes the input size, output size, and a fixexd buffer for the transaction size.\n * The formula used is:\n *\n * totalSize = inputSize + outputSize + TX_BUFFER_SIZE_OVERHEAD\n *\n * @param inputUtxos - The UTXOs used as inputs in the transaction.\n * @param outputs - The outputs in the transaction.\n * @returns The estimated transaction size in bytes.\n */\nconst getEstimatedSize = (\n  inputUtxos: UTXO[],\n  outputs: TransactionOutput[],\n): number => {\n  // Estimate the input size\n  const inputSize = inputUtxos.reduce((acc: number, u: UTXO): number => {\n    const script = Buffer.from(u.scriptPubKey, \"hex\");\n    const decompiledScript = bitcoinScript.decompile(script);\n    if (!decompiledScript) {\n      // Skip UTXOs with scripts that cannot be decompiled\n      return acc;\n    }\n    return acc + getInputSizeByScript(script);\n  }, 0);\n\n  // Estimate the output size\n  const outputSize = outputs.reduce((acc, output): number => {\n    if (isOP_RETURN(output.scriptPubKey)) {\n      return (\n        acc +\n        output.scriptPubKey.length +\n        OP_RETURN_OUTPUT_VALUE_SIZE +\n        OP_RETURN_VALUE_SERIALIZE_SIZE\n      );\n    }\n    return acc + MAX_NON_LEGACY_OUTPUT_SIZE;\n  }, 0);\n\n  return inputSize + outputSize + TX_BUFFER_SIZE_OVERHEAD;\n};\n\n/**\n * Adds a buffer to the transaction size-based fee calculation if the fee rate is low.\n * Some wallets have a relayer fee requirement, which means if the fee rate is\n * less than or equal to WALLET_RELAY_FEE_RATE_THRESHOLD (2 satoshis per byte),\n * there is a risk that the fee might not be sufficient to get the transaction relayed.\n * To mitigate this risk, we add a buffer to the fee calculation to ensure that\n * the transaction can be relayed.\n *\n * If the fee rate is less than or equal to WALLET_RELAY_FEE_RATE_THRESHOLD, a fixed buffer is added\n * (LOW_RATE_ESTIMATION_ACCURACY_BUFFER). If the fee rate is higher, no buffer is added.\n *\n * @param feeRate - The fee rate in satoshis per byte.\n * @returns The buffer amount in satoshis to be added to the transaction fee.\n */\nconst rateBasedTxBufferFee = (feeRate: number): number => {\n  return feeRate <= WALLET_RELAY_FEE_RATE_THRESHOLD\n    ? LOW_RATE_ESTIMATION_ACCURACY_BUFFER\n    : 0;\n};\n", "// Estimated size of a non-SegWit input in bytes\nexport const DEFAULT_INPUT_SIZE = 180;\n// Estimated size of a P2WPKH input in bytes\nexport const P2WPKH_INPUT_SIZE = 68;\n// Estimated size of a P2TR input in bytes\nexport const P2TR_INPUT_SIZE = 58;\n// Estimated size of a transaction buffer in bytes\nexport const TX_BUFFER_SIZE_OVERHEAD = 11;\n// Buffer for estimation accuracy when fee rate <= 2 sat/byte\nexport const LOW_RATE_ESTIMATION_ACCURACY_BUFFER = 30;\n// Size of a Taproot output, the largest non-legacy output type\nexport const MAX_NON_LEGACY_OUTPUT_SIZE = 43;\n// Buffer size for withdraw transaction fee calculation\nexport const WITHDRAW_TX_BUFFER_SIZE = 17;\n// Threshold for wallet relay fee rate. Different buffer fees are used based on this threshold\nexport const WALLET_RELAY_FEE_RATE_THRESHOLD = 2;\n// Estimated size of the OP_RETURN output value in bytes\nexport const OP_RETURN_OUTPUT_VALUE_SIZE = 8;\n// Because our OP_RETURN data will always be less than 80 bytes, which is less than 0xfd (253),\n// the value serialization size will always be 1 byte.\nexport const OP_RETURN_VALUE_SERIALIZE_SIZE = 1;\n", "import { script as bitcoinScript, opcodes, payments } from \"bitcoinjs-lib\";\nimport {\n  DEFAULT_INPUT_SIZE,\n  MAX_NON_LEGACY_OUTPUT_SIZE,\n  P2TR_INPUT_SIZE,\n  P2WPKH_INPUT_SIZE,\n} from \"../../constants/fee\";\nimport { UTXO } from \"../../types/UTXO\";\n\n// Helper function to check if a script is OP_RETURN\nexport const isOP_RETURN = (script: Buffer): boolean => {\n  const decompiled = bitcoinScript.decompile(script);\n  return !!decompiled && decompiled[0] === opcodes.OP_RETURN;\n};\n\n/**\n * Determines the size of a transaction input based on its script type.\n *\n * @param script - The script of the input.\n * @returns The estimated size of the input in bytes.\n */\nexport const getInputSizeByScript = (script: Buffer): number => {\n  // Check if input is in the format of \"00 <20-byte public key hash>\"\n  // If yes, it is a P2WPKH input\n  try {\n    const { address: p2wpkhAddress } = payments.p2wpkh({\n      output: script,\n    });\n    if (p2wpkhAddress) {\n      return P2WPKH_INPUT_SIZE;\n    }\n    // eslint-disable-next-line no-empty\n  } catch (error) {} // Ignore errors\n  // Check if input is in the format of \"51 <32-byte public key>\"\n  // If yes, it is a P2TR input\n  try {\n    const { address: p2trAddress } = payments.p2tr({\n      output: script,\n    });\n    if (p2trAddress) {\n      return P2TR_INPUT_SIZE;\n    }\n    // eslint-disable-next-line no-empty\n  } catch (error) {} // Ignore errors\n  // Otherwise, assume the input is largest P2PKH address type\n  return DEFAULT_INPUT_SIZE;\n};\n\n/**\n * Returns the estimated size for a change output.\n * This is used when the transaction has a change output to a particular address.\n *\n * @returns The estimated size for a change output in bytes.\n */\nexport const getEstimatedChangeOutputSize = (): number => {\n  return MAX_NON_LEGACY_OUTPUT_SIZE;\n};\n\n/**\n * Returns the sum of the values of the UTXOs.\n *\n * @param inputUTXOs - The UTXOs to sum the values of.\n * @returns The sum of the values of the UTXOs in satoshis.\n */\nexport const inputValueSum = (inputUTXOs: UTXO[]): number => {\n  return inputUTXOs.reduce((acc, utxo) => acc + utxo.value, 0);\n};\n", "// This sequence enables both the locktime field and also replace-by-fee\nexport const RBF_SEQUENCE = 0xfffffffd;\n// This sequence means the transaction is not replaceable\nexport const NON_RBF_SEQUENCE = 0xffffffff;\n// The Transaction version number used across the library(to be set in the psbt)\nexport const TRANSACTION_VERSION = 2;", "import { networks, Psbt, Transaction } from \"bitcoinjs-lib\";\nimport { StakingError, StakingErrorCode } from \"../error\";\nimport { StakingParams } from \"../types/params\";\nimport { PsbtResult, TransactionResult } from \"../types/transaction\";\nimport { UTXO } from \"../types/UTXO\";\nimport {\n  isTaproot,\n  isValidBitcoinAddress,\n  isValidNoCoordPublicKey,\n} from \"../utils/btc\";\nimport {\n  deriveSlashingOutput,\n  deriveStakingOutputInfo,\n  findMatchingTxOutputIndex,\n  toBuffers,\n  validateParams,\n  validateStakingTimelock,\n  validateStakingTxInputData,\n} from \"../utils/staking\";\nimport { stakingPsbt, unbondingPsbt } from \"./psbt\";\nimport { StakingScriptData, StakingScripts } from \"./stakingScript\";\nimport {\n  slashEarlyUnbondedTransaction,\n  slashTimelockUnbondedTransaction,\n  stakingTransaction,\n  unbondingTransaction,\n  withdrawEarlyUnbondedTransaction,\n  withdrawSlashingTransaction,\n  withdrawTimelockUnbondedTransaction,\n} from \"./transactions\";\nexport * from \"./stakingScript\";\n\nexport interface StakerInfo {\n  address: string;\n  publicKeyNoCoordHex: string;\n}\n\nexport class Staking {\n  network: networks.Network;\n  stakerInfo: StakerInfo;\n  params: StakingParams;\n  finalityProviderPksNoCoordHex: string[];\n  stakingTimelock: number;\n\n  constructor(\n    network: networks.Network,\n    stakerInfo: StakerInfo,\n    params: StakingParams,\n    finalityProviderPksNoCoordHex: string[],\n    stakingTimelock: number,\n  ) {\n    // Perform validations\n    if (!isValidBitcoinAddress(stakerInfo.address, network)) {\n      throw new StakingError(\n        StakingErrorCode.INVALID_INPUT,\n        \"Invalid staker bitcoin address\",\n      );\n    }\n    if (!isValidNoCoordPublicKey(stakerInfo.publicKeyNoCoordHex)) {\n      throw new StakingError(\n        StakingErrorCode.INVALID_INPUT,\n        \"Invalid staker public key\",\n      );\n    }\n    if (\n      finalityProviderPksNoCoordHex.length === 0 || \n      !finalityProviderPksNoCoordHex.every(isValidNoCoordPublicKey)\n    ) {\n      throw new StakingError(\n        StakingErrorCode.INVALID_INPUT,\n        \"Invalid finality providers public keys\",\n      );\n    }\n    validateParams(params);\n    validateStakingTimelock(stakingTimelock, params);\n\n    this.network = network;\n    this.stakerInfo = stakerInfo;\n    this.params = params;\n    this.finalityProviderPksNoCoordHex = finalityProviderPksNoCoordHex;\n    this.stakingTimelock = stakingTimelock;\n  }\n\n  /**\n   * buildScripts builds the staking scripts for the staking transaction.\n   * Note: different staking types may have different scripts.\n   * e.g the observable staking script has a data embed script.\n   *\n   * @returns {StakingScripts} - The staking scripts.\n   */\n  buildScripts(): StakingScripts {\n    const { covenantQuorum, covenantNoCoordPks, unbondingTime } = this.params;\n    // Create staking script data\n    let stakingScriptData;\n    try {\n      stakingScriptData = new StakingScriptData(\n        Buffer.from(this.stakerInfo.publicKeyNoCoordHex, \"hex\"),\n        this.finalityProviderPksNoCoordHex.map((pk) => Buffer.from(pk, \"hex\")),\n        toBuffers(covenantNoCoordPks),\n        covenantQuorum,\n        this.stakingTimelock,\n        unbondingTime,\n      );\n    } catch (error: unknown) {\n      throw StakingError.fromUnknown(\n        error,\n        StakingErrorCode.SCRIPT_FAILURE,\n        \"Cannot build staking script data\",\n      );\n    }\n\n    // Build scripts\n    let scripts;\n    try {\n      scripts = stakingScriptData.buildScripts();\n    } catch (error: unknown) {\n      throw StakingError.fromUnknown(\n        error,\n        StakingErrorCode.SCRIPT_FAILURE,\n        \"Cannot build staking scripts\",\n      );\n    }\n    return scripts;\n  }\n\n  /**\n   * Create a staking transaction for staking.\n   *\n   * @param {number} stakingAmountSat - The amount to stake in satoshis.\n   * @param {UTXO[]} inputUTXOs - The UTXOs to use as inputs for the staking\n   * transaction.\n   * @param {number} feeRate - The fee rate for the transaction in satoshis per byte.\n   * @returns {TransactionResult} - An object containing the unsigned\n   * transaction, and fee\n   * @throws {StakingError} - If the transaction cannot be built\n   */\n  public createStakingTransaction(\n    stakingAmountSat: number,\n    inputUTXOs: UTXO[],\n    feeRate: number,\n  ): TransactionResult {\n    validateStakingTxInputData(\n      stakingAmountSat,\n      this.stakingTimelock,\n      this.params,\n      inputUTXOs,\n      feeRate,\n    );\n\n    const scripts = this.buildScripts();\n\n    try {\n      const { transaction, fee } = stakingTransaction(\n        scripts,\n        stakingAmountSat,\n        this.stakerInfo.address,\n        inputUTXOs,\n        this.network,\n        feeRate,\n      );\n      return {\n        transaction,\n        fee,\n      };\n    } catch (error: unknown) {\n      throw StakingError.fromUnknown(\n        error,\n        StakingErrorCode.BUILD_TRANSACTION_FAILURE,\n        \"Cannot build unsigned staking transaction\",\n      );\n    }\n  }\n\n  /**\n   * Create a staking psbt based on the existing staking transaction.\n   *\n   * @param {Transaction} stakingTx - The staking transaction.\n   * @param {UTXO[]} inputUTXOs - The UTXOs to use as inputs for the staking\n   * transaction. The UTXOs that were used to create the staking transaction should\n   * be included in this array.\n   * @returns {Psbt} - The psbt.\n   */\n  public toStakingPsbt(stakingTx: Transaction, inputUTXOs: UTXO[]): Psbt {\n    // Check the staking output index can be found\n    const scripts = this.buildScripts();\n    const stakingOutputInfo = deriveStakingOutputInfo(scripts, this.network);\n    findMatchingTxOutputIndex(\n      stakingTx,\n      stakingOutputInfo.outputAddress,\n      this.network,\n    );\n\n    return stakingPsbt(\n      stakingTx,\n      this.network,\n      inputUTXOs,\n      isTaproot(this.stakerInfo.address, this.network)\n        ? Buffer.from(this.stakerInfo.publicKeyNoCoordHex, \"hex\")\n        : undefined,\n    );\n  }\n\n  /**\n   * Create an unbonding transaction for staking.\n   *\n   * @param {Transaction} stakingTx - The staking transaction to unbond.\n   * @returns {TransactionResult} - An object containing the unsigned\n   * transaction, and fee\n   * @throws {StakingError} - If the transaction cannot be built\n   */\n  public createUnbondingTransaction(stakingTx: Transaction): TransactionResult {\n    // Build scripts\n    const scripts = this.buildScripts();\n    const { outputAddress } = deriveStakingOutputInfo(scripts, this.network);\n    // Reconstruct the stakingOutputIndex\n    const stakingOutputIndex = findMatchingTxOutputIndex(\n      stakingTx,\n      outputAddress,\n      this.network,\n    );\n    // Create the unbonding transaction\n    try {\n      const { transaction } = unbondingTransaction(\n        scripts,\n        stakingTx,\n        this.params.unbondingFeeSat,\n        this.network,\n        stakingOutputIndex,\n      );\n      return {\n        transaction,\n        fee: this.params.unbondingFeeSat,\n      };\n    } catch (error) {\n      throw StakingError.fromUnknown(\n        error,\n        StakingErrorCode.BUILD_TRANSACTION_FAILURE,\n        \"Cannot build the unbonding transaction\",\n      );\n    }\n  }\n\n  /**\n   * Create an unbonding psbt based on the existing unbonding transaction and\n   * staking transaction.\n   *\n   * @param {Transaction} unbondingTx - The unbonding transaction.\n   * @param {Transaction} stakingTx - The staking transaction.\n   *\n   * @returns {Psbt} - The psbt.\n   */\n  public toUnbondingPsbt(\n    unbondingTx: Transaction,\n    stakingTx: Transaction,\n  ): Psbt {\n    return unbondingPsbt(\n      this.buildScripts(),\n      unbondingTx,\n      stakingTx,\n      this.network,\n    );\n  }\n\n  /**\n   * Creates a withdrawal transaction that spends from an unbonding or slashing\n   * transaction. The timelock on the input transaction must have expired before\n   * this withdrawal can be valid.\n   *\n   * @param {Transaction} earlyUnbondedTx - The unbonding or slashing\n   * transaction to withdraw from\n   * @param {number} feeRate - Fee rate in satoshis per byte for the withdrawal\n   * transaction\n   * @returns {PsbtResult} - Contains the unsigned PSBT and fee amount\n   * @throws {StakingError} - If the input transaction is invalid or withdrawal\n   * transaction cannot be built\n   */\n  public createWithdrawEarlyUnbondedTransaction(\n    earlyUnbondedTx: Transaction,\n    feeRate: number,\n  ): PsbtResult {\n    // Build scripts\n    const scripts = this.buildScripts();\n\n    // Create the withdraw early unbonded transaction\n    try {\n      return withdrawEarlyUnbondedTransaction(\n        scripts,\n        earlyUnbondedTx,\n        this.stakerInfo.address,\n        this.network,\n        feeRate,\n      );\n    } catch (error) {\n      throw StakingError.fromUnknown(\n        error,\n        StakingErrorCode.BUILD_TRANSACTION_FAILURE,\n        \"Cannot build unsigned withdraw early unbonded transaction\",\n      );\n    }\n  }\n\n  /**\n   * Create a withdrawal psbt that spends a naturally expired staking\n   * transaction.\n   *\n   * @param {Transaction} stakingTx - The staking transaction to withdraw from.\n   * @param {number} feeRate - The fee rate for the transaction in satoshis per byte.\n   * @returns {PsbtResult} - An object containing the unsigned psbt and fee\n   * @throws {StakingError} - If the delegation is invalid or the transaction cannot be built\n   */\n  public createWithdrawStakingExpiredPsbt(\n    stakingTx: Transaction,\n    feeRate: number,\n  ): PsbtResult {\n    // Build scripts\n    const scripts = this.buildScripts();\n    const { outputAddress } = deriveStakingOutputInfo(scripts, this.network);\n    // Reconstruct the stakingOutputIndex\n    const stakingOutputIndex = findMatchingTxOutputIndex(\n      stakingTx,\n      outputAddress,\n      this.network,\n    );\n\n    // Create the timelock unbonded transaction\n    try {\n      return withdrawTimelockUnbondedTransaction(\n        scripts,\n        stakingTx,\n        this.stakerInfo.address,\n        this.network,\n        feeRate,\n        stakingOutputIndex,\n      );\n    } catch (error) {\n      throw StakingError.fromUnknown(\n        error,\n        StakingErrorCode.BUILD_TRANSACTION_FAILURE,\n        \"Cannot build unsigned timelock unbonded transaction\",\n      );\n    }\n  }\n\n  /**\n   * Create a slashing psbt spending from the staking output.\n   *\n   * @param {Transaction} stakingTx - The staking transaction to slash.\n   * @returns {PsbtResult} - An object containing the unsigned psbt and fee\n   * @throws {StakingError} - If the delegation is invalid or the transaction cannot be built\n   */\n  public createStakingOutputSlashingPsbt(stakingTx: Transaction): PsbtResult {\n    if (!this.params.slashing) {\n      throw new StakingError(\n        StakingErrorCode.INVALID_PARAMS,\n        \"Slashing parameters are missing\",\n      );\n    }\n\n    // Build scripts\n    const scripts = this.buildScripts();\n\n    // Get the staking output address\n    const { outputAddress } = deriveStakingOutputInfo(scripts, this.network);\n\n    // Reconstruct the stakingOutputIndex\n    const stakingOutputIndex = findMatchingTxOutputIndex(\n      stakingTx,\n      outputAddress,\n      this.network,\n    )\n\n    // create the slash timelock unbonded transaction\n    try {\n      const { psbt } = slashTimelockUnbondedTransaction(\n        scripts,\n        stakingTx,\n        this.params.slashing.slashingPkScriptHex,\n        this.params.slashing.slashingRate,\n        this.params.slashing.minSlashingTxFeeSat,\n        this.network,\n        stakingOutputIndex,\n      );\n      return {\n        psbt,\n        fee: this.params.slashing.minSlashingTxFeeSat,\n      };\n    } catch (error) {\n      throw StakingError.fromUnknown(\n        error,\n        StakingErrorCode.BUILD_TRANSACTION_FAILURE,\n        \"Cannot build the slash timelock unbonded transaction\",\n      );\n    }\n  }\n\n  /**\n   * Create a slashing psbt for an unbonding output.\n   *\n   * @param {Transaction} unbondingTx - The unbonding transaction to slash.\n   * @returns {PsbtResult} - An object containing the unsigned psbt and fee\n   * @throws {StakingError} - If the delegation is invalid or the transaction cannot be built\n   */\n  public createUnbondingOutputSlashingPsbt(\n    unbondingTx: Transaction,\n  ): PsbtResult {\n    if (!this.params.slashing) {\n      throw new StakingError(\n        StakingErrorCode.INVALID_PARAMS,\n        \"Slashing parameters are missing\",\n      );\n    }\n    // Build scripts\n    const scripts = this.buildScripts();\n\n    // create the slash timelock unbonded transaction\n    try {\n      const { psbt } = slashEarlyUnbondedTransaction(\n        scripts,\n        unbondingTx,\n        this.params.slashing.slashingPkScriptHex,\n        this.params.slashing.slashingRate,\n        this.params.slashing.minSlashingTxFeeSat,\n        this.network,\n      );\n      return {\n        psbt,\n        fee: this.params.slashing.minSlashingTxFeeSat,\n      };\n    } catch (error) {\n      throw StakingError.fromUnknown(\n        error,\n        StakingErrorCode.BUILD_TRANSACTION_FAILURE,\n        \"Cannot build the slash early unbonded transaction\",\n      );\n    }\n  }\n\n  /**\n   * Create a withdraw slashing psbt that spends a slashing transaction from the\n   * staking output.\n   *\n   * @param {Transaction} slashingTx - The slashing transaction.\n   * @param {number} feeRate - The fee rate for the transaction in satoshis per byte.\n   * @returns {PsbtResult} - An object containing the unsigned psbt and fee\n   * @throws {StakingError} - If the delegation is invalid or the transaction cannot be built\n   */\n  public createWithdrawSlashingPsbt(\n    slashingTx: Transaction,\n    feeRate: number,\n  ): PsbtResult {\n    // Build scripts\n    const scripts = this.buildScripts();\n    const slashingOutputInfo = deriveSlashingOutput(scripts, this.network);\n\n    // Reconstruct and validate the slashingOutputIndex\n    const slashingOutputIndex = findMatchingTxOutputIndex(\n      slashingTx,\n      slashingOutputInfo.outputAddress,\n      this.network,\n    );\n\n    // Create the withdraw slashed transaction\n    try {\n      return withdrawSlashingTransaction(\n        scripts,\n        slashingTx,\n        this.stakerInfo.address,\n        this.network,\n        feeRate,\n        slashingOutputIndex,\n      );\n    } catch (error) {\n      throw StakingError.fromUnknown(\n        error,\n        StakingErrorCode.BUILD_TRANSACTION_FAILURE,\n        \"Cannot build withdraw slashing transaction\",\n      );\n    }\n  }\n}\n", "import {\n  btccheckpoint,\n  btcstaking,\n  btcstakingtx,\n} from \"@babylonlabs-io/babylon-proto-ts\";\nimport {\n  BIP322Sig,\n  BTCSigType,\n  ProofOfPossessionBTC,\n} from \"@babylonlabs-io/babylon-proto-ts/dist/generated/babylon/btcstaking/v1/pop\";\nimport { Psbt, Transaction, networks } from \"bitcoinjs-lib\";\nimport type { Emitter } from \"nanoevents\";\n\nimport { StakerInfo, Staking } from \".\";\nimport { BABYLON_REGISTRY_TYPE_URLS } from \"../constants/registry\";\nimport { StakingError, StakingErrorCode } from \"../error\";\nimport { TransactionResult, UTXO } from \"../types\";\nimport { ActionName } from \"../types/action\";\nimport { Contract, ContractId } from \"../types/contract\";\nimport { ManagerEvents } from \"../types/events\";\nimport {\n  BabylonProvider,\n  BtcProvider,\n  InclusionProof,\n  StakingInputs,\n} from \"../types/manager\";\nimport { StakingParams, VersionedStakingParams } from \"../types/params\";\nimport { reverseBuffer } from \"../utils\";\nimport { isValidBabylonAddress } from \"../utils/babylon\";\nimport { isNativeSegwit, isTaproot } from \"../utils/btc\";\nimport {\n  deriveStakingOutputInfo,\n  findMatchingTxOutputIndex,\n} from \"../utils/staking\";\nimport {\n  getBabylonParamByBtcHeight,\n  getBabylonParamByVersion,\n} from \"../utils/staking/param\";\nimport { createCovenantWitness } from \"./transactions\";\n\nexport class BabylonBtcStakingManager {\n  constructor(\n    protected network: networks.Network,\n    protected stakingParams: VersionedStakingParams[],\n    protected btcProvider: BtcProvider,\n    protected babylonProvider: BabylonProvider,\n    protected ee?: Emitter<ManagerEvents>\n  ) {\n    this.network = network;\n\n    if (stakingParams.length === 0) {\n      throw new Error(\"No staking parameters provided\");\n    }\n    this.stakingParams = stakingParams;\n  }\n\n  /**\n   * Creates a signed Pre-Staking Registration transaction that is ready to be\n   * sent to the Babylon chain.\n   * @param stakerBtcInfo - The staker BTC info which includes the BTC address\n   * and the no-coord public key in hex format.\n   * @param stakingInput - The staking inputs.\n   * @param babylonBtcTipHeight - The Babylon BTC tip height.\n   * @param inputUTXOs - The UTXOs that will be used to pay for the staking\n   * transaction.\n   * @param feeRate - The fee rate in satoshis per byte. Typical value for the\n   * fee rate is above 1. If the fee rate is too low, the transaction will not\n   * be included in a block.\n   * @param babylonAddress - The Babylon bech32 encoded address of the staker.\n   * @returns The signed babylon pre-staking registration transaction in base64\n   * format.\n   */\n  async preStakeRegistrationBabylonTransaction(\n    stakerBtcInfo: StakerInfo,\n    stakingInput: StakingInputs,\n    babylonBtcTipHeight: number,\n    inputUTXOs: UTXO[],\n    feeRate: number,\n    babylonAddress: string,\n  ): Promise<{\n    signedBabylonTx: Uint8Array;\n    stakingTx: Transaction;\n  }> {\n    if (babylonBtcTipHeight === 0) {\n      throw new Error(\"Babylon BTC tip height cannot be 0\");\n    }\n    if (inputUTXOs.length === 0) {\n      throw new Error(\"No input UTXOs provided\");\n    }\n    if (!isValidBabylonAddress(babylonAddress)) {\n      throw new Error(\"Invalid Babylon address\");\n    }\n\n    // Get the Babylon params based on the BTC tip height from Babylon chain\n    const params = getBabylonParamByBtcHeight(\n      babylonBtcTipHeight,\n      this.stakingParams,\n    );\n\n    const staking = new Staking(\n      this.network,\n      stakerBtcInfo,\n      params,\n      stakingInput.finalityProviderPksNoCoordHex,\n      stakingInput.stakingTimelock,\n    );\n\n    // Create unsigned staking transaction\n    const { transaction } = staking.createStakingTransaction(\n      stakingInput.stakingAmountSat,\n      inputUTXOs,\n      feeRate,\n    );\n\n    // Create delegation message without including inclusion proof\n    const msg = await this.createBtcDelegationMsg(\n      \"delegation:create\",\n      staking,\n      stakingInput,\n      transaction,\n      babylonAddress,\n      stakerBtcInfo,\n      params,\n    );\n\n    this.ee?.emit(\"delegation:create\", {\n      type: \"create-btc-delegation-msg\",\n    });\n\n    return {\n      signedBabylonTx: await this.babylonProvider.signTransaction(msg),\n      stakingTx: transaction,\n    };\n  }\n\n  /**\n   * Creates a signed post-staking registration transaction that is ready to be\n   * sent to the Babylon chain. This is used when a staking transaction is\n   * already created and included in a BTC block and we want to register it on\n   * the Babylon chain.\n   * @param stakerBtcInfo - The staker BTC info which includes the BTC address\n   * and the no-coord public key in hex format.\n   * @param stakingTx - The staking transaction.\n   * @param stakingTxHeight - The BTC height in which the staking transaction\n   * is included.\n   * @param stakingInput - The staking inputs.\n   * @param inclusionProof - Merkle Proof of Inclusion: Verifies transaction\n   * inclusion in a Bitcoin block that is k-deep.\n   * @param babylonAddress - The Babylon bech32 encoded address of the staker.\n   * @returns The signed babylon transaction in base64 format.\n   */\n  async postStakeRegistrationBabylonTransaction(\n    stakerBtcInfo: StakerInfo,\n    stakingTx: Transaction,\n    stakingTxHeight: number,\n    stakingInput: StakingInputs,\n    inclusionProof: InclusionProof,\n    babylonAddress: string,\n  ): Promise<{\n    signedBabylonTx: Uint8Array;\n  }> {\n    // Get the Babylon params at the time of the staking transaction\n    const params = getBabylonParamByBtcHeight(\n      stakingTxHeight,\n      this.stakingParams,\n    );\n\n    if (!isValidBabylonAddress(babylonAddress)) {\n      throw new Error(\"Invalid Babylon address\");\n    }\n\n    const stakingInstance = new Staking(\n      this.network,\n      stakerBtcInfo,\n      params,\n      stakingInput.finalityProviderPksNoCoordHex,\n      stakingInput.stakingTimelock,\n    );\n\n    // Validate if the stakingTx is valid based on the retrieved Babylon param\n    const scripts = stakingInstance.buildScripts();\n    const stakingOutputInfo = deriveStakingOutputInfo(scripts, this.network);\n    // Error will be thrown if the expected staking output address is not found\n    // in the stakingTx\n    findMatchingTxOutputIndex(\n      stakingTx,\n      stakingOutputInfo.outputAddress,\n      this.network,\n    );\n\n    // Create delegation message\n    const delegationMsg = await this.createBtcDelegationMsg(\n      \"delegation:register\",\n      stakingInstance,\n      stakingInput,\n      stakingTx,\n      babylonAddress,\n      stakerBtcInfo,\n      params,\n      this.getInclusionProof(inclusionProof),\n    );\n\n    this.ee?.emit(\"delegation:register\", {\n      type: \"create-btc-delegation-msg\",\n    });\n\n    return {\n      signedBabylonTx:\n        await this.babylonProvider.signTransaction(delegationMsg),\n    };\n  }\n\n  /**\n   * Estimates the BTC fee required for staking.\n   * @param stakerBtcInfo - The staker BTC info which includes the BTC address\n   * and the no-coord public key in hex format.\n   * @param babylonBtcTipHeight - The BTC tip height recorded on the Babylon\n   * chain.\n   * @param stakingInput - The staking inputs.\n   * @param inputUTXOs - The UTXOs that will be used to pay for the staking\n   * transaction.\n   * @param feeRate - The fee rate in satoshis per byte. Typical value for the\n   * fee rate is above 1. If the fee rate is too low, the transaction will not\n   * be included in a block.\n   * @returns The estimated BTC fee in satoshis.\n   */\n  estimateBtcStakingFee(\n    stakerBtcInfo: StakerInfo,\n    babylonBtcTipHeight: number,\n    stakingInput: StakingInputs,\n    inputUTXOs: UTXO[],\n    feeRate: number,\n  ): number {\n    if (babylonBtcTipHeight === 0) {\n      throw new Error(\"Babylon BTC tip height cannot be 0\");\n    }\n    // Get the param based on the tip height\n    const params = getBabylonParamByBtcHeight(\n      babylonBtcTipHeight,\n      this.stakingParams,\n    );\n\n    const staking = new Staking(\n      this.network,\n      stakerBtcInfo,\n      params,\n      stakingInput.finalityProviderPksNoCoordHex,\n      stakingInput.stakingTimelock,\n    );\n\n    const { fee: stakingFee } = staking.createStakingTransaction(\n      stakingInput.stakingAmountSat,\n      inputUTXOs,\n      feeRate,\n    );\n\n    return stakingFee;\n  }\n\n  /**\n   * Creates a signed staking transaction that is ready to be sent to the BTC\n   * network.\n   * @param stakerBtcInfo - The staker BTC info which includes the BTC address\n   * and the no-coord public key in hex format.\n   * @param stakingInput - The staking inputs.\n   * @param unsignedStakingTx - The unsigned staking transaction.\n   * @param inputUTXOs - The UTXOs that will be used to pay for the staking\n   * transaction.\n   * @param stakingParamsVersion - The params version that was used to create the\n   * delegation in Babylon chain\n   * @returns The signed staking transaction.\n   */\n  async createSignedBtcStakingTransaction(\n    stakerBtcInfo: StakerInfo,\n    stakingInput: StakingInputs,\n    unsignedStakingTx: Transaction,\n    inputUTXOs: UTXO[],\n    stakingParamsVersion: number,\n  ): Promise<Transaction> {\n    const params = getBabylonParamByVersion(\n      stakingParamsVersion,\n      this.stakingParams,\n    );\n\n    if (inputUTXOs.length === 0) {\n      throw new Error(\"No input UTXOs provided\");\n    }\n\n    const staking = new Staking(\n      this.network,\n      stakerBtcInfo,\n      params,\n      stakingInput.finalityProviderPksNoCoordHex,\n      stakingInput.stakingTimelock,\n    );\n\n    const stakingPsbt = staking.toStakingPsbt(unsignedStakingTx, inputUTXOs);\n\n    const contracts: Contract[] = [\n      {\n        id: ContractId.STAKING,\n        params: {\n          stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n          finalityProviders: stakingInput.finalityProviderPksNoCoordHex,\n          covenantPks: params.covenantNoCoordPks,\n          covenantThreshold: params.covenantQuorum,\n          minUnbondingTime: params.unbondingTime,\n          stakingDuration: stakingInput.stakingTimelock,\n        },\n      },\n    ];\n\n    this.ee?.emit(\"delegation:stake\", {\n      stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n      finalityProviders: stakingInput.finalityProviderPksNoCoordHex,\n      covenantPks: params.covenantNoCoordPks,\n      covenantThreshold: params.covenantQuorum,\n      unbondingTimeBlocks: params.unbondingTime,\n      stakingDuration: stakingInput.stakingTimelock,\n      type: \"staking\",\n    });\n\n    const signedStakingPsbtHex = await this.btcProvider.signPsbt(\n      stakingPsbt.toHex(),\n      {\n        contracts,\n        action: {\n          name: ActionName.SIGN_BTC_STAKING_TRANSACTION,\n        },\n      },\n    );\n\n    return Psbt.fromHex(signedStakingPsbtHex).extractTransaction();\n  }\n\n  /**\n   * Creates a partial signed unbonding transaction that is only signed by the\n   * staker. In order to complete the unbonding transaction, the covenant\n   * unbonding signatures need to be added to the transaction before sending it\n   * to the BTC network.\n   * NOTE: This method should only be used for Babylon phase-1 unbonding.\n   * @param stakerBtcInfo - The staker BTC info which includes the BTC address\n   * and the no-coord public key in hex format.\n   * @param stakingInput - The staking inputs.\n   * @param stakingParamsVersion - The params version that was used to create the\n   * delegation in Babylon chain\n   * @param stakingTx - The staking transaction.\n   * @returns The partial signed unbonding transaction and its fee.\n   */\n  async createPartialSignedBtcUnbondingTransaction(\n    stakerBtcInfo: StakerInfo,\n    stakingInput: StakingInputs,\n    stakingParamsVersion: number,\n    stakingTx: Transaction,\n  ): Promise<TransactionResult> {\n    // Get the staking params at the time of the staking transaction\n    const params = getBabylonParamByVersion(\n      stakingParamsVersion,\n      this.stakingParams,\n    );\n\n    const staking = new Staking(\n      this.network,\n      stakerBtcInfo,\n      params,\n      stakingInput.finalityProviderPksNoCoordHex,\n      stakingInput.stakingTimelock,\n    );\n\n    const { transaction: unbondingTx, fee } =\n      staking.createUnbondingTransaction(stakingTx);\n\n    const psbt = staking.toUnbondingPsbt(unbondingTx, stakingTx);\n\n    const contracts: Contract[] = [\n      {\n        id: ContractId.STAKING,\n        params: {\n          stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n          finalityProviders: stakingInput.finalityProviderPksNoCoordHex,\n          covenantPks: params.covenantNoCoordPks,\n          covenantThreshold: params.covenantQuorum,\n          minUnbondingTime: params.unbondingTime,\n          stakingDuration: stakingInput.stakingTimelock,\n        },\n      },\n      {\n        id: ContractId.UNBONDING,\n        params: {\n          stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n          finalityProviders: stakingInput.finalityProviderPksNoCoordHex,\n          covenantPks: params.covenantNoCoordPks,\n          covenantThreshold: params.covenantQuorum,\n          unbondingTimeBlocks: params.unbondingTime,\n          unbondingFeeSat: params.unbondingFeeSat,\n        },\n      },\n    ];\n\n    this.ee?.emit(\"delegation:unbond\", {\n      stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n      finalityProviders: stakingInput.finalityProviderPksNoCoordHex,\n      covenantPks: params.covenantNoCoordPks,\n      covenantThreshold: params.covenantQuorum,\n      stakingDuration: stakingInput.stakingTimelock,\n      unbondingTimeBlocks: params.unbondingTime,\n      unbondingFeeSat: params.unbondingFeeSat,\n      type: \"unbonding\",\n    });\n\n    const signedUnbondingPsbtHex = await this.btcProvider.signPsbt(\n      psbt.toHex(),\n      {\n        contracts,\n        action: {\n          name: ActionName.SIGN_BTC_UNBONDING_TRANSACTION,\n        },\n      },\n    );\n\n    const signedUnbondingTx = Psbt.fromHex(\n      signedUnbondingPsbtHex,\n    ).extractTransaction();\n\n    return {\n      transaction: signedUnbondingTx,\n      fee,\n    };\n  }\n\n  /**\n   * Creates a signed unbonding transaction that is ready to be sent to the BTC\n   * network.\n   * @param stakerBtcInfo - The staker BTC info which includes the BTC address\n   * and the no-coord public key in hex format.\n   * @param stakingInput - The staking inputs.\n   * @param stakingParamsVersion - The params version that was used to create the\n   * delegation in Babylon chain\n   * @param stakingTx - The staking transaction.\n   * @param unsignedUnbondingTx - The unsigned unbonding transaction.\n   * @param covenantUnbondingSignatures - The covenant unbonding signatures.\n   * It can be retrieved from the Babylon chain or API.\n   * @returns The signed unbonding transaction and its fee.\n   */\n  async createSignedBtcUnbondingTransaction(\n    stakerBtcInfo: StakerInfo,\n    stakingInput: StakingInputs,\n    stakingParamsVersion: number,\n    stakingTx: Transaction,\n    unsignedUnbondingTx: Transaction,\n    covenantUnbondingSignatures: {\n      btcPkHex: string;\n      sigHex: string;\n    }[],\n  ): Promise<TransactionResult> {\n    // Get the staking params at the time of the staking transaction\n    const params = getBabylonParamByVersion(\n      stakingParamsVersion,\n      this.stakingParams,\n    );\n\n    const { transaction: signedUnbondingTx, fee } =\n      await this.createPartialSignedBtcUnbondingTransaction(\n        stakerBtcInfo,\n        stakingInput,\n        stakingParamsVersion,\n        stakingTx,\n      );\n\n    // Check the computed txid of the signed unbonding transaction is the same as\n    // the txid of the unsigned unbonding transaction\n    if (signedUnbondingTx.getId() !== unsignedUnbondingTx.getId()) {\n      throw new Error(\n        \"Unbonding transaction hash does not match the computed hash\",\n      );\n    }\n\n    // Add covenant unbonding signatures\n    // Convert the params of covenants to buffer\n    const covenantBuffers = params.covenantNoCoordPks.map((covenant) =>\n      Buffer.from(covenant, \"hex\"),\n    );\n    const witness = createCovenantWitness(\n      // Since unbonding transactions always have a single input and output,\n      // we expect exactly one signature in TaprootScriptSpendSig when the\n      // signing is successful\n      signedUnbondingTx.ins[0].witness,\n      covenantBuffers,\n      covenantUnbondingSignatures,\n      params.covenantQuorum,\n    );\n    // Overwrite the witness to include the covenant unbonding signatures\n    signedUnbondingTx.ins[0].witness = witness;\n\n    return {\n      transaction: signedUnbondingTx,\n      fee,\n    };\n  }\n\n  /**\n   * Creates a signed withdrawal transaction on the unbodning output expiry path\n   * that is ready to be sent to the BTC network.\n   * @param stakingInput - The staking inputs.\n   * @param stakingParamsVersion - The params version that was used to create the\n   * delegation in Babylon chain\n   * @param earlyUnbondingTx - The early unbonding transaction.\n   * @param feeRate - The fee rate in satoshis per byte. Typical value for the\n   * fee rate is above 1. If the fee rate is too low, the transaction will not\n   * be included in a block.\n   * @returns The signed withdrawal transaction and its fee.\n   */\n  async createSignedBtcWithdrawEarlyUnbondedTransaction(\n    stakerBtcInfo: StakerInfo,\n    stakingInput: StakingInputs,\n    stakingParamsVersion: number,\n    earlyUnbondingTx: Transaction,\n    feeRate: number,\n  ): Promise<TransactionResult> {\n    const params = getBabylonParamByVersion(\n      stakingParamsVersion,\n      this.stakingParams,\n    );\n\n    const staking = new Staking(\n      this.network,\n      stakerBtcInfo,\n      params,\n      stakingInput.finalityProviderPksNoCoordHex,\n      stakingInput.stakingTimelock,\n    );\n\n    const { psbt: unbondingPsbt, fee } =\n      staking.createWithdrawEarlyUnbondedTransaction(earlyUnbondingTx, feeRate);\n\n    const contracts: Contract[] = [\n      {\n        id: ContractId.WITHDRAW,\n        params: {\n          stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n          timelockBlocks: params.unbondingTime,\n        },\n      },\n    ];\n\n    this.ee?.emit(\"delegation:withdraw\", {\n      stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n      timelockBlocks: params.unbondingTime,\n      type: \"early-unbonded\",\n    });\n\n    const signedWithdrawalPsbtHex = await this.btcProvider.signPsbt(\n      unbondingPsbt.toHex(),\n      {\n        contracts,\n        action: {\n          name: ActionName.SIGN_BTC_WITHDRAW_TRANSACTION,\n        },\n      },\n    );\n\n    return {\n      transaction: Psbt.fromHex(signedWithdrawalPsbtHex).extractTransaction(),\n      fee,\n    };\n  }\n\n  /**\n   * Creates a signed withdrawal transaction on the staking output expiry path\n   * that is ready to be sent to the BTC network.\n   * @param stakerBtcInfo - The staker BTC info which includes the BTC address\n   * and the no-coord public key in hex format.\n   * @param stakingInput - The staking inputs.\n   * @param stakingParamsVersion - The params version that was used to create the\n   * delegation in Babylon chain\n   * @param stakingTx - The staking transaction.\n   * @param feeRate - The fee rate in satoshis per byte. Typical value for the\n   * fee rate is above 1. If the fee rate is too low, the transaction will not\n   * be included in a block.\n   * @returns The signed withdrawal transaction and its fee.\n   */\n  async createSignedBtcWithdrawStakingExpiredTransaction(\n    stakerBtcInfo: StakerInfo,\n    stakingInput: StakingInputs,\n    stakingParamsVersion: number,\n    stakingTx: Transaction,\n    feeRate: number,\n  ): Promise<TransactionResult> {\n    const params = getBabylonParamByVersion(\n      stakingParamsVersion,\n      this.stakingParams,\n    );\n\n    const staking = new Staking(\n      this.network,\n      stakerBtcInfo,\n      params,\n      stakingInput.finalityProviderPksNoCoordHex,\n      stakingInput.stakingTimelock,\n    );\n\n    const { psbt, fee } = staking.createWithdrawStakingExpiredPsbt(\n      stakingTx,\n      feeRate,\n    );\n\n    const contracts: Contract[] = [\n      {\n        id: ContractId.WITHDRAW,\n        params: {\n          stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n          timelockBlocks: stakingInput.stakingTimelock,\n        },\n      },\n    ];\n\n    this.ee?.emit(\"delegation:withdraw\", {\n      stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n      timelockBlocks: stakingInput.stakingTimelock,\n      type: \"staking-expired\",\n    });\n\n    const signedWithdrawalPsbtHex = await this.btcProvider.signPsbt(\n      psbt.toHex(),\n      {\n        contracts,\n        action: {\n          name: ActionName.SIGN_BTC_WITHDRAW_TRANSACTION,\n        },\n      },\n    );\n\n    return {\n      transaction: Psbt.fromHex(signedWithdrawalPsbtHex).extractTransaction(),\n      fee,\n    };\n  }\n\n  /**\n   * Creates a signed withdrawal transaction for the expired slashing output that\n   * is ready to be sent to the BTC network.\n   * @param stakerBtcInfo - The staker BTC info which includes the BTC address\n   * and the no-coord public key in hex format.\n   * @param stakingInput - The staking inputs.\n   * @param stakingParamsVersion - The params version that was used to create the\n   * delegation in Babylon chain\n   * @param slashingTx - The slashing transaction.\n   * @param feeRate - The fee rate in satoshis per byte. Typical value for the\n   * fee rate is above 1. If the fee rate is too low, the transaction will not\n   * be included in a block.\n   * @returns The signed withdrawal transaction and its fee.\n   */\n  async createSignedBtcWithdrawSlashingTransaction(\n    stakerBtcInfo: StakerInfo,\n    stakingInput: StakingInputs,\n    stakingParamsVersion: number,\n    slashingTx: Transaction,\n    feeRate: number,\n  ): Promise<TransactionResult> {\n    const params = getBabylonParamByVersion(\n      stakingParamsVersion,\n      this.stakingParams,\n    );\n\n    const staking = new Staking(\n      this.network,\n      stakerBtcInfo,\n      params,\n      stakingInput.finalityProviderPksNoCoordHex,\n      stakingInput.stakingTimelock,\n    );\n\n    const { psbt, fee } = staking.createWithdrawSlashingPsbt(\n      slashingTx,\n      feeRate,\n    );\n\n    const contracts: Contract[] = [\n      {\n        id: ContractId.WITHDRAW,\n        params: {\n          stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n          timelockBlocks: params.unbondingTime,\n        },\n      },\n    ];\n\n    this.ee?.emit(\"delegation:withdraw\", {\n      stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n      timelockBlocks: params.unbondingTime,\n      type: \"slashing\",\n    });\n\n    const signedWithrawSlashingPsbtHex = await this.btcProvider.signPsbt(\n      psbt.toHex(),\n      {\n        contracts,\n        action: {\n          name: ActionName.SIGN_BTC_WITHDRAW_TRANSACTION,\n        },\n      },\n    );\n\n    return {\n      transaction: Psbt.fromHex(\n        signedWithrawSlashingPsbtHex,\n      ).extractTransaction(),\n      fee,\n    };\n  }\n\n  /**\n   * Creates a proof of possession for the staker based on ECDSA signature.\n   * @param bech32Address - The staker's bech32 address.\n   * @returns The proof of possession.\n   */\n  async createProofOfPossession(\n    channel: \"delegation:create\" | \"delegation:register\",\n    bech32Address: string,\n    stakerBtcAddress: string,\n  ): Promise<ProofOfPossessionBTC> {\n    let sigType: BTCSigType = BTCSigType.ECDSA;\n\n    // For Taproot or Native SegWit addresses, use the BIP322 signature scheme\n    // in the proof of possession as it uses the same signature type as the regular\n    // input UTXO spend. For legacy addresses, use the ECDSA signature scheme.\n    if (\n      isTaproot(stakerBtcAddress, this.network) ||\n      isNativeSegwit(stakerBtcAddress, this.network)\n    ) {\n      sigType = BTCSigType.BIP322;\n    }\n\n    this.ee?.emit(channel, {\n      bech32Address,\n      type: \"proof-of-possession\",\n    });\n\n    const signedBabylonAddress = await this.btcProvider.signMessage(\n      bech32Address,\n      sigType === BTCSigType.BIP322 ? \"bip322-simple\" : \"ecdsa\",\n    );\n\n    let btcSig: Uint8Array;\n    if (sigType === BTCSigType.BIP322) {\n      const bip322Sig = BIP322Sig.fromPartial({\n        address: stakerBtcAddress,\n        sig: Buffer.from(signedBabylonAddress, \"base64\"),\n      });\n      // Encode the BIP322 protobuf message to a Uint8Array\n      btcSig = BIP322Sig.encode(bip322Sig).finish();\n    } else {\n      // Encode the ECDSA signature to a Uint8Array\n      btcSig = Buffer.from(signedBabylonAddress, \"base64\");\n    }\n\n    return {\n      btcSigType: sigType,\n      btcSig,\n    };\n  }\n\n  /**\n   * Creates the unbonding, slashing, and unbonding slashing transactions and\n   * PSBTs.\n   * @param stakingInstance - The staking instance.\n   * @param stakingTx - The staking transaction.\n   * @returns The unbonding, slashing, and unbonding slashing transactions and\n   * PSBTs.\n   */\n  private async createDelegationTransactionsAndPsbts(\n    stakingInstance: Staking,\n    stakingTx: Transaction,\n  ) {\n    const { transaction: unbondingTx } =\n      stakingInstance.createUnbondingTransaction(stakingTx);\n\n    // Create slashing transactions and extract signatures\n    const { psbt: slashingPsbt } =\n      stakingInstance.createStakingOutputSlashingPsbt(stakingTx);\n\n    const { psbt: unbondingSlashingPsbt } =\n      stakingInstance.createUnbondingOutputSlashingPsbt(unbondingTx);\n\n    return {\n      unbondingTx,\n      slashingPsbt,\n      unbondingSlashingPsbt,\n    };\n  }\n\n  /**\n   * Creates a protobuf message for the BTC delegation.\n   * @param channel - The event channel to emit the message on.\n   * @param stakingInstance - The staking instance.\n   * @param stakingInput - The staking inputs.\n   * @param stakingTx - The staking transaction.\n   * @param bech32Address - The staker's babylon chain bech32 address\n   * @param stakerBtcInfo - The staker's BTC information such as address and\n   * public key\n   * @param params - The staking parameters.\n   * @param inclusionProof - The inclusion proof of the staking transaction.\n   * @returns The protobuf message.\n   */\n  public async createBtcDelegationMsg(\n    channel: \"delegation:create\" | \"delegation:register\",\n    stakingInstance: Staking,\n    stakingInput: StakingInputs,\n    stakingTx: Transaction,\n    bech32Address: string,\n    stakerBtcInfo: StakerInfo,\n    params: StakingParams,\n    inclusionProof?: btcstaking.InclusionProof,\n  ) {\n    if (!params.slashing) {\n      throw new StakingError(\n        StakingErrorCode.INVALID_PARAMS,\n        \"Slashing parameters are required for creating delegation message\",\n      );\n    }\n\n    const { unbondingTx, slashingPsbt, unbondingSlashingPsbt } =\n      await this.createDelegationTransactionsAndPsbts(\n        stakingInstance,\n        stakingTx,\n      );\n\n    const slashingContracts: Contract[] = [\n      {\n        id: ContractId.STAKING,\n        params: {\n          stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n          finalityProviders: stakingInput.finalityProviderPksNoCoordHex,\n          covenantPks: params.covenantNoCoordPks,\n          covenantThreshold: params.covenantQuorum,\n          minUnbondingTime: params.unbondingTime,\n          stakingDuration: stakingInput.stakingTimelock,\n        },\n      },\n      {\n        id: ContractId.SLASHING,\n        params: {\n          stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n          unbondingTimeBlocks: params.unbondingTime,\n          slashingFeeSat: params.slashing.minSlashingTxFeeSat,\n        },\n      },\n      {\n        id: ContractId.SLASHING_BURN,\n        params: {\n          stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n          slashingPkScriptHex: params.slashing.slashingPkScriptHex,\n        },\n      },\n    ];\n\n    // Sign the slashing PSBT\n    this.ee?.emit(channel, {\n      stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n      finalityProviders: stakingInput.finalityProviderPksNoCoordHex,\n      covenantPks: params.covenantNoCoordPks,\n      covenantThreshold: params.covenantQuorum,\n      unbondingTimeBlocks: params.unbondingTime,\n      stakingDuration: stakingInput.stakingTimelock,\n      slashingFeeSat: params.slashing.minSlashingTxFeeSat,\n      slashingPkScriptHex: params.slashing.slashingPkScriptHex,\n      type: \"staking-slashing\",\n    });\n\n    const signedSlashingPsbtHex = await this.btcProvider.signPsbt(\n      slashingPsbt.toHex(),\n      {\n        contracts: slashingContracts,\n        action: {\n          name: ActionName.SIGN_BTC_SLASHING_TRANSACTION,\n        },\n      },\n    );\n\n    const signedSlashingTx = Psbt.fromHex(\n      signedSlashingPsbtHex,\n    ).extractTransaction();\n    const slashingSig =\n      extractFirstSchnorrSignatureFromTransaction(signedSlashingTx);\n    if (!slashingSig) {\n      throw new Error(\"No signature found in the staking output slashing PSBT\");\n    }\n\n    const unbondingSlashingContracts: Contract[] = [\n      {\n        id: ContractId.UNBONDING,\n        params: {\n          stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n          finalityProviders: stakingInput.finalityProviderPksNoCoordHex,\n          covenantPks: params.covenantNoCoordPks,\n          covenantThreshold: params.covenantQuorum,\n          unbondingTimeBlocks: params.unbondingTime,\n          unbondingFeeSat: params.unbondingFeeSat,\n        },\n      },\n      {\n        id: ContractId.SLASHING,\n        params: {\n          stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n          unbondingTimeBlocks: params.unbondingTime,\n          slashingFeeSat: params.slashing.minSlashingTxFeeSat,\n        },\n      },\n      {\n        id: ContractId.SLASHING_BURN,\n        params: {\n          stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n          slashingPkScriptHex: params.slashing.slashingPkScriptHex,\n        },\n      },\n    ];\n\n    // Sign the unbonding slashing PSBT\n    this.ee?.emit(channel, {\n      stakerPk: stakerBtcInfo.publicKeyNoCoordHex,\n      finalityProviders: stakingInput.finalityProviderPksNoCoordHex,\n      covenantPks: params.covenantNoCoordPks,\n      covenantThreshold: params.covenantQuorum,\n      unbondingTimeBlocks: params.unbondingTime,\n      unbondingFeeSat: params.unbondingFeeSat,\n      slashingFeeSat: params.slashing.minSlashingTxFeeSat,\n      slashingPkScriptHex: params.slashing.slashingPkScriptHex,\n      type: \"unbonding-slashing\",\n    });\n\n    const signedUnbondingSlashingPsbtHex = await this.btcProvider.signPsbt(\n      unbondingSlashingPsbt.toHex(),\n      {\n        contracts: unbondingSlashingContracts,\n        action: {\n          name: ActionName.SIGN_BTC_UNBONDING_SLASHING_TRANSACTION,\n        },\n      },\n    );\n\n    const signedUnbondingSlashingTx = Psbt.fromHex(\n      signedUnbondingSlashingPsbtHex,\n    ).extractTransaction();\n    const unbondingSignatures = extractFirstSchnorrSignatureFromTransaction(\n      signedUnbondingSlashingTx,\n    );\n    if (!unbondingSignatures) {\n      throw new Error(\n        \"No signature found in the unbonding output slashing PSBT\",\n      );\n    }\n\n    // Create proof of possession\n    const proofOfPossession = await this.createProofOfPossession(\n      channel,\n      bech32Address,\n      stakerBtcInfo.address,\n    );\n\n    // Prepare the final protobuf message\n    const msg: btcstakingtx.MsgCreateBTCDelegation =\n      btcstakingtx.MsgCreateBTCDelegation.fromPartial({\n        stakerAddr: bech32Address,\n        pop: proofOfPossession,\n        btcPk: Uint8Array.from(\n          Buffer.from(stakerBtcInfo.publicKeyNoCoordHex, \"hex\"),\n        ),\n        fpBtcPkList: stakingInput.finalityProviderPksNoCoordHex.map((pk) =>\n          Uint8Array.from(Buffer.from(pk, \"hex\")),\n        ),\n        stakingTime: stakingInput.stakingTimelock,\n        stakingValue: stakingInput.stakingAmountSat,\n        stakingTx: Uint8Array.from(stakingTx.toBuffer()),\n        slashingTx: Uint8Array.from(\n          Buffer.from(clearTxSignatures(signedSlashingTx).toHex(), \"hex\"),\n        ),\n        delegatorSlashingSig: Uint8Array.from(slashingSig),\n        unbondingTime: params.unbondingTime,\n        unbondingTx: Uint8Array.from(unbondingTx.toBuffer()),\n        unbondingValue: stakingInput.stakingAmountSat - params.unbondingFeeSat,\n        unbondingSlashingTx: Uint8Array.from(\n          Buffer.from(\n            clearTxSignatures(signedUnbondingSlashingTx).toHex(),\n            \"hex\",\n          ),\n        ),\n        delegatorUnbondingSlashingSig: Uint8Array.from(unbondingSignatures),\n        stakingTxInclusionProof: inclusionProof,\n      });\n\n    return {\n      typeUrl: BABYLON_REGISTRY_TYPE_URLS.MsgCreateBTCDelegation,\n      value: msg,\n    };\n  }\n\n  /**\n   * Gets the inclusion proof for the staking transaction.\n   * See the type `InclusionProof` for more information\n   * @param inclusionProof - The inclusion proof.\n   * @returns The inclusion proof.\n   */\n  private getInclusionProof(\n    inclusionProof: InclusionProof,\n  ): btcstaking.InclusionProof {\n    const { pos, merkle, blockHashHex } = inclusionProof;\n    const proofHex = deriveMerkleProof(merkle);\n\n    const hash = reverseBuffer(\n      Uint8Array.from(Buffer.from(blockHashHex, \"hex\")),\n    );\n    const inclusionProofKey: btccheckpoint.TransactionKey =\n      btccheckpoint.TransactionKey.fromPartial({\n        index: pos,\n        hash,\n      });\n    return btcstaking.InclusionProof.fromPartial({\n      key: inclusionProofKey,\n      proof: Uint8Array.from(Buffer.from(proofHex, \"hex\")),\n    });\n  }\n}\n\n/**\n * Extracts the first valid Schnorr signature from a signed transaction.\n *\n * Since we only handle transactions with a single input and request a signature\n * for one public key, there can be at most one signature from the Bitcoin node.\n * A valid Schnorr signature is exactly 64 bytes in length.\n *\n * @param singedTransaction - The signed Bitcoin transaction to extract the signature from\n * @returns The first valid 64-byte Schnorr signature found in the transaction witness data,\n *          or undefined if no valid signature exists\n */\nconst extractFirstSchnorrSignatureFromTransaction = (\n  singedTransaction: Transaction,\n): Buffer | undefined => {\n  // Loop through each input to extract the witness signature\n  for (const input of singedTransaction.ins) {\n    if (input.witness && input.witness.length > 0) {\n      const schnorrSignature = input.witness[0];\n\n      // Check that it's a 64-byte Schnorr signature\n      if (schnorrSignature.length === 64) {\n        return schnorrSignature; // Return the first valid signature found\n      }\n    }\n  }\n  return undefined;\n};\n\n/**\n * Strips all signatures from a transaction by clearing both the script and\n * witness data. This is due to the fact that we only need the raw unsigned\n * transaction structure. The signatures are sent in a separate protobuf field\n * when creating the delegation message in the Babylon.\n * @param tx - The transaction to strip signatures from\n * @returns A copy of the transaction with all signatures removed\n */\nconst clearTxSignatures = (tx: Transaction): Transaction => {\n  tx.ins.forEach((input) => {\n    input.script = Buffer.alloc(0);\n    input.witness = [];\n  });\n  return tx;\n};\n\n/**\n * Derives the merkle proof from the list of hex strings. Note the\n * sibling hashes are reversed from hex before concatenation.\n * @param merkle - The merkle proof hex strings.\n * @returns The merkle proof in hex string format.\n */\nconst deriveMerkleProof = (merkle: string[]) => {\n  const proofHex = merkle.reduce((acc: string, m: string) => {\n    return acc + Buffer.from(m, \"hex\").reverse().toString(\"hex\");\n  }, \"\");\n  return proofHex;\n};\n\n/**\n * Get the staker signature from the unbonding transaction\n * This is used mostly for unbonding transactions from phase-1(Observable)\n * @param unbondingTx - The unbonding transaction\n * @returns The staker signature\n */\nexport const getUnbondingTxStakerSignature = (\n  unbondingTx: Transaction,\n): string => {\n  try {\n    // There is only one input and one output in the unbonding transaction\n    return unbondingTx.ins[0].witness[0].toString(\"hex\");\n  } catch (error) {\n    throw StakingError.fromUnknown(\n      error,\n      StakingErrorCode.INVALID_INPUT,\n      \"Failed to get staker signature\",\n    );\n  }\n};\n", "export const BABYLON_REGISTRY_TYPE_URLS = {\n  MsgCreateBTCDelegation: \"/babylon.btcstaking.v1.MsgCreateBTCDelegation\",\n};\n", "/**\n * Reverses the order of bytes in a buffer.\n * @param buffer - The buffer to reverse.\n * @returns A new buffer with the bytes reversed.\n */\nexport const reverseBuffer = (buffer: Uint8Array): Uint8Array => {\n  const clonedBuffer = new Uint8Array(buffer);\n  if (clonedBuffer.length < 1) return clonedBuffer;\n  for (let i = 0, j = clonedBuffer.length - 1; i < clonedBuffer.length / 2; i++, j--) {\n    let tmp = clonedBuffer[i];\n    clonedBuffer[i] = clonedBuffer[j];\n    clonedBuffer[j] = tmp;\n  }\n  return clonedBuffer;\n};\n\n/**\n * Converts a Uint8Array to a hexadecimal string.\n * @param uint8Array - The Uint8Array to convert.\n * @returns The hexadecimal string.\n */\nexport const uint8ArrayToHex = (uint8Array: Uint8Array): string => {\n  return Array.from(uint8Array)\n    .map((byte) => byte.toString(16).padStart(2, \"0\"))\n    .join(\"\");\n};\n", "import { fromBech32 } from \"@cosmjs/encoding\";\n\n/**\n * Validates a Babylon address. Babylon addresses are encoded in Bech32 format\n * and have a prefix of \"bbn\".\n * @param address - The address to validate.\n * @returns True if the address is valid, false otherwise.\n */\nexport const isValidBabylonAddress = (address: string): boolean => {\n  try {\n    const { prefix } = fromBech32(address);\n    return prefix === \"bbn\";\n  } catch (error) {\n    return false;\n  }\n};\n", "import { StakingParams, VersionedStakingParams } from \"../../types/params\";\n\n/*\n  Get the Babylon params version by BTC height\n  @param height - The BTC height\n  @param babylonParamsVersions - The Babylon params versions\n  @returns The Babylon params\n*/\nexport const getBabylonParamByBtcHeight = (\n  height: number,\n  babylonParamsVersions: VersionedStakingParams[],\n): StakingParams => {\n  // Sort by btcActivationHeight in ascending order\n  const sortedParams = [...babylonParamsVersions].sort(\n    (a, b) => b.btcActivationHeight - a.btcActivationHeight,\n  );\n\n  // Find first params where height is >= btcActivationHeight\n  const params = sortedParams.find(\n    (p) => height >= p.btcActivationHeight,\n  );\n  if (!params) throw new Error(`Babylon params not found for height ${height}`);\n  return params;\n};\n\n/*\n  Get the Babylon params by version\n  @param version - The Babylon params version\n  @param babylonParams - The Babylon params\n  @returns The Babylon params\n*/\nexport const getBabylonParamByVersion = (\n  version: number,\n  babylonParams: VersionedStakingParams[],\n): StakingParams => {\n  const params = babylonParams.find((p) => p.version === version);\n  if (!params) throw new Error(`Babylon params not found for version ${version}`);\n  return params;\n};", "import { opcodes, script } from \"bitcoinjs-lib\";\nimport {\n  MAGIC_BYTES_LEN,\n  StakingScriptData,\n  StakingScripts\n} from \"../stakingScript\";\n\n// Extending StakingScripts to add an extra field\nexport interface ObservableStakingScripts extends StakingScripts {\n  dataEmbedScript: Buffer;\n}\n\nexport class ObservableStakingScriptData extends StakingScriptData {\n  // The magic bytes used to identify the staking transaction on Babylon\n  // through the data return script\n  magicBytes: Buffer;\n  constructor(\n    stakerKey: Buffer,\n    finalityProviderKeys: Buffer[],\n    covenantKeys: Buffer[],\n    covenantThreshold: number,\n    stakingTimelock: number,\n    unbondingTimelock: number,\n    magicBytes: Buffer,\n  ) {\n    super(\n      stakerKey,\n      finalityProviderKeys,\n      covenantKeys,\n      covenantThreshold,\n      stakingTimelock,\n      unbondingTimelock,\n    );\n    if (\n      !magicBytes\n    ) {\n      throw new Error(\"Missing required input values\");\n    }\n    // check that the magic bytes are 4 in length\n    if (magicBytes.length != MAGIC_BYTES_LEN) {\n      throw new Error(\"Invalid script data provided\");\n    }\n\n    this.magicBytes = magicBytes;\n  }\n\n  /**\n   * Builds a data embed script for staking in the form:\n   *    OP_RETURN || <serializedStakingData>\n   * where serializedStakingData is the concatenation of:\n   *    MagicBytes || Version || StakerPublicKey || FinalityProviderPublicKey || StakingTimeLock\n   * Note: Only a single finality provider key is supported for now in phase 1\n   * @throws {Error} If the number of finality provider keys is not equal to 1.\n   * @returns {Buffer} The compiled data embed script.\n   */\n  buildDataEmbedScript(): Buffer {\n    // Only accept a single finality provider key for now\n    if (this.finalityProviderKeys.length != 1) {\n      throw new Error(\"Only a single finality provider key is supported\");\n    }\n    // 1 byte for version\n    const version = Buffer.alloc(1);\n    version.writeUInt8(0);\n    // 2 bytes for staking time\n    const stakingTimeLock = Buffer.alloc(2);\n    // big endian\n    stakingTimeLock.writeUInt16BE(this.stakingTimeLock);\n    const serializedStakingData = Buffer.concat([\n      this.magicBytes,\n      version,\n      this.stakerKey,\n      this.finalityProviderKeys[0],\n      stakingTimeLock,\n    ]);\n    return script.compile([opcodes.OP_RETURN, serializedStakingData]);\n  }\n\n  /**\n   * Builds the staking scripts.\n   * @returns {ObservableStakingScripts} The staking scripts that can be used to stake.\n   * contains the timelockScript, unbondingScript, slashingScript,\n   * unbondingTimelockScript, and dataEmbedScript.\n   * @throws {Error} If script data is invalid.\n   */\n  buildScripts(): ObservableStakingScripts {\n    const scripts = super.buildScripts();\n    return {\n      ...scripts,\n      dataEmbedScript: this.buildDataEmbedScript(),\n    };\n  }\n}\n", "import { ObservableVersionedStakingParams } from \"../../types/params\";\nimport { UTXO } from \"../../types/UTXO\";\nimport { StakingError, StakingErrorCode } from \"../../error\";\nimport { stakingTransaction } from \"../transactions\";\nimport { isTaproot } from \"../../utils/btc\";\nimport { toBuffers, validateStakingTxInputData } from \"../../utils/staking\";\nimport { TransactionResult } from \"../../types/transaction\";\nimport { ObservableStakingScriptData, ObservableStakingScripts } from \"./observableStakingScript\";\nimport { StakerInfo, Staking } from \"..\";\nimport { networks, Psbt, Transaction } from \"bitcoinjs-lib\";\nimport { stakingPsbt } from \"../psbt\";\nexport * from \"./observableStakingScript\";\n\n/**\n * ObservableStaking is a class that provides an interface to create observable\n * staking transactions for the Babylon Staking protocol.\n * \n * The class requires a network and staker information to create staking\n * transactions.\n * The staker information includes the staker's address and \n * public key(without coordinates).\n */\nexport class ObservableStaking extends Staking {\n  params: ObservableVersionedStakingParams;\n  constructor(\n    network: networks.Network,\n    stakerInfo: StakerInfo,\n    params: ObservableVersionedStakingParams,\n    finalityProviderPksNoCoordHex: string[],\n    stakingTimelock: number,\n  ) {\n    super(\n      network,\n      stakerInfo,\n      params,\n      finalityProviderPksNoCoordHex,\n      stakingTimelock,\n    );\n    if (!params.tag) {\n      throw new StakingError(\n        StakingErrorCode.INVALID_INPUT, \n        \"Observable staking parameters must include tag\",\n      );\n    }\n    if (!params.btcActivationHeight) {\n      throw new StakingError(\n        StakingErrorCode.INVALID_INPUT,\n        \"Observable staking parameters must include a positive activation height\",\n      );\n    }\n    // Observable is legacy phase-1 staking which require exactly \n    // one finality provider public key\n    if (finalityProviderPksNoCoordHex.length !== 1) {\n      throw new StakingError(\n        StakingErrorCode.INVALID_INPUT,\n        \"Observable staking requires exactly one finality provider public key\",\n      );\n    }\n    // Override the staking parameters type to ObservableStakingParams\n    this.params = params;\n  }\n  \n  /**\n   * Build the staking scripts for observable staking.\n   * This method overwrites the base method to include the OP_RETURN tag based \n   * on the tag provided in the parameters.\n   * \n   * @returns {ObservableStakingScripts} - The staking scripts for observable staking.\n   * @throws {StakingError} - If the scripts cannot be built.\n   */\n  buildScripts(): ObservableStakingScripts {\n    const { covenantQuorum, covenantNoCoordPks, unbondingTime, tag } = this.params;\n    // Create staking script data\n    let stakingScriptData;\n    try {\n      stakingScriptData = new ObservableStakingScriptData(\n        Buffer.from(this.stakerInfo.publicKeyNoCoordHex, \"hex\"),\n        this.finalityProviderPksNoCoordHex.map((pk) => Buffer.from(pk, \"hex\")),\n        toBuffers(covenantNoCoordPks),\n        covenantQuorum,\n        this.stakingTimelock,\n        unbondingTime,\n        Buffer.from(tag, \"hex\"),\n      );\n    } catch (error: unknown) {\n      throw StakingError.fromUnknown(\n        error, StakingErrorCode.SCRIPT_FAILURE, \n        \"Cannot build staking script data\",\n      );\n    }\n\n    // Build scripts\n    let scripts;\n    try {\n      scripts = stakingScriptData.buildScripts();\n    } catch (error: unknown) {\n      throw StakingError.fromUnknown(\n        error, StakingErrorCode.SCRIPT_FAILURE,\n        \"Cannot build staking scripts\",\n      );\n    }\n    return scripts;\n  }\n\n  /**\n   * Create a staking transaction for observable staking.\n   * This overwrites the method from the Staking class with the addtion\n   * of the \n   * 1. OP_RETURN tag in the staking scripts\n   * 2. lockHeight parameter\n   * \n   * @param {number} stakingAmountSat - The amount to stake in satoshis.\n   * @param {UTXO[]} inputUTXOs - The UTXOs to use as inputs for the staking \n   * transaction.\n   * @param {number} feeRate - The fee rate for the transaction in satoshis per byte.\n   * @returns {TransactionResult} - An object containing the unsigned transaction,\n   * and fee\n   */\n  public createStakingTransaction(\n    stakingAmountSat: number,\n    inputUTXOs: UTXO[],\n    feeRate: number,\n  ): TransactionResult {\n    validateStakingTxInputData(\n      stakingAmountSat,\n      this.stakingTimelock,\n      this.params,\n      inputUTXOs,\n      feeRate,\n    );\n\n    const scripts = this.buildScripts();\n\n    // Create the staking transaction\n    try {\n      const { transaction, fee } = stakingTransaction(\n        scripts,\n        stakingAmountSat,\n        this.stakerInfo.address,\n        inputUTXOs,\n        this.network,\n        feeRate,\n        // `lockHeight` is exclusive of the provided value.\n        // For example, if a Bitcoin height of X is provided,\n        // the transaction will be included starting from height X+1.\n        // https://learnmeabitcoin.com/technical/transaction/locktime/\n        this.params.btcActivationHeight - 1,\n      );\n      \n      return {\n        transaction,\n        fee,\n      };\n    } catch (error: unknown) {\n      throw StakingError.fromUnknown(\n        error, StakingErrorCode.BUILD_TRANSACTION_FAILURE,\n        \"Cannot build unsigned staking transaction\",\n      );\n    }\n  }\n\n  /**\n   * Create a staking psbt for observable staking.\n   * \n   * @param {Transaction} stakingTx - The staking transaction.\n   * @param {UTXO[]} inputUTXOs - The UTXOs to use as inputs for the staking \n   * transaction.\n   * @returns {Psbt} - The psbt.\n   */\n  public toStakingPsbt(\n    stakingTx: Transaction,\n    inputUTXOs: UTXO[],\n  ): Psbt {\n    return stakingPsbt(\n      stakingTx,\n      this.network,\n      inputUTXOs,\n      isTaproot(\n        this.stakerInfo.address, this.network\n      ) ? Buffer.from(this.stakerInfo.publicKeyNoCoordHex, \"hex\") : undefined,\n    );\n  }\n}\n", "/**\n * Base interface for staking parameters that define the rules and constraints\n * for staking operations.\n */\nexport interface StakingParams {\n  covenantNoCoordPks: string[];\n  covenantQuorum: number;\n  unbondingTime: number;\n  unbondingFeeSat: number;\n  maxStakingAmountSat: number;\n  minStakingAmountSat: number;\n  maxStakingTimeBlocks: number;\n  minStakingTimeBlocks: number;\n  slashing?: {\n    slashingPkScriptHex: string;\n    slashingRate: number;\n    minSlashingTxFeeSat: number;\n  }\n}\n\n/**\n * Type for StakingParams where slashing is required\n */\nexport type StakingParamsWithSlashing = StakingParams & {\n  slashing: NonNullable<StakingParams['slashing']>;\n};\n\n/**\n * Type guard to check if slashing exists in StakingParams\n */\nexport function hasSlashing(params: StakingParams): params is StakingParams & { slashing: NonNullable<StakingParams['slashing']> } {\n  return params.slashing !== undefined;\n}\n\n/**\n * Extension of StakingParams that includes activation height and version information.\n * These parameters are used to identify and select the appropriate staking rules at\n * different blockchain heights, but do not affect the actual staking transaction content.\n */\nexport interface VersionedStakingParams extends StakingParams {\n  btcActivationHeight: number;\n  version: number;\n}\n\n/**\n * Extension of VersionedStakingParams that includes a tag field for observability.\n */\nexport interface ObservableVersionedStakingParams extends VersionedStakingParams {\n  tag: string;\n}"],
  "mappings": "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",
  "names": ["import_bitcoinjs_lib", "import_bitcoinjs_lib", "import_bitcoinjs_lib", "BitcoinScriptType", "script", "import_bitcoinjs_lib", "import_bitcoinjs_lib", "import_bitcoinjs_lib", "import_bitcoinjs_lib", "script", "bitcoinScript", "script", "bitcoinScript", "stakingTransaction", "import_bitcoinjs_lib", "address", "stakingPsbt", "unbondingPsbt", "import_bitcoinjs_lib"]
}
