@babylonlabs-io/ts-sdk 0.36.2 → 0.37.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/dist/PayoutManager-BxAY2x0g.cjs +2 -0
  2. package/dist/PayoutManager-BxAY2x0g.cjs.map +1 -0
  3. package/dist/{PayoutManager-s_uH8Uuj.js → PayoutManager-sfxuOBGq.js} +51 -43
  4. package/dist/PayoutManager-sfxuOBGq.js.map +1 -0
  5. package/dist/{PeginManager-CB-dVkT2.js → PeginManager-C7-XYrkK.js} +13 -14
  6. package/dist/{PeginManager-CB-dVkT2.js.map → PeginManager-C7-XYrkK.js.map} +1 -1
  7. package/dist/{PeginManager-BPXVXu8t.cjs → PeginManager-CRuwG4I-.cjs} +2 -2
  8. package/dist/{PeginManager-BPXVXu8t.cjs.map → PeginManager-CRuwG4I-.cjs.map} +1 -1
  9. package/dist/assertPsbtUnsignedTxMatches-BoHwgW30.cjs +2 -0
  10. package/dist/assertPsbtUnsignedTxMatches-BoHwgW30.cjs.map +1 -0
  11. package/dist/assertPsbtUnsignedTxMatches-D7RxpR4A.js +263 -0
  12. package/dist/assertPsbtUnsignedTxMatches-D7RxpR4A.js.map +1 -0
  13. package/dist/{bitcoin-B0S8SHCX.js → bitcoin-B5aNKtsk.js} +77 -60
  14. package/dist/{bitcoin-B0S8SHCX.js.map → bitcoin-B5aNKtsk.js.map} +1 -1
  15. package/dist/bitcoin-CHfKAhcI.cjs +2 -0
  16. package/dist/{bitcoin-B3aqjuMP.cjs.map → bitcoin-CHfKAhcI.cjs.map} +1 -1
  17. package/dist/{buildAndBroadcastRefund-C2VqXiOx.js → buildAndBroadcastRefund-C1eOhIdo.js} +322 -322
  18. package/dist/buildAndBroadcastRefund-C1eOhIdo.js.map +1 -0
  19. package/dist/buildAndBroadcastRefund-_CEDUU5H.cjs +2 -0
  20. package/dist/buildAndBroadcastRefund-_CEDUU5H.cjs.map +1 -0
  21. package/dist/{challengeAssert-Yyyj-EdR.cjs → challengeAssert-BKDS_ADt.cjs} +2 -2
  22. package/dist/{challengeAssert-Yyyj-EdR.cjs.map → challengeAssert-BKDS_ADt.cjs.map} +1 -1
  23. package/dist/{challengeAssert-BzxQmdZy.js → challengeAssert-BXESW00N.js} +7 -7
  24. package/dist/{challengeAssert-BzxQmdZy.js.map → challengeAssert-BXESW00N.js.map} +1 -1
  25. package/dist/fundPeginTransaction-BBE3wTjR.cjs +2 -0
  26. package/dist/{fundPeginTransaction-DaWoYCgO.cjs.map → fundPeginTransaction-BBE3wTjR.cjs.map} +1 -1
  27. package/dist/fundPeginTransaction-t-6TsHAY.js +84 -0
  28. package/dist/{fundPeginTransaction-oV-dNJOU.js.map → fundPeginTransaction-t-6TsHAY.js.map} +1 -1
  29. package/dist/index.cjs +1 -1
  30. package/dist/index.js +174 -166
  31. package/dist/{noPayout-BXeUw0Qq.cjs → noPayout-B6s8vrW6.cjs} +2 -2
  32. package/dist/{noPayout-BXeUw0Qq.cjs.map → noPayout-B6s8vrW6.cjs.map} +1 -1
  33. package/dist/{noPayout-DBX6G96_.js → noPayout-BhgknZBx.js} +2 -2
  34. package/dist/{noPayout-DBX6G96_.js.map → noPayout-BhgknZBx.js.map} +1 -1
  35. package/dist/{peginInput-tbw9BpZy.cjs → peginInput-57FK2O99.cjs} +2 -2
  36. package/dist/{peginInput-tbw9BpZy.cjs.map → peginInput-57FK2O99.cjs.map} +1 -1
  37. package/dist/{peginInput-C2QPvuhR.js → peginInput-CYJzbuwA.js} +3 -3
  38. package/dist/{peginInput-C2QPvuhR.js.map → peginInput-CYJzbuwA.js.map} +1 -1
  39. package/dist/{reservation-CHUGW0F_.js → reservation-CB-4FBPk.js} +37 -36
  40. package/dist/reservation-CB-4FBPk.js.map +1 -0
  41. package/dist/reservation-hjXStM03.cjs +2 -0
  42. package/dist/reservation-hjXStM03.cjs.map +1 -0
  43. package/dist/tbv/core/clients/index.cjs +1 -1
  44. package/dist/tbv/core/clients/index.js +1 -1
  45. package/dist/tbv/core/clients/vault-provider/validators.d.ts.map +1 -1
  46. package/dist/tbv/core/index.cjs +1 -1
  47. package/dist/tbv/core/index.js +172 -164
  48. package/dist/tbv/core/managers/PayoutManager.d.ts.map +1 -1
  49. package/dist/tbv/core/managers/PeginManager.d.ts +7 -8
  50. package/dist/tbv/core/managers/PeginManager.d.ts.map +1 -1
  51. package/dist/tbv/core/managers/index.cjs +1 -1
  52. package/dist/tbv/core/managers/index.js +2 -2
  53. package/dist/tbv/core/primitives/index.cjs +1 -1
  54. package/dist/tbv/core/primitives/index.d.ts +3 -1
  55. package/dist/tbv/core/primitives/index.d.ts.map +1 -1
  56. package/dist/tbv/core/primitives/index.js +31 -27
  57. package/dist/tbv/core/primitives/psbt/__tests__/assertPsbtUnsignedTxMatches.test.d.ts +5 -0
  58. package/dist/tbv/core/primitives/psbt/__tests__/assertPsbtUnsignedTxMatches.test.d.ts.map +1 -0
  59. package/dist/tbv/core/primitives/psbt/assertPsbtUnsignedTxMatches.d.ts +31 -0
  60. package/dist/tbv/core/primitives/psbt/assertPsbtUnsignedTxMatches.d.ts.map +1 -0
  61. package/dist/tbv/core/primitives/psbt/index.d.ts +2 -0
  62. package/dist/tbv/core/primitives/psbt/index.d.ts.map +1 -1
  63. package/dist/tbv/core/primitives/utils/bitcoin.d.ts +33 -3
  64. package/dist/tbv/core/primitives/utils/bitcoin.d.ts.map +1 -1
  65. package/dist/tbv/core/primitives/utils/index.d.ts +1 -1
  66. package/dist/tbv/core/primitives/utils/index.d.ts.map +1 -1
  67. package/dist/tbv/core/services/deposit/runDepositorPresignFlow.d.ts.map +1 -1
  68. package/dist/tbv/core/services/deposit/signDepositorGraph.d.ts.map +1 -1
  69. package/dist/tbv/core/services/index.cjs +1 -1
  70. package/dist/tbv/core/services/index.js +2 -2
  71. package/dist/tbv/core/utils/fee/__tests__/peginFeeMath.test.d.ts +19 -0
  72. package/dist/tbv/core/utils/fee/__tests__/peginFeeMath.test.d.ts.map +1 -0
  73. package/dist/tbv/core/utils/fee/index.d.ts +1 -0
  74. package/dist/tbv/core/utils/fee/index.d.ts.map +1 -1
  75. package/dist/tbv/core/utils/fee/peginFeeMath.d.ts +99 -0
  76. package/dist/tbv/core/utils/fee/peginFeeMath.d.ts.map +1 -0
  77. package/dist/tbv/core/utils/index.cjs +1 -1
  78. package/dist/tbv/core/utils/index.js +44 -40
  79. package/dist/tbv/core/utils/transaction/fundPeginTransaction.d.ts.map +1 -1
  80. package/dist/tbv/core/utils/utxo/reservation.d.ts +4 -1
  81. package/dist/tbv/core/utils/utxo/reservation.d.ts.map +1 -1
  82. package/dist/tbv/core/utils/utxo/selectUtxos.d.ts.map +1 -1
  83. package/dist/tbv/index.cjs +1 -1
  84. package/dist/tbv/index.js +172 -164
  85. package/dist/testing/index.cjs +1 -1
  86. package/dist/testing/index.js +1 -1
  87. package/dist/vault-registry-reader-7gOYnrQD.cjs +2 -0
  88. package/dist/vault-registry-reader-7gOYnrQD.cjs.map +1 -0
  89. package/dist/{vault-registry-reader-CrLodprY.js → vault-registry-reader-Blhu9FW2.js} +130 -125
  90. package/dist/vault-registry-reader-Blhu9FW2.js.map +1 -0
  91. package/dist/waitForTransactionReceiptSmartAware-CmgFXFza.js +265 -0
  92. package/dist/waitForTransactionReceiptSmartAware-CmgFXFza.js.map +1 -0
  93. package/dist/waitForTransactionReceiptSmartAware-tv1mtSIY.cjs +2 -0
  94. package/dist/waitForTransactionReceiptSmartAware-tv1mtSIY.cjs.map +1 -0
  95. package/package.json +1 -1
  96. package/dist/PayoutManager-BhJoQZsG.cjs +0 -2
  97. package/dist/PayoutManager-BhJoQZsG.cjs.map +0 -1
  98. package/dist/PayoutManager-s_uH8Uuj.js.map +0 -1
  99. package/dist/bitcoin-B3aqjuMP.cjs +0 -2
  100. package/dist/buildAndBroadcastRefund-C2VqXiOx.js.map +0 -1
  101. package/dist/buildAndBroadcastRefund-CBIfcF47.cjs +0 -2
  102. package/dist/buildAndBroadcastRefund-CBIfcF47.cjs.map +0 -1
  103. package/dist/fundPeginTransaction-DaWoYCgO.cjs +0 -2
  104. package/dist/fundPeginTransaction-oV-dNJOU.js +0 -76
  105. package/dist/payout-BNFMBXS6.js +0 -193
  106. package/dist/payout-BNFMBXS6.js.map +0 -1
  107. package/dist/payout-DQ_fmJUA.cjs +0 -2
  108. package/dist/payout-DQ_fmJUA.cjs.map +0 -1
  109. package/dist/reservation-CHUGW0F_.js.map +0 -1
  110. package/dist/reservation-ho7mjW3X.cjs +0 -2
  111. package/dist/reservation-ho7mjW3X.cjs.map +0 -1
  112. package/dist/vault-registry-reader-CLnhAUN4.cjs +0 -2
  113. package/dist/vault-registry-reader-CLnhAUN4.cjs.map +0 -1
  114. package/dist/vault-registry-reader-CrLodprY.js.map +0 -1
  115. package/dist/waitForTransactionReceiptSmartAware-Cj_DKm0G.js +0 -217
  116. package/dist/waitForTransactionReceiptSmartAware-Cj_DKm0G.js.map +0 -1
  117. package/dist/waitForTransactionReceiptSmartAware-D9ykVriz.cjs +0 -2
  118. package/dist/waitForTransactionReceiptSmartAware-D9ykVriz.cjs.map +0 -1
@@ -1,2 +1,2 @@
1
- "use strict";const n=require("./bitcoin-B3aqjuMP.cjs"),P=require("@babylonlabs-io/babylon-tbv-rust-wasm"),d=require("buffer"),l=require("bitcoinjs-lib");function y(s){return n.processPublicKeyToXOnly(s).toLowerCase()}function E(s,t,u){const i=new Set;i.add(y(s));for(const r of t)i.add(y(r));return i.delete(y(u)),i.size}const w=2,I=0,m=0;async function H(s){const t=l.Transaction.fromHex(n.stripHexPrefix(s.payoutTxHex)),u=l.Transaction.fromHex(n.stripHexPrefix(s.peginTxHex)),i=l.Transaction.fromHex(n.stripHexPrefix(s.assertTxHex));if(t.ins.length!==w)throw new Error(`Depositor Payout transaction must have exactly ${w} inputs, got ${t.ins.length}`);const r=t.ins[0],c=t.ins[1],a=n.inputTxidHex(r),e=u.getId();if(a!==e||r.index!==I)throw new Error(`Depositor Payout input 0 must spend PegIn:${I}. Expected ${e}:${I}, got ${a}:${r.index}`);const o=n.inputTxidHex(c),p=i.getId();if(o!==p||c.index!==m)throw new Error(`Depositor Payout input 1 must spend Assert:${m}. Expected ${p}:${m}, got ${o}:${c.index}`);const f=u.outs[r.index],T=i.outs[c.index],{payoutScript:h,payoutControlBlock:g}=await P.getPeginPayoutScriptInfo(s.connectorParams),$=n.hexToUint8Array(h),b=n.hexToUint8Array(g),x=new l.Psbt;x.setVersion(t.version),x.setLocktime(t.locktime),x.addInput({hash:r.hash,index:r.index,sequence:r.sequence,witnessUtxo:{script:f.script,value:f.value},tapLeafScript:[{leafVersion:n.TAPSCRIPT_LEAF_VERSION,script:d.Buffer.from($),controlBlock:d.Buffer.from(b)}],tapInternalKey:d.Buffer.from(P.tapInternalPubkey)}),x.addInput({hash:c.hash,index:c.index,sequence:c.sequence,witnessUtxo:{script:T.script,value:T.value}});for(const A of t.outs)x.addOutput({script:A.script,value:A.value});return x.toHex()}async function v(s){const t=l.Transaction.fromHex(n.stripHexPrefix(s.challengeAssertTxHex)),u=l.Transaction.fromHex(n.stripHexPrefix(s.assertTxHex)),i=u.getId();if(s.connectorParamsPerInput.length!==t.ins.length)throw new Error(`Expected ${t.ins.length} connector params, got ${s.connectorParamsPerInput.length}`);const r=new Set;for(let e=0;e<t.ins.length;e++){const o=t.ins[e],p=n.inputTxidHex(o);if(p!==i)throw new Error(`ChallengeAssert input ${e} must spend an Assert output. Expected txid ${i}, got ${p}`);if(!u.outs[o.index])throw new Error(`Assert output ${o.index} not found for ChallengeAssert input ${e} (txid: ${i})`);if(r.has(o.index))throw new Error(`ChallengeAssert input ${e} duplicates Assert output index ${o.index}`);r.add(o.index)}const c=await Promise.all(s.connectorParamsPerInput.map(e=>P.getChallengeAssertScriptInfo(e))),a=new l.Psbt;a.setVersion(t.version),a.setLocktime(t.locktime);for(let e=0;e<t.ins.length;e++){const o=t.ins[e],p=u.outs[o.index],{script:f,controlBlock:T}=c[e],h=n.hexToUint8Array(f),g=n.hexToUint8Array(T);a.addInput({hash:o.hash,index:o.index,sequence:o.sequence,witnessUtxo:{script:p.script,value:p.value},tapLeafScript:[{leafVersion:n.TAPSCRIPT_LEAF_VERSION,script:d.Buffer.from(h),controlBlock:d.Buffer.from(g)}],tapInternalKey:d.Buffer.from(P.tapInternalPubkey)})}for(const e of t.outs)a.addOutput({script:e.script,value:e.value});return a.toHex()}exports.buildChallengeAssertPsbt=v;exports.buildDepositorPayoutPsbt=H;exports.computeNumLocalChallengers=E;
2
- //# sourceMappingURL=challengeAssert-Yyyj-EdR.cjs.map
1
+ "use strict";const n=require("./bitcoin-CHfKAhcI.cjs"),P=require("@babylonlabs-io/babylon-tbv-rust-wasm"),d=require("buffer"),l=require("bitcoinjs-lib");function y(s){return n.processPublicKeyToXOnly(s).toLowerCase()}function E(s,t,u){const i=new Set;i.add(y(s));for(const r of t)i.add(y(r));return i.delete(y(u)),i.size}const w=2,I=0,m=0;async function H(s){const t=l.Transaction.fromHex(n.stripHexPrefix(s.payoutTxHex)),u=l.Transaction.fromHex(n.stripHexPrefix(s.peginTxHex)),i=l.Transaction.fromHex(n.stripHexPrefix(s.assertTxHex));if(t.ins.length!==w)throw new Error(`Depositor Payout transaction must have exactly ${w} inputs, got ${t.ins.length}`);const r=t.ins[0],c=t.ins[1],a=n.inputTxidHex(r),e=u.getId();if(a!==e||r.index!==I)throw new Error(`Depositor Payout input 0 must spend PegIn:${I}. Expected ${e}:${I}, got ${a}:${r.index}`);const o=n.inputTxidHex(c),p=i.getId();if(o!==p||c.index!==m)throw new Error(`Depositor Payout input 1 must spend Assert:${m}. Expected ${p}:${m}, got ${o}:${c.index}`);const f=u.outs[r.index],T=i.outs[c.index],{payoutScript:h,payoutControlBlock:g}=await P.getPeginPayoutScriptInfo(s.connectorParams),$=n.hexToUint8Array(h),b=n.hexToUint8Array(g),x=new l.Psbt;x.setVersion(t.version),x.setLocktime(t.locktime),x.addInput({hash:r.hash,index:r.index,sequence:r.sequence,witnessUtxo:{script:f.script,value:f.value},tapLeafScript:[{leafVersion:n.TAPSCRIPT_LEAF_VERSION,script:d.Buffer.from($),controlBlock:d.Buffer.from(b)}],tapInternalKey:d.Buffer.from(P.tapInternalPubkey)}),x.addInput({hash:c.hash,index:c.index,sequence:c.sequence,witnessUtxo:{script:T.script,value:T.value}});for(const A of t.outs)x.addOutput({script:A.script,value:A.value});return x.toHex()}async function v(s){const t=l.Transaction.fromHex(n.stripHexPrefix(s.challengeAssertTxHex)),u=l.Transaction.fromHex(n.stripHexPrefix(s.assertTxHex)),i=u.getId();if(s.connectorParamsPerInput.length!==t.ins.length)throw new Error(`Expected ${t.ins.length} connector params, got ${s.connectorParamsPerInput.length}`);const r=new Set;for(let e=0;e<t.ins.length;e++){const o=t.ins[e],p=n.inputTxidHex(o);if(p!==i)throw new Error(`ChallengeAssert input ${e} must spend an Assert output. Expected txid ${i}, got ${p}`);if(!u.outs[o.index])throw new Error(`Assert output ${o.index} not found for ChallengeAssert input ${e} (txid: ${i})`);if(r.has(o.index))throw new Error(`ChallengeAssert input ${e} duplicates Assert output index ${o.index}`);r.add(o.index)}const c=await Promise.all(s.connectorParamsPerInput.map(e=>P.getChallengeAssertScriptInfo(e))),a=new l.Psbt;a.setVersion(t.version),a.setLocktime(t.locktime);for(let e=0;e<t.ins.length;e++){const o=t.ins[e],p=u.outs[o.index],{script:f,controlBlock:T}=c[e],h=n.hexToUint8Array(f),g=n.hexToUint8Array(T);a.addInput({hash:o.hash,index:o.index,sequence:o.sequence,witnessUtxo:{script:p.script,value:p.value},tapLeafScript:[{leafVersion:n.TAPSCRIPT_LEAF_VERSION,script:d.Buffer.from(h),controlBlock:d.Buffer.from(g)}],tapInternalKey:d.Buffer.from(P.tapInternalPubkey)})}for(const e of t.outs)a.addOutput({script:e.script,value:e.value});return a.toHex()}exports.buildChallengeAssertPsbt=v;exports.buildDepositorPayoutPsbt=H;exports.computeNumLocalChallengers=E;
2
+ //# sourceMappingURL=challengeAssert-BKDS_ADt.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"challengeAssert-Yyyj-EdR.cjs","sources":["../src/tbv/core/primitives/challengers.ts","../src/tbv/core/primitives/psbt/constants.ts","../src/tbv/core/primitives/psbt/depositorPayout.ts","../src/tbv/core/primitives/psbt/challengeAssert.ts"],"sourcesContent":["/**\n * Challenger counting utilities.\n *\n * Used for UI-level validation (e.g. computing minimum deposit amounts)\n * where the depositor's identity is known. The transaction builders use\n * `vaultKeeperBtcPubkeys.length` to match the VP's current validation.\n */\n\nimport { processPublicKeyToXOnly } from \"./utils/bitcoin\";\n\n/**\n * Normalize a public key to lowercase x-only hex for reliable comparison.\n *\n * Handles `0x` prefixes, compressed (33-byte), and uncompressed (65-byte) keys.\n */\nfunction normalizeKey(key: string): string {\n return processPublicKeyToXOnly(key).toLowerCase();\n}\n\n/**\n * Compute the number of local challengers for a vault.\n *\n * Mirrors the VP's `compute_num_challengers()` logic:\n * local challengers = {vault_provider} ∪ {vault_keepers} − {depositor}\n *\n * Keys are normalized to x-only lowercase hex before comparison, so\n * `0x`-prefixed, compressed, or mixed-case keys are handled correctly.\n *\n * @param vaultProviderPubkey - Vault provider BTC public key\n * @param vaultKeeperPubkeys - Vault keeper BTC public keys\n * @param depositorPubkey - Depositor (claimer) BTC public key\n * @returns Number of local challengers\n */\nexport function computeNumLocalChallengers(\n vaultProviderPubkey: string,\n vaultKeeperPubkeys: string[],\n depositorPubkey: string,\n): number {\n const localSet = new Set<string>();\n localSet.add(normalizeKey(vaultProviderPubkey));\n for (const vk of vaultKeeperPubkeys) {\n localSet.add(normalizeKey(vk));\n }\n localSet.delete(normalizeKey(depositorPubkey));\n return localSet.size;\n}\n","/**\n * Protocol invariants for depositor graph transactions.\n *\n * These indices and counts encode the on-chain vault protocol layout\n * (which output of PegIn/Assert each child transaction spends, and how\n * many inputs each transaction has). Consumed by the PSBT builders and\n * the depositor graph signing service; a drift between copies of these\n * values would silently change validation behaviour.\n *\n * @module primitives/psbt/constants\n * @see btc-vault crates/vault/docs/btc-transactions-spec.md\n */\n\n/**\n * Depositor Payout transaction input count.\n * Input 0: PegIn:0 (signed). Input 1: Assert:0 (in sighash, not signed).\n */\nexport const DEPOSITOR_PAYOUT_INPUT_COUNT = 2;\n\n/** PegIn vault output index spent by the depositor's Payout input 0. */\nexport const PEGIN_VAULT_OUTPUT_INDEX = 0;\n\n/** Payout input index bound to the graph Assert tx (NOT signed). */\nexport const PAYOUT_ASSERT_INPUT_INDEX = 1;\n\n/** Assert output index spent by the depositor's Payout input 1 (NOT signed). */\nexport const ASSERT_PAYOUT_OUTPUT_INDEX = 0;\n\n/** Assert output index spent by NoPayout input 0 (signed). */\nexport const ASSERT_NOPAYOUT_OUTPUT_INDEX = 0;\n","/**\n * Depositor Payout PSBT Builder\n *\n * Builds unsigned PSBTs for the depositor's own Payout transaction\n * (depositor-as-claimer path). The depositor signs input 0 using the\n * payout taproot script from WasmPeginPayoutConnector (PegIn vault UTXO).\n *\n * Input 0 spends PegIn:0 (the vault UTXO) — the same connector used for\n * VP/VK payout signing. The VP verifies this signature using the\n * PeginPayoutConnector's payout script.\n *\n * @module primitives/psbt/depositorPayout\n * @see btc-vault crates/vault/src/sign.rs — verify_depositor_signature / get_payout_tap_leaf_hash\n */\n\nimport {\n type PayoutConnectorParams,\n getPeginPayoutScriptInfo,\n tapInternalPubkey,\n} from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport { Buffer } from \"buffer\";\nimport { Psbt, Transaction } from \"bitcoinjs-lib\";\n\nimport {\n TAPSCRIPT_LEAF_VERSION,\n hexToUint8Array,\n inputTxidHex,\n stripHexPrefix,\n} from \"../utils/bitcoin\";\nimport {\n ASSERT_PAYOUT_OUTPUT_INDEX,\n DEPOSITOR_PAYOUT_INPUT_COUNT,\n PEGIN_VAULT_OUTPUT_INDEX,\n} from \"./constants\";\n\n/**\n * Parameters for building a depositor Payout PSBT\n */\nexport interface DepositorPayoutParams {\n /** Payout transaction hex (unsigned) */\n payoutTxHex: string;\n /** Authoritative PegIn transaction hex — input 0 must spend PegIn:0 */\n peginTxHex: string;\n /** Authoritative Assert transaction hex — input 1 must spend Assert:0 */\n assertTxHex: string;\n /** Parameters for the PeginPayout connector (depositor, VP, VKs, UCs, timelock) */\n connectorParams: PayoutConnectorParams;\n}\n\n/**\n * Build unsigned depositor Payout PSBT.\n *\n * The depositor's payout transaction has 2 inputs:\n * - Input 0: PegIn:0 (vault UTXO) — depositor signs using PeginPayoutConnector payout script\n * - Input 1: Assert:0 — NOT signed by depositor\n *\n * Both inputs must be present in the PSBT because Taproot SIGHASH_DEFAULT\n * commits to all input prevouts. Prevout script_pubkey/value are derived\n * from the authoritative parent transactions, not trusted from external input.\n *\n * @param params - Depositor payout parameters\n * @returns Unsigned PSBT hex ready for signing\n *\n * @throws If the payout transaction does not have exactly 2 inputs\n * @throws If input 0 does not reference peginTxHex at output index 0\n * @throws If input 1 does not reference assertTxHex at output index 0\n */\nexport async function buildDepositorPayoutPsbt(\n params: DepositorPayoutParams,\n): Promise<string> {\n const payoutTx = Transaction.fromHex(stripHexPrefix(params.payoutTxHex));\n const peginTx = Transaction.fromHex(stripHexPrefix(params.peginTxHex));\n const assertTx = Transaction.fromHex(stripHexPrefix(params.assertTxHex));\n\n if (payoutTx.ins.length !== DEPOSITOR_PAYOUT_INPUT_COUNT) {\n throw new Error(\n `Depositor Payout transaction must have exactly ${DEPOSITOR_PAYOUT_INPUT_COUNT} inputs, got ${payoutTx.ins.length}`,\n );\n }\n\n const input0 = payoutTx.ins[0];\n const input1 = payoutTx.ins[1];\n\n const input0Txid = inputTxidHex(input0);\n const peginTxid = peginTx.getId();\n if (input0Txid !== peginTxid || input0.index !== PEGIN_VAULT_OUTPUT_INDEX) {\n throw new Error(\n `Depositor Payout input 0 must spend PegIn:${PEGIN_VAULT_OUTPUT_INDEX}. ` +\n `Expected ${peginTxid}:${PEGIN_VAULT_OUTPUT_INDEX}, got ${input0Txid}:${input0.index}`,\n );\n }\n\n const input1Txid = inputTxidHex(input1);\n const assertTxid = assertTx.getId();\n if (input1Txid !== assertTxid || input1.index !== ASSERT_PAYOUT_OUTPUT_INDEX) {\n throw new Error(\n `Depositor Payout input 1 must spend Assert:${ASSERT_PAYOUT_OUTPUT_INDEX}. ` +\n `Expected ${assertTxid}:${ASSERT_PAYOUT_OUTPUT_INDEX}, got ${input1Txid}:${input1.index}`,\n );\n }\n\n const peginPrevOut = peginTx.outs[input0.index];\n const assertPrevOut = assertTx.outs[input1.index];\n\n const { payoutScript, payoutControlBlock } = await getPeginPayoutScriptInfo(\n params.connectorParams,\n );\n const scriptBytes = hexToUint8Array(payoutScript);\n const controlBlock = hexToUint8Array(payoutControlBlock);\n\n const psbt = new Psbt();\n psbt.setVersion(payoutTx.version);\n psbt.setLocktime(payoutTx.locktime);\n\n psbt.addInput({\n hash: input0.hash,\n index: input0.index,\n sequence: input0.sequence,\n witnessUtxo: {\n script: peginPrevOut.script,\n value: peginPrevOut.value,\n },\n tapLeafScript: [\n {\n leafVersion: TAPSCRIPT_LEAF_VERSION,\n script: Buffer.from(scriptBytes),\n controlBlock: Buffer.from(controlBlock),\n },\n ],\n tapInternalKey: Buffer.from(tapInternalPubkey),\n });\n\n psbt.addInput({\n hash: input1.hash,\n index: input1.index,\n sequence: input1.sequence,\n witnessUtxo: {\n script: assertPrevOut.script,\n value: assertPrevOut.value,\n },\n });\n\n for (const output of payoutTx.outs) {\n psbt.addOutput({\n script: output.script,\n value: output.value,\n });\n }\n\n return psbt.toHex();\n}\n","/**\n * ChallengeAssert PSBT Builder\n *\n * Builds an unsigned PSBT for a ChallengeAssert transaction\n * (depositor-as-claimer path, per challenger). The ChallengeAssert tx has\n * NUM_UTXOS_FOR_CHALLENGE_ASSERT (3) inputs, each spending a different Assert\n * output segment. The depositor signs ALL inputs, each with its own taproot\n * script derived from the per-segment connector params.\n *\n * @module primitives/psbt/challengeAssert\n * @see btc-vault crates/vault/docs/btc-transactions-spec.md — ChallengeAssert connector (NUM_UTXOS_FOR_CHALLENGE_ASSERT=3)\n */\n\nimport {\n type ChallengeAssertConnectorParams,\n getChallengeAssertScriptInfo,\n tapInternalPubkey,\n} from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport { Buffer } from \"buffer\";\nimport { Psbt, Transaction } from \"bitcoinjs-lib\";\n\nimport {\n TAPSCRIPT_LEAF_VERSION,\n hexToUint8Array,\n inputTxidHex,\n stripHexPrefix,\n} from \"../utils/bitcoin\";\n\n/**\n * Parameters for building a ChallengeAssert PSBT\n */\nexport interface ChallengeAssertParams {\n /** ChallengeAssert transaction hex (unsigned) */\n challengeAssertTxHex: string;\n /** Authoritative Assert transaction hex — every input must spend an Assert output */\n assertTxHex: string;\n /** Per-input connector params (one per input/segment, determines the taproot script) */\n connectorParamsPerInput: ChallengeAssertConnectorParams[];\n}\n\n/**\n * Build unsigned ChallengeAssert PSBT.\n *\n * The ChallengeAssert transaction has 3 inputs (one per Assert output segment).\n * Each input has its own taproot script derived from its connector params.\n * The depositor signs all inputs. Every prevout is derived from the\n * authoritative Assert transaction, never trusted from external input.\n *\n * @param params - ChallengeAssert parameters\n * @returns Unsigned PSBT hex ready for signing\n *\n * @throws If the number of connector params does not match the number of inputs\n * @throws If any input does not reference assertTxHex\n * @throws If any referenced Assert output is missing\n * @throws If two inputs reference the same Assert output index\n */\nexport async function buildChallengeAssertPsbt(\n params: ChallengeAssertParams,\n): Promise<string> {\n const challengeAssertTx = Transaction.fromHex(\n stripHexPrefix(params.challengeAssertTxHex),\n );\n const assertTx = Transaction.fromHex(stripHexPrefix(params.assertTxHex));\n const assertTxid = assertTx.getId();\n\n if (params.connectorParamsPerInput.length !== challengeAssertTx.ins.length) {\n throw new Error(\n `Expected ${challengeAssertTx.ins.length} connector params, got ${params.connectorParamsPerInput.length}`,\n );\n }\n\n const seenAssertOutputs = new Set<number>();\n for (let i = 0; i < challengeAssertTx.ins.length; i++) {\n const input = challengeAssertTx.ins[i];\n const inputTxid = inputTxidHex(input);\n if (inputTxid !== assertTxid) {\n throw new Error(\n `ChallengeAssert input ${i} must spend an Assert output. ` +\n `Expected txid ${assertTxid}, got ${inputTxid}`,\n );\n }\n if (!assertTx.outs[input.index]) {\n throw new Error(\n `Assert output ${input.index} not found for ChallengeAssert input ${i} (txid: ${assertTxid})`,\n );\n }\n if (seenAssertOutputs.has(input.index)) {\n throw new Error(\n `ChallengeAssert input ${i} duplicates Assert output index ${input.index}`,\n );\n }\n seenAssertOutputs.add(input.index);\n }\n\n const scriptInfos = await Promise.all(\n params.connectorParamsPerInput.map((cp) => getChallengeAssertScriptInfo(cp)),\n );\n\n const psbt = new Psbt();\n psbt.setVersion(challengeAssertTx.version);\n psbt.setLocktime(challengeAssertTx.locktime);\n\n for (let i = 0; i < challengeAssertTx.ins.length; i++) {\n const input = challengeAssertTx.ins[i];\n const assertPrevOut = assertTx.outs[input.index];\n\n const { script, controlBlock } = scriptInfos[i];\n const scriptBytes = hexToUint8Array(script);\n const controlBlockBytes = hexToUint8Array(controlBlock);\n\n psbt.addInput({\n hash: input.hash,\n index: input.index,\n sequence: input.sequence,\n witnessUtxo: {\n script: assertPrevOut.script,\n value: assertPrevOut.value,\n },\n tapLeafScript: [\n {\n leafVersion: TAPSCRIPT_LEAF_VERSION,\n script: Buffer.from(scriptBytes),\n controlBlock: Buffer.from(controlBlockBytes),\n },\n ],\n tapInternalKey: Buffer.from(tapInternalPubkey),\n });\n }\n\n for (const output of challengeAssertTx.outs) {\n psbt.addOutput({\n script: output.script,\n value: output.value,\n });\n }\n\n return psbt.toHex();\n}\n"],"names":["normalizeKey","key","processPublicKeyToXOnly","computeNumLocalChallengers","vaultProviderPubkey","vaultKeeperPubkeys","depositorPubkey","localSet","vk","DEPOSITOR_PAYOUT_INPUT_COUNT","PEGIN_VAULT_OUTPUT_INDEX","ASSERT_PAYOUT_OUTPUT_INDEX","buildDepositorPayoutPsbt","params","payoutTx","Transaction","stripHexPrefix","peginTx","assertTx","input0","input1","input0Txid","inputTxidHex","peginTxid","input1Txid","assertTxid","peginPrevOut","assertPrevOut","payoutScript","payoutControlBlock","getPeginPayoutScriptInfo","scriptBytes","hexToUint8Array","controlBlock","psbt","Psbt","TAPSCRIPT_LEAF_VERSION","Buffer","tapInternalPubkey","output","buildChallengeAssertPsbt","challengeAssertTx","seenAssertOutputs","i","input","inputTxid","scriptInfos","cp","getChallengeAssertScriptInfo","script","controlBlockBytes"],"mappings":"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"}
1
+ {"version":3,"file":"challengeAssert-BKDS_ADt.cjs","sources":["../src/tbv/core/primitives/challengers.ts","../src/tbv/core/primitives/psbt/constants.ts","../src/tbv/core/primitives/psbt/depositorPayout.ts","../src/tbv/core/primitives/psbt/challengeAssert.ts"],"sourcesContent":["/**\n * Challenger counting utilities.\n *\n * Used for UI-level validation (e.g. computing minimum deposit amounts)\n * where the depositor's identity is known. The transaction builders use\n * `vaultKeeperBtcPubkeys.length` to match the VP's current validation.\n */\n\nimport { processPublicKeyToXOnly } from \"./utils/bitcoin\";\n\n/**\n * Normalize a public key to lowercase x-only hex for reliable comparison.\n *\n * Handles `0x` prefixes, compressed (33-byte), and uncompressed (65-byte) keys.\n */\nfunction normalizeKey(key: string): string {\n return processPublicKeyToXOnly(key).toLowerCase();\n}\n\n/**\n * Compute the number of local challengers for a vault.\n *\n * Mirrors the VP's `compute_num_challengers()` logic:\n * local challengers = {vault_provider} ∪ {vault_keepers} − {depositor}\n *\n * Keys are normalized to x-only lowercase hex before comparison, so\n * `0x`-prefixed, compressed, or mixed-case keys are handled correctly.\n *\n * @param vaultProviderPubkey - Vault provider BTC public key\n * @param vaultKeeperPubkeys - Vault keeper BTC public keys\n * @param depositorPubkey - Depositor (claimer) BTC public key\n * @returns Number of local challengers\n */\nexport function computeNumLocalChallengers(\n vaultProviderPubkey: string,\n vaultKeeperPubkeys: string[],\n depositorPubkey: string,\n): number {\n const localSet = new Set<string>();\n localSet.add(normalizeKey(vaultProviderPubkey));\n for (const vk of vaultKeeperPubkeys) {\n localSet.add(normalizeKey(vk));\n }\n localSet.delete(normalizeKey(depositorPubkey));\n return localSet.size;\n}\n","/**\n * Protocol invariants for depositor graph transactions.\n *\n * These indices and counts encode the on-chain vault protocol layout\n * (which output of PegIn/Assert each child transaction spends, and how\n * many inputs each transaction has). Consumed by the PSBT builders and\n * the depositor graph signing service; a drift between copies of these\n * values would silently change validation behaviour.\n *\n * @module primitives/psbt/constants\n * @see btc-vault crates/vault/docs/btc-transactions-spec.md\n */\n\n/**\n * Depositor Payout transaction input count.\n * Input 0: PegIn:0 (signed). Input 1: Assert:0 (in sighash, not signed).\n */\nexport const DEPOSITOR_PAYOUT_INPUT_COUNT = 2;\n\n/** PegIn vault output index spent by the depositor's Payout input 0. */\nexport const PEGIN_VAULT_OUTPUT_INDEX = 0;\n\n/** Payout input index bound to the graph Assert tx (NOT signed). */\nexport const PAYOUT_ASSERT_INPUT_INDEX = 1;\n\n/** Assert output index spent by the depositor's Payout input 1 (NOT signed). */\nexport const ASSERT_PAYOUT_OUTPUT_INDEX = 0;\n\n/** Assert output index spent by NoPayout input 0 (signed). */\nexport const ASSERT_NOPAYOUT_OUTPUT_INDEX = 0;\n","/**\n * Depositor Payout PSBT Builder\n *\n * Builds unsigned PSBTs for the depositor's own Payout transaction\n * (depositor-as-claimer path). The depositor signs input 0 using the\n * payout taproot script from WasmPeginPayoutConnector (PegIn vault UTXO).\n *\n * Input 0 spends PegIn:0 (the vault UTXO) — the same connector used for\n * VP/VK payout signing. The VP verifies this signature using the\n * PeginPayoutConnector's payout script.\n *\n * @module primitives/psbt/depositorPayout\n * @see btc-vault crates/vault/src/sign.rs — verify_depositor_signature / get_payout_tap_leaf_hash\n */\n\nimport {\n type PayoutConnectorParams,\n getPeginPayoutScriptInfo,\n tapInternalPubkey,\n} from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport { Buffer } from \"buffer\";\nimport { Psbt, Transaction } from \"bitcoinjs-lib\";\n\nimport {\n TAPSCRIPT_LEAF_VERSION,\n hexToUint8Array,\n inputTxidHex,\n stripHexPrefix,\n} from \"../utils/bitcoin\";\nimport {\n ASSERT_PAYOUT_OUTPUT_INDEX,\n DEPOSITOR_PAYOUT_INPUT_COUNT,\n PEGIN_VAULT_OUTPUT_INDEX,\n} from \"./constants\";\n\n/**\n * Parameters for building a depositor Payout PSBT\n */\nexport interface DepositorPayoutParams {\n /** Payout transaction hex (unsigned) */\n payoutTxHex: string;\n /** Authoritative PegIn transaction hex — input 0 must spend PegIn:0 */\n peginTxHex: string;\n /** Authoritative Assert transaction hex — input 1 must spend Assert:0 */\n assertTxHex: string;\n /** Parameters for the PeginPayout connector (depositor, VP, VKs, UCs, timelock) */\n connectorParams: PayoutConnectorParams;\n}\n\n/**\n * Build unsigned depositor Payout PSBT.\n *\n * The depositor's payout transaction has 2 inputs:\n * - Input 0: PegIn:0 (vault UTXO) — depositor signs using PeginPayoutConnector payout script\n * - Input 1: Assert:0 — NOT signed by depositor\n *\n * Both inputs must be present in the PSBT because Taproot SIGHASH_DEFAULT\n * commits to all input prevouts. Prevout script_pubkey/value are derived\n * from the authoritative parent transactions, not trusted from external input.\n *\n * @param params - Depositor payout parameters\n * @returns Unsigned PSBT hex ready for signing\n *\n * @throws If the payout transaction does not have exactly 2 inputs\n * @throws If input 0 does not reference peginTxHex at output index 0\n * @throws If input 1 does not reference assertTxHex at output index 0\n */\nexport async function buildDepositorPayoutPsbt(\n params: DepositorPayoutParams,\n): Promise<string> {\n const payoutTx = Transaction.fromHex(stripHexPrefix(params.payoutTxHex));\n const peginTx = Transaction.fromHex(stripHexPrefix(params.peginTxHex));\n const assertTx = Transaction.fromHex(stripHexPrefix(params.assertTxHex));\n\n if (payoutTx.ins.length !== DEPOSITOR_PAYOUT_INPUT_COUNT) {\n throw new Error(\n `Depositor Payout transaction must have exactly ${DEPOSITOR_PAYOUT_INPUT_COUNT} inputs, got ${payoutTx.ins.length}`,\n );\n }\n\n const input0 = payoutTx.ins[0];\n const input1 = payoutTx.ins[1];\n\n const input0Txid = inputTxidHex(input0);\n const peginTxid = peginTx.getId();\n if (input0Txid !== peginTxid || input0.index !== PEGIN_VAULT_OUTPUT_INDEX) {\n throw new Error(\n `Depositor Payout input 0 must spend PegIn:${PEGIN_VAULT_OUTPUT_INDEX}. ` +\n `Expected ${peginTxid}:${PEGIN_VAULT_OUTPUT_INDEX}, got ${input0Txid}:${input0.index}`,\n );\n }\n\n const input1Txid = inputTxidHex(input1);\n const assertTxid = assertTx.getId();\n if (input1Txid !== assertTxid || input1.index !== ASSERT_PAYOUT_OUTPUT_INDEX) {\n throw new Error(\n `Depositor Payout input 1 must spend Assert:${ASSERT_PAYOUT_OUTPUT_INDEX}. ` +\n `Expected ${assertTxid}:${ASSERT_PAYOUT_OUTPUT_INDEX}, got ${input1Txid}:${input1.index}`,\n );\n }\n\n const peginPrevOut = peginTx.outs[input0.index];\n const assertPrevOut = assertTx.outs[input1.index];\n\n const { payoutScript, payoutControlBlock } = await getPeginPayoutScriptInfo(\n params.connectorParams,\n );\n const scriptBytes = hexToUint8Array(payoutScript);\n const controlBlock = hexToUint8Array(payoutControlBlock);\n\n const psbt = new Psbt();\n psbt.setVersion(payoutTx.version);\n psbt.setLocktime(payoutTx.locktime);\n\n psbt.addInput({\n hash: input0.hash,\n index: input0.index,\n sequence: input0.sequence,\n witnessUtxo: {\n script: peginPrevOut.script,\n value: peginPrevOut.value,\n },\n tapLeafScript: [\n {\n leafVersion: TAPSCRIPT_LEAF_VERSION,\n script: Buffer.from(scriptBytes),\n controlBlock: Buffer.from(controlBlock),\n },\n ],\n tapInternalKey: Buffer.from(tapInternalPubkey),\n });\n\n psbt.addInput({\n hash: input1.hash,\n index: input1.index,\n sequence: input1.sequence,\n witnessUtxo: {\n script: assertPrevOut.script,\n value: assertPrevOut.value,\n },\n });\n\n for (const output of payoutTx.outs) {\n psbt.addOutput({\n script: output.script,\n value: output.value,\n });\n }\n\n return psbt.toHex();\n}\n","/**\n * ChallengeAssert PSBT Builder\n *\n * Builds an unsigned PSBT for a ChallengeAssert transaction\n * (depositor-as-claimer path, per challenger). The ChallengeAssert tx has\n * NUM_UTXOS_FOR_CHALLENGE_ASSERT (3) inputs, each spending a different Assert\n * output segment. The depositor signs ALL inputs, each with its own taproot\n * script derived from the per-segment connector params.\n *\n * @module primitives/psbt/challengeAssert\n * @see btc-vault crates/vault/docs/btc-transactions-spec.md — ChallengeAssert connector (NUM_UTXOS_FOR_CHALLENGE_ASSERT=3)\n */\n\nimport {\n type ChallengeAssertConnectorParams,\n getChallengeAssertScriptInfo,\n tapInternalPubkey,\n} from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport { Buffer } from \"buffer\";\nimport { Psbt, Transaction } from \"bitcoinjs-lib\";\n\nimport {\n TAPSCRIPT_LEAF_VERSION,\n hexToUint8Array,\n inputTxidHex,\n stripHexPrefix,\n} from \"../utils/bitcoin\";\n\n/**\n * Parameters for building a ChallengeAssert PSBT\n */\nexport interface ChallengeAssertParams {\n /** ChallengeAssert transaction hex (unsigned) */\n challengeAssertTxHex: string;\n /** Authoritative Assert transaction hex — every input must spend an Assert output */\n assertTxHex: string;\n /** Per-input connector params (one per input/segment, determines the taproot script) */\n connectorParamsPerInput: ChallengeAssertConnectorParams[];\n}\n\n/**\n * Build unsigned ChallengeAssert PSBT.\n *\n * The ChallengeAssert transaction has 3 inputs (one per Assert output segment).\n * Each input has its own taproot script derived from its connector params.\n * The depositor signs all inputs. Every prevout is derived from the\n * authoritative Assert transaction, never trusted from external input.\n *\n * @param params - ChallengeAssert parameters\n * @returns Unsigned PSBT hex ready for signing\n *\n * @throws If the number of connector params does not match the number of inputs\n * @throws If any input does not reference assertTxHex\n * @throws If any referenced Assert output is missing\n * @throws If two inputs reference the same Assert output index\n */\nexport async function buildChallengeAssertPsbt(\n params: ChallengeAssertParams,\n): Promise<string> {\n const challengeAssertTx = Transaction.fromHex(\n stripHexPrefix(params.challengeAssertTxHex),\n );\n const assertTx = Transaction.fromHex(stripHexPrefix(params.assertTxHex));\n const assertTxid = assertTx.getId();\n\n if (params.connectorParamsPerInput.length !== challengeAssertTx.ins.length) {\n throw new Error(\n `Expected ${challengeAssertTx.ins.length} connector params, got ${params.connectorParamsPerInput.length}`,\n );\n }\n\n const seenAssertOutputs = new Set<number>();\n for (let i = 0; i < challengeAssertTx.ins.length; i++) {\n const input = challengeAssertTx.ins[i];\n const inputTxid = inputTxidHex(input);\n if (inputTxid !== assertTxid) {\n throw new Error(\n `ChallengeAssert input ${i} must spend an Assert output. ` +\n `Expected txid ${assertTxid}, got ${inputTxid}`,\n );\n }\n if (!assertTx.outs[input.index]) {\n throw new Error(\n `Assert output ${input.index} not found for ChallengeAssert input ${i} (txid: ${assertTxid})`,\n );\n }\n if (seenAssertOutputs.has(input.index)) {\n throw new Error(\n `ChallengeAssert input ${i} duplicates Assert output index ${input.index}`,\n );\n }\n seenAssertOutputs.add(input.index);\n }\n\n const scriptInfos = await Promise.all(\n params.connectorParamsPerInput.map((cp) => getChallengeAssertScriptInfo(cp)),\n );\n\n const psbt = new Psbt();\n psbt.setVersion(challengeAssertTx.version);\n psbt.setLocktime(challengeAssertTx.locktime);\n\n for (let i = 0; i < challengeAssertTx.ins.length; i++) {\n const input = challengeAssertTx.ins[i];\n const assertPrevOut = assertTx.outs[input.index];\n\n const { script, controlBlock } = scriptInfos[i];\n const scriptBytes = hexToUint8Array(script);\n const controlBlockBytes = hexToUint8Array(controlBlock);\n\n psbt.addInput({\n hash: input.hash,\n index: input.index,\n sequence: input.sequence,\n witnessUtxo: {\n script: assertPrevOut.script,\n value: assertPrevOut.value,\n },\n tapLeafScript: [\n {\n leafVersion: TAPSCRIPT_LEAF_VERSION,\n script: Buffer.from(scriptBytes),\n controlBlock: Buffer.from(controlBlockBytes),\n },\n ],\n tapInternalKey: Buffer.from(tapInternalPubkey),\n });\n }\n\n for (const output of challengeAssertTx.outs) {\n psbt.addOutput({\n script: output.script,\n value: output.value,\n });\n }\n\n return psbt.toHex();\n}\n"],"names":["normalizeKey","key","processPublicKeyToXOnly","computeNumLocalChallengers","vaultProviderPubkey","vaultKeeperPubkeys","depositorPubkey","localSet","vk","DEPOSITOR_PAYOUT_INPUT_COUNT","PEGIN_VAULT_OUTPUT_INDEX","ASSERT_PAYOUT_OUTPUT_INDEX","buildDepositorPayoutPsbt","params","payoutTx","Transaction","stripHexPrefix","peginTx","assertTx","input0","input1","input0Txid","inputTxidHex","peginTxid","input1Txid","assertTxid","peginPrevOut","assertPrevOut","payoutScript","payoutControlBlock","getPeginPayoutScriptInfo","scriptBytes","hexToUint8Array","controlBlock","psbt","Psbt","TAPSCRIPT_LEAF_VERSION","Buffer","tapInternalPubkey","output","buildChallengeAssertPsbt","challengeAssertTx","seenAssertOutputs","i","input","inputTxid","scriptInfos","cp","getChallengeAssertScriptInfo","script","controlBlockBytes"],"mappings":"yJAeA,SAASA,EAAaC,EAAqB,CACzC,OAAOC,EAAAA,wBAAwBD,CAAG,EAAE,YAAA,CACtC,CAgBO,SAASE,EACdC,EACAC,EACAC,EACQ,CACR,MAAMC,MAAe,IACrBA,EAAS,IAAIP,EAAaI,CAAmB,CAAC,EAC9C,UAAWI,KAAMH,EACfE,EAAS,IAAIP,EAAaQ,CAAE,CAAC,EAE/B,OAAAD,EAAS,OAAOP,EAAaM,CAAe,CAAC,EACtCC,EAAS,IAClB,CC5BO,MAAME,EAA+B,EAG/BC,EAA2B,EAM3BC,EAA6B,ECyC1C,eAAsBC,EACpBC,EACiB,CACjB,MAAMC,EAAWC,EAAAA,YAAY,QAAQC,EAAAA,eAAeH,EAAO,WAAW,CAAC,EACjEI,EAAUF,EAAAA,YAAY,QAAQC,EAAAA,eAAeH,EAAO,UAAU,CAAC,EAC/DK,EAAWH,EAAAA,YAAY,QAAQC,EAAAA,eAAeH,EAAO,WAAW,CAAC,EAEvE,GAAIC,EAAS,IAAI,SAAWL,EAC1B,MAAM,IAAI,MACR,kDAAkDA,CAA4B,gBAAgBK,EAAS,IAAI,MAAM,EAAA,EAIrH,MAAMK,EAASL,EAAS,IAAI,CAAC,EACvBM,EAASN,EAAS,IAAI,CAAC,EAEvBO,EAAaC,EAAAA,aAAaH,CAAM,EAChCI,EAAYN,EAAQ,MAAA,EAC1B,GAAII,IAAeE,GAAaJ,EAAO,QAAUT,EAC/C,MAAM,IAAI,MACR,6CAA6CA,CAAwB,cACvDa,CAAS,IAAIb,CAAwB,SAASW,CAAU,IAAIF,EAAO,KAAK,EAAA,EAI1F,MAAMK,EAAaF,EAAAA,aAAaF,CAAM,EAChCK,EAAaP,EAAS,MAAA,EAC5B,GAAIM,IAAeC,GAAcL,EAAO,QAAUT,EAChD,MAAM,IAAI,MACR,8CAA8CA,CAA0B,cAC1Dc,CAAU,IAAId,CAA0B,SAASa,CAAU,IAAIJ,EAAO,KAAK,EAAA,EAI7F,MAAMM,EAAeT,EAAQ,KAAKE,EAAO,KAAK,EACxCQ,EAAgBT,EAAS,KAAKE,EAAO,KAAK,EAE1C,CAAE,aAAAQ,EAAc,mBAAAC,CAAA,EAAuB,MAAMC,EAAAA,yBACjDjB,EAAO,eAAA,EAEHkB,EAAcC,EAAAA,gBAAgBJ,CAAY,EAC1CK,EAAeD,EAAAA,gBAAgBH,CAAkB,EAEjDK,EAAO,IAAIC,OACjBD,EAAK,WAAWpB,EAAS,OAAO,EAChCoB,EAAK,YAAYpB,EAAS,QAAQ,EAElCoB,EAAK,SAAS,CACZ,KAAMf,EAAO,KACb,MAAOA,EAAO,MACd,SAAUA,EAAO,SACjB,YAAa,CACX,OAAQO,EAAa,OACrB,MAAOA,EAAa,KAAA,EAEtB,cAAe,CACb,CACE,YAAaU,EAAAA,uBACb,OAAQC,EAAAA,OAAO,KAAKN,CAAW,EAC/B,aAAcM,EAAAA,OAAO,KAAKJ,CAAY,CAAA,CACxC,EAEF,eAAgBI,EAAAA,OAAO,KAAKC,EAAAA,iBAAiB,CAAA,CAC9C,EAEDJ,EAAK,SAAS,CACZ,KAAMd,EAAO,KACb,MAAOA,EAAO,MACd,SAAUA,EAAO,SACjB,YAAa,CACX,OAAQO,EAAc,OACtB,MAAOA,EAAc,KAAA,CACvB,CACD,EAED,UAAWY,KAAUzB,EAAS,KAC5BoB,EAAK,UAAU,CACb,OAAQK,EAAO,OACf,MAAOA,EAAO,KAAA,CACf,EAGH,OAAOL,EAAK,MAAA,CACd,CC9FA,eAAsBM,EACpB3B,EACiB,CACjB,MAAM4B,EAAoB1B,EAAAA,YAAY,QACpCC,EAAAA,eAAeH,EAAO,oBAAoB,CAAA,EAEtCK,EAAWH,EAAAA,YAAY,QAAQC,EAAAA,eAAeH,EAAO,WAAW,CAAC,EACjEY,EAAaP,EAAS,MAAA,EAE5B,GAAIL,EAAO,wBAAwB,SAAW4B,EAAkB,IAAI,OAClE,MAAM,IAAI,MACR,YAAYA,EAAkB,IAAI,MAAM,0BAA0B5B,EAAO,wBAAwB,MAAM,EAAA,EAI3G,MAAM6B,MAAwB,IAC9B,QAASC,EAAI,EAAGA,EAAIF,EAAkB,IAAI,OAAQE,IAAK,CACrD,MAAMC,EAAQH,EAAkB,IAAIE,CAAC,EAC/BE,EAAYvB,EAAAA,aAAasB,CAAK,EACpC,GAAIC,IAAcpB,EAChB,MAAM,IAAI,MACR,yBAAyBkB,CAAC,+CACPlB,CAAU,SAASoB,CAAS,EAAA,EAGnD,GAAI,CAAC3B,EAAS,KAAK0B,EAAM,KAAK,EAC5B,MAAM,IAAI,MACR,iBAAiBA,EAAM,KAAK,wCAAwCD,CAAC,WAAWlB,CAAU,GAAA,EAG9F,GAAIiB,EAAkB,IAAIE,EAAM,KAAK,EACnC,MAAM,IAAI,MACR,yBAAyBD,CAAC,mCAAmCC,EAAM,KAAK,EAAA,EAG5EF,EAAkB,IAAIE,EAAM,KAAK,CACnC,CAEA,MAAME,EAAc,MAAM,QAAQ,IAChCjC,EAAO,wBAAwB,IAAKkC,GAAOC,EAAAA,6BAA6BD,CAAE,CAAC,CAAA,EAGvEb,EAAO,IAAIC,OACjBD,EAAK,WAAWO,EAAkB,OAAO,EACzCP,EAAK,YAAYO,EAAkB,QAAQ,EAE3C,QAASE,EAAI,EAAGA,EAAIF,EAAkB,IAAI,OAAQE,IAAK,CACrD,MAAMC,EAAQH,EAAkB,IAAIE,CAAC,EAC/BhB,EAAgBT,EAAS,KAAK0B,EAAM,KAAK,EAEzC,CAAE,OAAAK,EAAQ,aAAAhB,GAAiBa,EAAYH,CAAC,EACxCZ,EAAcC,EAAAA,gBAAgBiB,CAAM,EACpCC,EAAoBlB,EAAAA,gBAAgBC,CAAY,EAEtDC,EAAK,SAAS,CACZ,KAAMU,EAAM,KACZ,MAAOA,EAAM,MACb,SAAUA,EAAM,SAChB,YAAa,CACX,OAAQjB,EAAc,OACtB,MAAOA,EAAc,KAAA,EAEvB,cAAe,CACb,CACE,YAAaS,EAAAA,uBACb,OAAQC,EAAAA,OAAO,KAAKN,CAAW,EAC/B,aAAcM,EAAAA,OAAO,KAAKa,CAAiB,CAAA,CAC7C,EAEF,eAAgBb,EAAAA,OAAO,KAAKC,EAAAA,iBAAiB,CAAA,CAC9C,CACH,CAEA,UAAWC,KAAUE,EAAkB,KACrCP,EAAK,UAAU,CACb,OAAQK,EAAO,OACf,MAAOA,EAAO,KAAA,CACf,EAGH,OAAOL,EAAK,MAAA,CACd"}
@@ -1,9 +1,9 @@
1
- import { p as U, s as x, c as y, h as T, T as E } from "./bitcoin-B0S8SHCX.js";
2
- import { getPeginPayoutScriptInfo as k, tapInternalPubkey as v, getChallengeAssertScriptInfo as _ } from "@babylonlabs-io/babylon-tbv-rust-wasm";
1
+ import { p as S, s as x, k as y, h as T, T as E } from "./bitcoin-B5aNKtsk.js";
2
+ import { getPeginPayoutScriptInfo as U, tapInternalPubkey as v, getChallengeAssertScriptInfo as _ } from "@babylonlabs-io/babylon-tbv-rust-wasm";
3
3
  import { Buffer as l } from "buffer";
4
4
  import { Transaction as d, Psbt as O } from "bitcoinjs-lib";
5
5
  function m(n) {
6
- return U(n).toLowerCase();
6
+ return S(n).toLowerCase();
7
7
  }
8
8
  function D(n, t, c) {
9
9
  const r = /* @__PURE__ */ new Set();
@@ -29,9 +29,9 @@ async function N(n) {
29
29
  throw new Error(
30
30
  `Depositor Payout input 1 must spend Assert:${I}. Expected ${a}:${I}, got ${s}:${i.index}`
31
31
  );
32
- const f = c.outs[o.index], h = r.outs[i.index], { payoutScript: P, payoutControlBlock: g } = await k(
32
+ const f = c.outs[o.index], h = r.outs[i.index], { payoutScript: P, payoutControlBlock: g } = await U(
33
33
  n.connectorParams
34
- ), H = T(P), S = T(g), p = new O();
34
+ ), H = T(P), k = T(g), p = new O();
35
35
  p.setVersion(t.version), p.setLocktime(t.locktime), p.addInput({
36
36
  hash: o.hash,
37
37
  index: o.index,
@@ -44,7 +44,7 @@ async function N(n) {
44
44
  {
45
45
  leafVersion: E,
46
46
  script: l.from(H),
47
- controlBlock: l.from(S)
47
+ controlBlock: l.from(k)
48
48
  }
49
49
  ],
50
50
  tapInternalKey: l.from(v)
@@ -125,4 +125,4 @@ export {
125
125
  N as b,
126
126
  D as c
127
127
  };
128
- //# sourceMappingURL=challengeAssert-BzxQmdZy.js.map
128
+ //# sourceMappingURL=challengeAssert-BXESW00N.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"challengeAssert-BzxQmdZy.js","sources":["../src/tbv/core/primitives/challengers.ts","../src/tbv/core/primitives/psbt/constants.ts","../src/tbv/core/primitives/psbt/depositorPayout.ts","../src/tbv/core/primitives/psbt/challengeAssert.ts"],"sourcesContent":["/**\n * Challenger counting utilities.\n *\n * Used for UI-level validation (e.g. computing minimum deposit amounts)\n * where the depositor's identity is known. The transaction builders use\n * `vaultKeeperBtcPubkeys.length` to match the VP's current validation.\n */\n\nimport { processPublicKeyToXOnly } from \"./utils/bitcoin\";\n\n/**\n * Normalize a public key to lowercase x-only hex for reliable comparison.\n *\n * Handles `0x` prefixes, compressed (33-byte), and uncompressed (65-byte) keys.\n */\nfunction normalizeKey(key: string): string {\n return processPublicKeyToXOnly(key).toLowerCase();\n}\n\n/**\n * Compute the number of local challengers for a vault.\n *\n * Mirrors the VP's `compute_num_challengers()` logic:\n * local challengers = {vault_provider} ∪ {vault_keepers} − {depositor}\n *\n * Keys are normalized to x-only lowercase hex before comparison, so\n * `0x`-prefixed, compressed, or mixed-case keys are handled correctly.\n *\n * @param vaultProviderPubkey - Vault provider BTC public key\n * @param vaultKeeperPubkeys - Vault keeper BTC public keys\n * @param depositorPubkey - Depositor (claimer) BTC public key\n * @returns Number of local challengers\n */\nexport function computeNumLocalChallengers(\n vaultProviderPubkey: string,\n vaultKeeperPubkeys: string[],\n depositorPubkey: string,\n): number {\n const localSet = new Set<string>();\n localSet.add(normalizeKey(vaultProviderPubkey));\n for (const vk of vaultKeeperPubkeys) {\n localSet.add(normalizeKey(vk));\n }\n localSet.delete(normalizeKey(depositorPubkey));\n return localSet.size;\n}\n","/**\n * Protocol invariants for depositor graph transactions.\n *\n * These indices and counts encode the on-chain vault protocol layout\n * (which output of PegIn/Assert each child transaction spends, and how\n * many inputs each transaction has). Consumed by the PSBT builders and\n * the depositor graph signing service; a drift between copies of these\n * values would silently change validation behaviour.\n *\n * @module primitives/psbt/constants\n * @see btc-vault crates/vault/docs/btc-transactions-spec.md\n */\n\n/**\n * Depositor Payout transaction input count.\n * Input 0: PegIn:0 (signed). Input 1: Assert:0 (in sighash, not signed).\n */\nexport const DEPOSITOR_PAYOUT_INPUT_COUNT = 2;\n\n/** PegIn vault output index spent by the depositor's Payout input 0. */\nexport const PEGIN_VAULT_OUTPUT_INDEX = 0;\n\n/** Payout input index bound to the graph Assert tx (NOT signed). */\nexport const PAYOUT_ASSERT_INPUT_INDEX = 1;\n\n/** Assert output index spent by the depositor's Payout input 1 (NOT signed). */\nexport const ASSERT_PAYOUT_OUTPUT_INDEX = 0;\n\n/** Assert output index spent by NoPayout input 0 (signed). */\nexport const ASSERT_NOPAYOUT_OUTPUT_INDEX = 0;\n","/**\n * Depositor Payout PSBT Builder\n *\n * Builds unsigned PSBTs for the depositor's own Payout transaction\n * (depositor-as-claimer path). The depositor signs input 0 using the\n * payout taproot script from WasmPeginPayoutConnector (PegIn vault UTXO).\n *\n * Input 0 spends PegIn:0 (the vault UTXO) — the same connector used for\n * VP/VK payout signing. The VP verifies this signature using the\n * PeginPayoutConnector's payout script.\n *\n * @module primitives/psbt/depositorPayout\n * @see btc-vault crates/vault/src/sign.rs — verify_depositor_signature / get_payout_tap_leaf_hash\n */\n\nimport {\n type PayoutConnectorParams,\n getPeginPayoutScriptInfo,\n tapInternalPubkey,\n} from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport { Buffer } from \"buffer\";\nimport { Psbt, Transaction } from \"bitcoinjs-lib\";\n\nimport {\n TAPSCRIPT_LEAF_VERSION,\n hexToUint8Array,\n inputTxidHex,\n stripHexPrefix,\n} from \"../utils/bitcoin\";\nimport {\n ASSERT_PAYOUT_OUTPUT_INDEX,\n DEPOSITOR_PAYOUT_INPUT_COUNT,\n PEGIN_VAULT_OUTPUT_INDEX,\n} from \"./constants\";\n\n/**\n * Parameters for building a depositor Payout PSBT\n */\nexport interface DepositorPayoutParams {\n /** Payout transaction hex (unsigned) */\n payoutTxHex: string;\n /** Authoritative PegIn transaction hex — input 0 must spend PegIn:0 */\n peginTxHex: string;\n /** Authoritative Assert transaction hex — input 1 must spend Assert:0 */\n assertTxHex: string;\n /** Parameters for the PeginPayout connector (depositor, VP, VKs, UCs, timelock) */\n connectorParams: PayoutConnectorParams;\n}\n\n/**\n * Build unsigned depositor Payout PSBT.\n *\n * The depositor's payout transaction has 2 inputs:\n * - Input 0: PegIn:0 (vault UTXO) — depositor signs using PeginPayoutConnector payout script\n * - Input 1: Assert:0 — NOT signed by depositor\n *\n * Both inputs must be present in the PSBT because Taproot SIGHASH_DEFAULT\n * commits to all input prevouts. Prevout script_pubkey/value are derived\n * from the authoritative parent transactions, not trusted from external input.\n *\n * @param params - Depositor payout parameters\n * @returns Unsigned PSBT hex ready for signing\n *\n * @throws If the payout transaction does not have exactly 2 inputs\n * @throws If input 0 does not reference peginTxHex at output index 0\n * @throws If input 1 does not reference assertTxHex at output index 0\n */\nexport async function buildDepositorPayoutPsbt(\n params: DepositorPayoutParams,\n): Promise<string> {\n const payoutTx = Transaction.fromHex(stripHexPrefix(params.payoutTxHex));\n const peginTx = Transaction.fromHex(stripHexPrefix(params.peginTxHex));\n const assertTx = Transaction.fromHex(stripHexPrefix(params.assertTxHex));\n\n if (payoutTx.ins.length !== DEPOSITOR_PAYOUT_INPUT_COUNT) {\n throw new Error(\n `Depositor Payout transaction must have exactly ${DEPOSITOR_PAYOUT_INPUT_COUNT} inputs, got ${payoutTx.ins.length}`,\n );\n }\n\n const input0 = payoutTx.ins[0];\n const input1 = payoutTx.ins[1];\n\n const input0Txid = inputTxidHex(input0);\n const peginTxid = peginTx.getId();\n if (input0Txid !== peginTxid || input0.index !== PEGIN_VAULT_OUTPUT_INDEX) {\n throw new Error(\n `Depositor Payout input 0 must spend PegIn:${PEGIN_VAULT_OUTPUT_INDEX}. ` +\n `Expected ${peginTxid}:${PEGIN_VAULT_OUTPUT_INDEX}, got ${input0Txid}:${input0.index}`,\n );\n }\n\n const input1Txid = inputTxidHex(input1);\n const assertTxid = assertTx.getId();\n if (input1Txid !== assertTxid || input1.index !== ASSERT_PAYOUT_OUTPUT_INDEX) {\n throw new Error(\n `Depositor Payout input 1 must spend Assert:${ASSERT_PAYOUT_OUTPUT_INDEX}. ` +\n `Expected ${assertTxid}:${ASSERT_PAYOUT_OUTPUT_INDEX}, got ${input1Txid}:${input1.index}`,\n );\n }\n\n const peginPrevOut = peginTx.outs[input0.index];\n const assertPrevOut = assertTx.outs[input1.index];\n\n const { payoutScript, payoutControlBlock } = await getPeginPayoutScriptInfo(\n params.connectorParams,\n );\n const scriptBytes = hexToUint8Array(payoutScript);\n const controlBlock = hexToUint8Array(payoutControlBlock);\n\n const psbt = new Psbt();\n psbt.setVersion(payoutTx.version);\n psbt.setLocktime(payoutTx.locktime);\n\n psbt.addInput({\n hash: input0.hash,\n index: input0.index,\n sequence: input0.sequence,\n witnessUtxo: {\n script: peginPrevOut.script,\n value: peginPrevOut.value,\n },\n tapLeafScript: [\n {\n leafVersion: TAPSCRIPT_LEAF_VERSION,\n script: Buffer.from(scriptBytes),\n controlBlock: Buffer.from(controlBlock),\n },\n ],\n tapInternalKey: Buffer.from(tapInternalPubkey),\n });\n\n psbt.addInput({\n hash: input1.hash,\n index: input1.index,\n sequence: input1.sequence,\n witnessUtxo: {\n script: assertPrevOut.script,\n value: assertPrevOut.value,\n },\n });\n\n for (const output of payoutTx.outs) {\n psbt.addOutput({\n script: output.script,\n value: output.value,\n });\n }\n\n return psbt.toHex();\n}\n","/**\n * ChallengeAssert PSBT Builder\n *\n * Builds an unsigned PSBT for a ChallengeAssert transaction\n * (depositor-as-claimer path, per challenger). The ChallengeAssert tx has\n * NUM_UTXOS_FOR_CHALLENGE_ASSERT (3) inputs, each spending a different Assert\n * output segment. The depositor signs ALL inputs, each with its own taproot\n * script derived from the per-segment connector params.\n *\n * @module primitives/psbt/challengeAssert\n * @see btc-vault crates/vault/docs/btc-transactions-spec.md — ChallengeAssert connector (NUM_UTXOS_FOR_CHALLENGE_ASSERT=3)\n */\n\nimport {\n type ChallengeAssertConnectorParams,\n getChallengeAssertScriptInfo,\n tapInternalPubkey,\n} from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport { Buffer } from \"buffer\";\nimport { Psbt, Transaction } from \"bitcoinjs-lib\";\n\nimport {\n TAPSCRIPT_LEAF_VERSION,\n hexToUint8Array,\n inputTxidHex,\n stripHexPrefix,\n} from \"../utils/bitcoin\";\n\n/**\n * Parameters for building a ChallengeAssert PSBT\n */\nexport interface ChallengeAssertParams {\n /** ChallengeAssert transaction hex (unsigned) */\n challengeAssertTxHex: string;\n /** Authoritative Assert transaction hex — every input must spend an Assert output */\n assertTxHex: string;\n /** Per-input connector params (one per input/segment, determines the taproot script) */\n connectorParamsPerInput: ChallengeAssertConnectorParams[];\n}\n\n/**\n * Build unsigned ChallengeAssert PSBT.\n *\n * The ChallengeAssert transaction has 3 inputs (one per Assert output segment).\n * Each input has its own taproot script derived from its connector params.\n * The depositor signs all inputs. Every prevout is derived from the\n * authoritative Assert transaction, never trusted from external input.\n *\n * @param params - ChallengeAssert parameters\n * @returns Unsigned PSBT hex ready for signing\n *\n * @throws If the number of connector params does not match the number of inputs\n * @throws If any input does not reference assertTxHex\n * @throws If any referenced Assert output is missing\n * @throws If two inputs reference the same Assert output index\n */\nexport async function buildChallengeAssertPsbt(\n params: ChallengeAssertParams,\n): Promise<string> {\n const challengeAssertTx = Transaction.fromHex(\n stripHexPrefix(params.challengeAssertTxHex),\n );\n const assertTx = Transaction.fromHex(stripHexPrefix(params.assertTxHex));\n const assertTxid = assertTx.getId();\n\n if (params.connectorParamsPerInput.length !== challengeAssertTx.ins.length) {\n throw new Error(\n `Expected ${challengeAssertTx.ins.length} connector params, got ${params.connectorParamsPerInput.length}`,\n );\n }\n\n const seenAssertOutputs = new Set<number>();\n for (let i = 0; i < challengeAssertTx.ins.length; i++) {\n const input = challengeAssertTx.ins[i];\n const inputTxid = inputTxidHex(input);\n if (inputTxid !== assertTxid) {\n throw new Error(\n `ChallengeAssert input ${i} must spend an Assert output. ` +\n `Expected txid ${assertTxid}, got ${inputTxid}`,\n );\n }\n if (!assertTx.outs[input.index]) {\n throw new Error(\n `Assert output ${input.index} not found for ChallengeAssert input ${i} (txid: ${assertTxid})`,\n );\n }\n if (seenAssertOutputs.has(input.index)) {\n throw new Error(\n `ChallengeAssert input ${i} duplicates Assert output index ${input.index}`,\n );\n }\n seenAssertOutputs.add(input.index);\n }\n\n const scriptInfos = await Promise.all(\n params.connectorParamsPerInput.map((cp) => getChallengeAssertScriptInfo(cp)),\n );\n\n const psbt = new Psbt();\n psbt.setVersion(challengeAssertTx.version);\n psbt.setLocktime(challengeAssertTx.locktime);\n\n for (let i = 0; i < challengeAssertTx.ins.length; i++) {\n const input = challengeAssertTx.ins[i];\n const assertPrevOut = assertTx.outs[input.index];\n\n const { script, controlBlock } = scriptInfos[i];\n const scriptBytes = hexToUint8Array(script);\n const controlBlockBytes = hexToUint8Array(controlBlock);\n\n psbt.addInput({\n hash: input.hash,\n index: input.index,\n sequence: input.sequence,\n witnessUtxo: {\n script: assertPrevOut.script,\n value: assertPrevOut.value,\n },\n tapLeafScript: [\n {\n leafVersion: TAPSCRIPT_LEAF_VERSION,\n script: Buffer.from(scriptBytes),\n controlBlock: Buffer.from(controlBlockBytes),\n },\n ],\n tapInternalKey: Buffer.from(tapInternalPubkey),\n });\n }\n\n for (const output of challengeAssertTx.outs) {\n psbt.addOutput({\n script: output.script,\n value: output.value,\n });\n }\n\n return psbt.toHex();\n}\n"],"names":["normalizeKey","key","processPublicKeyToXOnly","computeNumLocalChallengers","vaultProviderPubkey","vaultKeeperPubkeys","depositorPubkey","localSet","vk","DEPOSITOR_PAYOUT_INPUT_COUNT","PEGIN_VAULT_OUTPUT_INDEX","ASSERT_PAYOUT_OUTPUT_INDEX","buildDepositorPayoutPsbt","params","payoutTx","Transaction","stripHexPrefix","peginTx","assertTx","input0","input1","input0Txid","inputTxidHex","peginTxid","input1Txid","assertTxid","peginPrevOut","assertPrevOut","payoutScript","payoutControlBlock","getPeginPayoutScriptInfo","scriptBytes","hexToUint8Array","controlBlock","psbt","Psbt","TAPSCRIPT_LEAF_VERSION","Buffer","tapInternalPubkey","output","buildChallengeAssertPsbt","challengeAssertTx","seenAssertOutputs","i","input","inputTxid","scriptInfos","cp","getChallengeAssertScriptInfo","script","controlBlockBytes"],"mappings":"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"}
1
+ {"version":3,"file":"challengeAssert-BXESW00N.js","sources":["../src/tbv/core/primitives/challengers.ts","../src/tbv/core/primitives/psbt/constants.ts","../src/tbv/core/primitives/psbt/depositorPayout.ts","../src/tbv/core/primitives/psbt/challengeAssert.ts"],"sourcesContent":["/**\n * Challenger counting utilities.\n *\n * Used for UI-level validation (e.g. computing minimum deposit amounts)\n * where the depositor's identity is known. The transaction builders use\n * `vaultKeeperBtcPubkeys.length` to match the VP's current validation.\n */\n\nimport { processPublicKeyToXOnly } from \"./utils/bitcoin\";\n\n/**\n * Normalize a public key to lowercase x-only hex for reliable comparison.\n *\n * Handles `0x` prefixes, compressed (33-byte), and uncompressed (65-byte) keys.\n */\nfunction normalizeKey(key: string): string {\n return processPublicKeyToXOnly(key).toLowerCase();\n}\n\n/**\n * Compute the number of local challengers for a vault.\n *\n * Mirrors the VP's `compute_num_challengers()` logic:\n * local challengers = {vault_provider} ∪ {vault_keepers} − {depositor}\n *\n * Keys are normalized to x-only lowercase hex before comparison, so\n * `0x`-prefixed, compressed, or mixed-case keys are handled correctly.\n *\n * @param vaultProviderPubkey - Vault provider BTC public key\n * @param vaultKeeperPubkeys - Vault keeper BTC public keys\n * @param depositorPubkey - Depositor (claimer) BTC public key\n * @returns Number of local challengers\n */\nexport function computeNumLocalChallengers(\n vaultProviderPubkey: string,\n vaultKeeperPubkeys: string[],\n depositorPubkey: string,\n): number {\n const localSet = new Set<string>();\n localSet.add(normalizeKey(vaultProviderPubkey));\n for (const vk of vaultKeeperPubkeys) {\n localSet.add(normalizeKey(vk));\n }\n localSet.delete(normalizeKey(depositorPubkey));\n return localSet.size;\n}\n","/**\n * Protocol invariants for depositor graph transactions.\n *\n * These indices and counts encode the on-chain vault protocol layout\n * (which output of PegIn/Assert each child transaction spends, and how\n * many inputs each transaction has). Consumed by the PSBT builders and\n * the depositor graph signing service; a drift between copies of these\n * values would silently change validation behaviour.\n *\n * @module primitives/psbt/constants\n * @see btc-vault crates/vault/docs/btc-transactions-spec.md\n */\n\n/**\n * Depositor Payout transaction input count.\n * Input 0: PegIn:0 (signed). Input 1: Assert:0 (in sighash, not signed).\n */\nexport const DEPOSITOR_PAYOUT_INPUT_COUNT = 2;\n\n/** PegIn vault output index spent by the depositor's Payout input 0. */\nexport const PEGIN_VAULT_OUTPUT_INDEX = 0;\n\n/** Payout input index bound to the graph Assert tx (NOT signed). */\nexport const PAYOUT_ASSERT_INPUT_INDEX = 1;\n\n/** Assert output index spent by the depositor's Payout input 1 (NOT signed). */\nexport const ASSERT_PAYOUT_OUTPUT_INDEX = 0;\n\n/** Assert output index spent by NoPayout input 0 (signed). */\nexport const ASSERT_NOPAYOUT_OUTPUT_INDEX = 0;\n","/**\n * Depositor Payout PSBT Builder\n *\n * Builds unsigned PSBTs for the depositor's own Payout transaction\n * (depositor-as-claimer path). The depositor signs input 0 using the\n * payout taproot script from WasmPeginPayoutConnector (PegIn vault UTXO).\n *\n * Input 0 spends PegIn:0 (the vault UTXO) — the same connector used for\n * VP/VK payout signing. The VP verifies this signature using the\n * PeginPayoutConnector's payout script.\n *\n * @module primitives/psbt/depositorPayout\n * @see btc-vault crates/vault/src/sign.rs — verify_depositor_signature / get_payout_tap_leaf_hash\n */\n\nimport {\n type PayoutConnectorParams,\n getPeginPayoutScriptInfo,\n tapInternalPubkey,\n} from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport { Buffer } from \"buffer\";\nimport { Psbt, Transaction } from \"bitcoinjs-lib\";\n\nimport {\n TAPSCRIPT_LEAF_VERSION,\n hexToUint8Array,\n inputTxidHex,\n stripHexPrefix,\n} from \"../utils/bitcoin\";\nimport {\n ASSERT_PAYOUT_OUTPUT_INDEX,\n DEPOSITOR_PAYOUT_INPUT_COUNT,\n PEGIN_VAULT_OUTPUT_INDEX,\n} from \"./constants\";\n\n/**\n * Parameters for building a depositor Payout PSBT\n */\nexport interface DepositorPayoutParams {\n /** Payout transaction hex (unsigned) */\n payoutTxHex: string;\n /** Authoritative PegIn transaction hex — input 0 must spend PegIn:0 */\n peginTxHex: string;\n /** Authoritative Assert transaction hex — input 1 must spend Assert:0 */\n assertTxHex: string;\n /** Parameters for the PeginPayout connector (depositor, VP, VKs, UCs, timelock) */\n connectorParams: PayoutConnectorParams;\n}\n\n/**\n * Build unsigned depositor Payout PSBT.\n *\n * The depositor's payout transaction has 2 inputs:\n * - Input 0: PegIn:0 (vault UTXO) — depositor signs using PeginPayoutConnector payout script\n * - Input 1: Assert:0 — NOT signed by depositor\n *\n * Both inputs must be present in the PSBT because Taproot SIGHASH_DEFAULT\n * commits to all input prevouts. Prevout script_pubkey/value are derived\n * from the authoritative parent transactions, not trusted from external input.\n *\n * @param params - Depositor payout parameters\n * @returns Unsigned PSBT hex ready for signing\n *\n * @throws If the payout transaction does not have exactly 2 inputs\n * @throws If input 0 does not reference peginTxHex at output index 0\n * @throws If input 1 does not reference assertTxHex at output index 0\n */\nexport async function buildDepositorPayoutPsbt(\n params: DepositorPayoutParams,\n): Promise<string> {\n const payoutTx = Transaction.fromHex(stripHexPrefix(params.payoutTxHex));\n const peginTx = Transaction.fromHex(stripHexPrefix(params.peginTxHex));\n const assertTx = Transaction.fromHex(stripHexPrefix(params.assertTxHex));\n\n if (payoutTx.ins.length !== DEPOSITOR_PAYOUT_INPUT_COUNT) {\n throw new Error(\n `Depositor Payout transaction must have exactly ${DEPOSITOR_PAYOUT_INPUT_COUNT} inputs, got ${payoutTx.ins.length}`,\n );\n }\n\n const input0 = payoutTx.ins[0];\n const input1 = payoutTx.ins[1];\n\n const input0Txid = inputTxidHex(input0);\n const peginTxid = peginTx.getId();\n if (input0Txid !== peginTxid || input0.index !== PEGIN_VAULT_OUTPUT_INDEX) {\n throw new Error(\n `Depositor Payout input 0 must spend PegIn:${PEGIN_VAULT_OUTPUT_INDEX}. ` +\n `Expected ${peginTxid}:${PEGIN_VAULT_OUTPUT_INDEX}, got ${input0Txid}:${input0.index}`,\n );\n }\n\n const input1Txid = inputTxidHex(input1);\n const assertTxid = assertTx.getId();\n if (input1Txid !== assertTxid || input1.index !== ASSERT_PAYOUT_OUTPUT_INDEX) {\n throw new Error(\n `Depositor Payout input 1 must spend Assert:${ASSERT_PAYOUT_OUTPUT_INDEX}. ` +\n `Expected ${assertTxid}:${ASSERT_PAYOUT_OUTPUT_INDEX}, got ${input1Txid}:${input1.index}`,\n );\n }\n\n const peginPrevOut = peginTx.outs[input0.index];\n const assertPrevOut = assertTx.outs[input1.index];\n\n const { payoutScript, payoutControlBlock } = await getPeginPayoutScriptInfo(\n params.connectorParams,\n );\n const scriptBytes = hexToUint8Array(payoutScript);\n const controlBlock = hexToUint8Array(payoutControlBlock);\n\n const psbt = new Psbt();\n psbt.setVersion(payoutTx.version);\n psbt.setLocktime(payoutTx.locktime);\n\n psbt.addInput({\n hash: input0.hash,\n index: input0.index,\n sequence: input0.sequence,\n witnessUtxo: {\n script: peginPrevOut.script,\n value: peginPrevOut.value,\n },\n tapLeafScript: [\n {\n leafVersion: TAPSCRIPT_LEAF_VERSION,\n script: Buffer.from(scriptBytes),\n controlBlock: Buffer.from(controlBlock),\n },\n ],\n tapInternalKey: Buffer.from(tapInternalPubkey),\n });\n\n psbt.addInput({\n hash: input1.hash,\n index: input1.index,\n sequence: input1.sequence,\n witnessUtxo: {\n script: assertPrevOut.script,\n value: assertPrevOut.value,\n },\n });\n\n for (const output of payoutTx.outs) {\n psbt.addOutput({\n script: output.script,\n value: output.value,\n });\n }\n\n return psbt.toHex();\n}\n","/**\n * ChallengeAssert PSBT Builder\n *\n * Builds an unsigned PSBT for a ChallengeAssert transaction\n * (depositor-as-claimer path, per challenger). The ChallengeAssert tx has\n * NUM_UTXOS_FOR_CHALLENGE_ASSERT (3) inputs, each spending a different Assert\n * output segment. The depositor signs ALL inputs, each with its own taproot\n * script derived from the per-segment connector params.\n *\n * @module primitives/psbt/challengeAssert\n * @see btc-vault crates/vault/docs/btc-transactions-spec.md — ChallengeAssert connector (NUM_UTXOS_FOR_CHALLENGE_ASSERT=3)\n */\n\nimport {\n type ChallengeAssertConnectorParams,\n getChallengeAssertScriptInfo,\n tapInternalPubkey,\n} from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport { Buffer } from \"buffer\";\nimport { Psbt, Transaction } from \"bitcoinjs-lib\";\n\nimport {\n TAPSCRIPT_LEAF_VERSION,\n hexToUint8Array,\n inputTxidHex,\n stripHexPrefix,\n} from \"../utils/bitcoin\";\n\n/**\n * Parameters for building a ChallengeAssert PSBT\n */\nexport interface ChallengeAssertParams {\n /** ChallengeAssert transaction hex (unsigned) */\n challengeAssertTxHex: string;\n /** Authoritative Assert transaction hex — every input must spend an Assert output */\n assertTxHex: string;\n /** Per-input connector params (one per input/segment, determines the taproot script) */\n connectorParamsPerInput: ChallengeAssertConnectorParams[];\n}\n\n/**\n * Build unsigned ChallengeAssert PSBT.\n *\n * The ChallengeAssert transaction has 3 inputs (one per Assert output segment).\n * Each input has its own taproot script derived from its connector params.\n * The depositor signs all inputs. Every prevout is derived from the\n * authoritative Assert transaction, never trusted from external input.\n *\n * @param params - ChallengeAssert parameters\n * @returns Unsigned PSBT hex ready for signing\n *\n * @throws If the number of connector params does not match the number of inputs\n * @throws If any input does not reference assertTxHex\n * @throws If any referenced Assert output is missing\n * @throws If two inputs reference the same Assert output index\n */\nexport async function buildChallengeAssertPsbt(\n params: ChallengeAssertParams,\n): Promise<string> {\n const challengeAssertTx = Transaction.fromHex(\n stripHexPrefix(params.challengeAssertTxHex),\n );\n const assertTx = Transaction.fromHex(stripHexPrefix(params.assertTxHex));\n const assertTxid = assertTx.getId();\n\n if (params.connectorParamsPerInput.length !== challengeAssertTx.ins.length) {\n throw new Error(\n `Expected ${challengeAssertTx.ins.length} connector params, got ${params.connectorParamsPerInput.length}`,\n );\n }\n\n const seenAssertOutputs = new Set<number>();\n for (let i = 0; i < challengeAssertTx.ins.length; i++) {\n const input = challengeAssertTx.ins[i];\n const inputTxid = inputTxidHex(input);\n if (inputTxid !== assertTxid) {\n throw new Error(\n `ChallengeAssert input ${i} must spend an Assert output. ` +\n `Expected txid ${assertTxid}, got ${inputTxid}`,\n );\n }\n if (!assertTx.outs[input.index]) {\n throw new Error(\n `Assert output ${input.index} not found for ChallengeAssert input ${i} (txid: ${assertTxid})`,\n );\n }\n if (seenAssertOutputs.has(input.index)) {\n throw new Error(\n `ChallengeAssert input ${i} duplicates Assert output index ${input.index}`,\n );\n }\n seenAssertOutputs.add(input.index);\n }\n\n const scriptInfos = await Promise.all(\n params.connectorParamsPerInput.map((cp) => getChallengeAssertScriptInfo(cp)),\n );\n\n const psbt = new Psbt();\n psbt.setVersion(challengeAssertTx.version);\n psbt.setLocktime(challengeAssertTx.locktime);\n\n for (let i = 0; i < challengeAssertTx.ins.length; i++) {\n const input = challengeAssertTx.ins[i];\n const assertPrevOut = assertTx.outs[input.index];\n\n const { script, controlBlock } = scriptInfos[i];\n const scriptBytes = hexToUint8Array(script);\n const controlBlockBytes = hexToUint8Array(controlBlock);\n\n psbt.addInput({\n hash: input.hash,\n index: input.index,\n sequence: input.sequence,\n witnessUtxo: {\n script: assertPrevOut.script,\n value: assertPrevOut.value,\n },\n tapLeafScript: [\n {\n leafVersion: TAPSCRIPT_LEAF_VERSION,\n script: Buffer.from(scriptBytes),\n controlBlock: Buffer.from(controlBlockBytes),\n },\n ],\n tapInternalKey: Buffer.from(tapInternalPubkey),\n });\n }\n\n for (const output of challengeAssertTx.outs) {\n psbt.addOutput({\n script: output.script,\n value: output.value,\n });\n }\n\n return psbt.toHex();\n}\n"],"names":["normalizeKey","key","processPublicKeyToXOnly","computeNumLocalChallengers","vaultProviderPubkey","vaultKeeperPubkeys","depositorPubkey","localSet","vk","DEPOSITOR_PAYOUT_INPUT_COUNT","PEGIN_VAULT_OUTPUT_INDEX","ASSERT_PAYOUT_OUTPUT_INDEX","buildDepositorPayoutPsbt","params","payoutTx","Transaction","stripHexPrefix","peginTx","assertTx","input0","input1","input0Txid","inputTxidHex","peginTxid","input1Txid","assertTxid","peginPrevOut","assertPrevOut","payoutScript","payoutControlBlock","getPeginPayoutScriptInfo","scriptBytes","hexToUint8Array","controlBlock","psbt","Psbt","TAPSCRIPT_LEAF_VERSION","Buffer","tapInternalPubkey","output","buildChallengeAssertPsbt","challengeAssertTx","seenAssertOutputs","i","input","inputTxid","scriptInfos","cp","getChallengeAssertScriptInfo","script","controlBlockBytes"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";const m=require("bitcoinjs-lib"),u=require("buffer");function P(t){const o=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const n in t)if(n!=="default"){const i=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(o,n,i.get?i:{enumerable:!0,get:()=>t[n]})}}return o.default=t,Object.freeze(o)}const A=P(m),F=58,h=43,l=11,g=546,f=BigInt(g),S=30,I=2,N=1.1;function d(t){return t<=I?S:0}const U=1,O=1;function B(t,o){if(!Number.isInteger(t)||t<1)throw new Error(`peginOutputCount: vaultCount must be a positive integer, got ${t}`);const n=typeof o=="string"&&o.length>0;return t+U+(n?O:0)}const D=5;function R(t){const n=t.substring(8,12)==="0001"?12:8,i=parseInt(t.substring(n,n+2),16),r=parseInt(t.substring(n+2,n+4),16);if(i!==0)throw new Error(`Expected 0 inputs from WASM, got ${i}`);if(r===0)throw new Error("Expected at least 1 output from WASM, got 0");const E=u.Buffer.from(t.substring(0,8),"hex").readUInt32LE(0),a=u.Buffer.from(t.substring(t.length-8),"hex").readUInt32LE(0),_=[];let e=n+4;for(let s=0;s<r;s++){const c=t.substring(e,e+16),T=Number(u.Buffer.from(c,"hex").readBigUInt64LE(0));e+=16;const p=parseInt(t.substring(e,e+2),16);e+=2;const L=t.substring(e,e+p*2),b=u.Buffer.from(L,"hex");e+=p*2,_.push({value:T,script:b})}return{version:E,locktime:a,outputs:_}}function C(t){const{unfundedTxHex:o,selectedUTXOs:n,changeAddress:i,changeAmount:r,network:E}=t,{version:a,locktime:_,outputs:e}=R(o),s=new A.Transaction;s.version=a,s.locktime=_;for(const c of n){const T=u.Buffer.from(c.txid,"hex").reverse();s.addInput(T,c.vout)}for(const c of e)s.addOutput(c.script,c.value);if(r<0n)throw new Error(`fundPeginTransaction: changeAmount cannot be negative, got ${r}`);if(r>0n&&r<=f)throw new Error(`fundPeginTransaction: changeAmount must be 0 or strictly above DUST_THRESHOLD (${f}), got ${r}`);if(r>0n){const c=A.address.toOutputScript(i,E);s.addOutput(c,Number(r))}return s.toHex()}exports.BTC_DUST_SAT=g;exports.DUST_THRESHOLD=f;exports.FEE_SAFETY_MARGIN=N;exports.LOW_RATE_ESTIMATION_ACCURACY_BUFFER=S;exports.MAX_NON_LEGACY_OUTPUT_SIZE=h;exports.P2TR_INPUT_SIZE=F;exports.PEGIN_AUTH_ANCHOR_OUTPUTS=O;exports.PEGIN_FIXED_OUTPUTS=U;exports.SPLIT_TX_FEE_SAFETY_MULTIPLIER=D;exports.TX_BUFFER_SIZE_OVERHEAD=l;exports.WALLET_RELAY_FEE_RATE_THRESHOLD=I;exports.fundPeginTransaction=C;exports.parseUnfundedWasmTransaction=R;exports.peginOutputCount=B;exports.rateBasedTxBufferFee=d;
2
+ //# sourceMappingURL=fundPeginTransaction-BBE3wTjR.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"fundPeginTransaction-DaWoYCgO.cjs","sources":["../src/tbv/core/utils/fee/constants.ts","../src/tbv/core/utils/transaction/fundPeginTransaction.ts"],"sourcesContent":["/**\n * Fee calculation constants for Bitcoin transactions.\n * Based on btc-staking-ts values, adapted for vault peg-in transactions.\n */\n\n// P2TR input size in vbytes (42 vbytes non-witness + 16 vbytes witness)\nexport const P2TR_INPUT_SIZE = 58;\n\n// P2TR output size in bytes (largest non-legacy output type)\nexport const MAX_NON_LEGACY_OUTPUT_SIZE = 43;\n\n// Base transaction overhead (version, input/output counts, locktime, SegWit marker)\nexport const TX_BUFFER_SIZE_OVERHEAD = 11;\n\n// Dust threshold: outputs below this may not be relayed\nexport const BTC_DUST_SAT = 546;\n\n/** Pre-computed BigInt dust threshold to avoid repeated conversions in hot paths */\nexport const DUST_THRESHOLD = BigInt(BTC_DUST_SAT);\n\n// Buffer for low fee rate estimation accuracy (when feeRate <= 2 sat/vbyte)\nexport const LOW_RATE_ESTIMATION_ACCURACY_BUFFER = 30;\n\n// Wallet relay fee rate threshold - different buffer fees are used based on this\nexport const WALLET_RELAY_FEE_RATE_THRESHOLD = 2;\n\n// Safety margin: 10% buffer for size variations and fee market volatility\nexport const FEE_SAFETY_MARGIN = 1.1;\n\n/**\n * Adds a buffer to the transaction fee calculation if the fee rate is low.\n *\n * Some wallets have a relayer fee requirement. If the fee rate is <= 2 sat/vbyte,\n * there's a risk the fee might not be sufficient for transaction relay.\n * We add a buffer to ensure the transaction can be relayed.\n *\n * @param feeRate - Fee rate in satoshis per vbyte\n * @returns Buffer amount in satoshis to add to the transaction fee\n */\nexport function rateBasedTxBufferFee(feeRate: number): number {\n return feeRate <= WALLET_RELAY_FEE_RATE_THRESHOLD\n ? LOW_RATE_ESTIMATION_ACCURACY_BUFFER\n : 0;\n}\n\n/**\n * Number of always-present fixed (non-HTLC) outputs in a Pre-PegIn\n * transaction. Currently this is 1 CPFP anchor output.\n */\nexport const PEGIN_FIXED_OUTPUTS = 1;\n\n/**\n * Size of the auth-anchor `OP_RETURN` output when committed into a\n * Pre-PegIn. The output carries `OP_RETURN <PUSH32 hash>` = 34 script\n * bytes, plus 8 bytes value + 1 byte scriptLen = ~43 bytes total —\n * same as {@link MAX_NON_LEGACY_OUTPUT_SIZE}. Counted as one output\n * toward the fee-estimation output budget.\n */\nexport const PEGIN_AUTH_ANCHOR_OUTPUTS = 1;\n\n/**\n * Compute the total number of outputs (before change) in a Pre-PegIn\n * transaction.\n *\n * A Pre-PegIn tx has: N HTLC outputs (one per vault) + optional\n * auth-anchor OP_RETURN output + fixed outputs (CPFP anchor). This\n * count is used for fee estimation — the change output is handled\n * separately by `selectUtxosForPegin` when the change amount exceeds\n * the dust threshold.\n *\n * `authAnchorHash` is the same value forwarded into `buildPrePeginPsbt`:\n * when truthy the Pre-PegIn carries an OP_RETURN commitment, so callers\n * pass the same value to both functions and the fee budget stays in\n * lockstep with the output set. Passing `undefined`/`null` reproduces\n * the legacy single-arg behavior (HTLCs + CPFP only).\n *\n * @param vaultCount - Number of vaults in the batch (≥1).\n * @param authAnchorHash - The same auth-anchor commitment passed to\n * `buildPrePeginPsbt`. Truthy → counts the\n * OP_RETURN output in the budget.\n * @returns Total output count before change.\n * @throws If `vaultCount` is not a positive integer.\n */\nexport function peginOutputCount(\n vaultCount: number,\n authAnchorHash?: string | null,\n): number {\n if (!Number.isInteger(vaultCount) || vaultCount < 1) {\n throw new Error(\n `peginOutputCount: vaultCount must be a positive integer, got ${vaultCount}`,\n );\n }\n const hasAuthAnchor =\n typeof authAnchorHash === \"string\" && authAnchorHash.length > 0;\n return (\n vaultCount +\n PEGIN_FIXED_OUTPUTS +\n (hasAuthAnchor ? PEGIN_AUTH_ANCHOR_OUTPUTS : 0)\n );\n}\n\n/**\n * Safety multiplier for split transaction fee validation.\n * The signed PSBT's fee rate and absolute fee must not exceed this multiple\n * of the planned values. 5x accounts for witness estimation variance while\n * catching catastrophic wallet-side overpayment.\n */\nexport const SPLIT_TX_FEE_SAFETY_MULTIPLIER = 5;\n","/**\n * Transaction Funding Utility for Peg-in Transactions\n *\n * This module funds an unfunded transaction template from the SDK by adding\n * UTXO inputs and change outputs, creating a transaction ready for wallet signing.\n *\n * Transaction Flow:\n * 1. SDK buildPrePeginPsbt() → unfunded Pre-PegIn tx (0 inputs, HTLC + CPFP outputs)\n * 2. selectUtxosForPegin() → select UTXOs and calculate fees\n * 3. fundPeginTransaction() → add inputs/change, create funded transaction\n *\n * Technical Note:\n * We manually extract the vault output from SDK hex instead of using bitcoinjs-lib\n * parsing because bitcoinjs-lib cannot parse 0-input transactions (even witness format).\n */\n\nimport * as bitcoin from \"bitcoinjs-lib\";\nimport { Buffer } from \"buffer\";\n\nimport { DUST_THRESHOLD } from \"../fee/constants\";\nimport type { UTXO } from \"../utxo/selectUtxos\";\n\nexport interface FundPeginTransactionParams {\n /** Unfunded transaction hex from SDK (0 inputs, vault + depositor claim outputs) */\n unfundedTxHex: string;\n /** Selected UTXOs to use as inputs */\n selectedUTXOs: UTXO[];\n /** Change address (from wallet) */\n changeAddress: string;\n /** Change amount in satoshis */\n changeAmount: bigint;\n /** Bitcoin network */\n network: bitcoin.Network;\n}\n\n/** A single parsed output from the unfunded WASM transaction */\ninterface ParsedOutput {\n value: number;\n script: Buffer;\n}\n\n/** Parsed data from an unfunded WASM transaction */\ninterface ParsedUnfundedTx {\n version: number;\n locktime: number;\n outputs: ParsedOutput[];\n}\n\n/**\n * Parses an unfunded transaction hex from WASM.\n *\n * WASM produces witness-format transactions with 0 inputs, which bitcoinjs-lib cannot parse.\n * This function manually extracts the transaction components.\n *\n * Format: [version:4bytes][marker:0x00][flag:0x01][inputs:1byte=0x00][outputCount:1byte]\n * [output1: value:8bytes + scriptLen:1byte + script:N bytes]\n * [output2: ...]\n * [locktime:4bytes]\n *\n * @param unfundedTxHex - Raw transaction hex from WASM\n * @returns Parsed transaction components\n * @throws Error if transaction structure is invalid\n */\nexport function parseUnfundedWasmTransaction(\n unfundedTxHex: string,\n): ParsedUnfundedTx {\n // Check if witness markers are present (0x00 0x01 after version)\n const hasWitnessMarkers = unfundedTxHex.substring(8, 12) === \"0001\";\n const dataOffset = hasWitnessMarkers ? 12 : 8; // Skip version (8) + optional witness markers (4)\n\n // Parse input/output counts\n const inputCount = parseInt(\n unfundedTxHex.substring(dataOffset, dataOffset + 2),\n 16,\n );\n const outputCount = parseInt(\n unfundedTxHex.substring(dataOffset + 2, dataOffset + 4),\n 16,\n );\n\n if (inputCount !== 0) {\n throw new Error(`Expected 0 inputs from WASM, got ${inputCount}`);\n }\n if (outputCount === 0) {\n throw new Error(\"Expected at least 1 output from WASM, got 0\");\n }\n\n // Parse version (first 4 bytes, little-endian)\n const version = Buffer.from(unfundedTxHex.substring(0, 8), \"hex\").readUInt32LE(0);\n\n // Parse locktime (last 4 bytes, little-endian)\n const locktime = Buffer.from(\n unfundedTxHex.substring(unfundedTxHex.length - 8),\n \"hex\",\n ).readUInt32LE(0);\n\n // Parse all outputs sequentially\n const outputs: ParsedOutput[] = [];\n let pos = dataOffset + 4; // position after input/output counts\n\n for (let i = 0; i < outputCount; i++) {\n const valueHex = unfundedTxHex.substring(pos, pos + 16);\n const value = Number(Buffer.from(valueHex, \"hex\").readBigUInt64LE(0));\n pos += 16;\n\n const scriptLen = parseInt(unfundedTxHex.substring(pos, pos + 2), 16);\n pos += 2;\n\n const scriptHex = unfundedTxHex.substring(pos, pos + scriptLen * 2);\n const script = Buffer.from(scriptHex, \"hex\");\n pos += scriptLen * 2;\n\n outputs.push({ value, script });\n }\n\n return { version, locktime, outputs };\n}\n\n/**\n * Funds an unfunded peg-in transaction by adding inputs and change output.\n *\n * Takes an unfunded transaction template (0 inputs, 1 vault output) from the SDK\n * and adds UTXO inputs and a change output to create a funded transaction ready\n * for wallet signing.\n *\n * @param params - Transaction funding parameters\n * @returns Transaction hex string ready for wallet signing\n */\nexport function fundPeginTransaction(\n params: FundPeginTransactionParams,\n): string {\n const { unfundedTxHex, selectedUTXOs, changeAddress, changeAmount, network } =\n params;\n\n // Parse the unfunded transaction from WASM\n const { version, locktime, outputs } =\n parseUnfundedWasmTransaction(unfundedTxHex);\n\n // Create a new transaction with the extracted data\n const tx = new bitcoin.Transaction();\n tx.version = version;\n tx.locktime = locktime;\n\n // Add inputs from selected UTXOs\n for (const utxo of selectedUTXOs) {\n // Bitcoin uses reversed byte order for txid\n const txHash = Buffer.from(utxo.txid, \"hex\").reverse();\n tx.addInput(txHash, utxo.vout);\n }\n\n // Add all WASM outputs (vault output at index 0, depositor claim at index 1, etc.)\n for (const output of outputs) {\n tx.addOutput(output.script, output.value);\n }\n\n // Add change output if above dust threshold\n if (changeAmount > DUST_THRESHOLD) {\n const changeScript = bitcoin.address.toOutputScript(changeAddress, network);\n tx.addOutput(changeScript, Number(changeAmount));\n }\n\n return tx.toHex();\n}\n\n// Re-export getNetwork from the canonical location in primitives\nexport { getNetwork } from \"../../primitives/utils/bitcoin\";\n"],"names":["P2TR_INPUT_SIZE","MAX_NON_LEGACY_OUTPUT_SIZE","TX_BUFFER_SIZE_OVERHEAD","BTC_DUST_SAT","DUST_THRESHOLD","LOW_RATE_ESTIMATION_ACCURACY_BUFFER","WALLET_RELAY_FEE_RATE_THRESHOLD","FEE_SAFETY_MARGIN","rateBasedTxBufferFee","feeRate","PEGIN_FIXED_OUTPUTS","PEGIN_AUTH_ANCHOR_OUTPUTS","peginOutputCount","vaultCount","authAnchorHash","hasAuthAnchor","SPLIT_TX_FEE_SAFETY_MULTIPLIER","parseUnfundedWasmTransaction","unfundedTxHex","dataOffset","inputCount","outputCount","version","Buffer","locktime","outputs","pos","i","valueHex","value","scriptLen","scriptHex","script","fundPeginTransaction","params","selectedUTXOs","changeAddress","changeAmount","network","tx","bitcoin","utxo","txHash","output","changeScript"],"mappings":"4VAMaA,EAAkB,GAGlBC,EAA6B,GAG7BC,EAA0B,GAG1BC,EAAe,IAGfC,EAAiB,OAAOD,CAAY,EAGpCE,EAAsC,GAGtCC,EAAkC,EAGlCC,EAAoB,IAY1B,SAASC,EAAqBC,EAAyB,CAC5D,OAAOA,GAAWH,EACdD,EACA,CACN,CAMO,MAAMK,EAAsB,EAStBC,EAA4B,EAyBlC,SAASC,EACdC,EACAC,EACQ,CACR,GAAI,CAAC,OAAO,UAAUD,CAAU,GAAKA,EAAa,EAChD,MAAM,IAAI,MACR,gEAAgEA,CAAU,EAAA,EAG9E,MAAME,EACJ,OAAOD,GAAmB,UAAYA,EAAe,OAAS,EAChE,OACED,EACAH,GACCK,EAAgBJ,EAA4B,EAEjD,CAQO,MAAMK,EAAiC,EC5CvC,SAASC,EACdC,EACkB,CAGlB,MAAMC,EADoBD,EAAc,UAAU,EAAG,EAAE,IAAM,OACtB,GAAK,EAGtCE,EAAa,SACjBF,EAAc,UAAUC,EAAYA,EAAa,CAAC,EAClD,EAAA,EAEIE,EAAc,SAClBH,EAAc,UAAUC,EAAa,EAAGA,EAAa,CAAC,EACtD,EAAA,EAGF,GAAIC,IAAe,EACjB,MAAM,IAAI,MAAM,oCAAoCA,CAAU,EAAE,EAElE,GAAIC,IAAgB,EAClB,MAAM,IAAI,MAAM,6CAA6C,EAI/D,MAAMC,EAAUC,EAAAA,OAAO,KAAKL,EAAc,UAAU,EAAG,CAAC,EAAG,KAAK,EAAE,aAAa,CAAC,EAG1EM,EAAWD,EAAAA,OAAO,KACtBL,EAAc,UAAUA,EAAc,OAAS,CAAC,EAChD,KAAA,EACA,aAAa,CAAC,EAGVO,EAA0B,CAAA,EAChC,IAAIC,EAAMP,EAAa,EAEvB,QAASQ,EAAI,EAAGA,EAAIN,EAAaM,IAAK,CACpC,MAAMC,EAAWV,EAAc,UAAUQ,EAAKA,EAAM,EAAE,EAChDG,EAAQ,OAAON,EAAAA,OAAO,KAAKK,EAAU,KAAK,EAAE,gBAAgB,CAAC,CAAC,EACpEF,GAAO,GAEP,MAAMI,EAAY,SAASZ,EAAc,UAAUQ,EAAKA,EAAM,CAAC,EAAG,EAAE,EACpEA,GAAO,EAEP,MAAMK,EAAYb,EAAc,UAAUQ,EAAKA,EAAMI,EAAY,CAAC,EAC5DE,EAAST,EAAAA,OAAO,KAAKQ,EAAW,KAAK,EAC3CL,GAAOI,EAAY,EAEnBL,EAAQ,KAAK,CAAE,MAAAI,EAAO,OAAAG,CAAA,CAAQ,CAChC,CAEA,MAAO,CAAE,QAAAV,EAAS,SAAAE,EAAU,QAAAC,CAAA,CAC9B,CAYO,SAASQ,EACdC,EACQ,CACR,KAAM,CAAE,cAAAhB,EAAe,cAAAiB,EAAe,cAAAC,EAAe,aAAAC,EAAc,QAAAC,GACjEJ,EAGI,CAAE,QAAAZ,EAAS,SAAAE,EAAU,QAAAC,CAAA,EACzBR,EAA6BC,CAAa,EAGtCqB,EAAK,IAAIC,EAAQ,YACvBD,EAAG,QAAUjB,EACbiB,EAAG,SAAWf,EAGd,UAAWiB,KAAQN,EAAe,CAEhC,MAAMO,EAASnB,EAAAA,OAAO,KAAKkB,EAAK,KAAM,KAAK,EAAE,QAAA,EAC7CF,EAAG,SAASG,EAAQD,EAAK,IAAI,CAC/B,CAGA,UAAWE,KAAUlB,EACnBc,EAAG,UAAUI,EAAO,OAAQA,EAAO,KAAK,EAI1C,GAAIN,EAAejC,EAAgB,CACjC,MAAMwC,EAAeJ,EAAQ,QAAQ,eAAeJ,EAAeE,CAAO,EAC1EC,EAAG,UAAUK,EAAc,OAAOP,CAAY,CAAC,CACjD,CAEA,OAAOE,EAAG,MAAA,CACZ"}
1
+ {"version":3,"file":"fundPeginTransaction-BBE3wTjR.cjs","sources":["../src/tbv/core/utils/fee/constants.ts","../src/tbv/core/utils/transaction/fundPeginTransaction.ts"],"sourcesContent":["/**\n * Fee calculation constants for Bitcoin transactions.\n * Based on btc-staking-ts values, adapted for vault peg-in transactions.\n */\n\n// P2TR input size in vbytes (42 vbytes non-witness + 16 vbytes witness)\nexport const P2TR_INPUT_SIZE = 58;\n\n// P2TR output size in bytes (largest non-legacy output type)\nexport const MAX_NON_LEGACY_OUTPUT_SIZE = 43;\n\n// Base transaction overhead (version, input/output counts, locktime, SegWit marker)\nexport const TX_BUFFER_SIZE_OVERHEAD = 11;\n\n// Dust threshold: outputs below this may not be relayed\nexport const BTC_DUST_SAT = 546;\n\n/** Pre-computed BigInt dust threshold to avoid repeated conversions in hot paths */\nexport const DUST_THRESHOLD = BigInt(BTC_DUST_SAT);\n\n// Buffer for low fee rate estimation accuracy (when feeRate <= 2 sat/vbyte)\nexport const LOW_RATE_ESTIMATION_ACCURACY_BUFFER = 30;\n\n// Wallet relay fee rate threshold - different buffer fees are used based on this\nexport const WALLET_RELAY_FEE_RATE_THRESHOLD = 2;\n\n// Safety margin: 10% buffer for size variations and fee market volatility\nexport const FEE_SAFETY_MARGIN = 1.1;\n\n/**\n * Adds a buffer to the transaction fee calculation if the fee rate is low.\n *\n * Some wallets have a relayer fee requirement. If the fee rate is <= 2 sat/vbyte,\n * there's a risk the fee might not be sufficient for transaction relay.\n * We add a buffer to ensure the transaction can be relayed.\n *\n * @param feeRate - Fee rate in satoshis per vbyte\n * @returns Buffer amount in satoshis to add to the transaction fee\n */\nexport function rateBasedTxBufferFee(feeRate: number): number {\n return feeRate <= WALLET_RELAY_FEE_RATE_THRESHOLD\n ? LOW_RATE_ESTIMATION_ACCURACY_BUFFER\n : 0;\n}\n\n/**\n * Number of always-present fixed (non-HTLC) outputs in a Pre-PegIn\n * transaction. Currently this is 1 CPFP anchor output.\n */\nexport const PEGIN_FIXED_OUTPUTS = 1;\n\n/**\n * Size of the auth-anchor `OP_RETURN` output when committed into a\n * Pre-PegIn. The output carries `OP_RETURN <PUSH32 hash>` = 34 script\n * bytes, plus 8 bytes value + 1 byte scriptLen = ~43 bytes total —\n * same as {@link MAX_NON_LEGACY_OUTPUT_SIZE}. Counted as one output\n * toward the fee-estimation output budget.\n */\nexport const PEGIN_AUTH_ANCHOR_OUTPUTS = 1;\n\n/**\n * Compute the total number of outputs (before change) in a Pre-PegIn\n * transaction.\n *\n * A Pre-PegIn tx has: N HTLC outputs (one per vault) + optional\n * auth-anchor OP_RETURN output + fixed outputs (CPFP anchor). This\n * count is used for fee estimation — the change output is handled\n * separately by `selectUtxosForPegin` when the change amount exceeds\n * the dust threshold.\n *\n * `authAnchorHash` is the same value forwarded into `buildPrePeginPsbt`:\n * when truthy the Pre-PegIn carries an OP_RETURN commitment, so callers\n * pass the same value to both functions and the fee budget stays in\n * lockstep with the output set. Passing `undefined`/`null` reproduces\n * the legacy single-arg behavior (HTLCs + CPFP only).\n *\n * @param vaultCount - Number of vaults in the batch (≥1).\n * @param authAnchorHash - The same auth-anchor commitment passed to\n * `buildPrePeginPsbt`. Truthy → counts the\n * OP_RETURN output in the budget.\n * @returns Total output count before change.\n * @throws If `vaultCount` is not a positive integer.\n */\nexport function peginOutputCount(\n vaultCount: number,\n authAnchorHash?: string | null,\n): number {\n if (!Number.isInteger(vaultCount) || vaultCount < 1) {\n throw new Error(\n `peginOutputCount: vaultCount must be a positive integer, got ${vaultCount}`,\n );\n }\n const hasAuthAnchor =\n typeof authAnchorHash === \"string\" && authAnchorHash.length > 0;\n return (\n vaultCount +\n PEGIN_FIXED_OUTPUTS +\n (hasAuthAnchor ? PEGIN_AUTH_ANCHOR_OUTPUTS : 0)\n );\n}\n\n/**\n * Safety multiplier for split transaction fee validation.\n * The signed PSBT's fee rate and absolute fee must not exceed this multiple\n * of the planned values. 5x accounts for witness estimation variance while\n * catching catastrophic wallet-side overpayment.\n */\nexport const SPLIT_TX_FEE_SAFETY_MULTIPLIER = 5;\n","/**\n * Transaction Funding Utility for Peg-in Transactions\n *\n * This module funds an unfunded transaction template from the SDK by adding\n * UTXO inputs and change outputs, creating a transaction ready for wallet signing.\n *\n * Transaction Flow:\n * 1. SDK buildPrePeginPsbt() → unfunded Pre-PegIn tx (0 inputs, HTLC + CPFP outputs)\n * 2. selectUtxosForPegin() → select UTXOs and calculate fees\n * 3. fundPeginTransaction() → add inputs/change, create funded transaction\n *\n * Technical Note:\n * We manually extract the vault output from SDK hex instead of using bitcoinjs-lib\n * parsing because bitcoinjs-lib cannot parse 0-input transactions (even witness format).\n */\n\nimport * as bitcoin from \"bitcoinjs-lib\";\nimport { Buffer } from \"buffer\";\n\nimport { DUST_THRESHOLD } from \"../fee/constants\";\nimport type { UTXO } from \"../utxo/selectUtxos\";\n\nexport interface FundPeginTransactionParams {\n /** Unfunded transaction hex from SDK (0 inputs, vault + depositor claim outputs) */\n unfundedTxHex: string;\n /** Selected UTXOs to use as inputs */\n selectedUTXOs: UTXO[];\n /** Change address (from wallet) */\n changeAddress: string;\n /** Change amount in satoshis */\n changeAmount: bigint;\n /** Bitcoin network */\n network: bitcoin.Network;\n}\n\n/** A single parsed output from the unfunded WASM transaction */\ninterface ParsedOutput {\n value: number;\n script: Buffer;\n}\n\n/** Parsed data from an unfunded WASM transaction */\ninterface ParsedUnfundedTx {\n version: number;\n locktime: number;\n outputs: ParsedOutput[];\n}\n\n/**\n * Parses an unfunded transaction hex from WASM.\n *\n * WASM produces witness-format transactions with 0 inputs, which bitcoinjs-lib cannot parse.\n * This function manually extracts the transaction components.\n *\n * Format: [version:4bytes][marker:0x00][flag:0x01][inputs:1byte=0x00][outputCount:1byte]\n * [output1: value:8bytes + scriptLen:1byte + script:N bytes]\n * [output2: ...]\n * [locktime:4bytes]\n *\n * @param unfundedTxHex - Raw transaction hex from WASM\n * @returns Parsed transaction components\n * @throws Error if transaction structure is invalid\n */\nexport function parseUnfundedWasmTransaction(\n unfundedTxHex: string,\n): ParsedUnfundedTx {\n // Check if witness markers are present (0x00 0x01 after version)\n const hasWitnessMarkers = unfundedTxHex.substring(8, 12) === \"0001\";\n const dataOffset = hasWitnessMarkers ? 12 : 8; // Skip version (8) + optional witness markers (4)\n\n // Parse input/output counts\n const inputCount = parseInt(\n unfundedTxHex.substring(dataOffset, dataOffset + 2),\n 16,\n );\n const outputCount = parseInt(\n unfundedTxHex.substring(dataOffset + 2, dataOffset + 4),\n 16,\n );\n\n if (inputCount !== 0) {\n throw new Error(`Expected 0 inputs from WASM, got ${inputCount}`);\n }\n if (outputCount === 0) {\n throw new Error(\"Expected at least 1 output from WASM, got 0\");\n }\n\n // Parse version (first 4 bytes, little-endian)\n const version = Buffer.from(unfundedTxHex.substring(0, 8), \"hex\").readUInt32LE(0);\n\n // Parse locktime (last 4 bytes, little-endian)\n const locktime = Buffer.from(\n unfundedTxHex.substring(unfundedTxHex.length - 8),\n \"hex\",\n ).readUInt32LE(0);\n\n // Parse all outputs sequentially\n const outputs: ParsedOutput[] = [];\n let pos = dataOffset + 4; // position after input/output counts\n\n for (let i = 0; i < outputCount; i++) {\n const valueHex = unfundedTxHex.substring(pos, pos + 16);\n const value = Number(Buffer.from(valueHex, \"hex\").readBigUInt64LE(0));\n pos += 16;\n\n const scriptLen = parseInt(unfundedTxHex.substring(pos, pos + 2), 16);\n pos += 2;\n\n const scriptHex = unfundedTxHex.substring(pos, pos + scriptLen * 2);\n const script = Buffer.from(scriptHex, \"hex\");\n pos += scriptLen * 2;\n\n outputs.push({ value, script });\n }\n\n return { version, locktime, outputs };\n}\n\n/**\n * Funds an unfunded peg-in transaction by adding inputs and change output.\n *\n * Takes an unfunded transaction template (0 inputs, 1 vault output) from the SDK\n * and adds UTXO inputs and a change output to create a funded transaction ready\n * for wallet signing.\n *\n * @param params - Transaction funding parameters\n * @returns Transaction hex string ready for wallet signing\n */\nexport function fundPeginTransaction(\n params: FundPeginTransactionParams,\n): string {\n const { unfundedTxHex, selectedUTXOs, changeAddress, changeAmount, network } =\n params;\n\n // Parse the unfunded transaction from WASM\n const { version, locktime, outputs } =\n parseUnfundedWasmTransaction(unfundedTxHex);\n\n // Create a new transaction with the extracted data\n const tx = new bitcoin.Transaction();\n tx.version = version;\n tx.locktime = locktime;\n\n // Add inputs from selected UTXOs\n for (const utxo of selectedUTXOs) {\n // Bitcoin uses reversed byte order for txid\n const txHash = Buffer.from(utxo.txid, \"hex\").reverse();\n tx.addInput(txHash, utxo.vout);\n }\n\n // Add all WASM outputs (vault output at index 0, depositor claim at index 1, etc.)\n for (const output of outputs) {\n tx.addOutput(output.script, output.value);\n }\n\n // Trust the selector's change decision: `selectUtxosForPegin` runs every\n // candidate set through `applyChangeOutputPolicy` and returns\n // `changeAmount = 0n` whenever the residual would be at-or-below dust\n // after paying the change-output fee. Validate the contract at this\n // boundary — a hand-built or stale `changeAmount` in (0, DUST_THRESHOLD]\n // would produce a non-relayable dust output, and emitting one would also\n // bypass the canonical fee policy that the selector applied.\n if (changeAmount < 0n) {\n throw new Error(\n `fundPeginTransaction: changeAmount cannot be negative, got ${changeAmount}`,\n );\n }\n if (changeAmount > 0n && changeAmount <= DUST_THRESHOLD) {\n throw new Error(\n `fundPeginTransaction: changeAmount must be 0 or strictly above DUST_THRESHOLD (${DUST_THRESHOLD}), got ${changeAmount}`,\n );\n }\n if (changeAmount > 0n) {\n const changeScript = bitcoin.address.toOutputScript(changeAddress, network);\n tx.addOutput(changeScript, Number(changeAmount));\n }\n\n return tx.toHex();\n}\n\n// Re-export getNetwork from the canonical location in primitives\nexport { getNetwork } from \"../../primitives/utils/bitcoin\";\n"],"names":["P2TR_INPUT_SIZE","MAX_NON_LEGACY_OUTPUT_SIZE","TX_BUFFER_SIZE_OVERHEAD","BTC_DUST_SAT","DUST_THRESHOLD","LOW_RATE_ESTIMATION_ACCURACY_BUFFER","WALLET_RELAY_FEE_RATE_THRESHOLD","FEE_SAFETY_MARGIN","rateBasedTxBufferFee","feeRate","PEGIN_FIXED_OUTPUTS","PEGIN_AUTH_ANCHOR_OUTPUTS","peginOutputCount","vaultCount","authAnchorHash","hasAuthAnchor","SPLIT_TX_FEE_SAFETY_MULTIPLIER","parseUnfundedWasmTransaction","unfundedTxHex","dataOffset","inputCount","outputCount","version","Buffer","locktime","outputs","pos","i","valueHex","value","scriptLen","scriptHex","script","fundPeginTransaction","params","selectedUTXOs","changeAddress","changeAmount","network","tx","bitcoin","utxo","txHash","output","changeScript"],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ import * as f from "bitcoinjs-lib";
2
+ import { Buffer as a } from "buffer";
3
+ const R = 58, P = 43, w = 11, I = 546, T = BigInt(I), h = 30, S = 2, F = 1.1;
4
+ function l(t) {
5
+ return t <= S ? h : 0;
6
+ }
7
+ const U = 1, O = 1;
8
+ function N(t, c) {
9
+ if (!Number.isInteger(t) || t < 1)
10
+ throw new Error(
11
+ `peginOutputCount: vaultCount must be a positive integer, got ${t}`
12
+ );
13
+ const o = typeof c == "string" && c.length > 0;
14
+ return t + U + (o ? O : 0);
15
+ }
16
+ const d = 5;
17
+ function b(t) {
18
+ const o = t.substring(8, 12) === "0001" ? 12 : 8, i = parseInt(
19
+ t.substring(o, o + 2),
20
+ 16
21
+ ), n = parseInt(
22
+ t.substring(o + 2, o + 4),
23
+ 16
24
+ );
25
+ if (i !== 0)
26
+ throw new Error(`Expected 0 inputs from WASM, got ${i}`);
27
+ if (n === 0)
28
+ throw new Error("Expected at least 1 output from WASM, got 0");
29
+ const E = a.from(t.substring(0, 8), "hex").readUInt32LE(0), p = a.from(
30
+ t.substring(t.length - 8),
31
+ "hex"
32
+ ).readUInt32LE(0), u = [];
33
+ let s = o + 4;
34
+ for (let r = 0; r < n; r++) {
35
+ const e = t.substring(s, s + 16), _ = Number(a.from(e, "hex").readBigUInt64LE(0));
36
+ s += 16;
37
+ const g = parseInt(t.substring(s, s + 2), 16);
38
+ s += 2;
39
+ const m = t.substring(s, s + g * 2), A = a.from(m, "hex");
40
+ s += g * 2, u.push({ value: _, script: A });
41
+ }
42
+ return { version: E, locktime: p, outputs: u };
43
+ }
44
+ function v(t) {
45
+ const { unfundedTxHex: c, selectedUTXOs: o, changeAddress: i, changeAmount: n, network: E } = t, { version: p, locktime: u, outputs: s } = b(c), r = new f.Transaction();
46
+ r.version = p, r.locktime = u;
47
+ for (const e of o) {
48
+ const _ = a.from(e.txid, "hex").reverse();
49
+ r.addInput(_, e.vout);
50
+ }
51
+ for (const e of s)
52
+ r.addOutput(e.script, e.value);
53
+ if (n < 0n)
54
+ throw new Error(
55
+ `fundPeginTransaction: changeAmount cannot be negative, got ${n}`
56
+ );
57
+ if (n > 0n && n <= T)
58
+ throw new Error(
59
+ `fundPeginTransaction: changeAmount must be 0 or strictly above DUST_THRESHOLD (${T}), got ${n}`
60
+ );
61
+ if (n > 0n) {
62
+ const e = f.address.toOutputScript(i, E);
63
+ r.addOutput(e, Number(n));
64
+ }
65
+ return r.toHex();
66
+ }
67
+ export {
68
+ I as B,
69
+ T as D,
70
+ F,
71
+ h as L,
72
+ P as M,
73
+ R as P,
74
+ d as S,
75
+ w as T,
76
+ S as W,
77
+ U as a,
78
+ O as b,
79
+ b as c,
80
+ v as f,
81
+ N as p,
82
+ l as r
83
+ };
84
+ //# sourceMappingURL=fundPeginTransaction-t-6TsHAY.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fundPeginTransaction-oV-dNJOU.js","sources":["../src/tbv/core/utils/fee/constants.ts","../src/tbv/core/utils/transaction/fundPeginTransaction.ts"],"sourcesContent":["/**\n * Fee calculation constants for Bitcoin transactions.\n * Based on btc-staking-ts values, adapted for vault peg-in transactions.\n */\n\n// P2TR input size in vbytes (42 vbytes non-witness + 16 vbytes witness)\nexport const P2TR_INPUT_SIZE = 58;\n\n// P2TR output size in bytes (largest non-legacy output type)\nexport const MAX_NON_LEGACY_OUTPUT_SIZE = 43;\n\n// Base transaction overhead (version, input/output counts, locktime, SegWit marker)\nexport const TX_BUFFER_SIZE_OVERHEAD = 11;\n\n// Dust threshold: outputs below this may not be relayed\nexport const BTC_DUST_SAT = 546;\n\n/** Pre-computed BigInt dust threshold to avoid repeated conversions in hot paths */\nexport const DUST_THRESHOLD = BigInt(BTC_DUST_SAT);\n\n// Buffer for low fee rate estimation accuracy (when feeRate <= 2 sat/vbyte)\nexport const LOW_RATE_ESTIMATION_ACCURACY_BUFFER = 30;\n\n// Wallet relay fee rate threshold - different buffer fees are used based on this\nexport const WALLET_RELAY_FEE_RATE_THRESHOLD = 2;\n\n// Safety margin: 10% buffer for size variations and fee market volatility\nexport const FEE_SAFETY_MARGIN = 1.1;\n\n/**\n * Adds a buffer to the transaction fee calculation if the fee rate is low.\n *\n * Some wallets have a relayer fee requirement. If the fee rate is <= 2 sat/vbyte,\n * there's a risk the fee might not be sufficient for transaction relay.\n * We add a buffer to ensure the transaction can be relayed.\n *\n * @param feeRate - Fee rate in satoshis per vbyte\n * @returns Buffer amount in satoshis to add to the transaction fee\n */\nexport function rateBasedTxBufferFee(feeRate: number): number {\n return feeRate <= WALLET_RELAY_FEE_RATE_THRESHOLD\n ? LOW_RATE_ESTIMATION_ACCURACY_BUFFER\n : 0;\n}\n\n/**\n * Number of always-present fixed (non-HTLC) outputs in a Pre-PegIn\n * transaction. Currently this is 1 CPFP anchor output.\n */\nexport const PEGIN_FIXED_OUTPUTS = 1;\n\n/**\n * Size of the auth-anchor `OP_RETURN` output when committed into a\n * Pre-PegIn. The output carries `OP_RETURN <PUSH32 hash>` = 34 script\n * bytes, plus 8 bytes value + 1 byte scriptLen = ~43 bytes total —\n * same as {@link MAX_NON_LEGACY_OUTPUT_SIZE}. Counted as one output\n * toward the fee-estimation output budget.\n */\nexport const PEGIN_AUTH_ANCHOR_OUTPUTS = 1;\n\n/**\n * Compute the total number of outputs (before change) in a Pre-PegIn\n * transaction.\n *\n * A Pre-PegIn tx has: N HTLC outputs (one per vault) + optional\n * auth-anchor OP_RETURN output + fixed outputs (CPFP anchor). This\n * count is used for fee estimation — the change output is handled\n * separately by `selectUtxosForPegin` when the change amount exceeds\n * the dust threshold.\n *\n * `authAnchorHash` is the same value forwarded into `buildPrePeginPsbt`:\n * when truthy the Pre-PegIn carries an OP_RETURN commitment, so callers\n * pass the same value to both functions and the fee budget stays in\n * lockstep with the output set. Passing `undefined`/`null` reproduces\n * the legacy single-arg behavior (HTLCs + CPFP only).\n *\n * @param vaultCount - Number of vaults in the batch (≥1).\n * @param authAnchorHash - The same auth-anchor commitment passed to\n * `buildPrePeginPsbt`. Truthy → counts the\n * OP_RETURN output in the budget.\n * @returns Total output count before change.\n * @throws If `vaultCount` is not a positive integer.\n */\nexport function peginOutputCount(\n vaultCount: number,\n authAnchorHash?: string | null,\n): number {\n if (!Number.isInteger(vaultCount) || vaultCount < 1) {\n throw new Error(\n `peginOutputCount: vaultCount must be a positive integer, got ${vaultCount}`,\n );\n }\n const hasAuthAnchor =\n typeof authAnchorHash === \"string\" && authAnchorHash.length > 0;\n return (\n vaultCount +\n PEGIN_FIXED_OUTPUTS +\n (hasAuthAnchor ? PEGIN_AUTH_ANCHOR_OUTPUTS : 0)\n );\n}\n\n/**\n * Safety multiplier for split transaction fee validation.\n * The signed PSBT's fee rate and absolute fee must not exceed this multiple\n * of the planned values. 5x accounts for witness estimation variance while\n * catching catastrophic wallet-side overpayment.\n */\nexport const SPLIT_TX_FEE_SAFETY_MULTIPLIER = 5;\n","/**\n * Transaction Funding Utility for Peg-in Transactions\n *\n * This module funds an unfunded transaction template from the SDK by adding\n * UTXO inputs and change outputs, creating a transaction ready for wallet signing.\n *\n * Transaction Flow:\n * 1. SDK buildPrePeginPsbt() → unfunded Pre-PegIn tx (0 inputs, HTLC + CPFP outputs)\n * 2. selectUtxosForPegin() → select UTXOs and calculate fees\n * 3. fundPeginTransaction() → add inputs/change, create funded transaction\n *\n * Technical Note:\n * We manually extract the vault output from SDK hex instead of using bitcoinjs-lib\n * parsing because bitcoinjs-lib cannot parse 0-input transactions (even witness format).\n */\n\nimport * as bitcoin from \"bitcoinjs-lib\";\nimport { Buffer } from \"buffer\";\n\nimport { DUST_THRESHOLD } from \"../fee/constants\";\nimport type { UTXO } from \"../utxo/selectUtxos\";\n\nexport interface FundPeginTransactionParams {\n /** Unfunded transaction hex from SDK (0 inputs, vault + depositor claim outputs) */\n unfundedTxHex: string;\n /** Selected UTXOs to use as inputs */\n selectedUTXOs: UTXO[];\n /** Change address (from wallet) */\n changeAddress: string;\n /** Change amount in satoshis */\n changeAmount: bigint;\n /** Bitcoin network */\n network: bitcoin.Network;\n}\n\n/** A single parsed output from the unfunded WASM transaction */\ninterface ParsedOutput {\n value: number;\n script: Buffer;\n}\n\n/** Parsed data from an unfunded WASM transaction */\ninterface ParsedUnfundedTx {\n version: number;\n locktime: number;\n outputs: ParsedOutput[];\n}\n\n/**\n * Parses an unfunded transaction hex from WASM.\n *\n * WASM produces witness-format transactions with 0 inputs, which bitcoinjs-lib cannot parse.\n * This function manually extracts the transaction components.\n *\n * Format: [version:4bytes][marker:0x00][flag:0x01][inputs:1byte=0x00][outputCount:1byte]\n * [output1: value:8bytes + scriptLen:1byte + script:N bytes]\n * [output2: ...]\n * [locktime:4bytes]\n *\n * @param unfundedTxHex - Raw transaction hex from WASM\n * @returns Parsed transaction components\n * @throws Error if transaction structure is invalid\n */\nexport function parseUnfundedWasmTransaction(\n unfundedTxHex: string,\n): ParsedUnfundedTx {\n // Check if witness markers are present (0x00 0x01 after version)\n const hasWitnessMarkers = unfundedTxHex.substring(8, 12) === \"0001\";\n const dataOffset = hasWitnessMarkers ? 12 : 8; // Skip version (8) + optional witness markers (4)\n\n // Parse input/output counts\n const inputCount = parseInt(\n unfundedTxHex.substring(dataOffset, dataOffset + 2),\n 16,\n );\n const outputCount = parseInt(\n unfundedTxHex.substring(dataOffset + 2, dataOffset + 4),\n 16,\n );\n\n if (inputCount !== 0) {\n throw new Error(`Expected 0 inputs from WASM, got ${inputCount}`);\n }\n if (outputCount === 0) {\n throw new Error(\"Expected at least 1 output from WASM, got 0\");\n }\n\n // Parse version (first 4 bytes, little-endian)\n const version = Buffer.from(unfundedTxHex.substring(0, 8), \"hex\").readUInt32LE(0);\n\n // Parse locktime (last 4 bytes, little-endian)\n const locktime = Buffer.from(\n unfundedTxHex.substring(unfundedTxHex.length - 8),\n \"hex\",\n ).readUInt32LE(0);\n\n // Parse all outputs sequentially\n const outputs: ParsedOutput[] = [];\n let pos = dataOffset + 4; // position after input/output counts\n\n for (let i = 0; i < outputCount; i++) {\n const valueHex = unfundedTxHex.substring(pos, pos + 16);\n const value = Number(Buffer.from(valueHex, \"hex\").readBigUInt64LE(0));\n pos += 16;\n\n const scriptLen = parseInt(unfundedTxHex.substring(pos, pos + 2), 16);\n pos += 2;\n\n const scriptHex = unfundedTxHex.substring(pos, pos + scriptLen * 2);\n const script = Buffer.from(scriptHex, \"hex\");\n pos += scriptLen * 2;\n\n outputs.push({ value, script });\n }\n\n return { version, locktime, outputs };\n}\n\n/**\n * Funds an unfunded peg-in transaction by adding inputs and change output.\n *\n * Takes an unfunded transaction template (0 inputs, 1 vault output) from the SDK\n * and adds UTXO inputs and a change output to create a funded transaction ready\n * for wallet signing.\n *\n * @param params - Transaction funding parameters\n * @returns Transaction hex string ready for wallet signing\n */\nexport function fundPeginTransaction(\n params: FundPeginTransactionParams,\n): string {\n const { unfundedTxHex, selectedUTXOs, changeAddress, changeAmount, network } =\n params;\n\n // Parse the unfunded transaction from WASM\n const { version, locktime, outputs } =\n parseUnfundedWasmTransaction(unfundedTxHex);\n\n // Create a new transaction with the extracted data\n const tx = new bitcoin.Transaction();\n tx.version = version;\n tx.locktime = locktime;\n\n // Add inputs from selected UTXOs\n for (const utxo of selectedUTXOs) {\n // Bitcoin uses reversed byte order for txid\n const txHash = Buffer.from(utxo.txid, \"hex\").reverse();\n tx.addInput(txHash, utxo.vout);\n }\n\n // Add all WASM outputs (vault output at index 0, depositor claim at index 1, etc.)\n for (const output of outputs) {\n tx.addOutput(output.script, output.value);\n }\n\n // Add change output if above dust threshold\n if (changeAmount > DUST_THRESHOLD) {\n const changeScript = bitcoin.address.toOutputScript(changeAddress, network);\n tx.addOutput(changeScript, Number(changeAmount));\n }\n\n return tx.toHex();\n}\n\n// Re-export getNetwork from the canonical location in primitives\nexport { getNetwork } from \"../../primitives/utils/bitcoin\";\n"],"names":["P2TR_INPUT_SIZE","MAX_NON_LEGACY_OUTPUT_SIZE","TX_BUFFER_SIZE_OVERHEAD","BTC_DUST_SAT","DUST_THRESHOLD","LOW_RATE_ESTIMATION_ACCURACY_BUFFER","WALLET_RELAY_FEE_RATE_THRESHOLD","FEE_SAFETY_MARGIN","rateBasedTxBufferFee","feeRate","PEGIN_FIXED_OUTPUTS","PEGIN_AUTH_ANCHOR_OUTPUTS","peginOutputCount","vaultCount","authAnchorHash","hasAuthAnchor","SPLIT_TX_FEE_SAFETY_MULTIPLIER","parseUnfundedWasmTransaction","unfundedTxHex","dataOffset","inputCount","outputCount","version","Buffer","locktime","outputs","pos","i","valueHex","value","scriptLen","scriptHex","script","fundPeginTransaction","params","selectedUTXOs","changeAddress","changeAmount","network","tx","bitcoin","utxo","txHash","output","changeScript"],"mappings":";;AAMO,MAAMA,IAAkB,IAGlBC,IAA6B,IAG7BC,IAA0B,IAG1BC,IAAe,KAGfC,IAAiB,OAAOD,CAAY,GAGpCE,IAAsC,IAGtCC,IAAkC,GAGlCC,IAAoB;AAY1B,SAASC,EAAqBC,GAAyB;AAC5D,SAAOA,KAAWH,IACdD,IACA;AACN;AAMO,MAAMK,IAAsB,GAStBC,IAA4B;AAyBlC,SAASC,EACdC,GACAC,GACQ;AACR,MAAI,CAAC,OAAO,UAAUD,CAAU,KAAKA,IAAa;AAChD,UAAM,IAAI;AAAA,MACR,gEAAgEA,CAAU;AAAA,IAAA;AAG9E,QAAME,IACJ,OAAOD,KAAmB,YAAYA,EAAe,SAAS;AAChE,SACED,IACAH,KACCK,IAAgBJ,IAA4B;AAEjD;AAQO,MAAMK,IAAiC;AC5CvC,SAASC,EACdC,GACkB;AAGlB,QAAMC,IADoBD,EAAc,UAAU,GAAG,EAAE,MAAM,SACtB,KAAK,GAGtCE,IAAa;AAAA,IACjBF,EAAc,UAAUC,GAAYA,IAAa,CAAC;AAAA,IAClD;AAAA,EAAA,GAEIE,IAAc;AAAA,IAClBH,EAAc,UAAUC,IAAa,GAAGA,IAAa,CAAC;AAAA,IACtD;AAAA,EAAA;AAGF,MAAIC,MAAe;AACjB,UAAM,IAAI,MAAM,oCAAoCA,CAAU,EAAE;AAElE,MAAIC,MAAgB;AAClB,UAAM,IAAI,MAAM,6CAA6C;AAI/D,QAAMC,IAAUC,EAAO,KAAKL,EAAc,UAAU,GAAG,CAAC,GAAG,KAAK,EAAE,aAAa,CAAC,GAG1EM,IAAWD,EAAO;AAAA,IACtBL,EAAc,UAAUA,EAAc,SAAS,CAAC;AAAA,IAChD;AAAA,EAAA,EACA,aAAa,CAAC,GAGVO,IAA0B,CAAA;AAChC,MAAIC,IAAMP,IAAa;AAEvB,WAASQ,IAAI,GAAGA,IAAIN,GAAaM,KAAK;AACpC,UAAMC,IAAWV,EAAc,UAAUQ,GAAKA,IAAM,EAAE,GAChDG,IAAQ,OAAON,EAAO,KAAKK,GAAU,KAAK,EAAE,gBAAgB,CAAC,CAAC;AACpE,IAAAF,KAAO;AAEP,UAAMI,IAAY,SAASZ,EAAc,UAAUQ,GAAKA,IAAM,CAAC,GAAG,EAAE;AACpE,IAAAA,KAAO;AAEP,UAAMK,IAAYb,EAAc,UAAUQ,GAAKA,IAAMI,IAAY,CAAC,GAC5DE,IAAST,EAAO,KAAKQ,GAAW,KAAK;AAC3C,IAAAL,KAAOI,IAAY,GAEnBL,EAAQ,KAAK,EAAE,OAAAI,GAAO,QAAAG,EAAA,CAAQ;AAAA,EAChC;AAEA,SAAO,EAAE,SAAAV,GAAS,UAAAE,GAAU,SAAAC,EAAA;AAC9B;AAYO,SAASQ,EACdC,GACQ;AACR,QAAM,EAAE,eAAAhB,GAAe,eAAAiB,GAAe,eAAAC,GAAe,cAAAC,GAAc,SAAAC,MACjEJ,GAGI,EAAE,SAAAZ,GAAS,UAAAE,GAAU,SAAAC,EAAA,IACzBR,EAA6BC,CAAa,GAGtCqB,IAAK,IAAIC,EAAQ,YAAA;AACvB,EAAAD,EAAG,UAAUjB,GACbiB,EAAG,WAAWf;AAGd,aAAWiB,KAAQN,GAAe;AAEhC,UAAMO,IAASnB,EAAO,KAAKkB,EAAK,MAAM,KAAK,EAAE,QAAA;AAC7C,IAAAF,EAAG,SAASG,GAAQD,EAAK,IAAI;AAAA,EAC/B;AAGA,aAAWE,KAAUlB;AACnB,IAAAc,EAAG,UAAUI,EAAO,QAAQA,EAAO,KAAK;AAI1C,MAAIN,IAAejC,GAAgB;AACjC,UAAMwC,IAAeJ,EAAQ,QAAQ,eAAeJ,GAAeE,CAAO;AAC1E,IAAAC,EAAG,UAAUK,GAAc,OAAOP,CAAY,CAAC;AAAA,EACjD;AAEA,SAAOE,EAAG,MAAA;AACZ;"}
1
+ {"version":3,"file":"fundPeginTransaction-t-6TsHAY.js","sources":["../src/tbv/core/utils/fee/constants.ts","../src/tbv/core/utils/transaction/fundPeginTransaction.ts"],"sourcesContent":["/**\n * Fee calculation constants for Bitcoin transactions.\n * Based on btc-staking-ts values, adapted for vault peg-in transactions.\n */\n\n// P2TR input size in vbytes (42 vbytes non-witness + 16 vbytes witness)\nexport const P2TR_INPUT_SIZE = 58;\n\n// P2TR output size in bytes (largest non-legacy output type)\nexport const MAX_NON_LEGACY_OUTPUT_SIZE = 43;\n\n// Base transaction overhead (version, input/output counts, locktime, SegWit marker)\nexport const TX_BUFFER_SIZE_OVERHEAD = 11;\n\n// Dust threshold: outputs below this may not be relayed\nexport const BTC_DUST_SAT = 546;\n\n/** Pre-computed BigInt dust threshold to avoid repeated conversions in hot paths */\nexport const DUST_THRESHOLD = BigInt(BTC_DUST_SAT);\n\n// Buffer for low fee rate estimation accuracy (when feeRate <= 2 sat/vbyte)\nexport const LOW_RATE_ESTIMATION_ACCURACY_BUFFER = 30;\n\n// Wallet relay fee rate threshold - different buffer fees are used based on this\nexport const WALLET_RELAY_FEE_RATE_THRESHOLD = 2;\n\n// Safety margin: 10% buffer for size variations and fee market volatility\nexport const FEE_SAFETY_MARGIN = 1.1;\n\n/**\n * Adds a buffer to the transaction fee calculation if the fee rate is low.\n *\n * Some wallets have a relayer fee requirement. If the fee rate is <= 2 sat/vbyte,\n * there's a risk the fee might not be sufficient for transaction relay.\n * We add a buffer to ensure the transaction can be relayed.\n *\n * @param feeRate - Fee rate in satoshis per vbyte\n * @returns Buffer amount in satoshis to add to the transaction fee\n */\nexport function rateBasedTxBufferFee(feeRate: number): number {\n return feeRate <= WALLET_RELAY_FEE_RATE_THRESHOLD\n ? LOW_RATE_ESTIMATION_ACCURACY_BUFFER\n : 0;\n}\n\n/**\n * Number of always-present fixed (non-HTLC) outputs in a Pre-PegIn\n * transaction. Currently this is 1 CPFP anchor output.\n */\nexport const PEGIN_FIXED_OUTPUTS = 1;\n\n/**\n * Size of the auth-anchor `OP_RETURN` output when committed into a\n * Pre-PegIn. The output carries `OP_RETURN <PUSH32 hash>` = 34 script\n * bytes, plus 8 bytes value + 1 byte scriptLen = ~43 bytes total —\n * same as {@link MAX_NON_LEGACY_OUTPUT_SIZE}. Counted as one output\n * toward the fee-estimation output budget.\n */\nexport const PEGIN_AUTH_ANCHOR_OUTPUTS = 1;\n\n/**\n * Compute the total number of outputs (before change) in a Pre-PegIn\n * transaction.\n *\n * A Pre-PegIn tx has: N HTLC outputs (one per vault) + optional\n * auth-anchor OP_RETURN output + fixed outputs (CPFP anchor). This\n * count is used for fee estimation — the change output is handled\n * separately by `selectUtxosForPegin` when the change amount exceeds\n * the dust threshold.\n *\n * `authAnchorHash` is the same value forwarded into `buildPrePeginPsbt`:\n * when truthy the Pre-PegIn carries an OP_RETURN commitment, so callers\n * pass the same value to both functions and the fee budget stays in\n * lockstep with the output set. Passing `undefined`/`null` reproduces\n * the legacy single-arg behavior (HTLCs + CPFP only).\n *\n * @param vaultCount - Number of vaults in the batch (≥1).\n * @param authAnchorHash - The same auth-anchor commitment passed to\n * `buildPrePeginPsbt`. Truthy → counts the\n * OP_RETURN output in the budget.\n * @returns Total output count before change.\n * @throws If `vaultCount` is not a positive integer.\n */\nexport function peginOutputCount(\n vaultCount: number,\n authAnchorHash?: string | null,\n): number {\n if (!Number.isInteger(vaultCount) || vaultCount < 1) {\n throw new Error(\n `peginOutputCount: vaultCount must be a positive integer, got ${vaultCount}`,\n );\n }\n const hasAuthAnchor =\n typeof authAnchorHash === \"string\" && authAnchorHash.length > 0;\n return (\n vaultCount +\n PEGIN_FIXED_OUTPUTS +\n (hasAuthAnchor ? PEGIN_AUTH_ANCHOR_OUTPUTS : 0)\n );\n}\n\n/**\n * Safety multiplier for split transaction fee validation.\n * The signed PSBT's fee rate and absolute fee must not exceed this multiple\n * of the planned values. 5x accounts for witness estimation variance while\n * catching catastrophic wallet-side overpayment.\n */\nexport const SPLIT_TX_FEE_SAFETY_MULTIPLIER = 5;\n","/**\n * Transaction Funding Utility for Peg-in Transactions\n *\n * This module funds an unfunded transaction template from the SDK by adding\n * UTXO inputs and change outputs, creating a transaction ready for wallet signing.\n *\n * Transaction Flow:\n * 1. SDK buildPrePeginPsbt() → unfunded Pre-PegIn tx (0 inputs, HTLC + CPFP outputs)\n * 2. selectUtxosForPegin() → select UTXOs and calculate fees\n * 3. fundPeginTransaction() → add inputs/change, create funded transaction\n *\n * Technical Note:\n * We manually extract the vault output from SDK hex instead of using bitcoinjs-lib\n * parsing because bitcoinjs-lib cannot parse 0-input transactions (even witness format).\n */\n\nimport * as bitcoin from \"bitcoinjs-lib\";\nimport { Buffer } from \"buffer\";\n\nimport { DUST_THRESHOLD } from \"../fee/constants\";\nimport type { UTXO } from \"../utxo/selectUtxos\";\n\nexport interface FundPeginTransactionParams {\n /** Unfunded transaction hex from SDK (0 inputs, vault + depositor claim outputs) */\n unfundedTxHex: string;\n /** Selected UTXOs to use as inputs */\n selectedUTXOs: UTXO[];\n /** Change address (from wallet) */\n changeAddress: string;\n /** Change amount in satoshis */\n changeAmount: bigint;\n /** Bitcoin network */\n network: bitcoin.Network;\n}\n\n/** A single parsed output from the unfunded WASM transaction */\ninterface ParsedOutput {\n value: number;\n script: Buffer;\n}\n\n/** Parsed data from an unfunded WASM transaction */\ninterface ParsedUnfundedTx {\n version: number;\n locktime: number;\n outputs: ParsedOutput[];\n}\n\n/**\n * Parses an unfunded transaction hex from WASM.\n *\n * WASM produces witness-format transactions with 0 inputs, which bitcoinjs-lib cannot parse.\n * This function manually extracts the transaction components.\n *\n * Format: [version:4bytes][marker:0x00][flag:0x01][inputs:1byte=0x00][outputCount:1byte]\n * [output1: value:8bytes + scriptLen:1byte + script:N bytes]\n * [output2: ...]\n * [locktime:4bytes]\n *\n * @param unfundedTxHex - Raw transaction hex from WASM\n * @returns Parsed transaction components\n * @throws Error if transaction structure is invalid\n */\nexport function parseUnfundedWasmTransaction(\n unfundedTxHex: string,\n): ParsedUnfundedTx {\n // Check if witness markers are present (0x00 0x01 after version)\n const hasWitnessMarkers = unfundedTxHex.substring(8, 12) === \"0001\";\n const dataOffset = hasWitnessMarkers ? 12 : 8; // Skip version (8) + optional witness markers (4)\n\n // Parse input/output counts\n const inputCount = parseInt(\n unfundedTxHex.substring(dataOffset, dataOffset + 2),\n 16,\n );\n const outputCount = parseInt(\n unfundedTxHex.substring(dataOffset + 2, dataOffset + 4),\n 16,\n );\n\n if (inputCount !== 0) {\n throw new Error(`Expected 0 inputs from WASM, got ${inputCount}`);\n }\n if (outputCount === 0) {\n throw new Error(\"Expected at least 1 output from WASM, got 0\");\n }\n\n // Parse version (first 4 bytes, little-endian)\n const version = Buffer.from(unfundedTxHex.substring(0, 8), \"hex\").readUInt32LE(0);\n\n // Parse locktime (last 4 bytes, little-endian)\n const locktime = Buffer.from(\n unfundedTxHex.substring(unfundedTxHex.length - 8),\n \"hex\",\n ).readUInt32LE(0);\n\n // Parse all outputs sequentially\n const outputs: ParsedOutput[] = [];\n let pos = dataOffset + 4; // position after input/output counts\n\n for (let i = 0; i < outputCount; i++) {\n const valueHex = unfundedTxHex.substring(pos, pos + 16);\n const value = Number(Buffer.from(valueHex, \"hex\").readBigUInt64LE(0));\n pos += 16;\n\n const scriptLen = parseInt(unfundedTxHex.substring(pos, pos + 2), 16);\n pos += 2;\n\n const scriptHex = unfundedTxHex.substring(pos, pos + scriptLen * 2);\n const script = Buffer.from(scriptHex, \"hex\");\n pos += scriptLen * 2;\n\n outputs.push({ value, script });\n }\n\n return { version, locktime, outputs };\n}\n\n/**\n * Funds an unfunded peg-in transaction by adding inputs and change output.\n *\n * Takes an unfunded transaction template (0 inputs, 1 vault output) from the SDK\n * and adds UTXO inputs and a change output to create a funded transaction ready\n * for wallet signing.\n *\n * @param params - Transaction funding parameters\n * @returns Transaction hex string ready for wallet signing\n */\nexport function fundPeginTransaction(\n params: FundPeginTransactionParams,\n): string {\n const { unfundedTxHex, selectedUTXOs, changeAddress, changeAmount, network } =\n params;\n\n // Parse the unfunded transaction from WASM\n const { version, locktime, outputs } =\n parseUnfundedWasmTransaction(unfundedTxHex);\n\n // Create a new transaction with the extracted data\n const tx = new bitcoin.Transaction();\n tx.version = version;\n tx.locktime = locktime;\n\n // Add inputs from selected UTXOs\n for (const utxo of selectedUTXOs) {\n // Bitcoin uses reversed byte order for txid\n const txHash = Buffer.from(utxo.txid, \"hex\").reverse();\n tx.addInput(txHash, utxo.vout);\n }\n\n // Add all WASM outputs (vault output at index 0, depositor claim at index 1, etc.)\n for (const output of outputs) {\n tx.addOutput(output.script, output.value);\n }\n\n // Trust the selector's change decision: `selectUtxosForPegin` runs every\n // candidate set through `applyChangeOutputPolicy` and returns\n // `changeAmount = 0n` whenever the residual would be at-or-below dust\n // after paying the change-output fee. Validate the contract at this\n // boundary — a hand-built or stale `changeAmount` in (0, DUST_THRESHOLD]\n // would produce a non-relayable dust output, and emitting one would also\n // bypass the canonical fee policy that the selector applied.\n if (changeAmount < 0n) {\n throw new Error(\n `fundPeginTransaction: changeAmount cannot be negative, got ${changeAmount}`,\n );\n }\n if (changeAmount > 0n && changeAmount <= DUST_THRESHOLD) {\n throw new Error(\n `fundPeginTransaction: changeAmount must be 0 or strictly above DUST_THRESHOLD (${DUST_THRESHOLD}), got ${changeAmount}`,\n );\n }\n if (changeAmount > 0n) {\n const changeScript = bitcoin.address.toOutputScript(changeAddress, network);\n tx.addOutput(changeScript, Number(changeAmount));\n }\n\n return tx.toHex();\n}\n\n// Re-export getNetwork from the canonical location in primitives\nexport { getNetwork } from \"../../primitives/utils/bitcoin\";\n"],"names":["P2TR_INPUT_SIZE","MAX_NON_LEGACY_OUTPUT_SIZE","TX_BUFFER_SIZE_OVERHEAD","BTC_DUST_SAT","DUST_THRESHOLD","LOW_RATE_ESTIMATION_ACCURACY_BUFFER","WALLET_RELAY_FEE_RATE_THRESHOLD","FEE_SAFETY_MARGIN","rateBasedTxBufferFee","feeRate","PEGIN_FIXED_OUTPUTS","PEGIN_AUTH_ANCHOR_OUTPUTS","peginOutputCount","vaultCount","authAnchorHash","hasAuthAnchor","SPLIT_TX_FEE_SAFETY_MULTIPLIER","parseUnfundedWasmTransaction","unfundedTxHex","dataOffset","inputCount","outputCount","version","Buffer","locktime","outputs","pos","i","valueHex","value","scriptLen","scriptHex","script","fundPeginTransaction","params","selectedUTXOs","changeAddress","changeAmount","network","tx","bitcoin","utxo","txHash","output","changeScript"],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("./challengeAssert-Yyyj-EdR.cjs"),l=require("@babylonlabs-io/babylon-tbv-rust-wasm"),d=require("./peginInput-tbw9BpZy.cjs"),E=require("./noPayout-BXeUw0Qq.cjs"),T=require("./payout-DQ_fmJUA.cjs"),a=require("./bitcoin-B3aqjuMP.cjs"),_=require("./signing-Bnsro0hE.cjs"),c=require("./validation-u8W7Lp2x.cjs"),n=require("./PeginManager-BPXVXu8t.cjs"),g=require("./PayoutManager-BhJoQZsG.cjs"),R=require("./ProtocolParams.abi-BmvHwQJV.cjs"),m=require("./BTCVaultRegistry.abi-ZdPpION2.cjs"),P=require("./errors-BP73_stm.cjs"),I=require("./shared/index.cjs"),r=require("./fundPeginTransaction-DaWoYCgO.cjs"),u=require("./reservation-ho7mjW3X.cjs"),s=require("./waitForTransactionReceiptSmartAware-D9ykVriz.cjs"),o=require("./mempoolApi-YNkKjQCU.cjs"),t=require("./vault-registry-reader-CLnhAUN4.cjs"),i=require("./types-DnyyBNcC.cjs"),A=require("./errors-Bu0H-dZD.cjs"),e=require("./buildAndBroadcastRefund-CBIfcF47.cjs"),S=require("./peginState-BijNNT15.cjs");exports.buildChallengeAssertPsbt=p.buildChallengeAssertPsbt;exports.buildDepositorPayoutPsbt=p.buildDepositorPayoutPsbt;exports.computeNumLocalChallengers=p.computeNumLocalChallengers;Object.defineProperty(exports,"computeMinClaimValue",{enumerable:!0,get:()=>l.computeMinClaimValue});Object.defineProperty(exports,"deriveVaultId",{enumerable:!0,get:()=>l.deriveVaultId});Object.defineProperty(exports,"expandAuthAnchor",{enumerable:!0,get:()=>l.expandAuthAnchor});Object.defineProperty(exports,"expandHashlockSecret",{enumerable:!0,get:()=>l.expandHashlockSecret});Object.defineProperty(exports,"expandWotsSeed",{enumerable:!0,get:()=>l.expandWotsSeed});exports.buildPeginInputPsbt=d.buildPeginInputPsbt;exports.buildPeginTxFromFundedPrePegin=d.buildPeginTxFromFundedPrePegin;exports.buildPrePeginPsbt=d.buildPrePeginPsbt;exports.extractPeginInputSignature=d.extractPeginInputSignature;exports.finalizePeginInputPsbt=d.finalizePeginInputPsbt;exports.buildNoPayoutPsbt=E.buildNoPayoutPsbt;exports.buildRefundPsbt=E.buildRefundPsbt;exports.assertPayoutOutputMatchesRegistered=T.assertPayoutOutputMatchesRegistered;exports.buildPayoutPsbt=T.buildPayoutPsbt;exports.createPayoutScript=T.createPayoutScript;exports.extractPayoutSignature=T.extractPayoutSignature;exports.deriveNativeSegwitAddress=a.deriveNativeSegwitAddress;exports.deriveTaprootAddress=a.deriveTaprootAddress;exports.ensureHexPrefix=a.ensureHexPrefix;exports.formatSatoshisToBtc=a.formatSatoshisToBtc;exports.getNetwork=a.getNetwork;exports.hexToUint8Array=a.hexToUint8Array;exports.isAddressFromPublicKey=a.isAddressFromPublicKey;exports.isValidHex=a.isValidHex;exports.processPublicKeyToXOnly=a.processPublicKeyToXOnly;exports.stripHexPrefix=a.stripHexPrefix;exports.toXOnly=a.toXOnly;exports.uint8ArrayToHex=a.uint8ArrayToHex;exports.validateWalletPubkey=a.validateWalletPubkey;exports.createTaprootScriptPathSignOptions=_.createTaprootScriptPathSignOptions;exports.BITCOIN_ADDRESS_RE=c.BITCOIN_ADDRESS_RE;exports.HEX_RE=c.HEX_RE;exports.KNOWN_SCRIPT_PREFIXES=c.KNOWN_SCRIPT_PREFIXES;exports.MAX_REASONABLE_FEE_SATS=c.MAX_REASONABLE_FEE_SATS;exports.TXID_RE=c.TXID_RE;exports.PeginManager=n.PeginManager;exports.VAULT_APP_NAME=n.VAULT_APP_NAME;exports.buildFundingOutpointsCommitment=n.buildFundingOutpointsCommitment;exports.buildVaultContext=n.buildVaultContext;exports.computeWotsBlockPublicKeysHash=n.computeWotsBlockPublicKeysHash;exports.deriveVaultRoot=n.deriveVaultRoot;exports.deriveWotsBlocksFromSeed=n.deriveWotsBlocksFromSeed;exports.PayoutManager=g.PayoutManager;exports.computeHashlock=g.computeHashlock;exports.validateSecretAgainstHashlock=g.validateSecretAgainstHashlock;exports.ApplicationRegistryABI=R.ApplicationRegistryABI;exports.ProtocolParamsABI=R.ProtocolParamsABI;exports.BTCVaultRegistryABI=m.BTCVaultRegistryABI;exports.CONTRACT_ERRORS=P.CONTRACT_ERRORS;exports.extractErrorData=P.extractErrorData;exports.getContractErrorMessage=P.getContractErrorMessage;exports.handleContractError=P.handleContractError;exports.isKnownContractError=P.isKnownContractError;exports.BitcoinNetworks=I.BitcoinNetworks;exports.BTC_DUST_SAT=r.BTC_DUST_SAT;exports.DUST_THRESHOLD=r.DUST_THRESHOLD;exports.FEE_SAFETY_MARGIN=r.FEE_SAFETY_MARGIN;exports.LOW_RATE_ESTIMATION_ACCURACY_BUFFER=r.LOW_RATE_ESTIMATION_ACCURACY_BUFFER;exports.MAX_NON_LEGACY_OUTPUT_SIZE=r.MAX_NON_LEGACY_OUTPUT_SIZE;exports.P2TR_INPUT_SIZE=r.P2TR_INPUT_SIZE;exports.PEGIN_AUTH_ANCHOR_OUTPUTS=r.PEGIN_AUTH_ANCHOR_OUTPUTS;exports.PEGIN_FIXED_OUTPUTS=r.PEGIN_FIXED_OUTPUTS;exports.SPLIT_TX_FEE_SAFETY_MULTIPLIER=r.SPLIT_TX_FEE_SAFETY_MULTIPLIER;exports.TX_BUFFER_SIZE_OVERHEAD=r.TX_BUFFER_SIZE_OVERHEAD;exports.WALLET_RELAY_FEE_RATE_THRESHOLD=r.WALLET_RELAY_FEE_RATE_THRESHOLD;exports.fundPeginTransaction=r.fundPeginTransaction;exports.parseUnfundedWasmTransaction=r.parseUnfundedWasmTransaction;exports.peginOutputCount=r.peginOutputCount;exports.rateBasedTxBufferFee=r.rateBasedTxBufferFee;exports.UtxoNotAvailableError=u.UtxoNotAvailableError;exports.assertUtxosAvailable=u.assertUtxosAvailable;exports.collectReservedUtxoRefs=u.collectReservedUtxoRefs;exports.extractInputsFromTransaction=u.extractInputsFromTransaction;exports.selectUtxosForDeposit=u.selectUtxosForDeposit;exports.validateUtxosAvailable=u.validateUtxosAvailable;exports.BitcoinScriptType=s.BitcoinScriptType;exports.calculateBtcTxHash=s.calculateBtcTxHash;exports.getDustThreshold=s.getDustThreshold;exports.getPsbtInputFields=s.getPsbtInputFields;exports.getScriptType=s.getScriptType;exports.selectUtxosForPegin=s.selectUtxosForPegin;exports.shouldAddChangeOutput=s.shouldAddChangeOutput;exports.waitForTransactionReceiptSmartAware=s.waitForTransactionReceiptSmartAware;exports.MEMPOOL_API_URLS=o.MEMPOOL_API_URLS;exports.getAddressTxs=o.getAddressTxs;exports.getAddressUtxos=o.getAddressUtxos;exports.getMempoolApiUrl=o.getMempoolApiUrl;exports.getNetworkFees=o.getNetworkFees;exports.getTxHex=o.getTxHex;exports.getTxInfo=o.getTxInfo;exports.getUtxoInfo=o.getUtxoInfo;exports.pushTx=o.pushTx;exports.ServerIdentityError=t.ServerIdentityError;exports.VaultProviderRpcClient=t.VaultProviderRpcClient;exports.ViemProtocolParamsReader=t.ViemProtocolParamsReader;exports.ViemUniversalChallengerReader=t.ViemUniversalChallengerReader;exports.ViemVaultKeeperReader=t.ViemVaultKeeperReader;exports.ViemVaultRegistryReader=t.ViemVaultRegistryReader;exports.VpResponseValidationError=t.VpResponseValidationError;exports.VpTokenRegistry=t.VpTokenRegistry;exports.batchPollByProvider=t.batchPollByProvider;exports.createAuthenticatedVpClient=t.createAuthenticatedVpClient;exports.primeVpTokenRegistry=t.primeVpTokenRegistry;exports.resolveProtocolAddresses=t.resolveProtocolAddresses;exports.validateOffchainParams=t.validateOffchainParams;exports.validatePegInConfiguration=t.validatePegInConfiguration;exports.validateRequestDepositorClaimerArtifactsResponse=t.validateRequestDepositorClaimerArtifactsResponse;exports.validateTBVProtocolParams=t.validateTBVProtocolParams;exports.verifyServerIdentity=t.verifyServerIdentity;exports.vpTokenRegistry=t.vpTokenRegistry;exports.DaemonStatus=i.DaemonStatus;exports.JSON_RPC_ERROR_CODES=i.JSON_RPC_ERROR_CODES;exports.JsonRpcClient=i.JsonRpcClient;exports.JsonRpcError=i.JsonRpcError;exports.POST_WOTS_STATUSES=i.POST_WOTS_STATUSES;exports.PRE_DEPOSITOR_SIGNATURES_STATES=i.PRE_DEPOSITOR_SIGNATURES_STATES;exports.RpcErrorCode=i.RpcErrorCode;exports.VP_BATCH_MAX_SIZE=i.VP_BATCH_MAX_SIZE;exports.VP_TERMINAL_STATUSES=i.VP_TERMINAL_STATUSES;exports.VP_TRANSIENT_STATUSES=i.VP_TRANSIENT_STATUSES;exports.isWotsMismatchError=A.isWotsMismatchError;exports.parseFundingOutpointsFromTx=A.parseFundingOutpointsFromTx;exports.BIP68NotMatureError=e.BIP68NotMatureError;exports.ClaimerPegoutStatusValue=e.ClaimerPegoutStatusValue;exports.REFUND_VSIZE=e.REFUND_VSIZE;exports.RegisteredVaultVersionMismatchError=e.RegisteredVaultVersionMismatchError;exports.activateVault=e.activateVault;exports.buildAndBroadcastRefund=e.buildAndBroadcastRefund;exports.estimateRefundFeeSats=e.estimateRefundFeeSats;exports.isDepositAmountValid=e.isDepositAmountValid;exports.isPegoutTerminalStatus=e.isPegoutTerminalStatus;exports.isRecognizedPegoutStatus=e.isRecognizedPegoutStatus;exports.isRegisteredVaultVersionMismatchError=e.isRegisteredVaultVersionMismatchError;exports.runDepositorPresignFlow=e.runDepositorPresignFlow;exports.signDepositorGraph=e.signDepositorGraph;exports.submitWotsPublicKey=e.submitWotsPublicKey;exports.validateDepositAmount=e.validateDepositAmount;exports.validateMultiVaultDepositInputs=e.validateMultiVaultDepositInputs;exports.validateOnChainParticipantKeys=e.validateOnChainParticipantKeys;exports.validateProviderSelection=e.validateProviderSelection;exports.validateRemainingCapacity=e.validateRemainingCapacity;exports.validateVaultAmounts=e.validateVaultAmounts;exports.validateVaultProviderPubkey=e.validateVaultProviderPubkey;exports.verifyRegisteredVaultVersions=e.verifyRegisteredVaultVersions;exports.waitForPeginStatus=e.waitForPeginStatus;exports.ContractStatus=S.ContractStatus;exports.PeginAction=S.PeginAction;exports.canPerformAction=S.canPerformAction;exports.getPeginProtocolState=S.getPeginProtocolState;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=require("./challengeAssert-BKDS_ADt.cjs"),c=require("@babylonlabs-io/babylon-tbv-rust-wasm"),d=require("./peginInput-57FK2O99.cjs"),E=require("./noPayout-B6s8vrW6.cjs"),u=require("./assertPsbtUnsignedTxMatches-BoHwgW30.cjs"),r=require("./bitcoin-CHfKAhcI.cjs"),_=require("./signing-Bnsro0hE.cjs"),P=require("./validation-u8W7Lp2x.cjs"),n=require("./PeginManager-CRuwG4I-.cjs"),g=require("./PayoutManager-BxAY2x0g.cjs"),R=require("./ProtocolParams.abi-BmvHwQJV.cjs"),m=require("./BTCVaultRegistry.abi-ZdPpION2.cjs"),T=require("./errors-BP73_stm.cjs"),b=require("./shared/index.cjs"),i=require("./waitForTransactionReceiptSmartAware-tv1mtSIY.cjs"),a=require("./fundPeginTransaction-BBE3wTjR.cjs"),l=require("./reservation-hjXStM03.cjs"),s=require("./mempoolApi-YNkKjQCU.cjs"),t=require("./vault-registry-reader-7gOYnrQD.cjs"),o=require("./types-DnyyBNcC.cjs"),A=require("./errors-Bu0H-dZD.cjs"),e=require("./buildAndBroadcastRefund-_CEDUU5H.cjs"),p=require("./peginState-BijNNT15.cjs");exports.buildChallengeAssertPsbt=S.buildChallengeAssertPsbt;exports.buildDepositorPayoutPsbt=S.buildDepositorPayoutPsbt;exports.computeNumLocalChallengers=S.computeNumLocalChallengers;Object.defineProperty(exports,"computeMinClaimValue",{enumerable:!0,get:()=>c.computeMinClaimValue});Object.defineProperty(exports,"deriveVaultId",{enumerable:!0,get:()=>c.deriveVaultId});Object.defineProperty(exports,"expandAuthAnchor",{enumerable:!0,get:()=>c.expandAuthAnchor});Object.defineProperty(exports,"expandHashlockSecret",{enumerable:!0,get:()=>c.expandHashlockSecret});Object.defineProperty(exports,"expandWotsSeed",{enumerable:!0,get:()=>c.expandWotsSeed});exports.buildPeginInputPsbt=d.buildPeginInputPsbt;exports.buildPeginTxFromFundedPrePegin=d.buildPeginTxFromFundedPrePegin;exports.buildPrePeginPsbt=d.buildPrePeginPsbt;exports.extractPeginInputSignature=d.extractPeginInputSignature;exports.finalizePeginInputPsbt=d.finalizePeginInputPsbt;exports.buildNoPayoutPsbt=E.buildNoPayoutPsbt;exports.buildRefundPsbt=E.buildRefundPsbt;exports.PsbtSubstitutionError=u.PsbtSubstitutionError;exports.assertPayoutOutputMatchesRegistered=u.assertPayoutOutputMatchesRegistered;exports.assertPsbtUnsignedTxMatches=u.assertPsbtUnsignedTxMatches;exports.buildPayoutPsbt=u.buildPayoutPsbt;exports.createPayoutScript=u.createPayoutScript;exports.extractPayoutSignature=u.extractPayoutSignature;exports.deriveBip86ScriptPubKeyHex=r.deriveBip86ScriptPubKeyHex;exports.deriveNativeSegwitAddress=r.deriveNativeSegwitAddress;exports.deriveTaprootAddress=r.deriveTaprootAddress;exports.ensureHexPrefix=r.ensureHexPrefix;exports.formatSatoshisToBtc=r.formatSatoshisToBtc;exports.getNetwork=r.getNetwork;exports.getSortedXOnlyPubkeys=r.getSortedXOnlyPubkeys;exports.hexToUint8Array=r.hexToUint8Array;exports.isAddressFromPublicKey=r.isAddressFromPublicKey;exports.isValidHex=r.isValidHex;exports.processPublicKeyToXOnly=r.processPublicKeyToXOnly;exports.stripHexPrefix=r.stripHexPrefix;exports.toXOnly=r.toXOnly;exports.uint8ArrayToHex=r.uint8ArrayToHex;exports.validateWalletPubkey=r.validateWalletPubkey;exports.createTaprootScriptPathSignOptions=_.createTaprootScriptPathSignOptions;exports.BITCOIN_ADDRESS_RE=P.BITCOIN_ADDRESS_RE;exports.HEX_RE=P.HEX_RE;exports.KNOWN_SCRIPT_PREFIXES=P.KNOWN_SCRIPT_PREFIXES;exports.MAX_REASONABLE_FEE_SATS=P.MAX_REASONABLE_FEE_SATS;exports.TXID_RE=P.TXID_RE;exports.PeginManager=n.PeginManager;exports.VAULT_APP_NAME=n.VAULT_APP_NAME;exports.buildFundingOutpointsCommitment=n.buildFundingOutpointsCommitment;exports.buildVaultContext=n.buildVaultContext;exports.computeWotsBlockPublicKeysHash=n.computeWotsBlockPublicKeysHash;exports.deriveVaultRoot=n.deriveVaultRoot;exports.deriveWotsBlocksFromSeed=n.deriveWotsBlocksFromSeed;exports.PayoutManager=g.PayoutManager;exports.computeHashlock=g.computeHashlock;exports.validateSecretAgainstHashlock=g.validateSecretAgainstHashlock;exports.ApplicationRegistryABI=R.ApplicationRegistryABI;exports.ProtocolParamsABI=R.ProtocolParamsABI;exports.BTCVaultRegistryABI=m.BTCVaultRegistryABI;exports.CONTRACT_ERRORS=T.CONTRACT_ERRORS;exports.extractErrorData=T.extractErrorData;exports.getContractErrorMessage=T.getContractErrorMessage;exports.handleContractError=T.handleContractError;exports.isKnownContractError=T.isKnownContractError;exports.BitcoinNetworks=b.BitcoinNetworks;exports.BitcoinScriptType=i.BitcoinScriptType;exports.applyChangeOutputPolicy=i.applyChangeOutputPolicy;exports.calculateBtcTxHash=i.calculateBtcTxHash;exports.computeChangeOutputFeeSats=i.computeChangeOutputFeeSats;exports.computeMaxDeposit=i.computeMaxDeposit;exports.computePeginBaseFeeSats=i.computePeginBaseFeeSats;exports.getDustThreshold=i.getDustThreshold;exports.getPsbtInputFields=i.getPsbtInputFields;exports.getScriptType=i.getScriptType;exports.selectUtxosForPegin=i.selectUtxosForPegin;exports.shouldAddChangeOutput=i.shouldAddChangeOutput;exports.waitForTransactionReceiptSmartAware=i.waitForTransactionReceiptSmartAware;exports.BTC_DUST_SAT=a.BTC_DUST_SAT;exports.DUST_THRESHOLD=a.DUST_THRESHOLD;exports.FEE_SAFETY_MARGIN=a.FEE_SAFETY_MARGIN;exports.LOW_RATE_ESTIMATION_ACCURACY_BUFFER=a.LOW_RATE_ESTIMATION_ACCURACY_BUFFER;exports.MAX_NON_LEGACY_OUTPUT_SIZE=a.MAX_NON_LEGACY_OUTPUT_SIZE;exports.P2TR_INPUT_SIZE=a.P2TR_INPUT_SIZE;exports.PEGIN_AUTH_ANCHOR_OUTPUTS=a.PEGIN_AUTH_ANCHOR_OUTPUTS;exports.PEGIN_FIXED_OUTPUTS=a.PEGIN_FIXED_OUTPUTS;exports.SPLIT_TX_FEE_SAFETY_MULTIPLIER=a.SPLIT_TX_FEE_SAFETY_MULTIPLIER;exports.TX_BUFFER_SIZE_OVERHEAD=a.TX_BUFFER_SIZE_OVERHEAD;exports.WALLET_RELAY_FEE_RATE_THRESHOLD=a.WALLET_RELAY_FEE_RATE_THRESHOLD;exports.fundPeginTransaction=a.fundPeginTransaction;exports.parseUnfundedWasmTransaction=a.parseUnfundedWasmTransaction;exports.peginOutputCount=a.peginOutputCount;exports.rateBasedTxBufferFee=a.rateBasedTxBufferFee;exports.UtxoNotAvailableError=l.UtxoNotAvailableError;exports.assertUtxosAvailable=l.assertUtxosAvailable;exports.collectReservedUtxoRefs=l.collectReservedUtxoRefs;exports.extractInputsFromTransaction=l.extractInputsFromTransaction;exports.selectUtxosForDeposit=l.selectUtxosForDeposit;exports.validateUtxosAvailable=l.validateUtxosAvailable;exports.MEMPOOL_API_URLS=s.MEMPOOL_API_URLS;exports.getAddressTxs=s.getAddressTxs;exports.getAddressUtxos=s.getAddressUtxos;exports.getMempoolApiUrl=s.getMempoolApiUrl;exports.getNetworkFees=s.getNetworkFees;exports.getTxHex=s.getTxHex;exports.getTxInfo=s.getTxInfo;exports.getUtxoInfo=s.getUtxoInfo;exports.pushTx=s.pushTx;exports.ServerIdentityError=t.ServerIdentityError;exports.VaultProviderRpcClient=t.VaultProviderRpcClient;exports.ViemProtocolParamsReader=t.ViemProtocolParamsReader;exports.ViemUniversalChallengerReader=t.ViemUniversalChallengerReader;exports.ViemVaultKeeperReader=t.ViemVaultKeeperReader;exports.ViemVaultRegistryReader=t.ViemVaultRegistryReader;exports.VpResponseValidationError=t.VpResponseValidationError;exports.VpTokenRegistry=t.VpTokenRegistry;exports.batchPollByProvider=t.batchPollByProvider;exports.createAuthenticatedVpClient=t.createAuthenticatedVpClient;exports.primeVpTokenRegistry=t.primeVpTokenRegistry;exports.resolveProtocolAddresses=t.resolveProtocolAddresses;exports.validateOffchainParams=t.validateOffchainParams;exports.validatePegInConfiguration=t.validatePegInConfiguration;exports.validateRequestDepositorClaimerArtifactsResponse=t.validateRequestDepositorClaimerArtifactsResponse;exports.validateTBVProtocolParams=t.validateTBVProtocolParams;exports.verifyServerIdentity=t.verifyServerIdentity;exports.vpTokenRegistry=t.vpTokenRegistry;exports.DaemonStatus=o.DaemonStatus;exports.JSON_RPC_ERROR_CODES=o.JSON_RPC_ERROR_CODES;exports.JsonRpcClient=o.JsonRpcClient;exports.JsonRpcError=o.JsonRpcError;exports.POST_WOTS_STATUSES=o.POST_WOTS_STATUSES;exports.PRE_DEPOSITOR_SIGNATURES_STATES=o.PRE_DEPOSITOR_SIGNATURES_STATES;exports.RpcErrorCode=o.RpcErrorCode;exports.VP_BATCH_MAX_SIZE=o.VP_BATCH_MAX_SIZE;exports.VP_TERMINAL_STATUSES=o.VP_TERMINAL_STATUSES;exports.VP_TRANSIENT_STATUSES=o.VP_TRANSIENT_STATUSES;exports.isWotsMismatchError=A.isWotsMismatchError;exports.parseFundingOutpointsFromTx=A.parseFundingOutpointsFromTx;exports.BIP68NotMatureError=e.BIP68NotMatureError;exports.ClaimerPegoutStatusValue=e.ClaimerPegoutStatusValue;exports.REFUND_VSIZE=e.REFUND_VSIZE;exports.RegisteredVaultVersionMismatchError=e.RegisteredVaultVersionMismatchError;exports.activateVault=e.activateVault;exports.buildAndBroadcastRefund=e.buildAndBroadcastRefund;exports.estimateRefundFeeSats=e.estimateRefundFeeSats;exports.isDepositAmountValid=e.isDepositAmountValid;exports.isPegoutTerminalStatus=e.isPegoutTerminalStatus;exports.isRecognizedPegoutStatus=e.isRecognizedPegoutStatus;exports.isRegisteredVaultVersionMismatchError=e.isRegisteredVaultVersionMismatchError;exports.runDepositorPresignFlow=e.runDepositorPresignFlow;exports.signDepositorGraph=e.signDepositorGraph;exports.submitWotsPublicKey=e.submitWotsPublicKey;exports.validateDepositAmount=e.validateDepositAmount;exports.validateMultiVaultDepositInputs=e.validateMultiVaultDepositInputs;exports.validateOnChainParticipantKeys=e.validateOnChainParticipantKeys;exports.validateProviderSelection=e.validateProviderSelection;exports.validateRemainingCapacity=e.validateRemainingCapacity;exports.validateVaultAmounts=e.validateVaultAmounts;exports.validateVaultProviderPubkey=e.validateVaultProviderPubkey;exports.verifyRegisteredVaultVersions=e.verifyRegisteredVaultVersions;exports.waitForPeginStatus=e.waitForPeginStatus;exports.ContractStatus=p.ContractStatus;exports.PeginAction=p.PeginAction;exports.canPerformAction=p.canPerformAction;exports.getPeginProtocolState=p.getPeginProtocolState;
2
2
  //# sourceMappingURL=index.cjs.map