@arkade-os/boltz-swap 0.3.32 → 0.3.34

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-BXAD1s8j.d.ts} +69 -8
  3. package/dist/{arkade-swaps-WiKCanCL.d.ts → arkade-swaps-CfMets16.d.cts} +69 -8
  4. package/dist/{chunk-NHBWNN6H.js → chunk-5K2FS2FE.js} +8 -27
  5. package/dist/chunk-SJQJQO7P.js +25 -0
  6. package/dist/{chunk-B3Q4TFWT.js → chunk-TDBUZE4N.js} +817 -866
  7. package/dist/expo/background.cjs +840 -892
  8. package/dist/expo/background.d.cts +3 -3
  9. package/dist/expo/background.d.ts +3 -3
  10. package/dist/expo/background.js +9 -20
  11. package/dist/expo/index.cjs +840 -870
  12. package/dist/expo/index.d.cts +8 -6
  13. package/dist/expo/index.d.ts +8 -6
  14. package/dist/expo/index.js +17 -20
  15. package/dist/index.cjs +1034 -1022
  16. package/dist/index.d.cts +95 -11
  17. package/dist/index.d.ts +95 -11
  18. package/dist/index.js +164 -119
  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-BF3uTFae.d.cts → swapsPollProcessor-BpAqG0V6.d.cts} +3 -3
  28. package/dist/{swapsPollProcessor-wYOMzldd.d.ts → swapsPollProcessor-DFVOAy_-.d.ts} +3 -3
  29. package/dist/{types-BBI7-KJ0.d.cts → types--axEWA8c.d.cts} +42 -4
  30. package/dist/{types-BBI7-KJ0.d.ts → types--axEWA8c.d.ts} +42 -4
  31. package/package.json +10 -25
@@ -1,6 +1,9 @@
1
+ import {
2
+ hasImpossibleSwapsFilter
3
+ } from "../../chunk-SJQJQO7P.js";
4
+
1
5
  // src/repositories/realm/swap-repository.ts
2
6
  var RealmSwapRepository = class {
3
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
7
  constructor(realm) {
5
8
  this.realm = realm;
6
9
  }
@@ -38,21 +41,13 @@ var RealmSwapRepository = class {
38
41
  }
39
42
  async getAllSwaps(filter) {
40
43
  await this.ensureInit();
41
- if (Array.isArray(filter?.id) && filter.id.length === 0 || Array.isArray(filter?.status) && filter.status.length === 0 || Array.isArray(filter?.type) && filter.type.length === 0) {
42
- return [];
43
- }
44
+ if (hasImpossibleSwapsFilter(filter)) return [];
44
45
  let results = this.realm.objects("BoltzSwap");
45
46
  if (filter) {
46
47
  const filterParts = [];
47
48
  const filterArgs = [];
48
49
  let argIndex = 0;
49
- argIndex = this.addFilterCondition(
50
- filterParts,
51
- filterArgs,
52
- "id",
53
- filter.id,
54
- argIndex
55
- );
50
+ argIndex = this.addFilterCondition(filterParts, filterArgs, "id", filter.id, argIndex);
56
51
  argIndex = this.addFilterCondition(
57
52
  filterParts,
58
53
  filterArgs,
@@ -60,13 +55,7 @@ var RealmSwapRepository = class {
60
55
  filter.status,
61
56
  argIndex
62
57
  );
63
- this.addFilterCondition(
64
- filterParts,
65
- filterArgs,
66
- "type",
67
- filter.type,
68
- argIndex
69
- );
58
+ this.addFilterCondition(filterParts, filterArgs, "type", filter.type, argIndex);
70
59
  if (filterParts.length > 0) {
71
60
  const query = filterParts.join(" AND ");
72
61
  results = results.filtered(query, ...filterArgs);
@@ -76,10 +65,7 @@ var RealmSwapRepository = class {
76
65
  const reverse = filter.orderDirection === "desc";
77
66
  results = results.sorted("createdAt", reverse);
78
67
  }
79
- return [...results].map(
80
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
81
- (obj) => JSON.parse(obj.data)
82
- );
68
+ return [...results].map((obj) => JSON.parse(obj.data));
83
69
  }
84
70
  async clear() {
85
71
  await this.ensureInit();
@@ -24,6 +24,12 @@ __export(sqlite_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(sqlite_exports);
26
26
 
27
+ // src/repositories/swap-repository.ts
28
+ function hasImpossibleSwapsFilter(filter) {
29
+ if (!filter) return false;
30
+ return Array.isArray(filter.id) && filter.id.length === 0 || Array.isArray(filter.status) && filter.status.length === 0 || Array.isArray(filter.type) && filter.type.length === 0;
31
+ }
32
+
27
33
  // src/repositories/sqlite/swap-repository.ts
28
34
  var SQLiteSwapRepository = class {
29
35
  constructor(executor) {
@@ -66,13 +72,7 @@ var SQLiteSwapRepository = class {
66
72
  await this.executor.run(
67
73
  `INSERT OR REPLACE INTO boltz_swaps (id, type, status, created_at, data)
68
74
  VALUES (?, ?, ?, ?, ?)`,
69
- [
70
- swap.id,
71
- swap.type,
72
- swap.status,
73
- swap.createdAt,
74
- JSON.stringify(swap)
75
- ]
75
+ [swap.id, swap.type, swap.status, swap.createdAt, JSON.stringify(swap)]
76
76
  );
77
77
  }
78
78
  async deleteSwap(id) {
@@ -81,17 +81,13 @@ var SQLiteSwapRepository = class {
81
81
  }
82
82
  async getAllSwaps(filter) {
83
83
  await this.ensureInit();
84
- if (Array.isArray(filter?.id) && filter.id.length === 0 || Array.isArray(filter?.status) && filter.status.length === 0 || Array.isArray(filter?.type) && filter.type.length === 0) {
85
- return [];
86
- }
84
+ if (hasImpossibleSwapsFilter(filter)) return [];
87
85
  const conditions = [];
88
86
  const params = [];
89
87
  if (filter) {
90
88
  if (filter.id !== void 0) {
91
89
  if (Array.isArray(filter.id)) {
92
- conditions.push(
93
- `id IN (${filter.id.map(() => "?").join(",")})`
94
- );
90
+ conditions.push(`id IN (${filter.id.map(() => "?").join(",")})`);
95
91
  params.push(...filter.id);
96
92
  } else {
97
93
  conditions.push(`id = ?`);
@@ -100,9 +96,7 @@ var SQLiteSwapRepository = class {
100
96
  }
101
97
  if (filter.status !== void 0) {
102
98
  if (Array.isArray(filter.status)) {
103
- conditions.push(
104
- `status IN (${filter.status.map(() => "?").join(",")})`
105
- );
99
+ conditions.push(`status IN (${filter.status.map(() => "?").join(",")})`);
106
100
  params.push(...filter.status);
107
101
  } else {
108
102
  conditions.push(`status = ?`);
@@ -111,9 +105,7 @@ var SQLiteSwapRepository = class {
111
105
  }
112
106
  if (filter.type !== void 0) {
113
107
  if (Array.isArray(filter.type)) {
114
- conditions.push(
115
- `type IN (${filter.type.map(() => "?").join(",")})`
116
- );
108
+ conditions.push(`type IN (${filter.type.map(() => "?").join(",")})`);
117
109
  params.push(...filter.type);
118
110
  } else {
119
111
  conditions.push(`type = ?`);
@@ -129,10 +121,7 @@ var SQLiteSwapRepository = class {
129
121
  const direction = filter.orderDirection === "desc" ? "DESC" : "ASC";
130
122
  sql += ` ORDER BY created_at ${direction}`;
131
123
  }
132
- const rows = await this.executor.all(
133
- sql,
134
- params
135
- );
124
+ const rows = await this.executor.all(sql, params);
136
125
  return rows.map((row) => JSON.parse(row.data));
137
126
  }
138
127
  async clear() {
@@ -1,5 +1,5 @@
1
1
  import { SQLExecutor } from '@arkade-os/sdk/repositories/sqlite';
2
- import { m as SwapRepository, B as BoltzSwap, o as GetSwapsFilter } from '../../types-BBI7-KJ0.cjs';
2
+ import { n as SwapRepository, B as BoltzSwap, p as GetSwapsFilter } from '../../types--axEWA8c.cjs';
3
3
  import '@arkade-os/sdk';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { SQLExecutor } from '@arkade-os/sdk/repositories/sqlite';
2
- import { m as SwapRepository, B as BoltzSwap, o as GetSwapsFilter } from '../../types-BBI7-KJ0.js';
2
+ import { n as SwapRepository, B as BoltzSwap, p as GetSwapsFilter } from '../../types--axEWA8c.js';
3
3
  import '@arkade-os/sdk';
4
4
 
5
5
  /**
@@ -1,3 +1,7 @@
1
+ import {
2
+ hasImpossibleSwapsFilter
3
+ } from "../../chunk-SJQJQO7P.js";
4
+
1
5
  // src/repositories/sqlite/swap-repository.ts
2
6
  var SQLiteSwapRepository = class {
3
7
  constructor(executor) {
@@ -40,13 +44,7 @@ var SQLiteSwapRepository = class {
40
44
  await this.executor.run(
41
45
  `INSERT OR REPLACE INTO boltz_swaps (id, type, status, created_at, data)
42
46
  VALUES (?, ?, ?, ?, ?)`,
43
- [
44
- swap.id,
45
- swap.type,
46
- swap.status,
47
- swap.createdAt,
48
- JSON.stringify(swap)
49
- ]
47
+ [swap.id, swap.type, swap.status, swap.createdAt, JSON.stringify(swap)]
50
48
  );
51
49
  }
52
50
  async deleteSwap(id) {
@@ -55,17 +53,13 @@ var SQLiteSwapRepository = class {
55
53
  }
56
54
  async getAllSwaps(filter) {
57
55
  await this.ensureInit();
58
- if (Array.isArray(filter?.id) && filter.id.length === 0 || Array.isArray(filter?.status) && filter.status.length === 0 || Array.isArray(filter?.type) && filter.type.length === 0) {
59
- return [];
60
- }
56
+ if (hasImpossibleSwapsFilter(filter)) return [];
61
57
  const conditions = [];
62
58
  const params = [];
63
59
  if (filter) {
64
60
  if (filter.id !== void 0) {
65
61
  if (Array.isArray(filter.id)) {
66
- conditions.push(
67
- `id IN (${filter.id.map(() => "?").join(",")})`
68
- );
62
+ conditions.push(`id IN (${filter.id.map(() => "?").join(",")})`);
69
63
  params.push(...filter.id);
70
64
  } else {
71
65
  conditions.push(`id = ?`);
@@ -74,9 +68,7 @@ var SQLiteSwapRepository = class {
74
68
  }
75
69
  if (filter.status !== void 0) {
76
70
  if (Array.isArray(filter.status)) {
77
- conditions.push(
78
- `status IN (${filter.status.map(() => "?").join(",")})`
79
- );
71
+ conditions.push(`status IN (${filter.status.map(() => "?").join(",")})`);
80
72
  params.push(...filter.status);
81
73
  } else {
82
74
  conditions.push(`status = ?`);
@@ -85,9 +77,7 @@ var SQLiteSwapRepository = class {
85
77
  }
86
78
  if (filter.type !== void 0) {
87
79
  if (Array.isArray(filter.type)) {
88
- conditions.push(
89
- `type IN (${filter.type.map(() => "?").join(",")})`
90
- );
80
+ conditions.push(`type IN (${filter.type.map(() => "?").join(",")})`);
91
81
  params.push(...filter.type);
92
82
  } else {
93
83
  conditions.push(`type = ?`);
@@ -103,10 +93,7 @@ var SQLiteSwapRepository = class {
103
93
  const direction = filter.orderDirection === "desc" ? "DESC" : "ASC";
104
94
  sql += ` ORDER BY created_at ${direction}`;
105
95
  }
106
- const rows = await this.executor.all(
107
- sql,
108
- params
109
- );
96
+ const rows = await this.executor.all(sql, params);
110
97
  return rows.map((row) => JSON.parse(row.data));
111
98
  }
112
99
  async clear() {
@@ -1,6 +1,6 @@
1
1
  import { AsyncStorageTaskQueue, TaskProcessor } from '@arkade-os/sdk/worker/expo';
2
- import { ArkProvider, IndexerProvider, Identity, IWallet } from '@arkade-os/sdk';
3
- import { m as SwapRepository, p as BoltzSwapProvider, N as Network, A as ArkadeSwapsConfig } from './types-BBI7-KJ0.cjs';
2
+ import { Identity, ArkProvider, IndexerProvider, IWallet } from '@arkade-os/sdk';
3
+ import { n as SwapRepository, N as Network, r as BoltzSwapProvider, A as ArkadeSwapsConfig } from './types--axEWA8c.cjs';
4
4
 
5
5
  /**
6
6
  * Dependencies injected into every swap processor at runtime.
@@ -90,4 +90,4 @@ declare const SWAP_POLL_TASK_TYPE = "swap-poll";
90
90
  */
91
91
  declare const swapsPollProcessor: TaskProcessor<SwapTaskDependencies>;
92
92
 
93
- export { type DefineSwapBackgroundTaskOptions as D, type ExpoArkadeSwapsConfig as E, type PersistedSwapBackgroundConfig as P, SWAP_POLL_TASK_TYPE as S, type SwapTaskDependencies as a, type ExpoSwapBackgroundConfig as b, type ExpoArkadeLightningConfig as c, swapsPollProcessor as s };
93
+ export { type DefineSwapBackgroundTaskOptions as D, type ExpoArkadeSwapsConfig as E, type PersistedSwapBackgroundConfig as P, SWAP_POLL_TASK_TYPE as S, type SwapTaskDependencies as a, type ExpoArkadeLightningConfig as b, type ExpoSwapBackgroundConfig as c, swapsPollProcessor as s };
@@ -1,6 +1,6 @@
1
1
  import { AsyncStorageTaskQueue, TaskProcessor } from '@arkade-os/sdk/worker/expo';
2
- import { ArkProvider, IndexerProvider, Identity, IWallet } from '@arkade-os/sdk';
3
- import { m as SwapRepository, p as BoltzSwapProvider, N as Network, A as ArkadeSwapsConfig } from './types-BBI7-KJ0.js';
2
+ import { Identity, ArkProvider, IndexerProvider, IWallet } from '@arkade-os/sdk';
3
+ import { n as SwapRepository, N as Network, r as BoltzSwapProvider, A as ArkadeSwapsConfig } from './types--axEWA8c.js';
4
4
 
5
5
  /**
6
6
  * Dependencies injected into every swap processor at runtime.
@@ -90,4 +90,4 @@ declare const SWAP_POLL_TASK_TYPE = "swap-poll";
90
90
  */
91
91
  declare const swapsPollProcessor: TaskProcessor<SwapTaskDependencies>;
92
92
 
93
- export { type DefineSwapBackgroundTaskOptions as D, type ExpoArkadeSwapsConfig as E, type PersistedSwapBackgroundConfig as P, SWAP_POLL_TASK_TYPE as S, type SwapTaskDependencies as a, type ExpoSwapBackgroundConfig as b, type ExpoArkadeLightningConfig as c, swapsPollProcessor as s };
93
+ export { type DefineSwapBackgroundTaskOptions as D, type ExpoArkadeSwapsConfig as E, type PersistedSwapBackgroundConfig as P, SWAP_POLL_TASK_TYPE as S, type SwapTaskDependencies as a, type ExpoArkadeLightningConfig as b, type ExpoSwapBackgroundConfig as c, swapsPollProcessor as s };
@@ -1,4 +1,4 @@
1
- import { Transaction, NetworkName, IWallet, ArkProvider, IndexerProvider } from '@arkade-os/sdk';
1
+ import { Transaction, IWallet, ArkProvider, NetworkName, IndexerProvider } from '@arkade-os/sdk';
2
2
 
3
3
  /** Configuration for BoltzSwapProvider. */
4
4
  interface SwapProviderConfig {
@@ -337,7 +337,13 @@ declare class BoltzSwapProvider {
337
337
  transaction: Transaction;
338
338
  checkpoint: Transaction;
339
339
  }>;
340
- /** Monitors swap status updates via WebSocket. Calls update callback on each status change. Resolves when terminal. */
340
+ /**
341
+ * Monitors swap status updates and forwards them to the update callback.
342
+ * Prefers a WebSocket subscription; on connection error or premature close
343
+ * it falls back to REST polling so callers don't fail when the WS endpoint
344
+ * is flaky (observed in CI). Resolves when the swap reaches a terminal
345
+ * status.
346
+ */
341
347
  monitorSwap(swapId: string, update: (type: BoltzSwapStatus, data?: any) => void): Promise<void>;
342
348
  /** Returns current chain swap fees for a given pair (e.g. ARK→BTC). */
343
349
  getChainFees(from: Chain, to: Chain): Promise<ChainFeesResponse>;
@@ -469,7 +475,7 @@ interface SwapManagerCallbacks {
469
475
  refund: (swap: BoltzSubmarineSwap) => Promise<void>;
470
476
  claimArk: (swap: BoltzChainSwap) => Promise<void>;
471
477
  claimBtc: (swap: BoltzChainSwap) => Promise<void>;
472
- refundArk: (swap: BoltzChainSwap) => Promise<void>;
478
+ refundArk: (swap: BoltzChainSwap) => Promise<ChainArkRefundOutcome>;
473
479
  signServerClaim?: (swap: BoltzChainSwap) => Promise<void>;
474
480
  saveSwap: (swap: BoltzSwap) => Promise<void>;
475
481
  }
@@ -492,6 +498,13 @@ declare class SwapManager implements SwapManagerClient {
492
498
  * enough that a real "swap unknown to this provider" surfaces quickly.
493
499
  */
494
500
  private static readonly NOT_FOUND_THRESHOLD;
501
+ /**
502
+ * Delay between re-attempts of a chain refund that left VTXOs deferred
503
+ * (e.g. pre-CLTV recoverable VTXO, or Boltz 3-of-3 rejected before CLTV
504
+ * has elapsed). Boltz won't send another status update once the swap
505
+ * is `swap.expired`, so the manager owns the local retry cadence.
506
+ */
507
+ private static readonly REFUND_RETRY_DELAY_MS;
495
508
  private readonly swapProvider;
496
509
  private readonly config;
497
510
  private swapUpdateListeners;
@@ -507,6 +520,7 @@ declare class SwapManager implements SwapManagerClient {
507
520
  private reconnectTimer;
508
521
  private initialPollTimer;
509
522
  private pollRetryTimers;
523
+ private refundRetryTimers;
510
524
  private notFoundCounts;
511
525
  private isRunning;
512
526
  private currentReconnectDelay;
@@ -663,6 +677,19 @@ declare class SwapManager implements SwapManagerClient {
663
677
  * This is the core logic that determines what actions to take
664
678
  */
665
679
  private handleSwapStatusUpdate;
680
+ /**
681
+ * Drop a swap from monitoring and emit the terminal completion event.
682
+ * Shared between the on-status-update finalization path and the
683
+ * refund-retry finalization path (used when a previously-deferred
684
+ * chain refund has finished its remaining work).
685
+ */
686
+ private finalizeMonitoredSwap;
687
+ /**
688
+ * Schedule another `executeAutonomousAction` run for a chain swap whose
689
+ * refund left VTXOs deferred. After the retry completes, if no further
690
+ * deferral was reported, finalize monitoring cleanup.
691
+ */
692
+ private scheduleRefundRetry;
666
693
  /**
667
694
  * Execute autonomous action based on swap status
668
695
  * Uses locking to prevent race conditions with manual operations
@@ -941,6 +968,17 @@ interface SubmarineRefundOutcome {
941
968
  */
942
969
  skipped: number;
943
970
  }
971
+ /** Outcome of a single `refundArk` call: how many VTXOs were swept vs. deferred. */
972
+ interface ChainArkRefundOutcome {
973
+ /** Number of VTXOs successfully refunded. */
974
+ swept: number;
975
+ /**
976
+ * Number of VTXOs that could not be refunded yet (e.g. recoverable VTXO
977
+ * pre-CLTV, or Boltz rejected and CLTV still not satisfied). The caller
978
+ * is expected to retry these later.
979
+ */
980
+ skipped: number;
981
+ }
944
982
  /** Per-swap outcome of a bulk recovery call. */
945
983
  interface SubmarineRecoveryResult {
946
984
  /** ID of the swap whose VHTLC we attempted to refund. */
@@ -1099,4 +1137,4 @@ interface ChainFeesResponse {
1099
1137
  };
1100
1138
  }
1101
1139
 
1102
- export { type PendingSubmarineSwap as $, type ArkadeSwapsConfig as A, type BoltzSwap as B, type CreateLightningInvoiceRequest as C, type DecodedInvoice as D, isPendingChainSwap as E, type FeesResponse as F, type GetSwapStatusResponse as G, isPendingReverseSwap as H, isPendingSubmarineSwap as I, isReverseClaimableStatus as J, isReverseFailedStatus as K, type LimitsResponse as L, isReverseFinalStatus as M, type Network as N, isReversePendingStatus as O, isReverseSuccessStatus as P, isReverseSwapClaimable as Q, isSubmarineFailedStatus as R, type SendLightningPaymentRequest as S, isSubmarineFinalStatus as T, isSubmarinePendingStatus as U, isSubmarineSuccessStatus as V, isSubmarineRefundableStatus as W, isSubmarineSwapRefundable as X, SwapManager as Y, type IncomingPaymentSubscription as Z, type ArkadeSwapsCreateConfig as _, type BoltzChainSwap as a, type PendingReverseSwap as a0, type PendingChainSwap as a1, type PendingSwap as a2, type Vtxo as a3, type SubmarineRecoveryStatus as a4, type SwapManagerConfig as a5, type SwapManagerEvents as a6, type SwapManagerCallbacks as a7, type BoltzReverseSwap as b, type BoltzSubmarineSwap as c, type Chain as d, type CreateLightningInvoiceResponse as e, type SendLightningPaymentResponse as f, type SubmarineRefundOutcome as g, type SubmarineRecoveryInfo as h, type SubmarineRecoveryResult as i, type ChainFeesResponse as j, type ArkToBtcResponse as k, type BtcToArkResponse as l, type SwapRepository as m, type SwapManagerClient as n, type GetSwapsFilter as o, BoltzSwapProvider as p, type BoltzSwapStatus as q, isChainClaimableStatus as r, isChainFailedStatus as s, isChainFinalStatus as t, isChainPendingStatus as u, isChainRefundableStatus as v, isChainSignableStatus as w, isChainSuccessStatus as x, isChainSwapClaimable as y, isChainSwapRefundable as z };
1140
+ export { isReverseFinalStatus as $, type ArkadeSwapsConfig as A, type BoltzSwap as B, type CreateLightningInvoiceRequest as C, type DecodedInvoice as D, type SwapManagerEvents as E, type FeesResponse as F, type GetSwapStatusResponse as G, isChainClaimableStatus as H, type IncomingPaymentSubscription as I, isChainFailedStatus as J, isChainFinalStatus as K, type LimitsResponse as L, isChainPendingStatus as M, type Network as N, isChainRefundableStatus as O, type PendingChainSwap as P, isChainSignableStatus as Q, isChainSuccessStatus as R, type SendLightningPaymentRequest as S, isChainSwapClaimable as T, isChainSwapRefundable as U, type Vtxo as V, isPendingChainSwap as W, isPendingReverseSwap as X, isPendingSubmarineSwap as Y, isReverseClaimableStatus as Z, isReverseFailedStatus as _, type BoltzChainSwap as a, isReversePendingStatus as a0, isReverseSuccessStatus as a1, isReverseSwapClaimable as a2, isSubmarineFailedStatus as a3, isSubmarineFinalStatus as a4, isSubmarinePendingStatus as a5, isSubmarineRefundableStatus as a6, isSubmarineSuccessStatus as a7, isSubmarineSwapRefundable as a8, type BoltzReverseSwap as b, type BoltzSubmarineSwap as c, type Chain as d, type CreateLightningInvoiceResponse as e, type SendLightningPaymentResponse as f, type SubmarineRefundOutcome as g, type SubmarineRecoveryInfo as h, type SubmarineRecoveryResult as i, type ChainFeesResponse as j, type ArkToBtcResponse as k, type BtcToArkResponse as l, type ChainArkRefundOutcome as m, type SwapRepository as n, type SwapManagerClient as o, type GetSwapsFilter as p, type ArkadeSwapsCreateConfig as q, BoltzSwapProvider as r, type BoltzSwapStatus as s, type PendingReverseSwap as t, type PendingSubmarineSwap as u, type PendingSwap as v, type SubmarineRecoveryStatus as w, SwapManager as x, type SwapManagerCallbacks as y, type SwapManagerConfig as z };
@@ -1,4 +1,4 @@
1
- import { Transaction, NetworkName, IWallet, ArkProvider, IndexerProvider } from '@arkade-os/sdk';
1
+ import { Transaction, IWallet, ArkProvider, NetworkName, IndexerProvider } from '@arkade-os/sdk';
2
2
 
3
3
  /** Configuration for BoltzSwapProvider. */
4
4
  interface SwapProviderConfig {
@@ -337,7 +337,13 @@ declare class BoltzSwapProvider {
337
337
  transaction: Transaction;
338
338
  checkpoint: Transaction;
339
339
  }>;
340
- /** Monitors swap status updates via WebSocket. Calls update callback on each status change. Resolves when terminal. */
340
+ /**
341
+ * Monitors swap status updates and forwards them to the update callback.
342
+ * Prefers a WebSocket subscription; on connection error or premature close
343
+ * it falls back to REST polling so callers don't fail when the WS endpoint
344
+ * is flaky (observed in CI). Resolves when the swap reaches a terminal
345
+ * status.
346
+ */
341
347
  monitorSwap(swapId: string, update: (type: BoltzSwapStatus, data?: any) => void): Promise<void>;
342
348
  /** Returns current chain swap fees for a given pair (e.g. ARK→BTC). */
343
349
  getChainFees(from: Chain, to: Chain): Promise<ChainFeesResponse>;
@@ -469,7 +475,7 @@ interface SwapManagerCallbacks {
469
475
  refund: (swap: BoltzSubmarineSwap) => Promise<void>;
470
476
  claimArk: (swap: BoltzChainSwap) => Promise<void>;
471
477
  claimBtc: (swap: BoltzChainSwap) => Promise<void>;
472
- refundArk: (swap: BoltzChainSwap) => Promise<void>;
478
+ refundArk: (swap: BoltzChainSwap) => Promise<ChainArkRefundOutcome>;
473
479
  signServerClaim?: (swap: BoltzChainSwap) => Promise<void>;
474
480
  saveSwap: (swap: BoltzSwap) => Promise<void>;
475
481
  }
@@ -492,6 +498,13 @@ declare class SwapManager implements SwapManagerClient {
492
498
  * enough that a real "swap unknown to this provider" surfaces quickly.
493
499
  */
494
500
  private static readonly NOT_FOUND_THRESHOLD;
501
+ /**
502
+ * Delay between re-attempts of a chain refund that left VTXOs deferred
503
+ * (e.g. pre-CLTV recoverable VTXO, or Boltz 3-of-3 rejected before CLTV
504
+ * has elapsed). Boltz won't send another status update once the swap
505
+ * is `swap.expired`, so the manager owns the local retry cadence.
506
+ */
507
+ private static readonly REFUND_RETRY_DELAY_MS;
495
508
  private readonly swapProvider;
496
509
  private readonly config;
497
510
  private swapUpdateListeners;
@@ -507,6 +520,7 @@ declare class SwapManager implements SwapManagerClient {
507
520
  private reconnectTimer;
508
521
  private initialPollTimer;
509
522
  private pollRetryTimers;
523
+ private refundRetryTimers;
510
524
  private notFoundCounts;
511
525
  private isRunning;
512
526
  private currentReconnectDelay;
@@ -663,6 +677,19 @@ declare class SwapManager implements SwapManagerClient {
663
677
  * This is the core logic that determines what actions to take
664
678
  */
665
679
  private handleSwapStatusUpdate;
680
+ /**
681
+ * Drop a swap from monitoring and emit the terminal completion event.
682
+ * Shared between the on-status-update finalization path and the
683
+ * refund-retry finalization path (used when a previously-deferred
684
+ * chain refund has finished its remaining work).
685
+ */
686
+ private finalizeMonitoredSwap;
687
+ /**
688
+ * Schedule another `executeAutonomousAction` run for a chain swap whose
689
+ * refund left VTXOs deferred. After the retry completes, if no further
690
+ * deferral was reported, finalize monitoring cleanup.
691
+ */
692
+ private scheduleRefundRetry;
666
693
  /**
667
694
  * Execute autonomous action based on swap status
668
695
  * Uses locking to prevent race conditions with manual operations
@@ -941,6 +968,17 @@ interface SubmarineRefundOutcome {
941
968
  */
942
969
  skipped: number;
943
970
  }
971
+ /** Outcome of a single `refundArk` call: how many VTXOs were swept vs. deferred. */
972
+ interface ChainArkRefundOutcome {
973
+ /** Number of VTXOs successfully refunded. */
974
+ swept: number;
975
+ /**
976
+ * Number of VTXOs that could not be refunded yet (e.g. recoverable VTXO
977
+ * pre-CLTV, or Boltz rejected and CLTV still not satisfied). The caller
978
+ * is expected to retry these later.
979
+ */
980
+ skipped: number;
981
+ }
944
982
  /** Per-swap outcome of a bulk recovery call. */
945
983
  interface SubmarineRecoveryResult {
946
984
  /** ID of the swap whose VHTLC we attempted to refund. */
@@ -1099,4 +1137,4 @@ interface ChainFeesResponse {
1099
1137
  };
1100
1138
  }
1101
1139
 
1102
- export { type PendingSubmarineSwap as $, type ArkadeSwapsConfig as A, type BoltzSwap as B, type CreateLightningInvoiceRequest as C, type DecodedInvoice as D, isPendingChainSwap as E, type FeesResponse as F, type GetSwapStatusResponse as G, isPendingReverseSwap as H, isPendingSubmarineSwap as I, isReverseClaimableStatus as J, isReverseFailedStatus as K, type LimitsResponse as L, isReverseFinalStatus as M, type Network as N, isReversePendingStatus as O, isReverseSuccessStatus as P, isReverseSwapClaimable as Q, isSubmarineFailedStatus as R, type SendLightningPaymentRequest as S, isSubmarineFinalStatus as T, isSubmarinePendingStatus as U, isSubmarineSuccessStatus as V, isSubmarineRefundableStatus as W, isSubmarineSwapRefundable as X, SwapManager as Y, type IncomingPaymentSubscription as Z, type ArkadeSwapsCreateConfig as _, type BoltzChainSwap as a, type PendingReverseSwap as a0, type PendingChainSwap as a1, type PendingSwap as a2, type Vtxo as a3, type SubmarineRecoveryStatus as a4, type SwapManagerConfig as a5, type SwapManagerEvents as a6, type SwapManagerCallbacks as a7, type BoltzReverseSwap as b, type BoltzSubmarineSwap as c, type Chain as d, type CreateLightningInvoiceResponse as e, type SendLightningPaymentResponse as f, type SubmarineRefundOutcome as g, type SubmarineRecoveryInfo as h, type SubmarineRecoveryResult as i, type ChainFeesResponse as j, type ArkToBtcResponse as k, type BtcToArkResponse as l, type SwapRepository as m, type SwapManagerClient as n, type GetSwapsFilter as o, BoltzSwapProvider as p, type BoltzSwapStatus as q, isChainClaimableStatus as r, isChainFailedStatus as s, isChainFinalStatus as t, isChainPendingStatus as u, isChainRefundableStatus as v, isChainSignableStatus as w, isChainSuccessStatus as x, isChainSwapClaimable as y, isChainSwapRefundable as z };
1140
+ export { isReverseFinalStatus as $, type ArkadeSwapsConfig as A, type BoltzSwap as B, type CreateLightningInvoiceRequest as C, type DecodedInvoice as D, type SwapManagerEvents as E, type FeesResponse as F, type GetSwapStatusResponse as G, isChainClaimableStatus as H, type IncomingPaymentSubscription as I, isChainFailedStatus as J, isChainFinalStatus as K, type LimitsResponse as L, isChainPendingStatus as M, type Network as N, isChainRefundableStatus as O, type PendingChainSwap as P, isChainSignableStatus as Q, isChainSuccessStatus as R, type SendLightningPaymentRequest as S, isChainSwapClaimable as T, isChainSwapRefundable as U, type Vtxo as V, isPendingChainSwap as W, isPendingReverseSwap as X, isPendingSubmarineSwap as Y, isReverseClaimableStatus as Z, isReverseFailedStatus as _, type BoltzChainSwap as a, isReversePendingStatus as a0, isReverseSuccessStatus as a1, isReverseSwapClaimable as a2, isSubmarineFailedStatus as a3, isSubmarineFinalStatus as a4, isSubmarinePendingStatus as a5, isSubmarineRefundableStatus as a6, isSubmarineSuccessStatus as a7, isSubmarineSwapRefundable as a8, type BoltzReverseSwap as b, type BoltzSubmarineSwap as c, type Chain as d, type CreateLightningInvoiceResponse as e, type SendLightningPaymentResponse as f, type SubmarineRefundOutcome as g, type SubmarineRecoveryInfo as h, type SubmarineRecoveryResult as i, type ChainFeesResponse as j, type ArkToBtcResponse as k, type BtcToArkResponse as l, type ChainArkRefundOutcome as m, type SwapRepository as n, type SwapManagerClient as o, type GetSwapsFilter as p, type ArkadeSwapsCreateConfig as q, BoltzSwapProvider as r, type BoltzSwapStatus as s, type PendingReverseSwap as t, type PendingSubmarineSwap as u, type PendingSwap as v, type SubmarineRecoveryStatus as w, SwapManager as x, type SwapManagerCallbacks as y, type SwapManagerConfig as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkade-os/boltz-swap",
3
- "version": "0.3.32",
3
+ "version": "0.3.34",
4
4
  "type": "module",
5
5
  "description": "A production-ready TypeScript package that brings Boltz submarine-swaps to Arkade.",
6
6
  "main": "./dist/index.js",
@@ -70,13 +70,13 @@
70
70
  "author": "Arkade-OS",
71
71
  "license": "MIT",
72
72
  "dependencies": {
73
- "@arkade-os/sdk": "0.4.27",
73
+ "@noble/curves": "2.0.1",
74
74
  "@noble/hashes": "2.0.1",
75
75
  "@scure/base": "2.0.0",
76
76
  "@scure/btc-signer": "2.0.1",
77
- "bip68": "^1.0.4",
78
- "@noble/curves": "^2.0.1",
79
- "light-bolt11-decoder": "3.2.0"
77
+ "bip68": "1.0.4",
78
+ "light-bolt11-decoder": "3.2.0",
79
+ "@arkade-os/sdk": "0.4.29"
80
80
  },
81
81
  "peerDependencies": {
82
82
  "expo-task-manager": ">=3.0.0",
@@ -91,29 +91,17 @@
91
91
  }
92
92
  },
93
93
  "devDependencies": {
94
- "@eslint/js": "^9.35.0",
95
- "@types/node": "^24.3.1",
96
94
  "@types/ws": "^8.18.1",
97
- "@typescript-eslint/eslint-plugin": "^8.43.0",
98
- "@typescript-eslint/parser": "^8.43.0",
99
- "eslint": "^9.35.0",
100
- "eventsource": "^4.1.0",
101
- "fake-indexeddb": "^6.0.0",
102
- "prettier": "3.6.2",
103
- "tsup": "^8.5.0",
104
- "typescript": "^5.9.2",
105
- "vite": "7.1.11",
106
- "vitest": "^3.2.4"
107
- },
108
- "engines": {
109
- "node": ">=22.12.0 <23",
110
- "pnpm": ">=10.25.0 <11"
95
+ "vite": "7.1.11"
111
96
  },
112
97
  "publishConfig": {
113
- "access": "public"
98
+ "access": "public",
99
+ "registry": "https://registry.npmjs.org/"
114
100
  },
115
101
  "scripts": {
116
102
  "build": "tsup src/index.ts src/expo/index.ts src/expo/background.ts src/repositories/sqlite/index.ts src/repositories/realm/index.ts --format esm,cjs --dts --clean",
103
+ "smoke:dist": "node scripts/smoke-dist.mjs",
104
+ "typecheck": "tsc --noEmit",
117
105
  "format": "prettier --write src test",
118
106
  "lint": "prettier --check src test",
119
107
  "test": "vitest run",
@@ -121,9 +109,6 @@
121
109
  "test:integration": "vitest run test/e2e/**",
122
110
  "test:setup-docker": "node test/e2e/setup.mjs",
123
111
  "test:integration-docker": "vitest run test/e2e/**",
124
- "release": "pnpm run build && bash scripts/release.sh",
125
- "release:dry-run": "bash scripts/release.sh --dry-run",
126
- "release:cleanup": "bash scripts/release.sh --cleanup",
127
112
  "regtest:start": "./regtest/start-env.sh",
128
113
  "regtest:stop": "./regtest/stop-env.sh",
129
114
  "regtest:clean": "./regtest/clean-env.sh",