@babylonlabs-io/ts-sdk 0.27.1 → 0.28.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 (85) hide show
  1. package/dist/PeginManager-Da4uSHzl.cjs +2 -0
  2. package/dist/PeginManager-Da4uSHzl.cjs.map +1 -0
  3. package/dist/{context-ktqanzXE.js → PeginManager-DzMSIQ0I.js} +1100 -1058
  4. package/dist/PeginManager-DzMSIQ0I.js.map +1 -0
  5. package/dist/buildAndBroadcastRefund-DkEpTFkv.cjs +2 -0
  6. package/dist/buildAndBroadcastRefund-DkEpTFkv.cjs.map +1 -0
  7. package/dist/{buildAndBroadcastRefund-BzYJv-Fv.js → buildAndBroadcastRefund-xWS8frc6.js} +338 -348
  8. package/dist/buildAndBroadcastRefund-xWS8frc6.js.map +1 -0
  9. package/dist/index.cjs +1 -1
  10. package/dist/index.js +55 -55
  11. package/dist/sha2-6wN58S6R.js +280 -0
  12. package/dist/sha2-6wN58S6R.js.map +1 -0
  13. package/dist/sha2-CsTynrfJ.cjs +2 -0
  14. package/dist/sha2-CsTynrfJ.cjs.map +1 -0
  15. package/dist/shared/index.cjs.map +1 -1
  16. package/dist/shared/index.js.map +1 -1
  17. package/dist/shared/wallets/index.d.ts +2 -1
  18. package/dist/shared/wallets/index.d.ts.map +1 -1
  19. package/dist/shared/wallets/interfaces/BitcoinWallet.d.ts +8 -0
  20. package/dist/shared/wallets/interfaces/BitcoinWallet.d.ts.map +1 -1
  21. package/dist/signing-BZigafm0.js.map +1 -1
  22. package/dist/signing-DHSXjhLM.cjs.map +1 -1
  23. package/dist/tbv/core/clients/eth/vault-registry-reader.d.ts.map +1 -1
  24. package/dist/tbv/core/clients/index.cjs +1 -1
  25. package/dist/tbv/core/clients/index.js +2 -2
  26. package/dist/tbv/core/contracts/abis/BTCVaultRegistry.abi.d.ts +80 -70
  27. package/dist/tbv/core/contracts/abis/BTCVaultRegistry.abi.d.ts.map +1 -1
  28. package/dist/tbv/core/index.cjs +1 -1
  29. package/dist/tbv/core/index.js +52 -52
  30. package/dist/tbv/core/managers/PeginManager.d.ts +64 -27
  31. package/dist/tbv/core/managers/PeginManager.d.ts.map +1 -1
  32. package/dist/tbv/core/managers/index.d.ts +1 -1
  33. package/dist/tbv/core/managers/index.d.ts.map +1 -1
  34. package/dist/tbv/core/services/deposit/peginState.d.ts +1 -1
  35. package/dist/tbv/core/services/deposit/peginState.d.ts.map +1 -1
  36. package/dist/tbv/core/services/deposit/validation.d.ts +0 -4
  37. package/dist/tbv/core/services/deposit/validation.d.ts.map +1 -1
  38. package/dist/tbv/core/services/index.cjs +1 -1
  39. package/dist/tbv/core/services/index.js +1 -1
  40. package/dist/tbv/core/vault-secrets/__tests__/deriveVaultRoot.test.d.ts +13 -0
  41. package/dist/tbv/core/vault-secrets/__tests__/deriveVaultRoot.test.d.ts.map +1 -0
  42. package/dist/tbv/core/vault-secrets/context.d.ts +9 -0
  43. package/dist/tbv/core/vault-secrets/context.d.ts.map +1 -1
  44. package/dist/tbv/core/vault-secrets/deriveVaultRoot.d.ts +56 -0
  45. package/dist/tbv/core/vault-secrets/deriveVaultRoot.d.ts.map +1 -0
  46. package/dist/tbv/core/vault-secrets/expand.d.ts +18 -3
  47. package/dist/tbv/core/vault-secrets/expand.d.ts.map +1 -1
  48. package/dist/tbv/core/vault-secrets/index.d.ts +6 -3
  49. package/dist/tbv/core/vault-secrets/index.d.ts.map +1 -1
  50. package/dist/tbv/core/wots/blockDerivation.d.ts +20 -24
  51. package/dist/tbv/core/wots/blockDerivation.d.ts.map +1 -1
  52. package/dist/tbv/core/wots/errors.d.ts +3 -1
  53. package/dist/tbv/core/wots/errors.d.ts.map +1 -1
  54. package/dist/tbv/core/wots/index.d.ts +1 -2
  55. package/dist/tbv/core/wots/index.d.ts.map +1 -1
  56. package/dist/tbv/index.cjs +1 -1
  57. package/dist/tbv/index.js +52 -52
  58. package/dist/testing/MockBitcoinWallet.d.ts +10 -3
  59. package/dist/testing/MockBitcoinWallet.d.ts.map +1 -1
  60. package/dist/testing/index.cjs +1 -1
  61. package/dist/testing/index.cjs.map +1 -1
  62. package/dist/testing/index.js +67 -55
  63. package/dist/testing/index.js.map +1 -1
  64. package/dist/types-CnG3JsRs.js +680 -0
  65. package/dist/types-CnG3JsRs.js.map +1 -0
  66. package/dist/types-jmEyzzhY.cjs +2 -0
  67. package/dist/types-jmEyzzhY.cjs.map +1 -0
  68. package/dist/{vault-registry-reader-CpCOte7w.js → vault-registry-reader-BywZhqJL.js} +65 -64
  69. package/dist/{vault-registry-reader-CpCOte7w.js.map → vault-registry-reader-BywZhqJL.js.map} +1 -1
  70. package/dist/vault-registry-reader-DdruADqa.cjs +2 -0
  71. package/dist/{vault-registry-reader-BizmBSBV.cjs.map → vault-registry-reader-DdruADqa.cjs.map} +1 -1
  72. package/package.json +1 -1
  73. package/dist/buildAndBroadcastRefund-BEASMFsz.cjs +0 -2
  74. package/dist/buildAndBroadcastRefund-BEASMFsz.cjs.map +0 -1
  75. package/dist/buildAndBroadcastRefund-BzYJv-Fv.js.map +0 -1
  76. package/dist/context-B4fYDTxy.cjs +0 -2
  77. package/dist/context-B4fYDTxy.cjs.map +0 -1
  78. package/dist/context-ktqanzXE.js.map +0 -1
  79. package/dist/sha2-1XZuToHP.cjs +0 -2
  80. package/dist/sha2-1XZuToHP.cjs.map +0 -1
  81. package/dist/sha2-ZzfZqQSw.js +0 -1123
  82. package/dist/sha2-ZzfZqQSw.js.map +0 -1
  83. package/dist/tbv/core/wots/deriveWotsPkHash.d.ts +0 -9
  84. package/dist/tbv/core/wots/deriveWotsPkHash.d.ts.map +0 -1
  85. package/dist/vault-registry-reader-BizmBSBV.cjs +0 -2
@@ -1,20 +1,22 @@
1
- var te = Object.defineProperty;
2
- var ee = (e, t, n) => t in e ? te(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
3
- var b = (e, t, n) => ee(e, typeof t != "symbol" ? t + "" : t, n);
4
- import * as ne from "bitcoinjs-lib";
5
- import { Transaction as se, Psbt as yt } from "bitcoinjs-lib";
6
- import { Buffer as it } from "buffer";
7
- import { isAddressEqual as bt, createPublicClient as q, http as Z, encodeFunctionData as xt, zeroAddress as oe } from "viem";
8
- import { c as re } from "./signing-BZigafm0.js";
9
- import { deriveVaultId as Pt } from "@babylonlabs-io/babylon-tbv-rust-wasm";
10
- import { b as ie, a as ae, d as ce, e as le, f as ue } from "./challengeAssert-j2Vwqo0-.js";
11
- import { s as v, g as kt, e as I, i as he, p as de } from "./bitcoin-B-Y0DlqR.js";
12
- import { M as Et } from "./validation-CxqROCno.js";
13
- import { b as fe, f as G, i as ge } from "./psbtInputFields-DeTFSJOq.js";
14
- import { p as pe, f as me } from "./fundPeginTransaction-oV-dNJOU.js";
15
- import { p as we, f as ye } from "./vault-registry-reader-CpCOte7w.js";
16
- import { B as O, e as ht, f as U, g as S, h as V, i as Ut, H as be, r as F, j as xe, k as C, u as Pe, l as Tt, m as ke, n as Ee, o as Te, p as Ie, q as _e, t as ve, v as Be, w as It, x as Wt, s as W } from "./sha2-ZzfZqQSw.js";
17
- const H = {
1
+ var Jt = Object.defineProperty;
2
+ var te = (e, t, n) => t in e ? Jt(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
3
+ var b = (e, t, n) => te(e, typeof t != "symbol" ? t + "" : t, n);
4
+ import * as ee from "bitcoinjs-lib";
5
+ import { Transaction as ne, Psbt as ft } from "bitcoinjs-lib";
6
+ import { Buffer as et } from "buffer";
7
+ import { isAddressEqual as gt, createPublicClient as j, http as z, encodeFunctionData as pt, zeroAddress as se } from "viem";
8
+ import { deriveVaultId as mt } from "@babylonlabs-io/babylon-tbv-rust-wasm";
9
+ import { b as bt, a as oe, d as re, e as ie, f as ae } from "./challengeAssert-j2Vwqo0-.js";
10
+ import { u as $t, h as nt, e as I, s as _, g as wt, i as ce, p as le } from "./bitcoin-B-Y0DlqR.js";
11
+ import { h as ue } from "./buildAndBroadcastRefund-xWS8frc6.js";
12
+ import { c as he } from "./signing-BZigafm0.js";
13
+ import { M as yt } from "./validation-CxqROCno.js";
14
+ import { a as Rt, b as U, c as A, d as F, e as st, s as L, f as Ut, H as de, r as V, u as fe, g as xt, h as ge } from "./sha2-6wN58S6R.js";
15
+ import { b as pe, f as q, i as me } from "./psbtInputFields-DeTFSJOq.js";
16
+ import { p as be, f as we } from "./fundPeginTransaction-oV-dNJOU.js";
17
+ import { p as ye, f as xe } from "./vault-registry-reader-BywZhqJL.js";
18
+ import { B as C } from "./types-CnG3JsRs.js";
19
+ const S = {
18
20
  // VaultAlreadyExists()
19
21
  "0x04aabf33": "Vault already exists: This Bitcoin transaction has already been registered. Please select different UTXOs or use a different amount to create a unique transaction.",
20
22
  // ScriptPubKeyMismatch() - taproot output doesn't match expected script
@@ -48,7 +50,7 @@ const H = {
48
50
  // PeginTransactionAlreadyUsed()
49
51
  "0x7ed061c9": "This pegin transaction has already been used to activate another vault."
50
52
  };
51
- function dt(e) {
53
+ function at(e) {
52
54
  if (!e || typeof e != "object") return;
53
55
  const t = e;
54
56
  if (typeof t.data == "string" && t.data.startsWith("0x"))
@@ -67,24 +69,24 @@ function dt(e) {
67
69
  if (i)
68
70
  return i[1];
69
71
  }
70
- function Fn(e) {
71
- const t = dt(e);
72
+ function Ln(e) {
73
+ const t = at(e);
72
74
  if (t) {
73
75
  const n = t.substring(0, 10);
74
- return H[t] ?? H[n];
76
+ return S[t] ?? S[n];
75
77
  }
76
78
  }
77
- function Mn(e) {
78
- const t = dt(e);
79
+ function Vn(e) {
80
+ const t = at(e);
79
81
  if (t === void 0) return !1;
80
82
  const n = t.substring(0, 10);
81
- return t in H || n in H;
83
+ return t in S || n in S;
82
84
  }
83
- function A(e) {
85
+ function H(e) {
84
86
  console.error("[Contract Error] Raw error:", e);
85
- const t = dt(e);
87
+ const t = at(e);
86
88
  if (console.error("[Contract Error] Extracted error data:", t), t) {
87
- const s = t.substring(0, 10), o = H[t] ?? H[s];
89
+ const s = t.substring(0, 10), o = S[t] ?? S[s];
88
90
  if (o)
89
91
  throw console.error("[Contract Error] Known error:", o), new Error(o);
90
92
  }
@@ -102,326 +104,944 @@ function A(e) {
102
104
  }
103
105
  throw e instanceof Error ? (console.error("[Contract Error] Unhandled error:", e.message), e) : new Error(`Contract call failed: ${String(e)}`);
104
106
  }
105
- const Se = 0, Ae = /^0x[0-9a-f]+$/i, Ce = /^[0-9a-f]+$/i, He = /^[A-Za-z0-9+/]+={0,2}$/;
106
- function $(e) {
107
- if (typeof e != "string" || e.length === 0)
108
- throw new Error("BTC wallet returned empty public key");
109
- return de(e).toLowerCase();
107
+ const W = /* @__PURE__ */ BigInt(2 ** 32 - 1), Pt = /* @__PURE__ */ BigInt(32);
108
+ function Pe(e, t = !1) {
109
+ return t ? { h: Number(e & W), l: Number(e >> Pt & W) } : { h: Number(e >> Pt & W) | 0, l: Number(e & W) | 0 };
110
110
  }
111
- function Oe(e) {
112
- if (typeof e != "string" || e.length === 0)
113
- throw new Error("BTC wallet returned empty BIP-322 signature");
114
- if (e.startsWith("0x") || e.startsWith("0X")) {
115
- if (!Ae.test(e) || e.length < 4 || e.length % 2 !== 0)
116
- throw new Error("BTC wallet returned malformed hex BIP-322 signature");
117
- return e.toLowerCase();
111
+ function Ee(e, t = !1) {
112
+ const n = e.length;
113
+ let s = new Uint32Array(n), o = new Uint32Array(n);
114
+ for (let r = 0; r < n; r++) {
115
+ const { h: i, l: a } = Pe(e[r], t);
116
+ [s[r], o[r]] = [i, a];
118
117
  }
119
- if (Ce.test(e)) {
120
- if (e.length % 2 !== 0)
121
- throw new Error("BTC wallet returned malformed hex BIP-322 signature");
122
- return `0x${e.toLowerCase()}`;
118
+ return [s, o];
119
+ }
120
+ const ke = (e, t, n) => e << n | t >>> 32 - n, Te = (e, t, n) => t << n | e >>> 32 - n, _e = (e, t, n) => t << n - 32 | e >>> 64 - n, ve = (e, t, n) => e << n - 32 | t >>> 64 - n;
121
+ class Lt {
122
+ constructor(t, n) {
123
+ b(this, "oHash");
124
+ b(this, "iHash");
125
+ b(this, "blockLen");
126
+ b(this, "outputLen");
127
+ b(this, "finished", !1);
128
+ b(this, "destroyed", !1);
129
+ if (Rt(t), U(n, void 0, "key"), this.iHash = t.create(), typeof this.iHash.update != "function")
130
+ throw new Error("Expected instance of class which extends utils.Hash");
131
+ this.blockLen = this.iHash.blockLen, this.outputLen = this.iHash.outputLen;
132
+ const s = this.blockLen, o = new Uint8Array(s);
133
+ o.set(n.length > s ? t.create().update(n).digest() : n);
134
+ for (let r = 0; r < o.length; r++)
135
+ o[r] ^= 54;
136
+ this.iHash.update(o), this.oHash = t.create();
137
+ for (let r = 0; r < o.length; r++)
138
+ o[r] ^= 106;
139
+ this.oHash.update(o), A(o);
140
+ }
141
+ update(t) {
142
+ return F(this), this.iHash.update(t), this;
143
+ }
144
+ digestInto(t) {
145
+ F(this), U(t, this.outputLen, "output"), this.finished = !0, this.iHash.digestInto(t), this.oHash.update(t), this.oHash.digestInto(t), this.destroy();
146
+ }
147
+ digest() {
148
+ const t = new Uint8Array(this.oHash.outputLen);
149
+ return this.digestInto(t), t;
150
+ }
151
+ _cloneInto(t) {
152
+ t || (t = Object.create(Object.getPrototypeOf(this), {}));
153
+ const { oHash: n, iHash: s, finished: o, destroyed: r, blockLen: i, outputLen: a } = this;
154
+ return t = t, t.finished = o, t.destroyed = r, t.blockLen = i, t.outputLen = a, t.oHash = n._cloneInto(t.oHash), t.iHash = s._cloneInto(t.iHash), t;
155
+ }
156
+ clone() {
157
+ return this._cloneInto();
158
+ }
159
+ destroy() {
160
+ this.destroyed = !0, this.oHash.destroy(), this.iHash.destroy();
123
161
  }
124
- if (!He.test(e) || e.length % 4 !== 0)
125
- throw new Error("BTC wallet returned malformed base64 BIP-322 signature");
126
- const t = it.from(e, "base64");
127
- if (t.length === 0 || t.toString("base64") !== e)
128
- throw new Error("BTC wallet returned malformed base64 BIP-322 signature");
129
- return `0x${t.toString("hex")}`;
130
162
  }
131
- function $e(e, t, n, s) {
132
- const o = n == null ? void 0 : n[`${e}:${t}`];
133
- return o ? Promise.resolve({
134
- txid: e,
135
- vout: t,
136
- value: o.value,
137
- scriptPubKey: o.scriptPubKey
138
- }) : ye(e, t, s);
163
+ const Vt = (e, t, n) => new Lt(e, t).update(n).digest();
164
+ Vt.create = (e, t) => new Lt(e, t);
165
+ const G = /* @__PURE__ */ Uint8Array.of(0), Et = /* @__PURE__ */ Uint8Array.of();
166
+ function ct(e, t, n, s = 32) {
167
+ Rt(e), st(s, "length");
168
+ const o = e.outputLen;
169
+ if (s > 255 * o)
170
+ throw new Error("Length must be <= 255*HashLen");
171
+ const r = Math.ceil(s / o);
172
+ n === void 0 ? n = Et : U(n, void 0, "info");
173
+ const i = new Uint8Array(r * o), a = Vt.create(e, t), l = a._cloneInto(), u = new Uint8Array(a.outputLen);
174
+ for (let c = 0; c < r; c++)
175
+ G[0] = c + 1, l.update(c === 0 ? Et : u).update(n).update(G).digestInto(u), i.set(u, o * c), a._cloneInto(l);
176
+ return a.destroy(), l.destroy(), A(u, G), i.slice(0, s);
139
177
  }
140
- const _t = 12e4;
141
- class Nn {
142
- /**
143
- * Creates a new PeginManager instance.
144
- *
145
- * @param config - Manager configuration including wallets and contract addresses
146
- */
147
- constructor(t) {
148
- b(this, "config");
149
- this.config = t;
150
- }
151
- /**
152
- * Prepares a peg-in by building the Pre-PegIn HTLC transaction,
153
- * funding it, constructing the PegIn transaction, and signing the PegIn input.
154
- *
155
- * This method orchestrates the following steps:
156
- * 1. Get depositor BTC public key from wallet
157
- * 2. Build unfunded Pre-PegIn transaction (HTLC output) using primitives
158
- * 3. Select UTXOs to cover the HTLC value
159
- * 4. Fund the Pre-PegIn transaction
160
- * 5. Derive the PegIn transaction from the funded Pre-PegIn tx
161
- * 6. Build PSBT for signing the PegIn input (HTLC leaf 0)
162
- * 7. Sign via BTC wallet and extract depositor signature
163
- *
164
- * The returned `fundedPrePeginTxHex` is funded but unsigned (inputs unsigned).
165
- * Use `signAndBroadcast()` AFTER registering on Ethereum to broadcast it.
166
- *
167
- * @param params - Pegin parameters including amount, HTLC params, UTXOs
168
- * @returns Pegin result with funded Pre-PegIn tx, signed PegIn input, and signatures
169
- * @throws Error if wallet operations fail or insufficient funds
170
- */
171
- async preparePegin(t) {
172
- const n = await this.config.btcWallet.getPublicKeyHex(), s = $(n), o = v(t.vaultProviderBtcPubkey), r = t.vaultKeeperBtcPubkeys.map(v), i = t.universalChallengerBtcPubkeys.map(v);
173
- if (t.hashlocks.length !== t.amounts.length)
178
+ const Z = new TextEncoder().encode("babylonvault"), kt = 255, Tt = 65535, _t = 2, Ie = "hashlock", Be = "auth-anchor", He = "wots-seed";
179
+ function Wt(e) {
180
+ if (!Number.isInteger(e) || e < 0 || e > 4294967295)
181
+ throw new Error(`i2osp4: value must be a u32, got ${e}`);
182
+ const t = new Uint8Array(4);
183
+ return t[0] = e >>> 24 & 255, t[1] = e >>> 16 & 255, t[2] = e >>> 8 & 255, t[3] = e & 255, t;
184
+ }
185
+ function lt(e, t = new Uint8Array(0)) {
186
+ const n = new TextEncoder().encode(e);
187
+ if (n.length === 0 || n.length > kt)
188
+ throw new Error(
189
+ `info: label length must be in [1, ${kt}], got ${n.length}`
190
+ );
191
+ if (t.length > Tt)
192
+ throw new Error(
193
+ `info: ctx length must be in [0, ${Tt}], got ${t.length}`
194
+ );
195
+ const s = Z.length + 1 + n.length + _t + t.length, o = new Uint8Array(s);
196
+ let r = 0;
197
+ return o.set(Z, r), r += Z.length, o[r] = n.length, r += 1, o.set(n, r), r += n.length, o[r] = t.length >>> 8 & 255, o[r + 1] = t.length & 255, r += _t, o.set(t, r), o;
198
+ }
199
+ const vt = 32, Ae = 32, Se = 32, Ce = 64;
200
+ function ut(e) {
201
+ if (e.length !== vt)
202
+ throw new Error(
203
+ `vault-secrets: root must be exactly ${vt} bytes, got ${e.length}`
204
+ );
205
+ }
206
+ function Wn(e) {
207
+ return ut(e), ct(
208
+ L,
209
+ e,
210
+ lt(Be),
211
+ Ae
212
+ );
213
+ }
214
+ function Oe(e, t) {
215
+ return ut(e), ct(
216
+ L,
217
+ e,
218
+ lt(Ie, Wt(t)),
219
+ Se
220
+ );
221
+ }
222
+ function $e(e, t) {
223
+ return ut(e), ct(
224
+ L,
225
+ e,
226
+ lt(He, Wt(t)),
227
+ Ce
228
+ );
229
+ }
230
+ const R = 32, Y = 32, ot = 36, Nt = 32, X = 4, Re = X + R + X + Nt;
231
+ function rt(e, t, n) {
232
+ e[t] = n >>> 24 & 255, e[t + 1] = n >>> 16 & 255, e[t + 2] = n >>> 8 & 255, e[t + 3] = n & 255;
233
+ }
234
+ function Ue(e) {
235
+ if (e.txid.length !== Y)
236
+ throw new Error(
237
+ `outpoint.txid must be exactly ${Y} bytes, got ${e.txid.length}`
238
+ );
239
+ if (!Number.isInteger(e.vout) || e.vout < 0 || e.vout > 4294967295)
240
+ throw new Error(`outpoint.vout must be a u32, got ${e.vout}`);
241
+ const t = new Uint8Array(ot);
242
+ return t.set(e.txid, 0), rt(t, Y, e.vout), t;
243
+ }
244
+ function It(e, t) {
245
+ const n = Math.min(e.length, t.length);
246
+ for (let s = 0; s < n; s++)
247
+ if (e[s] !== t[s]) return e[s] - t[s];
248
+ return e.length - t.length;
249
+ }
250
+ function Le(e) {
251
+ if (e.length === 0)
252
+ throw new Error(
253
+ "buildFundingOutpointsCommitment: outpoints must be non-empty"
254
+ );
255
+ const t = e.map(Ue);
256
+ t.sort(It);
257
+ for (let s = 1; s < t.length; s++)
258
+ if (It(t[s - 1], t[s]) === 0)
174
259
  throw new Error(
175
- `hashlocks.length (${t.hashlocks.length}) must equal amounts.length (${t.amounts.length})`
176
- );
177
- if (t.hashlocks.length === 0)
178
- throw new Error("hashlocks must contain at least one entry");
179
- const a = r.length, h = {
180
- depositorPubkey: s,
181
- vaultProviderPubkey: o,
182
- vaultKeeperPubkeys: r,
183
- universalChallengerPubkeys: i,
184
- hashlocks: t.hashlocks,
185
- timelockRefund: t.timelockRefund,
186
- pegInAmounts: t.amounts,
187
- feeRate: t.protocolFeeRate,
188
- numLocalChallengers: a,
189
- councilQuorum: t.councilQuorum,
190
- councilSize: t.councilSize,
191
- network: this.config.btcNetwork
192
- }, u = await ie(h), c = fe(
193
- [...t.availableUTXOs],
194
- u.totalOutputValue,
195
- t.mempoolFeeRate,
196
- pe(
197
- u.htlcValues.length,
198
- h.authAnchorHash
199
- )
200
- ), m = kt(this.config.btcNetwork), l = me({
201
- unfundedTxHex: u.psbtHex,
202
- selectedUTXOs: c.selectedUTXOs,
203
- changeAddress: t.changeAddress,
204
- changeAmount: c.changeAmount,
205
- network: m
206
- }), y = v(G(l)), f = [], x = [], P = [];
207
- for (let g = 0; g < t.hashlocks.length; g++) {
208
- const p = await ae({
209
- prePeginParams: h,
210
- timelockPegin: t.timelockPegin,
211
- fundedPrePeginTxHex: l,
212
- htlcVout: g
213
- }), E = await ce({
214
- peginTxHex: p.txHex,
215
- fundedPrePeginTxHex: l,
216
- depositorPubkey: s,
217
- vaultProviderPubkey: o,
218
- vaultKeeperPubkeys: r,
219
- universalChallengerPubkeys: i,
220
- hashlock: t.hashlocks[g],
221
- timelockRefund: t.timelockRefund,
222
- network: this.config.btcNetwork
223
- });
224
- f.push(p), x.push(E.psbtHex), P.push(
225
- re(n, 1)
260
+ "buildFundingOutpointsCommitment: duplicate outpoint detected"
226
261
  );
262
+ const n = new Uint8Array(t.length * ot);
263
+ for (let s = 0; s < t.length; s++)
264
+ n.set(t[s], s * ot);
265
+ return L(n);
266
+ }
267
+ function Ve(e) {
268
+ if (e.depositorBtcPubkey.length !== R)
269
+ throw new Error(
270
+ `vaultContext: depositorBtcPubkey must be exactly ${R} bytes, got ${e.depositorBtcPubkey.length}`
271
+ );
272
+ const t = Le(e.fundingOutpoints), n = new Uint8Array(Re);
273
+ let s = 0;
274
+ return rt(n, s, R), s += X, n.set(e.depositorBtcPubkey, s), s += R, rt(n, s, Nt), s += X, n.set(t, s), n;
275
+ }
276
+ const We = "babylon-vault", Mt = 32, Bt = Mt * 2, Ne = /^[0-9a-f]+$/;
277
+ async function Me(e, t) {
278
+ const n = Ve(t), s = $t(n), o = await e.deriveContextHash(We, s);
279
+ if (typeof o != "string")
280
+ throw new Error(
281
+ `deriveVaultRoot: wallet must return a string, got ${typeof o}`
282
+ );
283
+ if (o.length !== Bt)
284
+ throw new Error(
285
+ `deriveVaultRoot: wallet must return a ${Bt}-character hex string (${Mt} bytes), got length ${o.length}`
286
+ );
287
+ if (!Ne.test(o))
288
+ throw new Error(
289
+ "deriveVaultRoot: wallet must return lowercase hex per derive-context-hash.md §2.1; got value with non-lowercase or non-hex characters"
290
+ );
291
+ return nt(o);
292
+ }
293
+ const Fe = /* @__PURE__ */ Uint8Array.from([
294
+ 7,
295
+ 4,
296
+ 13,
297
+ 1,
298
+ 10,
299
+ 6,
300
+ 15,
301
+ 3,
302
+ 12,
303
+ 0,
304
+ 9,
305
+ 5,
306
+ 2,
307
+ 14,
308
+ 11,
309
+ 8
310
+ ]), Ft = Uint8Array.from(new Array(16).fill(0).map((e, t) => t)), Xe = Ft.map((e) => (9 * e + 5) % 16), Xt = /* @__PURE__ */ (() => {
311
+ const n = [[Ft], [Xe]];
312
+ for (let s = 0; s < 4; s++)
313
+ for (let o of n)
314
+ o.push(o[s].map((r) => Fe[r]));
315
+ return n;
316
+ })(), Kt = Xt[0], Dt = Xt[1], jt = /* @__PURE__ */ [
317
+ [11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8],
318
+ [12, 13, 11, 15, 6, 9, 9, 7, 12, 15, 11, 13, 7, 8, 7, 7],
319
+ [13, 15, 14, 11, 7, 7, 6, 8, 13, 14, 13, 12, 5, 5, 6, 9],
320
+ [14, 11, 12, 14, 8, 6, 5, 5, 15, 12, 15, 14, 9, 9, 8, 6],
321
+ [15, 12, 13, 13, 9, 5, 8, 6, 14, 11, 12, 11, 8, 6, 5, 5]
322
+ ].map((e) => Uint8Array.from(e)), Ke = /* @__PURE__ */ Kt.map((e, t) => e.map((n) => jt[t][n])), De = /* @__PURE__ */ Dt.map((e, t) => e.map((n) => jt[t][n])), je = /* @__PURE__ */ Uint32Array.from([
323
+ 0,
324
+ 1518500249,
325
+ 1859775393,
326
+ 2400959708,
327
+ 2840853838
328
+ ]), ze = /* @__PURE__ */ Uint32Array.from([
329
+ 1352829926,
330
+ 1548603684,
331
+ 1836072691,
332
+ 2053994217,
333
+ 0
334
+ ]);
335
+ function Ht(e, t, n, s) {
336
+ return e === 0 ? t ^ n ^ s : e === 1 ? t & n | ~t & s : e === 2 ? (t | ~n) ^ s : e === 3 ? t & s | n & ~s : t ^ (n | ~s);
337
+ }
338
+ const N = /* @__PURE__ */ new Uint32Array(16);
339
+ class qe extends de {
340
+ constructor() {
341
+ super(64, 20, 8, !0);
342
+ b(this, "h0", 1732584193);
343
+ b(this, "h1", -271733879);
344
+ b(this, "h2", -1732584194);
345
+ b(this, "h3", 271733878);
346
+ b(this, "h4", -1009589776);
347
+ }
348
+ get() {
349
+ const { h0: n, h1: s, h2: o, h3: r, h4: i } = this;
350
+ return [n, s, o, r, i];
351
+ }
352
+ set(n, s, o, r, i) {
353
+ this.h0 = n | 0, this.h1 = s | 0, this.h2 = o | 0, this.h3 = r | 0, this.h4 = i | 0;
354
+ }
355
+ process(n, s) {
356
+ for (let p = 0; p < 16; p++, s += 4)
357
+ N[p] = n.getUint32(s, !0);
358
+ let o = this.h0 | 0, r = o, i = this.h1 | 0, a = i, l = this.h2 | 0, u = l, c = this.h3 | 0, y = c, g = this.h4 | 0, h = g;
359
+ for (let p = 0; p < 5; p++) {
360
+ const T = 4 - p, P = je[p], v = ze[p], d = Kt[p], x = Dt[p], f = Ke[p], m = De[p];
361
+ for (let w = 0; w < 16; w++) {
362
+ const E = V(o + Ht(p, i, l, c) + N[d[w]] + P, f[w]) + g | 0;
363
+ o = g, g = c, c = V(l, 10) | 0, l = i, i = E;
364
+ }
365
+ for (let w = 0; w < 16; w++) {
366
+ const E = V(r + Ht(T, a, u, y) + N[x[w]] + v, m[w]) + h | 0;
367
+ r = h, h = y, y = V(u, 10) | 0, u = a, a = E;
368
+ }
227
369
  }
228
- const w = await this.signPsbtsWithFallback(
229
- x,
230
- P
231
- ), d = [];
232
- for (let g = 0; g < w.length; g++) {
233
- const p = le(
234
- w[g],
235
- s
236
- ), E = ue(w[g]);
237
- d.push({
238
- htlcVout: g,
239
- htlcValue: u.htlcValues[g],
240
- peginTxHex: E,
241
- peginTxid: f[g].txid,
242
- peginInputSignature: p,
243
- vaultScriptPubKey: f[g].vaultScriptPubKey
244
- });
245
- }
246
- return {
247
- fundedPrePeginTxHex: l,
248
- prePeginTxid: y,
249
- perVault: d,
250
- selectedUTXOs: c.selectedUTXOs,
251
- fee: c.fee,
252
- changeAmount: c.changeAmount
253
- };
370
+ this.set(this.h1 + l + y | 0, this.h2 + c + h | 0, this.h3 + g + r | 0, this.h4 + o + a | 0, this.h0 + i + u | 0);
254
371
  }
255
- /**
256
- * Signs multiple PSBTs using batch signing if available, falling back to sequential signing.
257
- *
258
- * Wallets that support native batch signing (e.g. UniSat) will sign all PSBTs
259
- * in a single interaction. Others (e.g. Ledger, AppKit) implement signPsbts
260
- * by looping signPsbt internally, so the UX depends on the wallet adapter.
261
- */
262
- async signPsbtsWithFallback(t, n) {
263
- if (typeof this.config.btcWallet.signPsbts == "function") {
264
- const o = await this.config.btcWallet.signPsbts(
265
- t,
266
- n
267
- );
268
- if (o.length !== t.length)
269
- throw new Error(
270
- `Expected ${t.length} signed PSBTs but received ${o.length}`
271
- );
272
- return o;
372
+ roundClean() {
373
+ A(N);
374
+ }
375
+ destroy() {
376
+ this.destroyed = !0, A(this.buffer), this.set(0, 0, 0, 0, 0);
377
+ }
378
+ }
379
+ const Ge = /* @__PURE__ */ Ut(() => new qe()), Ze = BigInt(0), O = BigInt(1), Ye = BigInt(2), Qe = BigInt(7), Je = BigInt(256), tn = BigInt(113), zt = [], qt = [], Gt = [];
380
+ for (let e = 0, t = O, n = 1, s = 0; e < 24; e++) {
381
+ [n, s] = [s, (2 * n + 3 * s) % 5], zt.push(2 * (5 * s + n)), qt.push((e + 1) * (e + 2) / 2 % 64);
382
+ let o = Ze;
383
+ for (let r = 0; r < 7; r++)
384
+ t = (t << O ^ (t >> Qe) * tn) % Je, t & Ye && (o ^= O << (O << BigInt(r)) - O);
385
+ Gt.push(o);
386
+ }
387
+ const Zt = Ee(Gt, !0), en = Zt[0], nn = Zt[1], At = (e, t, n) => n > 32 ? _e(e, t, n) : ke(e, t, n), St = (e, t, n) => n > 32 ? ve(e, t, n) : Te(e, t, n);
388
+ function sn(e, t = 24) {
389
+ const n = new Uint32Array(10);
390
+ for (let s = 24 - t; s < 24; s++) {
391
+ for (let i = 0; i < 10; i++)
392
+ n[i] = e[i] ^ e[i + 10] ^ e[i + 20] ^ e[i + 30] ^ e[i + 40];
393
+ for (let i = 0; i < 10; i += 2) {
394
+ const a = (i + 8) % 10, l = (i + 2) % 10, u = n[l], c = n[l + 1], y = At(u, c, 1) ^ n[a], g = St(u, c, 1) ^ n[a + 1];
395
+ for (let h = 0; h < 50; h += 10)
396
+ e[i + h] ^= y, e[i + h + 1] ^= g;
273
397
  }
274
- const s = [];
275
- for (let o = 0; o < t.length; o++) {
276
- const r = await this.config.btcWallet.signPsbt(
277
- t[o],
278
- n[o]
279
- );
280
- s.push(r);
398
+ let o = e[2], r = e[3];
399
+ for (let i = 0; i < 24; i++) {
400
+ const a = qt[i], l = At(o, r, a), u = St(o, r, a), c = zt[i];
401
+ o = e[c], r = e[c + 1], e[c] = l, e[c + 1] = u;
281
402
  }
282
- return s;
403
+ for (let i = 0; i < 50; i += 10) {
404
+ for (let a = 0; a < 10; a++)
405
+ n[a] = e[i + a];
406
+ for (let a = 0; a < 10; a++)
407
+ e[i + a] ^= ~n[(a + 2) % 10] & n[(a + 4) % 10];
408
+ }
409
+ e[0] ^= en[s], e[1] ^= nn[s];
283
410
  }
284
- /**
285
- * Signs and broadcasts a funded peg-in transaction to the Bitcoin network.
286
- *
287
- * This method:
288
- * 1. Parses the funded transaction hex
289
- * 2. Fetches UTXO data from mempool for each input
290
- * 3. Creates a PSBT with proper witnessUtxo/tapInternalKey
291
- * 4. Signs via btcWallet.signPsbt()
292
- * 5. Finalizes and extracts the transaction
293
- * 6. Broadcasts via mempool API
294
- *
295
- * @param params - Transaction hex and depositor public key
296
- * @returns The broadcasted Bitcoin transaction ID
297
- * @throws Error if signing or broadcasting fails
298
- */
299
- async signAndBroadcast(t) {
300
- const { fundedPrePeginTxHex: n, depositorBtcPubkey: s } = t, o = n.startsWith("0x") ? n.slice(2) : n, r = se.fromHex(o);
301
- if (r.ins.length === 0)
302
- throw new Error("Transaction has no inputs");
303
- const i = new yt();
304
- i.setVersion(r.version), i.setLocktime(r.locktime);
305
- const a = it.from(
306
- $(s),
307
- "hex"
308
- ), h = this.config.mempoolApiUrl, u = r.ins.map((d) => {
309
- const g = it.from(d.hash).reverse().toString("hex"), p = d.index;
310
- return $e(g, p, t.localPrevouts, h).then(
311
- (E) => ({ input: d, utxoData: E, txid: g, vout: p })
312
- );
313
- }), c = await Promise.all(u), m = c.reduce(
314
- (d, g) => d + BigInt(g.utxoData.value),
315
- 0n
316
- ), l = r.outs.reduce(
317
- (d, g) => d + BigInt(g.value),
318
- 0n
319
- );
320
- if (m < l)
411
+ A(n);
412
+ }
413
+ class ht {
414
+ // NOTE: we accept arguments in bytes instead of bits here.
415
+ constructor(t, n, s, o = !1, r = 24) {
416
+ b(this, "state");
417
+ b(this, "pos", 0);
418
+ b(this, "posOut", 0);
419
+ b(this, "finished", !1);
420
+ b(this, "state32");
421
+ b(this, "destroyed", !1);
422
+ b(this, "blockLen");
423
+ b(this, "suffix");
424
+ b(this, "outputLen");
425
+ b(this, "enableXOF", !1);
426
+ b(this, "rounds");
427
+ if (this.blockLen = t, this.suffix = n, this.outputLen = s, this.enableXOF = o, this.rounds = r, st(s, "outputLen"), !(0 < t && t < 200))
428
+ throw new Error("only keccak-f1600 function is supported");
429
+ this.state = new Uint8Array(200), this.state32 = fe(this.state);
430
+ }
431
+ clone() {
432
+ return this._cloneInto();
433
+ }
434
+ keccak() {
435
+ xt(this.state32), sn(this.state32, this.rounds), xt(this.state32), this.posOut = 0, this.pos = 0;
436
+ }
437
+ update(t) {
438
+ F(this), U(t);
439
+ const { blockLen: n, state: s } = this, o = t.length;
440
+ for (let r = 0; r < o; ) {
441
+ const i = Math.min(n - this.pos, o - r);
442
+ for (let a = 0; a < i; a++)
443
+ s[this.pos++] ^= t[r++];
444
+ this.pos === n && this.keccak();
445
+ }
446
+ return this;
447
+ }
448
+ finish() {
449
+ if (this.finished)
450
+ return;
451
+ this.finished = !0;
452
+ const { state: t, suffix: n, pos: s, blockLen: o } = this;
453
+ t[s] ^= n, (n & 128) !== 0 && s === o - 1 && this.keccak(), t[o - 1] ^= 128, this.keccak();
454
+ }
455
+ writeInto(t) {
456
+ F(this, !1), U(t), this.finish();
457
+ const n = this.state, { blockLen: s } = this;
458
+ for (let o = 0, r = t.length; o < r; ) {
459
+ this.posOut >= s && this.keccak();
460
+ const i = Math.min(s - this.posOut, r - o);
461
+ t.set(n.subarray(this.posOut, this.posOut + i), o), this.posOut += i, o += i;
462
+ }
463
+ return t;
464
+ }
465
+ xofInto(t) {
466
+ if (!this.enableXOF)
467
+ throw new Error("XOF is not possible for this instance");
468
+ return this.writeInto(t);
469
+ }
470
+ xof(t) {
471
+ return st(t), this.xofInto(new Uint8Array(t));
472
+ }
473
+ digestInto(t) {
474
+ if (ge(t, this), this.finished)
475
+ throw new Error("digest() was already called");
476
+ return this.writeInto(t), this.destroy(), t;
477
+ }
478
+ digest() {
479
+ return this.digestInto(new Uint8Array(this.outputLen));
480
+ }
481
+ destroy() {
482
+ this.destroyed = !0, A(this.state);
483
+ }
484
+ _cloneInto(t) {
485
+ const { blockLen: n, suffix: s, outputLen: o, rounds: r, enableXOF: i } = this;
486
+ return t || (t = new ht(n, s, o, i, r)), t.state32.set(this.state32), t.pos = this.pos, t.posOut = this.posOut, t.finished = this.finished, t.rounds = r, t.suffix = s, t.outputLen = o, t.enableXOF = i, t.destroyed = this.destroyed, t;
487
+ }
488
+ }
489
+ const on = (e, t, n, s = {}) => Ut(() => new ht(t, e, n), s), rn = /* @__PURE__ */ on(1, 136, 32), Ct = 64, k = 20, it = 4, Yt = 2, an = 0, cn = 1, M = [64, 64], ln = (e) => Array.from(e).map((t) => t.toString(16).padStart(2, "0")).join("");
490
+ function dt(e) {
491
+ return Ge(L(e));
492
+ }
493
+ function Qt(e) {
494
+ return (1 << e) - 1;
495
+ }
496
+ function un(e) {
497
+ let t = 1;
498
+ for (; t * t < e + 1; ) t++;
499
+ return Math.max(t, 2);
500
+ }
501
+ function hn(e) {
502
+ const t = it, n = e * Qt(t);
503
+ return { d: t, n: e, checksum_radix: un(n) };
504
+ }
505
+ function Q(e, t) {
506
+ const n = [];
507
+ let s = t;
508
+ for (; s > 0; )
509
+ n.push(s & 255), s >>>= 8;
510
+ const o = new Uint8Array(e.length + n.length);
511
+ o.set(e);
512
+ for (let r = 0; r < n.length; r++)
513
+ o[e.length + r] = n[r];
514
+ return dt(o);
515
+ }
516
+ function J(e, t) {
517
+ let n = e;
518
+ for (let s = 0; s < t; s++)
519
+ n = dt(n);
520
+ return n;
521
+ }
522
+ function dn(e, t) {
523
+ const n = Qt(t.d), s = t.checksum_radix - 1, o = Math.floor(t.n * n / t.checksum_radix), r = [];
524
+ for (let c = 0; c < t.n; c++) {
525
+ const y = Q(e, c + Yt), g = J(y, n);
526
+ r.push(Array.from(g));
527
+ }
528
+ const i = Q(
529
+ e,
530
+ an
531
+ ), a = J(
532
+ i,
533
+ s
534
+ ), l = Q(
535
+ e,
536
+ cn
537
+ ), u = J(
538
+ l,
539
+ o
540
+ );
541
+ return {
542
+ config: t,
543
+ message_terminals: r,
544
+ checksum_major_terminal: Array.from(u),
545
+ checksum_minor_terminal: Array.from(a)
546
+ };
547
+ }
548
+ async function fn(e) {
549
+ try {
550
+ if (e.length !== Ct)
321
551
  throw new Error(
322
- `UTXO value mismatch: total input value (${m} sat) is less than total output value (${l} sat). This may indicate the mempool API returned manipulated UTXO data.`
552
+ `WOTS seed must be exactly ${Ct} bytes, got ${e.length}`
323
553
  );
324
- const y = m - l;
325
- if (y > Et)
554
+ const t = [];
555
+ for (let n = 0; n < M.length; n++) {
556
+ const s = M[n], o = hn(s), r = new Uint8Array(e.length + 1);
557
+ r.set(e), r[e.length] = n;
558
+ const i = dt(r);
559
+ try {
560
+ const a = dn(i, o);
561
+ if (a.config.d !== it)
562
+ throw new Error(
563
+ `Block ${n}: expected d=${it}, got d=${a.config.d}`
564
+ );
565
+ if (a.config.n !== s)
566
+ throw new Error(
567
+ `Block ${n}: expected n=${s}, got n=${a.config.n}`
568
+ );
569
+ if (a.message_terminals.length !== s)
570
+ throw new Error(
571
+ `Block ${n}: expected ${s} message terminals, got ${a.message_terminals.length}`
572
+ );
573
+ for (let l = 0; l < a.message_terminals.length; l++)
574
+ if (a.message_terminals[l].length !== k)
575
+ throw new Error(
576
+ `Block ${n} terminal ${l}: expected ${k} bytes, got ${a.message_terminals[l].length}`
577
+ );
578
+ if (a.checksum_minor_terminal.length !== k)
579
+ throw new Error(
580
+ `Block ${n} checksum_minor: expected ${k} bytes`
581
+ );
582
+ if (a.checksum_major_terminal.length !== k)
583
+ throw new Error(
584
+ `Block ${n} checksum_major: expected ${k} bytes`
585
+ );
586
+ t.push(a);
587
+ } finally {
588
+ r.fill(0), i.fill(0);
589
+ }
590
+ }
591
+ if (t.length !== M.length)
326
592
  throw new Error(
327
- `Implied transaction fee (${y} sat) exceeds maximum reasonable fee (${Et} sat). This may indicate manipulated UTXO data.`
593
+ `Expected ${M.length} blocks, got ${t.length}`
328
594
  );
329
- for (const { input: d, utxoData: g, txid: p, vout: E } of c) {
330
- const k = ge(
331
- {
332
- value: g.value,
333
- scriptPubKey: g.scriptPubKey
334
- },
335
- a
595
+ return t;
596
+ } finally {
597
+ e.fill(0);
598
+ }
599
+ }
600
+ function tt(e, t, n) {
601
+ if (e.length !== k)
602
+ throw new Error(
603
+ `Block ${t} ${n}: expected ${k} bytes, got ${e.length}`
604
+ );
605
+ for (let s = 0; s < e.length; s++) {
606
+ const o = e[s];
607
+ if (!Number.isInteger(o) || o < 0 || o > 255)
608
+ throw new Error(
609
+ `Block ${t} ${n}[${s}]: invalid byte value ${o}`
336
610
  );
337
- i.addInput({
338
- hash: d.hash,
339
- index: d.index,
340
- sequence: d.sequence,
341
- ...k
342
- });
343
- }
344
- for (const d of r.outs)
345
- i.addOutput({
346
- script: d.script,
347
- value: d.value
348
- });
349
- const f = await this.config.btcWallet.signPsbt(i.toHex()), x = yt.fromHex(f);
350
- try {
351
- x.finalizeAllInputs();
352
- } catch (d) {
353
- if (!x.data.inputs.every(
354
- (p) => p.finalScriptWitness || p.finalScriptSig
355
- ))
611
+ }
612
+ }
613
+ function gn(e) {
614
+ if (e.length === 0)
615
+ throw new Error("Public keys array must not be empty");
616
+ for (let r = 0; r < e.length; r++) {
617
+ const i = e[r];
618
+ tt(i.checksum_minor_terminal, r, "checksum_minor_terminal"), tt(i.checksum_major_terminal, r, "checksum_major_terminal");
619
+ for (let a = 0; a < i.message_terminals.length; a++)
620
+ tt(i.message_terminals[a], r, `message_terminal[${a}]`);
621
+ }
622
+ let t = 0;
623
+ for (const r of e)
624
+ t += Yt + r.message_terminals.length;
625
+ const n = new Uint8Array(t * k);
626
+ let s = 0;
627
+ for (const r of e) {
628
+ n.set(r.checksum_minor_terminal, s), s += k, n.set(r.checksum_major_terminal, s), s += k;
629
+ for (const i of r.message_terminals)
630
+ n.set(i, s), s += k;
631
+ }
632
+ const o = rn(n);
633
+ return `0x${ln(o)}`;
634
+ }
635
+ function Nn(e) {
636
+ const t = (e instanceof Error ? e.message : typeof e == "string" ? e : "").toLowerCase();
637
+ return t.includes("wots") && t.includes("hash") && t.includes("does not match");
638
+ }
639
+ const pn = 0, mn = /^0x[0-9a-f]+$/i, bn = /^[0-9a-f]+$/i, wn = /^[A-Za-z0-9+/]+={0,2}$/, yn = "00".repeat(32);
640
+ function $(e) {
641
+ if (typeof e != "string" || e.length === 0)
642
+ throw new Error("BTC wallet returned empty public key");
643
+ return le(e).toLowerCase();
644
+ }
645
+ function xn(e) {
646
+ if (typeof e != "string" || e.length === 0)
647
+ throw new Error("BTC wallet returned empty BIP-322 signature");
648
+ if (e.startsWith("0x") || e.startsWith("0X")) {
649
+ if (!mn.test(e) || e.length < 4 || e.length % 2 !== 0)
650
+ throw new Error("BTC wallet returned malformed hex BIP-322 signature");
651
+ return e.toLowerCase();
652
+ }
653
+ if (bn.test(e)) {
654
+ if (e.length % 2 !== 0)
655
+ throw new Error("BTC wallet returned malformed hex BIP-322 signature");
656
+ return `0x${e.toLowerCase()}`;
657
+ }
658
+ if (!wn.test(e) || e.length % 4 !== 0)
659
+ throw new Error("BTC wallet returned malformed base64 BIP-322 signature");
660
+ const t = et.from(e, "base64");
661
+ if (t.length === 0 || t.toString("base64") !== e)
662
+ throw new Error("BTC wallet returned malformed base64 BIP-322 signature");
663
+ return `0x${t.toString("hex")}`;
664
+ }
665
+ function Pn(e, t, n, s) {
666
+ const o = n == null ? void 0 : n[`${e}:${t}`];
667
+ return o ? Promise.resolve({
668
+ txid: e,
669
+ vout: t,
670
+ value: o.value,
671
+ scriptPubKey: o.scriptPubKey
672
+ }) : xe(e, t, s);
673
+ }
674
+ const Ot = 12e4;
675
+ class Mn {
676
+ /**
677
+ * Creates a new PeginManager instance.
678
+ *
679
+ * @param config - Manager configuration including wallets and contract addresses
680
+ */
681
+ constructor(t) {
682
+ b(this, "config");
683
+ this.config = t;
684
+ }
685
+ /**
686
+ * Prepare a peg-in: sizing pass → vault-root derivation (one wallet
687
+ * popup) → per-vault WOTS / hashlock derivation → commit pass with
688
+ * batch PSBT signing (one popup). Returns broadcast-ready txs, the
689
+ * pubkey snapshot, and the sensitive derived material.
690
+ *
691
+ * @throws If the wallet rejects, insufficient funds, or an internal
692
+ * invariant violation.
693
+ */
694
+ async preparePegin(t) {
695
+ if (t.amounts.length === 0)
696
+ throw new Error("amounts must contain at least one entry");
697
+ const n = await this.config.btcWallet.getPublicKeyHex(), s = $(n), o = await this.prepareSizing(s, t), r = o.selectedUTXOs.map(
698
+ (h) => ({
699
+ txid: nt(h.txid),
700
+ vout: h.vout
701
+ })
702
+ ), i = await Me(this.config.btcWallet, {
703
+ depositorBtcPubkey: nt(s),
704
+ fundingOutpoints: r
705
+ }), a = await this.expandPerVaultSecrets(i, t.amounts.length), { perVaultWotsKeys: l, wotsPkHashes: u, htlcSecretHexes: c, hashlocks: y } = a, g = await this.preparePeginCommit({
706
+ depositorBtcPubkeyRaw: n,
707
+ depositorBtcPubkey: s,
708
+ hashlocks: y,
709
+ sizing: o,
710
+ params: t
711
+ });
712
+ for (let h = 0; h < g.perVault.length; h++)
713
+ if (g.perVault[h].htlcVout !== h)
356
714
  throw new Error(
357
- `PSBT finalization failed and wallet did not auto-finalize: ${d}`
715
+ `Internal invariant violation: htlcVout/index mismatch at vault ${h} (expected ${h}, got ${g.perVault[h].htlcVout})`
358
716
  );
717
+ return {
718
+ transaction: {
719
+ ...g,
720
+ selectedUTXOs: o.selectedUTXOs,
721
+ fee: o.fee,
722
+ changeAmount: o.changeAmount
723
+ },
724
+ depositorBtcPubkey: s,
725
+ derivedSecrets: {
726
+ perVaultWotsKeys: l,
727
+ wotsPkHashes: u,
728
+ htlcSecretHexes: c
729
+ }
730
+ };
731
+ }
732
+ /**
733
+ * Derive per-vault WOTS keys + HTLC preimages from the wallet root.
734
+ * Takes ownership of `root`: zeros the buffer (and per-vault secret
735
+ * buffers) before returning, regardless of how the caller exits.
736
+ */
737
+ async expandPerVaultSecrets(t, n) {
738
+ const s = [], o = [], r = [], i = [];
739
+ try {
740
+ for (let a = 0; a < n; a++) {
741
+ const l = $e(t, a);
742
+ try {
743
+ const c = await fn(l);
744
+ s.push(c), o.push(gn(c));
745
+ } finally {
746
+ l.fill(0);
747
+ }
748
+ const u = Oe(t, a);
749
+ try {
750
+ const c = $t(u);
751
+ r.push(c), i.push(
752
+ ue(I(c)).slice(2)
753
+ );
754
+ } finally {
755
+ u.fill(0);
756
+ }
757
+ }
758
+ } finally {
759
+ t.fill(0);
359
760
  }
360
- const P = x.extractTransaction().toHex();
361
- return await we(P, h);
761
+ return { perVaultWotsKeys: s, wotsPkHashes: o, htlcSecretHexes: r, hashlocks: i };
362
762
  }
363
763
  /**
364
- * Registers a peg-in on Ethereum by calling the BTCVaultRegistry contract.
365
- *
366
- * This method:
367
- * 1. Re-verifies the PopSignature against the currently connected ETH
368
- * and BTC wallets — refuses to proceed if either has changed
369
- * 2. Derives vault ID and checks if it already exists (pre-flight)
370
- * 3. Encodes the contract call using viem
371
- * 4. Estimates gas (catches contract errors early with proper revert
372
- * reasons)
373
- * 5. Sends transaction with pre-estimated gas via
374
- * ethWallet.sendTransaction()
375
- *
376
- * The PopSignature must be obtained via
377
- * {@link signProofOfPossession} before this call.
764
+ * Build unfunded Pre-PegIn + select UTXOs. No PSBT signing.
378
765
  *
379
- * @param params - Registration parameters including the PopSignature
380
- * and the prepared Pre-PegIn / PegIn transactions
381
- * @returns Result containing Ethereum transaction hash and vault ID
382
- * @throws Error if the PopSignature does not match the connected wallets
383
- * @throws Error if the vault already exists
384
- * @throws Error if contract simulation fails (e.g., invalid signature,
385
- * unauthorized)
766
+ * Returns the full selection result (UTXOs, fee, changeAmount) so the
767
+ * commit pass funds the broadcast tx with the exact same set used to
768
+ * build the vault-context funding-outpoints commitment. Re-running
769
+ * `selectUtxosForPegin` in the commit pass would be deterministic given
770
+ * the same inputs, but threading the result through guarantees the
771
+ * domain separator structurally matches the funded tx inputs.
386
772
  */
387
- async registerPeginOnChain(t) {
773
+ async prepareSizing(t, n) {
774
+ const s = n.amounts.map(
775
+ () => yn
776
+ ), o = n.vaultKeeperBtcPubkeys.length, r = await bt({
777
+ depositorPubkey: t,
778
+ vaultProviderPubkey: _(n.vaultProviderBtcPubkey),
779
+ vaultKeeperPubkeys: n.vaultKeeperBtcPubkeys.map(_),
780
+ universalChallengerPubkeys: n.universalChallengerBtcPubkeys.map(_),
781
+ hashlocks: s,
782
+ timelockRefund: n.timelockRefund,
783
+ pegInAmounts: n.amounts,
784
+ feeRate: n.protocolFeeRate,
785
+ numLocalChallengers: o,
786
+ councilQuorum: n.councilQuorum,
787
+ councilSize: n.councilSize,
788
+ network: this.config.btcNetwork
789
+ }), i = pe(
790
+ [...n.availableUTXOs],
791
+ r.totalOutputValue,
792
+ n.mempoolFeeRate,
793
+ // No auth-anchor OP_RETURN in this PR (deferred to PR5).
794
+ be(r.htlcValues.length)
795
+ );
796
+ return {
797
+ selectedUTXOs: i.selectedUTXOs,
798
+ fee: i.fee,
799
+ changeAmount: i.changeAmount
800
+ };
801
+ }
802
+ /** Build PegIn txs and batch-sign their inputs with real hashlocks. */
803
+ async preparePeginCommit(t) {
388
804
  const {
389
- unsignedPrePeginTx: n,
390
- depositorSignedPeginTx: s,
805
+ depositorBtcPubkeyRaw: n,
806
+ depositorBtcPubkey: s,
807
+ hashlocks: o,
808
+ sizing: r,
809
+ params: i
810
+ } = t, a = _(i.vaultProviderBtcPubkey), l = i.vaultKeeperBtcPubkeys.map(_), u = i.universalChallengerBtcPubkeys.map(_), c = l.length, y = {
811
+ depositorPubkey: s,
812
+ vaultProviderPubkey: a,
813
+ vaultKeeperPubkeys: l,
814
+ universalChallengerPubkeys: u,
815
+ hashlocks: o,
816
+ timelockRefund: i.timelockRefund,
817
+ pegInAmounts: i.amounts,
818
+ feeRate: i.protocolFeeRate,
819
+ numLocalChallengers: c,
820
+ councilQuorum: i.councilQuorum,
821
+ councilSize: i.councilSize,
822
+ network: this.config.btcNetwork
823
+ }, g = await bt(y), h = wt(this.config.btcNetwork), p = we({
824
+ unfundedTxHex: g.psbtHex,
825
+ selectedUTXOs: r.selectedUTXOs,
826
+ changeAddress: i.changeAddress,
827
+ changeAmount: r.changeAmount,
828
+ network: h
829
+ }), T = _(q(p)), P = [], v = [], d = [];
830
+ for (let m = 0; m < o.length; m++) {
831
+ const w = await oe({
832
+ prePeginParams: y,
833
+ timelockPegin: i.timelockPegin,
834
+ fundedPrePeginTxHex: p,
835
+ htlcVout: m
836
+ }), E = await re({
837
+ peginTxHex: w.txHex,
838
+ fundedPrePeginTxHex: p,
839
+ depositorPubkey: s,
840
+ vaultProviderPubkey: a,
841
+ vaultKeeperPubkeys: l,
842
+ universalChallengerPubkeys: u,
843
+ hashlock: o[m],
844
+ timelockRefund: i.timelockRefund,
845
+ network: this.config.btcNetwork
846
+ });
847
+ P.push(w), v.push(E.psbtHex), d.push(
848
+ he(n, 1)
849
+ );
850
+ }
851
+ const x = await this.signPsbtsWithFallback(
852
+ v,
853
+ d
854
+ ), f = [];
855
+ for (let m = 0; m < x.length; m++) {
856
+ const w = ie(
857
+ x[m],
858
+ s
859
+ ), E = ae(x[m]);
860
+ f.push({
861
+ htlcVout: m,
862
+ htlcValue: g.htlcValues[m],
863
+ peginTxHex: E,
864
+ peginTxid: P[m].txid,
865
+ peginInputSignature: w,
866
+ vaultScriptPubKey: P[m].vaultScriptPubKey
867
+ });
868
+ }
869
+ return {
870
+ fundedPrePeginTxHex: p,
871
+ prePeginTxid: T,
872
+ perVault: f
873
+ };
874
+ }
875
+ /**
876
+ * Signs multiple PSBTs using batch signing if available, falling back to sequential signing.
877
+ *
878
+ * Wallets that support native batch signing (e.g. UniSat) will sign all PSBTs
879
+ * in a single interaction. Others (e.g. Ledger, AppKit) implement signPsbts
880
+ * by looping signPsbt internally, so the UX depends on the wallet adapter.
881
+ */
882
+ async signPsbtsWithFallback(t, n) {
883
+ if (typeof this.config.btcWallet.signPsbts == "function") {
884
+ const o = await this.config.btcWallet.signPsbts(
885
+ t,
886
+ n
887
+ );
888
+ if (o.length !== t.length)
889
+ throw new Error(
890
+ `Expected ${t.length} signed PSBTs but received ${o.length}`
891
+ );
892
+ return o;
893
+ }
894
+ const s = [];
895
+ for (let o = 0; o < t.length; o++) {
896
+ const r = await this.config.btcWallet.signPsbt(
897
+ t[o],
898
+ n[o]
899
+ );
900
+ s.push(r);
901
+ }
902
+ return s;
903
+ }
904
+ /**
905
+ * Signs and broadcasts a funded peg-in transaction to the Bitcoin network.
906
+ *
907
+ * This method:
908
+ * 1. Parses the funded transaction hex
909
+ * 2. Fetches UTXO data from mempool for each input
910
+ * 3. Creates a PSBT with proper witnessUtxo/tapInternalKey
911
+ * 4. Signs via btcWallet.signPsbt()
912
+ * 5. Finalizes and extracts the transaction
913
+ * 6. Broadcasts via mempool API
914
+ *
915
+ * @param params - Transaction hex and depositor public key
916
+ * @returns The broadcasted Bitcoin transaction ID
917
+ * @throws Error if signing or broadcasting fails
918
+ */
919
+ async signAndBroadcast(t) {
920
+ const { fundedPrePeginTxHex: n, depositorBtcPubkey: s } = t, o = n.startsWith("0x") ? n.slice(2) : n, r = ne.fromHex(o);
921
+ if (r.ins.length === 0)
922
+ throw new Error("Transaction has no inputs");
923
+ const i = new ft();
924
+ i.setVersion(r.version), i.setLocktime(r.locktime);
925
+ const a = et.from(
926
+ $(s),
927
+ "hex"
928
+ ), l = this.config.mempoolApiUrl, u = r.ins.map((d) => {
929
+ const x = et.from(d.hash).reverse().toString("hex"), f = d.index;
930
+ return Pn(x, f, t.localPrevouts, l).then(
931
+ (m) => ({ input: d, utxoData: m, txid: x, vout: f })
932
+ );
933
+ }), c = await Promise.all(u), y = c.reduce(
934
+ (d, x) => d + BigInt(x.utxoData.value),
935
+ 0n
936
+ ), g = r.outs.reduce(
937
+ (d, x) => d + BigInt(x.value),
938
+ 0n
939
+ );
940
+ if (y < g)
941
+ throw new Error(
942
+ `UTXO value mismatch: total input value (${y} sat) is less than total output value (${g} sat). This may indicate the mempool API returned manipulated UTXO data.`
943
+ );
944
+ const h = y - g;
945
+ if (h > yt)
946
+ throw new Error(
947
+ `Implied transaction fee (${h} sat) exceeds maximum reasonable fee (${yt} sat). This may indicate manipulated UTXO data.`
948
+ );
949
+ for (const { input: d, utxoData: x, txid: f, vout: m } of c) {
950
+ const w = me(
951
+ {
952
+ value: x.value,
953
+ scriptPubKey: x.scriptPubKey
954
+ },
955
+ a
956
+ );
957
+ i.addInput({
958
+ hash: d.hash,
959
+ index: d.index,
960
+ sequence: d.sequence,
961
+ ...w
962
+ });
963
+ }
964
+ for (const d of r.outs)
965
+ i.addOutput({
966
+ script: d.script,
967
+ value: d.value
968
+ });
969
+ const p = await this.config.btcWallet.signPsbt(i.toHex()), T = ft.fromHex(p);
970
+ try {
971
+ T.finalizeAllInputs();
972
+ } catch (d) {
973
+ if (!T.data.inputs.every(
974
+ (f) => f.finalScriptWitness || f.finalScriptSig
975
+ ))
976
+ throw new Error(
977
+ `PSBT finalization failed and wallet did not auto-finalize: ${d}`
978
+ );
979
+ }
980
+ const P = T.extractTransaction().toHex();
981
+ return await ye(P, l);
982
+ }
983
+ /**
984
+ * Registers a peg-in on Ethereum by calling the BTCVaultRegistry contract.
985
+ *
986
+ * This method:
987
+ * 1. Re-verifies the PopSignature against the currently connected ETH
988
+ * and BTC wallets — refuses to proceed if either has changed
989
+ * 2. Derives vault ID and checks if it already exists (pre-flight)
990
+ * 3. Encodes the contract call using viem
991
+ * 4. Estimates gas (catches contract errors early with proper revert
992
+ * reasons)
993
+ * 5. Sends transaction with pre-estimated gas via
994
+ * ethWallet.sendTransaction()
995
+ *
996
+ * The PopSignature must be obtained via
997
+ * {@link signProofOfPossession} before this call.
998
+ *
999
+ * @param params - Registration parameters including the PopSignature
1000
+ * and the prepared Pre-PegIn / PegIn transactions
1001
+ * @returns Result containing Ethereum transaction hash and vault ID
1002
+ * @throws Error if the PopSignature does not match the connected wallets
1003
+ * @throws Error if the vault already exists
1004
+ * @throws Error if contract simulation fails (e.g., invalid signature,
1005
+ * unauthorized)
1006
+ */
1007
+ async registerPeginOnChain(t) {
1008
+ const {
1009
+ unsignedPrePeginTx: n,
1010
+ depositorSignedPeginTx: s,
391
1011
  vaultProvider: o,
392
1012
  hashlock: r,
393
1013
  htlcVout: i,
394
1014
  depositorPayoutBtcAddress: a,
395
- depositorWotsPkHash: h,
1015
+ depositorWotsPkHash: l,
396
1016
  popSignature: u
397
1017
  } = t;
398
1018
  if (!this.config.ethWallet.account)
399
1019
  throw new Error("Ethereum wallet account not found");
400
1020
  const c = this.config.ethWallet.account.address;
401
- if (!bt(u.depositorEthAddress, c))
1021
+ if (!gt(u.depositorEthAddress, c))
402
1022
  throw new Error(
403
1023
  `Proof of possession was signed for ${u.depositorEthAddress} but the Ethereum wallet is currently connected to ${c}. Reconnect the original account or call signProofOfPossession() again.`
404
1024
  );
405
1025
  await this.assertPopMatchesBtcWallet(u);
406
- const m = u.btcPopSignature, l = I(u.depositorBtcPubkey), y = I(n), f = I(s), x = await this.resolvePayoutScriptPubKey(
1026
+ const y = u.btcPopSignature, g = I(u.depositorBtcPubkey), h = I(n), p = I(s), T = await this.resolvePayoutScriptPubKey(
407
1027
  a
408
- ), P = G(f), w = await Pt(
409
- v(P),
410
- v(c)
411
- ), d = I(w);
1028
+ ), P = q(p), v = await mt(
1029
+ _(P),
1030
+ _(c)
1031
+ ), d = I(v);
412
1032
  if (await this.checkVaultExists(d))
413
1033
  throw new Error(
414
1034
  `Vault already exists (ID: ${d}, peginTxHash: ${P}). 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.`
415
1035
  );
416
- const p = q({
1036
+ const f = j({
417
1037
  chain: this.config.ethChain,
418
- transport: Z()
1038
+ transport: z()
419
1039
  });
420
- let E;
1040
+ let m;
421
1041
  try {
422
- E = await p.readContract({
1042
+ m = await f.readContract({
423
1043
  address: this.config.vaultContracts.btcVaultRegistry,
424
- abi: O,
1044
+ abi: C,
425
1045
  functionName: "getPegInFee",
426
1046
  args: [o]
427
1047
  });
@@ -430,56 +1050,56 @@ class Nn {
430
1050
  "Failed to query pegin fee from the contract. Please check your network connection and that the contract address is correct."
431
1051
  );
432
1052
  }
433
- const k = xt({
434
- abi: O,
1053
+ const w = pt({
1054
+ abi: C,
435
1055
  functionName: "submitPeginRequest",
436
1056
  args: [
437
1057
  c,
438
- l,
439
- m,
1058
+ g,
440
1059
  y,
441
- f,
1060
+ h,
1061
+ p,
442
1062
  o,
443
1063
  r,
444
1064
  i,
445
- x,
446
- h
1065
+ T,
1066
+ l
447
1067
  ]
448
1068
  });
449
- let _;
1069
+ let E;
450
1070
  try {
451
- _ = await p.estimateGas({
1071
+ E = await f.estimateGas({
452
1072
  to: this.config.vaultContracts.btcVaultRegistry,
453
- data: k,
454
- value: E,
1073
+ data: w,
1074
+ value: m,
455
1075
  account: this.config.ethWallet.account.address
456
1076
  });
457
- } catch (j) {
458
- A(j);
1077
+ } catch (D) {
1078
+ H(D);
459
1079
  }
460
1080
  let B;
461
1081
  try {
462
1082
  B = await this.config.ethWallet.sendTransaction({
463
1083
  to: this.config.vaultContracts.btcVaultRegistry,
464
- data: k,
465
- value: E,
1084
+ data: w,
1085
+ value: m,
466
1086
  account: this.config.ethWallet.account,
467
1087
  chain: this.config.ethChain,
468
- gas: _
1088
+ gas: E
469
1089
  });
470
- } catch (j) {
471
- A(j);
1090
+ } catch (D) {
1091
+ H(D);
472
1092
  }
473
- const X = await p.waitForTransactionReceipt({
1093
+ const K = await f.waitForTransactionReceipt({
474
1094
  hash: B,
475
- timeout: _t
1095
+ timeout: Ot
476
1096
  });
477
- return X.status === "reverted" && A(
1097
+ return K.status === "reverted" && H(
478
1098
  new Error(
479
1099
  `Transaction reverted. Hash: ${B}. Check the transaction on block explorer for details.`
480
1100
  )
481
1101
  ), {
482
- ethTxHash: X.transactionHash,
1102
+ ethTxHash: K.transactionHash,
483
1103
  vaultId: d,
484
1104
  peginTxHash: P
485
1105
  };
@@ -501,39 +1121,39 @@ class Nn {
501
1121
  if (!this.config.ethWallet.account)
502
1122
  throw new Error("Ethereum wallet account not found");
503
1123
  const i = this.config.ethWallet.account.address;
504
- if (!bt(r.depositorEthAddress, i))
1124
+ if (!gt(r.depositorEthAddress, i))
505
1125
  throw new Error(
506
1126
  `Proof of possession was signed for ${r.depositorEthAddress} but the Ethereum wallet is currently connected to ${i}. Reconnect the original account or call signProofOfPossession() again.`
507
1127
  );
508
1128
  await this.assertPopMatchesBtcWallet(r);
509
- const a = r.btcPopSignature, h = [];
510
- for (const p of o)
511
- h.push(
512
- await this.resolvePayoutScriptPubKey(p.depositorPayoutBtcAddress)
1129
+ const a = r.btcPopSignature, l = [];
1130
+ for (const f of o)
1131
+ l.push(
1132
+ await this.resolvePayoutScriptPubKey(f.depositorPayoutBtcAddress)
513
1133
  );
514
1134
  const u = [];
515
- for (const p of o) {
516
- const E = I(
517
- p.depositorSignedPeginTx
518
- ), k = G(E), _ = await Pt(
519
- v(k),
520
- v(i)
521
- ), B = I(_);
1135
+ for (const f of o) {
1136
+ const m = I(
1137
+ f.depositorSignedPeginTx
1138
+ ), w = q(m), E = await mt(
1139
+ _(w),
1140
+ _(i)
1141
+ ), B = I(E);
522
1142
  if (await this.checkVaultExists(B))
523
1143
  throw new Error(
524
- `Vault already exists (ID: ${B}, peginTxHash: ${k}). To create a new vault, use different UTXOs or a different amount.`
1144
+ `Vault already exists (ID: ${B}, peginTxHash: ${w}). To create a new vault, use different UTXOs or a different amount.`
525
1145
  );
526
- u.push({ vaultId: B, peginTxHash: k });
1146
+ u.push({ vaultId: B, peginTxHash: w });
527
1147
  }
528
- const c = q({
1148
+ const c = j({
529
1149
  chain: this.config.ethChain,
530
- transport: Z()
1150
+ transport: z()
531
1151
  });
532
- let m;
1152
+ let y;
533
1153
  try {
534
- m = await c.readContract({
1154
+ y = await c.readContract({
535
1155
  address: this.config.vaultContracts.btcVaultRegistry,
536
- abi: O,
1156
+ abi: C,
537
1157
  functionName: "getPegInFee",
538
1158
  args: [n]
539
1159
  });
@@ -542,756 +1162,178 @@ class Nn {
542
1162
  "Failed to query pegin fee from the contract. Please check your network connection and that the contract address is correct."
543
1163
  );
544
1164
  }
545
- const l = m * BigInt(o.length), y = I(
1165
+ const g = y * BigInt(o.length), h = I(
546
1166
  r.depositorBtcPubkey
547
- ), f = I(s), x = o.map((p, E) => ({
548
- depositorBtcPubKey: y,
1167
+ ), p = I(s), T = o.map((f, m) => ({
1168
+ depositorBtcPubKey: h,
549
1169
  btcPopSignature: a,
550
- unsignedPrePeginTx: f,
1170
+ unsignedPrePeginTx: p,
551
1171
  depositorSignedPeginTx: I(
552
- p.depositorSignedPeginTx
1172
+ f.depositorSignedPeginTx
553
1173
  ),
554
- hashlock: p.hashlock,
555
- htlcVout: p.htlcVout,
556
- referralCode: Se,
557
- depositorPayoutBtcAddress: h[E],
558
- depositorWotsPkHash: p.depositorWotsPkHash
559
- })), P = xt({
560
- abi: O,
1174
+ hashlock: f.hashlock,
1175
+ htlcVout: f.htlcVout,
1176
+ referralCode: pn,
1177
+ depositorPayoutBtcAddress: l[m],
1178
+ depositorWotsPkHash: f.depositorWotsPkHash
1179
+ })), P = pt({
1180
+ abi: C,
561
1181
  functionName: "submitPeginRequestBatch",
562
- args: [i, n, x]
1182
+ args: [i, n, T]
563
1183
  });
564
- let w;
1184
+ let v;
565
1185
  try {
566
- w = await c.estimateGas({
1186
+ v = await c.estimateGas({
567
1187
  to: this.config.vaultContracts.btcVaultRegistry,
568
1188
  data: P,
569
- value: l,
1189
+ value: g,
570
1190
  account: this.config.ethWallet.account.address
571
1191
  });
572
- } catch (p) {
573
- A(p);
1192
+ } catch (f) {
1193
+ H(f);
574
1194
  }
575
1195
  let d;
576
1196
  try {
577
1197
  d = await this.config.ethWallet.sendTransaction({
578
1198
  to: this.config.vaultContracts.btcVaultRegistry,
579
1199
  data: P,
580
- value: l,
1200
+ value: g,
581
1201
  account: this.config.ethWallet.account,
582
1202
  chain: this.config.ethChain,
583
- gas: w
584
- });
585
- } catch (p) {
586
- A(p);
587
- }
588
- const g = await c.waitForTransactionReceipt({
589
- hash: d,
590
- timeout: _t
591
- });
592
- return g.status === "reverted" && A(
593
- new Error(
594
- `Batch transaction reverted. Hash: ${d}. Check the transaction on block explorer for details.`
595
- )
596
- ), {
597
- ethTxHash: g.transactionHash,
598
- vaults: u
599
- };
600
- }
601
- /**
602
- * Check if a vault already exists for a given vault ID.
603
- *
604
- * @param vaultId - The Bitcoin transaction hash (vault ID)
605
- * @returns True if vault exists, false otherwise
606
- */
607
- async checkVaultExists(t) {
608
- try {
609
- return (await q({
610
- chain: this.config.ethChain,
611
- transport: Z()
612
- }).readContract({
613
- address: this.config.vaultContracts.btcVaultRegistry,
614
- abi: O,
615
- functionName: "getBtcVaultBasicInfo",
616
- args: [t]
617
- }))[0] !== oe;
618
- } catch {
619
- return !1;
620
- }
621
- }
622
- /**
623
- * Resolve the BTC payout address to a scriptPubKey hex for the contract.
624
- *
625
- * If a payout address is provided, converts it directly.
626
- * If omitted, uses the wallet's address and validates it against the
627
- * wallet's public key to guard against a compromised wallet provider.
628
- */
629
- async resolvePayoutScriptPubKey(t) {
630
- let n;
631
- if (t)
632
- n = t;
633
- else {
634
- n = await this.config.btcWallet.getAddress();
635
- const o = await this.config.btcWallet.getPublicKeyHex();
636
- if (!he(
637
- n,
638
- o,
639
- this.config.btcNetwork
640
- ))
641
- throw new Error(
642
- "The BTC address from your wallet does not match the wallet's public key. Please ensure your wallet is using a supported address type (Taproot or Native SegWit)."
643
- );
644
- }
645
- const s = kt(this.config.btcNetwork);
646
- try {
647
- return `0x${ne.address.toOutputScript(n, s).toString("hex")}`;
648
- } catch {
649
- throw new Error(
650
- `Invalid BTC payout address: "${n}". Please provide a valid Bitcoin address for the ${this.config.btcNetwork} network.`
651
- );
652
- }
653
- }
654
- /**
655
- * Sign a BIP-322 BTC Proof-of-Possession binding the connected BTC
656
- * wallet to the connected ETH account for this chain and vault
657
- * registry. The returned {@link PopSignature} can be reused across
658
- * every register call in the same session.
659
- */
660
- async signProofOfPossession() {
661
- if (!this.config.ethWallet.account)
662
- throw new Error("Ethereum wallet account not found");
663
- const t = this.config.ethWallet.account.address, n = $(
664
- await this.config.btcWallet.getPublicKeyHex()
665
- ), s = this.config.vaultContracts.btcVaultRegistry, o = `${t.toLowerCase()}:${this.config.ethChain.id}:pegin:${s.toLowerCase()}`, r = await this.config.btcWallet.signMessage(
666
- o,
667
- "bip322-simple"
668
- );
669
- return {
670
- btcPopSignature: Oe(r),
671
- depositorEthAddress: t,
672
- depositorBtcPubkey: n
673
- };
674
- }
675
- async assertPopMatchesBtcWallet(t) {
676
- const n = $(
677
- await this.config.btcWallet.getPublicKeyHex()
678
- ), s = $(t.depositorBtcPubkey);
679
- if (n !== s)
680
- throw new Error(
681
- `Proof of possession was signed with BTC pubkey ${s} but the BTC wallet is currently connected to ${n}. Reconnect the original wallet or call signProofOfPossession() again.`
682
- );
683
- }
684
- /**
685
- * Gets the configured Bitcoin network.
686
- *
687
- * @returns The Bitcoin network (mainnet, testnet, signet, regtest)
688
- */
689
- getNetwork() {
690
- return this.config.btcNetwork;
691
- }
692
- /**
693
- * Gets the configured BTCVaultRegistry contract address.
694
- *
695
- * @returns The Ethereum address of the BTCVaultRegistry contract
696
- */
697
- getVaultContractAddress() {
698
- return this.config.vaultContracts.btcVaultRegistry;
699
- }
700
- }
701
- class Ft {
702
- constructor(t, n) {
703
- b(this, "oHash");
704
- b(this, "iHash");
705
- b(this, "blockLen");
706
- b(this, "outputLen");
707
- b(this, "finished", !1);
708
- b(this, "destroyed", !1);
709
- if (ht(t), U(n, void 0, "key"), this.iHash = t.create(), typeof this.iHash.update != "function")
710
- throw new Error("Expected instance of class which extends utils.Hash");
711
- this.blockLen = this.iHash.blockLen, this.outputLen = this.iHash.outputLen;
712
- const s = this.blockLen, o = new Uint8Array(s);
713
- o.set(n.length > s ? t.create().update(n).digest() : n);
714
- for (let r = 0; r < o.length; r++)
715
- o[r] ^= 54;
716
- this.iHash.update(o), this.oHash = t.create();
717
- for (let r = 0; r < o.length; r++)
718
- o[r] ^= 106;
719
- this.oHash.update(o), S(o);
720
- }
721
- update(t) {
722
- return V(this), this.iHash.update(t), this;
723
- }
724
- digestInto(t) {
725
- V(this), U(t, this.outputLen, "output"), this.finished = !0, this.iHash.digestInto(t), this.oHash.update(t), this.oHash.digestInto(t), this.destroy();
726
- }
727
- digest() {
728
- const t = new Uint8Array(this.oHash.outputLen);
729
- return this.digestInto(t), t;
730
- }
731
- _cloneInto(t) {
732
- t || (t = Object.create(Object.getPrototypeOf(this), {}));
733
- const { oHash: n, iHash: s, finished: o, destroyed: r, blockLen: i, outputLen: a } = this;
734
- return t = t, t.finished = o, t.destroyed = r, t.blockLen = i, t.outputLen = a, t.oHash = n._cloneInto(t.oHash), t.iHash = s._cloneInto(t.iHash), t;
735
- }
736
- clone() {
737
- return this._cloneInto();
738
- }
739
- destroy() {
740
- this.destroyed = !0, this.oHash.destroy(), this.iHash.destroy();
741
- }
742
- }
743
- const K = (e, t, n) => new Ft(e, t).update(n).digest();
744
- K.create = (e, t) => new Ft(e, t);
745
- const Le = /* @__PURE__ */ Uint8Array.from([
746
- 7,
747
- 4,
748
- 13,
749
- 1,
750
- 10,
751
- 6,
752
- 15,
753
- 3,
754
- 12,
755
- 0,
756
- 9,
757
- 5,
758
- 2,
759
- 14,
760
- 11,
761
- 8
762
- ]), Mt = Uint8Array.from(new Array(16).fill(0).map((e, t) => t)), Re = Mt.map((e) => (9 * e + 5) % 16), Nt = /* @__PURE__ */ (() => {
763
- const n = [[Mt], [Re]];
764
- for (let s = 0; s < 4; s++)
765
- for (let o of n)
766
- o.push(o[s].map((r) => Le[r]));
767
- return n;
768
- })(), Vt = Nt[0], Dt = Nt[1], Kt = /* @__PURE__ */ [
769
- [11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8],
770
- [12, 13, 11, 15, 6, 9, 9, 7, 12, 15, 11, 13, 7, 8, 7, 7],
771
- [13, 15, 14, 11, 7, 7, 6, 8, 13, 14, 13, 12, 5, 5, 6, 9],
772
- [14, 11, 12, 14, 8, 6, 5, 5, 15, 12, 15, 14, 9, 9, 8, 6],
773
- [15, 12, 13, 13, 9, 5, 8, 6, 14, 11, 12, 11, 8, 6, 5, 5]
774
- ].map((e) => Uint8Array.from(e)), Ue = /* @__PURE__ */ Vt.map((e, t) => e.map((n) => Kt[t][n])), We = /* @__PURE__ */ Dt.map((e, t) => e.map((n) => Kt[t][n])), Fe = /* @__PURE__ */ Uint32Array.from([
775
- 0,
776
- 1518500249,
777
- 1859775393,
778
- 2400959708,
779
- 2840853838
780
- ]), Me = /* @__PURE__ */ Uint32Array.from([
781
- 1352829926,
782
- 1548603684,
783
- 1836072691,
784
- 2053994217,
785
- 0
786
- ]);
787
- function vt(e, t, n, s) {
788
- return e === 0 ? t ^ n ^ s : e === 1 ? t & n | ~t & s : e === 2 ? (t | ~n) ^ s : e === 3 ? t & s | n & ~s : t ^ (n | ~s);
789
- }
790
- const M = /* @__PURE__ */ new Uint32Array(16);
791
- class Ne extends be {
792
- constructor() {
793
- super(64, 20, 8, !0);
794
- b(this, "h0", 1732584193);
795
- b(this, "h1", -271733879);
796
- b(this, "h2", -1732584194);
797
- b(this, "h3", 271733878);
798
- b(this, "h4", -1009589776);
799
- }
800
- get() {
801
- const { h0: n, h1: s, h2: o, h3: r, h4: i } = this;
802
- return [n, s, o, r, i];
803
- }
804
- set(n, s, o, r, i) {
805
- this.h0 = n | 0, this.h1 = s | 0, this.h2 = o | 0, this.h3 = r | 0, this.h4 = i | 0;
806
- }
807
- process(n, s) {
808
- for (let f = 0; f < 16; f++, s += 4)
809
- M[f] = n.getUint32(s, !0);
810
- let o = this.h0 | 0, r = o, i = this.h1 | 0, a = i, h = this.h2 | 0, u = h, c = this.h3 | 0, m = c, l = this.h4 | 0, y = l;
811
- for (let f = 0; f < 5; f++) {
812
- const x = 4 - f, P = Fe[f], w = Me[f], d = Vt[f], g = Dt[f], p = Ue[f], E = We[f];
813
- for (let k = 0; k < 16; k++) {
814
- const _ = F(o + vt(f, i, h, c) + M[d[k]] + P, p[k]) + l | 0;
815
- o = l, l = c, c = F(h, 10) | 0, h = i, i = _;
816
- }
817
- for (let k = 0; k < 16; k++) {
818
- const _ = F(r + vt(x, a, u, m) + M[g[k]] + w, E[k]) + y | 0;
819
- r = y, y = m, m = F(u, 10) | 0, u = a, a = _;
820
- }
821
- }
822
- this.set(this.h1 + h + m | 0, this.h2 + c + y | 0, this.h3 + l + r | 0, this.h4 + o + a | 0, this.h0 + i + u | 0);
823
- }
824
- roundClean() {
825
- S(M);
826
- }
827
- destroy() {
828
- this.destroyed = !0, S(this.buffer), this.set(0, 0, 0, 0, 0);
829
- }
830
- }
831
- const Ve = /* @__PURE__ */ Ut(() => new Ne()), De = BigInt(0), L = BigInt(1), Ke = BigInt(2), Xe = BigInt(7), je = BigInt(256), qe = BigInt(113), Xt = [], jt = [], qt = [];
832
- for (let e = 0, t = L, n = 1, s = 0; e < 24; e++) {
833
- [n, s] = [s, (2 * n + 3 * s) % 5], Xt.push(2 * (5 * s + n)), jt.push((e + 1) * (e + 2) / 2 % 64);
834
- let o = De;
835
- for (let r = 0; r < 7; r++)
836
- t = (t << L ^ (t >> Xe) * qe) % je, t & Ke && (o ^= L << (L << BigInt(r)) - L);
837
- qt.push(o);
838
- }
839
- const Zt = xe(qt, !0), Ze = Zt[0], Ge = Zt[1], Bt = (e, t, n) => n > 32 ? Ie(e, t, n) : Ee(e, t, n), St = (e, t, n) => n > 32 ? _e(e, t, n) : Te(e, t, n);
840
- function ze(e, t = 24) {
841
- const n = new Uint32Array(10);
842
- for (let s = 24 - t; s < 24; s++) {
843
- for (let i = 0; i < 10; i++)
844
- n[i] = e[i] ^ e[i + 10] ^ e[i + 20] ^ e[i + 30] ^ e[i + 40];
845
- for (let i = 0; i < 10; i += 2) {
846
- const a = (i + 8) % 10, h = (i + 2) % 10, u = n[h], c = n[h + 1], m = Bt(u, c, 1) ^ n[a], l = St(u, c, 1) ^ n[a + 1];
847
- for (let y = 0; y < 50; y += 10)
848
- e[i + y] ^= m, e[i + y + 1] ^= l;
849
- }
850
- let o = e[2], r = e[3];
851
- for (let i = 0; i < 24; i++) {
852
- const a = jt[i], h = Bt(o, r, a), u = St(o, r, a), c = Xt[i];
853
- o = e[c], r = e[c + 1], e[c] = h, e[c + 1] = u;
854
- }
855
- for (let i = 0; i < 50; i += 10) {
856
- for (let a = 0; a < 10; a++)
857
- n[a] = e[i + a];
858
- for (let a = 0; a < 10; a++)
859
- e[i + a] ^= ~n[(a + 2) % 10] & n[(a + 4) % 10];
860
- }
861
- e[0] ^= Ze[s], e[1] ^= Ge[s];
862
- }
863
- S(n);
864
- }
865
- class ft {
866
- // NOTE: we accept arguments in bytes instead of bits here.
867
- constructor(t, n, s, o = !1, r = 24) {
868
- b(this, "state");
869
- b(this, "pos", 0);
870
- b(this, "posOut", 0);
871
- b(this, "finished", !1);
872
- b(this, "state32");
873
- b(this, "destroyed", !1);
874
- b(this, "blockLen");
875
- b(this, "suffix");
876
- b(this, "outputLen");
877
- b(this, "enableXOF", !1);
878
- b(this, "rounds");
879
- if (this.blockLen = t, this.suffix = n, this.outputLen = s, this.enableXOF = o, this.rounds = r, C(s, "outputLen"), !(0 < t && t < 200))
880
- throw new Error("only keccak-f1600 function is supported");
881
- this.state = new Uint8Array(200), this.state32 = Pe(this.state);
882
- }
883
- clone() {
884
- return this._cloneInto();
885
- }
886
- keccak() {
887
- Tt(this.state32), ze(this.state32, this.rounds), Tt(this.state32), this.posOut = 0, this.pos = 0;
888
- }
889
- update(t) {
890
- V(this), U(t);
891
- const { blockLen: n, state: s } = this, o = t.length;
892
- for (let r = 0; r < o; ) {
893
- const i = Math.min(n - this.pos, o - r);
894
- for (let a = 0; a < i; a++)
895
- s[this.pos++] ^= t[r++];
896
- this.pos === n && this.keccak();
897
- }
898
- return this;
899
- }
900
- finish() {
901
- if (this.finished)
902
- return;
903
- this.finished = !0;
904
- const { state: t, suffix: n, pos: s, blockLen: o } = this;
905
- t[s] ^= n, (n & 128) !== 0 && s === o - 1 && this.keccak(), t[o - 1] ^= 128, this.keccak();
906
- }
907
- writeInto(t) {
908
- V(this, !1), U(t), this.finish();
909
- const n = this.state, { blockLen: s } = this;
910
- for (let o = 0, r = t.length; o < r; ) {
911
- this.posOut >= s && this.keccak();
912
- const i = Math.min(s - this.posOut, r - o);
913
- t.set(n.subarray(this.posOut, this.posOut + i), o), this.posOut += i, o += i;
1203
+ gas: v
1204
+ });
1205
+ } catch (f) {
1206
+ H(f);
914
1207
  }
915
- return t;
916
- }
917
- xofInto(t) {
918
- if (!this.enableXOF)
919
- throw new Error("XOF is not possible for this instance");
920
- return this.writeInto(t);
921
- }
922
- xof(t) {
923
- return C(t), this.xofInto(new Uint8Array(t));
924
- }
925
- digestInto(t) {
926
- if (ke(t, this), this.finished)
927
- throw new Error("digest() was already called");
928
- return this.writeInto(t), this.destroy(), t;
929
- }
930
- digest() {
931
- return this.digestInto(new Uint8Array(this.outputLen));
932
- }
933
- destroy() {
934
- this.destroyed = !0, S(this.state);
935
- }
936
- _cloneInto(t) {
937
- const { blockLen: n, suffix: s, outputLen: o, rounds: r, enableXOF: i } = this;
938
- return t || (t = new ft(n, s, o, i, r)), t.state32.set(this.state32), t.pos = this.pos, t.posOut = this.posOut, t.finished = this.finished, t.rounds = r, t.suffix = s, t.outputLen = o, t.enableXOF = i, t.destroyed = this.destroyed, t;
1208
+ const x = await c.waitForTransactionReceipt({
1209
+ hash: d,
1210
+ timeout: Ot
1211
+ });
1212
+ return x.status === "reverted" && H(
1213
+ new Error(
1214
+ `Batch transaction reverted. Hash: ${d}. Check the transaction on block explorer for details.`
1215
+ )
1216
+ ), {
1217
+ ethTxHash: x.transactionHash,
1218
+ vaults: u
1219
+ };
939
1220
  }
940
- }
941
- const Ye = (e, t, n, s = {}) => Ut(() => new ft(t, e, n), s), Je = /* @__PURE__ */ Ye(1, 136, 32);
942
- function Qe(e, t, n, s) {
943
- ht(e);
944
- const o = Be({ dkLen: 32, asyncTick: 10 }, s), { c: r, dkLen: i, asyncTick: a } = o;
945
- if (C(r, "c"), C(i, "dkLen"), C(a, "asyncTick"), r < 1)
946
- throw new Error("iterations (c) must be >= 1");
947
- const h = It(t, "password"), u = It(n, "salt"), c = new Uint8Array(i), m = K.create(e, h), l = m._cloneInto().update(u);
948
- return { c: r, dkLen: i, asyncTick: a, DK: c, PRF: m, PRFSalt: l };
949
- }
950
- function tn(e, t, n, s, o) {
951
- return e.destroy(), t.destroy(), s && s.destroy(), S(o), n;
952
- }
953
- function en(e, t, n, s) {
954
- const { c: o, dkLen: r, DK: i, PRF: a, PRFSalt: h } = Qe(e, t, n, s);
955
- let u;
956
- const c = new Uint8Array(4), m = ve(c), l = new Uint8Array(a.outputLen);
957
- for (let y = 1, f = 0; f < r; y++, f += a.outputLen) {
958
- const x = i.subarray(f, f + a.outputLen);
959
- m.setInt32(0, y, !1), (u = h._cloneInto(u)).update(c).digestInto(l), x.set(l.subarray(0, x.length));
960
- for (let P = 1; P < o; P++) {
961
- a._cloneInto(u).update(l).digestInto(l);
962
- for (let w = 0; w < x.length; w++)
963
- x[w] ^= l[w];
1221
+ /**
1222
+ * Check if a vault already exists for a given vault ID.
1223
+ *
1224
+ * @param vaultId - The Bitcoin transaction hash (vault ID)
1225
+ * @returns True if vault exists, false otherwise
1226
+ */
1227
+ async checkVaultExists(t) {
1228
+ try {
1229
+ return (await j({
1230
+ chain: this.config.ethChain,
1231
+ transport: z()
1232
+ }).readContract({
1233
+ address: this.config.vaultContracts.btcVaultRegistry,
1234
+ abi: C,
1235
+ functionName: "getBtcVaultBasicInfo",
1236
+ args: [t]
1237
+ })).depositor !== se;
1238
+ } catch {
1239
+ return !1;
964
1240
  }
965
1241
  }
966
- return tn(a, h, i, u, l);
967
- }
968
- function Gt(e) {
969
- if (typeof e != "string")
970
- throw new TypeError("invalid mnemonic type: " + typeof e);
971
- return e.normalize("NFKD");
972
- }
973
- function nn(e) {
974
- const t = Gt(e), n = t.split(" ");
975
- if (![12, 15, 18, 21, 24].includes(n.length))
976
- throw new Error("Invalid mnemonic");
977
- return { nfkd: t, words: n };
978
- }
979
- const sn = (e) => Gt("mnemonic" + e);
980
- function on(e, t = "") {
981
- return en(Wt, nn(e).nfkd, sn(t), { c: 2048, dkLen: 64 });
982
- }
983
- const z = 32, Y = 64, rn = 4, T = 20, at = 4, zt = 2, an = 0, cn = 1, N = [64, 64];
984
- function ct(...e) {
985
- const t = e.reduce((o, r) => o + r.length, 0), n = new Uint8Array(t);
986
- let s = 0;
987
- for (const o of e)
988
- n.set(o, s), s += o.length;
989
- return n;
990
- }
991
- function J(e) {
992
- return new TextEncoder().encode(e);
993
- }
994
- function Q(e) {
995
- const t = new Uint8Array(rn);
996
- return new DataView(t.buffer).setUint32(0, e.length, !1), ct(t, e);
997
- }
998
- function At(e) {
999
- return e.startsWith("0x") || e.startsWith("0X") ? e.slice(2) : e;
1000
- }
1001
- const ln = (e) => Array.from(e).map((t) => t.toString(16).padStart(2, "0")).join("");
1002
- function un(e, t) {
1003
- return K(Wt, e, t);
1004
- }
1005
- function gt(e) {
1006
- return Ve(W(e));
1007
- }
1008
- function Yt(e) {
1009
- return (1 << e) - 1;
1010
- }
1011
- function hn(e) {
1012
- let t = 1;
1013
- for (; t * t < e + 1; ) t++;
1014
- return Math.max(t, 2);
1015
- }
1016
- function dn(e) {
1017
- const t = at, n = Yt(t), s = e * n;
1018
- return { d: t, n: e, checksum_radix: hn(s) };
1019
- }
1020
- function tt(e, t) {
1021
- const n = [];
1022
- let s = t;
1023
- for (; s > 0; )
1024
- n.push(s & 255), s >>>= 8;
1025
- const o = new Uint8Array(e.length + n.length);
1026
- o.set(e);
1027
- for (let r = 0; r < n.length; r++)
1028
- o[e.length + r] = n[r];
1029
- return gt(o);
1030
- }
1031
- function et(e, t) {
1032
- let n = e;
1033
- for (let s = 0; s < t; s++)
1034
- n = gt(n);
1035
- return n;
1036
- }
1037
- function fn(e, t) {
1038
- const n = Yt(t.d), s = t.checksum_radix - 1, o = Math.floor(t.n * n / t.checksum_radix), r = [];
1039
- for (let c = 0; c < t.n; c++) {
1040
- const m = tt(e, c + zt), l = et(m, n);
1041
- r.push(Array.from(l));
1042
- }
1043
- const i = tt(
1044
- e,
1045
- an
1046
- ), a = et(
1047
- i,
1048
- s
1049
- ), h = tt(
1050
- e,
1051
- cn
1052
- ), u = et(
1053
- h,
1054
- o
1055
- );
1056
- return {
1057
- config: t,
1058
- message_terminals: r,
1059
- checksum_major_terminal: Array.from(u),
1060
- checksum_minor_terminal: Array.from(a)
1061
- };
1062
- }
1063
- function gn(e) {
1064
- const t = on(e), n = new Uint8Array(t);
1065
- return t.fill(0), n;
1066
- }
1067
- async function pn(e, t, n, s) {
1068
- if (e.length !== Y)
1069
- throw new Error(
1070
- `WOTS seed must be exactly ${Y} bytes, got ${e.length}`
1071
- );
1072
- const o = At(t).toLowerCase(), r = At(n).toLowerCase(), i = e.slice(z, Y), a = e.slice(0, z), h = ct(
1073
- a,
1074
- ct(
1075
- Q(J(o)),
1076
- Q(J(r)),
1077
- Q(J(s.toLowerCase()))
1078
- )
1079
- ), u = un(i, h), c = u.slice(0, z);
1080
- try {
1081
- const m = [];
1082
- for (let l = 0; l < N.length; l++) {
1083
- const y = N[l], f = dn(y), x = new Uint8Array(c.length + 1);
1084
- x.set(c), x[c.length] = l;
1085
- const P = gt(x);
1086
- try {
1087
- const w = fn(P, f);
1088
- if (w.config.d !== at)
1089
- throw new Error(`Block ${l}: expected d=${at}, got d=${w.config.d}`);
1090
- if (w.config.n !== y)
1091
- throw new Error(`Block ${l}: expected n=${y}, got n=${w.config.n}`);
1092
- if (w.message_terminals.length !== y)
1093
- throw new Error(`Block ${l}: expected ${y} message terminals, got ${w.message_terminals.length}`);
1094
- for (let d = 0; d < w.message_terminals.length; d++)
1095
- if (w.message_terminals[d].length !== T)
1096
- throw new Error(`Block ${l} terminal ${d}: expected ${T} bytes, got ${w.message_terminals[d].length}`);
1097
- if (w.checksum_minor_terminal.length !== T)
1098
- throw new Error(`Block ${l} checksum_minor: expected ${T} bytes`);
1099
- if (w.checksum_major_terminal.length !== T)
1100
- throw new Error(`Block ${l} checksum_major: expected ${T} bytes`);
1101
- m.push(w);
1102
- } finally {
1103
- x.fill(0), P.fill(0);
1104
- }
1242
+ /**
1243
+ * Resolve the BTC payout address to a scriptPubKey hex for the contract.
1244
+ *
1245
+ * If a payout address is provided, converts it directly.
1246
+ * If omitted, uses the wallet's address and validates it against the
1247
+ * wallet's public key to guard against a compromised wallet provider.
1248
+ */
1249
+ async resolvePayoutScriptPubKey(t) {
1250
+ let n;
1251
+ if (t)
1252
+ n = t;
1253
+ else {
1254
+ n = await this.config.btcWallet.getAddress();
1255
+ const o = await this.config.btcWallet.getPublicKeyHex();
1256
+ if (!ce(
1257
+ n,
1258
+ o,
1259
+ this.config.btcNetwork
1260
+ ))
1261
+ throw new Error(
1262
+ "The BTC address from your wallet does not match the wallet's public key. Please ensure your wallet is using a supported address type (Taproot or Native SegWit)."
1263
+ );
1105
1264
  }
1106
- if (m.length !== N.length)
1265
+ const s = wt(this.config.btcNetwork);
1266
+ try {
1267
+ return `0x${ee.address.toOutputScript(n, s).toString("hex")}`;
1268
+ } catch {
1107
1269
  throw new Error(
1108
- `Expected ${N.length} blocks, got ${m.length}`
1270
+ `Invalid BTC payout address: "${n}". Please provide a valid Bitcoin address for the ${this.config.btcNetwork} network.`
1109
1271
  );
1110
- return m;
1111
- } finally {
1112
- h.fill(0), i.fill(0), a.fill(0), u.fill(0), c.fill(0), e.fill(0);
1272
+ }
1113
1273
  }
1114
- }
1115
- function nt(e, t, n) {
1116
- if (e.length !== T)
1117
- throw new Error(
1118
- `Block ${t} ${n}: expected ${T} bytes, got ${e.length}`
1274
+ /**
1275
+ * Sign a BIP-322 BTC Proof-of-Possession binding the connected BTC
1276
+ * wallet to the connected ETH account for this chain and vault
1277
+ * registry. The returned {@link PopSignature} can be reused across
1278
+ * every register call in the same session.
1279
+ */
1280
+ async signProofOfPossession() {
1281
+ if (!this.config.ethWallet.account)
1282
+ throw new Error("Ethereum wallet account not found");
1283
+ const t = this.config.ethWallet.account.address, n = $(
1284
+ await this.config.btcWallet.getPublicKeyHex()
1285
+ ), s = this.config.vaultContracts.btcVaultRegistry, o = `${t.toLowerCase()}:${this.config.ethChain.id}:pegin:${s.toLowerCase()}`, r = await this.config.btcWallet.signMessage(
1286
+ o,
1287
+ "bip322-simple"
1119
1288
  );
1120
- for (let s = 0; s < e.length; s++) {
1121
- const o = e[s];
1122
- if (!Number.isInteger(o) || o < 0 || o > 255)
1289
+ return {
1290
+ btcPopSignature: xn(r),
1291
+ depositorEthAddress: t,
1292
+ depositorBtcPubkey: n
1293
+ };
1294
+ }
1295
+ async assertPopMatchesBtcWallet(t) {
1296
+ const n = $(
1297
+ await this.config.btcWallet.getPublicKeyHex()
1298
+ ), s = $(t.depositorBtcPubkey);
1299
+ if (n !== s)
1123
1300
  throw new Error(
1124
- `Block ${t} ${n}[${s}]: invalid byte value ${o}`
1301
+ `Proof of possession was signed with BTC pubkey ${s} but the BTC wallet is currently connected to ${n}. Reconnect the original wallet or call signProofOfPossession() again.`
1125
1302
  );
1126
1303
  }
1127
- }
1128
- function mn(e) {
1129
- if (e.length === 0)
1130
- throw new Error("Public keys array must not be empty");
1131
- for (let r = 0; r < e.length; r++) {
1132
- const i = e[r];
1133
- nt(i.checksum_minor_terminal, r, "checksum_minor_terminal"), nt(i.checksum_major_terminal, r, "checksum_major_terminal");
1134
- for (let a = 0; a < i.message_terminals.length; a++)
1135
- nt(i.message_terminals[a], r, `message_terminal[${a}]`);
1136
- }
1137
- let t = 0;
1138
- for (const r of e)
1139
- t += zt + r.message_terminals.length;
1140
- const n = new Uint8Array(t * T);
1141
- let s = 0;
1142
- for (const r of e) {
1143
- n.set(r.checksum_minor_terminal, s), s += T, n.set(r.checksum_major_terminal, s), s += T;
1144
- for (const i of r.message_terminals)
1145
- n.set(i, s), s += T;
1304
+ /**
1305
+ * Gets the configured Bitcoin network.
1306
+ *
1307
+ * @returns The Bitcoin network (mainnet, testnet, signet, regtest)
1308
+ */
1309
+ getNetwork() {
1310
+ return this.config.btcNetwork;
1146
1311
  }
1147
- const o = Je(n);
1148
- return `0x${ln(o)}`;
1149
- }
1150
- async function Vn(e, t, n, s) {
1151
- const o = gn(e);
1152
- try {
1153
- const r = await pn(
1154
- o,
1155
- t,
1156
- n,
1157
- s
1158
- );
1159
- return mn(r);
1160
- } finally {
1161
- o.fill(0);
1312
+ /**
1313
+ * Gets the configured BTCVaultRegistry contract address.
1314
+ *
1315
+ * @returns The Ethereum address of the BTCVaultRegistry contract
1316
+ */
1317
+ getVaultContractAddress() {
1318
+ return this.config.vaultContracts.btcVaultRegistry;
1162
1319
  }
1163
1320
  }
1164
- function Dn(e) {
1165
- const t = (e instanceof Error ? e.message : typeof e == "string" ? e : "").toLowerCase();
1166
- return t.includes("wots") && t.includes("hash") && t.includes("does not match");
1167
- }
1168
- const st = /* @__PURE__ */ Uint8Array.of(0), Ct = /* @__PURE__ */ Uint8Array.of();
1169
- function pt(e, t, n, s = 32) {
1170
- ht(e), C(s, "length");
1171
- const o = e.outputLen;
1172
- if (s > 255 * o)
1173
- throw new Error("Length must be <= 255*HashLen");
1174
- const r = Math.ceil(s / o);
1175
- n === void 0 ? n = Ct : U(n, void 0, "info");
1176
- const i = new Uint8Array(r * o), a = K.create(e, t), h = a._cloneInto(), u = new Uint8Array(a.outputLen);
1177
- for (let c = 0; c < r; c++)
1178
- st[0] = c + 1, h.update(c === 0 ? Ct : u).update(n).update(st).digestInto(u), i.set(u, o * c), a._cloneInto(h);
1179
- return a.destroy(), h.destroy(), S(u, st), i.slice(0, s);
1180
- }
1181
- const ot = new TextEncoder().encode("babylonvault"), Ht = 255, Ot = 65535, $t = 2, wn = "hashlock", yn = "auth-anchor", bn = "wots-seed";
1182
- function Jt(e) {
1183
- if (!Number.isInteger(e) || e < 0 || e > 4294967295)
1184
- throw new Error(`i2osp4: value must be a u32, got ${e}`);
1185
- const t = new Uint8Array(4);
1186
- return t[0] = e >>> 24 & 255, t[1] = e >>> 16 & 255, t[2] = e >>> 8 & 255, t[3] = e & 255, t;
1187
- }
1188
- function mt(e, t = new Uint8Array(0)) {
1189
- const n = new TextEncoder().encode(e);
1190
- if (n.length === 0 || n.length > Ht)
1191
- throw new Error(
1192
- `info: label length must be in [1, ${Ht}], got ${n.length}`
1193
- );
1194
- if (t.length > Ot)
1195
- throw new Error(
1196
- `info: ctx length must be in [0, ${Ot}], got ${t.length}`
1197
- );
1198
- const s = ot.length + 1 + n.length + $t + t.length, o = new Uint8Array(s);
1199
- let r = 0;
1200
- return o.set(ot, r), r += ot.length, o[r] = n.length, r += 1, o.set(n, r), r += n.length, o[r] = t.length >>> 8 & 255, o[r + 1] = t.length & 255, r += $t, o.set(t, r), o;
1201
- }
1202
- const Lt = 32, xn = 32, Pn = 32, kn = 64;
1203
- function wt(e) {
1204
- if (e.length !== Lt)
1205
- throw new Error(
1206
- `vault-secrets: root must be exactly ${Lt} bytes, got ${e.length}`
1207
- );
1208
- }
1209
- function Kn(e) {
1210
- return wt(e), pt(
1211
- W,
1212
- e,
1213
- mt(yn),
1214
- xn
1215
- );
1216
- }
1217
- function Xn(e, t) {
1218
- return wt(e), pt(
1219
- W,
1220
- e,
1221
- mt(wn, Jt(t)),
1222
- Pn
1223
- );
1224
- }
1225
- function jn(e, t) {
1226
- return wt(e), pt(
1227
- W,
1228
- e,
1229
- mt(bn, Jt(t)),
1230
- kn
1231
- );
1232
- }
1233
- const R = 32, rt = 32, lt = 36, Qt = 32, D = 4, En = D + R + D + Qt;
1234
- function ut(e, t, n) {
1235
- e[t] = n >>> 24 & 255, e[t + 1] = n >>> 16 & 255, e[t + 2] = n >>> 8 & 255, e[t + 3] = n & 255;
1236
- }
1237
- function Tn(e) {
1238
- if (e.txid.length !== rt)
1239
- throw new Error(
1240
- `outpoint.txid must be exactly ${rt} bytes, got ${e.txid.length}`
1241
- );
1242
- if (!Number.isInteger(e.vout) || e.vout < 0 || e.vout > 4294967295)
1243
- throw new Error(`outpoint.vout must be a u32, got ${e.vout}`);
1244
- const t = new Uint8Array(lt);
1245
- return t.set(e.txid, 0), ut(t, rt, e.vout), t;
1246
- }
1247
- function Rt(e, t) {
1248
- const n = Math.min(e.length, t.length);
1249
- for (let s = 0; s < n; s++)
1250
- if (e[s] !== t[s]) return e[s] - t[s];
1251
- return e.length - t.length;
1252
- }
1253
- function In(e) {
1254
- if (e.length === 0)
1255
- throw new Error(
1256
- "buildFundingOutpointsCommitment: outpoints must be non-empty"
1257
- );
1258
- const t = e.map(Tn);
1259
- t.sort(Rt);
1260
- for (let s = 1; s < t.length; s++)
1261
- if (Rt(t[s - 1], t[s]) === 0)
1262
- throw new Error(
1263
- "buildFundingOutpointsCommitment: duplicate outpoint detected"
1264
- );
1265
- const n = new Uint8Array(t.length * lt);
1266
- for (let s = 0; s < t.length; s++)
1267
- n.set(t[s], s * lt);
1268
- return W(n);
1269
- }
1270
- function qn(e) {
1271
- if (e.depositorBtcPubkey.length !== R)
1272
- throw new Error(
1273
- `vaultContext: depositorBtcPubkey must be exactly ${R} bytes, got ${e.depositorBtcPubkey.length}`
1274
- );
1275
- const t = In(e.fundingOutpoints), n = new Uint8Array(En);
1276
- let s = 0;
1277
- return ut(n, s, R), s += D, n.set(e.depositorBtcPubkey, s), s += R, ut(n, s, Qt), s += D, n.set(t, s), n;
1278
- }
1279
1321
  export {
1280
- H as C,
1281
- Nn as P,
1282
- Vn as a,
1283
- Dn as b,
1284
- mn as c,
1285
- pn as d,
1286
- dt as e,
1287
- Kn as f,
1288
- Fn as g,
1289
- A as h,
1290
- Mn as i,
1291
- Xn as j,
1292
- jn as k,
1293
- In as l,
1294
- gn as m,
1295
- qn as n
1322
+ S as C,
1323
+ Mn as P,
1324
+ We as V,
1325
+ Nn as a,
1326
+ Wn as b,
1327
+ gn as c,
1328
+ fn as d,
1329
+ at as e,
1330
+ Oe as f,
1331
+ Ln as g,
1332
+ H as h,
1333
+ Vn as i,
1334
+ $e as j,
1335
+ Le as k,
1336
+ Ve as l,
1337
+ Me as m
1296
1338
  };
1297
- //# sourceMappingURL=context-ktqanzXE.js.map
1339
+ //# sourceMappingURL=PeginManager-DzMSIQ0I.js.map