@arkade-os/boltz-swap 0.3.15 → 0.3.17

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 { m as BoltzSwapProvider, V as SwapManager, j as SwapRepository, X as ArkadeSwapsCreateConfig, A as ArkadeSwapsConfig, k as SwapManagerClient, C as CreateLightningInvoiceRequest, e as CreateLightningInvoiceResponse, b as BoltzReverseSwap, S as SendLightningPaymentRequest, f as SendLightningPaymentResponse, c as BoltzSubmarineSwap, h as ArkToBtcResponse, a as BoltzChainSwap, i as BtcToArkResponse, d as Chain, F as FeesResponse, g as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, B as BoltzSwap } from './types-C-2sBQWJ.cjs';
2
+ import { m as BoltzSwapProvider, V as SwapManager, j as SwapRepository, X as ArkadeSwapsCreateConfig, A as ArkadeSwapsConfig, k as SwapManagerClient, C as CreateLightningInvoiceRequest, e as CreateLightningInvoiceResponse, b as BoltzReverseSwap, S as SendLightningPaymentRequest, f as SendLightningPaymentResponse, c as BoltzSubmarineSwap, h as ArkToBtcResponse, a as BoltzChainSwap, i as BtcToArkResponse, d as Chain, F as FeesResponse, g as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, B as BoltzSwap } from './types-CKxFfdEH.cjs';
3
3
  import { TransactionOutput } from '@scure/btc-signer/psbt.js';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { IWallet, ArkProvider, IndexerProvider, ArkInfo, Identity, ArkTxInput, VHTLC } from '@arkade-os/sdk';
2
- import { m as BoltzSwapProvider, V as SwapManager, j as SwapRepository, X as ArkadeSwapsCreateConfig, A as ArkadeSwapsConfig, k as SwapManagerClient, C as CreateLightningInvoiceRequest, e as CreateLightningInvoiceResponse, b as BoltzReverseSwap, S as SendLightningPaymentRequest, f as SendLightningPaymentResponse, c as BoltzSubmarineSwap, h as ArkToBtcResponse, a as BoltzChainSwap, i as BtcToArkResponse, d as Chain, F as FeesResponse, g as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, B as BoltzSwap } from './types-C-2sBQWJ.js';
2
+ import { m as BoltzSwapProvider, V as SwapManager, j as SwapRepository, X as ArkadeSwapsCreateConfig, A as ArkadeSwapsConfig, k as SwapManagerClient, C as CreateLightningInvoiceRequest, e as CreateLightningInvoiceResponse, b as BoltzReverseSwap, S as SendLightningPaymentRequest, f as SendLightningPaymentResponse, c as BoltzSubmarineSwap, h as ArkToBtcResponse, a as BoltzChainSwap, i as BtcToArkResponse, d as Chain, F as FeesResponse, g as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, B as BoltzSwap } from './types-CKxFfdEH.js';
3
3
  import { TransactionOutput } from '@scure/btc-signer/psbt.js';
4
4
 
5
5
  /**
@@ -2,8 +2,8 @@ import {
2
2
  defineExpoSwapBackgroundTask,
3
3
  registerExpoSwapBackgroundTask,
4
4
  unregisterExpoSwapBackgroundTask
5
- } from "./chunk-DPGNWPDB.js";
6
- import "./chunk-Y6GPJDXY.js";
5
+ } from "./chunk-GSCLW33R.js";
6
+ import "./chunk-CS6UXZP6.js";
7
7
  import "./chunk-3RG5ZIWI.js";
8
8
  export {
9
9
  defineExpoSwapBackgroundTask,
@@ -86,6 +86,13 @@ var TransactionRefundedError = class extends SwapError {
86
86
  this.name = "TransactionRefundedError";
87
87
  }
88
88
  };
89
+ var BoltzRefundError = class extends Error {
90
+ constructor(message, cause) {
91
+ super(message);
92
+ this.cause = cause;
93
+ this.name = "BoltzRefundError";
94
+ }
95
+ };
89
96
 
90
97
  // src/boltz-swap-provider.ts
91
98
  import { Transaction } from "@arkade-os/sdk";
@@ -366,6 +373,18 @@ var BoltzSwapProvider = class {
366
373
  max: response.ARK.BTC.limits.maximal
367
374
  };
368
375
  }
376
+ /** Returns the current BTC chain tip height from Boltz. */
377
+ async getChainHeight() {
378
+ const response = await this.request(
379
+ "/v2/chain/heights",
380
+ "GET"
381
+ );
382
+ if (typeof response?.BTC !== "number")
383
+ throw new SchemaError({
384
+ message: "error fetching chain heights"
385
+ });
386
+ return response.BTC;
387
+ }
369
388
  /** Gets the lockup transaction ID for a reverse swap. */
370
389
  async getReverseSwapTxId(id) {
371
390
  const res = await this.request(
@@ -446,7 +465,7 @@ var BoltzSwapProvider = class {
446
465
  invoiceAmount,
447
466
  claimPublicKey,
448
467
  preimageHash,
449
- ...description?.trim() ? { description: description.trim() } : {},
468
+ description: description?.trim() || "Send to Arkade address",
450
469
  ...this.referralId ? { referralId: this.referralId } : {}
451
470
  };
452
471
  const response = await this.request(
@@ -2869,10 +2888,22 @@ var refundVHTLCwithOffchainTx = async (swapId, identity, arkProvider, boltzXOnly
2869
2888
  `Expected one checkpoint transaction, got ${checkpointPtxs.length}`
2870
2889
  );
2871
2890
  const unsignedCheckpointTx = checkpointPtxs[0];
2872
- const {
2873
- transaction: boltzSignedRefundTx,
2874
- checkpoint: boltzSignedCheckpointTx
2875
- } = await refundFunc(swapId, unsignedRefundTx, unsignedCheckpointTx);
2891
+ let boltzSignedRefundTx;
2892
+ let boltzSignedCheckpointTx;
2893
+ try {
2894
+ const result = await refundFunc(
2895
+ swapId,
2896
+ unsignedRefundTx,
2897
+ unsignedCheckpointTx
2898
+ );
2899
+ boltzSignedRefundTx = result.transaction;
2900
+ boltzSignedCheckpointTx = result.checkpoint;
2901
+ } catch (error) {
2902
+ throw new BoltzRefundError(
2903
+ `Boltz rejected refund for swap ${swapId}`,
2904
+ error
2905
+ );
2906
+ }
2876
2907
  const boltzXOnlyPublicKeyHex = hex7.encode(boltzXOnlyPublicKey);
2877
2908
  const refundLeafHash = tapLeafHash3(
2878
2909
  scriptFromTapLeafScript(input.tapLeafScript)
@@ -3213,10 +3244,14 @@ var ArkadeSwaps = class _ArkadeSwaps {
3213
3244
  */
3214
3245
  async claimVHTLC(pendingSwap) {
3215
3246
  if (!pendingSwap.preimage)
3216
- throw new Error("Preimage is required to claim VHTLC");
3247
+ throw new Error(
3248
+ `Swap ${pendingSwap.id}: preimage is required to claim VHTLC`
3249
+ );
3217
3250
  const { refundPublicKey, lockupAddress, timeoutBlockHeights } = pendingSwap.response;
3218
3251
  if (!refundPublicKey || !lockupAddress || !timeoutBlockHeights)
3219
- throw new Error("Incomplete reverse swap response");
3252
+ throw new Error(
3253
+ `Swap ${pendingSwap.id}: incomplete reverse swap response`
3254
+ );
3220
3255
  const preimage = hex8.decode(pendingSwap.preimage);
3221
3256
  const arkInfo = await this.arkProvider.getInfo();
3222
3257
  const address = await this.wallet.getAddress();
@@ -3244,17 +3279,23 @@ var ArkadeSwaps = class _ArkadeSwaps {
3244
3279
  timeoutBlockHeights
3245
3280
  });
3246
3281
  if (!vhtlcScript.claimScript)
3247
- throw new Error("Failed to create VHTLC script for reverse swap");
3282
+ throw new Error(
3283
+ `Swap ${pendingSwap.id}: failed to create VHTLC script for reverse swap`
3284
+ );
3248
3285
  if (vhtlcAddress !== lockupAddress)
3249
- throw new Error("Boltz is trying to scam us");
3286
+ throw new Error(
3287
+ `Swap ${pendingSwap.id}: VHTLC address mismatch. Expected ${lockupAddress}, got ${vhtlcAddress}`
3288
+ );
3250
3289
  const { vtxos } = await this.indexerProvider.getVtxos({
3251
3290
  scripts: [hex8.encode(vhtlcScript.pkScript)]
3252
3291
  });
3253
3292
  if (vtxos.length === 0)
3254
- throw new Error("No spendable virtual coins found");
3293
+ throw new Error(
3294
+ `Swap ${pendingSwap.id}: no spendable virtual coins found`
3295
+ );
3255
3296
  const vtxo = vtxos[0];
3256
3297
  if (vtxo.isSpent) {
3257
- throw new Error("VHTLC is already spent");
3298
+ throw new Error(`Swap ${pendingSwap.id}: VHTLC is already spent`);
3258
3299
  }
3259
3300
  const input = {
3260
3301
  ...vtxo,
@@ -3387,7 +3428,9 @@ var ArkadeSwaps = class _ArkadeSwaps {
3387
3428
  async sendLightningPayment(args) {
3388
3429
  const pendingSwap = await this.createSubmarineSwap(args);
3389
3430
  if (!pendingSwap.response.address)
3390
- throw new Error("Missing address in submarine swap response");
3431
+ throw new Error(
3432
+ `Swap ${pendingSwap.id}: missing address in submarine swap response`
3433
+ );
3391
3434
  await this.savePendingSubmarineSwap(pendingSwap);
3392
3435
  const txid = await this.wallet.send({
3393
3436
  address: pendingSwap.response.address,
@@ -3457,7 +3500,9 @@ var ArkadeSwaps = class _ArkadeSwaps {
3457
3500
  async refundVHTLC(pendingSwap) {
3458
3501
  const preimageHash = pendingSwap.request.invoice ? getInvoicePaymentHash(pendingSwap.request.invoice) : pendingSwap.preimageHash;
3459
3502
  if (!preimageHash)
3460
- throw new Error("Preimage hash is required to refund VHTLC");
3503
+ throw new Error(
3504
+ `Swap ${pendingSwap.id}: preimage hash is required to refund VHTLC`
3505
+ );
3461
3506
  const arkInfo = await this.arkProvider.getInfo();
3462
3507
  const address = await this.wallet.getAddress();
3463
3508
  if (!address) throw new Error("Failed to get ark address from wallet");
@@ -3473,7 +3518,9 @@ var ArkadeSwaps = class _ArkadeSwaps {
3473
3518
  );
3474
3519
  const { claimPublicKey, timeoutBlockHeights } = pendingSwap.response;
3475
3520
  if (!claimPublicKey || !timeoutBlockHeights)
3476
- throw new Error("Incomplete submarine swap response");
3521
+ throw new Error(
3522
+ `Swap ${pendingSwap.id}: incomplete submarine swap response`
3523
+ );
3477
3524
  const boltzXOnlyPublicKey = normalizeToXOnlyKey(
3478
3525
  hex8.decode(claimPublicKey),
3479
3526
  "boltz",
@@ -3488,45 +3535,90 @@ var ArkadeSwaps = class _ArkadeSwaps {
3488
3535
  timeoutBlockHeights
3489
3536
  });
3490
3537
  if (!vhtlcScript.claimScript)
3491
- throw new Error("Failed to create VHTLC script for submarine swap");
3538
+ throw new Error(
3539
+ `Swap ${pendingSwap.id}: failed to create VHTLC script for submarine swap`
3540
+ );
3492
3541
  if (vhtlcAddress !== pendingSwap.response.address)
3493
3542
  throw new Error(
3494
3543
  `VHTLC address mismatch for swap ${pendingSwap.id}: expected ${pendingSwap.response.address}, got ${vhtlcAddress}`
3495
3544
  );
3496
3545
  const vhtlcPkScriptHex = hex8.encode(vhtlcScript.pkScript);
3497
- const { vtxos: spendableVtxos } = await this.indexerProvider.getVtxos({
3498
- scripts: [vhtlcPkScriptHex],
3499
- spendableOnly: true
3500
- });
3501
- if (spendableVtxos.length === 0) {
3546
+ const [spendableResult, recoverableResult] = await Promise.all([
3547
+ this.indexerProvider.getVtxos({
3548
+ scripts: [vhtlcPkScriptHex],
3549
+ spendableOnly: true
3550
+ }),
3551
+ this.indexerProvider.getVtxos({
3552
+ scripts: [vhtlcPkScriptHex],
3553
+ recoverableOnly: true
3554
+ })
3555
+ ]);
3556
+ const refundableVtxos = [
3557
+ ...new Map(
3558
+ [...spendableResult.vtxos, ...recoverableResult.vtxos].map(
3559
+ (vtxo) => [`${vtxo.txid}:${vtxo.vout}`, vtxo]
3560
+ )
3561
+ ).values()
3562
+ ];
3563
+ if (refundableVtxos.length === 0) {
3502
3564
  const { vtxos: allVtxos } = await this.indexerProvider.getVtxos({
3503
3565
  scripts: [vhtlcPkScriptHex]
3504
3566
  });
3567
+ if (allVtxos.length === 0) {
3568
+ throw new Error(
3569
+ `Swap ${pendingSwap.id}: VHTLC not found for address ${pendingSwap.response.address}`
3570
+ );
3571
+ }
3572
+ if (allVtxos.every((vtxo) => vtxo.isSpent)) {
3573
+ throw new Error(
3574
+ `Swap ${pendingSwap.id}: VHTLC is already spent`
3575
+ );
3576
+ }
3505
3577
  throw new Error(
3506
- allVtxos.length > 0 ? "VHTLC is already spent" : `VHTLC not found for address ${pendingSwap.response.address}`
3578
+ `Swap ${pendingSwap.id}: VHTLC has no refundable VTXOs yet`
3507
3579
  );
3508
3580
  }
3509
3581
  const outputScript = ArkAddress2.decode(address).pkScript;
3582
+ const refundWithoutReceiverLeaf = vhtlcScript.refundWithoutReceiver();
3583
+ const refundLocktime = BigInt(timeoutBlockHeights.refund);
3584
+ const currentBlockHeight = await this.swapProvider.getChainHeight();
3585
+ const cltvSatisfied = BigInt(currentBlockHeight) >= refundLocktime;
3510
3586
  let boltzCallCount = 0;
3511
- for (const vtxo of spendableVtxos) {
3587
+ let skippedCount = 0;
3588
+ for (const vtxo of refundableVtxos) {
3512
3589
  const isRecoverableVtxo = isRecoverable(vtxo);
3513
- const input = {
3514
- ...vtxo,
3515
- tapLeafScript: isRecoverableVtxo ? vhtlcScript.refundWithoutReceiver() : vhtlcScript.refund(),
3516
- tapTree: vhtlcScript.encode()
3517
- };
3518
3590
  const output = {
3519
3591
  amount: BigInt(vtxo.value),
3520
3592
  script: outputScript
3521
3593
  };
3522
- if (isRecoverableVtxo) {
3594
+ if (cltvSatisfied) {
3595
+ const input2 = {
3596
+ ...vtxo,
3597
+ tapLeafScript: refundWithoutReceiverLeaf,
3598
+ tapTree: vhtlcScript.encode()
3599
+ };
3523
3600
  await this.joinBatch(
3524
3601
  this.wallet.identity,
3525
- input,
3602
+ input2,
3526
3603
  output,
3527
- arkInfo
3604
+ arkInfo,
3605
+ isRecoverableVtxo
3606
+ );
3607
+ continue;
3608
+ }
3609
+ if (isRecoverableVtxo) {
3610
+ logger.error(
3611
+ `Swap ${pendingSwap.id}: recoverable VTXO ${vtxo.txid}:${vtxo.vout} cannot be refunded yet \u2014 refundWithoutReceiver locktime has not passed (refundLocktime=${timeoutBlockHeights.refund}, currentBlockHeight=${currentBlockHeight}). Refund will be retried after locktime.`
3528
3612
  );
3529
- } else {
3613
+ skippedCount++;
3614
+ continue;
3615
+ }
3616
+ const input = {
3617
+ ...vtxo,
3618
+ tapLeafScript: vhtlcScript.refund(),
3619
+ tapTree: vhtlcScript.encode()
3620
+ };
3621
+ try {
3530
3622
  if (boltzCallCount > 0) {
3531
3623
  await new Promise((r) => setTimeout(r, 2e3));
3532
3624
  }
@@ -3545,14 +3637,42 @@ var ArkadeSwaps = class _ArkadeSwaps {
3545
3637
  )
3546
3638
  );
3547
3639
  boltzCallCount++;
3640
+ } catch (error) {
3641
+ if (!(error instanceof BoltzRefundError)) {
3642
+ throw error;
3643
+ }
3644
+ const tipNow = await this.swapProvider.getChainHeight();
3645
+ if (BigInt(tipNow) < refundLocktime) {
3646
+ logger.error(
3647
+ `Swap ${pendingSwap.id}: Boltz rejected VTXO outpoint and refundWithoutReceiver locktime has not passed yet (currentBlockHeight=${tipNow}, locktime=${timeoutBlockHeights.refund}). Refund will be retried after locktime.`
3648
+ );
3649
+ skippedCount++;
3650
+ continue;
3651
+ }
3652
+ logger.warn(
3653
+ `Swap ${pendingSwap.id}: Boltz rejected VTXO outpoint, falling back to refundWithoutReceiver via joinBatch`
3654
+ );
3655
+ const fallbackInput = {
3656
+ ...vtxo,
3657
+ tapLeafScript: refundWithoutReceiverLeaf,
3658
+ tapTree: vhtlcScript.encode()
3659
+ };
3660
+ await this.joinBatch(
3661
+ this.wallet.identity,
3662
+ fallbackInput,
3663
+ output,
3664
+ arkInfo,
3665
+ false
3666
+ );
3548
3667
  }
3549
3668
  }
3669
+ const fullyRefunded = skippedCount === 0;
3550
3670
  await updateSubmarineSwapStatus(
3551
3671
  pendingSwap,
3552
3672
  pendingSwap.status,
3553
3673
  // Keep current status
3554
3674
  this.savePendingSubmarineSwap.bind(this),
3555
- { refundable: true, refunded: true }
3675
+ { refundable: true, refunded: fullyRefunded }
3556
3676
  );
3557
3677
  }
3558
3678
  /**
@@ -3755,14 +3875,22 @@ var ArkadeSwaps = class _ArkadeSwaps {
3755
3875
  */
3756
3876
  async claimBtc(pendingSwap) {
3757
3877
  if (!pendingSwap.toAddress)
3758
- throw new Error("Destination address is required");
3878
+ throw new Error(
3879
+ `Swap ${pendingSwap.id}: destination address is required`
3880
+ );
3759
3881
  if (!pendingSwap.response.claimDetails.swapTree)
3760
- throw new Error("Missing swap tree in claim details");
3882
+ throw new Error(
3883
+ `Swap ${pendingSwap.id}: missing swap tree in claim details`
3884
+ );
3761
3885
  if (!pendingSwap.response.claimDetails.serverPublicKey)
3762
- throw new Error("Missing server public key in claim details");
3886
+ throw new Error(
3887
+ `Swap ${pendingSwap.id}: missing server public key in claim details`
3888
+ );
3763
3889
  const swapStatus = await this.getSwapStatus(pendingSwap.id);
3764
3890
  if (!swapStatus.transaction?.hex)
3765
- throw new Error("BTC transaction hex is required");
3891
+ throw new Error(
3892
+ `Swap ${pendingSwap.id}: BTC transaction hex is required`
3893
+ );
3766
3894
  const lockupTx = Transaction6.fromRaw(
3767
3895
  hex8.decode(swapStatus.transaction.hex)
3768
3896
  );
@@ -3817,7 +3945,9 @@ var ArkadeSwaps = class _ArkadeSwaps {
3817
3945
  }
3818
3946
  );
3819
3947
  if (!signedTxData.pubNonce || !signedTxData.partialSignature)
3820
- throw new Error("Invalid signature data from server");
3948
+ throw new Error(
3949
+ `Swap ${pendingSwap.id}: invalid signature data from server`
3950
+ );
3821
3951
  const musigSession = musigMessage.aggregateNonces([
3822
3952
  [
3823
3953
  hex8.decode(
@@ -3842,9 +3972,13 @@ var ArkadeSwaps = class _ArkadeSwaps {
3842
3972
  */
3843
3973
  async refundArk(pendingSwap) {
3844
3974
  if (!pendingSwap.response.lockupDetails.serverPublicKey)
3845
- throw new Error("Missing server public key in lockup details");
3975
+ throw new Error(
3976
+ `Swap ${pendingSwap.id}: missing server public key in lockup details`
3977
+ );
3846
3978
  if (!pendingSwap.response.lockupDetails.timeouts)
3847
- throw new Error("Missing timeouts in lockup details");
3979
+ throw new Error(
3980
+ `Swap ${pendingSwap.id}: missing timeouts in lockup details`
3981
+ );
3848
3982
  const arkInfo = await this.arkProvider.getInfo();
3849
3983
  const address = await this.wallet.getAddress();
3850
3984
  const ourXOnlyPublicKey = normalizeToXOnlyKey(
@@ -3870,12 +4004,12 @@ var ArkadeSwaps = class _ArkadeSwaps {
3870
4004
  });
3871
4005
  if (vtxos.length === 0) {
3872
4006
  throw new Error(
3873
- `VHTLC not found for address ${pendingSwap.response.lockupDetails.lockupAddress}`
4007
+ `Swap ${pendingSwap.id}: VHTLC not found for address ${pendingSwap.response.lockupDetails.lockupAddress}`
3874
4008
  );
3875
4009
  }
3876
4010
  const vtxo = vtxos[0];
3877
4011
  if (vtxo.isSpent) {
3878
- throw new Error("VHTLC is already spent");
4012
+ throw new Error(`Swap ${pendingSwap.id}: VHTLC is already spent`);
3879
4013
  }
3880
4014
  const { vhtlcAddress, vhtlcScript } = this.createVHTLCScript({
3881
4015
  network: arkInfo.network,
@@ -3886,7 +4020,9 @@ var ArkadeSwaps = class _ArkadeSwaps {
3886
4020
  timeoutBlockHeights: pendingSwap.response.lockupDetails.timeouts
3887
4021
  });
3888
4022
  if (!vhtlcScript.refundScript)
3889
- throw new Error("Failed to create VHTLC script for chain swap");
4023
+ throw new Error(
4024
+ `Swap ${pendingSwap.id}: failed to create VHTLC script for chain swap`
4025
+ );
3890
4026
  if (pendingSwap.response.lockupDetails.lockupAddress !== vhtlcAddress) {
3891
4027
  throw new SwapError({
3892
4028
  message: "Unable to claim: invalid VHTLC address"
@@ -4060,11 +4196,17 @@ var ArkadeSwaps = class _ArkadeSwaps {
4060
4196
  */
4061
4197
  async claimArk(pendingSwap) {
4062
4198
  if (!pendingSwap.toAddress)
4063
- throw new Error("Destination address is required");
4199
+ throw new Error(
4200
+ `Swap ${pendingSwap.id}: destination address is required`
4201
+ );
4064
4202
  if (!pendingSwap.response.claimDetails.serverPublicKey)
4065
- throw new Error("Missing server public key in claim details");
4203
+ throw new Error(
4204
+ `Swap ${pendingSwap.id}: missing server public key in claim details`
4205
+ );
4066
4206
  if (!pendingSwap.response.claimDetails.timeouts)
4067
- throw new Error("Missing timeouts in claim details");
4207
+ throw new Error(
4208
+ `Swap ${pendingSwap.id}: missing timeouts in claim details`
4209
+ );
4068
4210
  const arkInfo = await this.arkProvider.getInfo();
4069
4211
  const preimage = hex8.decode(pendingSwap.preimage);
4070
4212
  const address = await this.wallet.getAddress();
@@ -4089,7 +4231,9 @@ var ArkadeSwaps = class _ArkadeSwaps {
4089
4231
  timeoutBlockHeights: pendingSwap.response.claimDetails.timeouts
4090
4232
  });
4091
4233
  if (!vhtlcScript.claimScript)
4092
- throw new Error("Failed to create VHTLC script for chain swap");
4234
+ throw new Error(
4235
+ `Swap ${pendingSwap.id}: failed to create VHTLC script for chain swap`
4236
+ );
4093
4237
  if (pendingSwap.response.claimDetails.lockupAddress !== vhtlcAddress) {
4094
4238
  throw new SwapError({
4095
4239
  message: "Unable to claim: invalid VHTLC address"
@@ -4100,7 +4244,9 @@ var ArkadeSwaps = class _ArkadeSwaps {
4100
4244
  spendableOnly: true
4101
4245
  });
4102
4246
  if (spendableVtxos.vtxos.length === 0)
4103
- throw new Error("No spendable virtual coins found");
4247
+ throw new Error(
4248
+ `Swap ${pendingSwap.id}: no spendable virtual coins found`
4249
+ );
4104
4250
  const vtxo = spendableVtxos.vtxos[0];
4105
4251
  const input = {
4106
4252
  ...vtxo,
@@ -4140,16 +4286,20 @@ var ArkadeSwaps = class _ArkadeSwaps {
4140
4286
  */
4141
4287
  async signCooperativeClaimForServer(pendingSwap) {
4142
4288
  if (!pendingSwap.response.lockupDetails.swapTree)
4143
- throw new Error("Missing swap tree in lockup details");
4289
+ throw new Error(
4290
+ `Swap ${pendingSwap.id}: missing swap tree in lockup details`
4291
+ );
4144
4292
  if (!pendingSwap.response.lockupDetails.serverPublicKey)
4145
- throw new Error("Missing server public key in lockup details");
4293
+ throw new Error(
4294
+ `Swap ${pendingSwap.id}: missing server public key in lockup details`
4295
+ );
4146
4296
  const claimDetails = await this.swapProvider.getChainClaimDetails(
4147
4297
  pendingSwap.id
4148
4298
  );
4149
4299
  const serverPubKey = pendingSwap.response.lockupDetails.serverPublicKey;
4150
4300
  if (claimDetails.publicKey !== serverPubKey) {
4151
4301
  throw new Error(
4152
- `Server public key mismatch: claim response has ${claimDetails.publicKey}, expected ${serverPubKey}`
4302
+ `Swap ${pendingSwap.id}: server public key mismatch \u2014 claim response has ${claimDetails.publicKey}, expected ${serverPubKey}`
4153
4303
  );
4154
4304
  }
4155
4305
  const musig = tweakMusig(
@@ -4269,15 +4419,23 @@ var ArkadeSwaps = class _ArkadeSwaps {
4269
4419
  const { to, from, swap, arkInfo } = args;
4270
4420
  if (from === "ARK") {
4271
4421
  if (!swap.response.lockupDetails.serverPublicKey)
4272
- throw new Error("Missing serverPublicKey in lockup details");
4422
+ throw new Error(
4423
+ `Swap ${swap.id}: missing serverPublicKey in lockup details`
4424
+ );
4273
4425
  if (!swap.response.lockupDetails.timeouts)
4274
- throw new Error("Missing timeouts in lockup details");
4426
+ throw new Error(
4427
+ `Swap ${swap.id}: missing timeouts in lockup details`
4428
+ );
4275
4429
  }
4276
4430
  if (to === "ARK") {
4277
4431
  if (!swap.response.claimDetails.serverPublicKey)
4278
- throw new Error("Missing serverPublicKey in claim details");
4432
+ throw new Error(
4433
+ `Swap ${swap.id}: missing serverPublicKey in claim details`
4434
+ );
4279
4435
  if (!swap.response.claimDetails.timeouts)
4280
- throw new Error("Missing timeouts in claim details");
4436
+ throw new Error(
4437
+ `Swap ${swap.id}: missing timeouts in claim details`
4438
+ );
4281
4439
  }
4282
4440
  const lockupAddress = to === "ARK" ? swap.response.claimDetails.lockupAddress : swap.response.lockupDetails.lockupAddress;
4283
4441
  const receiverPubkey = to === "ARK" ? swap.request.claimPublicKey : swap.response.lockupDetails.serverPublicKey;
@@ -4643,6 +4801,7 @@ export {
4643
4801
  SwapExpiredError,
4644
4802
  TransactionFailedError,
4645
4803
  PreimageFetchError,
4804
+ BoltzRefundError,
4646
4805
  isSubmarineFailedStatus,
4647
4806
  isSubmarineFinalStatus,
4648
4807
  isSubmarinePendingStatus,
@@ -8,7 +8,7 @@ import {
8
8
  isSubmarineFinalStatus,
9
9
  isSubmarineSwapRefundable,
10
10
  logger
11
- } from "./chunk-Y6GPJDXY.js";
11
+ } from "./chunk-CS6UXZP6.js";
12
12
  import {
13
13
  __require
14
14
  } from "./chunk-3RG5ZIWI.js";