@babylonlabs-io/ts-sdk 0.28.0 → 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 (53) hide show
  1. package/dist/PeginManager-Da4uSHzl.cjs +2 -0
  2. package/dist/PeginManager-Da4uSHzl.cjs.map +1 -0
  3. package/dist/{deriveVaultRoot-DAMZDqg-.js → PeginManager-DzMSIQ0I.js} +1131 -1043
  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-Cc4-L7gX.js → buildAndBroadcastRefund-xWS8frc6.js} +318 -329
  8. package/dist/buildAndBroadcastRefund-xWS8frc6.js.map +1 -0
  9. package/dist/index.cjs +1 -1
  10. package/dist/index.js +4 -4
  11. package/dist/{sha2-CPdTLk1u.js → sha2-6wN58S6R.js} +9 -9
  12. package/dist/{sha2-CPdTLk1u.js.map → sha2-6wN58S6R.js.map} +1 -1
  13. package/dist/tbv/core/clients/eth/vault-registry-reader.d.ts.map +1 -1
  14. package/dist/tbv/core/clients/index.cjs +1 -1
  15. package/dist/tbv/core/clients/index.js +2 -2
  16. package/dist/tbv/core/contracts/abis/BTCVaultRegistry.abi.d.ts +80 -70
  17. package/dist/tbv/core/contracts/abis/BTCVaultRegistry.abi.d.ts.map +1 -1
  18. package/dist/tbv/core/index.cjs +1 -1
  19. package/dist/tbv/core/index.js +4 -4
  20. package/dist/tbv/core/managers/PeginManager.d.ts +64 -27
  21. package/dist/tbv/core/managers/PeginManager.d.ts.map +1 -1
  22. package/dist/tbv/core/managers/index.d.ts +1 -1
  23. package/dist/tbv/core/managers/index.d.ts.map +1 -1
  24. package/dist/tbv/core/services/deposit/validation.d.ts +0 -4
  25. package/dist/tbv/core/services/deposit/validation.d.ts.map +1 -1
  26. package/dist/tbv/core/services/index.cjs +1 -1
  27. package/dist/tbv/core/services/index.js +1 -1
  28. package/dist/tbv/index.cjs +1 -1
  29. package/dist/tbv/index.js +4 -4
  30. package/dist/testing/MockBitcoinWallet.d.ts +1 -0
  31. package/dist/testing/MockBitcoinWallet.d.ts.map +1 -1
  32. package/dist/testing/index.cjs +1 -1
  33. package/dist/testing/index.cjs.map +1 -1
  34. package/dist/testing/index.js +35 -34
  35. package/dist/testing/index.js.map +1 -1
  36. package/dist/{types-CQ86O7NX.js → types-CnG3JsRs.js} +111 -81
  37. package/dist/types-CnG3JsRs.js.map +1 -0
  38. package/dist/types-jmEyzzhY.cjs +2 -0
  39. package/dist/types-jmEyzzhY.cjs.map +1 -0
  40. package/dist/{vault-registry-reader-CshEgmS0.js → vault-registry-reader-BywZhqJL.js} +37 -37
  41. package/dist/{vault-registry-reader-CshEgmS0.js.map → vault-registry-reader-BywZhqJL.js.map} +1 -1
  42. package/dist/{vault-registry-reader-_2BjSjoN.cjs → vault-registry-reader-DdruADqa.cjs} +2 -2
  43. package/dist/{vault-registry-reader-_2BjSjoN.cjs.map → vault-registry-reader-DdruADqa.cjs.map} +1 -1
  44. package/package.json +1 -1
  45. package/dist/buildAndBroadcastRefund-Cc4-L7gX.js.map +0 -1
  46. package/dist/buildAndBroadcastRefund-OoaQaNqn.cjs +0 -2
  47. package/dist/buildAndBroadcastRefund-OoaQaNqn.cjs.map +0 -1
  48. package/dist/deriveVaultRoot-B4gnRbW_.cjs +0 -2
  49. package/dist/deriveVaultRoot-B4gnRbW_.cjs.map +0 -1
  50. package/dist/deriveVaultRoot-DAMZDqg-.js.map +0 -1
  51. package/dist/types-CQ86O7NX.js.map +0 -1
  52. package/dist/types-CcwaEPE1.cjs +0 -2
  53. package/dist/types-CcwaEPE1.cjs.map +0 -1
@@ -1,183 +1,16 @@
1
1
  var W = Object.defineProperty;
2
2
  var X = (e, t, r) => t in e ? W(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r;
3
- var P = (e, t, r) => X(e, typeof t != "symbol" ? t + "" : t, r);
4
- import { B as G, c as Y, a as j, R as q, d as N, D as b } from "./types-CQ86O7NX.js";
5
- import { v as A, b as Q, s as l, e as J, p as w, f } from "./bitcoin-B-Y0DlqR.js";
6
- import { s as Z } from "./sha2-CPdTLk1u.js";
3
+ var y = (e, t, r) => X(e, typeof t != "symbol" ? t + "" : t, r);
4
+ import { B as G, c as Y, a as j, R as q, d as N, D as g } from "./types-CnG3JsRs.js";
5
+ import { e as Q, s as l, v as A, b as J, p as P, f } from "./bitcoin-B-Y0DlqR.js";
6
+ import { s as Z } from "./sha2-6wN58S6R.js";
7
7
  import * as ee from "bitcoinjs-lib";
8
- import { Transaction as te, Psbt as B } from "bitcoinjs-lib";
8
+ import { Psbt as B, Transaction as te } from "bitcoinjs-lib";
9
9
  import { Buffer as V } from "buffer";
10
- import { c as y } from "./signing-BZigafm0.js";
10
+ import { c as b } from "./signing-BZigafm0.js";
11
11
  import "@babylonlabs-io/babylon-tbv-rust-wasm";
12
- import { a as H, e as x, b as re } from "./payout-B_fvQU3q.js";
13
- class oe {
14
- /**
15
- * Creates a new PayoutManager instance.
16
- *
17
- * @param config - Manager configuration including wallet
18
- */
19
- constructor(t) {
20
- P(this, "config");
21
- this.config = t;
22
- }
23
- /**
24
- * Signs a Payout transaction and extracts the Schnorr signature.
25
- *
26
- * Flow:
27
- * 1. Vault provider submits Claim transaction
28
- * 2. Claimer submits Assert transaction to prove validity
29
- * 3. Payout can be executed (references Assert tx)
30
- *
31
- * This method orchestrates the following steps:
32
- * 1. Get wallet's public key and convert to x-only format
33
- * 2. Validate wallet pubkey matches on-chain depositor pubkey (if provided)
34
- * 3. Build unsigned PSBT using primitives
35
- * 4. Sign PSBT via btcWallet.signPsbt()
36
- * 5. Extract 64-byte Schnorr signature using primitives
37
- *
38
- * The returned signature can be submitted to the vault provider API.
39
- *
40
- * @param params - Payout signing parameters
41
- * @returns Signature result with 64-byte Schnorr signature and depositor pubkey
42
- * @throws Error if wallet pubkey doesn't match depositor pubkey
43
- * @throws Error if wallet operations fail or signature extraction fails
44
- */
45
- async signPayoutTransaction(t) {
46
- this.validatePayoutOutputs(
47
- t.payoutTxHex,
48
- t.registeredPayoutScriptPubKey
49
- );
50
- const r = await this.config.btcWallet.getPublicKeyHex(), { depositorPubkey: o } = A(
51
- r,
52
- t.depositorBtcPubkey
53
- ), s = await H({
54
- payoutTxHex: t.payoutTxHex,
55
- peginTxHex: t.peginTxHex,
56
- assertTxHex: t.assertTxHex,
57
- depositorBtcPubkey: o,
58
- vaultProviderBtcPubkey: t.vaultProviderBtcPubkey,
59
- vaultKeeperBtcPubkeys: t.vaultKeeperBtcPubkeys,
60
- universalChallengerBtcPubkeys: t.universalChallengerBtcPubkeys,
61
- timelockPegin: t.timelockPegin,
62
- network: this.config.network
63
- }), c = await this.config.btcWallet.signPsbt(
64
- s.psbtHex,
65
- y(r, 1)
66
- );
67
- return {
68
- signature: x(c, o),
69
- depositorBtcPubkey: o
70
- };
71
- }
72
- /**
73
- * Gets the configured Bitcoin network.
74
- *
75
- * @returns The Bitcoin network (mainnet, testnet, signet, regtest)
76
- */
77
- getNetwork() {
78
- return this.config.network;
79
- }
80
- /**
81
- * Checks if the wallet supports batch signing (signPsbts).
82
- *
83
- * @returns true if batch signing is supported
84
- */
85
- supportsBatchSigning() {
86
- return typeof this.config.btcWallet.signPsbts == "function";
87
- }
88
- /**
89
- * Batch signs multiple payout transactions (1 per claimer).
90
- * This allows signing all transactions with a single wallet interaction.
91
- *
92
- * @param transactions - Array of payout params to sign
93
- * @returns Array of signature results matching input order
94
- * @throws Error if wallet doesn't support batch signing
95
- * @throws Error if any signing operation fails
96
- */
97
- async signPayoutTransactionsBatch(t) {
98
- if (!this.supportsBatchSigning())
99
- throw new Error(
100
- "Wallet does not support batch signing (signPsbts method not available)"
101
- );
102
- const r = await this.config.btcWallet.getPublicKeyHex(), o = [], s = [], c = [];
103
- for (const n of t) {
104
- this.validatePayoutOutputs(
105
- n.payoutTxHex,
106
- n.registeredPayoutScriptPubKey
107
- );
108
- const { depositorPubkey: u } = A(
109
- r,
110
- n.depositorBtcPubkey
111
- );
112
- c.push(u);
113
- const d = await H({
114
- payoutTxHex: n.payoutTxHex,
115
- peginTxHex: n.peginTxHex,
116
- assertTxHex: n.assertTxHex,
117
- depositorBtcPubkey: u,
118
- vaultProviderBtcPubkey: n.vaultProviderBtcPubkey,
119
- vaultKeeperBtcPubkeys: n.vaultKeeperBtcPubkeys,
120
- universalChallengerBtcPubkeys: n.universalChallengerBtcPubkeys,
121
- timelockPegin: n.timelockPegin,
122
- network: this.config.network
123
- });
124
- o.push(d.psbtHex), s.push(y(r, 1));
125
- }
126
- const a = await this.config.btcWallet.signPsbts(
127
- o,
128
- s
129
- );
130
- if (a.length !== t.length)
131
- throw new Error(
132
- `Expected ${t.length} signed PSBTs but received ${a.length}`
133
- );
134
- const i = [];
135
- for (let n = 0; n < t.length; n++) {
136
- const u = c[n], d = x(
137
- a[n],
138
- u
139
- );
140
- i.push({
141
- payoutSignature: d,
142
- depositorBtcPubkey: u
143
- });
144
- }
145
- return i;
146
- }
147
- /**
148
- * Validates that the payout transaction's largest output pays to the
149
- * registered depositor payout address (scriptPubKey).
150
- *
151
- * This prevents two attack vectors from a malicious vault provider:
152
- * 1. Substituting a completely different payout address
153
- * 2. Including a dust output to the correct address while routing
154
- * the actual funds to an attacker-controlled address
155
- *
156
- * @param payoutTxHex - Raw payout transaction hex
157
- * @param registeredPayoutScriptPubKey - On-chain registered scriptPubKey (hex, with or without 0x prefix)
158
- * @throws Error if scriptPubKey is invalid hex
159
- * @throws Error if the largest output does not pay to the registered address
160
- */
161
- validatePayoutOutputs(t, r) {
162
- if (!Q(r))
163
- throw new Error(
164
- "Invalid registeredPayoutScriptPubKey: not valid hex"
165
- );
166
- const o = V.from(
167
- l(r),
168
- "hex"
169
- ), s = te.fromHex(l(t));
170
- if (s.outs.length === 0)
171
- throw new Error("Payout transaction has no outputs");
172
- if (!s.outs.reduce(
173
- (a, i) => i.value > a.value ? i : a
174
- ).script.equals(o))
175
- throw new Error(
176
- "Payout transaction does not pay to the registered depositor payout address"
177
- );
178
- }
179
- }
180
- const I = 66;
12
+ import { e as w, a as I, b as re } from "./payout-B_fvQU3q.js";
13
+ const H = 66;
181
14
  function L(e) {
182
15
  if (!e.startsWith("0x") && !e.startsWith("0X"))
183
16
  throw new Error("Expected 0x-prefixed hex string");
@@ -191,42 +24,42 @@ function L(e) {
191
24
  r[o] = parseInt(t.slice(o * 2, o * 2 + 2), 16);
192
25
  return r;
193
26
  }
194
- function ne(e) {
27
+ function oe(e) {
195
28
  return `0x${Array.from(e).map((t) => t.toString(16).padStart(2, "0")).join("")}`;
196
29
  }
197
30
  function S(e, t) {
198
- if (e.length !== I)
31
+ if (e.length !== H)
199
32
  throw new Error(
200
- `${t} must be exactly 32 bytes (${I} hex chars with 0x prefix), got ${e.length}`
33
+ `${t} must be exactly 32 bytes (${H} hex chars with 0x prefix), got ${e.length}`
201
34
  );
202
35
  }
203
- function se(e) {
36
+ function ne(e) {
204
37
  S(e, "Secret");
205
38
  const t = L(e), r = Z(t);
206
- return ne(r);
39
+ return oe(r);
207
40
  }
208
41
  function ie(e, t) {
209
- return S(e, "Secret"), S(t, "Hashlock"), L(t), se(e).toLowerCase() === t.toLowerCase();
42
+ return S(e, "Secret"), S(t, "Hashlock"), L(t), ne(e).toLowerCase() === t.toLowerCase();
210
43
  }
211
- const ae = /^0x[0-9a-fA-F]{64}$/, ue = /^0x[0-9a-fA-F]{40}$/, ce = /^0x([0-9a-fA-F]{2})*$/;
44
+ const se = /^0x[0-9a-fA-F]{64}$/, ae = /^0x[0-9a-fA-F]{40}$/, ue = /^0x([0-9a-fA-F]{2})*$/;
212
45
  function E(e, t) {
213
46
  if (e.length !== 66)
214
47
  throw new Error(
215
48
  `${t} must be 32 bytes (66 hex chars with 0x prefix), got length ${e.length}`
216
49
  );
217
- if (!ae.test(e))
50
+ if (!se.test(e))
218
51
  throw new Error(
219
52
  `${t} must contain only hex characters after the 0x prefix`
220
53
  );
221
54
  }
222
- function le(e, t) {
223
- if (!ue.test(e))
55
+ function ce(e, t) {
56
+ if (!ae.test(e))
224
57
  throw new Error(
225
58
  `${t} must be a 20-byte 0x-prefixed hex address (42 chars)`
226
59
  );
227
60
  }
228
- function de(e, t) {
229
- if (!ce.test(e))
61
+ function le(e, t) {
62
+ if (!ue.test(e))
230
63
  throw new Error(
231
64
  `${t} must be a 0x-prefixed hex string with an even number of hex chars`
232
65
  );
@@ -236,41 +69,41 @@ async function Je(e) {
236
69
  btcVaultRegistryAddress: t,
237
70
  vaultId: r,
238
71
  hashlock: o,
239
- activationMetadata: s,
72
+ activationMetadata: i,
240
73
  writeContract: c,
241
74
  signal: a
242
75
  } = e;
243
- a == null || a.throwIfAborted(), le(t, "btcVaultRegistryAddress"), E(r, "vaultId");
244
- const i = J(e.secret);
245
- if (E(i, "secret"), o !== void 0 && (E(o, "hashlock"), !ie(i, o)))
76
+ a == null || a.throwIfAborted(), ce(t, "btcVaultRegistryAddress"), E(r, "vaultId");
77
+ const s = Q(e.secret);
78
+ if (E(s, "secret"), o !== void 0 && (E(o, "hashlock"), !ie(s, o)))
246
79
  throw new Error(
247
80
  "Invalid secret: SHA256(secret) does not match the provided hashlock"
248
81
  );
249
- return de(s, "activationMetadata"), c({
82
+ return le(i, "activationMetadata"), c({
250
83
  address: t,
251
84
  abi: G,
252
85
  functionName: "activateVaultWithSecret",
253
- args: [r, i, s]
86
+ args: [r, s, i]
254
87
  });
255
88
  }
256
- const he = 1e4;
89
+ const de = 1e4;
257
90
  async function D(e) {
258
91
  const {
259
92
  statusReader: t,
260
93
  peginTxid: r,
261
94
  targetStatuses: o,
262
- timeoutMs: s,
263
- pollIntervalMs: c = he,
95
+ timeoutMs: i,
96
+ pollIntervalMs: c = de,
264
97
  signal: a
265
- } = e, i = Date.now();
98
+ } = e, s = Date.now();
266
99
  for (; ; ) {
267
100
  if (a != null && a.aborted)
268
101
  throw new Error(
269
102
  `Polling aborted for pegin ${r.slice(0, 8)}… (target: ${[...o].join(", ")})`
270
103
  );
271
- if (Date.now() - i >= s)
104
+ if (Date.now() - s >= i)
272
105
  throw new Error(
273
- `Polling timeout after ${s}ms for pegin ${r.slice(0, 8)}… (target: ${[...o].join(", ")})`
106
+ `Polling timeout after ${i}ms for pegin ${r.slice(0, 8)}… (target: ${[...o].join(", ")})`
274
107
  );
275
108
  try {
276
109
  const u = (await t.getPeginStatus(
@@ -302,7 +135,7 @@ async function D(e) {
302
135
  }
303
136
  }
304
137
  const pe = 300 * 1e3, fe = /* @__PURE__ */ new Set([
305
- b.PENDING_DEPOSITOR_WOTS_PK,
138
+ g.PENDING_DEPOSITOR_WOTS_PK,
306
139
  ...N
307
140
  ]);
308
141
  async function Ze(e) {
@@ -310,81 +143,81 @@ async function Ze(e) {
310
143
  statusReader: t,
311
144
  wotsSubmitter: r,
312
145
  peginTxid: o,
313
- depositorPk: s,
146
+ depositorPk: i,
314
147
  wotsPublicKeys: c,
315
148
  timeoutMs: a = pe,
316
- signal: i
149
+ signal: s
317
150
  } = e;
318
- i == null || i.throwIfAborted();
151
+ s == null || s.throwIfAborted();
319
152
  const n = await D({
320
153
  statusReader: t,
321
154
  peginTxid: o,
322
155
  targetStatuses: fe,
323
156
  timeoutMs: a,
324
- signal: i
157
+ signal: s
325
158
  });
326
- N.has(n) || (i == null || i.throwIfAborted(), await r.submitDepositorWotsKey(
159
+ N.has(n) || (s == null || s.throwIfAborted(), await r.submitDepositorWotsKey(
327
160
  {
328
161
  pegin_txid: o,
329
- depositor_pk: s,
162
+ depositor_pk: i,
330
163
  wots_public_keys: c
331
164
  },
332
- i
165
+ s
333
166
  ));
334
167
  }
335
- const $ = 1;
336
- function ge(e, t, r) {
337
- const o = B.fromBase64(e), s = o.data.getTransaction().toString("hex").toLowerCase(), c = l(t).toLowerCase();
338
- if (s !== c)
168
+ const R = 1;
169
+ function he(e, t, r) {
170
+ const o = B.fromBase64(e), i = o.data.getTransaction().toString("hex").toLowerCase(), c = l(t).toLowerCase();
171
+ if (i !== c)
339
172
  throw new Error(
340
173
  `PSBT integrity check failed for ${r}: unsigned transaction does not match tx_hex`
341
174
  );
342
175
  return o;
343
176
  }
344
- function be(e) {
177
+ function ge(e) {
345
178
  const t = B.fromHex(e.toHex());
346
179
  for (const r of t.data.inputs)
347
180
  delete r.tapBip32Derivation, delete r.tapMerkleRoot;
348
181
  return t;
349
182
  }
350
- function R(e, t, r) {
183
+ function $(e, t, r) {
351
184
  if (!e)
352
185
  throw new Error(`Missing ${r} PSBT`);
353
- const o = ge(e, t, r);
354
- return be(o).toHex();
186
+ const o = he(e, t, r);
187
+ return ge(o).toHex();
355
188
  }
356
- function ye(e, t) {
357
- const r = [], o = [], s = [], c = R(
189
+ function be(e, t) {
190
+ const r = [], o = [], i = [], c = $(
358
191
  e.payout_psbt,
359
192
  e.payout_tx.tx_hex,
360
193
  "depositor payout"
361
194
  );
362
195
  r.push(c), o.push(
363
- y(t, $)
196
+ b(t, R)
364
197
  );
365
198
  for (const a of e.challenger_presign_data) {
366
- const i = l(a.challenger_pubkey), n = r.length, u = R(
199
+ const s = l(a.challenger_pubkey), n = r.length, u = $(
367
200
  a.nopayout_psbt,
368
201
  a.nopayout_tx.tx_hex,
369
- `nopayout (challenger ${i})`
202
+ `nopayout (challenger ${s})`
370
203
  );
371
204
  r.push(u), o.push(
372
- y(t, $)
373
- ), s.push({
374
- challengerPubkey: i,
205
+ b(t, R)
206
+ ), i.push({
207
+ challengerPubkey: s,
375
208
  noPayoutIdx: n
376
209
  });
377
210
  }
378
- return { psbtHexes: r, signOptions: o, challengerEntries: s };
211
+ return { psbtHexes: r, signOptions: o, challengerEntries: i };
379
212
  }
380
- function Pe(e, t, r) {
381
- const o = x(
213
+ function ye(e, t, r) {
214
+ const o = w(
382
215
  e[0],
383
216
  r
384
- ), s = {};
217
+ ), i = {};
385
218
  for (const c of t)
386
- s[c.challengerPubkey] = {
387
- nopayout_signature: x(
219
+ i[c.challengerPubkey] = {
220
+ nopayout_signature: w(
388
221
  e[c.noPayoutIdx],
389
222
  r
390
223
  )
@@ -393,44 +226,211 @@ function Pe(e, t, r) {
393
226
  payout_signatures: {
394
227
  payout_signature: o
395
228
  },
396
- per_challenger: s
229
+ per_challenger: i
397
230
  };
398
231
  }
399
- async function we(e, t, r) {
232
+ async function Pe(e, t, r) {
400
233
  if (typeof e.signPsbts == "function")
401
234
  return e.signPsbts(t, r);
402
235
  const o = [];
403
- for (let s = 0; s < t.length; s++)
404
- o.push(await e.signPsbt(t[s], r == null ? void 0 : r[s]));
236
+ for (let i = 0; i < t.length; i++)
237
+ o.push(await e.signPsbt(t[i], r == null ? void 0 : r[i]));
405
238
  return o;
406
239
  }
407
- async function xe(e) {
408
- const { depositorGraph: t, depositorBtcPubkey: r, btcWallet: o } = e, s = l(r), c = await o.getPublicKeyHex(), { psbtHexes: a, signOptions: i, challengerEntries: n } = ye(t, c), u = await we(
240
+ async function we(e) {
241
+ const { depositorGraph: t, depositorBtcPubkey: r, btcWallet: o } = e, i = l(r), c = await o.getPublicKeyHex(), { psbtHexes: a, signOptions: s, challengerEntries: n } = be(t, c), u = await Pe(
409
242
  o,
410
243
  a,
411
- i
244
+ s
412
245
  );
413
246
  if (u.length !== a.length)
414
247
  throw new Error(
415
248
  `Wallet returned ${u.length} signed PSBTs, expected ${a.length}`
416
249
  );
417
- return Pe(
250
+ return ye(
418
251
  u,
419
252
  n,
420
- s
253
+ i
421
254
  );
422
255
  }
256
+ class xe {
257
+ /**
258
+ * Creates a new PayoutManager instance.
259
+ *
260
+ * @param config - Manager configuration including wallet
261
+ */
262
+ constructor(t) {
263
+ y(this, "config");
264
+ this.config = t;
265
+ }
266
+ /**
267
+ * Signs a Payout transaction and extracts the Schnorr signature.
268
+ *
269
+ * Flow:
270
+ * 1. Vault provider submits Claim transaction
271
+ * 2. Claimer submits Assert transaction to prove validity
272
+ * 3. Payout can be executed (references Assert tx)
273
+ *
274
+ * This method orchestrates the following steps:
275
+ * 1. Get wallet's public key and convert to x-only format
276
+ * 2. Validate wallet pubkey matches on-chain depositor pubkey (if provided)
277
+ * 3. Build unsigned PSBT using primitives
278
+ * 4. Sign PSBT via btcWallet.signPsbt()
279
+ * 5. Extract 64-byte Schnorr signature using primitives
280
+ *
281
+ * The returned signature can be submitted to the vault provider API.
282
+ *
283
+ * @param params - Payout signing parameters
284
+ * @returns Signature result with 64-byte Schnorr signature and depositor pubkey
285
+ * @throws Error if wallet pubkey doesn't match depositor pubkey
286
+ * @throws Error if wallet operations fail or signature extraction fails
287
+ */
288
+ async signPayoutTransaction(t) {
289
+ this.validatePayoutOutputs(
290
+ t.payoutTxHex,
291
+ t.registeredPayoutScriptPubKey
292
+ );
293
+ const r = await this.config.btcWallet.getPublicKeyHex(), { depositorPubkey: o } = A(
294
+ r,
295
+ t.depositorBtcPubkey
296
+ ), i = await I({
297
+ payoutTxHex: t.payoutTxHex,
298
+ peginTxHex: t.peginTxHex,
299
+ assertTxHex: t.assertTxHex,
300
+ depositorBtcPubkey: o,
301
+ vaultProviderBtcPubkey: t.vaultProviderBtcPubkey,
302
+ vaultKeeperBtcPubkeys: t.vaultKeeperBtcPubkeys,
303
+ universalChallengerBtcPubkeys: t.universalChallengerBtcPubkeys,
304
+ timelockPegin: t.timelockPegin,
305
+ network: this.config.network
306
+ }), c = await this.config.btcWallet.signPsbt(
307
+ i.psbtHex,
308
+ b(r, 1)
309
+ );
310
+ return {
311
+ signature: w(c, o),
312
+ depositorBtcPubkey: o
313
+ };
314
+ }
315
+ /**
316
+ * Gets the configured Bitcoin network.
317
+ *
318
+ * @returns The Bitcoin network (mainnet, testnet, signet, regtest)
319
+ */
320
+ getNetwork() {
321
+ return this.config.network;
322
+ }
323
+ /**
324
+ * Checks if the wallet supports batch signing (signPsbts).
325
+ *
326
+ * @returns true if batch signing is supported
327
+ */
328
+ supportsBatchSigning() {
329
+ return typeof this.config.btcWallet.signPsbts == "function";
330
+ }
331
+ /**
332
+ * Batch signs multiple payout transactions (1 per claimer).
333
+ * This allows signing all transactions with a single wallet interaction.
334
+ *
335
+ * @param transactions - Array of payout params to sign
336
+ * @returns Array of signature results matching input order
337
+ * @throws Error if wallet doesn't support batch signing
338
+ * @throws Error if any signing operation fails
339
+ */
340
+ async signPayoutTransactionsBatch(t) {
341
+ if (!this.supportsBatchSigning())
342
+ throw new Error(
343
+ "Wallet does not support batch signing (signPsbts method not available)"
344
+ );
345
+ const r = await this.config.btcWallet.getPublicKeyHex(), o = [], i = [], c = [];
346
+ for (const n of t) {
347
+ this.validatePayoutOutputs(
348
+ n.payoutTxHex,
349
+ n.registeredPayoutScriptPubKey
350
+ );
351
+ const { depositorPubkey: u } = A(
352
+ r,
353
+ n.depositorBtcPubkey
354
+ );
355
+ c.push(u);
356
+ const d = await I({
357
+ payoutTxHex: n.payoutTxHex,
358
+ peginTxHex: n.peginTxHex,
359
+ assertTxHex: n.assertTxHex,
360
+ depositorBtcPubkey: u,
361
+ vaultProviderBtcPubkey: n.vaultProviderBtcPubkey,
362
+ vaultKeeperBtcPubkeys: n.vaultKeeperBtcPubkeys,
363
+ universalChallengerBtcPubkeys: n.universalChallengerBtcPubkeys,
364
+ timelockPegin: n.timelockPegin,
365
+ network: this.config.network
366
+ });
367
+ o.push(d.psbtHex), i.push(b(r, 1));
368
+ }
369
+ const a = await this.config.btcWallet.signPsbts(
370
+ o,
371
+ i
372
+ );
373
+ if (a.length !== t.length)
374
+ throw new Error(
375
+ `Expected ${t.length} signed PSBTs but received ${a.length}`
376
+ );
377
+ const s = [];
378
+ for (let n = 0; n < t.length; n++) {
379
+ const u = c[n], d = w(
380
+ a[n],
381
+ u
382
+ );
383
+ s.push({
384
+ payoutSignature: d,
385
+ depositorBtcPubkey: u
386
+ });
387
+ }
388
+ return s;
389
+ }
390
+ /**
391
+ * Validates that the payout transaction's largest output pays to the
392
+ * registered depositor payout address (scriptPubKey).
393
+ *
394
+ * This prevents two attack vectors from a malicious vault provider:
395
+ * 1. Substituting a completely different payout address
396
+ * 2. Including a dust output to the correct address while routing
397
+ * the actual funds to an attacker-controlled address
398
+ *
399
+ * @param payoutTxHex - Raw payout transaction hex
400
+ * @param registeredPayoutScriptPubKey - On-chain registered scriptPubKey (hex, with or without 0x prefix)
401
+ * @throws Error if scriptPubKey is invalid hex
402
+ * @throws Error if the largest output does not pay to the registered address
403
+ */
404
+ validatePayoutOutputs(t, r) {
405
+ if (!J(r))
406
+ throw new Error(
407
+ "Invalid registeredPayoutScriptPubKey: not valid hex"
408
+ );
409
+ const o = V.from(
410
+ l(r),
411
+ "hex"
412
+ ), i = te.fromHex(l(t));
413
+ if (i.outs.length === 0)
414
+ throw new Error("Payout transaction has no outputs");
415
+ if (!i.outs.reduce(
416
+ (a, s) => s.value > a.value ? s : a
417
+ ).script.equals(o))
418
+ throw new Error(
419
+ "Payout transaction does not pay to the registered depositor payout address"
420
+ );
421
+ }
422
+ }
423
423
  const me = 1200 * 1e3, K = /* @__PURE__ */ new Set([
424
- b.PENDING_ACKS,
425
- b.PENDING_ACTIVATION,
426
- b.ACTIVATED
427
- ]), ve = /* @__PURE__ */ new Set([
428
- b.PENDING_DEPOSITOR_SIGNATURES,
424
+ g.PENDING_ACKS,
425
+ g.PENDING_ACTIVATION,
426
+ g.ACTIVATED
427
+ ]), Te = /* @__PURE__ */ new Set([
428
+ g.PENDING_DEPOSITOR_SIGNATURES,
429
429
  ...K
430
430
  ]);
431
- function Te(e) {
431
+ function ve(e) {
432
432
  return e.map((t) => ({
433
- claimerPubkeyXOnly: w(t.claimer_pubkey),
433
+ claimerPubkeyXOnly: P(t.claimer_pubkey),
434
434
  payoutTxHex: t.payout_tx.tx_hex,
435
435
  assertTxHex: t.assert_tx.tx_hex
436
436
  }));
@@ -446,13 +446,13 @@ function Ee(e) {
446
446
  function ke(e, t) {
447
447
  const r = l(e).toLowerCase(), o = l(
448
448
  t.vaultProviderBtcPubkey
449
- ).toLowerCase(), s = l(
449
+ ).toLowerCase(), i = l(
450
450
  t.depositorBtcPubkey
451
451
  ).toLowerCase();
452
- if (r === o || r === s)
452
+ if (r === o || r === i)
453
453
  return t.registeredPayoutScriptPubKey;
454
454
  if (!t.vaultKeeperBtcPubkeys.some(
455
- (i) => l(i).toLowerCase() === r
455
+ (s) => l(s).toLowerCase() === r
456
456
  ))
457
457
  throw new Error(
458
458
  `Unknown claimer pubkey ${r}: not VP, depositor, or a registered vault keeper`
@@ -476,49 +476,49 @@ function C(e, t) {
476
476
  };
477
477
  }
478
478
  async function Se(e, t, r, o) {
479
- const s = new oe({
479
+ const i = new xe({
480
480
  network: t.network,
481
481
  btcWallet: e
482
482
  }), c = r.length;
483
483
  o == null || o(0, c);
484
484
  let a;
485
- if (s.supportsBatchSigning())
486
- a = (await s.signPayoutTransactionsBatch(
485
+ if (i.supportsBatchSigning())
486
+ a = (await i.signPayoutTransactionsBatch(
487
487
  r.map((u) => C(u, t))
488
488
  )).map((u) => u.payoutSignature);
489
489
  else {
490
490
  a = [];
491
491
  for (let n = 0; n < r.length; n++) {
492
492
  o == null || o(n, c);
493
- const u = await s.signPayoutTransaction(
493
+ const u = await i.signPayoutTransaction(
494
494
  C(r[n], t)
495
495
  );
496
496
  a.push(u.signature);
497
497
  }
498
498
  }
499
- const i = {};
499
+ const s = {};
500
500
  for (let n = 0; n < r.length; n++)
501
- i[r[n].claimerPubkeyXOnly] = {
501
+ s[r[n].claimerPubkeyXOnly] = {
502
502
  payout_signature: a[n]
503
503
  };
504
- return o == null || o(c, c), i;
504
+ return o == null || o(c, c), s;
505
505
  }
506
506
  async function et(e) {
507
507
  const {
508
508
  statusReader: t,
509
509
  presignClient: r,
510
510
  btcWallet: o,
511
- peginTxid: s,
511
+ peginTxid: i,
512
512
  depositorPk: c,
513
513
  signingContext: a,
514
- timeoutMs: i = me,
514
+ timeoutMs: s = me,
515
515
  signal: n,
516
516
  onProgress: u
517
517
  } = e, d = await D({
518
518
  statusReader: t,
519
- peginTxid: s,
520
- targetStatuses: ve,
521
- timeoutMs: i,
519
+ peginTxid: i,
520
+ targetStatuses: Te,
521
+ timeoutMs: s,
522
522
  signal: n
523
523
  });
524
524
  if (K.has(d))
@@ -526,31 +526,31 @@ async function et(e) {
526
526
  n == null || n.throwIfAborted();
527
527
  const h = await r.requestDepositorPresignTransactions(
528
528
  {
529
- pegin_txid: s,
529
+ pegin_txid: i,
530
530
  depositor_pk: c
531
531
  },
532
532
  n
533
533
  );
534
534
  n == null || n.throwIfAborted();
535
- const g = w(c), m = h.txs.filter(
536
- (z) => w(z.claimer_pubkey) !== g
537
- ), v = Te(m), T = await Se(
535
+ const x = P(c), m = h.txs.filter(
536
+ (z) => P(z.claimer_pubkey) !== x
537
+ ), T = ve(m), v = await Se(
538
538
  o,
539
539
  a,
540
- v,
540
+ T,
541
541
  u
542
542
  );
543
543
  n == null || n.throwIfAborted();
544
- const p = await xe({
544
+ const p = await we({
545
545
  depositorGraph: h.depositor_graph,
546
546
  depositorBtcPubkey: c,
547
547
  btcWallet: o
548
548
  });
549
549
  n == null || n.throwIfAborted();
550
- const _ = { ...T };
550
+ const _ = { ...v };
551
551
  _[l(c)] = p.payout_signatures, await r.submitDepositorPresignatures(
552
552
  {
553
- pegin_txid: s,
553
+ pegin_txid: i,
554
554
  depositor_pk: c,
555
555
  signatures: _,
556
556
  depositor_claimer_presignatures: p
@@ -566,11 +566,11 @@ function tt(e) {
566
566
  amountSats: t,
567
567
  minDeposit: r,
568
568
  maxDeposit: o,
569
- btcBalance: s,
569
+ btcBalance: i,
570
570
  estimatedFeeSats: c,
571
571
  depositorClaimValue: a
572
572
  } = e;
573
- return !(t <= 0n || t < r || o && o > 0n && t > o || c == null || a == null || t + c + a > s);
573
+ return !(t <= 0n || t < r || o && o > 0n && t > o || c == null || a == null || t + c + a > i);
574
574
  }
575
575
  function rt(e, t, r) {
576
576
  return e <= 0n ? {
@@ -601,10 +601,10 @@ function nt(e, t) {
601
601
  error: "At least one vault provider must be selected"
602
602
  };
603
603
  const r = t.map(
604
- (s) => s.toLowerCase()
604
+ (i) => i.toLowerCase()
605
605
  );
606
606
  return e.filter(
607
- (s) => !r.includes(s.toLowerCase())
607
+ (i) => !r.includes(i.toLowerCase())
608
608
  ).length > 0 ? {
609
609
  valid: !1,
610
610
  error: "Invalid vault provider selected"
@@ -617,21 +617,21 @@ function _e(e, t, r) {
617
617
  error: "At least one vault amount required"
618
618
  };
619
619
  for (let o = 0; o < e.length; o++) {
620
- const s = e[o];
621
- if (s <= 0n)
620
+ const i = e[o];
621
+ if (i <= 0n)
622
622
  return {
623
623
  valid: !1,
624
624
  error: `Vault ${o + 1} amount must be positive`
625
625
  };
626
- if (t && s < t)
626
+ if (t && i < t)
627
627
  return {
628
628
  valid: !1,
629
- error: `Vault ${o + 1} amount ${f(s)} BTC is below minimum deposit ${f(t)} BTC`
629
+ error: `Vault ${o + 1} amount ${f(i)} BTC is below minimum deposit ${f(t)} BTC`
630
630
  };
631
- if (r && s > r)
631
+ if (r && i > r)
632
632
  return {
633
633
  valid: !1,
634
- error: `Vault ${o + 1} amount ${f(s)} BTC exceeds maximum deposit ${f(r)} BTC`
634
+ error: `Vault ${o + 1} amount ${f(i)} BTC exceeds maximum deposit ${f(r)} BTC`
635
635
  };
636
636
  }
637
637
  return { valid: !0 };
@@ -643,73 +643,62 @@ function Ae(e) {
643
643
  error: "Invalid pubkey format: must be 64 hex characters (32-byte x-only public key, no 0x prefix)"
644
644
  };
645
645
  }
646
- function He(e) {
646
+ function Ie(e) {
647
647
  if (!e || e.length === 0)
648
648
  throw new Error(
649
649
  "No vault keepers available. The system requires at least one vault keeper to create a deposit."
650
650
  );
651
651
  }
652
- function Ie(e) {
652
+ function He(e) {
653
653
  if (!e || e.length === 0)
654
654
  throw new Error(
655
655
  "No universal challengers available. The system requires at least one universal challenger to create a deposit."
656
656
  );
657
657
  }
658
- function $e(e) {
658
+ function Re(e) {
659
659
  if (e.length === 0)
660
660
  throw new Error("No spendable UTXOs available");
661
661
  }
662
- function st(e) {
662
+ function it(e) {
663
663
  const {
664
664
  vaultAmounts: t,
665
665
  confirmedUTXOs: r,
666
666
  vaultProviderBtcPubkey: o,
667
- vaultKeeperBtcPubkeys: s,
667
+ vaultKeeperBtcPubkeys: i,
668
668
  universalChallengerBtcPubkeys: c,
669
669
  minDeposit: a,
670
- maxDeposit: i,
671
- htlcSecretHexesLength: n,
672
- depositorSecretHashesLength: u
673
- } = e, d = t.length;
674
- if (n !== d)
675
- throw new Error(
676
- `htlcSecretHexes length (${n}) must match vaultAmounts length (${d})`
677
- );
678
- if (u !== d)
679
- throw new Error(
680
- `depositorSecretHashes length (${u}) must match vaultAmounts length (${d})`
681
- );
682
- const h = _e(
670
+ maxDeposit: s
671
+ } = e, n = _e(
683
672
  t,
684
673
  a,
685
- i
674
+ s
686
675
  );
687
- if (!h.valid)
688
- throw new Error(h.error);
689
- const g = Ae(o);
690
- if (!g.valid)
691
- throw new Error(g.error);
692
- He(s), Ie(c), $e(r);
676
+ if (!n.valid)
677
+ throw new Error(n.error);
678
+ const u = Ae(o);
679
+ if (!u.valid)
680
+ throw new Error(u.error);
681
+ Ie(i), He(c), Re(r);
693
682
  }
694
683
  var U = /* @__PURE__ */ ((e) => (e.CLAIM_EVENT_RECEIVED = "ClaimEventReceived", e.CLAIM_BROADCAST = "ClaimBroadcast", e.ASSERT_BROADCAST = "AssertBroadcast", e.CHALLENGE_ASSERT_OBSERVED = "ChallengeAssertObserved", e.WRONGLY_CHALLENGED_BROADCAST = "WronglyChallengedBroadcast", e.PAYOUT_BROADCAST = "PayoutBroadcast", e.FAILED = "Failed", e))(U || {});
695
- const Re = /* @__PURE__ */ new Set([
684
+ const $e = /* @__PURE__ */ new Set([
696
685
  "PayoutBroadcast",
697
686
  "Failed"
698
687
  /* FAILED */
699
688
  ]);
700
- function it(e) {
689
+ function st(e) {
701
690
  return Object.values(U).includes(
702
691
  e
703
692
  );
704
693
  }
705
694
  function at(e) {
706
- return !!e && Re.has(e);
695
+ return !!e && $e.has(e);
707
696
  }
708
697
  class Ce extends Error {
709
698
  constructor(r, o) {
710
699
  super(`Refund not yet mature (BIP68 not final): ${o.message}`);
711
- P(this, "vaultId");
712
- P(this, "cause");
700
+ y(this, "vaultId");
701
+ y(this, "cause");
713
702
  this.name = "BIP68NotMatureError", this.vaultId = r, this.cause = o;
714
703
  }
715
704
  }
@@ -787,22 +776,22 @@ async function ut(e) {
787
776
  vaultId: t,
788
777
  readVault: r,
789
778
  readPrePeginContext: o,
790
- feeRate: s,
779
+ feeRate: i,
791
780
  signPsbt: c,
792
781
  broadcastTx: a,
793
- signal: i
782
+ signal: s
794
783
  } = e;
795
- i == null || i.throwIfAborted(), M(t, "vaultId");
784
+ s == null || s.throwIfAborted(), M(t, "vaultId");
796
785
  const n = await r();
797
- Ke(n), i == null || i.throwIfAborted();
786
+ Ke(n), s == null || s.throwIfAborted();
798
787
  const u = await o(n);
799
- if (Ue(u), i == null || i.throwIfAborted(), !Number.isFinite(s) || s <= 0)
800
- throw new Error(`feeRate must be a positive number, got ${s}`);
801
- const d = BigInt(Math.ceil(s * Ve));
802
- i == null || i.throwIfAborted();
803
- const h = w(
788
+ if (Ue(u), s == null || s.throwIfAborted(), !Number.isFinite(i) || i <= 0)
789
+ throw new Error(`feeRate must be a positive number, got ${i}`);
790
+ const d = BigInt(Math.ceil(i * Ve));
791
+ s == null || s.throwIfAborted();
792
+ const h = P(
804
793
  n.depositorBtcPubkey
805
- ), { psbtHex: g } = await re({
794
+ ), { psbtHex: x } = await re({
806
795
  prePeginParams: {
807
796
  depositorPubkey: h,
808
797
  vaultProviderPubkey: l(u.vaultProviderPubkey),
@@ -826,14 +815,14 @@ async function ut(e) {
826
815
  // unspendable PSBT. Match the `hashlocks` array handling above.
827
816
  hashlock: l(n.hashlock)
828
817
  });
829
- i == null || i.throwIfAborted();
830
- const m = y(
818
+ s == null || s.throwIfAborted();
819
+ const m = b(
831
820
  n.depositorBtcPubkey,
832
821
  Le
833
- ), v = await c(g, m), T = Fe(v);
834
- i == null || i.throwIfAborted();
822
+ ), T = await c(x, m), v = Fe(T);
823
+ s == null || s.throwIfAborted();
835
824
  try {
836
- return await a(T);
825
+ return await a(v);
837
826
  } catch (p) {
838
827
  throw p instanceof Error && De.test(p.message) ? new Ce(t, p) : p;
839
828
  }
@@ -841,18 +830,18 @@ async function ut(e) {
841
830
  export {
842
831
  Ce as B,
843
832
  U as C,
844
- oe as P,
833
+ xe as P,
845
834
  Je as a,
846
- xe as b,
835
+ we as b,
847
836
  ot as c,
848
837
  nt as d,
849
838
  _e as e,
850
839
  Ae as f,
851
- st as g,
852
- se as h,
840
+ it as g,
841
+ ne as h,
853
842
  tt as i,
854
843
  ie as j,
855
- it as k,
844
+ st as k,
856
845
  at as l,
857
846
  ut as m,
858
847
  et as p,
@@ -860,4 +849,4 @@ export {
860
849
  rt as v,
861
850
  D as w
862
851
  };
863
- //# sourceMappingURL=buildAndBroadcastRefund-Cc4-L7gX.js.map
852
+ //# sourceMappingURL=buildAndBroadcastRefund-xWS8frc6.js.map