@arkade-os/boltz-swap 0.3.15 → 0.3.16

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-CNH5DDKV.js";
6
+ import "./chunk-RL4PDED5.js";
7
7
  import "./chunk-3RG5ZIWI.js";
8
8
  export {
9
9
  defineExpoSwapBackgroundTask,
@@ -8,7 +8,7 @@ import {
8
8
  isSubmarineFinalStatus,
9
9
  isSubmarineSwapRefundable,
10
10
  logger
11
- } from "./chunk-Y6GPJDXY.js";
11
+ } from "./chunk-RL4PDED5.js";
12
12
  import {
13
13
  __require
14
14
  } from "./chunk-3RG5ZIWI.js";
@@ -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(
@@ -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,7 +3535,9 @@ 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}`
@@ -3503,30 +3552,50 @@ var ArkadeSwaps = class _ArkadeSwaps {
3503
3552
  scripts: [vhtlcPkScriptHex]
3504
3553
  });
3505
3554
  throw new Error(
3506
- allVtxos.length > 0 ? "VHTLC is already spent" : `VHTLC not found for address ${pendingSwap.response.address}`
3555
+ allVtxos.length > 0 ? `Swap ${pendingSwap.id}: VHTLC is already spent` : `Swap ${pendingSwap.id}: VHTLC not found for address ${pendingSwap.response.address}`
3507
3556
  );
3508
3557
  }
3509
3558
  const outputScript = ArkAddress2.decode(address).pkScript;
3559
+ const refundWithoutReceiverLeaf = vhtlcScript.refundWithoutReceiver();
3560
+ const refundLocktime = BigInt(timeoutBlockHeights.refund);
3561
+ const currentBlockHeight = await this.swapProvider.getChainHeight();
3562
+ const cltvSatisfied = BigInt(currentBlockHeight) >= refundLocktime;
3510
3563
  let boltzCallCount = 0;
3564
+ let skippedCount = 0;
3511
3565
  for (const vtxo of spendableVtxos) {
3512
3566
  const isRecoverableVtxo = isRecoverable(vtxo);
3513
- const input = {
3514
- ...vtxo,
3515
- tapLeafScript: isRecoverableVtxo ? vhtlcScript.refundWithoutReceiver() : vhtlcScript.refund(),
3516
- tapTree: vhtlcScript.encode()
3517
- };
3518
3567
  const output = {
3519
3568
  amount: BigInt(vtxo.value),
3520
3569
  script: outputScript
3521
3570
  };
3522
- if (isRecoverableVtxo) {
3571
+ if (cltvSatisfied) {
3572
+ const input2 = {
3573
+ ...vtxo,
3574
+ tapLeafScript: refundWithoutReceiverLeaf,
3575
+ tapTree: vhtlcScript.encode()
3576
+ };
3523
3577
  await this.joinBatch(
3524
3578
  this.wallet.identity,
3525
- input,
3579
+ input2,
3526
3580
  output,
3527
- arkInfo
3581
+ arkInfo,
3582
+ isRecoverableVtxo
3583
+ );
3584
+ continue;
3585
+ }
3586
+ if (isRecoverableVtxo) {
3587
+ logger.error(
3588
+ `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
3589
  );
3529
- } else {
3590
+ skippedCount++;
3591
+ continue;
3592
+ }
3593
+ const input = {
3594
+ ...vtxo,
3595
+ tapLeafScript: vhtlcScript.refund(),
3596
+ tapTree: vhtlcScript.encode()
3597
+ };
3598
+ try {
3530
3599
  if (boltzCallCount > 0) {
3531
3600
  await new Promise((r) => setTimeout(r, 2e3));
3532
3601
  }
@@ -3545,14 +3614,42 @@ var ArkadeSwaps = class _ArkadeSwaps {
3545
3614
  )
3546
3615
  );
3547
3616
  boltzCallCount++;
3617
+ } catch (error) {
3618
+ if (!(error instanceof BoltzRefundError)) {
3619
+ throw error;
3620
+ }
3621
+ const tipNow = await this.swapProvider.getChainHeight();
3622
+ if (BigInt(tipNow) < refundLocktime) {
3623
+ logger.error(
3624
+ `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.`
3625
+ );
3626
+ skippedCount++;
3627
+ continue;
3628
+ }
3629
+ logger.warn(
3630
+ `Swap ${pendingSwap.id}: Boltz rejected VTXO outpoint, falling back to refundWithoutReceiver via joinBatch`
3631
+ );
3632
+ const fallbackInput = {
3633
+ ...vtxo,
3634
+ tapLeafScript: refundWithoutReceiverLeaf,
3635
+ tapTree: vhtlcScript.encode()
3636
+ };
3637
+ await this.joinBatch(
3638
+ this.wallet.identity,
3639
+ fallbackInput,
3640
+ output,
3641
+ arkInfo,
3642
+ false
3643
+ );
3548
3644
  }
3549
3645
  }
3646
+ const fullyRefunded = skippedCount === 0;
3550
3647
  await updateSubmarineSwapStatus(
3551
3648
  pendingSwap,
3552
3649
  pendingSwap.status,
3553
3650
  // Keep current status
3554
3651
  this.savePendingSubmarineSwap.bind(this),
3555
- { refundable: true, refunded: true }
3652
+ { refundable: true, refunded: fullyRefunded }
3556
3653
  );
3557
3654
  }
3558
3655
  /**
@@ -3755,14 +3852,22 @@ var ArkadeSwaps = class _ArkadeSwaps {
3755
3852
  */
3756
3853
  async claimBtc(pendingSwap) {
3757
3854
  if (!pendingSwap.toAddress)
3758
- throw new Error("Destination address is required");
3855
+ throw new Error(
3856
+ `Swap ${pendingSwap.id}: destination address is required`
3857
+ );
3759
3858
  if (!pendingSwap.response.claimDetails.swapTree)
3760
- throw new Error("Missing swap tree in claim details");
3859
+ throw new Error(
3860
+ `Swap ${pendingSwap.id}: missing swap tree in claim details`
3861
+ );
3761
3862
  if (!pendingSwap.response.claimDetails.serverPublicKey)
3762
- throw new Error("Missing server public key in claim details");
3863
+ throw new Error(
3864
+ `Swap ${pendingSwap.id}: missing server public key in claim details`
3865
+ );
3763
3866
  const swapStatus = await this.getSwapStatus(pendingSwap.id);
3764
3867
  if (!swapStatus.transaction?.hex)
3765
- throw new Error("BTC transaction hex is required");
3868
+ throw new Error(
3869
+ `Swap ${pendingSwap.id}: BTC transaction hex is required`
3870
+ );
3766
3871
  const lockupTx = Transaction6.fromRaw(
3767
3872
  hex8.decode(swapStatus.transaction.hex)
3768
3873
  );
@@ -3817,7 +3922,9 @@ var ArkadeSwaps = class _ArkadeSwaps {
3817
3922
  }
3818
3923
  );
3819
3924
  if (!signedTxData.pubNonce || !signedTxData.partialSignature)
3820
- throw new Error("Invalid signature data from server");
3925
+ throw new Error(
3926
+ `Swap ${pendingSwap.id}: invalid signature data from server`
3927
+ );
3821
3928
  const musigSession = musigMessage.aggregateNonces([
3822
3929
  [
3823
3930
  hex8.decode(
@@ -3842,9 +3949,13 @@ var ArkadeSwaps = class _ArkadeSwaps {
3842
3949
  */
3843
3950
  async refundArk(pendingSwap) {
3844
3951
  if (!pendingSwap.response.lockupDetails.serverPublicKey)
3845
- throw new Error("Missing server public key in lockup details");
3952
+ throw new Error(
3953
+ `Swap ${pendingSwap.id}: missing server public key in lockup details`
3954
+ );
3846
3955
  if (!pendingSwap.response.lockupDetails.timeouts)
3847
- throw new Error("Missing timeouts in lockup details");
3956
+ throw new Error(
3957
+ `Swap ${pendingSwap.id}: missing timeouts in lockup details`
3958
+ );
3848
3959
  const arkInfo = await this.arkProvider.getInfo();
3849
3960
  const address = await this.wallet.getAddress();
3850
3961
  const ourXOnlyPublicKey = normalizeToXOnlyKey(
@@ -3870,12 +3981,12 @@ var ArkadeSwaps = class _ArkadeSwaps {
3870
3981
  });
3871
3982
  if (vtxos.length === 0) {
3872
3983
  throw new Error(
3873
- `VHTLC not found for address ${pendingSwap.response.lockupDetails.lockupAddress}`
3984
+ `Swap ${pendingSwap.id}: VHTLC not found for address ${pendingSwap.response.lockupDetails.lockupAddress}`
3874
3985
  );
3875
3986
  }
3876
3987
  const vtxo = vtxos[0];
3877
3988
  if (vtxo.isSpent) {
3878
- throw new Error("VHTLC is already spent");
3989
+ throw new Error(`Swap ${pendingSwap.id}: VHTLC is already spent`);
3879
3990
  }
3880
3991
  const { vhtlcAddress, vhtlcScript } = this.createVHTLCScript({
3881
3992
  network: arkInfo.network,
@@ -3886,7 +3997,9 @@ var ArkadeSwaps = class _ArkadeSwaps {
3886
3997
  timeoutBlockHeights: pendingSwap.response.lockupDetails.timeouts
3887
3998
  });
3888
3999
  if (!vhtlcScript.refundScript)
3889
- throw new Error("Failed to create VHTLC script for chain swap");
4000
+ throw new Error(
4001
+ `Swap ${pendingSwap.id}: failed to create VHTLC script for chain swap`
4002
+ );
3890
4003
  if (pendingSwap.response.lockupDetails.lockupAddress !== vhtlcAddress) {
3891
4004
  throw new SwapError({
3892
4005
  message: "Unable to claim: invalid VHTLC address"
@@ -4060,11 +4173,17 @@ var ArkadeSwaps = class _ArkadeSwaps {
4060
4173
  */
4061
4174
  async claimArk(pendingSwap) {
4062
4175
  if (!pendingSwap.toAddress)
4063
- throw new Error("Destination address is required");
4176
+ throw new Error(
4177
+ `Swap ${pendingSwap.id}: destination address is required`
4178
+ );
4064
4179
  if (!pendingSwap.response.claimDetails.serverPublicKey)
4065
- throw new Error("Missing server public key in claim details");
4180
+ throw new Error(
4181
+ `Swap ${pendingSwap.id}: missing server public key in claim details`
4182
+ );
4066
4183
  if (!pendingSwap.response.claimDetails.timeouts)
4067
- throw new Error("Missing timeouts in claim details");
4184
+ throw new Error(
4185
+ `Swap ${pendingSwap.id}: missing timeouts in claim details`
4186
+ );
4068
4187
  const arkInfo = await this.arkProvider.getInfo();
4069
4188
  const preimage = hex8.decode(pendingSwap.preimage);
4070
4189
  const address = await this.wallet.getAddress();
@@ -4089,7 +4208,9 @@ var ArkadeSwaps = class _ArkadeSwaps {
4089
4208
  timeoutBlockHeights: pendingSwap.response.claimDetails.timeouts
4090
4209
  });
4091
4210
  if (!vhtlcScript.claimScript)
4092
- throw new Error("Failed to create VHTLC script for chain swap");
4211
+ throw new Error(
4212
+ `Swap ${pendingSwap.id}: failed to create VHTLC script for chain swap`
4213
+ );
4093
4214
  if (pendingSwap.response.claimDetails.lockupAddress !== vhtlcAddress) {
4094
4215
  throw new SwapError({
4095
4216
  message: "Unable to claim: invalid VHTLC address"
@@ -4100,7 +4221,9 @@ var ArkadeSwaps = class _ArkadeSwaps {
4100
4221
  spendableOnly: true
4101
4222
  });
4102
4223
  if (spendableVtxos.vtxos.length === 0)
4103
- throw new Error("No spendable virtual coins found");
4224
+ throw new Error(
4225
+ `Swap ${pendingSwap.id}: no spendable virtual coins found`
4226
+ );
4104
4227
  const vtxo = spendableVtxos.vtxos[0];
4105
4228
  const input = {
4106
4229
  ...vtxo,
@@ -4140,16 +4263,20 @@ var ArkadeSwaps = class _ArkadeSwaps {
4140
4263
  */
4141
4264
  async signCooperativeClaimForServer(pendingSwap) {
4142
4265
  if (!pendingSwap.response.lockupDetails.swapTree)
4143
- throw new Error("Missing swap tree in lockup details");
4266
+ throw new Error(
4267
+ `Swap ${pendingSwap.id}: missing swap tree in lockup details`
4268
+ );
4144
4269
  if (!pendingSwap.response.lockupDetails.serverPublicKey)
4145
- throw new Error("Missing server public key in lockup details");
4270
+ throw new Error(
4271
+ `Swap ${pendingSwap.id}: missing server public key in lockup details`
4272
+ );
4146
4273
  const claimDetails = await this.swapProvider.getChainClaimDetails(
4147
4274
  pendingSwap.id
4148
4275
  );
4149
4276
  const serverPubKey = pendingSwap.response.lockupDetails.serverPublicKey;
4150
4277
  if (claimDetails.publicKey !== serverPubKey) {
4151
4278
  throw new Error(
4152
- `Server public key mismatch: claim response has ${claimDetails.publicKey}, expected ${serverPubKey}`
4279
+ `Swap ${pendingSwap.id}: server public key mismatch \u2014 claim response has ${claimDetails.publicKey}, expected ${serverPubKey}`
4153
4280
  );
4154
4281
  }
4155
4282
  const musig = tweakMusig(
@@ -4269,15 +4396,23 @@ var ArkadeSwaps = class _ArkadeSwaps {
4269
4396
  const { to, from, swap, arkInfo } = args;
4270
4397
  if (from === "ARK") {
4271
4398
  if (!swap.response.lockupDetails.serverPublicKey)
4272
- throw new Error("Missing serverPublicKey in lockup details");
4399
+ throw new Error(
4400
+ `Swap ${swap.id}: missing serverPublicKey in lockup details`
4401
+ );
4273
4402
  if (!swap.response.lockupDetails.timeouts)
4274
- throw new Error("Missing timeouts in lockup details");
4403
+ throw new Error(
4404
+ `Swap ${swap.id}: missing timeouts in lockup details`
4405
+ );
4275
4406
  }
4276
4407
  if (to === "ARK") {
4277
4408
  if (!swap.response.claimDetails.serverPublicKey)
4278
- throw new Error("Missing serverPublicKey in claim details");
4409
+ throw new Error(
4410
+ `Swap ${swap.id}: missing serverPublicKey in claim details`
4411
+ );
4279
4412
  if (!swap.response.claimDetails.timeouts)
4280
- throw new Error("Missing timeouts in claim details");
4413
+ throw new Error(
4414
+ `Swap ${swap.id}: missing timeouts in claim details`
4415
+ );
4281
4416
  }
4282
4417
  const lockupAddress = to === "ARK" ? swap.response.claimDetails.lockupAddress : swap.response.lockupDetails.lockupAddress;
4283
4418
  const receiverPubkey = to === "ARK" ? swap.request.claimPublicKey : swap.response.lockupDetails.serverPublicKey;
@@ -4643,6 +4778,7 @@ export {
4643
4778
  SwapExpiredError,
4644
4779
  TransactionFailedError,
4645
4780
  PreimageFetchError,
4781
+ BoltzRefundError,
4646
4782
  isSubmarineFailedStatus,
4647
4783
  isSubmarineFinalStatus,
4648
4784
  isSubmarinePendingStatus,