@arkade-os/boltz-swap 0.3.40 → 0.3.42
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.
- package/README.md +29 -0
- package/dist/{arkade-swaps-DnRiRcdW.d.ts → arkade-swaps-C3sUFr5f.d.cts} +59 -5
- package/dist/{arkade-swaps-CObmwpZQ.d.cts → arkade-swaps-LvsGHtre.d.ts} +59 -5
- package/dist/{chunk-WGLBFONB.js → chunk-CWY37W4B.js} +1 -1
- package/dist/{chunk-GYWMQOCP.js → chunk-UXYHW7KV.js} +138 -35
- package/dist/expo/background.cjs +137 -35
- package/dist/expo/background.d.cts +3 -3
- package/dist/expo/background.d.ts +3 -3
- package/dist/expo/background.js +2 -2
- package/dist/expo/index.cjs +140 -35
- package/dist/expo/index.d.cts +9 -5
- package/dist/expo/index.d.ts +9 -5
- package/dist/expo/index.js +5 -2
- package/dist/index.cjs +156 -35
- package/dist/index.d.cts +21 -9
- package/dist/index.d.ts +21 -9
- package/dist/index.js +20 -1
- package/dist/repositories/realm/index.d.cts +1 -1
- package/dist/repositories/realm/index.d.ts +1 -1
- package/dist/repositories/sqlite/index.d.cts +1 -1
- package/dist/repositories/sqlite/index.d.ts +1 -1
- package/dist/{swapsPollProcessor-BlyUrhtO.d.cts → swapsPollProcessor-CGMXUKPe.d.cts} +1 -1
- package/dist/{swapsPollProcessor-Bv4Z2R7g.d.ts → swapsPollProcessor-CuDM6sxV.d.ts} +1 -1
- package/dist/{types-D97i1LFu.d.cts → types-8NrCdOpS.d.cts} +51 -1
- package/dist/{types-D97i1LFu.d.ts → types-8NrCdOpS.d.ts} +51 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -61,6 +61,35 @@ console.log('Paid:', result.txid);
|
|
|
61
61
|
// SwapManager auto-refunds if payment fails
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
+
By default the call resolves only once the swap fully settles (`transaction.claimed`),
|
|
65
|
+
i.e. after Boltz has swept the HTLC. To show an optimistic "sent" state as soon as the
|
|
66
|
+
payment is in flight — like most Lightning wallets — pass `waitFor: 'funded'`:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
const result = await swaps.sendLightningPayment({
|
|
70
|
+
invoice: 'lnbc500u1pj...',
|
|
71
|
+
waitFor: 'funded',
|
|
72
|
+
});
|
|
73
|
+
// Resolves as soon as the lockup transaction is observed: the funds are
|
|
74
|
+
// committed and the swap is refundable from here. result.preimage is not
|
|
75
|
+
// reported on this path — the proof of payment is persisted to the stored
|
|
76
|
+
// swap once it settles. Monitoring continues in the
|
|
77
|
+
// background and keeps the stored swap up to date until a terminal status,
|
|
78
|
+
// but a late failure no longer rejects — keep the SwapManager enabled so
|
|
79
|
+
// auto-refunds are handled for you. With the SwapManager disabled, a late
|
|
80
|
+
// failure is only persisted as refundable and the funds stay locked until
|
|
81
|
+
// you recover them via restoreSwaps()/recoverSubmarineFunds().
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The same milestone is exposed for a swap you already hold as
|
|
85
|
+
`waitForSwapFunded(pendingSwap)`, alongside `waitForSwapSettlement(pendingSwap)`.
|
|
86
|
+
|
|
87
|
+
If the app restarts before the swap settles, the in-process monitoring is gone — call
|
|
88
|
+
`refreshSwapsStatus()` on startup to reconcile: it polls every pending swap and persists
|
|
89
|
+
the latest status, including the preimage for swaps that settled while the app was
|
|
90
|
+
closed. Read the swap back from the repository (e.g. `getSwapHistory()`) to flip a
|
|
91
|
+
pending UI row to "completed".
|
|
92
|
+
|
|
64
93
|
### ARK to BTC
|
|
65
94
|
|
|
66
95
|
```typescript
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IWallet, ArkProvider, IndexerProvider, ArkInfo, Identity, ArkTxInput, VHTLC } from '@arkade-os/sdk';
|
|
2
|
-
import { r as BoltzSwapProvider,
|
|
2
|
+
import { r as BoltzSwapProvider, y as SwapManager, m as SwapRepository, q as ArkadeSwapsCreateConfig, A as ArkadeSwapsConfig, n as SwapManagerClient, C as CreateLightningInvoiceRequest, e as CreateLightningInvoiceResponse, b as BoltzReverseSwap, S as SendLightningPaymentRequest, o as SendLightningPaymentResponse, O as OptimisticSendLightningPaymentResponse, c as BoltzSubmarineSwap, f as SubmarineRefundOutcome, g as SubmarineRecoveryInfo, h as SubmarineRecoveryResult, j as ArkToBtcResponse, a as BoltzChainSwap, l as ChainArkRefundOutcome, k as BtcToArkResponse, d as Chain, F as FeesResponse, i as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, B as BoltzSwap } from './types-8NrCdOpS.cjs';
|
|
3
3
|
import { TransactionOutput } from '@scure/btc-signer/psbt.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -134,12 +134,33 @@ declare class ArkadeSwaps {
|
|
|
134
134
|
}>;
|
|
135
135
|
/**
|
|
136
136
|
* Sends a Lightning payment via a submarine swap (Arkade → Lightning).
|
|
137
|
-
* Creates the swap, sends funds, and waits for settlement
|
|
137
|
+
* Creates the swap, sends funds, and waits for settlement (or, with
|
|
138
|
+
* `waitFor: "funded"`, only until the lockup transaction is observed —
|
|
139
|
+
* see {@link SendLightningPaymentRequest.waitFor}). Auto-refunds on
|
|
140
|
+
* failures observed before the promise resolves.
|
|
138
141
|
* @param args.invoice - BOLT11 Lightning invoice to pay.
|
|
139
|
-
* @
|
|
142
|
+
* @param args.waitFor - "settled" (default) resolves with the preimage at
|
|
143
|
+
* "transaction.claimed"; "funded" resolves without a preimage as soon as
|
|
144
|
+
* the payment is in flight.
|
|
145
|
+
* @returns The amount paid, preimage (proof of payment, unless resolved
|
|
146
|
+
* at "funded"), and transaction ID.
|
|
140
147
|
* @throws {TransactionFailedError} If the payment fails (auto-refunds if possible).
|
|
148
|
+
* @remarks With `waitFor: "funded"`, failures observed *after* the promise
|
|
149
|
+
* resolves are only persisted to the repository (refundable flag) — the
|
|
150
|
+
* active auto-refund in this method is no longer reachable. Keep the
|
|
151
|
+
* SwapManager enabled so late failures are refunded automatically;
|
|
152
|
+
* without it the caller must recover via {@link restoreSwaps} /
|
|
153
|
+
* {@link recoverSubmarineFunds}.
|
|
154
|
+
*
|
|
155
|
+
* Note on types: the overloads narrow on the `waitFor` literal, so a
|
|
156
|
+
* request stored in a variable typed as `SendLightningPaymentRequest`
|
|
157
|
+
* widens the result to {@link OptimisticSendLightningPaymentResponse}
|
|
158
|
+
* (optional preimage) even on the default settled path.
|
|
141
159
|
*/
|
|
142
|
-
sendLightningPayment(args: SendLightningPaymentRequest
|
|
160
|
+
sendLightningPayment(args: SendLightningPaymentRequest & {
|
|
161
|
+
waitFor?: "settled";
|
|
162
|
+
}): Promise<SendLightningPaymentResponse>;
|
|
163
|
+
sendLightningPayment(args: SendLightningPaymentRequest): Promise<OptimisticSendLightningPaymentResponse>;
|
|
143
164
|
/**
|
|
144
165
|
* Creates a submarine swap (Arkade → Lightning) and saves it to storage.
|
|
145
166
|
* @param args.invoice - BOLT11 Lightning invoice to pay.
|
|
@@ -229,6 +250,9 @@ declare class ArkadeSwaps {
|
|
|
229
250
|
recoverAllSubmarineFunds(swaps: BoltzSubmarineSwap[]): Promise<SubmarineRecoveryResult[]>;
|
|
230
251
|
/**
|
|
231
252
|
* Waits for a submarine swap's Lightning payment to settle.
|
|
253
|
+
* Resolves only at the terminal "transaction.claimed" status, once Boltz
|
|
254
|
+
* has swept the HTLC. To resolve as soon as the payment is in flight, use
|
|
255
|
+
* {@link waitForSwapFunded} instead.
|
|
232
256
|
* @param pendingSwap - The submarine swap to monitor.
|
|
233
257
|
* @returns The preimage from the settled Lightning payment (proof of payment).
|
|
234
258
|
* @throws {SwapExpiredError} If the swap expires.
|
|
@@ -238,6 +262,32 @@ declare class ArkadeSwaps {
|
|
|
238
262
|
waitForSwapSettlement(pendingSwap: BoltzSubmarineSwap): Promise<{
|
|
239
263
|
preimage: string;
|
|
240
264
|
}>;
|
|
265
|
+
/**
|
|
266
|
+
* Waits until a submarine swap is funded: resolves as soon as the lockup
|
|
267
|
+
* transaction is observed ("transaction.mempool" or any later status in
|
|
268
|
+
* the lifecycle — statuses can be skipped since subscriptions report only
|
|
269
|
+
* the current one). The sender's funds are committed and the swap is
|
|
270
|
+
* refundable from this point, which is when most Lightning wallets show
|
|
271
|
+
* a payment as "sent".
|
|
272
|
+
*
|
|
273
|
+
* Monitoring continues in the background until the swap reaches a
|
|
274
|
+
* terminal status, persisting updates to the repository (the preimage on
|
|
275
|
+
* claim, the refundable flag on failure), but this promise no longer
|
|
276
|
+
* rejects once resolved — acting on a late failure is the caller's
|
|
277
|
+
* responsibility (the SwapManager handles it automatically when enabled).
|
|
278
|
+
* @param pendingSwap - The submarine swap to monitor.
|
|
279
|
+
* @throws {SwapExpiredError} If the swap expires before funding.
|
|
280
|
+
* @throws {InvoiceFailedToPayError} If Boltz fails to route the payment.
|
|
281
|
+
* @throws {TransactionLockupFailedError} If the lockup transaction fails.
|
|
282
|
+
*/
|
|
283
|
+
waitForSwapFunded(pendingSwap: BoltzSubmarineSwap): Promise<void>;
|
|
284
|
+
/**
|
|
285
|
+
* Shared wait machinery: monitors the swap and resolves at the terminal
|
|
286
|
+
* "transaction.claimed" status (with the preimage) or, when `resolveAt`
|
|
287
|
+
* is given, as soon as that status — or any later one in the successful
|
|
288
|
+
* progression — is observed (without a preimage).
|
|
289
|
+
*/
|
|
290
|
+
private waitForSubmarineSwap;
|
|
241
291
|
/**
|
|
242
292
|
* Creates a chain swap from ARK to BTC.
|
|
243
293
|
* @param args.btcAddress - Destination Bitcoin address.
|
|
@@ -528,7 +578,10 @@ interface IArkadeSwaps extends AsyncDisposable {
|
|
|
528
578
|
stopSwapManager(): Promise<void>;
|
|
529
579
|
getSwapManager(): SwapManagerClient | null;
|
|
530
580
|
createLightningInvoice(args: CreateLightningInvoiceRequest): Promise<CreateLightningInvoiceResponse>;
|
|
531
|
-
sendLightningPayment(args: SendLightningPaymentRequest
|
|
581
|
+
sendLightningPayment(args: SendLightningPaymentRequest & {
|
|
582
|
+
waitFor?: "settled";
|
|
583
|
+
}): Promise<SendLightningPaymentResponse>;
|
|
584
|
+
sendLightningPayment(args: SendLightningPaymentRequest): Promise<OptimisticSendLightningPaymentResponse>;
|
|
532
585
|
createSubmarineSwap(args: SendLightningPaymentRequest): Promise<BoltzSubmarineSwap>;
|
|
533
586
|
createReverseSwap(args: CreateLightningInvoiceRequest): Promise<BoltzReverseSwap>;
|
|
534
587
|
claimVHTLC(pendingSwap: BoltzReverseSwap): Promise<void>;
|
|
@@ -543,6 +596,7 @@ interface IArkadeSwaps extends AsyncDisposable {
|
|
|
543
596
|
waitForSwapSettlement(pendingSwap: BoltzSubmarineSwap): Promise<{
|
|
544
597
|
preimage: string;
|
|
545
598
|
}>;
|
|
599
|
+
waitForSwapFunded(pendingSwap: BoltzSubmarineSwap): Promise<void>;
|
|
546
600
|
restoreSwaps(boltzFees?: FeesResponse): Promise<{
|
|
547
601
|
chainSwaps: BoltzChainSwap[];
|
|
548
602
|
reverseSwaps: BoltzReverseSwap[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IWallet, ArkProvider, IndexerProvider, ArkInfo, Identity, ArkTxInput, VHTLC } from '@arkade-os/sdk';
|
|
2
|
-
import { r as BoltzSwapProvider,
|
|
2
|
+
import { r as BoltzSwapProvider, y as SwapManager, m as SwapRepository, q as ArkadeSwapsCreateConfig, A as ArkadeSwapsConfig, n as SwapManagerClient, C as CreateLightningInvoiceRequest, e as CreateLightningInvoiceResponse, b as BoltzReverseSwap, S as SendLightningPaymentRequest, o as SendLightningPaymentResponse, O as OptimisticSendLightningPaymentResponse, c as BoltzSubmarineSwap, f as SubmarineRefundOutcome, g as SubmarineRecoveryInfo, h as SubmarineRecoveryResult, j as ArkToBtcResponse, a as BoltzChainSwap, l as ChainArkRefundOutcome, k as BtcToArkResponse, d as Chain, F as FeesResponse, i as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, B as BoltzSwap } from './types-8NrCdOpS.js';
|
|
3
3
|
import { TransactionOutput } from '@scure/btc-signer/psbt.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -134,12 +134,33 @@ declare class ArkadeSwaps {
|
|
|
134
134
|
}>;
|
|
135
135
|
/**
|
|
136
136
|
* Sends a Lightning payment via a submarine swap (Arkade → Lightning).
|
|
137
|
-
* Creates the swap, sends funds, and waits for settlement
|
|
137
|
+
* Creates the swap, sends funds, and waits for settlement (or, with
|
|
138
|
+
* `waitFor: "funded"`, only until the lockup transaction is observed —
|
|
139
|
+
* see {@link SendLightningPaymentRequest.waitFor}). Auto-refunds on
|
|
140
|
+
* failures observed before the promise resolves.
|
|
138
141
|
* @param args.invoice - BOLT11 Lightning invoice to pay.
|
|
139
|
-
* @
|
|
142
|
+
* @param args.waitFor - "settled" (default) resolves with the preimage at
|
|
143
|
+
* "transaction.claimed"; "funded" resolves without a preimage as soon as
|
|
144
|
+
* the payment is in flight.
|
|
145
|
+
* @returns The amount paid, preimage (proof of payment, unless resolved
|
|
146
|
+
* at "funded"), and transaction ID.
|
|
140
147
|
* @throws {TransactionFailedError} If the payment fails (auto-refunds if possible).
|
|
148
|
+
* @remarks With `waitFor: "funded"`, failures observed *after* the promise
|
|
149
|
+
* resolves are only persisted to the repository (refundable flag) — the
|
|
150
|
+
* active auto-refund in this method is no longer reachable. Keep the
|
|
151
|
+
* SwapManager enabled so late failures are refunded automatically;
|
|
152
|
+
* without it the caller must recover via {@link restoreSwaps} /
|
|
153
|
+
* {@link recoverSubmarineFunds}.
|
|
154
|
+
*
|
|
155
|
+
* Note on types: the overloads narrow on the `waitFor` literal, so a
|
|
156
|
+
* request stored in a variable typed as `SendLightningPaymentRequest`
|
|
157
|
+
* widens the result to {@link OptimisticSendLightningPaymentResponse}
|
|
158
|
+
* (optional preimage) even on the default settled path.
|
|
141
159
|
*/
|
|
142
|
-
sendLightningPayment(args: SendLightningPaymentRequest
|
|
160
|
+
sendLightningPayment(args: SendLightningPaymentRequest & {
|
|
161
|
+
waitFor?: "settled";
|
|
162
|
+
}): Promise<SendLightningPaymentResponse>;
|
|
163
|
+
sendLightningPayment(args: SendLightningPaymentRequest): Promise<OptimisticSendLightningPaymentResponse>;
|
|
143
164
|
/**
|
|
144
165
|
* Creates a submarine swap (Arkade → Lightning) and saves it to storage.
|
|
145
166
|
* @param args.invoice - BOLT11 Lightning invoice to pay.
|
|
@@ -229,6 +250,9 @@ declare class ArkadeSwaps {
|
|
|
229
250
|
recoverAllSubmarineFunds(swaps: BoltzSubmarineSwap[]): Promise<SubmarineRecoveryResult[]>;
|
|
230
251
|
/**
|
|
231
252
|
* Waits for a submarine swap's Lightning payment to settle.
|
|
253
|
+
* Resolves only at the terminal "transaction.claimed" status, once Boltz
|
|
254
|
+
* has swept the HTLC. To resolve as soon as the payment is in flight, use
|
|
255
|
+
* {@link waitForSwapFunded} instead.
|
|
232
256
|
* @param pendingSwap - The submarine swap to monitor.
|
|
233
257
|
* @returns The preimage from the settled Lightning payment (proof of payment).
|
|
234
258
|
* @throws {SwapExpiredError} If the swap expires.
|
|
@@ -238,6 +262,32 @@ declare class ArkadeSwaps {
|
|
|
238
262
|
waitForSwapSettlement(pendingSwap: BoltzSubmarineSwap): Promise<{
|
|
239
263
|
preimage: string;
|
|
240
264
|
}>;
|
|
265
|
+
/**
|
|
266
|
+
* Waits until a submarine swap is funded: resolves as soon as the lockup
|
|
267
|
+
* transaction is observed ("transaction.mempool" or any later status in
|
|
268
|
+
* the lifecycle — statuses can be skipped since subscriptions report only
|
|
269
|
+
* the current one). The sender's funds are committed and the swap is
|
|
270
|
+
* refundable from this point, which is when most Lightning wallets show
|
|
271
|
+
* a payment as "sent".
|
|
272
|
+
*
|
|
273
|
+
* Monitoring continues in the background until the swap reaches a
|
|
274
|
+
* terminal status, persisting updates to the repository (the preimage on
|
|
275
|
+
* claim, the refundable flag on failure), but this promise no longer
|
|
276
|
+
* rejects once resolved — acting on a late failure is the caller's
|
|
277
|
+
* responsibility (the SwapManager handles it automatically when enabled).
|
|
278
|
+
* @param pendingSwap - The submarine swap to monitor.
|
|
279
|
+
* @throws {SwapExpiredError} If the swap expires before funding.
|
|
280
|
+
* @throws {InvoiceFailedToPayError} If Boltz fails to route the payment.
|
|
281
|
+
* @throws {TransactionLockupFailedError} If the lockup transaction fails.
|
|
282
|
+
*/
|
|
283
|
+
waitForSwapFunded(pendingSwap: BoltzSubmarineSwap): Promise<void>;
|
|
284
|
+
/**
|
|
285
|
+
* Shared wait machinery: monitors the swap and resolves at the terminal
|
|
286
|
+
* "transaction.claimed" status (with the preimage) or, when `resolveAt`
|
|
287
|
+
* is given, as soon as that status — or any later one in the successful
|
|
288
|
+
* progression — is observed (without a preimage).
|
|
289
|
+
*/
|
|
290
|
+
private waitForSubmarineSwap;
|
|
241
291
|
/**
|
|
242
292
|
* Creates a chain swap from ARK to BTC.
|
|
243
293
|
* @param args.btcAddress - Destination Bitcoin address.
|
|
@@ -528,7 +578,10 @@ interface IArkadeSwaps extends AsyncDisposable {
|
|
|
528
578
|
stopSwapManager(): Promise<void>;
|
|
529
579
|
getSwapManager(): SwapManagerClient | null;
|
|
530
580
|
createLightningInvoice(args: CreateLightningInvoiceRequest): Promise<CreateLightningInvoiceResponse>;
|
|
531
|
-
sendLightningPayment(args: SendLightningPaymentRequest
|
|
581
|
+
sendLightningPayment(args: SendLightningPaymentRequest & {
|
|
582
|
+
waitFor?: "settled";
|
|
583
|
+
}): Promise<SendLightningPaymentResponse>;
|
|
584
|
+
sendLightningPayment(args: SendLightningPaymentRequest): Promise<OptimisticSendLightningPaymentResponse>;
|
|
532
585
|
createSubmarineSwap(args: SendLightningPaymentRequest): Promise<BoltzSubmarineSwap>;
|
|
533
586
|
createReverseSwap(args: CreateLightningInvoiceRequest): Promise<BoltzReverseSwap>;
|
|
534
587
|
claimVHTLC(pendingSwap: BoltzReverseSwap): Promise<void>;
|
|
@@ -543,6 +596,7 @@ interface IArkadeSwaps extends AsyncDisposable {
|
|
|
543
596
|
waitForSwapSettlement(pendingSwap: BoltzSubmarineSwap): Promise<{
|
|
544
597
|
preimage: string;
|
|
545
598
|
}>;
|
|
599
|
+
waitForSwapFunded(pendingSwap: BoltzSubmarineSwap): Promise<void>;
|
|
546
600
|
restoreSwaps(boltzFees?: FeesResponse): Promise<{
|
|
547
601
|
chainSwaps: BoltzChainSwap[];
|
|
548
602
|
reverseSwaps: BoltzReverseSwap[];
|
|
@@ -233,6 +233,22 @@ var isSubmarinePendingStatus = (status) => {
|
|
|
233
233
|
var isSubmarineRefundableStatus = (status) => {
|
|
234
234
|
return ["invoice.failedToPay", "transaction.lockupFailed", "swap.expired"].includes(status);
|
|
235
235
|
};
|
|
236
|
+
var SUBMARINE_STATUS_PROGRESSION = [
|
|
237
|
+
"swap.created",
|
|
238
|
+
"invoice.set",
|
|
239
|
+
"transaction.mempool",
|
|
240
|
+
"transaction.confirmed",
|
|
241
|
+
"invoice.pending",
|
|
242
|
+
"invoice.paid",
|
|
243
|
+
"transaction.claim.pending",
|
|
244
|
+
"transaction.claimed"
|
|
245
|
+
];
|
|
246
|
+
var hasSubmarineStatusReached = (status, target) => {
|
|
247
|
+
const progression = SUBMARINE_STATUS_PROGRESSION;
|
|
248
|
+
const statusIndex = progression.indexOf(status);
|
|
249
|
+
const targetIndex = progression.indexOf(target);
|
|
250
|
+
return statusIndex >= 0 && targetIndex >= 0 && statusIndex >= targetIndex;
|
|
251
|
+
};
|
|
236
252
|
var isSubmarineSuccessStatus = (status) => {
|
|
237
253
|
return status === "transaction.claimed";
|
|
238
254
|
};
|
|
@@ -3599,16 +3615,6 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3599
3615
|
this.swapProvider.monitorSwap(pendingSwap.id, onStatusUpdate).catch(reject);
|
|
3600
3616
|
});
|
|
3601
3617
|
}
|
|
3602
|
-
// =========================================================================
|
|
3603
|
-
// Lightning: Submarine swaps (send Arkade -> Lightning)
|
|
3604
|
-
// =========================================================================
|
|
3605
|
-
/**
|
|
3606
|
-
* Sends a Lightning payment via a submarine swap (Arkade → Lightning).
|
|
3607
|
-
* Creates the swap, sends funds, and waits for settlement. Auto-refunds on failure.
|
|
3608
|
-
* @param args.invoice - BOLT11 Lightning invoice to pay.
|
|
3609
|
-
* @returns The amount paid, preimage (proof of payment), and transaction ID.
|
|
3610
|
-
* @throws {TransactionFailedError} If the payment fails (auto-refunds if possible).
|
|
3611
|
-
*/
|
|
3612
3618
|
async sendLightningPayment(args) {
|
|
3613
3619
|
const pendingSwap = await this.createSubmarineSwap(args);
|
|
3614
3620
|
if (!pendingSwap.response.address)
|
|
@@ -3619,6 +3625,18 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3619
3625
|
amount: pendingSwap.response.expectedAmount
|
|
3620
3626
|
});
|
|
3621
3627
|
try {
|
|
3628
|
+
if (args.waitFor === "funded") {
|
|
3629
|
+
if (!this.swapManager) {
|
|
3630
|
+
logger.warn(
|
|
3631
|
+
`Swap ${pendingSwap.id}: sendLightningPayment with waitFor "funded" but SwapManager is disabled \u2014 a failure after this promise resolves is only persisted as refundable, not auto-refunded; recover via restoreSwaps/recoverSubmarineFunds`
|
|
3632
|
+
);
|
|
3633
|
+
}
|
|
3634
|
+
await this.waitForSwapFunded(pendingSwap);
|
|
3635
|
+
return {
|
|
3636
|
+
amount: pendingSwap.response.expectedAmount,
|
|
3637
|
+
txid
|
|
3638
|
+
};
|
|
3639
|
+
}
|
|
3622
3640
|
const { preimage } = await this.waitForSwapSettlement(pendingSwap);
|
|
3623
3641
|
return {
|
|
3624
3642
|
amount: pendingSwap.response.expectedAmount,
|
|
@@ -4120,6 +4138,9 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4120
4138
|
}
|
|
4121
4139
|
/**
|
|
4122
4140
|
* Waits for a submarine swap's Lightning payment to settle.
|
|
4141
|
+
* Resolves only at the terminal "transaction.claimed" status, once Boltz
|
|
4142
|
+
* has swept the HTLC. To resolve as soon as the payment is in flight, use
|
|
4143
|
+
* {@link waitForSwapFunded} instead.
|
|
4123
4144
|
* @param pendingSwap - The submarine swap to monitor.
|
|
4124
4145
|
* @returns The preimage from the settled Lightning payment (proof of payment).
|
|
4125
4146
|
* @throws {SwapExpiredError} If the swap expires.
|
|
@@ -4127,19 +4148,59 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4127
4148
|
* @throws {TransactionLockupFailedError} If the lockup transaction fails.
|
|
4128
4149
|
*/
|
|
4129
4150
|
async waitForSwapSettlement(pendingSwap) {
|
|
4151
|
+
return this.waitForSubmarineSwap(pendingSwap);
|
|
4152
|
+
}
|
|
4153
|
+
/**
|
|
4154
|
+
* Waits until a submarine swap is funded: resolves as soon as the lockup
|
|
4155
|
+
* transaction is observed ("transaction.mempool" or any later status in
|
|
4156
|
+
* the lifecycle — statuses can be skipped since subscriptions report only
|
|
4157
|
+
* the current one). The sender's funds are committed and the swap is
|
|
4158
|
+
* refundable from this point, which is when most Lightning wallets show
|
|
4159
|
+
* a payment as "sent".
|
|
4160
|
+
*
|
|
4161
|
+
* Monitoring continues in the background until the swap reaches a
|
|
4162
|
+
* terminal status, persisting updates to the repository (the preimage on
|
|
4163
|
+
* claim, the refundable flag on failure), but this promise no longer
|
|
4164
|
+
* rejects once resolved — acting on a late failure is the caller's
|
|
4165
|
+
* responsibility (the SwapManager handles it automatically when enabled).
|
|
4166
|
+
* @param pendingSwap - The submarine swap to monitor.
|
|
4167
|
+
* @throws {SwapExpiredError} If the swap expires before funding.
|
|
4168
|
+
* @throws {InvoiceFailedToPayError} If Boltz fails to route the payment.
|
|
4169
|
+
* @throws {TransactionLockupFailedError} If the lockup transaction fails.
|
|
4170
|
+
*/
|
|
4171
|
+
async waitForSwapFunded(pendingSwap) {
|
|
4172
|
+
await this.waitForSubmarineSwap(pendingSwap, "transaction.mempool");
|
|
4173
|
+
}
|
|
4174
|
+
/**
|
|
4175
|
+
* Shared wait machinery: monitors the swap and resolves at the terminal
|
|
4176
|
+
* "transaction.claimed" status (with the preimage) or, when `resolveAt`
|
|
4177
|
+
* is given, as soon as that status — or any later one in the successful
|
|
4178
|
+
* progression — is observed (without a preimage).
|
|
4179
|
+
*/
|
|
4180
|
+
async waitForSubmarineSwap(pendingSwap, resolveAt) {
|
|
4130
4181
|
return new Promise((resolve, reject) => {
|
|
4131
|
-
let
|
|
4182
|
+
let isFinal = false;
|
|
4183
|
+
let isSettled = false;
|
|
4132
4184
|
const onStatusUpdate = async (status) => {
|
|
4133
|
-
if (
|
|
4134
|
-
const saveStatus = (additionalFields) =>
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4185
|
+
if (isFinal) return;
|
|
4186
|
+
const saveStatus = async (additionalFields) => {
|
|
4187
|
+
try {
|
|
4188
|
+
await updateSubmarineSwapStatus(
|
|
4189
|
+
pendingSwap,
|
|
4190
|
+
status,
|
|
4191
|
+
this.savePendingSubmarineSwap.bind(this),
|
|
4192
|
+
additionalFields
|
|
4193
|
+
);
|
|
4194
|
+
} catch (error) {
|
|
4195
|
+
logger.error(
|
|
4196
|
+
`Swap ${pendingSwap.id}: failed to persist status "${status}": ${error}`
|
|
4197
|
+
);
|
|
4198
|
+
}
|
|
4199
|
+
};
|
|
4140
4200
|
switch (status) {
|
|
4141
4201
|
case "swap.expired":
|
|
4142
|
-
|
|
4202
|
+
isFinal = true;
|
|
4203
|
+
isSettled = true;
|
|
4143
4204
|
await saveStatus({ refundable: true });
|
|
4144
4205
|
reject(
|
|
4145
4206
|
new SwapExpiredError({
|
|
@@ -4149,7 +4210,8 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4149
4210
|
);
|
|
4150
4211
|
break;
|
|
4151
4212
|
case "invoice.failedToPay":
|
|
4152
|
-
|
|
4213
|
+
isFinal = true;
|
|
4214
|
+
isSettled = true;
|
|
4153
4215
|
await saveStatus({ refundable: true });
|
|
4154
4216
|
reject(
|
|
4155
4217
|
new InvoiceFailedToPayError({
|
|
@@ -4159,7 +4221,8 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4159
4221
|
);
|
|
4160
4222
|
break;
|
|
4161
4223
|
case "transaction.lockupFailed":
|
|
4162
|
-
|
|
4224
|
+
isFinal = true;
|
|
4225
|
+
isSettled = true;
|
|
4163
4226
|
await saveStatus({ refundable: true });
|
|
4164
4227
|
reject(
|
|
4165
4228
|
new TransactionLockupFailedError({
|
|
@@ -4169,23 +4232,47 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4169
4232
|
);
|
|
4170
4233
|
break;
|
|
4171
4234
|
case "transaction.claimed": {
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4235
|
+
isFinal = true;
|
|
4236
|
+
isSettled = true;
|
|
4237
|
+
try {
|
|
4238
|
+
const { preimage } = await this.swapProvider.getSwapPreimage(
|
|
4239
|
+
pendingSwap.id
|
|
4240
|
+
);
|
|
4241
|
+
await saveStatus({ preimage });
|
|
4242
|
+
resolve({ preimage });
|
|
4243
|
+
} catch (error) {
|
|
4244
|
+
logger.error(
|
|
4245
|
+
`Swap ${pendingSwap.id}: failed to fetch preimage on claim: ${error}`
|
|
4246
|
+
);
|
|
4247
|
+
reject(error);
|
|
4248
|
+
}
|
|
4178
4249
|
break;
|
|
4179
4250
|
}
|
|
4180
4251
|
default:
|
|
4181
4252
|
await saveStatus();
|
|
4253
|
+
if (resolveAt && hasSubmarineStatusReached(status, resolveAt)) {
|
|
4254
|
+
isSettled = true;
|
|
4255
|
+
resolve({ preimage: void 0 });
|
|
4256
|
+
}
|
|
4182
4257
|
break;
|
|
4183
4258
|
}
|
|
4184
4259
|
};
|
|
4185
|
-
this.swapProvider.monitorSwap(pendingSwap.id,
|
|
4186
|
-
|
|
4187
|
-
|
|
4260
|
+
this.swapProvider.monitorSwap(pendingSwap.id, (status) => {
|
|
4261
|
+
onStatusUpdate(status).catch(
|
|
4262
|
+
(error) => logger.error(
|
|
4263
|
+
`Swap ${pendingSwap.id}: error handling status "${status}": ${error}`
|
|
4264
|
+
)
|
|
4265
|
+
);
|
|
4266
|
+
}).catch((error) => {
|
|
4267
|
+
if (!isSettled) {
|
|
4268
|
+
isFinal = true;
|
|
4269
|
+
isSettled = true;
|
|
4188
4270
|
reject(error);
|
|
4271
|
+
} else {
|
|
4272
|
+
isFinal = true;
|
|
4273
|
+
logger.warn(
|
|
4274
|
+
`Swap ${pendingSwap.id}: monitor failed after settlement: ${error}`
|
|
4275
|
+
);
|
|
4189
4276
|
}
|
|
4190
4277
|
});
|
|
4191
4278
|
});
|
|
@@ -5209,13 +5296,28 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
5209
5296
|
for (const swap of await this.getPendingSubmarineSwapsFromStorage()) {
|
|
5210
5297
|
if (isSubmarineFinalStatus(swap.status)) continue;
|
|
5211
5298
|
promises.push(
|
|
5212
|
-
this.getSwapStatus(swap.id).then(
|
|
5213
|
-
|
|
5299
|
+
this.getSwapStatus(swap.id).then(async ({ status }) => {
|
|
5300
|
+
let additionalFields;
|
|
5301
|
+
if (isSubmarineSuccessStatus(status) && !swap.preimage) {
|
|
5302
|
+
try {
|
|
5303
|
+
const { preimage } = await this.swapProvider.getSwapPreimage(
|
|
5304
|
+
swap.id
|
|
5305
|
+
);
|
|
5306
|
+
additionalFields = { preimage };
|
|
5307
|
+
} catch (error) {
|
|
5308
|
+
logger.warn(
|
|
5309
|
+
`Failed to fetch preimage for settled swap ${swap.id}:`,
|
|
5310
|
+
error
|
|
5311
|
+
);
|
|
5312
|
+
}
|
|
5313
|
+
}
|
|
5314
|
+
await updateSubmarineSwapStatus(
|
|
5214
5315
|
swap,
|
|
5215
5316
|
status,
|
|
5216
|
-
this.savePendingSubmarineSwap.bind(this)
|
|
5217
|
-
|
|
5218
|
-
|
|
5317
|
+
this.savePendingSubmarineSwap.bind(this),
|
|
5318
|
+
additionalFields
|
|
5319
|
+
);
|
|
5320
|
+
}).catch((error) => {
|
|
5219
5321
|
logger.error(`Failed to refresh swap status for ${swap.id}:`, error);
|
|
5220
5322
|
})
|
|
5221
5323
|
);
|
|
@@ -5385,6 +5487,7 @@ export {
|
|
|
5385
5487
|
isSubmarineFinalStatus,
|
|
5386
5488
|
isSubmarinePendingStatus,
|
|
5387
5489
|
isSubmarineRefundableStatus,
|
|
5490
|
+
hasSubmarineStatusReached,
|
|
5388
5491
|
isSubmarineSuccessStatus,
|
|
5389
5492
|
isReverseFailedStatus,
|
|
5390
5493
|
isReverseFinalStatus,
|