@arkade-os/boltz-swap 0.3.35 → 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.
@@ -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--axEWA8c.cjs';
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<void>;
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<void>;
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<void>;
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<void>;
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--axEWA8c.js';
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<void>;
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<void>;
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<void>;
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<void>;
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
- * @throws If the swap is already in a final status (submarine/chain swaps throw immediately;
1372
- * reverse swaps return the existing txid).
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
- throw new Error("Submarine swap already completed");
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
- resolve({ txid: updatedSwap.id });
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
- resolve({ txid: updatedSwap.id });
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
- await this.claimArkCallback(swap);
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
- await this.claimBtcCallback(swap);
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
@@ -3003,6 +3069,7 @@ var claimVHTLCwithOffchainTx = async (identity, vhtlcScript, serverXOnlyPublicKe
3003
3069
  })
3004
3070
  );
3005
3071
  await arkProvider.finalizeTx(arkTxid, finalCheckpoints);
3072
+ return arkTxid;
3006
3073
  };
3007
3074
  var refundVHTLCwithOffchainTx = async (swapId, identity, arkProvider, boltzXOnlyPublicKey, ourXOnlyPublicKey, serverXOnlyPublicKey, input, output, arkInfo, refundFunc) => {
3008
3075
  const rawCheckpointTapscript = hex7.decode(arkInfo.checkpointTapscript);
@@ -3161,12 +3228,8 @@ var ArkadeSwaps = class _ArkadeSwaps {
3161
3228
  refund: async (swap) => {
3162
3229
  await this.refundVHTLC(swap);
3163
3230
  },
3164
- claimArk: async (swap) => {
3165
- await this.claimArk(swap);
3166
- },
3167
- claimBtc: async (swap) => {
3168
- await this.claimBtc(swap);
3169
- },
3231
+ claimArk: (swap) => this.claimArk(swap),
3232
+ claimBtc: (swap) => this.claimBtc(swap),
3170
3233
  refundArk: async (swap) => {
3171
3234
  return this.refundArk(swap);
3172
3235
  },
@@ -4177,6 +4240,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
4177
4240
  }
4178
4241
  return new Promise((resolve, reject) => {
4179
4242
  let claimStarted = false;
4243
+ let claimPromise;
4180
4244
  const swap = { ...pendingSwap };
4181
4245
  const onStatusUpdate = async (status, data) => {
4182
4246
  const updateSwapStatus = async () => {
@@ -4194,16 +4258,24 @@ var ArkadeSwaps = class _ArkadeSwaps {
4194
4258
  const updatedSwap = await updateSwapStatus();
4195
4259
  if (claimStarted) return;
4196
4260
  claimStarted = true;
4197
- this.claimBtc(updatedSwap).catch(reject);
4261
+ claimPromise = this.claimBtc(updatedSwap);
4262
+ claimPromise.catch(reject);
4198
4263
  break;
4199
4264
  }
4200
- case "transaction.claimed":
4265
+ case "transaction.claimed": {
4201
4266
  await updateSwapStatus();
4202
- const claimedStatus = await this.getSwapStatus(pendingSwap.id);
4203
- resolve({
4204
- txid: claimedStatus.transaction?.id ?? ""
4205
- });
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 });
4206
4277
  break;
4278
+ }
4207
4279
  case "transaction.lockupFailed":
4208
4280
  await updateSwapStatus();
4209
4281
  await this.quoteSwap(swap.response.id, quoteOptionsForSwap(swap)).catch(
@@ -4252,6 +4324,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
4252
4324
  /**
4253
4325
  * Claim sats on BTC chain by claiming the HTLC.
4254
4326
  * @param pendingSwap - The pending chain swap with BTC transaction hex.
4327
+ * @returns The BTC transaction ID of the claim.
4255
4328
  */
4256
4329
  async claimBtc(pendingSwap) {
4257
4330
  if (!pendingSwap.toAddress)
@@ -4324,6 +4397,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
4324
4397
  finalScriptWitness: [musigSigned.aggregatePartials()]
4325
4398
  });
4326
4399
  await this.swapProvider.postBtcTransaction(claimTx.hex);
4400
+ return { txid: claimTx.id };
4327
4401
  }
4328
4402
  /**
4329
4403
  * When an ARK to BTC swap fails, refund every unspent VTXO at the chain
@@ -4523,6 +4597,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
4523
4597
  }
4524
4598
  return new Promise((resolve, reject) => {
4525
4599
  let claimStarted = false;
4600
+ let claimPromise;
4526
4601
  const swap = { ...pendingSwap };
4527
4602
  const onStatusUpdate = async (status, data) => {
4528
4603
  const updateSwapStatus = () => {
@@ -4535,15 +4610,23 @@ var ArkadeSwaps = class _ArkadeSwaps {
4535
4610
  await updateSwapStatus();
4536
4611
  if (claimStarted) return;
4537
4612
  claimStarted = true;
4538
- this.claimArk(swap).catch(reject);
4613
+ claimPromise = this.claimArk(swap);
4614
+ claimPromise.catch(reject);
4539
4615
  break;
4540
- case "transaction.claimed":
4616
+ case "transaction.claimed": {
4541
4617
  await updateSwapStatus();
4542
- const claimedStatus = await this.getSwapStatus(pendingSwap.id);
4543
- resolve({
4544
- txid: claimedStatus.transaction?.id ?? ""
4545
- });
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 });
4546
4628
  break;
4629
+ }
4547
4630
  case "transaction.claim.pending":
4548
4631
  await updateSwapStatus();
4549
4632
  await this.signCooperativeClaimForServer(swap).catch((err) => {
@@ -4602,6 +4685,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
4602
4685
  * Claim sats on ARK chain by claiming the VHTLC.
4603
4686
  * Refactored to use claimVHTLCIdentity + claimVHTLCwithOffchainTx utilities.
4604
4687
  * @param pendingSwap - The pending chain swap.
4688
+ * @returns The Ark transaction ID of the claim.
4605
4689
  */
4606
4690
  async claimArk(pendingSwap) {
4607
4691
  if (!pendingSwap.toAddress)
@@ -4664,24 +4748,42 @@ var ArkadeSwaps = class _ArkadeSwaps {
4664
4748
  script: ArkAddress2.decode(address).pkScript
4665
4749
  };
4666
4750
  const vhtlcIdentity = claimVHTLCIdentity(this.wallet.identity, preimage);
4667
- if (isRecoverable(vtxo)) {
4668
- await this.joinBatch(vhtlcIdentity, input, output, arkInfo);
4669
- } else {
4670
- await claimVHTLCwithOffchainTx(
4671
- vhtlcIdentity,
4672
- vhtlcScript,
4673
- serverXOnlyPublicKey,
4674
- input,
4675
- output,
4676
- arkInfo,
4677
- this.arkProvider
4678
- );
4679
- }
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
+ );
4680
4760
  const finalStatus = await this.getSwapStatus(pendingSwap.id);
4681
4761
  await this.savePendingChainSwap({
4682
4762
  ...pendingSwap,
4683
4763
  status: finalStatus.status
4684
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;
4685
4787
  }
4686
4788
  /**
4687
4789
  * Sign a cooperative claim for the server in BTC => ARK swaps.
@@ -7,7 +7,7 @@ import {
7
7
  isSubmarineFinalStatus,
8
8
  isSubmarineSwapRefundable,
9
9
  logger
10
- } from "./chunk-B4CYBKFJ.js";
10
+ } from "./chunk-CFB2NNGT.js";
11
11
 
12
12
  // src/expo/swapsPollProcessor.ts
13
13
  var SWAP_POLL_TASK_TYPE = "swap-poll";