@arkade-os/boltz-swap 0.3.34 → 0.3.36
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/dist/{arkade-swaps-CfMets16.d.cts → arkade-swaps-DG9UepoS.d.cts} +26 -5
- package/dist/{arkade-swaps-BXAD1s8j.d.ts → arkade-swaps-Uet3tgN6.d.ts} +26 -5
- package/dist/{chunk-TDBUZE4N.js → chunk-CFB2NNGT.js} +168 -70
- package/dist/{chunk-5K2FS2FE.js → chunk-DNCIVDU5.js} +1 -1
- package/dist/expo/background.cjs +168 -70
- 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 +168 -70
- package/dist/expo/index.d.cts +10 -6
- package/dist/expo/index.d.ts +10 -6
- package/dist/expo/index.js +2 -2
- package/dist/index.cjs +180 -78
- package/dist/index.d.cts +16 -6
- package/dist/index.d.ts +16 -6
- package/dist/index.js +13 -9
- 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-BpAqG0V6.d.cts → swapsPollProcessor-BlyUrhtO.d.cts} +1 -1
- package/dist/{swapsPollProcessor-DFVOAy_-.d.ts → swapsPollProcessor-Bv4Z2R7g.d.ts} +1 -1
- package/dist/{types--axEWA8c.d.cts → types-D97i1LFu.d.cts} +47 -4
- package/dist/{types--axEWA8c.d.ts → types-D97i1LFu.d.ts} +47 -4
- package/package.json +3 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IWallet, ArkProvider, IndexerProvider, ArkInfo, Identity, ArkTxInput, VHTLC } from '@arkade-os/sdk';
|
|
2
|
-
import { r as BoltzSwapProvider, x as SwapManager, n as SwapRepository, q as ArkadeSwapsCreateConfig, A as ArkadeSwapsConfig, o as SwapManagerClient, C as CreateLightningInvoiceRequest, e as CreateLightningInvoiceResponse, b as BoltzReverseSwap, S as SendLightningPaymentRequest, f as SendLightningPaymentResponse, c as BoltzSubmarineSwap, g as SubmarineRefundOutcome, h as SubmarineRecoveryInfo, i as SubmarineRecoveryResult, k as ArkToBtcResponse, a as BoltzChainSwap, m as ChainArkRefundOutcome, l as BtcToArkResponse, d as Chain, F as FeesResponse, j as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, B as BoltzSwap } from './types
|
|
2
|
+
import { r as BoltzSwapProvider, x as SwapManager, n as SwapRepository, q as ArkadeSwapsCreateConfig, A as ArkadeSwapsConfig, o as SwapManagerClient, C as CreateLightningInvoiceRequest, e as CreateLightningInvoiceResponse, b as BoltzReverseSwap, S as SendLightningPaymentRequest, f as SendLightningPaymentResponse, c as BoltzSubmarineSwap, g as SubmarineRefundOutcome, h as SubmarineRecoveryInfo, i as SubmarineRecoveryResult, k as ArkToBtcResponse, a as BoltzChainSwap, m as ChainArkRefundOutcome, l as BtcToArkResponse, d as Chain, F as FeesResponse, j as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, B as BoltzSwap } from './types-D97i1LFu.cjs';
|
|
3
3
|
import { TransactionOutput } from '@scure/btc-signer/psbt.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -264,8 +264,11 @@ declare class ArkadeSwaps {
|
|
|
264
264
|
/**
|
|
265
265
|
* Claim sats on BTC chain by claiming the HTLC.
|
|
266
266
|
* @param pendingSwap - The pending chain swap with BTC transaction hex.
|
|
267
|
+
* @returns The BTC transaction ID of the claim.
|
|
267
268
|
*/
|
|
268
|
-
claimBtc(pendingSwap: BoltzChainSwap): Promise<
|
|
269
|
+
claimBtc(pendingSwap: BoltzChainSwap): Promise<{
|
|
270
|
+
txid: string;
|
|
271
|
+
}>;
|
|
269
272
|
/**
|
|
270
273
|
* When an ARK to BTC swap fails, refund every unspent VTXO at the chain
|
|
271
274
|
* swap's ARK lockup address.
|
|
@@ -305,8 +308,22 @@ declare class ArkadeSwaps {
|
|
|
305
308
|
* Claim sats on ARK chain by claiming the VHTLC.
|
|
306
309
|
* Refactored to use claimVHTLCIdentity + claimVHTLCwithOffchainTx utilities.
|
|
307
310
|
* @param pendingSwap - The pending chain swap.
|
|
311
|
+
* @returns The Ark transaction ID of the claim.
|
|
308
312
|
*/
|
|
309
|
-
claimArk(pendingSwap: BoltzChainSwap): Promise<
|
|
313
|
+
claimArk(pendingSwap: BoltzChainSwap): Promise<{
|
|
314
|
+
txid: string;
|
|
315
|
+
}>;
|
|
316
|
+
/**
|
|
317
|
+
* Resolve the on-chain txid for a chain swap at completion.
|
|
318
|
+
*
|
|
319
|
+
* The claim transaction we broadcast (claimBtc/claimArk) carries the real
|
|
320
|
+
* on-chain txid; getSwapStatus does not surface it at transaction.claimed.
|
|
321
|
+
* Prefer the claim's txid and fall back to the provider status only for
|
|
322
|
+
* resumed swaps where we never ran the claim ourselves (claimPromise is
|
|
323
|
+
* undefined). Returns undefined when no usable txid is available, so
|
|
324
|
+
* callers never resolve with the Boltz swap id in place of a real txid.
|
|
325
|
+
*/
|
|
326
|
+
private resolveChainClaimTxid;
|
|
310
327
|
/**
|
|
311
328
|
* Sign a cooperative claim for the server in BTC => ARK swaps.
|
|
312
329
|
* @param pendingSwap - The pending chain swap.
|
|
@@ -523,7 +540,9 @@ interface IArkadeSwaps extends AsyncDisposable {
|
|
|
523
540
|
waitAndClaimBtc(pendingSwap: BoltzChainSwap): Promise<{
|
|
524
541
|
txid: string;
|
|
525
542
|
}>;
|
|
526
|
-
claimBtc(pendingSwap: BoltzChainSwap): Promise<
|
|
543
|
+
claimBtc(pendingSwap: BoltzChainSwap): Promise<{
|
|
544
|
+
txid: string;
|
|
545
|
+
}>;
|
|
527
546
|
refundArk(pendingSwap: BoltzChainSwap): Promise<ChainArkRefundOutcome>;
|
|
528
547
|
btcToArk(args: {
|
|
529
548
|
feeSatsPerByte?: number;
|
|
@@ -533,7 +552,9 @@ interface IArkadeSwaps extends AsyncDisposable {
|
|
|
533
552
|
waitAndClaimArk(pendingSwap: BoltzChainSwap): Promise<{
|
|
534
553
|
txid: string;
|
|
535
554
|
}>;
|
|
536
|
-
claimArk(pendingSwap: BoltzChainSwap): Promise<
|
|
555
|
+
claimArk(pendingSwap: BoltzChainSwap): Promise<{
|
|
556
|
+
txid: string;
|
|
557
|
+
}>;
|
|
537
558
|
signCooperativeClaimForServer(pendingSwap: BoltzChainSwap): Promise<void>;
|
|
538
559
|
waitAndClaimChain(pendingSwap: BoltzChainSwap): Promise<{
|
|
539
560
|
txid: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IWallet, ArkProvider, IndexerProvider, ArkInfo, Identity, ArkTxInput, VHTLC } from '@arkade-os/sdk';
|
|
2
|
-
import { r as BoltzSwapProvider, x as SwapManager, n as SwapRepository, q as ArkadeSwapsCreateConfig, A as ArkadeSwapsConfig, o as SwapManagerClient, C as CreateLightningInvoiceRequest, e as CreateLightningInvoiceResponse, b as BoltzReverseSwap, S as SendLightningPaymentRequest, f as SendLightningPaymentResponse, c as BoltzSubmarineSwap, g as SubmarineRefundOutcome, h as SubmarineRecoveryInfo, i as SubmarineRecoveryResult, k as ArkToBtcResponse, a as BoltzChainSwap, m as ChainArkRefundOutcome, l as BtcToArkResponse, d as Chain, F as FeesResponse, j as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, B as BoltzSwap } from './types
|
|
2
|
+
import { r as BoltzSwapProvider, x as SwapManager, n as SwapRepository, q as ArkadeSwapsCreateConfig, A as ArkadeSwapsConfig, o as SwapManagerClient, C as CreateLightningInvoiceRequest, e as CreateLightningInvoiceResponse, b as BoltzReverseSwap, S as SendLightningPaymentRequest, f as SendLightningPaymentResponse, c as BoltzSubmarineSwap, g as SubmarineRefundOutcome, h as SubmarineRecoveryInfo, i as SubmarineRecoveryResult, k as ArkToBtcResponse, a as BoltzChainSwap, m as ChainArkRefundOutcome, l as BtcToArkResponse, d as Chain, F as FeesResponse, j as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, B as BoltzSwap } from './types-D97i1LFu.js';
|
|
3
3
|
import { TransactionOutput } from '@scure/btc-signer/psbt.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -264,8 +264,11 @@ declare class ArkadeSwaps {
|
|
|
264
264
|
/**
|
|
265
265
|
* Claim sats on BTC chain by claiming the HTLC.
|
|
266
266
|
* @param pendingSwap - The pending chain swap with BTC transaction hex.
|
|
267
|
+
* @returns The BTC transaction ID of the claim.
|
|
267
268
|
*/
|
|
268
|
-
claimBtc(pendingSwap: BoltzChainSwap): Promise<
|
|
269
|
+
claimBtc(pendingSwap: BoltzChainSwap): Promise<{
|
|
270
|
+
txid: string;
|
|
271
|
+
}>;
|
|
269
272
|
/**
|
|
270
273
|
* When an ARK to BTC swap fails, refund every unspent VTXO at the chain
|
|
271
274
|
* swap's ARK lockup address.
|
|
@@ -305,8 +308,22 @@ declare class ArkadeSwaps {
|
|
|
305
308
|
* Claim sats on ARK chain by claiming the VHTLC.
|
|
306
309
|
* Refactored to use claimVHTLCIdentity + claimVHTLCwithOffchainTx utilities.
|
|
307
310
|
* @param pendingSwap - The pending chain swap.
|
|
311
|
+
* @returns The Ark transaction ID of the claim.
|
|
308
312
|
*/
|
|
309
|
-
claimArk(pendingSwap: BoltzChainSwap): Promise<
|
|
313
|
+
claimArk(pendingSwap: BoltzChainSwap): Promise<{
|
|
314
|
+
txid: string;
|
|
315
|
+
}>;
|
|
316
|
+
/**
|
|
317
|
+
* Resolve the on-chain txid for a chain swap at completion.
|
|
318
|
+
*
|
|
319
|
+
* The claim transaction we broadcast (claimBtc/claimArk) carries the real
|
|
320
|
+
* on-chain txid; getSwapStatus does not surface it at transaction.claimed.
|
|
321
|
+
* Prefer the claim's txid and fall back to the provider status only for
|
|
322
|
+
* resumed swaps where we never ran the claim ourselves (claimPromise is
|
|
323
|
+
* undefined). Returns undefined when no usable txid is available, so
|
|
324
|
+
* callers never resolve with the Boltz swap id in place of a real txid.
|
|
325
|
+
*/
|
|
326
|
+
private resolveChainClaimTxid;
|
|
310
327
|
/**
|
|
311
328
|
* Sign a cooperative claim for the server in BTC => ARK swaps.
|
|
312
329
|
* @param pendingSwap - The pending chain swap.
|
|
@@ -523,7 +540,9 @@ interface IArkadeSwaps extends AsyncDisposable {
|
|
|
523
540
|
waitAndClaimBtc(pendingSwap: BoltzChainSwap): Promise<{
|
|
524
541
|
txid: string;
|
|
525
542
|
}>;
|
|
526
|
-
claimBtc(pendingSwap: BoltzChainSwap): Promise<
|
|
543
|
+
claimBtc(pendingSwap: BoltzChainSwap): Promise<{
|
|
544
|
+
txid: string;
|
|
545
|
+
}>;
|
|
527
546
|
refundArk(pendingSwap: BoltzChainSwap): Promise<ChainArkRefundOutcome>;
|
|
528
547
|
btcToArk(args: {
|
|
529
548
|
feeSatsPerByte?: number;
|
|
@@ -533,7 +552,9 @@ interface IArkadeSwaps extends AsyncDisposable {
|
|
|
533
552
|
waitAndClaimArk(pendingSwap: BoltzChainSwap): Promise<{
|
|
534
553
|
txid: string;
|
|
535
554
|
}>;
|
|
536
|
-
claimArk(pendingSwap: BoltzChainSwap): Promise<
|
|
555
|
+
claimArk(pendingSwap: BoltzChainSwap): Promise<{
|
|
556
|
+
txid: string;
|
|
557
|
+
}>;
|
|
537
558
|
signCooperativeClaimForServer(pendingSwap: BoltzChainSwap): Promise<void>;
|
|
538
559
|
waitAndClaimChain(pendingSwap: BoltzChainSwap): Promise<{
|
|
539
560
|
txid: string;
|
|
@@ -1092,6 +1092,13 @@ var SwapManager = class _SwapManager {
|
|
|
1092
1092
|
swapsInProgress = /* @__PURE__ */ new Set();
|
|
1093
1093
|
// Per-swap subscriptions for UI hooks
|
|
1094
1094
|
swapSubscriptions = /* @__PURE__ */ new Map();
|
|
1095
|
+
// In-flight (or settled) chain-swap claim promises, keyed by swap id. The
|
|
1096
|
+
// manager performs chain claims itself, so the claim tx it broadcasts is
|
|
1097
|
+
// the swap's on-chain completion; getSwapStatus does not surface that txid
|
|
1098
|
+
// at transaction.claimed. resolveClaimedTxid awaits the stored promise so a
|
|
1099
|
+
// transaction.claimed update that races an in-flight claim still resolves
|
|
1100
|
+
// the real txid instead of falling back to the provider and failing.
|
|
1101
|
+
chainClaimPromises = /* @__PURE__ */ new Map();
|
|
1095
1102
|
// Action callbacks (injected via setCallbacks)
|
|
1096
1103
|
claimCallback = null;
|
|
1097
1104
|
refundCallback = null;
|
|
@@ -1233,6 +1240,7 @@ var SwapManager = class _SwapManager {
|
|
|
1233
1240
|
}
|
|
1234
1241
|
this.isRunning = true;
|
|
1235
1242
|
this.initialSwaps.clear();
|
|
1243
|
+
this.chainClaimPromises.clear();
|
|
1236
1244
|
for (const swap of pendingSwaps) {
|
|
1237
1245
|
this.initialSwaps.set(swap.id, swap);
|
|
1238
1246
|
}
|
|
@@ -1326,6 +1334,7 @@ var SwapManager = class _SwapManager {
|
|
|
1326
1334
|
async removeSwap(swapId) {
|
|
1327
1335
|
this.monitoredSwaps.delete(swapId);
|
|
1328
1336
|
this.swapSubscriptions.delete(swapId);
|
|
1337
|
+
this.chainClaimPromises.delete(swapId);
|
|
1329
1338
|
const retryTimer = this.pollRetryTimers.get(swapId);
|
|
1330
1339
|
if (retryTimer) {
|
|
1331
1340
|
clearTimeout(retryTimer);
|
|
@@ -1368,9 +1377,14 @@ var SwapManager = class _SwapManager {
|
|
|
1368
1377
|
* Blocks until the swap reaches a final status or fails.
|
|
1369
1378
|
* Useful when you want blocking behavior even with SwapManager enabled.
|
|
1370
1379
|
*
|
|
1371
|
-
*
|
|
1372
|
-
*
|
|
1380
|
+
* If the swap is already in a final status, resolves immediately with the
|
|
1381
|
+
* on-chain txid of the successfully claimed swap (reverse: from
|
|
1382
|
+
* getReverseSwapTxId; submarine/chain: from getSwapStatus) and throws for a
|
|
1383
|
+
* failed final status.
|
|
1384
|
+
*
|
|
1385
|
+
* @throws If the swap is already in a failed final status.
|
|
1373
1386
|
* @throws If the swap is not found in the manager.
|
|
1387
|
+
* @throws If a completed swap has no transaction id available yet.
|
|
1374
1388
|
*/
|
|
1375
1389
|
async waitForSwapCompletion(swapId) {
|
|
1376
1390
|
let swap = this.monitoredSwaps.get(swapId);
|
|
@@ -1385,10 +1399,12 @@ var SwapManager = class _SwapManager {
|
|
|
1385
1399
|
const response = await this.swapProvider.getReverseSwapTxId(swap.id);
|
|
1386
1400
|
return { txid: response.id };
|
|
1387
1401
|
}
|
|
1388
|
-
if (isPendingSubmarineSwap(swap)) {
|
|
1389
|
-
|
|
1402
|
+
if (isPendingSubmarineSwap(swap) || isPendingChainSwap(swap)) {
|
|
1403
|
+
if (swap.status === "transaction.claimed") {
|
|
1404
|
+
return this.resolveClaimedTxid(swap.id);
|
|
1405
|
+
}
|
|
1406
|
+
throw new Error(`Swap ${swap.id} already in final status: ${swap.status}`);
|
|
1390
1407
|
}
|
|
1391
|
-
throw new Error("Chain swap already completed");
|
|
1392
1408
|
}
|
|
1393
1409
|
return new Promise((resolve, reject) => {
|
|
1394
1410
|
let unsubscribe = null;
|
|
@@ -1403,13 +1419,13 @@ var SwapManager = class _SwapManager {
|
|
|
1403
1419
|
}
|
|
1404
1420
|
} else if (isPendingSubmarineSwap(updatedSwap)) {
|
|
1405
1421
|
if (updatedSwap.status === "transaction.claimed") {
|
|
1406
|
-
|
|
1422
|
+
this.resolveClaimedTxid(updatedSwap.id).then(resolve).catch(reject);
|
|
1407
1423
|
} else {
|
|
1408
1424
|
reject(new Error(`Swap failed with status: ${updatedSwap.status}`));
|
|
1409
1425
|
}
|
|
1410
1426
|
} else if (isPendingChainSwap(updatedSwap)) {
|
|
1411
1427
|
if (updatedSwap.status === "transaction.claimed") {
|
|
1412
|
-
|
|
1428
|
+
this.resolveClaimedTxid(updatedSwap.id).then(resolve).catch(reject);
|
|
1413
1429
|
} else {
|
|
1414
1430
|
reject(new Error(`Swap failed with status: ${updatedSwap.status}`));
|
|
1415
1431
|
}
|
|
@@ -1420,6 +1436,37 @@ var SwapManager = class _SwapManager {
|
|
|
1420
1436
|
}).catch(reject);
|
|
1421
1437
|
});
|
|
1422
1438
|
}
|
|
1439
|
+
/**
|
|
1440
|
+
* Resolve the on-chain txid for a claimed submarine/chain swap.
|
|
1441
|
+
*
|
|
1442
|
+
* Chain swaps are claimed by the manager itself, so the claim txid captured
|
|
1443
|
+
* from the claimArk/claimBtc callback is the swap's on-chain completion and
|
|
1444
|
+
* is preferred — Boltz does not surface it via getSwapStatus at
|
|
1445
|
+
* transaction.claimed. Submarine swaps (claimed by Boltz) and chain swaps
|
|
1446
|
+
* we never claimed in this session (e.g. restored already-claimed) fall
|
|
1447
|
+
* back to the provider status. Rejects when no transaction id is available,
|
|
1448
|
+
* so callers never receive the Boltz swap id in place of a real txid.
|
|
1449
|
+
*/
|
|
1450
|
+
async resolveClaimedTxid(swapId) {
|
|
1451
|
+
const claimPromise = this.chainClaimPromises.get(swapId);
|
|
1452
|
+
if (claimPromise) {
|
|
1453
|
+
const claimTxid = await claimPromise.then(
|
|
1454
|
+
(result) => result?.txid,
|
|
1455
|
+
() => void 0
|
|
1456
|
+
);
|
|
1457
|
+
if (claimTxid && claimTxid.trim() !== "") {
|
|
1458
|
+
return { txid: claimTxid };
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
const status = await this.swapProvider.getSwapStatus(swapId);
|
|
1462
|
+
const txid = status.transaction?.id;
|
|
1463
|
+
if (!txid || txid.trim() === "") {
|
|
1464
|
+
throw new SwapError({
|
|
1465
|
+
message: `Transaction ID not available for completed swap ${swapId}`
|
|
1466
|
+
});
|
|
1467
|
+
}
|
|
1468
|
+
return { txid };
|
|
1469
|
+
}
|
|
1423
1470
|
/**
|
|
1424
1471
|
* Check if a swap is currently being processed
|
|
1425
1472
|
* Useful for preventing race conditions
|
|
@@ -1623,6 +1670,7 @@ var SwapManager = class _SwapManager {
|
|
|
1623
1670
|
if (!this.monitoredSwaps.has(swap.id)) return;
|
|
1624
1671
|
this.monitoredSwaps.delete(swap.id);
|
|
1625
1672
|
this.swapSubscriptions.delete(swap.id);
|
|
1673
|
+
this.chainClaimPromises.delete(swap.id);
|
|
1626
1674
|
const retryTimer = this.pollRetryTimers.get(swap.id);
|
|
1627
1675
|
if (retryTimer) {
|
|
1628
1676
|
clearTimeout(retryTimer);
|
|
@@ -1793,7 +1841,9 @@ var SwapManager = class _SwapManager {
|
|
|
1793
1841
|
logger.error("claimArk callback not set");
|
|
1794
1842
|
return;
|
|
1795
1843
|
}
|
|
1796
|
-
|
|
1844
|
+
const claimPromise = this.claimArkCallback(swap);
|
|
1845
|
+
this.rememberChainClaim(swap.id, claimPromise);
|
|
1846
|
+
await claimPromise;
|
|
1797
1847
|
}
|
|
1798
1848
|
/**
|
|
1799
1849
|
* Execute claim action for chain swap Ark to Btc
|
|
@@ -1803,7 +1853,23 @@ var SwapManager = class _SwapManager {
|
|
|
1803
1853
|
logger.error("claimBtc callback not set");
|
|
1804
1854
|
return;
|
|
1805
1855
|
}
|
|
1806
|
-
|
|
1856
|
+
const claimPromise = this.claimBtcCallback(swap);
|
|
1857
|
+
this.rememberChainClaim(swap.id, claimPromise);
|
|
1858
|
+
await claimPromise;
|
|
1859
|
+
}
|
|
1860
|
+
/**
|
|
1861
|
+
* Store the in-flight claim promise returned by a claim callback so
|
|
1862
|
+
* {@link resolveClaimedTxid} can await it and surface the real on-chain
|
|
1863
|
+
* txid at transaction.claimed — even when that update races the still
|
|
1864
|
+
* in-flight claim. Storing the promise (not the resolved txid) closes the
|
|
1865
|
+
* window where the txid is not yet captured when transaction.claimed
|
|
1866
|
+
* arrives. Defensive against callbacks that don't return a promise (older
|
|
1867
|
+
* integrations, test doubles): those simply fall back to getSwapStatus.
|
|
1868
|
+
*/
|
|
1869
|
+
rememberChainClaim(swapId, claimPromise) {
|
|
1870
|
+
if (claimPromise) {
|
|
1871
|
+
this.chainClaimPromises.set(swapId, claimPromise);
|
|
1872
|
+
}
|
|
1807
1873
|
}
|
|
1808
1874
|
/**
|
|
1809
1875
|
* Execute refund action for chain swap Ark to Btc
|
|
@@ -2670,6 +2736,20 @@ function extractInvoiceAmount(amountSats, fees) {
|
|
|
2670
2736
|
if (miner >= amountSats) return 0;
|
|
2671
2737
|
return Math.ceil((amountSats - miner) / (1 - percentage / 100));
|
|
2672
2738
|
}
|
|
2739
|
+
function resolveVhtlcTimeouts(tree, timeoutBlockHeights) {
|
|
2740
|
+
const resolved = timeoutBlockHeights ?? {
|
|
2741
|
+
refund: extractTimeLockFromLeafOutput(tree.refundWithoutBoltzLeaf?.output ?? ""),
|
|
2742
|
+
unilateralClaim: extractTimeLockFromLeafOutput(tree.unilateralClaimLeaf?.output ?? ""),
|
|
2743
|
+
unilateralRefund: extractTimeLockFromLeafOutput(tree.unilateralRefundLeaf?.output ?? ""),
|
|
2744
|
+
unilateralRefundWithoutReceiver: extractTimeLockFromLeafOutput(
|
|
2745
|
+
tree.unilateralRefundWithoutBoltzLeaf?.output ?? ""
|
|
2746
|
+
)
|
|
2747
|
+
};
|
|
2748
|
+
if (!resolved.refund || !resolved.unilateralClaim || !resolved.unilateralRefund || !resolved.unilateralRefundWithoutReceiver) {
|
|
2749
|
+
return void 0;
|
|
2750
|
+
}
|
|
2751
|
+
return resolved;
|
|
2752
|
+
}
|
|
2673
2753
|
|
|
2674
2754
|
// src/utils/identity.ts
|
|
2675
2755
|
import { ConditionWitness, setArkPsbtField, Transaction as Transaction3 } from "@arkade-os/sdk";
|
|
@@ -2989,6 +3069,7 @@ var claimVHTLCwithOffchainTx = async (identity, vhtlcScript, serverXOnlyPublicKe
|
|
|
2989
3069
|
})
|
|
2990
3070
|
);
|
|
2991
3071
|
await arkProvider.finalizeTx(arkTxid, finalCheckpoints);
|
|
3072
|
+
return arkTxid;
|
|
2992
3073
|
};
|
|
2993
3074
|
var refundVHTLCwithOffchainTx = async (swapId, identity, arkProvider, boltzXOnlyPublicKey, ourXOnlyPublicKey, serverXOnlyPublicKey, input, output, arkInfo, refundFunc) => {
|
|
2994
3075
|
const rawCheckpointTapscript = hex7.decode(arkInfo.checkpointTapscript);
|
|
@@ -3147,12 +3228,8 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3147
3228
|
refund: async (swap) => {
|
|
3148
3229
|
await this.refundVHTLC(swap);
|
|
3149
3230
|
},
|
|
3150
|
-
claimArk:
|
|
3151
|
-
|
|
3152
|
-
},
|
|
3153
|
-
claimBtc: async (swap) => {
|
|
3154
|
-
await this.claimBtc(swap);
|
|
3155
|
-
},
|
|
3231
|
+
claimArk: (swap) => this.claimArk(swap),
|
|
3232
|
+
claimBtc: (swap) => this.claimBtc(swap),
|
|
3156
3233
|
refundArk: async (swap) => {
|
|
3157
3234
|
return this.refundArk(swap);
|
|
3158
3235
|
},
|
|
@@ -4163,6 +4240,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4163
4240
|
}
|
|
4164
4241
|
return new Promise((resolve, reject) => {
|
|
4165
4242
|
let claimStarted = false;
|
|
4243
|
+
let claimPromise;
|
|
4166
4244
|
const swap = { ...pendingSwap };
|
|
4167
4245
|
const onStatusUpdate = async (status, data) => {
|
|
4168
4246
|
const updateSwapStatus = async () => {
|
|
@@ -4180,16 +4258,24 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4180
4258
|
const updatedSwap = await updateSwapStatus();
|
|
4181
4259
|
if (claimStarted) return;
|
|
4182
4260
|
claimStarted = true;
|
|
4183
|
-
this.claimBtc(updatedSwap)
|
|
4261
|
+
claimPromise = this.claimBtc(updatedSwap);
|
|
4262
|
+
claimPromise.catch(reject);
|
|
4184
4263
|
break;
|
|
4185
4264
|
}
|
|
4186
|
-
case "transaction.claimed":
|
|
4265
|
+
case "transaction.claimed": {
|
|
4187
4266
|
await updateSwapStatus();
|
|
4188
|
-
const
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4267
|
+
const txid = await this.resolveChainClaimTxid(pendingSwap.id, claimPromise);
|
|
4268
|
+
if (!txid) {
|
|
4269
|
+
reject(
|
|
4270
|
+
new SwapError({
|
|
4271
|
+
message: `Transaction ID not available for claimed swap ${pendingSwap.id}.`
|
|
4272
|
+
})
|
|
4273
|
+
);
|
|
4274
|
+
break;
|
|
4275
|
+
}
|
|
4276
|
+
resolve({ txid });
|
|
4192
4277
|
break;
|
|
4278
|
+
}
|
|
4193
4279
|
case "transaction.lockupFailed":
|
|
4194
4280
|
await updateSwapStatus();
|
|
4195
4281
|
await this.quoteSwap(swap.response.id, quoteOptionsForSwap(swap)).catch(
|
|
@@ -4238,6 +4324,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4238
4324
|
/**
|
|
4239
4325
|
* Claim sats on BTC chain by claiming the HTLC.
|
|
4240
4326
|
* @param pendingSwap - The pending chain swap with BTC transaction hex.
|
|
4327
|
+
* @returns The BTC transaction ID of the claim.
|
|
4241
4328
|
*/
|
|
4242
4329
|
async claimBtc(pendingSwap) {
|
|
4243
4330
|
if (!pendingSwap.toAddress)
|
|
@@ -4310,6 +4397,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4310
4397
|
finalScriptWitness: [musigSigned.aggregatePartials()]
|
|
4311
4398
|
});
|
|
4312
4399
|
await this.swapProvider.postBtcTransaction(claimTx.hex);
|
|
4400
|
+
return { txid: claimTx.id };
|
|
4313
4401
|
}
|
|
4314
4402
|
/**
|
|
4315
4403
|
* When an ARK to BTC swap fails, refund every unspent VTXO at the chain
|
|
@@ -4509,6 +4597,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4509
4597
|
}
|
|
4510
4598
|
return new Promise((resolve, reject) => {
|
|
4511
4599
|
let claimStarted = false;
|
|
4600
|
+
let claimPromise;
|
|
4512
4601
|
const swap = { ...pendingSwap };
|
|
4513
4602
|
const onStatusUpdate = async (status, data) => {
|
|
4514
4603
|
const updateSwapStatus = () => {
|
|
@@ -4521,15 +4610,23 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4521
4610
|
await updateSwapStatus();
|
|
4522
4611
|
if (claimStarted) return;
|
|
4523
4612
|
claimStarted = true;
|
|
4524
|
-
this.claimArk(swap)
|
|
4613
|
+
claimPromise = this.claimArk(swap);
|
|
4614
|
+
claimPromise.catch(reject);
|
|
4525
4615
|
break;
|
|
4526
|
-
case "transaction.claimed":
|
|
4616
|
+
case "transaction.claimed": {
|
|
4527
4617
|
await updateSwapStatus();
|
|
4528
|
-
const
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4618
|
+
const txid = await this.resolveChainClaimTxid(pendingSwap.id, claimPromise);
|
|
4619
|
+
if (!txid) {
|
|
4620
|
+
reject(
|
|
4621
|
+
new SwapError({
|
|
4622
|
+
message: `Transaction ID not available for claimed swap ${pendingSwap.id}.`
|
|
4623
|
+
})
|
|
4624
|
+
);
|
|
4625
|
+
break;
|
|
4626
|
+
}
|
|
4627
|
+
resolve({ txid });
|
|
4532
4628
|
break;
|
|
4629
|
+
}
|
|
4533
4630
|
case "transaction.claim.pending":
|
|
4534
4631
|
await updateSwapStatus();
|
|
4535
4632
|
await this.signCooperativeClaimForServer(swap).catch((err) => {
|
|
@@ -4588,6 +4685,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4588
4685
|
* Claim sats on ARK chain by claiming the VHTLC.
|
|
4589
4686
|
* Refactored to use claimVHTLCIdentity + claimVHTLCwithOffchainTx utilities.
|
|
4590
4687
|
* @param pendingSwap - The pending chain swap.
|
|
4688
|
+
* @returns The Ark transaction ID of the claim.
|
|
4591
4689
|
*/
|
|
4592
4690
|
async claimArk(pendingSwap) {
|
|
4593
4691
|
if (!pendingSwap.toAddress)
|
|
@@ -4650,24 +4748,42 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4650
4748
|
script: ArkAddress2.decode(address).pkScript
|
|
4651
4749
|
};
|
|
4652
4750
|
const vhtlcIdentity = claimVHTLCIdentity(this.wallet.identity, preimage);
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
arkInfo,
|
|
4663
|
-
this.arkProvider
|
|
4664
|
-
);
|
|
4665
|
-
}
|
|
4751
|
+
const txid = isRecoverable(vtxo) ? await this.joinBatch(vhtlcIdentity, input, output, arkInfo) : await claimVHTLCwithOffchainTx(
|
|
4752
|
+
vhtlcIdentity,
|
|
4753
|
+
vhtlcScript,
|
|
4754
|
+
serverXOnlyPublicKey,
|
|
4755
|
+
input,
|
|
4756
|
+
output,
|
|
4757
|
+
arkInfo,
|
|
4758
|
+
this.arkProvider
|
|
4759
|
+
);
|
|
4666
4760
|
const finalStatus = await this.getSwapStatus(pendingSwap.id);
|
|
4667
4761
|
await this.savePendingChainSwap({
|
|
4668
4762
|
...pendingSwap,
|
|
4669
4763
|
status: finalStatus.status
|
|
4670
4764
|
});
|
|
4765
|
+
return { txid };
|
|
4766
|
+
}
|
|
4767
|
+
/**
|
|
4768
|
+
* Resolve the on-chain txid for a chain swap at completion.
|
|
4769
|
+
*
|
|
4770
|
+
* The claim transaction we broadcast (claimBtc/claimArk) carries the real
|
|
4771
|
+
* on-chain txid; getSwapStatus does not surface it at transaction.claimed.
|
|
4772
|
+
* Prefer the claim's txid and fall back to the provider status only for
|
|
4773
|
+
* resumed swaps where we never ran the claim ourselves (claimPromise is
|
|
4774
|
+
* undefined). Returns undefined when no usable txid is available, so
|
|
4775
|
+
* callers never resolve with the Boltz swap id in place of a real txid.
|
|
4776
|
+
*/
|
|
4777
|
+
async resolveChainClaimTxid(swapId, claimPromise) {
|
|
4778
|
+
if (claimPromise) {
|
|
4779
|
+
const claimTxid = await claimPromise.then(
|
|
4780
|
+
(res) => res.txid,
|
|
4781
|
+
() => void 0
|
|
4782
|
+
);
|
|
4783
|
+
if (claimTxid && claimTxid.trim() !== "") return claimTxid;
|
|
4784
|
+
}
|
|
4785
|
+
const txid = (await this.getSwapStatus(swapId)).transaction?.id;
|
|
4786
|
+
return txid && txid.trim() !== "" ? txid : void 0;
|
|
4671
4787
|
}
|
|
4672
4788
|
/**
|
|
4673
4789
|
* Sign a cooperative claim for the server in BTC => ARK swaps.
|
|
@@ -5111,20 +5227,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
5111
5227
|
onchainAmount: amount,
|
|
5112
5228
|
lockupAddress,
|
|
5113
5229
|
refundPublicKey: serverPublicKey,
|
|
5114
|
-
timeoutBlockHeights: timeoutBlockHeights
|
|
5115
|
-
refund: extractTimeLockFromLeafOutput(
|
|
5116
|
-
tree.refundWithoutBoltzLeaf?.output ?? ""
|
|
5117
|
-
),
|
|
5118
|
-
unilateralClaim: extractTimeLockFromLeafOutput(
|
|
5119
|
-
tree.unilateralClaimLeaf?.output ?? ""
|
|
5120
|
-
),
|
|
5121
|
-
unilateralRefund: extractTimeLockFromLeafOutput(
|
|
5122
|
-
tree.unilateralRefundLeaf?.output ?? ""
|
|
5123
|
-
),
|
|
5124
|
-
unilateralRefundWithoutReceiver: extractTimeLockFromLeafOutput(
|
|
5125
|
-
tree.unilateralRefundWithoutBoltzLeaf?.output ?? ""
|
|
5126
|
-
)
|
|
5127
|
-
}
|
|
5230
|
+
timeoutBlockHeights: resolveVhtlcTimeouts(tree, timeoutBlockHeights)
|
|
5128
5231
|
},
|
|
5129
5232
|
status,
|
|
5130
5233
|
type: "reverse",
|
|
@@ -5157,26 +5260,20 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
5157
5260
|
address: lockupAddress,
|
|
5158
5261
|
expectedAmount: amount,
|
|
5159
5262
|
claimPublicKey: serverPublicKey,
|
|
5160
|
-
timeoutBlockHeights: timeoutBlockHeights
|
|
5161
|
-
refund: extractTimeLockFromLeafOutput(
|
|
5162
|
-
tree.refundWithoutBoltzLeaf?.output ?? ""
|
|
5163
|
-
),
|
|
5164
|
-
unilateralClaim: extractTimeLockFromLeafOutput(
|
|
5165
|
-
tree.unilateralClaimLeaf?.output ?? ""
|
|
5166
|
-
),
|
|
5167
|
-
unilateralRefund: extractTimeLockFromLeafOutput(
|
|
5168
|
-
tree.unilateralRefundLeaf?.output ?? ""
|
|
5169
|
-
),
|
|
5170
|
-
unilateralRefundWithoutReceiver: extractTimeLockFromLeafOutput(
|
|
5171
|
-
tree.unilateralRefundWithoutBoltzLeaf?.output ?? ""
|
|
5172
|
-
)
|
|
5173
|
-
}
|
|
5263
|
+
timeoutBlockHeights: resolveVhtlcTimeouts(tree, timeoutBlockHeights)
|
|
5174
5264
|
}
|
|
5175
5265
|
});
|
|
5176
5266
|
} else if (isRestoredChainSwap(swap)) {
|
|
5177
5267
|
const refundDetails = swap.refundDetails;
|
|
5178
5268
|
if (!refundDetails) continue;
|
|
5179
|
-
const {
|
|
5269
|
+
const {
|
|
5270
|
+
amount,
|
|
5271
|
+
lockupAddress,
|
|
5272
|
+
serverPublicKey,
|
|
5273
|
+
timeoutBlockHeight,
|
|
5274
|
+
tree,
|
|
5275
|
+
timeoutBlockHeights
|
|
5276
|
+
} = refundDetails;
|
|
5180
5277
|
chainSwaps.push({
|
|
5181
5278
|
id,
|
|
5182
5279
|
type: "chain",
|
|
@@ -5202,7 +5299,8 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
5202
5299
|
amount,
|
|
5203
5300
|
lockupAddress,
|
|
5204
5301
|
serverPublicKey,
|
|
5205
|
-
timeoutBlockHeight
|
|
5302
|
+
timeoutBlockHeight,
|
|
5303
|
+
timeouts: resolveVhtlcTimeouts(tree, timeoutBlockHeights)
|
|
5206
5304
|
}
|
|
5207
5305
|
}
|
|
5208
5306
|
});
|