@babylonlabs-io/ts-sdk 0.66.1 → 0.68.0

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 (157) hide show
  1. package/dist/PeginManager--2R3T2S8.js +1458 -0
  2. package/dist/PeginManager--2R3T2S8.js.map +1 -0
  3. package/dist/PeginManager-CKWq8ouZ.cjs +2 -0
  4. package/dist/PeginManager-CKWq8ouZ.cjs.map +1 -0
  5. package/dist/{batchPoll-cIxrSLLJ.js → batchPoll-Cjj1du0i.js} +372 -421
  6. package/dist/batchPoll-Cjj1du0i.js.map +1 -0
  7. package/dist/batchPoll-REVZiE-M.cjs +2 -0
  8. package/dist/batchPoll-REVZiE-M.cjs.map +1 -0
  9. package/dist/{bitcoin-d9eaaZB_.js → bitcoin-Ch_jxnDa.js} +3 -3
  10. package/dist/{bitcoin-d9eaaZB_.js.map → bitcoin-Ch_jxnDa.js.map} +1 -1
  11. package/dist/{buildAndBroadcastRefund-C4LiPATK.js → buildAndBroadcastRefund-CpMDJ8up.js} +142 -150
  12. package/dist/buildAndBroadcastRefund-CpMDJ8up.js.map +1 -0
  13. package/dist/buildAndBroadcastRefund-DrXwxrW1.cjs +2 -0
  14. package/dist/buildAndBroadcastRefund-DrXwxrW1.cjs.map +1 -0
  15. package/dist/challengeAssert-BNQ8sToz.js +64 -0
  16. package/dist/challengeAssert-BNQ8sToz.js.map +1 -0
  17. package/dist/challengeAssert-BrpC3-cQ.cjs +2 -0
  18. package/dist/challengeAssert-BrpC3-cQ.cjs.map +1 -0
  19. package/dist/index.cjs +1 -1
  20. package/dist/index.js +246 -243
  21. package/dist/mempoolApi-EU1La9wk.cjs +2 -0
  22. package/dist/{mempoolApi-CXfr-L6x.cjs.map → mempoolApi-EU1La9wk.cjs.map} +1 -1
  23. package/dist/{mempoolApi-BxSINXIB.js → mempoolApi-_D-jvtj_.js} +191 -117
  24. package/dist/{mempoolApi-BxSINXIB.js.map → mempoolApi-_D-jvtj_.js.map} +1 -1
  25. package/dist/{noPayout-BaZGRLD2.js → noPayout-CXn-geIS.js} +3 -3
  26. package/dist/{noPayout-BaZGRLD2.js.map → noPayout-CXn-geIS.js.map} +1 -1
  27. package/dist/{noPayout-CnQ1WLtr.cjs → noPayout-Ox27Td9x.cjs} +2 -2
  28. package/dist/{noPayout-CnQ1WLtr.cjs.map → noPayout-Ox27Td9x.cjs.map} +1 -1
  29. package/dist/{onChainBtcPubkey-DeF4cKoO.js → onChainBtcPubkey-BAHZyKQL.js} +2 -2
  30. package/dist/{onChainBtcPubkey-DeF4cKoO.js.map → onChainBtcPubkey-BAHZyKQL.js.map} +1 -1
  31. package/dist/{parseFundingOutpoints-pBRE11Hr.js → parseFundingOutpoints-CO-f6IHK.js} +2 -2
  32. package/dist/{parseFundingOutpoints-pBRE11Hr.js.map → parseFundingOutpoints-CO-f6IHK.js.map} +1 -1
  33. package/dist/{reservation-B4i_PQhY.js → reservation-CBAvoF3U.js} +2 -2
  34. package/dist/{reservation-B4i_PQhY.js.map → reservation-CBAvoF3U.js.map} +1 -1
  35. package/dist/{signPsbtsWithFallback-Bb66DfY5.js → signPsbtsWithFallback-Bv79gLFe.js} +122 -100
  36. package/dist/signPsbtsWithFallback-Bv79gLFe.js.map +1 -0
  37. package/dist/signPsbtsWithFallback-DJ4kE9UI.cjs +2 -0
  38. package/dist/signPsbtsWithFallback-DJ4kE9UI.cjs.map +1 -0
  39. package/dist/tbv/core/clients/index.cjs +1 -1
  40. package/dist/tbv/core/clients/index.js +3 -3
  41. package/dist/tbv/core/clients/vault-provider/auth/__tests__/bip322P2wpkhVectors.d.ts +32 -0
  42. package/dist/tbv/core/clients/vault-provider/auth/__tests__/bip322P2wpkhVectors.d.ts.map +1 -0
  43. package/dist/tbv/core/clients/vault-provider/auth/__tests__/bip322Verify.test.d.ts +9 -6
  44. package/dist/tbv/core/clients/vault-provider/auth/__tests__/bip322Verify.test.d.ts.map +1 -1
  45. package/dist/tbv/core/clients/vault-provider/auth/bip322Verify.d.ts +45 -20
  46. package/dist/tbv/core/clients/vault-provider/auth/bip322Verify.d.ts.map +1 -1
  47. package/dist/tbv/core/deposit-terms/__tests__/depositTerms.test.d.ts +2 -0
  48. package/dist/tbv/core/deposit-terms/__tests__/depositTerms.test.d.ts.map +1 -0
  49. package/dist/tbv/core/deposit-terms/depositTerms.d.ts +42 -5
  50. package/dist/tbv/core/deposit-terms/depositTerms.d.ts.map +1 -1
  51. package/dist/tbv/core/deposit-terms/prePeginApproval.d.ts +10 -5
  52. package/dist/tbv/core/deposit-terms/prePeginApproval.d.ts.map +1 -1
  53. package/dist/tbv/core/index.cjs +1 -1
  54. package/dist/tbv/core/index.js +244 -241
  55. package/dist/tbv/core/managers/PayoutManager.d.ts +8 -2
  56. package/dist/tbv/core/managers/PayoutManager.d.ts.map +1 -1
  57. package/dist/tbv/core/managers/PeginManager.d.ts +7 -0
  58. package/dist/tbv/core/managers/PeginManager.d.ts.map +1 -1
  59. package/dist/tbv/core/managers/index.cjs +1 -1
  60. package/dist/tbv/core/managers/index.js +2 -2
  61. package/dist/tbv/core/managers/pegin/__tests__/verifyPopWitness.test.d.ts +11 -0
  62. package/dist/tbv/core/managers/pegin/__tests__/verifyPopWitness.test.d.ts.map +1 -0
  63. package/dist/tbv/core/managers/pegin/expandPerVaultSecrets.d.ts.map +1 -1
  64. package/dist/tbv/core/managers/pegin/index.d.ts +1 -0
  65. package/dist/tbv/core/managers/pegin/index.d.ts.map +1 -1
  66. package/dist/tbv/core/managers/pegin/verifyPopWitness.d.ts +21 -0
  67. package/dist/tbv/core/managers/pegin/verifyPopWitness.d.ts.map +1 -0
  68. package/dist/tbv/core/primitives/challengers.d.ts +31 -5
  69. package/dist/tbv/core/primitives/challengers.d.ts.map +1 -1
  70. package/dist/tbv/core/primitives/index.cjs +1 -1
  71. package/dist/tbv/core/primitives/index.d.ts +2 -0
  72. package/dist/tbv/core/primitives/index.d.ts.map +1 -1
  73. package/dist/tbv/core/primitives/index.js +43 -41
  74. package/dist/tbv/core/primitives/psbt/__tests__/helpers.d.ts +5 -0
  75. package/dist/tbv/core/primitives/psbt/__tests__/helpers.d.ts.map +1 -1
  76. package/dist/tbv/core/primitives/psbt/__tests__/verifyKeyPathSchnorrSignature.test.d.ts +12 -0
  77. package/dist/tbv/core/primitives/psbt/__tests__/verifyKeyPathSchnorrSignature.test.d.ts.map +1 -0
  78. package/dist/tbv/core/primitives/psbt/payout.d.ts +19 -7
  79. package/dist/tbv/core/primitives/psbt/payout.d.ts.map +1 -1
  80. package/dist/tbv/core/primitives/psbt/pegin.d.ts +2 -2
  81. package/dist/tbv/core/primitives/psbt/verifyKeyPathSchnorrSignature.d.ts +64 -0
  82. package/dist/tbv/core/primitives/psbt/verifyKeyPathSchnorrSignature.d.ts.map +1 -0
  83. package/dist/tbv/core/primitives/psbt/verifyP2wpkhEcdsaSignature.d.ts +40 -0
  84. package/dist/tbv/core/primitives/psbt/verifyP2wpkhEcdsaSignature.d.ts.map +1 -0
  85. package/dist/tbv/core/primitives/psbt/verifyScriptPathSchnorrSignature.d.ts +2 -1
  86. package/dist/tbv/core/primitives/psbt/verifyScriptPathSchnorrSignature.d.ts.map +1 -1
  87. package/dist/tbv/core/primitives/utils/__tests__/taproot.test.d.ts +13 -0
  88. package/dist/tbv/core/primitives/utils/__tests__/taproot.test.d.ts.map +1 -0
  89. package/dist/tbv/core/primitives/utils/taproot.d.ts +29 -0
  90. package/dist/tbv/core/primitives/utils/taproot.d.ts.map +1 -0
  91. package/dist/tbv/core/services/deposit/runDepositorPresignFlow.d.ts +2 -2
  92. package/dist/tbv/core/services/deposit/runDepositorPresignFlow.d.ts.map +1 -1
  93. package/dist/tbv/core/services/deposit/signDepositorGraph.d.ts.map +1 -1
  94. package/dist/tbv/core/services/index.cjs +1 -1
  95. package/dist/tbv/core/services/index.js +2 -2
  96. package/dist/tbv/core/utils/index.js +2 -2
  97. package/dist/tbv/core/utils/witness/witnessStack.d.ts +24 -0
  98. package/dist/tbv/core/utils/witness/witnessStack.d.ts.map +1 -0
  99. package/dist/tbv/core/vault-secrets/index.js +1 -1
  100. package/dist/tbv/index.cjs +1 -1
  101. package/dist/tbv/index.js +244 -241
  102. package/dist/tbv/integrations/aave/clients/__tests__/query.test.d.ts +11 -0
  103. package/dist/tbv/integrations/aave/clients/__tests__/query.test.d.ts.map +1 -0
  104. package/dist/tbv/integrations/aave/clients/query.d.ts.map +1 -1
  105. package/dist/tbv/integrations/aave/index.cjs +1 -1
  106. package/dist/tbv/integrations/aave/index.cjs.map +1 -1
  107. package/dist/tbv/integrations/aave/index.js +132 -114
  108. package/dist/tbv/integrations/aave/index.js.map +1 -1
  109. package/dist/testing/MockBitcoinWallet.d.ts +10 -1
  110. package/dist/testing/MockBitcoinWallet.d.ts.map +1 -1
  111. package/dist/testing/__tests__/MockBitcoinWallet.test.d.ts +2 -0
  112. package/dist/testing/__tests__/MockBitcoinWallet.test.d.ts.map +1 -0
  113. package/dist/testing/index.cjs +1 -1
  114. package/dist/testing/index.cjs.map +1 -1
  115. package/dist/testing/index.js +134 -47
  116. package/dist/testing/index.js.map +1 -1
  117. package/dist/testing/signBip322P2wpkhWitness.d.ts +20 -0
  118. package/dist/testing/signBip322P2wpkhWitness.d.ts.map +1 -0
  119. package/dist/{toRefundInputs-BY_fcvrv.js → toRefundInputs-9hv_6k0E.js} +6 -6
  120. package/dist/{toRefundInputs-BY_fcvrv.js.map → toRefundInputs-9hv_6k0E.js.map} +1 -1
  121. package/dist/{toRefundInputs-DYL9C-aG.cjs → toRefundInputs-D8sFs44p.cjs} +2 -2
  122. package/dist/{toRefundInputs-DYL9C-aG.cjs.map → toRefundInputs-D8sFs44p.cjs.map} +1 -1
  123. package/dist/verifyKeyPathSchnorrSignature-DCOzQkDf.cjs +2 -0
  124. package/dist/verifyKeyPathSchnorrSignature-DCOzQkDf.cjs.map +1 -0
  125. package/dist/verifyKeyPathSchnorrSignature-oGCUbjjZ.js +363 -0
  126. package/dist/verifyKeyPathSchnorrSignature-oGCUbjjZ.js.map +1 -0
  127. package/dist/verifyScriptPathSchnorrSignature-Dy9gF5RF.js +931 -0
  128. package/dist/verifyScriptPathSchnorrSignature-Dy9gF5RF.js.map +1 -0
  129. package/dist/verifyScriptPathSchnorrSignature-la8XOAFm.cjs +2 -0
  130. package/dist/verifyScriptPathSchnorrSignature-la8XOAFm.cjs.map +1 -0
  131. package/package.json +2 -2
  132. package/dist/PeginManager-BBl4xkWz.js +0 -1359
  133. package/dist/PeginManager-BBl4xkWz.js.map +0 -1
  134. package/dist/PeginManager-p-ajwSxG.cjs +0 -2
  135. package/dist/PeginManager-p-ajwSxG.cjs.map +0 -1
  136. package/dist/batchPoll-6L5oToGr.cjs +0 -2
  137. package/dist/batchPoll-6L5oToGr.cjs.map +0 -1
  138. package/dist/batchPoll-cIxrSLLJ.js.map +0 -1
  139. package/dist/buildAndBroadcastRefund-C4LiPATK.js.map +0 -1
  140. package/dist/buildAndBroadcastRefund-Daw5ZUKR.cjs +0 -2
  141. package/dist/buildAndBroadcastRefund-Daw5ZUKR.cjs.map +0 -1
  142. package/dist/challengeAssert-BFRE2DM-.cjs +0 -2
  143. package/dist/challengeAssert-BFRE2DM-.cjs.map +0 -1
  144. package/dist/challengeAssert-C7PzyJ7g.js +0 -75
  145. package/dist/challengeAssert-C7PzyJ7g.js.map +0 -1
  146. package/dist/mempoolApi-CXfr-L6x.cjs +0 -2
  147. package/dist/peginInput-Ci921gTl.cjs +0 -2
  148. package/dist/peginInput-Ci921gTl.cjs.map +0 -1
  149. package/dist/peginInput-HQPWZfly.js +0 -123
  150. package/dist/peginInput-HQPWZfly.js.map +0 -1
  151. package/dist/signPsbtsWithFallback-Bb66DfY5.js.map +0 -1
  152. package/dist/signPsbtsWithFallback-PTgWxsG3.cjs +0 -2
  153. package/dist/signPsbtsWithFallback-PTgWxsG3.cjs.map +0 -1
  154. package/dist/verifyScriptPathSchnorrSignature-DPAd_qke.cjs +0 -2
  155. package/dist/verifyScriptPathSchnorrSignature-DPAd_qke.cjs.map +0 -1
  156. package/dist/verifyScriptPathSchnorrSignature-i-koT139.js +0 -817
  157. package/dist/verifyScriptPathSchnorrSignature-i-koT139.js.map +0 -1
@@ -0,0 +1,1458 @@
1
+ var qt = Object.defineProperty;
2
+ var Gt = (s, t, e) => t in s ? qt(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e;
3
+ var y = (s, t, e) => Gt(s, typeof t != "symbol" ? t + "" : t, e);
4
+ import { c as St, H as Yt, r as W, a as K, b as it, u as zt, d as at, e as ct, f as lt, g as jt, s as _t } from "./sha2-BYVxyZzX.js";
5
+ import * as At from "bitcoinjs-lib";
6
+ import { Transaction as Ct, Psbt as ut } from "bitcoinjs-lib";
7
+ import { Buffer as O } from "buffer";
8
+ import { isAddressEqual as ht, encodeFunctionData as J, zeroAddress as Qt } from "viem";
9
+ import { B as H } from "./BTCVaultRegistry.abi-CJwWI2EO.js";
10
+ import { h as R } from "./errors-Blc-JWnI.js";
11
+ import { expandWotsSeed as Zt, expandHashlockSecret as Jt, expandAuthAnchor as te, deriveVaultId as dt } from "@babylonlabs-io/babylon-tbv-rust-wasm";
12
+ import { a as ft, b as ee, f as pt, g as se } from "./verifyScriptPathSchnorrSignature-Dy9gF5RF.js";
13
+ import { d as oe, b as ne, e as re, f as ie, c as ae } from "./verifyKeyPathSchnorrSignature-oGCUbjjZ.js";
14
+ import { p as ce, h as tt, u as et, e as C, i as gt, s as B, k as mt, X as le } from "./bitcoin-Ch_jxnDa.js";
15
+ import { c as ue } from "./signing-DaLvGwQe.js";
16
+ import { M as bt } from "./validation-Dj3dqYtl.js";
17
+ import { p as he, d as It } from "./parseFundingOutpoints-CO-f6IHK.js";
18
+ import { c as de, s as U, r as fe, b as pe, d as ge } from "./signPsbtsWithFallback-Bv79gLFe.js";
19
+ import { s as me, f as G, i as be, w as wt } from "./waitForTransactionReceiptSmartAware-lobLm0q0.js";
20
+ import { p as we, f as Pe } from "./fundPeginTransaction-B2wyjqp0.js";
21
+ import { M as X, B as xe } from "./constants-GjWXdaqV.js";
22
+ import { l as ye, m as ke, p as Ee, V as Te, i as ve } from "./mempoolApi-_D-jvtj_.js";
23
+ import * as Be from "@bitcoin-js/tiny-secp256k1-asmjs";
24
+ const F = /* @__PURE__ */ BigInt(2 ** 32 - 1), Pt = /* @__PURE__ */ BigInt(32);
25
+ function Se(s, t = !1) {
26
+ return t ? { h: Number(s & F), l: Number(s >> Pt & F) } : { h: Number(s >> Pt & F) | 0, l: Number(s & F) | 0 };
27
+ }
28
+ function _e(s, t = !1) {
29
+ const e = s.length;
30
+ let o = new Uint32Array(e), i = new Uint32Array(e);
31
+ for (let r = 0; r < e; r++) {
32
+ const { h: n, l: a } = Se(s[r], t);
33
+ [o[r], i[r]] = [n, a];
34
+ }
35
+ return [o, i];
36
+ }
37
+ const Ae = (s, t, e) => s << e | t >>> 32 - e, Ce = (s, t, e) => t << e | s >>> 32 - e, Ie = (s, t, e) => t << e - 32 | s >>> 64 - e, He = (s, t, e) => s << e - 32 | t >>> 64 - e, Re = 64;
38
+ function $e(s) {
39
+ const t = s.prepeginTxid.toLowerCase();
40
+ if (!/^[0-9a-f]+$/.test(t) || t.length !== Re)
41
+ throw new Error(
42
+ `buildDepositTerms: prepeginTxid must be 64 hex chars, got "${s.prepeginTxid}"`
43
+ );
44
+ if (s.peginAmounts.length === 0)
45
+ throw new Error("buildDepositTerms: at least one pegin amount is required");
46
+ if (s.timelockPegin <= 0 || s.timelockAssert <= 0 || s.timelockRefund <= 0)
47
+ throw new Error("buildDepositTerms: timelocks must be positive");
48
+ if (!Number.isInteger(s.maxAcceptableCommissionBps) || s.maxAcceptableCommissionBps < 0 || s.maxAcceptableCommissionBps >= X)
49
+ throw new Error(
50
+ `buildDepositTerms: maxAcceptableCommissionBps must be an integer in [0, ${X}), got ${s.maxAcceptableCommissionBps}`
51
+ );
52
+ const e = BigInt(xe), o = s.peginAmounts.map(
53
+ (i, r) => ({
54
+ htlcVout: r,
55
+ vaultProviderBtcPubkey: s.vaultProviderBtcPubkey,
56
+ peginAmount: i,
57
+ // Ceiling, not quote: floor(peginAmount * maxAcceptableBps / 10_000) —
58
+ // the same bound the registration calldata enforces on-chain, so any
59
+ // stamped commission the contract admits stays under it (firmware
60
+ // >= c8db53e checks the payout commission output <= this value).
61
+ commissionFee: i * BigInt(s.maxAcceptableCommissionBps) / e,
62
+ depositorClaimValue: s.depositorClaimValue,
63
+ peginMaxFee: s.peginMaxFee
64
+ })
65
+ );
66
+ return {
67
+ vaultCoreVersion: s.vaultCoreVersion,
68
+ protocolFeeRate: s.protocolFeeRate,
69
+ timelockPegin: s.timelockPegin,
70
+ timelockAssert: s.timelockAssert,
71
+ timelockRefund: s.timelockRefund,
72
+ prepeginTxid: t,
73
+ prepeginMaxFee: s.prepeginMaxFee,
74
+ vaultKeeperBtcPubkeys: [...s.vaultKeeperBtcPubkeys],
75
+ universalChallengerBtcPubkeys: [...s.universalChallengerBtcPubkeys],
76
+ vaults: o
77
+ };
78
+ }
79
+ const st = 25, Ht = 9999;
80
+ function Y(s) {
81
+ if (!Number.isInteger(s) || s < 0 || s >= X)
82
+ throw new Error(
83
+ `Quoted commissionBps must be an integer in [0, ${X}), got ${s}`
84
+ );
85
+ return Math.min(
86
+ s + st,
87
+ Ht
88
+ );
89
+ }
90
+ const Oe = /^0x[0-9a-f]+$/i, Ve = /^[0-9a-f]+$/i, Me = /^[A-Za-z0-9+/]+={0,2}$/;
91
+ function $(s) {
92
+ if (typeof s != "string" || s.length === 0)
93
+ throw new Error("BTC wallet returned empty public key");
94
+ return ce(s).toLowerCase();
95
+ }
96
+ function We(s) {
97
+ if (typeof s != "string" || s.length === 0)
98
+ throw new Error("BTC wallet returned empty BIP-322 signature");
99
+ if (s.startsWith("0x") || s.startsWith("0X")) {
100
+ if (!Oe.test(s) || s.length < 4 || s.length % 2 !== 0)
101
+ throw new Error("BTC wallet returned malformed hex BIP-322 signature");
102
+ return s.toLowerCase();
103
+ }
104
+ if (Ve.test(s)) {
105
+ if (s.length % 2 !== 0)
106
+ throw new Error("BTC wallet returned malformed hex BIP-322 signature");
107
+ return `0x${s.toLowerCase()}`;
108
+ }
109
+ if (!Me.test(s) || s.length % 4 !== 0)
110
+ throw new Error("BTC wallet returned malformed base64 BIP-322 signature");
111
+ const t = O.from(s, "base64");
112
+ if (t.length === 0 || t.toString("base64") !== s)
113
+ throw new Error("BTC wallet returned malformed base64 BIP-322 signature");
114
+ return `0x${t.toString("hex")}`;
115
+ }
116
+ async function Ue(s) {
117
+ const { wallet: t, depositTerms: e, fundedPrePeginTxHex: o, depositorBtcPubkey: i } = s, r = typeof t.approveDepositTerms == "function" ? t.approveDepositTerms : void 0;
118
+ if (!r && !e)
119
+ return;
120
+ const n = o.startsWith("0x") ? o.slice(2) : o, c = Ct.fromHex(n).getId();
121
+ if (e && e.prepeginTxid.replace(/^0x/, "").toLowerCase() !== c)
122
+ throw new Error(
123
+ `Deposit terms do not match the transaction being broadcast: terms are for prepeginTxid ${e.prepeginTxid}, but this transaction is ${c}.`
124
+ );
125
+ if (!r)
126
+ return;
127
+ if (!e)
128
+ throw new Error(
129
+ "This wallet requires approved deposit terms before signing the Pre-PegIn transaction, but none were provided. Pass PreparePeginResult.depositTerms (fresh flows) or a resume rebuild."
130
+ );
131
+ if (typeof t.deriveContextHash != "function")
132
+ throw new Error(
133
+ "A deposit-approval wallet must also implement deriveContextHash, but this one does not."
134
+ );
135
+ if (typeof t.holdsApprovedDepositTerms == "function") {
136
+ let g = !1;
137
+ try {
138
+ g = await t.holdsApprovedDepositTerms(e);
139
+ } catch {
140
+ }
141
+ if (g)
142
+ return;
143
+ }
144
+ const u = he(o);
145
+ (await It(
146
+ { deriveContextHash: t.deriveContextHash.bind(t) },
147
+ {
148
+ depositorBtcPubkey: tt(
149
+ $(i)
150
+ ),
151
+ fundingOutpoints: u
152
+ }
153
+ )).fill(0), await r.call(t, e);
154
+ }
155
+ const Fe = /* @__PURE__ */ Uint8Array.from([
156
+ 7,
157
+ 4,
158
+ 13,
159
+ 1,
160
+ 10,
161
+ 6,
162
+ 15,
163
+ 3,
164
+ 12,
165
+ 0,
166
+ 9,
167
+ 5,
168
+ 2,
169
+ 14,
170
+ 11,
171
+ 8
172
+ ]), Rt = Uint8Array.from(new Array(16).fill(0).map((s, t) => t)), Ne = Rt.map((s) => (9 * s + 5) % 16), $t = /* @__PURE__ */ (() => {
173
+ const e = [[Rt], [Ne]];
174
+ for (let o = 0; o < 4; o++)
175
+ for (let i of e)
176
+ i.push(i[o].map((r) => Fe[r]));
177
+ return e;
178
+ })(), Ot = $t[0], Vt = $t[1], Mt = /* @__PURE__ */ [
179
+ [11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8],
180
+ [12, 13, 11, 15, 6, 9, 9, 7, 12, 15, 11, 13, 7, 8, 7, 7],
181
+ [13, 15, 14, 11, 7, 7, 6, 8, 13, 14, 13, 12, 5, 5, 6, 9],
182
+ [14, 11, 12, 14, 8, 6, 5, 5, 15, 12, 15, 14, 9, 9, 8, 6],
183
+ [15, 12, 13, 13, 9, 5, 8, 6, 14, 11, 12, 11, 8, 6, 5, 5]
184
+ ].map((s) => Uint8Array.from(s)), De = /* @__PURE__ */ Ot.map((s, t) => s.map((e) => Mt[t][e])), Le = /* @__PURE__ */ Vt.map((s, t) => s.map((e) => Mt[t][e])), Ke = /* @__PURE__ */ Uint32Array.from([
185
+ 0,
186
+ 1518500249,
187
+ 1859775393,
188
+ 2400959708,
189
+ 2840853838
190
+ ]), Xe = /* @__PURE__ */ Uint32Array.from([
191
+ 1352829926,
192
+ 1548603684,
193
+ 1836072691,
194
+ 2053994217,
195
+ 0
196
+ ]);
197
+ function xt(s, t, e, o) {
198
+ return s === 0 ? t ^ e ^ o : s === 1 ? t & e | ~t & o : s === 2 ? (t | ~e) ^ o : s === 3 ? t & o | e & ~o : t ^ (e | ~o);
199
+ }
200
+ const N = /* @__PURE__ */ new Uint32Array(16);
201
+ class qe extends Yt {
202
+ constructor() {
203
+ super(64, 20, 8, !0);
204
+ y(this, "h0", 1732584193);
205
+ y(this, "h1", -271733879);
206
+ y(this, "h2", -1732584194);
207
+ y(this, "h3", 271733878);
208
+ y(this, "h4", -1009589776);
209
+ }
210
+ get() {
211
+ const { h0: e, h1: o, h2: i, h3: r, h4: n } = this;
212
+ return [e, o, i, r, n];
213
+ }
214
+ set(e, o, i, r, n) {
215
+ this.h0 = e | 0, this.h1 = o | 0, this.h2 = i | 0, this.h3 = r | 0, this.h4 = n | 0;
216
+ }
217
+ process(e, o) {
218
+ for (let d = 0; d < 16; d++, o += 4)
219
+ N[d] = e.getUint32(o, !0);
220
+ let i = this.h0 | 0, r = i, n = this.h1 | 0, a = n, c = this.h2 | 0, u = c, h = this.h3 | 0, g = h, b = this.h4 | 0, w = b;
221
+ for (let d = 0; d < 5; d++) {
222
+ const E = 4 - d, k = Ke[d], f = Xe[d], v = Ot[d], _ = Vt[d], p = De[d], P = Le[d];
223
+ for (let l = 0; l < 16; l++) {
224
+ const x = W(i + xt(d, n, c, h) + N[v[l]] + k, p[l]) + b | 0;
225
+ i = b, b = h, h = W(c, 10) | 0, c = n, n = x;
226
+ }
227
+ for (let l = 0; l < 16; l++) {
228
+ const x = W(r + xt(E, a, u, g) + N[_[l]] + f, P[l]) + w | 0;
229
+ r = w, w = g, g = W(u, 10) | 0, u = a, a = x;
230
+ }
231
+ }
232
+ this.set(this.h1 + c + g | 0, this.h2 + h + w | 0, this.h3 + b + r | 0, this.h4 + i + a | 0, this.h0 + n + u | 0);
233
+ }
234
+ roundClean() {
235
+ K(N);
236
+ }
237
+ destroy() {
238
+ this.destroyed = !0, K(this.buffer), this.set(0, 0, 0, 0, 0);
239
+ }
240
+ }
241
+ const Ge = /* @__PURE__ */ St(() => new qe()), Ye = BigInt(0), M = BigInt(1), ze = BigInt(2), je = BigInt(7), Qe = BigInt(256), Ze = BigInt(113), Wt = [], Ut = [], Ft = [];
242
+ for (let s = 0, t = M, e = 1, o = 0; s < 24; s++) {
243
+ [e, o] = [o, (2 * e + 3 * o) % 5], Wt.push(2 * (5 * o + e)), Ut.push((s + 1) * (s + 2) / 2 % 64);
244
+ let i = Ye;
245
+ for (let r = 0; r < 7; r++)
246
+ t = (t << M ^ (t >> je) * Ze) % Qe, t & ze && (i ^= M << (M << BigInt(r)) - M);
247
+ Ft.push(i);
248
+ }
249
+ const Nt = _e(Ft, !0), Je = Nt[0], ts = Nt[1], yt = (s, t, e) => e > 32 ? Ie(s, t, e) : Ae(s, t, e), kt = (s, t, e) => e > 32 ? He(s, t, e) : Ce(s, t, e);
250
+ function es(s, t = 24) {
251
+ const e = new Uint32Array(10);
252
+ for (let o = 24 - t; o < 24; o++) {
253
+ for (let n = 0; n < 10; n++)
254
+ e[n] = s[n] ^ s[n + 10] ^ s[n + 20] ^ s[n + 30] ^ s[n + 40];
255
+ for (let n = 0; n < 10; n += 2) {
256
+ const a = (n + 8) % 10, c = (n + 2) % 10, u = e[c], h = e[c + 1], g = yt(u, h, 1) ^ e[a], b = kt(u, h, 1) ^ e[a + 1];
257
+ for (let w = 0; w < 50; w += 10)
258
+ s[n + w] ^= g, s[n + w + 1] ^= b;
259
+ }
260
+ let i = s[2], r = s[3];
261
+ for (let n = 0; n < 24; n++) {
262
+ const a = Ut[n], c = yt(i, r, a), u = kt(i, r, a), h = Wt[n];
263
+ i = s[h], r = s[h + 1], s[h] = c, s[h + 1] = u;
264
+ }
265
+ for (let n = 0; n < 50; n += 10) {
266
+ for (let a = 0; a < 10; a++)
267
+ e[a] = s[n + a];
268
+ for (let a = 0; a < 10; a++)
269
+ s[n + a] ^= ~e[(a + 2) % 10] & e[(a + 4) % 10];
270
+ }
271
+ s[0] ^= Je[o], s[1] ^= ts[o];
272
+ }
273
+ K(e);
274
+ }
275
+ class nt {
276
+ // NOTE: we accept arguments in bytes instead of bits here.
277
+ constructor(t, e, o, i = !1, r = 24) {
278
+ y(this, "state");
279
+ y(this, "pos", 0);
280
+ y(this, "posOut", 0);
281
+ y(this, "finished", !1);
282
+ y(this, "state32");
283
+ y(this, "destroyed", !1);
284
+ y(this, "blockLen");
285
+ y(this, "suffix");
286
+ y(this, "outputLen");
287
+ y(this, "enableXOF", !1);
288
+ y(this, "rounds");
289
+ if (this.blockLen = t, this.suffix = e, this.outputLen = o, this.enableXOF = i, this.rounds = r, it(o, "outputLen"), !(0 < t && t < 200))
290
+ throw new Error("only keccak-f1600 function is supported");
291
+ this.state = new Uint8Array(200), this.state32 = zt(this.state);
292
+ }
293
+ clone() {
294
+ return this._cloneInto();
295
+ }
296
+ keccak() {
297
+ at(this.state32), es(this.state32, this.rounds), at(this.state32), this.posOut = 0, this.pos = 0;
298
+ }
299
+ update(t) {
300
+ ct(this), lt(t);
301
+ const { blockLen: e, state: o } = this, i = t.length;
302
+ for (let r = 0; r < i; ) {
303
+ const n = Math.min(e - this.pos, i - r);
304
+ for (let a = 0; a < n; a++)
305
+ o[this.pos++] ^= t[r++];
306
+ this.pos === e && this.keccak();
307
+ }
308
+ return this;
309
+ }
310
+ finish() {
311
+ if (this.finished)
312
+ return;
313
+ this.finished = !0;
314
+ const { state: t, suffix: e, pos: o, blockLen: i } = this;
315
+ t[o] ^= e, (e & 128) !== 0 && o === i - 1 && this.keccak(), t[i - 1] ^= 128, this.keccak();
316
+ }
317
+ writeInto(t) {
318
+ ct(this, !1), lt(t), this.finish();
319
+ const e = this.state, { blockLen: o } = this;
320
+ for (let i = 0, r = t.length; i < r; ) {
321
+ this.posOut >= o && this.keccak();
322
+ const n = Math.min(o - this.posOut, r - i);
323
+ t.set(e.subarray(this.posOut, this.posOut + n), i), this.posOut += n, i += n;
324
+ }
325
+ return t;
326
+ }
327
+ xofInto(t) {
328
+ if (!this.enableXOF)
329
+ throw new Error("XOF is not possible for this instance");
330
+ return this.writeInto(t);
331
+ }
332
+ xof(t) {
333
+ return it(t), this.xofInto(new Uint8Array(t));
334
+ }
335
+ digestInto(t) {
336
+ if (jt(t, this), this.finished)
337
+ throw new Error("digest() was already called");
338
+ return this.writeInto(t), this.destroy(), t;
339
+ }
340
+ digest() {
341
+ return this.digestInto(new Uint8Array(this.outputLen));
342
+ }
343
+ destroy() {
344
+ this.destroyed = !0, K(this.state);
345
+ }
346
+ _cloneInto(t) {
347
+ const { blockLen: e, suffix: o, outputLen: i, rounds: r, enableXOF: n } = this;
348
+ return t || (t = new nt(e, o, i, n, r)), t.state32.set(this.state32), t.pos = this.pos, t.posOut = this.posOut, t.finished = this.finished, t.rounds = r, t.suffix = o, t.outputLen = i, t.enableXOF = n, t.destroyed = this.destroyed, t;
349
+ }
350
+ }
351
+ const ss = (s, t, e, o = {}) => St(() => new nt(t, s, e), o), os = /* @__PURE__ */ ss(1, 136, 32), Et = 64, S = 20, ot = 4, Dt = 2, ns = 0, rs = 1, D = [64, 64], is = (s) => Array.from(s).map((t) => t.toString(16).padStart(2, "0")).join("");
352
+ function rt(s) {
353
+ return Ge(_t(s));
354
+ }
355
+ function Lt(s) {
356
+ return (1 << s) - 1;
357
+ }
358
+ function as(s) {
359
+ let t = 1;
360
+ for (; t * t < s + 1; ) t++;
361
+ return Math.max(t, 2);
362
+ }
363
+ function cs(s) {
364
+ const t = ot, e = s * Lt(t);
365
+ return { d: t, n: s, checksum_radix: as(e) };
366
+ }
367
+ function z(s, t) {
368
+ const e = [];
369
+ let o = t;
370
+ for (; o > 0; )
371
+ e.push(o & 255), o >>>= 8;
372
+ const i = new Uint8Array(s.length + e.length);
373
+ i.set(s);
374
+ for (let r = 0; r < e.length; r++)
375
+ i[s.length + r] = e[r];
376
+ return rt(i);
377
+ }
378
+ function j(s, t) {
379
+ let e = s;
380
+ for (let o = 0; o < t; o++)
381
+ e = rt(e);
382
+ return e;
383
+ }
384
+ function ls(s, t) {
385
+ const e = Lt(t.d), o = t.checksum_radix - 1, i = Math.floor(t.n * e / t.checksum_radix), r = [];
386
+ for (let h = 0; h < t.n; h++) {
387
+ const g = z(s, h + Dt), b = j(g, e);
388
+ r.push(Array.from(b));
389
+ }
390
+ const n = z(
391
+ s,
392
+ ns
393
+ ), a = j(
394
+ n,
395
+ o
396
+ ), c = z(
397
+ s,
398
+ rs
399
+ ), u = j(
400
+ c,
401
+ i
402
+ );
403
+ return {
404
+ config: t,
405
+ message_terminals: r,
406
+ checksum_major_terminal: Array.from(u),
407
+ checksum_minor_terminal: Array.from(a)
408
+ };
409
+ }
410
+ async function us(s) {
411
+ try {
412
+ if (s.length !== Et)
413
+ throw new Error(
414
+ `WOTS seed must be exactly ${Et} bytes, got ${s.length}`
415
+ );
416
+ const t = [];
417
+ for (let e = 0; e < D.length; e++) {
418
+ const o = D[e], i = cs(o), r = new Uint8Array(s.length + 1);
419
+ r.set(s), r[s.length] = e;
420
+ const n = rt(r);
421
+ try {
422
+ const a = ls(n, i);
423
+ if (a.config.d !== ot)
424
+ throw new Error(
425
+ `Block ${e}: expected d=${ot}, got d=${a.config.d}`
426
+ );
427
+ if (a.config.n !== o)
428
+ throw new Error(
429
+ `Block ${e}: expected n=${o}, got n=${a.config.n}`
430
+ );
431
+ if (a.message_terminals.length !== o)
432
+ throw new Error(
433
+ `Block ${e}: expected ${o} message terminals, got ${a.message_terminals.length}`
434
+ );
435
+ for (let c = 0; c < a.message_terminals.length; c++)
436
+ if (a.message_terminals[c].length !== S)
437
+ throw new Error(
438
+ `Block ${e} terminal ${c}: expected ${S} bytes, got ${a.message_terminals[c].length}`
439
+ );
440
+ if (a.checksum_minor_terminal.length !== S)
441
+ throw new Error(
442
+ `Block ${e} checksum_minor: expected ${S} bytes`
443
+ );
444
+ if (a.checksum_major_terminal.length !== S)
445
+ throw new Error(
446
+ `Block ${e} checksum_major: expected ${S} bytes`
447
+ );
448
+ t.push(a);
449
+ } finally {
450
+ r.fill(0), n.fill(0);
451
+ }
452
+ }
453
+ if (t.length !== D.length)
454
+ throw new Error(
455
+ `Expected ${D.length} blocks, got ${t.length}`
456
+ );
457
+ return t;
458
+ } finally {
459
+ s.fill(0);
460
+ }
461
+ }
462
+ function Q(s, t, e) {
463
+ if (s.length !== S)
464
+ throw new Error(
465
+ `Block ${t} ${e}: expected ${S} bytes, got ${s.length}`
466
+ );
467
+ for (let o = 0; o < s.length; o++) {
468
+ const i = s[o];
469
+ if (!Number.isInteger(i) || i < 0 || i > 255)
470
+ throw new Error(
471
+ `Block ${t} ${e}[${o}]: invalid byte value ${i}`
472
+ );
473
+ }
474
+ }
475
+ function hs(s) {
476
+ if (s.length === 0)
477
+ throw new Error("Public keys array must not be empty");
478
+ for (let r = 0; r < s.length; r++) {
479
+ const n = s[r];
480
+ Q(n.checksum_minor_terminal, r, "checksum_minor_terminal"), Q(n.checksum_major_terminal, r, "checksum_major_terminal");
481
+ for (let a = 0; a < n.message_terminals.length; a++)
482
+ Q(n.message_terminals[a], r, `message_terminal[${a}]`);
483
+ }
484
+ let t = 0;
485
+ for (const r of s)
486
+ t += Dt + r.message_terminals.length;
487
+ const e = new Uint8Array(t * S);
488
+ let o = 0;
489
+ for (const r of s) {
490
+ e.set(r.checksum_minor_terminal, o), o += S, e.set(r.checksum_major_terminal, o), o += S;
491
+ for (const n of r.message_terminals)
492
+ e.set(n, o), o += S;
493
+ }
494
+ const i = os(e);
495
+ return `0x${is(i)}`;
496
+ }
497
+ async function ds(s, t) {
498
+ const e = [], o = [], i = [], r = [];
499
+ try {
500
+ for (let n = 0; n < t; n++) {
501
+ const a = await Zt(s, n);
502
+ try {
503
+ const u = await us(a);
504
+ e.push(u), o.push(hs(u));
505
+ } finally {
506
+ a.fill(0);
507
+ }
508
+ const c = await Jt(s, n);
509
+ try {
510
+ const u = et(c);
511
+ i.push(u), r.push(de(C(u)).slice(2));
512
+ } finally {
513
+ c.fill(0);
514
+ }
515
+ }
516
+ } finally {
517
+ s.fill(0);
518
+ }
519
+ return { perVaultWotsKeys: e, wotsPkHashes: o, htlcSecretHexes: i, hashlocks: r };
520
+ }
521
+ const fs = 1, ps = 2, gs = 33, ms = 2, bs = 3, ws = 1, L = 64, Ps = 0, Tt = 1, vt = /^[0-9a-f]{64}$/i, xs = /^(?:[0-9a-f]{2})+$/;
522
+ function ys(s) {
523
+ const t = s.slice(2);
524
+ if (!xs.test(t))
525
+ throw new Error(
526
+ "proof of possession witness is not even-length lowercase hex"
527
+ );
528
+ return oe(
529
+ Uint8Array.from(O.from(t, "hex")),
530
+ "proof of possession witness"
531
+ );
532
+ }
533
+ function ks(s, t, e) {
534
+ var i;
535
+ const o = ys(e);
536
+ if (o.length === fs) {
537
+ const [r] = o;
538
+ let n, a;
539
+ if (r.length === L)
540
+ n = r, a = Ps;
541
+ else if (r.length === L + 1 && r[L] === Tt)
542
+ n = r.subarray(0, L), a = Tt;
543
+ else
544
+ throw new Error(
545
+ "proof of possession witness item must be a 64-byte Schnorr signature (or 65 bytes ending in 0x01)"
546
+ );
547
+ if (!vt.test(t))
548
+ throw new Error(
549
+ `depositor public key must be bare 64-char x-only hex, got "${t}"`
550
+ );
551
+ const c = Uint8Array.from(O.from(t, "hex"));
552
+ if (!ye(s, c, n, a))
553
+ throw new Error(
554
+ "proof of possession signature does not verify against the depositor key"
555
+ );
556
+ return { kind: "p2tr-verified" };
557
+ }
558
+ if (o.length === ps) {
559
+ if (!vt.test(t))
560
+ throw new Error(
561
+ `depositor public key must be bare 64-char x-only hex, got "${t}"`
562
+ );
563
+ const [r, n] = o;
564
+ if (n.length !== gs || n[0] !== ms && n[0] !== bs)
565
+ throw new Error(
566
+ `proof of possession P2WPKH witness item 1 is not a compressed public key (${n.length} bytes, prefix 0x${((i = n[0]) == null ? void 0 : i.toString(16)) ?? "none"})`
567
+ );
568
+ if (!Be.isPointCompressed(n))
569
+ throw new Error(
570
+ "proof of possession P2WPKH witness pubkey is not a valid secp256k1 point"
571
+ );
572
+ const a = O.from(
573
+ n.subarray(ws)
574
+ ).toString("hex");
575
+ if (a !== t.toLowerCase())
576
+ throw new Error(
577
+ `proof of possession witness pubkey does not match the depositor key: witness carries ${a}, expected ${t}`
578
+ );
579
+ if (!ke(s, n, r))
580
+ throw new Error(
581
+ "proof of possession signature does not verify against the depositor key"
582
+ );
583
+ return { kind: "p2wpkh-verified" };
584
+ }
585
+ throw new Error(
586
+ `proof of possession witness has ${o.length} items; expected 1 (P2TR) or 2 (P2WPKH)`
587
+ );
588
+ }
589
+ const Kt = 0, Z = "00".repeat(32);
590
+ function Es(s, t) {
591
+ const e = {
592
+ bitcoin: "bc",
593
+ testnet: "tb",
594
+ signet: "tb",
595
+ regtest: "bcrt"
596
+ };
597
+ try {
598
+ const o = At.address.fromBech32(s);
599
+ return o.prefix === e[t] && o.version === 0 && o.data.length === 20;
600
+ } catch {
601
+ return !1;
602
+ }
603
+ }
604
+ function Ts(s, t, e, o) {
605
+ const i = e == null ? void 0 : e[`${s}:${t}`];
606
+ return i ? Promise.resolve({
607
+ txid: s,
608
+ vout: t,
609
+ value: i.value,
610
+ scriptPubKey: i.scriptPubKey
611
+ }) : ve(s, t, o);
612
+ }
613
+ const Bt = 12e4;
614
+ class js {
615
+ /**
616
+ * Creates a new PeginManager instance.
617
+ *
618
+ * @param config - Manager configuration including wallets and contract addresses
619
+ */
620
+ constructor(t) {
621
+ y(this, "config");
622
+ this.config = t;
623
+ }
624
+ /**
625
+ * Prepare a peg-in: sizing pass → vault-root derivation (one wallet
626
+ * popup) → per-vault WOTS / hashlock derivation → commit pass with
627
+ * PSBT signing (signPsbt for a single vault, one batch popup for a
628
+ * split). Returns broadcast-ready txs, the pubkey snapshot, and the
629
+ * sensitive derived material.
630
+ *
631
+ * @throws If the wallet rejects, insufficient funds, or an internal
632
+ * invariant violation.
633
+ */
634
+ async preparePegin(t) {
635
+ if (t.amounts.length === 0)
636
+ throw new Error("amounts must contain at least one entry");
637
+ const e = await this.config.btcWallet.getPublicKeyHex(), o = $(e);
638
+ if (U(this.config.btcWallet)) {
639
+ const f = (await fe(this.config.btcWallet)).trim();
640
+ if (t.changeAddress.trim() !== f)
641
+ throw new Error(
642
+ `Pre-PegIn changeAddress "${t.changeAddress}" is not the approval wallet's change address ("${f}"). Refusing to build a tx the signing device would reject.`
643
+ );
644
+ } else if (!gt(
645
+ t.changeAddress,
646
+ e,
647
+ this.config.btcNetwork
648
+ ))
649
+ throw new Error(
650
+ `Pre-PegIn changeAddress "${t.changeAddress}" is not derived from the connected wallet's public key. Refusing to build a tx that would send change to an address the signing key doesn't control.`
651
+ );
652
+ const i = await this.prepareSizing(o, t), r = i.selectedUTXOs.map(
653
+ (f) => ({
654
+ txid: tt(f.txid),
655
+ vout: f.vout
656
+ })
657
+ ), n = await It(this.config.btcWallet, {
658
+ depositorBtcPubkey: tt(o),
659
+ fundingOutpoints: r
660
+ });
661
+ let a, c;
662
+ try {
663
+ const f = await te(n);
664
+ try {
665
+ a = et(f), c = et(_t(f));
666
+ } finally {
667
+ f.fill(0);
668
+ }
669
+ } catch (f) {
670
+ throw n.fill(0), f;
671
+ }
672
+ const u = await ds(n, t.amounts.length), { perVaultWotsKeys: h, wotsPkHashes: g, htlcSecretHexes: b, hashlocks: w } = u, d = await this.preparePeginCommit({
673
+ depositorBtcPubkeyRaw: e,
674
+ depositorBtcPubkey: o,
675
+ hashlocks: w,
676
+ authAnchorHash: c,
677
+ sizing: i,
678
+ params: t
679
+ });
680
+ for (let f = 0; f < d.perVault.length; f++)
681
+ if (d.perVault[f].htlcVout !== f)
682
+ throw new Error(
683
+ `Internal invariant violation: htlcVout/index mismatch at vault ${f} (expected ${f}, got ${d.perVault[f].htlcVout})`
684
+ );
685
+ pe(
686
+ d.fundedPrePeginTxHex,
687
+ t.amounts.length,
688
+ c
689
+ );
690
+ const { depositTerms: E, ...k } = d;
691
+ return {
692
+ transaction: {
693
+ ...k,
694
+ selectedUTXOs: i.selectedUTXOs,
695
+ fee: i.fee,
696
+ changeAmount: i.changeAmount
697
+ },
698
+ depositorBtcPubkey: o,
699
+ derivedSecrets: {
700
+ perVaultWotsKeys: h,
701
+ wotsPkHashes: g,
702
+ htlcSecretHexes: b,
703
+ authAnchorHex: a
704
+ },
705
+ depositTerms: E
706
+ };
707
+ }
708
+ /**
709
+ * Build unfunded Pre-PegIn + select UTXOs. No PSBT signing.
710
+ *
711
+ * Returns the full selection result (UTXOs, fee, changeAmount) so the
712
+ * commit pass funds the broadcast tx with the exact same set used to
713
+ * build the vault-context funding-outpoints commitment. Re-running
714
+ * `selectUtxosForPegin` in the commit pass would be deterministic given
715
+ * the same inputs, but threading the result through guarantees the
716
+ * domain separator structurally matches the funded tx inputs.
717
+ *
718
+ * Sizing runs before the wallet popup, so neither the real per-vault
719
+ * hashlocks nor the real `authAnchorHash` are known yet. Both slots
720
+ * are filled with a 32-byte placeholder; the commit pass swaps in the
721
+ * real values. Output budget is identical (32-byte push regardless of
722
+ * content), so UTXO selection is invariant under substitution.
723
+ */
724
+ async prepareSizing(t, e) {
725
+ const o = e.amounts.map(
726
+ () => Z
727
+ ), i = e.vaultKeeperBtcPubkeys.length, r = await ft({
728
+ vaultCoreVersion: e.vaultCoreVersion,
729
+ depositorPubkey: t,
730
+ vaultProviderPubkey: B(e.vaultProviderBtcPubkey),
731
+ vaultKeeperPubkeys: e.vaultKeeperBtcPubkeys.map(B),
732
+ universalChallengerPubkeys: e.universalChallengerBtcPubkeys.map(B),
733
+ hashlocks: o,
734
+ timelockRefund: e.timelockRefund,
735
+ pegInAmounts: e.amounts,
736
+ feeRate: e.protocolFeeRate,
737
+ minPeginFeeRate: e.minPeginFeeRate,
738
+ numLocalChallengers: i,
739
+ councilQuorum: e.councilQuorum,
740
+ councilSize: e.councilSize,
741
+ network: this.config.btcNetwork,
742
+ authAnchorHash: Z
743
+ }), n = me(
744
+ [...e.availableUTXOs],
745
+ r.totalOutputValue,
746
+ e.mempoolFeeRate,
747
+ we(r.htlcValues.length, !0)
748
+ );
749
+ return {
750
+ selectedUTXOs: n.selectedUTXOs,
751
+ fee: n.fee,
752
+ changeAmount: n.changeAmount
753
+ };
754
+ }
755
+ /** Build PegIn txs and batch-sign their inputs with real hashlocks. */
756
+ async preparePeginCommit(t) {
757
+ const {
758
+ depositorBtcPubkeyRaw: e,
759
+ depositorBtcPubkey: o,
760
+ hashlocks: i,
761
+ authAnchorHash: r,
762
+ sizing: n,
763
+ params: a
764
+ } = t, c = Z.toLowerCase();
765
+ for (let m = 0; m < i.length; m++)
766
+ if (i[m].toLowerCase() === c)
767
+ throw new Error(
768
+ `preparePeginCommit refusing to build with sizing-pass placeholder hashlock at vault ${m} — internal substitution bug`
769
+ );
770
+ if (r.toLowerCase() === c)
771
+ throw new Error(
772
+ "preparePeginCommit refusing to build with sizing-pass placeholder auth-anchor hash — internal substitution bug"
773
+ );
774
+ const u = B(
775
+ a.vaultProviderBtcPubkey
776
+ ), h = a.vaultKeeperBtcPubkeys.map(B), g = a.universalChallengerBtcPubkeys.map(B), b = h.length, w = {
777
+ vaultCoreVersion: a.vaultCoreVersion,
778
+ depositorPubkey: o,
779
+ vaultProviderPubkey: u,
780
+ vaultKeeperPubkeys: h,
781
+ universalChallengerPubkeys: g,
782
+ hashlocks: i,
783
+ timelockRefund: a.timelockRefund,
784
+ pegInAmounts: a.amounts,
785
+ feeRate: a.protocolFeeRate,
786
+ minPeginFeeRate: a.minPeginFeeRate,
787
+ numLocalChallengers: b,
788
+ councilQuorum: a.councilQuorum,
789
+ councilSize: a.councilSize,
790
+ network: this.config.btcNetwork,
791
+ authAnchorHash: r
792
+ }, d = await ft(w), E = mt(this.config.btcNetwork), k = Pe({
793
+ unfundedTxHex: d.psbtHex,
794
+ selectedUTXOs: n.selectedUTXOs,
795
+ changeAddress: a.changeAddress,
796
+ changeAmount: n.changeAmount,
797
+ network: E
798
+ }), f = n.selectedUTXOs.reduce((m, T) => m + BigInt(T.value), 0n) - d.totalOutputValue - n.changeAmount;
799
+ if (f !== n.fee)
800
+ throw new Error(
801
+ `Pre-PegIn funded fee ${f} does not match the sizing-pass fee ${n.fee}; refusing to publish a deposit-terms fee bound the funded transaction does not pay.`
802
+ );
803
+ const v = B(
804
+ G(k)
805
+ ), _ = [], p = [], P = [];
806
+ for (let m = 0; m < i.length; m++) {
807
+ const T = await ee({
808
+ prePeginParams: w,
809
+ timelockPegin: a.timelockPegin,
810
+ fundedPrePeginTxHex: k,
811
+ htlcVout: m
812
+ }), I = await ne({
813
+ vaultCoreVersion: a.vaultCoreVersion,
814
+ peginTxHex: T.txHex,
815
+ fundedPrePeginTxHex: k,
816
+ depositorPubkey: o,
817
+ vaultProviderPubkey: u,
818
+ vaultKeeperPubkeys: h,
819
+ universalChallengerPubkeys: g,
820
+ hashlock: i[m],
821
+ timelockRefund: a.timelockRefund,
822
+ network: this.config.btcNetwork
823
+ });
824
+ _.push(T), p.push(I.psbtHex), P.push(
825
+ ue(e, 1)
826
+ );
827
+ }
828
+ const l = $e({
829
+ vaultCoreVersion: a.vaultCoreVersion,
830
+ protocolFeeRate: a.protocolFeeRate,
831
+ timelockPegin: a.timelockPegin,
832
+ timelockAssert: a.timelockAssert,
833
+ timelockRefund: a.timelockRefund,
834
+ prepeginTxid: v,
835
+ prepeginMaxFee: n.fee,
836
+ vaultProviderBtcPubkey: u,
837
+ vaultKeeperBtcPubkeys: h,
838
+ universalChallengerBtcPubkeys: g,
839
+ maxAcceptableCommissionBps: Y(
840
+ a.commissionBps
841
+ ),
842
+ peginAmounts: a.amounts,
843
+ depositorClaimValue: d.depositorClaimValue,
844
+ peginMaxFee: d.minPeginFee
845
+ });
846
+ U(this.config.btcWallet) && await this.config.btcWallet.approveDepositTerms(l);
847
+ const x = await ge(
848
+ this.config.btcWallet,
849
+ p,
850
+ P
851
+ ), A = [];
852
+ for (let m = 0; m < x.length; m++) {
853
+ pt({
854
+ requestedPsbtHex: p[m],
855
+ returnedPsbtHex: x[m]
856
+ });
857
+ const T = re(
858
+ x[m],
859
+ o
860
+ );
861
+ se({
862
+ requestedPsbtHex: p[m],
863
+ signatureHex: T,
864
+ signerXOnlyPubkeyHex: o,
865
+ inputIndex: 0
866
+ });
867
+ const I = ie(x[m]);
868
+ A.push({
869
+ htlcVout: m,
870
+ htlcValue: d.htlcValues[m],
871
+ peginTxHex: I,
872
+ peginTxid: _[m].txid,
873
+ peginInputSignature: T,
874
+ vaultScriptPubKey: _[m].vaultScriptPubKey
875
+ });
876
+ }
877
+ return {
878
+ fundedPrePeginTxHex: k,
879
+ prePeginTxid: v,
880
+ perVault: A,
881
+ depositTerms: l
882
+ };
883
+ }
884
+ /**
885
+ * Signs and broadcasts a funded peg-in transaction to the Bitcoin network.
886
+ *
887
+ * This method:
888
+ * 1. Parses the funded transaction hex
889
+ * 2. Fetches UTXO data from mempool for each input
890
+ * 3. Creates a PSBT with proper witnessUtxo/tapInternalKey
891
+ * 4. Signs via btcWallet.signPsbt()
892
+ * 5. Finalizes and extracts the transaction
893
+ * 6. Broadcasts via mempool API
894
+ *
895
+ * IMPORTANT — this method does NOT gate on Ethereum finality. Committing
896
+ * BTC to the HTLC while the peg-in registration is still reorg-exposed can
897
+ * strand the deposit: the vault record disappears from the chain while the
898
+ * BTC stays locked until the HTLC refund timelock. Callers must await
899
+ * `waitForPeginRegistrationDepth` for the registered vault(s) before calling
900
+ * this. The gate is not applied here because the params carry no vault ID —
901
+ * adding one would be a breaking signature change.
902
+ *
903
+ * @param params - Transaction hex and depositor public key
904
+ * @returns The broadcasted Bitcoin transaction ID
905
+ * @throws Error if signing or broadcasting fails
906
+ */
907
+ async signAndBroadcast(t) {
908
+ const { fundedPrePeginTxHex: e, depositorBtcPubkey: o } = t, i = e.startsWith("0x") ? e.slice(2) : e, r = Ct.fromHex(i);
909
+ if (r.ins.length === 0)
910
+ throw new Error("Transaction has no inputs");
911
+ const n = new ut();
912
+ n.setVersion(r.version), n.setLocktime(r.locktime);
913
+ const a = O.from(
914
+ $(o),
915
+ "hex"
916
+ ), c = this.config.mempoolApiUrl, u = r.ins.map((p) => {
917
+ const P = O.from(p.hash).reverse().toString("hex"), l = p.index;
918
+ return Ts(P, l, t.localPrevouts, c).then(
919
+ (x) => ({ input: p, utxoData: x, txid: P, vout: l })
920
+ );
921
+ }), h = await Promise.all(u), g = h.reduce(
922
+ (p, P) => p + BigInt(P.utxoData.value),
923
+ 0n
924
+ ), b = r.outs.reduce(
925
+ (p, P) => p + BigInt(P.value),
926
+ 0n
927
+ );
928
+ if (g < b)
929
+ throw new Error(
930
+ `UTXO value mismatch: total input value (${g} sat) is less than total output value (${b} sat). This may indicate the mempool API returned manipulated UTXO data.`
931
+ );
932
+ const w = g - b;
933
+ if (w > bt)
934
+ throw new Error(
935
+ `Implied transaction fee (${w} sat) exceeds maximum reasonable fee (${bt} sat). This may indicate manipulated UTXO data.`
936
+ );
937
+ for (const { input: p, utxoData: P, txid: l, vout: x } of h) {
938
+ const A = be(
939
+ {
940
+ value: P.value,
941
+ scriptPubKey: P.scriptPubKey
942
+ },
943
+ a
944
+ );
945
+ n.addInput({
946
+ hash: p.hash,
947
+ index: p.index,
948
+ sequence: p.sequence,
949
+ ...A
950
+ });
951
+ }
952
+ for (const p of r.outs)
953
+ n.addOutput({
954
+ script: p.script,
955
+ value: p.value
956
+ });
957
+ await Ue({
958
+ wallet: this.config.btcWallet,
959
+ depositTerms: t.depositTerms,
960
+ fundedPrePeginTxHex: e,
961
+ depositorBtcPubkey: o
962
+ });
963
+ const d = n.toHex(), E = await this.config.btcWallet.signPsbt(d);
964
+ pt({
965
+ requestedPsbtHex: d,
966
+ returnedPsbtHex: E
967
+ });
968
+ const k = ae({
969
+ requestedPsbtHex: d,
970
+ returnedPsbtHex: E
971
+ });
972
+ if (U(this.config.btcWallet) && k !== n.data.inputs.length)
973
+ throw new Error(
974
+ `Key-path verification covered ${k} of ${n.data.inputs.length} Pre-PegIn inputs; an approval wallet signs every input key-path, so the unverified ones must not be broadcast.`
975
+ );
976
+ const f = ut.fromHex(E);
977
+ try {
978
+ f.finalizeAllInputs();
979
+ } catch (p) {
980
+ if (!f.data.inputs.every(
981
+ (l) => l.finalScriptWitness || l.finalScriptSig
982
+ ))
983
+ throw new Error(
984
+ `PSBT finalization failed and wallet did not auto-finalize: ${p}`
985
+ );
986
+ }
987
+ const v = f.extractTransaction().toHex();
988
+ return await Ee(v, c);
989
+ }
990
+ /**
991
+ * Registers a peg-in on Ethereum by calling the BTCVaultRegistry contract.
992
+ *
993
+ * This method:
994
+ * 1. Re-verifies the PopSignature against the currently connected ETH
995
+ * and BTC wallets — refuses to proceed if either has changed
996
+ * 2. Derives vault ID and checks if it already exists (pre-flight)
997
+ * 3. Encodes the contract call using viem
998
+ * 4. Estimates gas (catches contract errors early with proper revert
999
+ * reasons)
1000
+ * 5. Sends transaction with pre-estimated gas via
1001
+ * ethWallet.sendTransaction()
1002
+ *
1003
+ * The PopSignature must be obtained via
1004
+ * {@link signProofOfPossession} before this call.
1005
+ *
1006
+ * @param params - Registration parameters including the PopSignature
1007
+ * and the prepared Pre-PegIn / PegIn transactions
1008
+ * @returns Result containing Ethereum transaction hash and vault ID
1009
+ * @throws Error if the PopSignature does not match the connected wallets
1010
+ * @throws Error if the vault already exists
1011
+ * @throws Error if contract simulation fails (e.g., invalid signature,
1012
+ * unauthorized)
1013
+ */
1014
+ async registerPeginOnChain(t) {
1015
+ const {
1016
+ unsignedPrePeginTx: e,
1017
+ depositorSignedPeginTx: o,
1018
+ vaultProvider: i,
1019
+ hashlock: r,
1020
+ htlcVout: n,
1021
+ depositorPayoutBtcAddress: a,
1022
+ depositorWotsPkHash: c,
1023
+ popSignature: u
1024
+ } = t;
1025
+ if (!this.config.ethWallet.account)
1026
+ throw new Error("Ethereum wallet account not found");
1027
+ const h = this.config.ethWallet.account.address;
1028
+ if (!ht(u.depositorEthAddress, h))
1029
+ throw new Error(
1030
+ `Proof of possession was signed for ${u.depositorEthAddress} but the Ethereum wallet is currently connected to ${h}. Reconnect the original account or call signProofOfPossession() again.`
1031
+ );
1032
+ const g = await this.assertPopMatchesBtcWallet(u), b = u.btcPopSignature, w = C(
1033
+ u.depositorBtcPubkey
1034
+ ), d = C(e), E = C(o), k = a ?? await this.config.btcWallet.getAddress(), f = this.resolvePayoutScriptPubKey(
1035
+ g,
1036
+ k
1037
+ ), v = G(E), _ = await dt(
1038
+ B(v),
1039
+ B(h)
1040
+ ), p = C(_);
1041
+ if (await this.checkVaultExists(p))
1042
+ throw new Error(
1043
+ `Vault already exists (ID: ${p}, peginTxHash: ${v}). Vault IDs are derived from the pegin transaction hash and depositor address. To create a new vault, use different UTXOs or a different amount to generate a unique transaction.`
1044
+ );
1045
+ const l = this.config.publicClient;
1046
+ let x;
1047
+ try {
1048
+ x = await l.readContract({
1049
+ address: this.config.vaultContracts.btcVaultRegistry,
1050
+ abi: H,
1051
+ functionName: "getPegInFee",
1052
+ args: [i]
1053
+ });
1054
+ } catch (V) {
1055
+ throw new Error(
1056
+ "Failed to query pegin fee from the contract. Please check your network connection and that the contract address is correct.",
1057
+ { cause: V }
1058
+ );
1059
+ }
1060
+ const A = await this.resolveMaxAcceptableCommissionBps(
1061
+ i,
1062
+ t.quotedCommissionBps
1063
+ ), m = J({
1064
+ abi: H,
1065
+ functionName: "submitPeginRequest",
1066
+ args: [
1067
+ h,
1068
+ w,
1069
+ b,
1070
+ d,
1071
+ E,
1072
+ i,
1073
+ A,
1074
+ r,
1075
+ n,
1076
+ f,
1077
+ c
1078
+ ]
1079
+ });
1080
+ let T;
1081
+ try {
1082
+ T = await l.estimateGas({
1083
+ to: this.config.vaultContracts.btcVaultRegistry,
1084
+ data: m,
1085
+ value: x,
1086
+ account: this.config.ethWallet.account.address
1087
+ });
1088
+ } catch (V) {
1089
+ R(V);
1090
+ }
1091
+ let I;
1092
+ try {
1093
+ I = await this.config.ethWallet.sendTransaction({
1094
+ to: this.config.vaultContracts.btcVaultRegistry,
1095
+ data: m,
1096
+ value: x,
1097
+ account: this.config.ethWallet.account,
1098
+ chain: this.config.ethChain,
1099
+ gas: T
1100
+ });
1101
+ } catch (V) {
1102
+ R(V);
1103
+ }
1104
+ const q = await wt({
1105
+ publicClient: l,
1106
+ walletAddress: this.config.ethWallet.account.address,
1107
+ hash: I,
1108
+ timeout: Bt
1109
+ });
1110
+ return q.status === "reverted" && R(
1111
+ new Error(
1112
+ `Transaction reverted. Hash: ${q.transactionHash}. Check the transaction on block explorer for details.`
1113
+ )
1114
+ ), {
1115
+ ethTxHash: q.transactionHash,
1116
+ vaultId: p,
1117
+ peginTxHash: v
1118
+ };
1119
+ }
1120
+ /**
1121
+ * Register multiple pegins on Ethereum in a single transaction.
1122
+ *
1123
+ * Uses the contract's submitPeginRequestBatch() to submit all vault
1124
+ * registrations atomically. All vaults must share the same vault provider.
1125
+ * The PoP signature is signed once and included in each request.
1126
+ *
1127
+ * @param params - Batch registration parameters
1128
+ * @returns Batch result with per-vault IDs and single ETH tx hash
1129
+ */
1130
+ async registerPeginBatchOnChain(t) {
1131
+ const { vaultProvider: e, unsignedPrePeginTx: o, requests: i, popSignature: r } = t;
1132
+ if (i.length === 0)
1133
+ throw new Error("Batch pegin requires at least one request");
1134
+ if (!this.config.ethWallet.account)
1135
+ throw new Error("Ethereum wallet account not found");
1136
+ const n = this.config.ethWallet.account.address;
1137
+ if (!ht(r.depositorEthAddress, n))
1138
+ throw new Error(
1139
+ `Proof of possession was signed for ${r.depositorEthAddress} but the Ethereum wallet is currently connected to ${n}. Reconnect the original account or call signProofOfPossession() again.`
1140
+ );
1141
+ const a = await this.assertPopMatchesBtcWallet(r), c = r.btcPopSignature, u = i.map(
1142
+ (l) => this.resolvePayoutScriptPubKey(
1143
+ a,
1144
+ l.depositorPayoutBtcAddress
1145
+ )
1146
+ ), h = [];
1147
+ for (const l of i) {
1148
+ const x = C(
1149
+ l.depositorSignedPeginTx
1150
+ ), A = G(x), m = await dt(
1151
+ B(A),
1152
+ B(n)
1153
+ ), T = C(m);
1154
+ if (await this.checkVaultExists(T))
1155
+ throw new Error(
1156
+ `Vault already exists (ID: ${T}, peginTxHash: ${A}). To create a new vault, use different UTXOs or a different amount.`
1157
+ );
1158
+ h.push({ vaultId: T, peginTxHash: A });
1159
+ }
1160
+ const g = this.config.publicClient;
1161
+ let b;
1162
+ try {
1163
+ b = await g.readContract({
1164
+ address: this.config.vaultContracts.btcVaultRegistry,
1165
+ abi: H,
1166
+ functionName: "getPegInFee",
1167
+ args: [e]
1168
+ });
1169
+ } catch (l) {
1170
+ throw new Error(
1171
+ "Failed to query pegin fee from the contract. Please check your network connection and that the contract address is correct.",
1172
+ { cause: l }
1173
+ );
1174
+ }
1175
+ const w = b * BigInt(i.length), d = await this.resolveMaxAcceptableCommissionBps(
1176
+ e,
1177
+ t.quotedCommissionBps
1178
+ ), E = C(
1179
+ r.depositorBtcPubkey
1180
+ ), k = C(o), f = i.map((l, x) => ({
1181
+ depositorBtcPubKey: E,
1182
+ btcPopSignature: c,
1183
+ unsignedPrePeginTx: k,
1184
+ depositorSignedPeginTx: C(
1185
+ l.depositorSignedPeginTx
1186
+ ),
1187
+ hashlock: l.hashlock,
1188
+ htlcVout: l.htlcVout,
1189
+ referralCode: Kt,
1190
+ depositorPayoutBtcAddress: u[x],
1191
+ depositorWotsPkHash: l.depositorWotsPkHash
1192
+ })), v = J({
1193
+ abi: H,
1194
+ functionName: "submitPeginRequestBatch",
1195
+ args: [
1196
+ n,
1197
+ e,
1198
+ d,
1199
+ f
1200
+ ]
1201
+ });
1202
+ let _;
1203
+ try {
1204
+ _ = await g.estimateGas({
1205
+ to: this.config.vaultContracts.btcVaultRegistry,
1206
+ data: v,
1207
+ value: w,
1208
+ account: this.config.ethWallet.account.address
1209
+ });
1210
+ } catch (l) {
1211
+ R(l);
1212
+ }
1213
+ let p;
1214
+ try {
1215
+ p = await this.config.ethWallet.sendTransaction({
1216
+ to: this.config.vaultContracts.btcVaultRegistry,
1217
+ data: v,
1218
+ value: w,
1219
+ account: this.config.ethWallet.account,
1220
+ chain: this.config.ethChain,
1221
+ gas: _
1222
+ });
1223
+ } catch (l) {
1224
+ R(l);
1225
+ }
1226
+ const P = await wt({
1227
+ publicClient: g,
1228
+ walletAddress: this.config.ethWallet.account.address,
1229
+ hash: p,
1230
+ timeout: Bt
1231
+ });
1232
+ return P.status === "reverted" && R(
1233
+ new Error(
1234
+ `Batch transaction reverted. Hash: ${P.transactionHash}. Check the transaction on block explorer for details.`
1235
+ )
1236
+ ), {
1237
+ ethTxHash: P.transactionHash,
1238
+ vaults: h
1239
+ };
1240
+ }
1241
+ // Anchor to quoted+headroom when supplied (refuse if chain drifted past it);
1242
+ // otherwise fall back to chain-current+headroom — see #1691.
1243
+ async resolveMaxAcceptableCommissionBps(t, e) {
1244
+ if (e === void 0 && U(this.config.btcWallet))
1245
+ throw new Error(
1246
+ "quotedCommissionBps is required when the wallet approved deposit terms: the registration ceiling must anchor to the approved quote."
1247
+ );
1248
+ let o;
1249
+ try {
1250
+ o = await new Te(
1251
+ this.config.publicClient,
1252
+ this.config.vaultContracts.btcVaultRegistry
1253
+ ).getVaultProviderCommission(t);
1254
+ } catch (i) {
1255
+ throw new Error(
1256
+ "Failed to query vault provider commission from the contract. Please check your network connection and that the contract address is correct.",
1257
+ { cause: i }
1258
+ );
1259
+ }
1260
+ if (e !== void 0) {
1261
+ if (o > e + st)
1262
+ throw new Error(
1263
+ `Vault provider commission changed since quote: quoted ${e} bps, chain currently reports ${o} bps (allowed drift ${st} bps). Please refresh to see the new commission and try again.`
1264
+ );
1265
+ return Y(e);
1266
+ }
1267
+ return Y(o);
1268
+ }
1269
+ /**
1270
+ * Check if a vault already exists for a given vault ID.
1271
+ *
1272
+ * The contract returns a default struct (with `depositor === zeroAddress`)
1273
+ * when no vault is registered, so existence is signalled in the response,
1274
+ * not via a thrown error. RPC/network failures are propagated rather than
1275
+ * silently treated as "vault doesn't exist", which would otherwise let
1276
+ * downstream calls run with stale assumptions.
1277
+ *
1278
+ * @param vaultId - The Bitcoin transaction hash (vault ID)
1279
+ * @returns True if vault exists, false otherwise
1280
+ * @throws If the underlying RPC read fails
1281
+ */
1282
+ async checkVaultExists(t) {
1283
+ return (await this.config.publicClient.readContract({
1284
+ address: this.config.vaultContracts.btcVaultRegistry,
1285
+ abi: H,
1286
+ functionName: "getBtcVaultBasicInfo",
1287
+ args: [t]
1288
+ })).depositor !== Qt;
1289
+ }
1290
+ /**
1291
+ * Resolve the BTC scriptPubKey to register as the depositor's payout sink.
1292
+ *
1293
+ * `address` is validated against the verified depositor pubkey, sourced
1294
+ * from `assertPopMatchesBtcWallet`'s return value rather than
1295
+ * `popSignature.depositorBtcPubkey` (which is x-only, parity stripped).
1296
+ * For wallets that expose a compressed key this preserves y-parity end to
1297
+ * end. For Taproot wallets that only expose an x-only key, the helper
1298
+ * itself fails closed for P2WPKH — the parity is unknowable, so the
1299
+ * payout sink must be a P2TR address derived from that same x.
1300
+ *
1301
+ * The helper does not call into the wallet so the batch path can resolve
1302
+ * many requests without any extra adapter reads. Threat closed: a
1303
+ * state-race or stale FE state that lets a non-wallet address reach the
1304
+ * on-chain payout-script registration.
1305
+ */
1306
+ resolvePayoutScriptPubKey(t, e) {
1307
+ if (!gt(
1308
+ e,
1309
+ t,
1310
+ this.config.btcNetwork
1311
+ ))
1312
+ throw B(t).length === le && Es(e, this.config.btcNetwork) ? new Error(
1313
+ `BTC payout address "${e}" is a P2WPKH (Native SegWit) address, but the connected wallet only exposes an x-only public key. P2WPKH validation requires a compressed key with known y-parity. Use a P2TR (Taproot) payout address instead.`
1314
+ ) : new Error(
1315
+ `BTC payout address "${e}" is not derived from the connected wallet's public key. The payout sink must be controlled by the same key that signs the pegin; refusing to register a mismatched address.`
1316
+ );
1317
+ const o = mt(this.config.btcNetwork);
1318
+ try {
1319
+ return `0x${At.address.toOutputScript(e, o).toString("hex")}`;
1320
+ } catch {
1321
+ throw new Error(
1322
+ `Invalid BTC payout address: "${e}". Please provide a valid Bitcoin address for the ${this.config.btcNetwork} network.`
1323
+ );
1324
+ }
1325
+ }
1326
+ /**
1327
+ * Sign a BIP-322 BTC Proof-of-Possession binding the connected BTC
1328
+ * wallet to the connected ETH account for this chain and vault
1329
+ * registry. The returned {@link PopSignature} can be reused across
1330
+ * every register call in the same session.
1331
+ *
1332
+ * The witness is verified against the depositor key before it is
1333
+ * returned — Schnorr for one-item (P2TR), ECDSA over the BIP-322
1334
+ * P2WPKH virtual transaction for two-item — see {@link verifyPopWitness}.
1335
+ *
1336
+ * @throws If the wallet returns a malformed witness or a signature that
1337
+ * does not verify.
1338
+ */
1339
+ async signProofOfPossession() {
1340
+ if (!this.config.ethWallet.account)
1341
+ throw new Error("Ethereum wallet account not found");
1342
+ const t = this.config.ethWallet.account.address, e = $(
1343
+ await this.config.btcWallet.getPublicKeyHex()
1344
+ ), o = this.config.vaultContracts.btcVaultRegistry, i = `${t.toLowerCase()}:${this.config.ethChain.id}:pegin:${o.toLowerCase()}`, r = await this.config.btcWallet.signMessage(
1345
+ i,
1346
+ "bip322-simple"
1347
+ ), n = We(r);
1348
+ return ks(
1349
+ new TextEncoder().encode(i),
1350
+ e,
1351
+ n
1352
+ ), { btcPopSignature: n, depositorEthAddress: t, depositorBtcPubkey: e };
1353
+ }
1354
+ /**
1355
+ * Confirm the connected BTC wallet still matches the PoP it produced, and
1356
+ * return the wallet's *raw* pubkey hex (parity-preserving form, as the
1357
+ * wallet adapter returns it). The raw form is required by callers that
1358
+ * validate Native SegWit / P2WPKH addresses, since P2WPKH is derived from
1359
+ * a parity-bearing compressed key — an x-only form would let an attacker
1360
+ * substitute the opposite-parity P2WPKH address.
1361
+ */
1362
+ async assertPopMatchesBtcWallet(t) {
1363
+ const e = await this.config.btcWallet.getPublicKeyHex(), o = $(e), i = $(t.depositorBtcPubkey);
1364
+ if (o !== i)
1365
+ throw new Error(
1366
+ `Proof of possession was signed with BTC pubkey ${i} but the BTC wallet is currently connected to ${o}. Reconnect the original wallet or call signProofOfPossession() again.`
1367
+ );
1368
+ return e;
1369
+ }
1370
+ /**
1371
+ * Gets the configured Bitcoin network.
1372
+ *
1373
+ * @returns The Bitcoin network (mainnet, testnet, signet, regtest)
1374
+ */
1375
+ getNetwork() {
1376
+ return this.config.btcNetwork;
1377
+ }
1378
+ /**
1379
+ * Gets the configured BTCVaultRegistry contract address.
1380
+ *
1381
+ * @returns The Ethereum address of the BTCVaultRegistry contract
1382
+ */
1383
+ getVaultContractAddress() {
1384
+ return this.config.vaultContracts.btcVaultRegistry;
1385
+ }
1386
+ }
1387
+ const vs = 80, Bs = 250, Ss = 300, _s = 22, Xt = "ab";
1388
+ function As(s, t) {
1389
+ const e = Xt.repeat(Ss), o = B(s).toLowerCase(), i = t.toString(16).padStart(8, "0"), r = `${o}${i}`, n = e.slice(r.length);
1390
+ return `0x${r}${n}`;
1391
+ }
1392
+ function Cs(s, t) {
1393
+ const e = (o) => `0x${Xt.repeat(o)}`;
1394
+ return {
1395
+ depositorBtcPubKey: e(32),
1396
+ btcPopSignature: e(vs),
1397
+ unsignedPrePeginTx: e(Bs),
1398
+ depositorSignedPeginTx: As(
1399
+ s,
1400
+ t
1401
+ ),
1402
+ hashlock: e(32),
1403
+ htlcVout: t,
1404
+ referralCode: Kt,
1405
+ depositorPayoutBtcAddress: e(_s),
1406
+ depositorWotsPkHash: e(32)
1407
+ };
1408
+ }
1409
+ async function Qs(s) {
1410
+ const {
1411
+ publicClient: t,
1412
+ btcVaultRegistry: e,
1413
+ depositorEthAddress: o,
1414
+ vaultProvider: i,
1415
+ batchSize: r
1416
+ } = s;
1417
+ if (r <= 0)
1418
+ throw new Error(
1419
+ `estimateSubmitPeginRequestBatchGas requires batchSize >= 1 (received ${r})`
1420
+ );
1421
+ const a = await t.readContract({
1422
+ address: e,
1423
+ abi: H,
1424
+ functionName: "getPegInFee",
1425
+ args: [i]
1426
+ }) * BigInt(r), c = Array.from(
1427
+ { length: r },
1428
+ (h, g) => Cs(o, g)
1429
+ ), u = J({
1430
+ abi: H,
1431
+ functionName: "submitPeginRequestBatch",
1432
+ args: [
1433
+ o,
1434
+ i,
1435
+ Ht,
1436
+ c
1437
+ ]
1438
+ });
1439
+ return t.estimateGas({
1440
+ to: e,
1441
+ data: u,
1442
+ value: a,
1443
+ account: o
1444
+ });
1445
+ }
1446
+ export {
1447
+ st as C,
1448
+ Ht as M,
1449
+ js as P,
1450
+ Y as a,
1451
+ $e as b,
1452
+ hs as c,
1453
+ us as d,
1454
+ Qs as e,
1455
+ Ue as f,
1456
+ ds as g
1457
+ };
1458
+ //# sourceMappingURL=PeginManager--2R3T2S8.js.map