@arkade-os/boltz-swap 0.3.49 → 0.3.51

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.
@@ -35,6 +35,7 @@ var SQLiteSwapRepository = class {
35
35
  constructor(executor) {
36
36
  this.executor = executor;
37
37
  }
38
+ executor;
38
39
  version = 1;
39
40
  initPromise = null;
40
41
  // ── Lifecycle ──────────────────────────────────────────────────────
@@ -1,5 +1,5 @@
1
1
  import { SQLExecutor } from '@arkade-os/sdk/repositories/sqlite';
2
- import { m as SwapRepository, B as BoltzSwap, p as GetSwapsFilter } from '../../types-BKEkNZxK.cjs';
2
+ import { m as SwapRepository, B as BoltzSwap, p as GetSwapsFilter } from '../../types-Db4JSdjk.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, p as GetSwapsFilter } from '../../types-BKEkNZxK.js';
2
+ import { m as SwapRepository, B as BoltzSwap, p as GetSwapsFilter } from '../../types-Db4JSdjk.js';
3
3
  import '@arkade-os/sdk';
4
4
 
5
5
  /**
@@ -7,6 +7,7 @@ var SQLiteSwapRepository = class {
7
7
  constructor(executor) {
8
8
  this.executor = executor;
9
9
  }
10
+ executor;
10
11
  version = 1;
11
12
  initPromise = null;
12
13
  // ── Lifecycle ──────────────────────────────────────────────────────
@@ -1,6 +1,6 @@
1
1
  import { AsyncStorageTaskQueue, TaskProcessor } from '@arkade-os/sdk/worker/expo';
2
2
  import { Identity, ArkProvider, IndexerProvider, IWallet } from '@arkade-os/sdk';
3
- import { m as SwapRepository, N as Network, r as BoltzSwapProvider, A as ArkadeSwapsConfig } from './types-BKEkNZxK.js';
3
+ import { m as SwapRepository, N as Network, r as BoltzSwapProvider, A as ArkadeSwapsConfig } from './types-Db4JSdjk.js';
4
4
 
5
5
  /**
6
6
  * Dependencies injected into every swap processor at runtime.
@@ -1,6 +1,6 @@
1
1
  import { AsyncStorageTaskQueue, TaskProcessor } from '@arkade-os/sdk/worker/expo';
2
2
  import { Identity, ArkProvider, IndexerProvider, IWallet } from '@arkade-os/sdk';
3
- import { m as SwapRepository, N as Network, r as BoltzSwapProvider, A as ArkadeSwapsConfig } from './types-BKEkNZxK.cjs';
3
+ import { m as SwapRepository, N as Network, r as BoltzSwapProvider, A as ArkadeSwapsConfig } from './types-Db4JSdjk.cjs';
4
4
 
5
5
  /**
6
6
  * Dependencies injected into every swap processor at runtime.
@@ -499,7 +499,14 @@ interface SwapManagerClient {
499
499
  /** Internal callbacks wired by ArkadeSwaps to perform claim/refund/save operations. */
500
500
  interface SwapManagerCallbacks {
501
501
  claim: (swap: BoltzReverseSwap) => Promise<void>;
502
- refund: (swap: BoltzSubmarineSwap) => Promise<void>;
502
+ /**
503
+ * Refund a submarine swap's VHTLC.
504
+ *
505
+ * Returns the outcome so the manager can re-arm a deferred refund: every
506
+ * refundable submarine status except `transaction.lockupFailed` is also
507
+ * final, so Boltz sends no further update to re-trigger one.
508
+ */
509
+ refund: (swap: BoltzSubmarineSwap) => Promise<SubmarineRefundOutcome>;
503
510
  /**
504
511
  * Claim the ARK side of a BTC→ARK chain swap.
505
512
  *
@@ -541,12 +548,20 @@ declare class SwapManager implements SwapManagerClient {
541
548
  */
542
549
  private static readonly NOT_FOUND_THRESHOLD;
543
550
  /**
544
- * Delay between re-attempts of a chain refund that left VTXOs deferred
545
- * (e.g. pre-CLTV recoverable VTXO, or Boltz 3-of-3 rejected before CLTV
546
- * has elapsed). Boltz won't send another status update once the swap
547
- * is `swap.expired`, so the manager owns the local retry cadence.
551
+ * Floor on the delay between re-attempts of a refund that left VTXOs
552
+ * deferred, and the delay used when the outcome names no retry time. Boltz
553
+ * won't send another status update once the swap is refundable-and-final,
554
+ * so the manager owns the local retry cadence.
548
555
  */
549
556
  private static readonly REFUND_RETRY_DELAY_MS;
557
+ /**
558
+ * Ceiling on that delay. A deferral can be hours out (a pre-CLTV VTXO waits
559
+ * out the whole refund locktime), and `setTimeout` fires *immediately* past
560
+ * its 32-bit millisecond range, so long waits are broken into re-armed
561
+ * hops. Re-attempting costs an indexer lookup and re-defers, which also lets
562
+ * the cadence recover from a suspended device or a clock jump.
563
+ */
564
+ private static readonly MAX_REFUND_RETRY_DELAY_MS;
550
565
  private readonly swapProvider;
551
566
  private readonly config;
552
567
  private swapUpdateListeners;
@@ -744,15 +759,35 @@ declare class SwapManager implements SwapManagerClient {
744
759
  * chain refund has finished its remaining work).
745
760
  */
746
761
  private finalizeMonitoredSwap;
762
+ private static isRefundRetryableSwap;
763
+ private static hasPendingRefundRetry;
764
+ private shouldMonitorOnStart;
765
+ /**
766
+ * How long to wait before re-attempting a refund, given the `retryAt`
767
+ * (Unix seconds) the outcome reported. Clamped at both ends: see
768
+ * {@link SwapManager.REFUND_RETRY_DELAY_MS} and
769
+ * {@link SwapManager.MAX_REFUND_RETRY_DELAY_MS}.
770
+ */
771
+ private static refundRetryDelayMs;
772
+ private static persistedRefundRetryDelayMs;
773
+ private static nextRefundRetryAt;
774
+ private clearRefundRetry;
775
+ private resumePersistedRefundRetries;
747
776
  /**
748
- * Schedule another `executeAutonomousAction` run for a chain swap whose
749
- * refund left VTXOs deferred. After the retry completes, if no further
750
- * deferral was reported, finalize monitoring cleanup.
777
+ * Schedule another `executeAutonomousAction` run for a swap whose refund
778
+ * left VTXOs deferred. The pending retry and its next attempt time are saved
779
+ * with the swap so stop/start and application restart can re-arm it.
751
780
  */
752
781
  private scheduleRefundRetry;
782
+ private armRefundRetryTimer;
753
783
  /**
754
784
  * Execute autonomous action based on swap status
755
785
  * Uses locking to prevent race conditions with manual operations
786
+ *
787
+ * @returns `false` when another action for this swap already held the lock
788
+ * and this call did nothing, `true` when it ran. Callers that finalize on
789
+ * the result must not act on `false`: the in-flight action owns the swap's
790
+ * outcome and will re-arm or finalize from its own result.
756
791
  */
757
792
  private executeAutonomousAction;
758
793
  /**
@@ -761,6 +796,8 @@ declare class SwapManager implements SwapManagerClient {
761
796
  private executeClaimAction;
762
797
  /**
763
798
  * Execute refund action for submarine swap
799
+ *
800
+ * @returns The refund outcome, or `undefined` if no callback is wired.
764
801
  */
765
802
  private executeRefundAction;
766
803
  /**
@@ -991,6 +1028,13 @@ interface OptimisticSendLightningPaymentResponse {
991
1028
  /** Transaction ID of the Arkade payment. */
992
1029
  txid: string;
993
1030
  }
1031
+ /** Persisted state for a locally deferred refund retry. */
1032
+ interface RefundRetryState {
1033
+ /** True while SwapManager still needs to retry the local refund path. */
1034
+ pending: true;
1035
+ /** Unix timestamp (seconds) for the next retry attempt. */
1036
+ nextRetryAt: number;
1037
+ }
994
1038
  /** Tracks an in-progress reverse swap (Lightning → Arkade). */
995
1039
  interface BoltzReverseSwap {
996
1040
  /** Unique swap ID from Boltz. */
@@ -1024,6 +1068,8 @@ interface BoltzSubmarineSwap {
1024
1068
  refunded?: boolean;
1025
1069
  /** Whether the swap is eligible for refund. */
1026
1070
  refundable?: boolean;
1071
+ /** Deferred local refund retry state, if any. */
1072
+ refundRetry?: RefundRetryState;
1027
1073
  /** Current Boltz swap status. */
1028
1074
  status: BoltzSwapStatus;
1029
1075
  /** The original request sent to Boltz. */
@@ -1067,6 +1113,15 @@ interface SubmarineRecoveryInfo {
1067
1113
  /** Reason populated when `status === "invalid_swap"`. */
1068
1114
  error?: string;
1069
1115
  }
1116
+ /**
1117
+ * Earliest Unix timestamp (seconds) at which retrying the deferred VTXOs could
1118
+ * make progress, or `undefined` when nothing was deferred. Deferrals do not all
1119
+ * last the same time — a server-side CLTV rejection clears as soon as a later
1120
+ * block carries the locktime, whereas a pre-CLTV VTXO must wait out the whole
1121
+ * refund locktime — so callers schedule from this instead of polling at a fixed
1122
+ * interval. It is a lower bound, not a promise: a retry may defer again.
1123
+ */
1124
+ type RefundRetryAt = number | undefined;
1070
1125
  /** Outcome of a single `refundVHTLC` call: how many VTXOs were swept vs. deferred. */
1071
1126
  interface SubmarineRefundOutcome {
1072
1127
  /** Number of VTXOs successfully refunded (joined a batch or via Boltz co-sign). */
@@ -1077,6 +1132,8 @@ interface SubmarineRefundOutcome {
1077
1132
  * is expected to retry these later.
1078
1133
  */
1079
1134
  skipped: number;
1135
+ /** When a retry could first succeed; see {@link RefundRetryAt}. */
1136
+ retryAt?: RefundRetryAt;
1080
1137
  }
1081
1138
  /** Outcome of a single `refundArk` call: how many VTXOs were swept vs. deferred. */
1082
1139
  interface ChainArkRefundOutcome {
@@ -1088,6 +1145,8 @@ interface ChainArkRefundOutcome {
1088
1145
  * is expected to retry these later.
1089
1146
  */
1090
1147
  skipped: number;
1148
+ /** When a retry could first succeed; see {@link RefundRetryAt}. */
1149
+ retryAt?: RefundRetryAt;
1091
1150
  }
1092
1151
  /** Per-swap outcome of a bulk recovery call. */
1093
1152
  interface SubmarineRecoveryResult {
@@ -1120,6 +1179,8 @@ interface BoltzChainSwap {
1120
1179
  feeSatsPerByte: number;
1121
1180
  /** Current Boltz swap status. */
1122
1181
  status: BoltzSwapStatus;
1182
+ /** Deferred local ARK refund retry state, if any. */
1183
+ refundRetry?: RefundRetryState;
1123
1184
  /** The original chain swap request sent to Boltz. */
1124
1185
  request: CreateChainSwapRequest;
1125
1186
  /** Boltz API response with lockup and claim details. */
@@ -499,7 +499,14 @@ interface SwapManagerClient {
499
499
  /** Internal callbacks wired by ArkadeSwaps to perform claim/refund/save operations. */
500
500
  interface SwapManagerCallbacks {
501
501
  claim: (swap: BoltzReverseSwap) => Promise<void>;
502
- refund: (swap: BoltzSubmarineSwap) => Promise<void>;
502
+ /**
503
+ * Refund a submarine swap's VHTLC.
504
+ *
505
+ * Returns the outcome so the manager can re-arm a deferred refund: every
506
+ * refundable submarine status except `transaction.lockupFailed` is also
507
+ * final, so Boltz sends no further update to re-trigger one.
508
+ */
509
+ refund: (swap: BoltzSubmarineSwap) => Promise<SubmarineRefundOutcome>;
503
510
  /**
504
511
  * Claim the ARK side of a BTC→ARK chain swap.
505
512
  *
@@ -541,12 +548,20 @@ declare class SwapManager implements SwapManagerClient {
541
548
  */
542
549
  private static readonly NOT_FOUND_THRESHOLD;
543
550
  /**
544
- * Delay between re-attempts of a chain refund that left VTXOs deferred
545
- * (e.g. pre-CLTV recoverable VTXO, or Boltz 3-of-3 rejected before CLTV
546
- * has elapsed). Boltz won't send another status update once the swap
547
- * is `swap.expired`, so the manager owns the local retry cadence.
551
+ * Floor on the delay between re-attempts of a refund that left VTXOs
552
+ * deferred, and the delay used when the outcome names no retry time. Boltz
553
+ * won't send another status update once the swap is refundable-and-final,
554
+ * so the manager owns the local retry cadence.
548
555
  */
549
556
  private static readonly REFUND_RETRY_DELAY_MS;
557
+ /**
558
+ * Ceiling on that delay. A deferral can be hours out (a pre-CLTV VTXO waits
559
+ * out the whole refund locktime), and `setTimeout` fires *immediately* past
560
+ * its 32-bit millisecond range, so long waits are broken into re-armed
561
+ * hops. Re-attempting costs an indexer lookup and re-defers, which also lets
562
+ * the cadence recover from a suspended device or a clock jump.
563
+ */
564
+ private static readonly MAX_REFUND_RETRY_DELAY_MS;
550
565
  private readonly swapProvider;
551
566
  private readonly config;
552
567
  private swapUpdateListeners;
@@ -744,15 +759,35 @@ declare class SwapManager implements SwapManagerClient {
744
759
  * chain refund has finished its remaining work).
745
760
  */
746
761
  private finalizeMonitoredSwap;
762
+ private static isRefundRetryableSwap;
763
+ private static hasPendingRefundRetry;
764
+ private shouldMonitorOnStart;
765
+ /**
766
+ * How long to wait before re-attempting a refund, given the `retryAt`
767
+ * (Unix seconds) the outcome reported. Clamped at both ends: see
768
+ * {@link SwapManager.REFUND_RETRY_DELAY_MS} and
769
+ * {@link SwapManager.MAX_REFUND_RETRY_DELAY_MS}.
770
+ */
771
+ private static refundRetryDelayMs;
772
+ private static persistedRefundRetryDelayMs;
773
+ private static nextRefundRetryAt;
774
+ private clearRefundRetry;
775
+ private resumePersistedRefundRetries;
747
776
  /**
748
- * Schedule another `executeAutonomousAction` run for a chain swap whose
749
- * refund left VTXOs deferred. After the retry completes, if no further
750
- * deferral was reported, finalize monitoring cleanup.
777
+ * Schedule another `executeAutonomousAction` run for a swap whose refund
778
+ * left VTXOs deferred. The pending retry and its next attempt time are saved
779
+ * with the swap so stop/start and application restart can re-arm it.
751
780
  */
752
781
  private scheduleRefundRetry;
782
+ private armRefundRetryTimer;
753
783
  /**
754
784
  * Execute autonomous action based on swap status
755
785
  * Uses locking to prevent race conditions with manual operations
786
+ *
787
+ * @returns `false` when another action for this swap already held the lock
788
+ * and this call did nothing, `true` when it ran. Callers that finalize on
789
+ * the result must not act on `false`: the in-flight action owns the swap's
790
+ * outcome and will re-arm or finalize from its own result.
756
791
  */
757
792
  private executeAutonomousAction;
758
793
  /**
@@ -761,6 +796,8 @@ declare class SwapManager implements SwapManagerClient {
761
796
  private executeClaimAction;
762
797
  /**
763
798
  * Execute refund action for submarine swap
799
+ *
800
+ * @returns The refund outcome, or `undefined` if no callback is wired.
764
801
  */
765
802
  private executeRefundAction;
766
803
  /**
@@ -991,6 +1028,13 @@ interface OptimisticSendLightningPaymentResponse {
991
1028
  /** Transaction ID of the Arkade payment. */
992
1029
  txid: string;
993
1030
  }
1031
+ /** Persisted state for a locally deferred refund retry. */
1032
+ interface RefundRetryState {
1033
+ /** True while SwapManager still needs to retry the local refund path. */
1034
+ pending: true;
1035
+ /** Unix timestamp (seconds) for the next retry attempt. */
1036
+ nextRetryAt: number;
1037
+ }
994
1038
  /** Tracks an in-progress reverse swap (Lightning → Arkade). */
995
1039
  interface BoltzReverseSwap {
996
1040
  /** Unique swap ID from Boltz. */
@@ -1024,6 +1068,8 @@ interface BoltzSubmarineSwap {
1024
1068
  refunded?: boolean;
1025
1069
  /** Whether the swap is eligible for refund. */
1026
1070
  refundable?: boolean;
1071
+ /** Deferred local refund retry state, if any. */
1072
+ refundRetry?: RefundRetryState;
1027
1073
  /** Current Boltz swap status. */
1028
1074
  status: BoltzSwapStatus;
1029
1075
  /** The original request sent to Boltz. */
@@ -1067,6 +1113,15 @@ interface SubmarineRecoveryInfo {
1067
1113
  /** Reason populated when `status === "invalid_swap"`. */
1068
1114
  error?: string;
1069
1115
  }
1116
+ /**
1117
+ * Earliest Unix timestamp (seconds) at which retrying the deferred VTXOs could
1118
+ * make progress, or `undefined` when nothing was deferred. Deferrals do not all
1119
+ * last the same time — a server-side CLTV rejection clears as soon as a later
1120
+ * block carries the locktime, whereas a pre-CLTV VTXO must wait out the whole
1121
+ * refund locktime — so callers schedule from this instead of polling at a fixed
1122
+ * interval. It is a lower bound, not a promise: a retry may defer again.
1123
+ */
1124
+ type RefundRetryAt = number | undefined;
1070
1125
  /** Outcome of a single `refundVHTLC` call: how many VTXOs were swept vs. deferred. */
1071
1126
  interface SubmarineRefundOutcome {
1072
1127
  /** Number of VTXOs successfully refunded (joined a batch or via Boltz co-sign). */
@@ -1077,6 +1132,8 @@ interface SubmarineRefundOutcome {
1077
1132
  * is expected to retry these later.
1078
1133
  */
1079
1134
  skipped: number;
1135
+ /** When a retry could first succeed; see {@link RefundRetryAt}. */
1136
+ retryAt?: RefundRetryAt;
1080
1137
  }
1081
1138
  /** Outcome of a single `refundArk` call: how many VTXOs were swept vs. deferred. */
1082
1139
  interface ChainArkRefundOutcome {
@@ -1088,6 +1145,8 @@ interface ChainArkRefundOutcome {
1088
1145
  * is expected to retry these later.
1089
1146
  */
1090
1147
  skipped: number;
1148
+ /** When a retry could first succeed; see {@link RefundRetryAt}. */
1149
+ retryAt?: RefundRetryAt;
1091
1150
  }
1092
1151
  /** Per-swap outcome of a bulk recovery call. */
1093
1152
  interface SubmarineRecoveryResult {
@@ -1120,6 +1179,8 @@ interface BoltzChainSwap {
1120
1179
  feeSatsPerByte: number;
1121
1180
  /** Current Boltz swap status. */
1122
1181
  status: BoltzSwapStatus;
1182
+ /** Deferred local ARK refund retry state, if any. */
1183
+ refundRetry?: RefundRetryState;
1123
1184
  /** The original chain swap request sent to Boltz. */
1124
1185
  request: CreateChainSwapRequest;
1125
1186
  /** Boltz API response with lockup and claim details. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkade-os/boltz-swap",
3
- "version": "0.3.49",
3
+ "version": "0.3.51",
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",
@@ -76,7 +76,7 @@
76
76
  "@scure/btc-signer": "2.0.1",
77
77
  "bip68": "1.0.4",
78
78
  "light-bolt11-decoder": "3.2.0",
79
- "@arkade-os/sdk": "0.4.44"
79
+ "@arkade-os/sdk": "0.4.46"
80
80
  },
81
81
  "peerDependencies": {
82
82
  "expo-task-manager": ">=3.0.0",
@@ -92,7 +92,7 @@
92
92
  },
93
93
  "devDependencies": {
94
94
  "@types/ws": "^8.18.1",
95
- "vite": "^7.3.2"
95
+ "vite": "^7.3.6"
96
96
  },
97
97
  "publishConfig": {
98
98
  "access": "public",