@arkade-os/boltz-swap 0.3.32 → 0.3.33

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 (31) hide show
  1. package/README.md +22 -26
  2. package/dist/{arkade-swaps-CS8FZSVL.d.cts → arkade-swaps-9M7FRuq1.d.cts} +57 -5
  3. package/dist/{arkade-swaps-WiKCanCL.d.ts → arkade-swaps-DNsyWeFr.d.ts} +57 -5
  4. package/dist/{chunk-NHBWNN6H.js → chunk-HNQDJOLM.js} +8 -27
  5. package/dist/{chunk-B3Q4TFWT.js → chunk-SJ5SYSMK.js} +551 -779
  6. package/dist/chunk-SJQJQO7P.js +25 -0
  7. package/dist/expo/background.cjs +573 -805
  8. package/dist/expo/background.d.cts +3 -3
  9. package/dist/expo/background.d.ts +3 -3
  10. package/dist/expo/background.js +8 -20
  11. package/dist/expo/index.cjs +574 -783
  12. package/dist/expo/index.d.cts +7 -5
  13. package/dist/expo/index.d.ts +7 -5
  14. package/dist/expo/index.js +17 -20
  15. package/dist/index.cjs +732 -931
  16. package/dist/index.d.cts +80 -10
  17. package/dist/index.d.ts +80 -10
  18. package/dist/index.js +126 -115
  19. package/dist/repositories/realm/index.cjs +10 -22
  20. package/dist/repositories/realm/index.d.cts +7 -5
  21. package/dist/repositories/realm/index.d.ts +7 -5
  22. package/dist/repositories/realm/index.js +8 -22
  23. package/dist/repositories/sqlite/index.cjs +12 -23
  24. package/dist/repositories/sqlite/index.d.cts +1 -1
  25. package/dist/repositories/sqlite/index.d.ts +1 -1
  26. package/dist/repositories/sqlite/index.js +10 -23
  27. package/dist/{swapsPollProcessor-wYOMzldd.d.ts → swapsPollProcessor-CEgeGlbP.d.ts} +3 -3
  28. package/dist/{swapsPollProcessor-BF3uTFae.d.cts → swapsPollProcessor-CuITxZie.d.cts} +3 -3
  29. package/dist/{types-BBI7-KJ0.d.cts → types-CrKkVzBB.d.cts} +9 -3
  30. package/dist/{types-BBI7-KJ0.d.ts → types-CrKkVzBB.d.ts} +9 -3
  31. package/package.json +10 -25
@@ -1,3 +1,9 @@
1
+ import {
2
+ applyCreatedAtOrder,
3
+ applySwapsFilter,
4
+ hasImpossibleSwapsFilter
5
+ } from "./chunk-SJQJQO7P.js";
6
+
1
7
  // src/errors.ts
2
8
  var SwapError = class extends Error {
3
9
  /** Whether the swap can still be claimed (default: false). */
@@ -7,7 +13,10 @@ var SwapError = class extends Error {
7
13
  /** The pending swap associated with this error, if available. */
8
14
  pendingSwap;
9
15
  constructor(options = {}) {
10
- super(options.message ?? "Error during swap.");
16
+ super(
17
+ options.message ?? "Error during swap.",
18
+ options.cause !== void 0 ? { cause: options.cause } : void 0
19
+ );
11
20
  this.name = "SwapError";
12
21
  this.isClaimable = options.isClaimable ?? false;
13
22
  this.isRefundable = options.isRefundable ?? false;
@@ -99,6 +108,96 @@ var TransactionRefundedError = class extends SwapError {
99
108
  this.name = "TransactionRefundedError";
100
109
  }
101
110
  };
111
+ var QuoteRejectedError = class _QuoteRejectedError extends SwapError {
112
+ reason;
113
+ quotedAmount;
114
+ floor;
115
+ constructor(options) {
116
+ super({
117
+ message: options.message ?? _QuoteRejectedError.defaultMessage(options),
118
+ ...options
119
+ });
120
+ this.name = "QuoteRejectedError";
121
+ this.reason = options.reason;
122
+ this.quotedAmount = "quotedAmount" in options ? options.quotedAmount : void 0;
123
+ this.floor = "floor" in options ? options.floor : void 0;
124
+ }
125
+ static defaultMessage(options) {
126
+ switch (options.reason) {
127
+ case "below_floor":
128
+ return `Boltz quote ${options.quotedAmount} is below acceptable floor ${options.floor}`;
129
+ case "non_positive":
130
+ return `Boltz quote ${options.quotedAmount} is not positive`;
131
+ case "no_baseline":
132
+ return "Cannot accept quote: no minAcceptableAmount and no stored pending swap";
133
+ }
134
+ }
135
+ /**
136
+ * Serialize into a plain `Error` whose `.message` carries the full
137
+ * rejection payload as JSON behind a marker prefix. Structured clone
138
+ * (used by `postMessage` between page and service worker) preserves
139
+ * `Error.message` reliably but strips custom `.name` and own properties,
140
+ * so we move the typed data into the message field for transport.
141
+ */
142
+ toTransportError() {
143
+ return new Error(
144
+ QUOTE_REJECTION_TRANSPORT_PREFIX + JSON.stringify({
145
+ reason: this.reason,
146
+ message: this.message,
147
+ quotedAmount: this.quotedAmount,
148
+ floor: this.floor
149
+ })
150
+ );
151
+ }
152
+ /**
153
+ * Inverse of `toTransportError`. Returns a real `QuoteRejectedError` if
154
+ * `error` carries the transport prefix, else `null`.
155
+ */
156
+ static fromTransportError(error) {
157
+ if (!(error instanceof Error) || !error.message.startsWith(QUOTE_REJECTION_TRANSPORT_PREFIX)) {
158
+ return null;
159
+ }
160
+ const payload = error.message.slice(QUOTE_REJECTION_TRANSPORT_PREFIX.length);
161
+ let data;
162
+ try {
163
+ data = JSON.parse(payload);
164
+ } catch {
165
+ return null;
166
+ }
167
+ if (typeof data.reason !== "string" || !QUOTE_REJECTION_REASONS.has(data.reason)) {
168
+ return null;
169
+ }
170
+ const message = typeof data.message === "string" ? data.message : void 0;
171
+ const reason = data.reason;
172
+ const quotedAmount = typeof data.quotedAmount === "number" ? data.quotedAmount : null;
173
+ const floor = typeof data.floor === "number" ? data.floor : null;
174
+ switch (reason) {
175
+ case "below_floor":
176
+ if (quotedAmount === null || floor === null) return null;
177
+ return new _QuoteRejectedError({
178
+ reason,
179
+ quotedAmount,
180
+ floor,
181
+ message
182
+ });
183
+ case "non_positive":
184
+ if (quotedAmount === null) return null;
185
+ return new _QuoteRejectedError({
186
+ reason,
187
+ quotedAmount,
188
+ message
189
+ });
190
+ case "no_baseline":
191
+ return new _QuoteRejectedError({ reason, message });
192
+ }
193
+ }
194
+ };
195
+ var QUOTE_REJECTION_TRANSPORT_PREFIX = "QUOTE_REJECTED::";
196
+ var QUOTE_REJECTION_REASONS = /* @__PURE__ */ new Set([
197
+ "below_floor",
198
+ "non_positive",
199
+ "no_baseline"
200
+ ]);
102
201
  var BoltzRefundError = class extends Error {
103
202
  constructor(message, cause) {
104
203
  super(message);
@@ -111,18 +210,10 @@ var BoltzRefundError = class extends Error {
111
210
  import { Transaction } from "@arkade-os/sdk";
112
211
  import { base64 } from "@scure/base";
113
212
  var isSubmarineFailedStatus = (status) => {
114
- return [
115
- "invoice.failedToPay",
116
- "transaction.lockupFailed",
117
- "swap.expired"
118
- ].includes(status);
213
+ return ["invoice.failedToPay", "transaction.lockupFailed", "swap.expired"].includes(status);
119
214
  };
120
215
  var isSubmarineFinalStatus = (status) => {
121
- return [
122
- "invoice.failedToPay",
123
- "transaction.claimed",
124
- "swap.expired"
125
- ].includes(status);
216
+ return ["invoice.failedToPay", "transaction.claimed", "swap.expired"].includes(status);
126
217
  };
127
218
  var isSubmarinePendingStatus = (status) => {
128
219
  return [
@@ -136,11 +227,7 @@ var isSubmarinePendingStatus = (status) => {
136
227
  ].includes(status);
137
228
  };
138
229
  var isSubmarineRefundableStatus = (status) => {
139
- return [
140
- "invoice.failedToPay",
141
- "transaction.lockupFailed",
142
- "swap.expired"
143
- ].includes(status);
230
+ return ["invoice.failedToPay", "transaction.lockupFailed", "swap.expired"].includes(status);
144
231
  };
145
232
  var isSubmarineSuccessStatus = (status) => {
146
233
  return status === "transaction.claimed";
@@ -164,11 +251,7 @@ var isReverseFinalStatus = (status) => {
164
251
  ].includes(status);
165
252
  };
166
253
  var isReversePendingStatus = (status) => {
167
- return [
168
- "swap.created",
169
- "transaction.mempool",
170
- "transaction.confirmed"
171
- ].includes(status);
254
+ return ["swap.created", "transaction.mempool", "transaction.confirmed"].includes(status);
172
255
  };
173
256
  var isReverseClaimableStatus = (status) => {
174
257
  return ["transaction.mempool", "transaction.confirmed"].includes(status);
@@ -180,10 +263,7 @@ var isChainFailedStatus = (status) => {
180
263
  return ["transaction.failed", "swap.expired"].includes(status);
181
264
  };
182
265
  var isChainClaimableStatus = (status) => {
183
- return [
184
- "transaction.server.mempool",
185
- "transaction.server.confirmed"
186
- ].includes(status);
266
+ return ["transaction.server.mempool", "transaction.server.confirmed"].includes(status);
187
267
  };
188
268
  var isChainFinalStatus = (status) => {
189
269
  return [
@@ -322,8 +402,7 @@ var BASE_URLS = {
322
402
  var isSwapNotFoundBody = (error) => {
323
403
  const needle = "could not find swap";
324
404
  const fromJson = error.errorData?.error;
325
- if (typeof fromJson === "string" && fromJson.toLowerCase().includes(needle))
326
- return true;
405
+ if (typeof fromJson === "string" && fromJson.toLowerCase().includes(needle)) return true;
327
406
  return error.message.toLowerCase().includes(needle);
328
407
  };
329
408
  var BoltzSwapProvider = class {
@@ -337,10 +416,7 @@ var BoltzSwapProvider = class {
337
416
  this.network = config.network;
338
417
  this.referralId = config.referralId ?? "arkade-ts-sdk";
339
418
  const apiUrl = config.apiUrl || BASE_URLS[config.network];
340
- if (!apiUrl)
341
- throw new Error(
342
- `API URL is required for network: ${config.network}`
343
- );
419
+ if (!apiUrl) throw new Error(`API URL is required for network: ${config.network}`);
344
420
  this.apiUrl = apiUrl;
345
421
  this.wsUrl = this.apiUrl.replace(/^http(s)?:\/\//, "ws$1://").replace("9069", "9004") + "/v2/ws";
346
422
  }
@@ -359,10 +435,7 @@ var BoltzSwapProvider = class {
359
435
  /** Returns current Lightning swap fees (submarine + reverse) from Boltz. */
360
436
  async getFees() {
361
437
  const [submarine, reverse] = await Promise.all([
362
- this.request(
363
- "/v2/swap/submarine",
364
- "GET"
365
- ),
438
+ this.request("/v2/swap/submarine", "GET"),
366
439
  this.request("/v2/swap/reverse", "GET")
367
440
  ]);
368
441
  if (!isGetSubmarinePairsResponse(submarine))
@@ -382,10 +455,7 @@ var BoltzSwapProvider = class {
382
455
  }
383
456
  /** Returns current Lightning swap min/max limits from Boltz. */
384
457
  async getLimits() {
385
- const response = await this.request(
386
- "/v2/swap/submarine",
387
- "GET"
388
- );
458
+ const response = await this.request("/v2/swap/submarine", "GET");
389
459
  if (!isGetSubmarinePairsResponse(response))
390
460
  throw new SchemaError({ message: "error fetching limits" });
391
461
  return {
@@ -395,10 +465,7 @@ var BoltzSwapProvider = class {
395
465
  }
396
466
  /** Returns the current BTC chain tip height from Boltz. */
397
467
  async getChainHeight() {
398
- const response = await this.request(
399
- "/v2/chain/heights",
400
- "GET"
401
- );
468
+ const response = await this.request("/v2/chain/heights", "GET");
402
469
  if (typeof response?.BTC !== "number")
403
470
  throw new SchemaError({
404
471
  message: "error fetching chain heights"
@@ -428,10 +495,7 @@ var BoltzSwapProvider = class {
428
495
  async getSwapStatus(id) {
429
496
  let response;
430
497
  try {
431
- response = await this.request(
432
- `/v2/swap/${id}`,
433
- "GET"
434
- );
498
+ response = await this.request(`/v2/swap/${id}`, "GET");
435
499
  } catch (error) {
436
500
  if (error instanceof NetworkError && error.statusCode === 404 && isSwapNotFoundBody(error)) {
437
501
  throw new SwapNotFoundError(id, error.errorData);
@@ -527,12 +591,10 @@ var BoltzSwapProvider = class {
527
591
  throw new SwapError({ message: "Invalid 'to' chain" });
528
592
  if (["BTC", "ARK"].indexOf(from) === -1)
529
593
  throw new SwapError({ message: "Invalid 'from' chain" });
530
- if (to === from)
531
- throw new SwapError({ message: "Invalid swap direction" });
594
+ if (to === from) throw new SwapError({ message: "Invalid swap direction" });
532
595
  if (!preimageHash || preimageHash.length != 64)
533
596
  throw new SwapError({ message: "Invalid preimageHash" });
534
- if (feeSatsPerByte <= 0)
535
- throw new SwapError({ message: "Invalid feeSatsPerByte" });
597
+ if (feeSatsPerByte <= 0) throw new SwapError({ message: "Invalid feeSatsPerByte" });
536
598
  if (serverLockAmount !== void 0 && userLockAmount !== void 0 || serverLockAmount === void 0 && userLockAmount === void 0)
537
599
  throw new SwapError({
538
600
  message: "Either serverLockAmount or userLockAmount must be provided"
@@ -587,12 +649,8 @@ var BoltzSwapProvider = class {
587
649
  message: "Error refunding submarine swap"
588
650
  });
589
651
  return {
590
- transaction: Transaction.fromPSBT(
591
- base64.decode(response.transaction)
592
- ),
593
- checkpoint: Transaction.fromPSBT(
594
- base64.decode(response.checkpoint)
595
- )
652
+ transaction: Transaction.fromPSBT(base64.decode(response.transaction)),
653
+ checkpoint: Transaction.fromPSBT(base64.decode(response.checkpoint))
596
654
  };
597
655
  }
598
656
  /** Requests Boltz co-signature for a chain swap refund. Returns signed transaction + checkpoint. */
@@ -611,53 +669,53 @@ var BoltzSwapProvider = class {
611
669
  message: "Error refunding chain swap"
612
670
  });
613
671
  return {
614
- transaction: Transaction.fromPSBT(
615
- base64.decode(response.transaction)
616
- ),
617
- checkpoint: Transaction.fromPSBT(
618
- base64.decode(response.checkpoint)
619
- )
672
+ transaction: Transaction.fromPSBT(base64.decode(response.transaction)),
673
+ checkpoint: Transaction.fromPSBT(base64.decode(response.checkpoint))
620
674
  };
621
675
  }
622
- /** Monitors swap status updates via WebSocket. Calls update callback on each status change. Resolves when terminal. */
676
+ /**
677
+ * Monitors swap status updates and forwards them to the update callback.
678
+ * Prefers a WebSocket subscription; on connection error or premature close
679
+ * it falls back to REST polling so callers don't fail when the WS endpoint
680
+ * is flaky (observed in CI). Resolves when the swap reaches a terminal
681
+ * status.
682
+ */
623
683
  async monitorSwap(swapId, update) {
624
684
  return new Promise((resolve, reject) => {
625
- const webSocket = new globalThis.WebSocket(this.wsUrl);
626
- const connectionTimeout = setTimeout(() => {
627
- webSocket.close();
628
- reject(new NetworkError("WebSocket connection timeout"));
629
- }, 3e4);
630
- webSocket.onerror = (error) => {
631
- clearTimeout(connectionTimeout);
632
- reject(
633
- new NetworkError(
634
- `WebSocket error: ${error.message}`
635
- )
636
- );
637
- };
638
- webSocket.onopen = () => {
639
- clearTimeout(connectionTimeout);
640
- webSocket.send(
641
- JSON.stringify({
642
- op: "subscribe",
643
- channel: "swap.update",
644
- args: [swapId]
645
- })
646
- );
685
+ let settled = false;
686
+ let lastStatus = null;
687
+ let pollTimer = null;
688
+ let webSocket = null;
689
+ let connectionTimeout = null;
690
+ const cleanup = () => {
691
+ if (connectionTimeout) {
692
+ clearTimeout(connectionTimeout);
693
+ connectionTimeout = null;
694
+ }
695
+ if (pollTimer) {
696
+ clearInterval(pollTimer);
697
+ pollTimer = null;
698
+ }
699
+ if (webSocket) {
700
+ try {
701
+ webSocket.close();
702
+ } catch {
703
+ }
704
+ webSocket = null;
705
+ }
647
706
  };
648
- webSocket.onclose = () => {
649
- clearTimeout(connectionTimeout);
650
- resolve();
707
+ const finish = (err) => {
708
+ if (settled) return;
709
+ settled = true;
710
+ cleanup();
711
+ if (err) reject(err);
712
+ else resolve();
651
713
  };
652
- webSocket.onmessage = async (rawMsg) => {
653
- const msg = JSON.parse(rawMsg.data);
654
- if (msg.event !== "update" || msg.args[0].id !== swapId) return;
655
- if (msg.args[0].error) {
656
- webSocket.close();
657
- reject(new SwapError({ message: msg.args[0].error }));
658
- }
659
- const status = msg.args[0].status;
660
- const negotiable = status === "transaction.lockupFailed" && msg.args[0].failureDetails?.actual !== void 0 && msg.args[0].failureDetails?.expected !== void 0;
714
+ const handleStatus = (status, data) => {
715
+ if (settled) return;
716
+ if (status === lastStatus) return;
717
+ lastStatus = status;
718
+ const negotiable = status === "transaction.lockupFailed" && data?.failureDetails?.actual !== void 0 && data?.failureDetails?.expected !== void 0;
661
719
  switch (status) {
662
720
  case "invoice.settled":
663
721
  case "transaction.claimed":
@@ -666,13 +724,13 @@ var BoltzSwapProvider = class {
666
724
  case "invoice.failedToPay":
667
725
  case "transaction.failed":
668
726
  case "swap.expired":
669
- webSocket.close();
670
- update(status, msg.args[0]);
671
- break;
727
+ update(status, data);
728
+ finish();
729
+ return;
672
730
  case "transaction.lockupFailed":
673
- if (!negotiable) webSocket.close();
674
- update(status, msg.args[0]);
675
- break;
731
+ update(status, data);
732
+ if (!negotiable) finish();
733
+ return;
676
734
  case "invoice.paid":
677
735
  case "invoice.pending":
678
736
  case "invoice.set":
@@ -682,9 +740,77 @@ var BoltzSwapProvider = class {
682
740
  case "transaction.claim.pending":
683
741
  case "transaction.server.mempool":
684
742
  case "transaction.server.confirmed":
685
- update(status, msg.args[0]);
743
+ update(status, data);
744
+ return;
686
745
  }
687
746
  };
747
+ const startPolling = () => {
748
+ if (settled || pollTimer) return;
749
+ const poll = async () => {
750
+ if (settled) return;
751
+ try {
752
+ const result = await this.getSwapStatus(swapId);
753
+ handleStatus(result.status, { ...result, id: swapId });
754
+ } catch {
755
+ }
756
+ };
757
+ pollTimer = setInterval(poll, 1e3);
758
+ poll();
759
+ };
760
+ try {
761
+ webSocket = new globalThis.WebSocket(this.wsUrl);
762
+ connectionTimeout = setTimeout(() => {
763
+ try {
764
+ webSocket?.close();
765
+ } catch {
766
+ }
767
+ webSocket = null;
768
+ startPolling();
769
+ }, 5e3);
770
+ webSocket.onerror = () => {
771
+ if (connectionTimeout) {
772
+ clearTimeout(connectionTimeout);
773
+ connectionTimeout = null;
774
+ }
775
+ webSocket = null;
776
+ startPolling();
777
+ };
778
+ webSocket.onopen = () => {
779
+ if (connectionTimeout) {
780
+ clearTimeout(connectionTimeout);
781
+ connectionTimeout = null;
782
+ }
783
+ webSocket?.send(
784
+ JSON.stringify({
785
+ op: "subscribe",
786
+ channel: "swap.update",
787
+ args: [swapId]
788
+ })
789
+ );
790
+ };
791
+ webSocket.onclose = () => {
792
+ if (connectionTimeout) {
793
+ clearTimeout(connectionTimeout);
794
+ connectionTimeout = null;
795
+ }
796
+ if (!settled && !pollTimer) startPolling();
797
+ };
798
+ webSocket.onmessage = (rawMsg) => {
799
+ try {
800
+ const msg = JSON.parse(rawMsg.data);
801
+ if (msg.event !== "update" || msg.args?.[0]?.id !== swapId) return;
802
+ if (msg.args[0].error) {
803
+ finish(new SwapError({ message: msg.args[0].error }));
804
+ return;
805
+ }
806
+ handleStatus(msg.args[0].status, msg.args[0]);
807
+ } catch {
808
+ }
809
+ };
810
+ } catch {
811
+ webSocket = null;
812
+ startPolling();
813
+ }
688
814
  });
689
815
  }
690
816
  /** Returns current chain swap fees for a given pair (e.g. ARK→BTC). */
@@ -692,10 +818,7 @@ var BoltzSwapProvider = class {
692
818
  if (from === to) {
693
819
  throw new SwapError({ message: "Invalid chain pair" });
694
820
  }
695
- const response = await this.request(
696
- "/v2/swap/chain",
697
- "GET"
698
- );
821
+ const response = await this.request("/v2/swap/chain", "GET");
699
822
  if (!isGetChainPairsResponse(response))
700
823
  throw new SchemaError({ message: "error fetching fees" });
701
824
  if (!response[from]?.[to]) {
@@ -710,10 +833,7 @@ var BoltzSwapProvider = class {
710
833
  if (from === to) {
711
834
  throw new SwapError({ message: "Invalid chain pair" });
712
835
  }
713
- const response = await this.request(
714
- "/v2/swap/chain",
715
- "GET"
716
- );
836
+ const response = await this.request("/v2/swap/chain", "GET");
717
837
  if (!isGetChainPairsResponse(response))
718
838
  throw new SchemaError({ message: "error fetching limits" });
719
839
  if (!response[from]?.[to]) {
@@ -842,9 +962,7 @@ var BoltzSwapProvider = class {
842
962
  return await response.json();
843
963
  } catch (error) {
844
964
  if (error instanceof NetworkError) throw error;
845
- throw new NetworkError(
846
- `Request to ${url} failed: ${error.message}`
847
- );
965
+ throw new NetworkError(`Request to ${url} failed: ${error.message}`);
848
966
  }
849
967
  }
850
968
  };
@@ -854,9 +972,7 @@ import bolt11 from "light-bolt11-decoder";
854
972
  import { ArkAddress } from "@arkade-os/sdk";
855
973
  var decodeInvoice = (invoice) => {
856
974
  const decoded = bolt11.decode(invoice);
857
- const millisats = Number(
858
- decoded.sections.find((s) => s.name === "amount")?.value ?? "0"
859
- );
975
+ const millisats = Number(decoded.sections.find((s) => s.name === "amount")?.value ?? "0");
860
976
  return {
861
977
  expiry: decoded.expiry ?? 3600,
862
978
  amountSats: Math.floor(millisats / 1e3),
@@ -996,9 +1112,7 @@ var SwapManager = class _SwapManager {
996
1112
  this.wsConnectedListeners.add(config.events.onWebSocketConnected);
997
1113
  }
998
1114
  if (config.events?.onWebSocketDisconnected) {
999
- this.wsDisconnectedListeners.add(
1000
- config.events.onWebSocketDisconnected
1001
- );
1115
+ this.wsDisconnectedListeners.add(config.events.onWebSocketDisconnected);
1002
1116
  }
1003
1117
  this.currentReconnectDelay = this.config.reconnectDelayMs;
1004
1118
  this.currentPollRetryDelay = this.config.pollRetryDelayMs;
@@ -1149,9 +1263,7 @@ var SwapManager = class _SwapManager {
1149
1263
  */
1150
1264
  setPollInterval(ms) {
1151
1265
  if (ms <= 0) {
1152
- throw new RangeError(
1153
- `setPollInterval: ms must be a positive number, got ${ms}`
1154
- );
1266
+ throw new RangeError(`setPollInterval: ms must be a positive number, got ${ms}`);
1155
1267
  }
1156
1268
  const cappedInterval = Math.min(ms, this.config.maxPollIntervalMs);
1157
1269
  if (cappedInterval !== ms) {
@@ -1160,10 +1272,7 @@ var SwapManager = class _SwapManager {
1160
1272
  );
1161
1273
  }
1162
1274
  this.config.pollInterval = cappedInterval;
1163
- this.currentPollRetryDelay = Math.min(
1164
- cappedInterval,
1165
- this.config.pollRetryDelayMs
1166
- );
1275
+ this.currentPollRetryDelay = Math.min(cappedInterval, this.config.pollRetryDelayMs);
1167
1276
  if (this.isRunning) {
1168
1277
  if (this.usePollingFallback) {
1169
1278
  this.startPollingFallback();
@@ -1248,9 +1357,7 @@ var SwapManager = class _SwapManager {
1248
1357
  }
1249
1358
  if (this.isFinalStatus(swap)) {
1250
1359
  if (isPendingReverseSwap(swap)) {
1251
- const response = await this.swapProvider.getReverseSwapTxId(
1252
- swap.id
1253
- );
1360
+ const response = await this.swapProvider.getReverseSwapTxId(swap.id);
1254
1361
  return { txid: response.id };
1255
1362
  }
1256
1363
  if (isPendingSubmarineSwap(swap)) {
@@ -1267,31 +1374,19 @@ var SwapManager = class _SwapManager {
1267
1374
  if (updatedSwap.status === "invoice.settled") {
1268
1375
  this.swapProvider.getReverseSwapTxId(updatedSwap.id).then((response) => resolve({ txid: response.id })).catch((error) => reject(error));
1269
1376
  } else {
1270
- reject(
1271
- new Error(
1272
- `Swap failed with status: ${updatedSwap.status}`
1273
- )
1274
- );
1377
+ reject(new Error(`Swap failed with status: ${updatedSwap.status}`));
1275
1378
  }
1276
1379
  } else if (isPendingSubmarineSwap(updatedSwap)) {
1277
1380
  if (updatedSwap.status === "transaction.claimed") {
1278
1381
  resolve({ txid: updatedSwap.id });
1279
1382
  } else {
1280
- reject(
1281
- new Error(
1282
- `Swap failed with status: ${updatedSwap.status}`
1283
- )
1284
- );
1383
+ reject(new Error(`Swap failed with status: ${updatedSwap.status}`));
1285
1384
  }
1286
1385
  } else if (isPendingChainSwap(updatedSwap)) {
1287
1386
  if (updatedSwap.status === "transaction.claimed") {
1288
1387
  resolve({ txid: updatedSwap.id });
1289
1388
  } else {
1290
- reject(
1291
- new Error(
1292
- `Swap failed with status: ${updatedSwap.status}`
1293
- )
1294
- );
1389
+ reject(new Error(`Swap failed with status: ${updatedSwap.status}`));
1295
1390
  }
1296
1391
  }
1297
1392
  };
@@ -1334,16 +1429,12 @@ var SwapManager = class _SwapManager {
1334
1429
  const connectionTimeout = setTimeout(() => {
1335
1430
  logger.error("WebSocket connection timeout");
1336
1431
  this.websocket?.close();
1337
- this.enterPollingFallback(
1338
- new NetworkError("WebSocket connection failed")
1339
- );
1432
+ this.enterPollingFallback(new NetworkError("WebSocket connection failed"));
1340
1433
  }, 1e4);
1341
1434
  this.websocket.onerror = (error) => {
1342
1435
  clearTimeout(connectionTimeout);
1343
1436
  logger.error("WebSocket error:", error);
1344
- this.enterPollingFallback(
1345
- new NetworkError("WebSocket connection failed")
1346
- );
1437
+ this.enterPollingFallback(new NetworkError("WebSocket connection failed"));
1347
1438
  };
1348
1439
  this.websocket.onopen = () => {
1349
1440
  clearTimeout(connectionTimeout);
@@ -1383,9 +1474,7 @@ var SwapManager = class _SwapManager {
1383
1474
  };
1384
1475
  } catch (error) {
1385
1476
  logger.error("Failed to create WebSocket:", error);
1386
- this.enterPollingFallback(
1387
- new NetworkError("WebSocket connection failed")
1388
- );
1477
+ this.enterPollingFallback(new NetworkError("WebSocket connection failed"));
1389
1478
  }
1390
1479
  }
1391
1480
  /**
@@ -1420,11 +1509,8 @@ var SwapManager = class _SwapManager {
1420
1509
  * Schedule WebSocket reconnection with exponential backoff
1421
1510
  */
1422
1511
  scheduleReconnect() {
1423
- if (this.reconnectTimer || this.webSocketUnavailable || !this.hasWebSocketSupport())
1424
- return;
1425
- logger.log(
1426
- `Scheduling WebSocket reconnect in ${this.currentReconnectDelay}ms`
1427
- );
1512
+ if (this.reconnectTimer || this.webSocketUnavailable || !this.hasWebSocketSupport()) return;
1513
+ logger.log(`Scheduling WebSocket reconnect in ${this.currentReconnectDelay}ms`);
1428
1514
  this.reconnectTimer = setTimeout(() => {
1429
1515
  this.reconnectTimer = null;
1430
1516
  this.isReconnecting = false;
@@ -1439,8 +1525,7 @@ var SwapManager = class _SwapManager {
1439
1525
  * Subscribe to a specific swap ID on the WebSocket
1440
1526
  */
1441
1527
  subscribeToSwap(swapId) {
1442
- if (!this.websocket || this.websocket.readyState !== WebSocket.OPEN)
1443
- return;
1528
+ if (!this.websocket || this.websocket.readyState !== WebSocket.OPEN) return;
1444
1529
  this.websocket.send(
1445
1530
  JSON.stringify({
1446
1531
  op: "subscribe",
@@ -1463,9 +1548,7 @@ var SwapManager = class _SwapManager {
1463
1548
  if (msg.args[0].error) {
1464
1549
  logger.error(`Swap ${swapId} error:`, msg.args[0].error);
1465
1550
  const error = new Error(msg.args[0].error);
1466
- this.swapFailedListeners.forEach(
1467
- (listener) => listener(swap, error)
1468
- );
1551
+ this.swapFailedListeners.forEach((listener) => listener(swap, error));
1469
1552
  return;
1470
1553
  }
1471
1554
  const newStatus = msg.args[0].status;
@@ -1483,19 +1566,14 @@ var SwapManager = class _SwapManager {
1483
1566
  const oldStatus = swap.status;
1484
1567
  if (oldStatus === newStatus) return;
1485
1568
  swap.status = newStatus;
1486
- this.swapUpdateListeners.forEach(
1487
- (listener) => listener(swap, oldStatus)
1488
- );
1569
+ this.swapUpdateListeners.forEach((listener) => listener(swap, oldStatus));
1489
1570
  const subscribers = this.swapSubscriptions.get(swap.id);
1490
1571
  if (subscribers) {
1491
1572
  subscribers.forEach((callback) => {
1492
1573
  try {
1493
1574
  callback(swap, oldStatus);
1494
1575
  } catch (error) {
1495
- logger.error(
1496
- `Error in swap subscription callback for ${swap.id}:`,
1497
- error
1498
- );
1576
+ logger.error(`Error in swap subscription callback for ${swap.id}:`, error);
1499
1577
  }
1500
1578
  });
1501
1579
  }
@@ -1520,9 +1598,7 @@ var SwapManager = class _SwapManager {
1520
1598
  */
1521
1599
  async executeAutonomousAction(swap) {
1522
1600
  if (this.swapsInProgress.has(swap.id)) {
1523
- logger.log(
1524
- `Swap ${swap.id} is already being processed, skipping autonomous action`
1525
- );
1601
+ logger.log(`Swap ${swap.id} is already being processed, skipping autonomous action`);
1526
1602
  return;
1527
1603
  }
1528
1604
  try {
@@ -1537,9 +1613,7 @@ var SwapManager = class _SwapManager {
1537
1613
  if (isReverseClaimableStatus(swap.status)) {
1538
1614
  logger.log(`Auto-claiming reverse swap ${swap.id}`);
1539
1615
  await this.executeClaimAction(swap);
1540
- this.actionExecutedListeners.forEach(
1541
- (listener) => listener(swap, "claim")
1542
- );
1616
+ this.actionExecutedListeners.forEach((listener) => listener(swap, "claim"));
1543
1617
  }
1544
1618
  } else if (isPendingSubmarineSwap(swap)) {
1545
1619
  if (!swap.request?.invoice || swap.request.invoice.length === 0) {
@@ -1551,9 +1625,7 @@ var SwapManager = class _SwapManager {
1551
1625
  if (isSubmarineRefundableStatus(swap.status)) {
1552
1626
  logger.log(`Auto-refunding submarine swap ${swap.id}`);
1553
1627
  await this.executeRefundAction(swap);
1554
- this.actionExecutedListeners.forEach(
1555
- (listener) => listener(swap, "refund")
1556
- );
1628
+ this.actionExecutedListeners.forEach((listener) => listener(swap, "refund"));
1557
1629
  }
1558
1630
  } else if (isPendingChainSwap(swap)) {
1559
1631
  if (isChainClaimableStatus(swap.status)) {
@@ -1603,13 +1675,8 @@ var SwapManager = class _SwapManager {
1603
1675
  }
1604
1676
  }
1605
1677
  } catch (error) {
1606
- logger.error(
1607
- `Failed to execute autonomous action for swap ${swap.id}:`,
1608
- error
1609
- );
1610
- this.swapFailedListeners.forEach(
1611
- (listener) => listener(swap, error)
1612
- );
1678
+ logger.error(`Failed to execute autonomous action for swap ${swap.id}:`, error);
1679
+ this.swapFailedListeners.forEach((listener) => listener(swap, error));
1613
1680
  } finally {
1614
1681
  this.swapsInProgress.delete(swap.id);
1615
1682
  }
@@ -1710,9 +1777,7 @@ var SwapManager = class _SwapManager {
1710
1777
  logger.log(`Resuming chain refund for swap ${swap.id}`);
1711
1778
  await this.executeAutonomousAction(swap);
1712
1779
  } else if (isPendingChainSwap(swap) && swap.request.to === "ARK" && isChainSignableStatus(swap.status)) {
1713
- logger.log(
1714
- `Resuming server claim signing for swap ${swap.id}`
1715
- );
1780
+ logger.log(`Resuming server claim signing for swap ${swap.id}`);
1716
1781
  await this.executeAutonomousAction(swap);
1717
1782
  }
1718
1783
  } catch (error) {
@@ -1771,9 +1836,7 @@ var SwapManager = class _SwapManager {
1771
1836
  }
1772
1837
  async pollSingleSwap(swap) {
1773
1838
  try {
1774
- const statusResponse = await this.swapProvider.getSwapStatus(
1775
- swap.id
1776
- );
1839
+ const statusResponse = await this.swapProvider.getSwapStatus(swap.id);
1777
1840
  this.notFoundCounts.delete(swap.id);
1778
1841
  if (statusResponse.status !== swap.status) {
1779
1842
  await this.handleSwapStatusUpdate(swap, statusResponse.status);
@@ -1784,9 +1847,7 @@ var SwapManager = class _SwapManager {
1784
1847
  return;
1785
1848
  }
1786
1849
  if (error instanceof NetworkError && error.statusCode === 429) {
1787
- logger.warn(
1788
- `Rate-limited polling swap ${swap.id}, retrying in 2s`
1789
- );
1850
+ logger.warn(`Rate-limited polling swap ${swap.id}, retrying in 2s`);
1790
1851
  const existing = this.pollRetryTimers.get(swap.id);
1791
1852
  if (existing) clearTimeout(existing);
1792
1853
  this.pollRetryTimers.set(
@@ -1794,25 +1855,17 @@ var SwapManager = class _SwapManager {
1794
1855
  setTimeout(async () => {
1795
1856
  this.pollRetryTimers.delete(swap.id);
1796
1857
  try {
1797
- const retry = await this.swapProvider.getSwapStatus(
1798
- swap.id
1799
- );
1858
+ const retry = await this.swapProvider.getSwapStatus(swap.id);
1800
1859
  this.notFoundCounts.delete(swap.id);
1801
1860
  if (retry.status !== swap.status) {
1802
- await this.handleSwapStatusUpdate(
1803
- swap,
1804
- retry.status
1805
- );
1861
+ await this.handleSwapStatusUpdate(swap, retry.status);
1806
1862
  }
1807
1863
  } catch (retryError) {
1808
1864
  if (retryError instanceof SwapNotFoundError) {
1809
1865
  await this.handleSwapNotFound(swap);
1810
1866
  return;
1811
1867
  }
1812
- logger.error(
1813
- `Retry poll for swap ${swap.id} also failed:`,
1814
- retryError
1815
- );
1868
+ logger.error(`Retry poll for swap ${swap.id} also failed:`, retryError);
1816
1869
  }
1817
1870
  }, 2e3)
1818
1871
  );
@@ -1864,9 +1917,7 @@ var SwapManager = class _SwapManager {
1864
1917
  this.pollRetryTimers.delete(swap.id);
1865
1918
  }
1866
1919
  this.notFoundCounts.delete(swap.id);
1867
- this.swapUpdateListeners.forEach(
1868
- (listener) => listener(swap, oldStatus)
1869
- );
1920
+ this.swapUpdateListeners.forEach((listener) => listener(swap, oldStatus));
1870
1921
  const subscribers = this.swapSubscriptions.get(swap.id);
1871
1922
  if (subscribers) {
1872
1923
  subscribers.forEach((callback) => {
@@ -1931,9 +1982,7 @@ async function saveSwap(swap, saver) {
1931
1982
  if (saver.saveSubmarineSwap) {
1932
1983
  await saver.saveSubmarineSwap(swap);
1933
1984
  } else {
1934
- console.warn(
1935
- "No saveSubmarineSwap handler provided, swap not saved"
1936
- );
1985
+ console.warn("No saveSubmarineSwap handler provided, swap not saved");
1937
1986
  }
1938
1987
  } else if (isPendingChainSwap(swap)) {
1939
1988
  if (saver.saveChainSwap) {
@@ -2012,6 +2061,10 @@ function initDatabase(db) {
2012
2061
  swapStore.createIndex("createdAt", "createdAt", { unique: false });
2013
2062
  }
2014
2063
  }
2064
+ function asArray(v) {
2065
+ if (v === void 0) return void 0;
2066
+ return Array.isArray(v) ? v : [v];
2067
+ }
2015
2068
  var IndexedDbSwapRepository = class {
2016
2069
  constructor(dbName = DEFAULT_DB_NAME) {
2017
2070
  this.dbName = dbName;
@@ -2026,10 +2079,7 @@ var IndexedDbSwapRepository = class {
2026
2079
  async saveSwap(swap) {
2027
2080
  const db = await this.getDB();
2028
2081
  return new Promise((resolve, reject) => {
2029
- const transaction = db.transaction(
2030
- [STORE_SWAPS_STATE],
2031
- "readwrite"
2032
- );
2082
+ const transaction = db.transaction([STORE_SWAPS_STATE], "readwrite");
2033
2083
  const store = transaction.objectStore(STORE_SWAPS_STATE);
2034
2084
  const request = store.put(swap);
2035
2085
  request.onsuccess = () => resolve();
@@ -2039,10 +2089,7 @@ var IndexedDbSwapRepository = class {
2039
2089
  async deleteSwap(id) {
2040
2090
  const db = await this.getDB();
2041
2091
  return new Promise((resolve, reject) => {
2042
- const transaction = db.transaction(
2043
- [STORE_SWAPS_STATE],
2044
- "readwrite"
2045
- );
2092
+ const transaction = db.transaction([STORE_SWAPS_STATE], "readwrite");
2046
2093
  const store = transaction.objectStore(STORE_SWAPS_STATE);
2047
2094
  const request = store.delete(id);
2048
2095
  request.onsuccess = () => resolve();
@@ -2055,10 +2102,7 @@ var IndexedDbSwapRepository = class {
2055
2102
  async clear() {
2056
2103
  const db = await this.getDB();
2057
2104
  return new Promise((resolve, reject) => {
2058
- const transaction = db.transaction(
2059
- [STORE_SWAPS_STATE],
2060
- "readwrite"
2061
- );
2105
+ const transaction = db.transaction([STORE_SWAPS_STATE], "readwrite");
2062
2106
  const store = transaction.objectStore(STORE_SWAPS_STATE);
2063
2107
  const request = store.clear();
2064
2108
  request.onsuccess = () => resolve();
@@ -2075,11 +2119,10 @@ var IndexedDbSwapRepository = class {
2075
2119
  request.onsuccess = () => resolve(request.result ?? []);
2076
2120
  })
2077
2121
  );
2078
- return Promise.all(requests).then(
2079
- (results) => results.flatMap((result) => result)
2080
- );
2122
+ return Promise.all(requests).then((results) => results.flatMap((result) => result));
2081
2123
  }
2082
2124
  async getAllSwapsFromStore(filter) {
2125
+ if (hasImpossibleSwapsFilter(filter)) return [];
2083
2126
  const db = await this.getDB();
2084
2127
  const store = db.transaction([STORE_SWAPS_STATE], "readonly").objectStore(STORE_SWAPS_STATE);
2085
2128
  if (!filter || Object.keys(filter).length === 0) {
@@ -2089,9 +2132,8 @@ var IndexedDbSwapRepository = class {
2089
2132
  request.onerror = () => reject(request.error);
2090
2133
  });
2091
2134
  }
2092
- const normalizedFilter = normalizeFilter(filter);
2093
- if (normalizedFilter.has("id")) {
2094
- const ids = normalizedFilter.get("id");
2135
+ const ids = asArray(filter.id);
2136
+ if (ids) {
2095
2137
  const swaps = await Promise.all(
2096
2138
  ids.map(
2097
2139
  (id) => new Promise((resolve, reject) => {
@@ -2101,34 +2143,17 @@ var IndexedDbSwapRepository = class {
2101
2143
  })
2102
2144
  )
2103
2145
  );
2104
- return this.sortIfNeeded(
2105
- this.applySwapsFilter(swaps, normalizedFilter),
2106
- filter
2107
- );
2146
+ return applyCreatedAtOrder(applySwapsFilter(swaps, filter), filter);
2108
2147
  }
2109
- if (normalizedFilter.has("type")) {
2110
- const types = normalizedFilter.get("type");
2111
- const swaps = await this.getSwapsByIndexValues(
2112
- store,
2113
- "type",
2114
- types
2115
- );
2116
- return this.sortIfNeeded(
2117
- this.applySwapsFilter(swaps, normalizedFilter),
2118
- filter
2119
- );
2148
+ const types = asArray(filter.type);
2149
+ if (types) {
2150
+ const swaps = await this.getSwapsByIndexValues(store, "type", types);
2151
+ return applyCreatedAtOrder(applySwapsFilter(swaps, filter), filter);
2120
2152
  }
2121
- if (normalizedFilter.has("status")) {
2122
- const ids = normalizedFilter.get("status");
2123
- const swaps = await this.getSwapsByIndexValues(
2124
- store,
2125
- "status",
2126
- ids
2127
- );
2128
- return this.sortIfNeeded(
2129
- this.applySwapsFilter(swaps, normalizedFilter),
2130
- filter
2131
- );
2153
+ const statuses = asArray(filter.status);
2154
+ if (statuses) {
2155
+ const swaps = await this.getSwapsByIndexValues(store, "status", statuses);
2156
+ return applyCreatedAtOrder(applySwapsFilter(swaps, filter), filter);
2132
2157
  }
2133
2158
  if (filter.orderBy === "createdAt") {
2134
2159
  return this.getAllSwapsByCreatedAt(store, filter.orderDirection);
@@ -2138,22 +2163,7 @@ var IndexedDbSwapRepository = class {
2138
2163
  request.onsuccess = () => resolve(request.result ?? []);
2139
2164
  request.onerror = () => reject(request.error);
2140
2165
  });
2141
- return this.sortIfNeeded(
2142
- this.applySwapsFilter(allSwaps, normalizedFilter),
2143
- filter
2144
- );
2145
- }
2146
- applySwapsFilter(swaps, filter) {
2147
- return swaps.filter((swap) => {
2148
- if (swap === void 0) return false;
2149
- if (filter.has("id") && !filter.get("id")?.includes(swap.id))
2150
- return false;
2151
- if (filter.has("status") && !filter.get("status")?.includes(swap.status))
2152
- return false;
2153
- if (filter.has("type") && !filter.get("type")?.includes(swap.type))
2154
- return false;
2155
- return true;
2156
- });
2166
+ return applyCreatedAtOrder(applySwapsFilter(allSwaps, filter), filter);
2157
2167
  }
2158
2168
  async getAllSwapsByCreatedAt(store, orderDirection) {
2159
2169
  const index = store.index("createdAt");
@@ -2173,30 +2183,12 @@ var IndexedDbSwapRepository = class {
2173
2183
  };
2174
2184
  });
2175
2185
  }
2176
- sortIfNeeded(swaps, filter) {
2177
- if (filter?.orderBy !== "createdAt") return swaps;
2178
- const direction = filter.orderDirection === "asc" ? 1 : -1;
2179
- return swaps.slice().sort((a, b) => (a.createdAt - b.createdAt) * direction);
2180
- }
2181
2186
  async [Symbol.asyncDispose]() {
2182
2187
  if (!this.db) return;
2183
2188
  await closeDatabase(this.dbName);
2184
2189
  this.db = null;
2185
2190
  }
2186
2191
  };
2187
- var FILTER_FIELDS = ["id", "status", "type"];
2188
- function normalizeFilter(filter) {
2189
- const res = /* @__PURE__ */ new Map();
2190
- FILTER_FIELDS.forEach((current) => {
2191
- if (!filter?.[current]) return;
2192
- if (Array.isArray(filter[current])) {
2193
- res.set(current, filter[current]);
2194
- } else {
2195
- res.set(current, [filter[current]]);
2196
- }
2197
- });
2198
- return res;
2199
- }
2200
2192
 
2201
2193
  // src/arkade-swaps.ts
2202
2194
  import {
@@ -2225,8 +2217,7 @@ var findKeyIndex = (keys, target) => keys.findIndex((k) => equalBytes(target, k)
2225
2217
  var assertPublicKeys = (keys) => {
2226
2218
  const seen = /* @__PURE__ */ new Set();
2227
2219
  for (const key of keys) {
2228
- if (key.length !== 33)
2229
- throw new Error(`public key must be 33 bytes, got ${key.length}`);
2220
+ if (key.length !== 33) throw new Error(`public key must be 33 bytes, got ${key.length}`);
2230
2221
  const enc = hex3.encode(key);
2231
2222
  if (seen.has(enc)) throw new Error(`duplicate public key ${enc}`);
2232
2223
  seen.add(enc);
@@ -2234,9 +2225,7 @@ var assertPublicKeys = (keys) => {
2234
2225
  };
2235
2226
  var aggregateKeys = (publicKeys, tweak) => {
2236
2227
  assertPublicKeys([...publicKeys]);
2237
- return keyAggExport(
2238
- keyAggregate([...publicKeys], tweak ? [tweak] : [], tweak ? [true] : [])
2239
- );
2228
+ return keyAggExport(keyAggregate([...publicKeys], tweak ? [tweak] : [], tweak ? [true] : []));
2240
2229
  };
2241
2230
  var MusigKeyAgg = class _MusigKeyAgg {
2242
2231
  constructor(privateKey, myPublicKey, publicKeys, myIndex, aggPubkey, internalKey, _tweak) {
@@ -2283,18 +2272,12 @@ var MusigWithMessage = class {
2283
2272
  this.msg = msg;
2284
2273
  }
2285
2274
  generateNonce() {
2286
- const nonce = nonceGen(
2287
- this.myPublicKey,
2288
- this.privateKey,
2289
- this.aggPubkey,
2290
- this.msg
2291
- );
2275
+ const nonce = nonceGen(this.myPublicKey, this.privateKey, this.aggPubkey, this.msg);
2292
2276
  return new MusigWithNonce(
2293
2277
  this.privateKey,
2294
2278
  this.myPublicKey,
2295
2279
  this.publicKeys,
2296
2280
  this.myIndex,
2297
- this.aggPubkey,
2298
2281
  this.tweak,
2299
2282
  this.msg,
2300
2283
  nonce
@@ -2302,12 +2285,11 @@ var MusigWithMessage = class {
2302
2285
  }
2303
2286
  };
2304
2287
  var MusigWithNonce = class {
2305
- constructor(privateKey, myPublicKey, publicKeys, myIndex, aggPubkey, tweak, msg, nonce) {
2288
+ constructor(privateKey, myPublicKey, publicKeys, myIndex, tweak, msg, nonce) {
2306
2289
  this.privateKey = privateKey;
2307
2290
  this.myPublicKey = myPublicKey;
2308
2291
  this.publicKeys = publicKeys;
2309
2292
  this.myIndex = myIndex;
2310
- this.aggPubkey = aggPubkey;
2311
2293
  this.tweak = tweak;
2312
2294
  this.msg = msg;
2313
2295
  this.nonce = nonce;
@@ -2339,10 +2321,8 @@ var MusigWithNonce = class {
2339
2321
  const aggregatedNonce = nonceAggregate([...ordered]);
2340
2322
  return new MusigNoncesAggregated(
2341
2323
  this.privateKey,
2342
- this.myPublicKey,
2343
2324
  this.publicKeys,
2344
2325
  this.myIndex,
2345
- this.aggPubkey,
2346
2326
  this.tweak,
2347
2327
  this.msg,
2348
2328
  this.nonce,
@@ -2352,12 +2332,10 @@ var MusigWithNonce = class {
2352
2332
  }
2353
2333
  };
2354
2334
  var MusigNoncesAggregated = class {
2355
- constructor(privateKey, myPublicKey, publicKeys, myIndex, aggPubkey, tweak, msg, nonce, pubNonces, aggregatedNonce) {
2335
+ constructor(privateKey, publicKeys, myIndex, tweak, msg, nonce, pubNonces, aggregatedNonce) {
2356
2336
  this.privateKey = privateKey;
2357
- this.myPublicKey = myPublicKey;
2358
2337
  this.publicKeys = publicKeys;
2359
2338
  this.myIndex = myIndex;
2360
- this.aggPubkey = aggPubkey;
2361
2339
  this.tweak = tweak;
2362
2340
  this.msg = msg;
2363
2341
  this.nonce = nonce;
@@ -2403,11 +2381,7 @@ var MusigSession = class {
2403
2381
  const index = typeof publicKeyOrIndex === "number" ? publicKeyOrIndex : findKeyIndex(this.publicKeys, publicKeyOrIndex);
2404
2382
  if (index < 0 || index >= this.publicKeys.length)
2405
2383
  throw new Error("public key not found or index out of range");
2406
- if (!this.session.partialSigVerify(
2407
- signature,
2408
- [...this.pubNonces],
2409
- index
2410
- )) {
2384
+ if (!this.session.partialSigVerify(signature, [...this.pubNonces], index)) {
2411
2385
  throw new Error("invalid partial signature");
2412
2386
  }
2413
2387
  this.partialSignatures[index] = signature;
@@ -2416,12 +2390,7 @@ var MusigSession = class {
2416
2390
  signPartial() {
2417
2391
  const sig = this.session.sign(this.nonce.secret, this.privateKey, true);
2418
2392
  this.partialSignatures[this.myIndex] = sig;
2419
- return new MusigSigned(
2420
- this.session,
2421
- [...this.partialSignatures],
2422
- sig,
2423
- this.nonce.public
2424
- );
2393
+ return new MusigSigned(this.session, [...this.partialSignatures], sig, this.nonce.public);
2425
2394
  }
2426
2395
  };
2427
2396
  var MusigSigned = class {
@@ -2435,14 +2404,11 @@ var MusigSigned = class {
2435
2404
  if (this.partialSignatures.some((s) => s === null)) {
2436
2405
  throw new Error("not all partial signatures are set");
2437
2406
  }
2438
- return this.session.partialSigAgg(
2439
- this.partialSignatures
2440
- );
2407
+ return this.session.partialSigAgg(this.partialSignatures);
2441
2408
  }
2442
2409
  };
2443
2410
  var create = (privateKey, publicKeys) => {
2444
- if (publicKeys.length < 2)
2445
- throw new Error("need at least 2 keys to aggregate");
2411
+ if (publicKeys.length < 2) throw new Error("need at least 2 keys to aggregate");
2446
2412
  const keys = [...publicKeys];
2447
2413
  assertPublicKeys(keys);
2448
2414
  Object.freeze(keys);
@@ -2450,14 +2416,7 @@ var create = (privateKey, publicKeys) => {
2450
2416
  const myIndex = findKeyIndex(keys, myPublicKey);
2451
2417
  if (myIndex === -1) throw new Error("our key is not in publicKeys");
2452
2418
  const aggPubkey = aggregateKeys(keys);
2453
- return new MusigKeyAgg(
2454
- privateKey,
2455
- myPublicKey,
2456
- keys,
2457
- myIndex,
2458
- aggPubkey,
2459
- aggPubkey
2460
- );
2419
+ return new MusigKeyAgg(privateKey, myPublicKey, keys, myIndex, aggPubkey, aggPubkey);
2461
2420
  };
2462
2421
 
2463
2422
  // src/utils/boltz-swap-tx.ts
@@ -2533,9 +2492,7 @@ var taprootHashTree = (tree) => {
2533
2492
  };
2534
2493
  var tweakMusig = (musig, tree) => {
2535
2494
  const tweak = taprootHashTree(tree).hash;
2536
- return musig.xonlyTweakAdd(
2537
- schnorr.utils.taggedHash("TapTweak", musig.aggPubkey, tweak)
2538
- );
2495
+ return musig.xonlyTweakAdd(schnorr.utils.taggedHash("TapTweak", musig.aggPubkey, tweak));
2539
2496
  };
2540
2497
  var toXOnly = (pubKey) => {
2541
2498
  if (pubKey.length === 32) return pubKey;
@@ -2547,9 +2504,7 @@ var toXOnly = (pubKey) => {
2547
2504
  }
2548
2505
  return pubKey.subarray(1, 33);
2549
2506
  }
2550
- throw new Error(
2551
- `Invalid public key length: expected 32 or 33 bytes, got ${pubKey.length}`
2552
- );
2507
+ throw new Error(`Invalid public key length: expected 32 or 33 bytes, got ${pubKey.length}`);
2553
2508
  };
2554
2509
  var p2trScript = (publicKey) => Script.encode(["OP_1", toXOnly(publicKey)]);
2555
2510
  var detectSwapOutput = (tweakedKey, transaction) => {
@@ -2564,8 +2519,7 @@ var detectSwapOutput = (tweakedKey, transaction) => {
2564
2519
  };
2565
2520
  var DUMMY_TAPROOT_SIGNATURE = new Uint8Array(64);
2566
2521
  var constructClaimTransaction = (utxo, destinationScript, fee) => {
2567
- if (fee < BigInt(0) || fee >= utxo.amount)
2568
- throw new Error("fee exceeds utxo amount");
2522
+ if (fee < BigInt(0) || fee >= utxo.amount) throw new Error("fee exceeds utxo amount");
2569
2523
  const tx = new Transaction2({ version: 2 });
2570
2524
  tx.addOutput({
2571
2525
  amount: utxo.amount - fee,
@@ -2584,9 +2538,7 @@ var constructClaimTransaction = (utxo, destinationScript, fee) => {
2584
2538
  };
2585
2539
  var targetFee = (satPerVbyte, constructTx) => {
2586
2540
  const tx = constructTx(BigInt(1));
2587
- return constructTx(
2588
- BigInt(Math.ceil((tx.vsize + tx.inputsLength) * satPerVbyte))
2589
- );
2541
+ return constructTx(BigInt(Math.ceil((tx.vsize + tx.inputsLength) * satPerVbyte)));
2590
2542
  };
2591
2543
 
2592
2544
  // src/utils/restoration.ts
@@ -2610,10 +2562,7 @@ function extractTimeLockFromLeafOutput(scriptHex) {
2610
2562
  const data = opcodes[hasCSV - 1];
2611
2563
  if (data instanceof Uint8Array) {
2612
2564
  const dataBytes = new Uint8Array(data).reverse();
2613
- const {
2614
- blocks,
2615
- seconds
2616
- } = bip68.decode(
2565
+ const { blocks, seconds } = bip68.decode(
2617
2566
  parseInt(hex5.encode(dataBytes), 16)
2618
2567
  );
2619
2568
  return blocks ?? seconds ?? 0;
@@ -2634,11 +2583,7 @@ function extractInvoiceAmount(amountSats, fees) {
2634
2583
  }
2635
2584
 
2636
2585
  // src/utils/identity.ts
2637
- import {
2638
- ConditionWitness,
2639
- setArkPsbtField,
2640
- Transaction as Transaction3
2641
- } from "@arkade-os/sdk";
2586
+ import { ConditionWitness, setArkPsbtField, Transaction as Transaction3 } from "@arkade-os/sdk";
2642
2587
  function claimVHTLCIdentity(identity, preimage) {
2643
2588
  return {
2644
2589
  ...identity,
@@ -2647,13 +2592,8 @@ function claimVHTLCIdentity(identity, preimage) {
2647
2592
  let signedTx = await identity.sign(cpy, inputIndexes);
2648
2593
  signedTx = Transaction3.fromPSBT(signedTx.toPSBT());
2649
2594
  if (preimage) {
2650
- for (const inputIndex of inputIndexes || Array.from(
2651
- { length: signedTx.inputsLength },
2652
- (_, i) => i
2653
- )) {
2654
- setArkPsbtField(signedTx, inputIndex, ConditionWitness, [
2655
- preimage
2656
- ]);
2595
+ for (const inputIndex of inputIndexes || Array.from({ length: signedTx.inputsLength }, (_, i) => i)) {
2596
+ setArkPsbtField(signedTx, inputIndex, ConditionWitness, [preimage]);
2657
2597
  }
2658
2598
  }
2659
2599
  return signedTx;
@@ -2728,17 +2668,13 @@ function createVHTLCBatchHandler(intentId, vhtlc, arkProvider, identity, session
2728
2668
  if (!sweepTapTreeRoot) {
2729
2669
  throw new Error("Sweep tap tree root not set");
2730
2670
  }
2731
- const xOnlyPublicKeys = event.cosignersPublicKeys.map(
2732
- (k) => k.slice(2)
2733
- );
2671
+ const xOnlyPublicKeys = event.cosignersPublicKeys.map((k) => k.slice(2));
2734
2672
  const signerPublicKey = await session.getPublicKey();
2735
2673
  const xonlySignerPublicKey = signerPublicKey.subarray(1);
2736
2674
  if (!xOnlyPublicKeys.includes(hex6.encode(xonlySignerPublicKey))) {
2737
2675
  return { skip: true };
2738
2676
  }
2739
- const commitmentTx = Transaction4.fromPSBT(
2740
- base642.decode(event.unsignedCommitmentTx)
2741
- );
2677
+ const commitmentTx = Transaction4.fromPSBT(base642.decode(event.unsignedCommitmentTx));
2742
2678
  validateVtxoTxGraph(vtxoTree, commitmentTx, sweepTapTreeRoot);
2743
2679
  const sharedOutput = commitmentTx.getOutput(0);
2744
2680
  if (!sharedOutput?.amount) {
@@ -2754,18 +2690,11 @@ function createVHTLCBatchHandler(intentId, vhtlc, arkProvider, identity, session
2754
2690
  if (!session) {
2755
2691
  return { fullySigned: true };
2756
2692
  }
2757
- const { hasAllNonces } = await session.aggregatedNonces(
2758
- event.txid,
2759
- event.nonces
2760
- );
2693
+ const { hasAllNonces } = await session.aggregatedNonces(event.txid, event.nonces);
2761
2694
  if (!hasAllNonces) return { fullySigned: false };
2762
2695
  const signatures = await session.sign();
2763
2696
  const pubkey = hex6.encode(await session.getPublicKey());
2764
- await arkProvider.submitTreeSignatures(
2765
- event.id,
2766
- pubkey,
2767
- signatures
2768
- );
2697
+ await arkProvider.submitTreeSignatures(event.id, pubkey, signatures);
2769
2698
  return { fullySigned: true };
2770
2699
  },
2771
2700
  onBatchFinalization: async (event, _, connectorTree) => {
@@ -2773,9 +2702,7 @@ function createVHTLCBatchHandler(intentId, vhtlc, arkProvider, identity, session
2773
2702
  return;
2774
2703
  }
2775
2704
  if (!connectorTree) {
2776
- throw new Error(
2777
- "BatchFinalizationEvent: expected connector tree to be defined"
2778
- );
2705
+ throw new Error("BatchFinalizationEvent: expected connector tree to be defined");
2779
2706
  }
2780
2707
  validateConnectorsTxGraph(event.commitmentTx, connectorTree);
2781
2708
  const connectors = connectorTree.leaves();
@@ -2790,9 +2717,7 @@ function createVHTLCBatchHandler(intentId, vhtlc, arkProvider, identity, session
2790
2717
  connectors[connectorIndex]
2791
2718
  );
2792
2719
  const signedForfeitTx = await identity.sign(forfeitTx);
2793
- await arkProvider.submitSignedForfeitTxs([
2794
- base642.encode(signedForfeitTx.toPSBT())
2795
- ]);
2720
+ await arkProvider.submitSignedForfeitTxs([base642.encode(signedForfeitTx.toPSBT())]);
2796
2721
  }
2797
2722
  };
2798
2723
  }
@@ -2852,36 +2777,22 @@ var createVHTLCScript = (args) => {
2852
2777
  serverPubkey,
2853
2778
  timeoutBlockHeights: vhtlcTimeouts
2854
2779
  } = args;
2855
- const receiverXOnlyPublicKey = normalizeToXOnlyKey(
2856
- hex7.decode(receiverPubkey),
2857
- "receiver"
2858
- );
2859
- const senderXOnlyPublicKey = normalizeToXOnlyKey(
2860
- hex7.decode(senderPubkey),
2861
- "sender"
2862
- );
2863
- const serverXOnlyPublicKey = normalizeToXOnlyKey(
2864
- hex7.decode(serverPubkey),
2865
- "server"
2866
- );
2780
+ const receiverXOnlyPublicKey = normalizeToXOnlyKey(hex7.decode(receiverPubkey), "receiver");
2781
+ const senderXOnlyPublicKey = normalizeToXOnlyKey(hex7.decode(senderPubkey), "sender");
2782
+ const serverXOnlyPublicKey = normalizeToXOnlyKey(hex7.decode(serverPubkey), "server");
2867
2783
  const vhtlcScript = new VHTLC.Script({
2868
2784
  preimageHash: ripemd160(preimageHash),
2869
2785
  sender: senderXOnlyPublicKey,
2870
2786
  receiver: receiverXOnlyPublicKey,
2871
2787
  server: serverXOnlyPublicKey,
2872
2788
  refundLocktime: BigInt(vhtlcTimeouts.refund),
2873
- unilateralClaimDelay: toBip68RelativeTimelock(
2874
- vhtlcTimeouts.unilateralClaim
2875
- ),
2876
- unilateralRefundDelay: toBip68RelativeTimelock(
2877
- vhtlcTimeouts.unilateralRefund
2878
- ),
2789
+ unilateralClaimDelay: toBip68RelativeTimelock(vhtlcTimeouts.unilateralClaim),
2790
+ unilateralRefundDelay: toBip68RelativeTimelock(vhtlcTimeouts.unilateralRefund),
2879
2791
  unilateralRefundWithoutReceiverDelay: toBip68RelativeTimelock(
2880
2792
  vhtlcTimeouts.unilateralRefundWithoutReceiver
2881
2793
  )
2882
2794
  });
2883
- if (!vhtlcScript.claimScript)
2884
- throw new Error("Failed to create VHTLC script");
2795
+ if (!vhtlcScript.claimScript) throw new Error("Failed to create VHTLC script");
2885
2796
  const hrp = network === "bitcoin" ? "ark" : "tark";
2886
2797
  const vhtlcAddress = vhtlcScript.address(hrp, serverXOnlyPublicKey).encode();
2887
2798
  return { vhtlcScript, vhtlcAddress };
@@ -2915,11 +2826,7 @@ var joinBatch = async (arkProvider, identity, input, output, {
2915
2826
  unknown: [VtxoTaprootTree.encode(input.tapTree)],
2916
2827
  sequence: getSequence2(input.tapLeafScript)
2917
2828
  };
2918
- const registerIntent = Intent.create(
2919
- intentMessage,
2920
- [intentInput],
2921
- [output]
2922
- );
2829
+ const registerIntent = Intent.create(intentMessage, [intentInput], [output]);
2923
2830
  const deleteIntent = Intent.create(deleteMessage, [intentInput]);
2924
2831
  const [signedRegisterIntent, signedDeleteIntent] = await Promise.all([
2925
2832
  identity.sign(registerIntent),
@@ -2943,14 +2850,8 @@ var joinBatch = async (arkProvider, identity, input, output, {
2943
2850
  normalizeToXOnlyKey(forfeitPubkey, "forfeit"),
2944
2851
  isRecoverable2 ? void 0 : OutScript.encode(decodedAddress)
2945
2852
  );
2946
- const topics = [
2947
- hex7.encode(signerPublicKey),
2948
- `${input.txid}:${input.vout}`
2949
- ];
2950
- const eventStream = arkProvider.getEventStream(
2951
- abortController.signal,
2952
- topics
2953
- );
2853
+ const topics = [hex7.encode(signerPublicKey), `${input.txid}:${input.vout}`];
2854
+ const eventStream = arkProvider.getEventStream(abortController.signal, topics);
2954
2855
  const commitmentTxid = await Batch.join(eventStream, handler, {
2955
2856
  abortController
2956
2857
  });
@@ -2971,14 +2872,8 @@ var joinBatch = async (arkProvider, identity, input, output, {
2971
2872
  };
2972
2873
  var claimVHTLCwithOffchainTx = async (identity, vhtlcScript, serverXOnlyPublicKey, input, output, arkInfo, arkProvider) => {
2973
2874
  const rawCheckpointTapscript = hex7.decode(arkInfo.checkpointTapscript);
2974
- const serverUnrollScript = CSVMultisigTapscript2.decode(
2975
- rawCheckpointTapscript
2976
- );
2977
- const { arkTx, checkpoints } = buildOffchainTx(
2978
- [input],
2979
- [output],
2980
- serverUnrollScript
2981
- );
2875
+ const serverUnrollScript = CSVMultisigTapscript2.decode(rawCheckpointTapscript);
2876
+ const { arkTx, checkpoints } = buildOffchainTx([input], [output], serverUnrollScript);
2982
2877
  const signedArkTx = await identity.sign(arkTx);
2983
2878
  const { arkTxid, finalArkTx, signedCheckpointTxs } = await arkProvider.submitTx(
2984
2879
  base643.encode(signedArkTx.toPSBT()),
@@ -2986,9 +2881,7 @@ var claimVHTLCwithOffchainTx = async (identity, vhtlcScript, serverXOnlyPublicKe
2986
2881
  );
2987
2882
  const finalTx = Transaction5.fromPSBT(base643.decode(finalArkTx));
2988
2883
  const serverPubkeyHex = hex7.encode(serverXOnlyPublicKey);
2989
- const claimLeafHash = tapLeafHash3(
2990
- scriptFromTapLeafScript(vhtlcScript.claim())
2991
- );
2884
+ const claimLeafHash = tapLeafHash3(scriptFromTapLeafScript(vhtlcScript.claim()));
2992
2885
  for (let i = 0; i < finalTx.inputsLength; i++) {
2993
2886
  if (!verifySignatures(finalTx, i, [serverPubkeyHex], claimLeafHash)) {
2994
2887
  throw new Error("Invalid final Ark transaction");
@@ -2998,13 +2891,9 @@ var claimVHTLCwithOffchainTx = async (identity, vhtlcScript, serverXOnlyPublicKe
2998
2891
  signedCheckpointTxs.map(async (c, idx) => {
2999
2892
  const tx = Transaction5.fromPSBT(base643.decode(c));
3000
2893
  const checkpointLeaf = checkpoints[idx].getInput(0).tapLeafScript[0];
3001
- const cpLeafHash = tapLeafHash3(
3002
- scriptFromTapLeafScript(checkpointLeaf)
3003
- );
2894
+ const cpLeafHash = tapLeafHash3(scriptFromTapLeafScript(checkpointLeaf));
3004
2895
  if (!verifySignatures(tx, 0, [serverPubkeyHex], cpLeafHash)) {
3005
- throw new Error(
3006
- "Invalid server signature in checkpoint transaction"
3007
- );
2896
+ throw new Error("Invalid server signature in checkpoint transaction");
3008
2897
  }
3009
2898
  const signedCheckpoint = await identity.sign(tx, [0]);
3010
2899
  return base643.encode(signedCheckpoint.toPSBT());
@@ -3014,61 +2903,37 @@ var claimVHTLCwithOffchainTx = async (identity, vhtlcScript, serverXOnlyPublicKe
3014
2903
  };
3015
2904
  var refundVHTLCwithOffchainTx = async (swapId, identity, arkProvider, boltzXOnlyPublicKey, ourXOnlyPublicKey, serverXOnlyPublicKey, input, output, arkInfo, refundFunc) => {
3016
2905
  const rawCheckpointTapscript = hex7.decode(arkInfo.checkpointTapscript);
3017
- const serverUnrollScript = CSVMultisigTapscript2.decode(
3018
- rawCheckpointTapscript
2906
+ const serverUnrollScript = CSVMultisigTapscript2.decode(rawCheckpointTapscript);
2907
+ const { arkTx: unsignedRefundTx, checkpoints: checkpointPtxs } = buildOffchainTx(
2908
+ [input],
2909
+ [output],
2910
+ serverUnrollScript
3019
2911
  );
3020
- const { arkTx: unsignedRefundTx, checkpoints: checkpointPtxs } = buildOffchainTx([input], [output], serverUnrollScript);
3021
2912
  if (checkpointPtxs.length !== 1)
3022
- throw new Error(
3023
- `Expected one checkpoint transaction, got ${checkpointPtxs.length}`
3024
- );
2913
+ throw new Error(`Expected one checkpoint transaction, got ${checkpointPtxs.length}`);
3025
2914
  const unsignedCheckpointTx = checkpointPtxs[0];
3026
2915
  let boltzSignedRefundTx;
3027
2916
  let boltzSignedCheckpointTx;
3028
2917
  try {
3029
- const result = await refundFunc(
3030
- swapId,
3031
- unsignedRefundTx,
3032
- unsignedCheckpointTx
3033
- );
2918
+ const result = await refundFunc(swapId, unsignedRefundTx, unsignedCheckpointTx);
3034
2919
  boltzSignedRefundTx = result.transaction;
3035
2920
  boltzSignedCheckpointTx = result.checkpoint;
3036
2921
  } catch (error) {
3037
- throw new BoltzRefundError(
3038
- `Boltz rejected refund for swap ${swapId}`,
3039
- error
3040
- );
2922
+ throw new BoltzRefundError(`Boltz rejected refund for swap ${swapId}`, error);
3041
2923
  }
3042
2924
  const boltzXOnlyPublicKeyHex = hex7.encode(boltzXOnlyPublicKey);
3043
- const refundLeafHash = tapLeafHash3(
3044
- scriptFromTapLeafScript(input.tapLeafScript)
3045
- );
3046
- if (!verifySignatures(
3047
- boltzSignedRefundTx,
3048
- 0,
3049
- [boltzXOnlyPublicKeyHex],
3050
- refundLeafHash
3051
- )) {
2925
+ const refundLeafHash = tapLeafHash3(scriptFromTapLeafScript(input.tapLeafScript));
2926
+ if (!verifySignatures(boltzSignedRefundTx, 0, [boltzXOnlyPublicKeyHex], refundLeafHash)) {
3052
2927
  throw new Error("Invalid Boltz signature in refund transaction");
3053
2928
  }
3054
2929
  const checkpointLeaf = unsignedCheckpointTx.getInput(0).tapLeafScript[0];
3055
- const checkpointLeafHash = tapLeafHash3(
3056
- scriptFromTapLeafScript(checkpointLeaf)
3057
- );
3058
- if (!verifySignatures(
3059
- boltzSignedCheckpointTx,
3060
- 0,
3061
- [boltzXOnlyPublicKeyHex],
3062
- checkpointLeafHash
3063
- )) {
2930
+ const checkpointLeafHash = tapLeafHash3(scriptFromTapLeafScript(checkpointLeaf));
2931
+ if (!verifySignatures(boltzSignedCheckpointTx, 0, [boltzXOnlyPublicKeyHex], checkpointLeafHash)) {
3064
2932
  throw new Error("Invalid Boltz signature in checkpoint transaction");
3065
2933
  }
3066
2934
  const signedRefundTx = await identity.sign(unsignedRefundTx);
3067
2935
  const signedCheckpointTx = await identity.sign(unsignedCheckpointTx);
3068
- const combinedSignedRefundTx = combineTapscriptSigs(
3069
- boltzSignedRefundTx,
3070
- signedRefundTx
3071
- );
2936
+ const combinedSignedRefundTx = combineTapscriptSigs(boltzSignedRefundTx, signedRefundTx);
3072
2937
  const combinedSignedCheckpointTx = combineTapscriptSigs(
3073
2938
  boltzSignedCheckpointTx,
3074
2939
  signedCheckpointTx
@@ -3092,25 +2957,16 @@ var refundVHTLCwithOffchainTx = async (swapId, identity, arkProvider, boltzXOnly
3092
2957
  `Expected one signed checkpoint transaction, got ${signedCheckpointTxs.length}`
3093
2958
  );
3094
2959
  }
3095
- const serverSignedCheckpointTx = Transaction5.fromPSBT(
3096
- base643.decode(signedCheckpointTxs[0])
3097
- );
2960
+ const serverSignedCheckpointTx = Transaction5.fromPSBT(base643.decode(signedCheckpointTxs[0]));
3098
2961
  const serverPubkeyHex = hex7.encode(serverXOnlyPublicKey);
3099
- if (!verifySignatures(
3100
- serverSignedCheckpointTx,
3101
- 0,
3102
- [serverPubkeyHex],
3103
- checkpointLeafHash
3104
- )) {
2962
+ if (!verifySignatures(serverSignedCheckpointTx, 0, [serverPubkeyHex], checkpointLeafHash)) {
3105
2963
  throw new Error("Invalid server signature in checkpoint transaction");
3106
2964
  }
3107
2965
  const finalCheckpointTx = combineTapscriptSigs(
3108
2966
  combinedSignedCheckpointTx,
3109
2967
  serverSignedCheckpointTx
3110
2968
  );
3111
- await arkProvider.finalizeTx(arkTxid, [
3112
- base643.encode(finalCheckpointTx.toPSBT())
3113
- ]);
2969
+ await arkProvider.finalizeTx(arkTxid, [base643.encode(finalCheckpointTx.toPSBT())]);
3114
2970
  };
3115
2971
  function scriptFromTapLeafScript(leaf) {
3116
2972
  return leaf[1].subarray(0, leaf[1].length - 1);
@@ -3118,21 +2974,21 @@ function scriptFromTapLeafScript(leaf) {
3118
2974
 
3119
2975
  // src/arkade-swaps.ts
3120
2976
  var dedupeVtxos = (vtxos) => [
3121
- ...new Map(
3122
- vtxos.map((vtxo) => [`${vtxo.txid}:${vtxo.vout}`, vtxo])
3123
- ).values()
2977
+ ...new Map(vtxos.map((vtxo) => [`${vtxo.txid}:${vtxo.vout}`, vtxo])).values()
3124
2978
  ];
3125
2979
  var hasNonEmptyString = (value) => typeof value === "string" && value.length > 0;
3126
2980
  var canRecoverViaBoltz3of3 = (refundableVtxos, swap) => {
3127
2981
  const hasRequiredSwapMetadata = hasNonEmptyString(swap.id) && hasNonEmptyString(swap.request.refundPublicKey) && hasNonEmptyString(swap.response.address) && hasNonEmptyString(swap.response.claimPublicKey) && !!swap.response.timeoutBlockHeights;
3128
2982
  if (!hasRequiredSwapMetadata) return false;
3129
- return refundableVtxos.some(
3130
- (vtxo) => !vtxo.isSpent && !isRecoverable(vtxo)
3131
- );
2983
+ return refundableVtxos.some((vtxo) => !vtxo.isSpent && !isRecoverable(vtxo));
3132
2984
  };
3133
2985
  var isSubmarineRefundLocktimeReached = (refundTimestamp) => Math.floor(Date.now() / 1e3) >= refundTimestamp;
3134
2986
  var CLAIM_VTXO_RETRY_ATTEMPTS = 3;
3135
2987
  var CLAIM_VTXO_RETRY_DELAY_MS = 500;
2988
+ var quoteOptionsForSwap = (swap) => {
2989
+ const amount = swap.response?.claimDetails?.amount;
2990
+ return typeof amount === "number" ? { minAcceptableAmount: amount } : void 0;
2991
+ };
3136
2992
  var ArkadeSwaps = class _ArkadeSwaps {
3137
2993
  /** The Arkade wallet instance used for signing and address generation. */
3138
2994
  wallet;
@@ -3168,10 +3024,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
3168
3024
  return new _ArkadeSwaps(config);
3169
3025
  }
3170
3026
  const arkProvider = config.arkProvider ?? config.wallet.arkProvider;
3171
- if (!arkProvider)
3172
- throw new Error(
3173
- "Ark provider is required either in wallet or config."
3174
- );
3027
+ if (!arkProvider) throw new Error("Ark provider is required either in wallet or config.");
3175
3028
  const arkInfo = await arkProvider.getInfo();
3176
3029
  const network = arkInfo.network;
3177
3030
  const swapProvider = new BoltzSwapProvider({ network });
@@ -3182,16 +3035,11 @@ var ArkadeSwaps = class _ArkadeSwaps {
3182
3035
  if (!config.swapProvider) throw new Error("Swap provider is required.");
3183
3036
  this.wallet = config.wallet;
3184
3037
  const arkProvider = config.arkProvider ?? config.wallet.arkProvider;
3185
- if (!arkProvider)
3186
- throw new Error(
3187
- "Ark provider is required either in wallet or config."
3188
- );
3038
+ if (!arkProvider) throw new Error("Ark provider is required either in wallet or config.");
3189
3039
  this.arkProvider = arkProvider;
3190
3040
  const indexerProvider = config.indexerProvider ?? config.wallet.indexerProvider;
3191
3041
  if (!indexerProvider)
3192
- throw new Error(
3193
- "Indexer provider is required either in wallet or config."
3194
- );
3042
+ throw new Error("Indexer provider is required either in wallet or config.");
3195
3043
  this.indexerProvider = indexerProvider;
3196
3044
  this.swapProvider = config.swapProvider;
3197
3045
  if (config.swapRepository) {
@@ -3202,10 +3050,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
3202
3050
  if (config.swapManager !== false) {
3203
3051
  const swapManagerConfig = !config.swapManager || config.swapManager === true ? {} : config.swapManager;
3204
3052
  const shouldAutostart = swapManagerConfig.autoStart ?? true;
3205
- this.swapManager = new SwapManager(
3206
- this.swapProvider,
3207
- swapManagerConfig
3208
- );
3053
+ this.swapManager = new SwapManager(this.swapProvider, swapManagerConfig);
3209
3054
  this.swapManager.setCallbacks({
3210
3055
  claim: async (swap) => {
3211
3056
  await this.claimVHTLC(swap);
@@ -3353,19 +3198,15 @@ var ArkadeSwaps = class _ArkadeSwaps {
3353
3198
  * @throws {SwapError} If amount is <= 0 or key retrieval fails.
3354
3199
  */
3355
3200
  async createReverseSwap(args) {
3356
- if (args.amount <= 0)
3357
- throw new SwapError({ message: "Amount must be greater than 0" });
3358
- const claimPublicKey = hex8.encode(
3359
- await this.wallet.identity.compressedPublicKey()
3360
- );
3201
+ if (args.amount <= 0) throw new SwapError({ message: "Amount must be greater than 0" });
3202
+ const claimPublicKey = hex8.encode(await this.wallet.identity.compressedPublicKey());
3361
3203
  if (!claimPublicKey)
3362
3204
  throw new SwapError({
3363
3205
  message: "Failed to get claim public key from wallet"
3364
3206
  });
3365
3207
  const preimage = randomBytes(32);
3366
3208
  const preimageHash = hex8.encode(sha2563(preimage));
3367
- if (!preimageHash)
3368
- throw new SwapError({ message: "Failed to get preimage hash" });
3209
+ if (!preimageHash) throw new SwapError({ message: "Failed to get preimage hash" });
3369
3210
  const swapRequest = {
3370
3211
  invoiceAmount: args.amount,
3371
3212
  claimPublicKey,
@@ -3395,18 +3236,14 @@ var ArkadeSwaps = class _ArkadeSwaps {
3395
3236
  */
3396
3237
  async claimVHTLC(pendingSwap) {
3397
3238
  if (!pendingSwap.preimage)
3398
- throw new Error(
3399
- `Swap ${pendingSwap.id}: preimage is required to claim VHTLC`
3400
- );
3239
+ throw new Error(`Swap ${pendingSwap.id}: preimage is required to claim VHTLC`);
3401
3240
  const {
3402
3241
  refundPublicKey,
3403
3242
  lockupAddress,
3404
3243
  timeoutBlockHeights: vhtlcTimeouts
3405
3244
  } = pendingSwap.response;
3406
3245
  if (!refundPublicKey || !lockupAddress || !vhtlcTimeouts)
3407
- throw new Error(
3408
- `Swap ${pendingSwap.id}: incomplete reverse swap response`
3409
- );
3246
+ throw new Error(`Swap ${pendingSwap.id}: incomplete reverse swap response`);
3410
3247
  const preimage = hex8.decode(pendingSwap.preimage);
3411
3248
  const arkInfo = await this.arkProvider.getInfo();
3412
3249
  const address = await this.wallet.getAddress();
@@ -3451,15 +3288,11 @@ var ArkadeSwaps = class _ArkadeSwaps {
3451
3288
  break;
3452
3289
  }
3453
3290
  if (attempt < CLAIM_VTXO_RETRY_ATTEMPTS) {
3454
- await new Promise(
3455
- (resolve) => setTimeout(resolve, CLAIM_VTXO_RETRY_DELAY_MS)
3456
- );
3291
+ await new Promise((resolve) => setTimeout(resolve, CLAIM_VTXO_RETRY_DELAY_MS));
3457
3292
  }
3458
3293
  }
3459
3294
  if (!vtxo) {
3460
- throw new Error(
3461
- `Swap ${pendingSwap.id}: no spendable virtual coins found`
3462
- );
3295
+ throw new Error(`Swap ${pendingSwap.id}: no spendable virtual coins found`);
3463
3296
  }
3464
3297
  if (vtxo.isSpent) {
3465
3298
  throw new Error(`Swap ${pendingSwap.id}: VHTLC is already spent`);
@@ -3473,10 +3306,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
3473
3306
  amount: BigInt(vtxo.value),
3474
3307
  script: ArkAddress2.decode(address).pkScript
3475
3308
  };
3476
- const vhtlcIdentity = claimVHTLCIdentity(
3477
- this.wallet.identity,
3478
- preimage
3479
- );
3309
+ const vhtlcIdentity = claimVHTLCIdentity(this.wallet.identity, preimage);
3480
3310
  let finalStatus;
3481
3311
  if (isRecoverable(vtxo)) {
3482
3312
  await this.joinBatch(vhtlcIdentity, input, output, arkInfo);
@@ -3595,9 +3425,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
3595
3425
  async sendLightningPayment(args) {
3596
3426
  const pendingSwap = await this.createSubmarineSwap(args);
3597
3427
  if (!pendingSwap.response.address)
3598
- throw new Error(
3599
- `Swap ${pendingSwap.id}: missing address in submarine swap response`
3600
- );
3428
+ throw new Error(`Swap ${pendingSwap.id}: missing address in submarine swap response`);
3601
3429
  await this.savePendingSubmarineSwap(pendingSwap);
3602
3430
  const txid = await this.wallet.send({
3603
3431
  address: pendingSwap.response.address,
@@ -3630,9 +3458,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
3630
3458
  * @throws {SwapError} If invoice is missing or key retrieval fails.
3631
3459
  */
3632
3460
  async createSubmarineSwap(args) {
3633
- const refundPublicKey = hex8.encode(
3634
- await this.wallet.identity.compressedPublicKey()
3635
- );
3461
+ const refundPublicKey = hex8.encode(await this.wallet.identity.compressedPublicKey());
3636
3462
  if (!refundPublicKey)
3637
3463
  throw new SwapError({
3638
3464
  message: "Failed to get refund public key from wallet"
@@ -3670,9 +3496,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
3670
3496
  async buildSubmarineVHTLCContext(swap, arkInfo) {
3671
3497
  const preimageHash = swap.request.invoice ? getInvoicePaymentHash(swap.request.invoice) : swap.preimageHash;
3672
3498
  if (!preimageHash)
3673
- throw new Error(
3674
- `Swap ${swap.id}: preimage hash is required to refund VHTLC`
3675
- );
3499
+ throw new Error(`Swap ${swap.id}: preimage hash is required to refund VHTLC`);
3676
3500
  const resolvedArkInfo = arkInfo ?? await this.arkProvider.getInfo();
3677
3501
  const ourXOnlyPublicKey = normalizeToXOnlyKey(
3678
3502
  await this.wallet.identity.xOnlyPublicKey(),
@@ -3686,9 +3510,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
3686
3510
  );
3687
3511
  const { claimPublicKey, timeoutBlockHeights: vhtlcTimeouts } = swap.response;
3688
3512
  if (!claimPublicKey || !vhtlcTimeouts)
3689
- throw new Error(
3690
- `Swap ${swap.id}: incomplete submarine swap response`
3691
- );
3513
+ throw new Error(`Swap ${swap.id}: incomplete submarine swap response`);
3692
3514
  const boltzXOnlyPublicKey = normalizeToXOnlyKey(
3693
3515
  hex8.decode(claimPublicKey),
3694
3516
  "boltz",
@@ -3703,9 +3525,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
3703
3525
  timeoutBlockHeights: vhtlcTimeouts
3704
3526
  });
3705
3527
  if (!vhtlcScript.claimScript)
3706
- throw new Error(
3707
- `Swap ${swap.id}: failed to create VHTLC script for submarine swap`
3708
- );
3528
+ throw new Error(`Swap ${swap.id}: failed to create VHTLC script for submarine swap`);
3709
3529
  if (vhtlcAddress !== swap.response.address)
3710
3530
  throw new Error(
3711
3531
  `VHTLC address mismatch for swap ${swap.id}: expected ${swap.response.address}, got ${vhtlcAddress}`
@@ -3744,10 +3564,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
3744
3564
  recoverableOnly: true
3745
3565
  })
3746
3566
  ]);
3747
- const refundableVtxos = dedupeVtxos([
3748
- ...spendableResult.vtxos,
3749
- ...recoverableResult.vtxos
3750
- ]);
3567
+ const refundableVtxos = dedupeVtxos([...spendableResult.vtxos, ...recoverableResult.vtxos]);
3751
3568
  let diagnostic;
3752
3569
  if (refundableVtxos.length === 0) {
3753
3570
  const { vtxos: allVtxos } = await this.indexerProvider.getVtxos({
@@ -3767,13 +3584,8 @@ var ArkadeSwaps = class _ArkadeSwaps {
3767
3584
  submarineRecoveryInfoFromLookup(swap, lookup) {
3768
3585
  const { refundableVtxos, diagnostic, vhtlcTimeouts } = lookup;
3769
3586
  if (refundableVtxos.length > 0) {
3770
- const cltvSatisfied = isSubmarineRefundLocktimeReached(
3771
- vhtlcTimeouts.refund
3772
- );
3773
- const amountSats = refundableVtxos.reduce(
3774
- (sum, vtxo) => sum + Number(vtxo.value),
3775
- 0
3776
- );
3587
+ const cltvSatisfied = isSubmarineRefundLocktimeReached(vhtlcTimeouts.refund);
3588
+ const amountSats = refundableVtxos.reduce((sum, vtxo) => sum + Number(vtxo.value), 0);
3777
3589
  const isRecoverable2 = cltvSatisfied || canRecoverViaBoltz3of3(refundableVtxos, swap);
3778
3590
  return {
3779
3591
  swap,
@@ -3837,19 +3649,13 @@ var ArkadeSwaps = class _ArkadeSwaps {
3837
3649
  );
3838
3650
  }
3839
3651
  if (diagnostic.allSpent) {
3840
- throw new Error(
3841
- `Swap ${pendingSwap.id}: VHTLC is already spent`
3842
- );
3652
+ throw new Error(`Swap ${pendingSwap.id}: VHTLC is already spent`);
3843
3653
  }
3844
- throw new Error(
3845
- `Swap ${pendingSwap.id}: VHTLC has no refundable VTXOs yet`
3846
- );
3654
+ throw new Error(`Swap ${pendingSwap.id}: VHTLC has no refundable VTXOs yet`);
3847
3655
  }
3848
3656
  const outputScript = ArkAddress2.decode(address).pkScript;
3849
3657
  const refundWithoutReceiverLeaf = vhtlcScript.refundWithoutReceiver();
3850
- const cltvSatisfied = isSubmarineRefundLocktimeReached(
3851
- vhtlcTimeouts.refund
3852
- );
3658
+ const cltvSatisfied = isSubmarineRefundLocktimeReached(vhtlcTimeouts.refund);
3853
3659
  let boltzCallCount = 0;
3854
3660
  let sweptCount = 0;
3855
3661
  let skippedCount = 0;
@@ -3901,9 +3707,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
3901
3707
  input,
3902
3708
  output,
3903
3709
  arkInfo,
3904
- this.swapProvider.refundSubmarineSwap.bind(
3905
- this.swapProvider
3906
- )
3710
+ this.swapProvider.refundSubmarineSwap.bind(this.swapProvider)
3907
3711
  );
3908
3712
  boltzCallCount++;
3909
3713
  sweptCount++;
@@ -3926,13 +3730,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
3926
3730
  tapLeafScript: refundWithoutReceiverLeaf,
3927
3731
  tapTree: vhtlcScript.encode()
3928
3732
  };
3929
- await this.joinBatch(
3930
- this.wallet.identity,
3931
- fallbackInput,
3932
- output,
3933
- arkInfo,
3934
- false
3935
- );
3733
+ await this.joinBatch(this.wallet.identity, fallbackInput, output, arkInfo, false);
3936
3734
  sweptCount++;
3937
3735
  }
3938
3736
  }
@@ -4028,10 +3826,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
4028
3826
  try {
4029
3827
  return {
4030
3828
  swap,
4031
- context: await this.buildSubmarineVHTLCContext(
4032
- swap,
4033
- arkInfo
4034
- )
3829
+ context: await this.buildSubmarineVHTLCContext(swap, arkInfo)
4035
3830
  };
4036
3831
  } catch (err) {
4037
3832
  return {
@@ -4044,9 +3839,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
4044
3839
  const valid = prepared.filter(
4045
3840
  (item) => "context" in item
4046
3841
  );
4047
- const scripts = [
4048
- ...new Set(valid.map(({ context }) => context.vhtlcPkScriptHex))
4049
- ];
3842
+ const scripts = [...new Set(valid.map(({ context }) => context.vhtlcPkScriptHex))];
4050
3843
  const refundableByScript = /* @__PURE__ */ new Map();
4051
3844
  if (scripts.length > 0) {
4052
3845
  const [spendableResult, recoverableResult] = await Promise.all([
@@ -4081,9 +3874,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
4081
3874
  error: item.error
4082
3875
  };
4083
3876
  }
4084
- const refundableVtxos = refundableByScript.get(
4085
- item.context.vhtlcPkScriptHex.toLowerCase()
4086
- ) ?? [];
3877
+ const refundableVtxos = refundableByScript.get(item.context.vhtlcPkScriptHex.toLowerCase()) ?? [];
4087
3878
  return this.submarineRecoveryInfoFromLookup(item.swap, {
4088
3879
  ...item.context,
4089
3880
  refundableVtxos
@@ -4262,9 +4053,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
4262
4053
  */
4263
4054
  async waitAndClaimBtc(pendingSwap) {
4264
4055
  if (this.swapManager && await this.swapManager.hasSwap(pendingSwap.id)) {
4265
- const { txid } = await this.swapManager.waitForSwapCompletion(
4266
- pendingSwap.id
4267
- );
4056
+ const { txid } = await this.swapManager.waitForSwapCompletion(pendingSwap.id);
4268
4057
  return { txid };
4269
4058
  }
4270
4059
  return new Promise((resolve, reject) => {
@@ -4291,24 +4080,25 @@ var ArkadeSwaps = class _ArkadeSwaps {
4291
4080
  }
4292
4081
  case "transaction.claimed":
4293
4082
  await updateSwapStatus();
4294
- const claimedStatus = await this.getSwapStatus(
4295
- pendingSwap.id
4296
- );
4083
+ const claimedStatus = await this.getSwapStatus(pendingSwap.id);
4297
4084
  resolve({
4298
4085
  txid: claimedStatus.transaction?.id ?? ""
4299
4086
  });
4300
4087
  break;
4301
4088
  case "transaction.lockupFailed":
4302
4089
  await updateSwapStatus();
4303
- await this.quoteSwap(swap.response.id).catch((err) => {
4304
- reject(
4305
- new SwapError({
4306
- message: `Failed to renegotiate quote: ${err.message}`,
4307
- isRefundable: true,
4308
- pendingSwap: swap
4309
- })
4310
- );
4311
- });
4090
+ await this.quoteSwap(swap.response.id, quoteOptionsForSwap(swap)).catch(
4091
+ (err) => {
4092
+ reject(
4093
+ new SwapError({
4094
+ message: `Failed to renegotiate quote: ${err.message}`,
4095
+ isRefundable: true,
4096
+ pendingSwap: swap,
4097
+ cause: err
4098
+ })
4099
+ );
4100
+ }
4101
+ );
4312
4102
  break;
4313
4103
  case "swap.expired":
4314
4104
  await updateSwapStatus();
@@ -4346,30 +4136,18 @@ var ArkadeSwaps = class _ArkadeSwaps {
4346
4136
  */
4347
4137
  async claimBtc(pendingSwap) {
4348
4138
  if (!pendingSwap.toAddress)
4349
- throw new Error(
4350
- `Swap ${pendingSwap.id}: destination address is required`
4351
- );
4139
+ throw new Error(`Swap ${pendingSwap.id}: destination address is required`);
4352
4140
  if (!pendingSwap.response.claimDetails.swapTree)
4353
- throw new Error(
4354
- `Swap ${pendingSwap.id}: missing swap tree in claim details`
4355
- );
4141
+ throw new Error(`Swap ${pendingSwap.id}: missing swap tree in claim details`);
4356
4142
  if (!pendingSwap.response.claimDetails.serverPublicKey)
4357
- throw new Error(
4358
- `Swap ${pendingSwap.id}: missing server public key in claim details`
4359
- );
4143
+ throw new Error(`Swap ${pendingSwap.id}: missing server public key in claim details`);
4360
4144
  const swapStatus = await this.getSwapStatus(pendingSwap.id);
4361
4145
  if (!swapStatus.transaction?.hex)
4362
- throw new Error(
4363
- `Swap ${pendingSwap.id}: BTC transaction hex is required`
4364
- );
4365
- const lockupTx = Transaction6.fromRaw(
4366
- hex8.decode(swapStatus.transaction.hex)
4367
- );
4146
+ throw new Error(`Swap ${pendingSwap.id}: BTC transaction hex is required`);
4147
+ const lockupTx = Transaction6.fromRaw(hex8.decode(swapStatus.transaction.hex));
4368
4148
  const arkInfo = await this.arkProvider.getInfo();
4369
4149
  const network = arkInfo.network === "bitcoin" ? NETWORK : arkInfo.network === "mutinynet" ? MUTINYNET_NETWORK : REGTEST_NETWORK;
4370
- const swapTree = deserializeSwapTree(
4371
- pendingSwap.response.claimDetails.swapTree
4372
- );
4150
+ const swapTree = deserializeSwapTree(pendingSwap.response.claimDetails.swapTree);
4373
4151
  const musig = tweakMusig(
4374
4152
  create(hex8.decode(pendingSwap.ephemeralKey), [
4375
4153
  hex8.decode(pendingSwap.response.claimDetails.serverPublicKey),
@@ -4390,19 +4168,14 @@ var ArkadeSwaps = class _ArkadeSwaps {
4390
4168
  vout: swapOutput.vout,
4391
4169
  transactionId: lockupTx.id
4392
4170
  },
4393
- OutScript2.encode(
4394
- Address2(network).decode(pendingSwap.toAddress)
4395
- ),
4171
+ OutScript2.encode(Address2(network).decode(pendingSwap.toAddress)),
4396
4172
  feeToDeliverExactAmount > fee ? feeToDeliverExactAmount : fee
4397
4173
  )
4398
4174
  );
4399
4175
  const musigMessage = musig.message(
4400
- claimTx.preimageWitnessV1(
4401
- 0,
4402
- [swapOutput.script],
4403
- SigHash2.DEFAULT,
4404
- [swapOutput.amount]
4405
- )
4176
+ claimTx.preimageWitnessV1(0, [swapOutput.script], SigHash2.DEFAULT, [
4177
+ swapOutput.amount
4178
+ ])
4406
4179
  ).generateNonce();
4407
4180
  const signedTxData = await this.swapProvider.postChainClaimDetails(
4408
4181
  pendingSwap.response.id,
@@ -4416,14 +4189,10 @@ var ArkadeSwaps = class _ArkadeSwaps {
4416
4189
  }
4417
4190
  );
4418
4191
  if (!signedTxData.pubNonce || !signedTxData.partialSignature)
4419
- throw new Error(
4420
- `Swap ${pendingSwap.id}: invalid signature data from server`
4421
- );
4192
+ throw new Error(`Swap ${pendingSwap.id}: invalid signature data from server`);
4422
4193
  const musigSession = musigMessage.aggregateNonces([
4423
4194
  [
4424
- hex8.decode(
4425
- pendingSwap.response.claimDetails.serverPublicKey
4426
- ),
4195
+ hex8.decode(pendingSwap.response.claimDetails.serverPublicKey),
4427
4196
  hex8.decode(signedTxData.pubNonce)
4428
4197
  ]
4429
4198
  ]).initializeSession();
@@ -4443,13 +4212,9 @@ var ArkadeSwaps = class _ArkadeSwaps {
4443
4212
  */
4444
4213
  async refundArk(pendingSwap) {
4445
4214
  if (!pendingSwap.response.lockupDetails.serverPublicKey)
4446
- throw new Error(
4447
- `Swap ${pendingSwap.id}: missing server public key in lockup details`
4448
- );
4215
+ throw new Error(`Swap ${pendingSwap.id}: missing server public key in lockup details`);
4449
4216
  if (!pendingSwap.response.lockupDetails.timeouts)
4450
- throw new Error(
4451
- `Swap ${pendingSwap.id}: missing timeouts in lockup details`
4452
- );
4217
+ throw new Error(`Swap ${pendingSwap.id}: missing timeouts in lockup details`);
4453
4218
  const arkInfo = await this.arkProvider.getInfo();
4454
4219
  const address = await this.wallet.getAddress();
4455
4220
  const ourXOnlyPublicKey = normalizeToXOnlyKey(
@@ -4491,9 +4256,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
4491
4256
  timeoutBlockHeights: pendingSwap.response.lockupDetails.timeouts
4492
4257
  });
4493
4258
  if (!vhtlcScript.refundScript)
4494
- throw new Error(
4495
- `Swap ${pendingSwap.id}: failed to create VHTLC script for chain swap`
4496
- );
4259
+ throw new Error(`Swap ${pendingSwap.id}: failed to create VHTLC script for chain swap`);
4497
4260
  if (pendingSwap.response.lockupDetails.lockupAddress !== vhtlcAddress) {
4498
4261
  throw new SwapError({
4499
4262
  message: "Unable to claim: invalid VHTLC address"
@@ -4574,9 +4337,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
4574
4337
  */
4575
4338
  async waitAndClaimArk(pendingSwap) {
4576
4339
  if (this.swapManager && await this.swapManager.hasSwap(pendingSwap.id)) {
4577
- const { txid } = await this.swapManager.waitForSwapCompletion(
4578
- pendingSwap.id
4579
- );
4340
+ const { txid } = await this.swapManager.waitForSwapCompletion(pendingSwap.id);
4580
4341
  return { txid };
4581
4342
  }
4582
4343
  return new Promise((resolve, reject) => {
@@ -4597,37 +4358,33 @@ var ArkadeSwaps = class _ArkadeSwaps {
4597
4358
  break;
4598
4359
  case "transaction.claimed":
4599
4360
  await updateSwapStatus();
4600
- const claimedStatus = await this.getSwapStatus(
4601
- pendingSwap.id
4602
- );
4361
+ const claimedStatus = await this.getSwapStatus(pendingSwap.id);
4603
4362
  resolve({
4604
4363
  txid: claimedStatus.transaction?.id ?? ""
4605
4364
  });
4606
4365
  break;
4607
4366
  case "transaction.claim.pending":
4608
4367
  await updateSwapStatus();
4609
- await this.signCooperativeClaimForServer(swap).catch(
4368
+ await this.signCooperativeClaimForServer(swap).catch((err) => {
4369
+ logger.error(`Failed to sign cooperative claim for ${swap.id}:`, err);
4370
+ });
4371
+ break;
4372
+ case "transaction.lockupFailed":
4373
+ await updateSwapStatus();
4374
+ await this.quoteSwap(swap.response.id, quoteOptionsForSwap(swap)).catch(
4610
4375
  (err) => {
4611
- logger.error(
4612
- `Failed to sign cooperative claim for ${swap.id}:`,
4613
- err
4376
+ reject(
4377
+ new SwapError({
4378
+ message: `Failed to renegotiate quote: ${err.message}`,
4379
+ isRefundable: false,
4380
+ // TODO btc refund not implemented yet
4381
+ pendingSwap: swap,
4382
+ cause: err
4383
+ })
4614
4384
  );
4615
4385
  }
4616
4386
  );
4617
4387
  break;
4618
- case "transaction.lockupFailed":
4619
- await updateSwapStatus();
4620
- await this.quoteSwap(swap.response.id).catch((err) => {
4621
- reject(
4622
- new SwapError({
4623
- message: `Failed to renegotiate quote: ${err.message}`,
4624
- isRefundable: false,
4625
- // TODO btc refund not implemented yet
4626
- pendingSwap: swap
4627
- })
4628
- );
4629
- });
4630
- break;
4631
4388
  case "swap.expired":
4632
4389
  await updateSwapStatus();
4633
4390
  reject(
@@ -4667,17 +4424,11 @@ var ArkadeSwaps = class _ArkadeSwaps {
4667
4424
  */
4668
4425
  async claimArk(pendingSwap) {
4669
4426
  if (!pendingSwap.toAddress)
4670
- throw new Error(
4671
- `Swap ${pendingSwap.id}: destination address is required`
4672
- );
4427
+ throw new Error(`Swap ${pendingSwap.id}: destination address is required`);
4673
4428
  if (!pendingSwap.response.claimDetails.serverPublicKey)
4674
- throw new Error(
4675
- `Swap ${pendingSwap.id}: missing server public key in claim details`
4676
- );
4429
+ throw new Error(`Swap ${pendingSwap.id}: missing server public key in claim details`);
4677
4430
  if (!pendingSwap.response.claimDetails.timeouts)
4678
- throw new Error(
4679
- `Swap ${pendingSwap.id}: missing timeouts in claim details`
4680
- );
4431
+ throw new Error(`Swap ${pendingSwap.id}: missing timeouts in claim details`);
4681
4432
  const arkInfo = await this.arkProvider.getInfo();
4682
4433
  const preimage = hex8.decode(pendingSwap.preimage);
4683
4434
  const address = await this.wallet.getAddress();
@@ -4689,10 +4440,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
4689
4440
  pendingSwap.response.claimDetails.serverPublicKey,
4690
4441
  "sender"
4691
4442
  );
4692
- const serverXOnlyPublicKey = normalizeToXOnlyKey(
4693
- arkInfo.signerPubkey,
4694
- "server"
4695
- );
4443
+ const serverXOnlyPublicKey = normalizeToXOnlyKey(arkInfo.signerPubkey, "server");
4696
4444
  const { vhtlcAddress, vhtlcScript } = this.createVHTLCScript({
4697
4445
  network: arkInfo.network,
4698
4446
  preimageHash: hex8.decode(pendingSwap.request.preimageHash),
@@ -4702,9 +4450,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
4702
4450
  timeoutBlockHeights: pendingSwap.response.claimDetails.timeouts
4703
4451
  });
4704
4452
  if (!vhtlcScript.claimScript)
4705
- throw new Error(
4706
- `Swap ${pendingSwap.id}: failed to create VHTLC script for chain swap`
4707
- );
4453
+ throw new Error(`Swap ${pendingSwap.id}: failed to create VHTLC script for chain swap`);
4708
4454
  if (pendingSwap.response.claimDetails.lockupAddress !== vhtlcAddress) {
4709
4455
  throw new SwapError({
4710
4456
  message: "Unable to claim: invalid VHTLC address"
@@ -4721,15 +4467,11 @@ var ArkadeSwaps = class _ArkadeSwaps {
4721
4467
  break;
4722
4468
  }
4723
4469
  if (attempt < CLAIM_VTXO_RETRY_ATTEMPTS) {
4724
- await new Promise(
4725
- (resolve) => setTimeout(resolve, CLAIM_VTXO_RETRY_DELAY_MS)
4726
- );
4470
+ await new Promise((resolve) => setTimeout(resolve, CLAIM_VTXO_RETRY_DELAY_MS));
4727
4471
  }
4728
4472
  }
4729
4473
  if (!vtxo) {
4730
- throw new Error(
4731
- `Swap ${pendingSwap.id}: no spendable virtual coins found`
4732
- );
4474
+ throw new Error(`Swap ${pendingSwap.id}: no spendable virtual coins found`);
4733
4475
  }
4734
4476
  const input = {
4735
4477
  ...vtxo,
@@ -4740,10 +4482,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
4740
4482
  amount: BigInt(vtxo.value),
4741
4483
  script: ArkAddress2.decode(address).pkScript
4742
4484
  };
4743
- const vhtlcIdentity = claimVHTLCIdentity(
4744
- this.wallet.identity,
4745
- preimage
4746
- );
4485
+ const vhtlcIdentity = claimVHTLCIdentity(this.wallet.identity, preimage);
4747
4486
  if (isRecoverable(vtxo)) {
4748
4487
  await this.joinBatch(vhtlcIdentity, input, output, arkInfo);
4749
4488
  } else {
@@ -4769,16 +4508,10 @@ var ArkadeSwaps = class _ArkadeSwaps {
4769
4508
  */
4770
4509
  async signCooperativeClaimForServer(pendingSwap) {
4771
4510
  if (!pendingSwap.response.lockupDetails.swapTree)
4772
- throw new Error(
4773
- `Swap ${pendingSwap.id}: missing swap tree in lockup details`
4774
- );
4511
+ throw new Error(`Swap ${pendingSwap.id}: missing swap tree in lockup details`);
4775
4512
  if (!pendingSwap.response.lockupDetails.serverPublicKey)
4776
- throw new Error(
4777
- `Swap ${pendingSwap.id}: missing server public key in lockup details`
4778
- );
4779
- const claimDetails = await this.swapProvider.getChainClaimDetails(
4780
- pendingSwap.id
4781
- );
4513
+ throw new Error(`Swap ${pendingSwap.id}: missing server public key in lockup details`);
4514
+ const claimDetails = await this.swapProvider.getChainClaimDetails(pendingSwap.id);
4782
4515
  const serverPubKey = pendingSwap.response.lockupDetails.serverPublicKey;
4783
4516
  if (claimDetails.publicKey !== serverPubKey) {
4784
4517
  throw new Error(
@@ -4794,9 +4527,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
4794
4527
  );
4795
4528
  const musigNonces = musig.message(hex8.decode(claimDetails.transactionHash)).generateNonce().aggregateNonces([
4796
4529
  [
4797
- hex8.decode(
4798
- pendingSwap.response.lockupDetails.serverPublicKey
4799
- ),
4530
+ hex8.decode(pendingSwap.response.lockupDetails.serverPublicKey),
4800
4531
  hex8.decode(claimDetails.pubNonce)
4801
4532
  ]
4802
4533
  ]).initializeSession();
@@ -4815,10 +4546,8 @@ var ArkadeSwaps = class _ArkadeSwaps {
4815
4546
  * @returns The transaction ID of the claim.
4816
4547
  */
4817
4548
  async waitAndClaimChain(pendingSwap) {
4818
- if (pendingSwap.request.to === "ARK")
4819
- return this.waitAndClaimArk(pendingSwap);
4820
- if (pendingSwap.request.to === "BTC")
4821
- return this.waitAndClaimBtc(pendingSwap);
4549
+ if (pendingSwap.request.to === "ARK") return this.waitAndClaimArk(pendingSwap);
4550
+ if (pendingSwap.request.to === "BTC") return this.waitAndClaimBtc(pendingSwap);
4822
4551
  throw new SwapError({
4823
4552
  message: `Unsupported swap destination: ${pendingSwap.request.to}`
4824
4553
  });
@@ -4833,11 +4562,9 @@ var ArkadeSwaps = class _ArkadeSwaps {
4833
4562
  */
4834
4563
  async createChainSwap(args) {
4835
4564
  const { to, from, receiverLockAmount, senderLockAmount, toAddress } = args;
4836
- if (!toAddress)
4837
- throw new SwapError({ message: "Destination address is required" });
4565
+ if (!toAddress) throw new SwapError({ message: "Destination address is required" });
4838
4566
  const feeSatsPerByte = args.feeSatsPerByte ?? 1;
4839
- if (feeSatsPerByte <= 0)
4840
- throw new SwapError({ message: "Invalid feeSatsPerByte" });
4567
+ if (feeSatsPerByte <= 0) throw new SwapError({ message: "Invalid feeSatsPerByte" });
4841
4568
  let amount, serverLockAmount, userLockAmount;
4842
4569
  if (receiverLockAmount) {
4843
4570
  amount = receiverLockAmount;
@@ -4852,8 +4579,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
4852
4579
  }
4853
4580
  const preimage = randomBytes(32);
4854
4581
  const preimageHash = hex8.encode(sha2563(preimage));
4855
- if (!preimageHash)
4856
- throw new SwapError({ message: "Failed to get preimage hash" });
4582
+ if (!preimageHash) throw new SwapError({ message: "Failed to get preimage hash" });
4857
4583
  const ephemeralKey = secp256k12.utils.randomSecretKey();
4858
4584
  const refundPublicKey = to === "ARK" ? hex8.encode(secp256k12.getPublicKey(ephemeralKey)) : hex8.encode(await this.wallet.identity.compressedPublicKey());
4859
4585
  if (!refundPublicKey)
@@ -4902,30 +4628,20 @@ var ArkadeSwaps = class _ArkadeSwaps {
4902
4628
  const { to, from, swap, arkInfo } = args;
4903
4629
  if (from === "ARK") {
4904
4630
  if (!swap.response.lockupDetails.serverPublicKey)
4905
- throw new Error(
4906
- `Swap ${swap.id}: missing serverPublicKey in lockup details`
4907
- );
4631
+ throw new Error(`Swap ${swap.id}: missing serverPublicKey in lockup details`);
4908
4632
  if (!swap.response.lockupDetails.timeouts)
4909
- throw new Error(
4910
- `Swap ${swap.id}: missing timeouts in lockup details`
4911
- );
4633
+ throw new Error(`Swap ${swap.id}: missing timeouts in lockup details`);
4912
4634
  }
4913
4635
  if (to === "ARK") {
4914
4636
  if (!swap.response.claimDetails.serverPublicKey)
4915
- throw new Error(
4916
- `Swap ${swap.id}: missing serverPublicKey in claim details`
4917
- );
4637
+ throw new Error(`Swap ${swap.id}: missing serverPublicKey in claim details`);
4918
4638
  if (!swap.response.claimDetails.timeouts)
4919
- throw new Error(
4920
- `Swap ${swap.id}: missing timeouts in claim details`
4921
- );
4639
+ throw new Error(`Swap ${swap.id}: missing timeouts in claim details`);
4922
4640
  }
4923
4641
  const lockupAddress = to === "ARK" ? swap.response.claimDetails.lockupAddress : swap.response.lockupDetails.lockupAddress;
4924
4642
  const receiverPubkey = to === "ARK" ? swap.request.claimPublicKey : swap.response.lockupDetails.serverPublicKey;
4925
4643
  const senderPubkey = to === "ARK" ? swap.response.claimDetails.serverPublicKey : swap.request.refundPublicKey;
4926
- const serverPubkey = hex8.encode(
4927
- normalizeToXOnlyKey(arkInfo.signerPubkey, "server")
4928
- );
4644
+ const serverPubkey = hex8.encode(normalizeToXOnlyKey(arkInfo.signerPubkey, "server"));
4929
4645
  const vhtlcTimeouts = to === "ARK" ? swap.response.claimDetails.timeouts : swap.response.lockupDetails.timeouts;
4930
4646
  const { vhtlcAddress } = this.createVHTLCScript({
4931
4647
  network: arkInfo.network,
@@ -4943,15 +4659,110 @@ var ArkadeSwaps = class _ArkadeSwaps {
4943
4659
  return true;
4944
4660
  }
4945
4661
  /**
4946
- * Renegotiates the quote for an existing swap.
4662
+ * Renegotiates the quote for an existing chain swap. Convenience wrapper
4663
+ * over `getSwapQuote` + `acceptSwapQuote` with a safety floor.
4664
+ *
4665
+ * The floor is resolved in order:
4666
+ * 1. `options.minAcceptableAmount` if provided.
4667
+ * 2. The original `response.claimDetails.amount` of the stored
4668
+ * pending swap (Boltz-confirmed server-lock amount at creation).
4669
+ * 3. Otherwise throws `QuoteRejectedError({ reason: "no_baseline" })`.
4670
+ *
4671
+ * `options.maxSlippageBps` (default 0) relaxes the floor by basis points.
4672
+ * Quotes ≤ 0 are always rejected. On rejection the acceptance is NOT
4673
+ * posted to Boltz.
4674
+ *
4675
+ * Prefer `getSwapQuote` / `acceptSwapQuote` for callers that want to
4676
+ * inspect the quote before committing.
4677
+ *
4947
4678
  * @param swapId - The ID of the swap.
4679
+ * @param options - Optional floor and slippage configuration.
4948
4680
  * @returns The accepted quote amount.
4681
+ * @throws QuoteRejectedError if the quote is non-positive, below the
4682
+ * effective floor, or no baseline is available.
4683
+ */
4684
+ async quoteSwap(swapId, options) {
4685
+ const effectiveFloor = await this.resolveEffectiveFloor(swapId, options);
4686
+ const amount = await this.getSwapQuote(swapId);
4687
+ this.validateQuote(amount, effectiveFloor);
4688
+ await this.swapProvider.postChainQuote(swapId, { amount });
4689
+ return amount;
4690
+ }
4691
+ /**
4692
+ * Fetches a renegotiated quote from Boltz without accepting it.
4693
+ * Pair with `acceptSwapQuote` to commit a specific value.
4949
4694
  */
4950
- async quoteSwap(swapId) {
4695
+ async getSwapQuote(swapId) {
4951
4696
  const { amount } = await this.swapProvider.getChainQuote(swapId);
4697
+ return amount;
4698
+ }
4699
+ /**
4700
+ * Accepts a quote amount for an existing chain swap, after validating it
4701
+ * against the configured floor. See `quoteSwap` for floor-resolution rules.
4702
+ *
4703
+ * @throws QuoteRejectedError if `amount` ≤ 0, below the effective floor,
4704
+ * or no baseline is available.
4705
+ */
4706
+ async acceptSwapQuote(swapId, amount, options) {
4707
+ const effectiveFloor = await this.resolveEffectiveFloor(swapId, options);
4708
+ this.validateQuote(amount, effectiveFloor);
4952
4709
  await this.swapProvider.postChainQuote(swapId, { amount });
4953
4710
  return amount;
4954
4711
  }
4712
+ async resolveEffectiveFloor(swapId, options) {
4713
+ this.validateQuoteOptions(options);
4714
+ const floor = await this.resolveQuoteFloor(swapId, options);
4715
+ const slippageBps = options?.maxSlippageBps ?? 0;
4716
+ return Math.floor(floor - floor * slippageBps / 1e4);
4717
+ }
4718
+ async resolveQuoteFloor(swapId, options) {
4719
+ if (options?.minAcceptableAmount !== void 0) {
4720
+ return options.minAcceptableAmount;
4721
+ }
4722
+ const swaps = await this.swapRepository.getAllSwaps({
4723
+ id: swapId,
4724
+ type: "chain"
4725
+ });
4726
+ const stored = swaps[0];
4727
+ const amount = stored?.response?.claimDetails?.amount;
4728
+ if (typeof amount !== "number") {
4729
+ throw new QuoteRejectedError({ reason: "no_baseline" });
4730
+ }
4731
+ return amount;
4732
+ }
4733
+ validateQuoteOptions(options) {
4734
+ if (options?.minAcceptableAmount !== void 0) {
4735
+ const v = options.minAcceptableAmount;
4736
+ if (!Number.isInteger(v) || v <= 0) {
4737
+ throw new TypeError(
4738
+ `Invalid minAcceptableAmount: ${v} \u2014 must be a positive integer`
4739
+ );
4740
+ }
4741
+ }
4742
+ if (options?.maxSlippageBps !== void 0) {
4743
+ const v = options.maxSlippageBps;
4744
+ if (!Number.isInteger(v) || v < 0 || v > 1e4) {
4745
+ throw new TypeError(
4746
+ `Invalid maxSlippageBps: ${v} \u2014 must be an integer in [0, 10000]`
4747
+ );
4748
+ }
4749
+ }
4750
+ }
4751
+ validateQuote(amount, effectiveFloor) {
4752
+ if (!(amount > 0)) {
4753
+ throw new QuoteRejectedError({
4754
+ reason: "non_positive",
4755
+ quotedAmount: amount
4756
+ });
4757
+ }
4758
+ if (amount < effectiveFloor) {
4759
+ throw new QuoteRejectedError({
4760
+ reason: "below_floor",
4761
+ quotedAmount: amount,
4762
+ floor: effectiveFloor
4763
+ });
4764
+ }
4765
+ }
4955
4766
  // =========================================================================
4956
4767
  // Shared utilities
4957
4768
  // =========================================================================
@@ -4965,14 +4776,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
4965
4776
  * @returns The commitment transaction ID.
4966
4777
  */
4967
4778
  async joinBatch(identity, input, output, arkInfo, isRecoverable2 = true) {
4968
- return joinBatch(
4969
- this.arkProvider,
4970
- identity,
4971
- input,
4972
- output,
4973
- arkInfo,
4974
- isRecoverable2
4975
- );
4779
+ return joinBatch(this.arkProvider, identity, input, output, arkInfo, isRecoverable2);
4976
4780
  }
4977
4781
  /**
4978
4782
  * Creates a VHTLC script for the swap.
@@ -5010,9 +4814,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
5010
4814
  async getPendingSubmarineSwaps() {
5011
4815
  const swaps = await this.getPendingSubmarineSwapsFromStorage();
5012
4816
  if (!swaps) return [];
5013
- return swaps.filter(
5014
- (swap) => swap.status === "invoice.set"
5015
- );
4817
+ return swaps.filter((swap) => swap.status === "invoice.set");
5016
4818
  }
5017
4819
  /**
5018
4820
  * Returns pending reverse swaps (those with status `swap.created`).
@@ -5020,9 +4822,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
5020
4822
  async getPendingReverseSwaps() {
5021
4823
  const swaps = await this.getPendingReverseSwapsFromStorage();
5022
4824
  if (!swaps) return [];
5023
- return swaps.filter(
5024
- (swap) => swap.status === "swap.created"
5025
- );
4825
+ return swaps.filter((swap) => swap.status === "swap.created");
5026
4826
  }
5027
4827
  /**
5028
4828
  * Returns pending chain swaps (those with status `swap.created`).
@@ -5061,10 +4861,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
5061
4861
  this.savePendingReverseSwap.bind(this)
5062
4862
  )
5063
4863
  ).catch((error) => {
5064
- logger.error(
5065
- `Failed to refresh swap status for ${swap.id}:`,
5066
- error
5067
- );
4864
+ logger.error(`Failed to refresh swap status for ${swap.id}:`, error);
5068
4865
  })
5069
4866
  );
5070
4867
  }
@@ -5078,23 +4875,15 @@ var ArkadeSwaps = class _ArkadeSwaps {
5078
4875
  this.savePendingSubmarineSwap.bind(this)
5079
4876
  )
5080
4877
  ).catch((error) => {
5081
- logger.error(
5082
- `Failed to refresh swap status for ${swap.id}:`,
5083
- error
5084
- );
4878
+ logger.error(`Failed to refresh swap status for ${swap.id}:`, error);
5085
4879
  })
5086
4880
  );
5087
4881
  }
5088
4882
  for (const swap of await this.getPendingChainSwapsFromStorage()) {
5089
4883
  if (isChainFinalStatus(swap.status)) continue;
5090
4884
  promises.push(
5091
- this.getSwapStatus(swap.id).then(
5092
- ({ status }) => this.savePendingChainSwap({ ...swap, status })
5093
- ).catch((error) => {
5094
- logger.error(
5095
- `Failed to refresh swap status for ${swap.id}:`,
5096
- error
5097
- );
4885
+ this.getSwapStatus(swap.id).then(({ status }) => this.savePendingChainSwap({ ...swap, status })).catch((error) => {
4886
+ logger.error(`Failed to refresh swap status for ${swap.id}:`, error);
5098
4887
  })
5099
4888
  );
5100
4889
  }
@@ -5111,9 +4900,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
5111
4900
  * display/monitoring and are not automatically wired into the SwapManager.
5112
4901
  */
5113
4902
  async restoreSwaps(boltzFees) {
5114
- const publicKey = hex8.encode(
5115
- await this.wallet.identity.compressedPublicKey()
5116
- );
4903
+ const publicKey = hex8.encode(await this.wallet.identity.compressedPublicKey());
5117
4904
  if (!publicKey) throw new Error("Failed to get public key from wallet");
5118
4905
  const fees = boltzFees ?? await this.swapProvider.getFees();
5119
4906
  const chainSwaps = [];
@@ -5165,25 +4952,14 @@ var ArkadeSwaps = class _ArkadeSwaps {
5165
4952
  preimage: ""
5166
4953
  });
5167
4954
  } else if (isRestoredSubmarineSwap(swap)) {
5168
- const {
5169
- amount,
5170
- lockupAddress,
5171
- serverPublicKey,
5172
- tree,
5173
- timeoutBlockHeights
5174
- } = swap.refundDetails;
4955
+ const { amount, lockupAddress, serverPublicKey, tree, timeoutBlockHeights } = swap.refundDetails;
5175
4956
  let preimage = "";
5176
4957
  if (!isSubmarineFinalStatus(status)) {
5177
4958
  try {
5178
- const data = await this.swapProvider.getSwapPreimage(
5179
- swap.id
5180
- );
4959
+ const data = await this.swapProvider.getSwapPreimage(swap.id);
5181
4960
  preimage = data.preimage;
5182
4961
  } catch (error) {
5183
- logger.warn(
5184
- `Failed to restore preimage for submarine swap ${id}`,
5185
- error
5186
- );
4962
+ logger.warn(`Failed to restore preimage for submarine swap ${id}`, error);
5187
4963
  }
5188
4964
  }
5189
4965
  submarineSwaps.push({
@@ -5221,12 +4997,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
5221
4997
  } else if (isRestoredChainSwap(swap)) {
5222
4998
  const refundDetails = swap.refundDetails;
5223
4999
  if (!refundDetails) continue;
5224
- const {
5225
- amount,
5226
- lockupAddress,
5227
- serverPublicKey,
5228
- timeoutBlockHeight
5229
- } = refundDetails;
5000
+ const { amount, lockupAddress, serverPublicKey, timeoutBlockHeight } = refundDetails;
5230
5001
  chainSwaps.push({
5231
5002
  id,
5232
5003
  type: "chain",
@@ -5285,6 +5056,7 @@ export {
5285
5056
  SwapExpiredError,
5286
5057
  TransactionFailedError,
5287
5058
  PreimageFetchError,
5059
+ QuoteRejectedError,
5288
5060
  BoltzRefundError,
5289
5061
  isSubmarineFailedStatus,
5290
5062
  isSubmarineFinalStatus,