@arkade-os/boltz-swap 0.3.0 → 0.3.2

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/index.cjs CHANGED
@@ -90,8 +90,11 @@ module.exports = __toCommonJS(index_exports);
90
90
 
91
91
  // src/errors.ts
92
92
  var SwapError = class extends Error {
93
+ /** Whether the swap can still be claimed (default: false). */
93
94
  isClaimable;
95
+ /** Whether the swap can be refunded (default: false). */
94
96
  isRefundable;
97
+ /** The pending swap associated with this error, if available. */
95
98
  pendingSwap;
96
99
  constructor(options = {}) {
97
100
  super(options.message ?? "Error during swap.");
@@ -123,7 +126,9 @@ var InsufficientFundsError = class extends SwapError {
123
126
  }
124
127
  };
125
128
  var NetworkError = class extends Error {
129
+ /** HTTP status code from the failed request, if available. */
126
130
  statusCode;
131
+ /** Raw error payload from the Boltz API, if available. */
127
132
  errorData;
128
133
  constructor(message, statusCode, errorData) {
129
134
  super(message);
@@ -365,7 +370,10 @@ var isTree = (data) => {
365
370
  return data && typeof data === "object" && isLeaf(data.claimLeaf) && isLeaf(data.refundLeaf) && isLeaf(data.refundWithoutBoltzLeaf) && isLeaf(data.unilateralClaimLeaf) && isLeaf(data.unilateralRefundLeaf) && isLeaf(data.unilateralRefundWithoutBoltzLeaf);
366
371
  };
367
372
  var isDetails = (data) => {
368
- return data && typeof data === "object" && isTree(data.tree) && (data.amount === void 0 || typeof data.amount === "number") && typeof data.keyIndex === "number" && (data.transaction === void 0 || data.transaction && typeof data.transaction === "object" && typeof data.transaction.id === "string" && typeof data.transaction.vout === "number") && typeof data.lockupAddress === "string" && typeof data.serverPublicKey === "string" && typeof data.timeoutBlockHeight === "number" && isTimeoutBlockHeights(data.timeoutBlockHeights) && (data.preimageHash === void 0 || typeof data.preimageHash === "string");
373
+ return data && typeof data === "object" && isTree(data.tree) && (data.amount === void 0 || typeof data.amount === "number") && typeof data.keyIndex === "number" && (data.transaction === void 0 || data.transaction && typeof data.transaction === "object" && typeof data.transaction.id === "string" && typeof data.transaction.vout === "number") && typeof data.lockupAddress === "string" && typeof data.serverPublicKey === "string" && typeof data.timeoutBlockHeight === "number" && (data.timeoutBlockHeights === void 0 || isTimeoutBlockHeights(data.timeoutBlockHeights)) && (data.preimageHash === void 0 || typeof data.preimageHash === "string");
374
+ };
375
+ var isRestoredChainSwap = (data) => {
376
+ return data && typeof data === "object" && typeof data.id === "string" && data.type === "chain" && typeof data.status === "string" && typeof data.createdAt === "number" && (data.from === "ARK" || data.from === "BTC") && (data.to === "ARK" || data.to === "BTC") && typeof data.preimageHash === "string" && data.refundDetails && typeof data.refundDetails === "object" && isTree(data.refundDetails.tree) && typeof data.refundDetails.amount === "number" && typeof data.refundDetails.keyIndex === "number" && (data.refundDetails.transaction === void 0 || data.refundDetails.transaction && typeof data.refundDetails.transaction === "object" && typeof data.refundDetails.transaction.id === "string" && typeof data.refundDetails.transaction.vout === "number") && typeof data.refundDetails.lockupAddress === "string" && typeof data.refundDetails.serverPublicKey === "string" && typeof data.refundDetails.timeoutBlockHeight === "number";
369
377
  };
370
378
  var isRestoredSubmarineSwap = (data) => {
371
379
  return data && typeof data === "object" && data.to === "BTC" && typeof data.id === "string" && data.from === "ARK" && data.type === "submarine" && typeof data.createdAt === "number" && typeof data.preimageHash === "string" && typeof data.status === "string" && isDetails(data.refundDetails);
@@ -375,10 +383,11 @@ var isRestoredReverseSwap = (data) => {
375
383
  };
376
384
  var isCreateSwapsRestoreResponse = (data) => {
377
385
  return Array.isArray(data) && data.every(
378
- (item) => isRestoredReverseSwap(item) || isRestoredSubmarineSwap(item)
386
+ (item) => isRestoredChainSwap(item) || isRestoredReverseSwap(item) || isRestoredSubmarineSwap(item)
379
387
  );
380
388
  };
381
389
  var BASE_URLS = {
390
+ bitcoin: "https://api.ark.boltz.exchange",
382
391
  mutinynet: "https://api.boltz.mutinynet.arkade.sh",
383
392
  regtest: "http://localhost:9069"
384
393
  };
@@ -387,6 +396,7 @@ var BoltzSwapProvider = class {
387
396
  apiUrl;
388
397
  network;
389
398
  referralId;
399
+ /** @param config Provider configuration with network and optional API URL. */
390
400
  constructor(config) {
391
401
  this.network = config.network;
392
402
  this.referralId = config.referralId;
@@ -398,15 +408,19 @@ var BoltzSwapProvider = class {
398
408
  this.apiUrl = apiUrl;
399
409
  this.wsUrl = this.apiUrl.replace(/^http(s)?:\/\//, "ws$1://").replace("9069", "9004") + "/v2/ws";
400
410
  }
411
+ /** Returns the Boltz API base URL. */
401
412
  getApiUrl() {
402
413
  return this.apiUrl;
403
414
  }
415
+ /** Returns the Boltz WebSocket URL (derived from apiUrl). */
404
416
  getWsUrl() {
405
417
  return this.wsUrl;
406
418
  }
419
+ /** Returns the configured network. */
407
420
  getNetwork() {
408
421
  return this.network;
409
422
  }
423
+ /** Returns current Lightning swap fees (submarine + reverse) from Boltz. */
410
424
  async getFees() {
411
425
  const [submarine, reverse] = await Promise.all([
412
426
  this.request(
@@ -430,6 +444,7 @@ var BoltzSwapProvider = class {
430
444
  }
431
445
  };
432
446
  }
447
+ /** Returns current Lightning swap min/max limits from Boltz. */
433
448
  async getLimits() {
434
449
  const response = await this.request(
435
450
  "/v2/swap/submarine",
@@ -442,6 +457,7 @@ var BoltzSwapProvider = class {
442
457
  max: response.ARK.BTC.limits.maximal
443
458
  };
444
459
  }
460
+ /** Gets the lockup transaction ID for a reverse swap. */
445
461
  async getReverseSwapTxId(id) {
446
462
  const res = await this.request(
447
463
  `/v2/swap/reverse/${id}/transaction`,
@@ -453,6 +469,7 @@ var BoltzSwapProvider = class {
453
469
  });
454
470
  return res;
455
471
  }
472
+ /** Queries the current status of a swap by ID. */
456
473
  async getSwapStatus(id) {
457
474
  const response = await this.request(
458
475
  `/v2/swap/${id}`,
@@ -464,6 +481,7 @@ var BoltzSwapProvider = class {
464
481
  });
465
482
  return response;
466
483
  }
484
+ /** Gets the preimage for a settled submarine swap (proof of payment). */
467
485
  async getSwapPreimage(id) {
468
486
  const res = await this.request(
469
487
  `/v2/swap/submarine/${id}/preimage`,
@@ -475,6 +493,7 @@ var BoltzSwapProvider = class {
475
493
  });
476
494
  return res;
477
495
  }
496
+ /** Creates a submarine swap (Arkade → Lightning) on Boltz. */
478
497
  async createSubmarineSwap({
479
498
  invoice,
480
499
  refundPublicKey
@@ -500,6 +519,7 @@ var BoltzSwapProvider = class {
500
519
  throw new SchemaError({ message: "Error creating submarine swap" });
501
520
  return response;
502
521
  }
522
+ /** Creates a reverse swap (Lightning → Arkade) on Boltz. */
503
523
  async createReverseSwap({
504
524
  invoiceAmount,
505
525
  claimPublicKey,
@@ -529,6 +549,7 @@ var BoltzSwapProvider = class {
529
549
  throw new SchemaError({ message: "Error creating reverse swap" });
530
550
  return response;
531
551
  }
552
+ /** Creates a chain swap (ARK ↔ BTC) on Boltz. */
532
553
  async createChainSwap({
533
554
  to,
534
555
  from,
@@ -587,6 +608,7 @@ var BoltzSwapProvider = class {
587
608
  throw new SchemaError({ message: "Error creating chain swap" });
588
609
  return response;
589
610
  }
611
+ /** Requests Boltz co-signature for a submarine swap refund. Returns signed transaction + checkpoint. */
590
612
  async refundSubmarineSwap(swapId, transaction, checkpoint) {
591
613
  const requestBody = {
592
614
  checkpoint: import_base.base64.encode(checkpoint.toPSBT()),
@@ -610,6 +632,7 @@ var BoltzSwapProvider = class {
610
632
  )
611
633
  };
612
634
  }
635
+ /** Requests Boltz co-signature for a chain swap refund. Returns signed transaction + checkpoint. */
613
636
  async refundChainSwap(swapId, transaction, checkpoint) {
614
637
  const requestBody = {
615
638
  checkpoint: import_base.base64.encode(checkpoint.toPSBT()),
@@ -633,6 +656,7 @@ var BoltzSwapProvider = class {
633
656
  )
634
657
  };
635
658
  }
659
+ /** Monitors swap status updates via WebSocket. Calls update callback on each status change. Resolves when terminal. */
636
660
  async monitorSwap(swapId, update) {
637
661
  return new Promise((resolve, reject) => {
638
662
  const webSocket = new globalThis.WebSocket(this.wsUrl);
@@ -700,6 +724,7 @@ var BoltzSwapProvider = class {
700
724
  };
701
725
  });
702
726
  }
727
+ /** Returns current chain swap fees for a given pair (e.g. ARK→BTC). */
703
728
  async getChainFees(from, to) {
704
729
  if (from === to) {
705
730
  throw new SwapError({ message: "Invalid chain pair" });
@@ -717,6 +742,7 @@ var BoltzSwapProvider = class {
717
742
  }
718
743
  return response[from][to].fees;
719
744
  }
745
+ /** Returns current chain swap min/max limits for a given pair. */
720
746
  async getChainLimits(from, to) {
721
747
  if (from === to) {
722
748
  throw new SwapError({ message: "Invalid chain pair" });
@@ -737,6 +763,7 @@ var BoltzSwapProvider = class {
737
763
  max: response[from][to].limits.maximal
738
764
  };
739
765
  }
766
+ /** Gets claim details (pubNonce, publicKey, transactionHash) for cooperative chain swap claiming. */
740
767
  async getChainClaimDetails(swapId) {
741
768
  const response = await this.request(
742
769
  `/v2/swap/chain/${swapId}/claim`,
@@ -748,6 +775,7 @@ var BoltzSwapProvider = class {
748
775
  });
749
776
  return response;
750
777
  }
778
+ /** Gets a renegotiated quote for a chain swap when lockup amount differs from expected. */
751
779
  async getChainQuote(swapId) {
752
780
  const response = await this.request(
753
781
  `/v2/swap/chain/${swapId}/quote`,
@@ -759,6 +787,7 @@ var BoltzSwapProvider = class {
759
787
  });
760
788
  return response;
761
789
  }
790
+ /** Accepts a renegotiated quote amount for a chain swap. */
762
791
  async postChainQuote(swapId, request) {
763
792
  const response = await this.request(
764
793
  `/v2/swap/chain/${swapId}/quote`,
@@ -771,6 +800,7 @@ var BoltzSwapProvider = class {
771
800
  });
772
801
  return response;
773
802
  }
803
+ /** Broadcasts a raw BTC transaction through Boltz. */
774
804
  async postBtcTransaction(hex9) {
775
805
  const requestBody = { hex: hex9 };
776
806
  const response = await this.request(
@@ -784,6 +814,7 @@ var BoltzSwapProvider = class {
784
814
  });
785
815
  return response;
786
816
  }
817
+ /** Posts claim details (preimage + signing data) or cooperative signature for a chain swap. */
787
818
  async postChainClaimDetails(swapId, request) {
788
819
  const response = await this.request(
789
820
  `/v2/swap/chain/${swapId}/claim`,
@@ -796,6 +827,7 @@ var BoltzSwapProvider = class {
796
827
  });
797
828
  return response;
798
829
  }
830
+ /** Restores swaps from Boltz API using the wallet's public key. */
799
831
  async restoreSwaps(publicKey) {
800
832
  const requestBody = {
801
833
  publicKey
@@ -2858,24 +2890,61 @@ var validFinalArkTx = (finalArkTx, _pubkey, _tapLeaves) => {
2858
2890
  };
2859
2891
 
2860
2892
  // src/arkade-swaps.ts
2861
- var ArkadeSwaps = class {
2893
+ var ArkadeSwaps = class _ArkadeSwaps {
2894
+ /** The Arkade wallet instance used for signing and address generation. */
2862
2895
  wallet;
2896
+ /** Provider for Ark protocol operations (VTXO management, batch joining). */
2863
2897
  arkProvider;
2898
+ /** Boltz API client for creating and monitoring swaps. */
2864
2899
  swapProvider;
2900
+ /** Provider for querying VTXO state on the Ark indexer. */
2865
2901
  indexerProvider;
2902
+ /** Background swap monitor, or null if not enabled. */
2866
2903
  swapManager = null;
2904
+ /** Storage backend for persisting swap data. */
2867
2905
  swapRepository;
2906
+ /**
2907
+ * Creates an ArkadeSwaps instance, auto-detecting the network from the wallet's Ark server.
2908
+ * If no `swapProvider` is given, one is created automatically using the detected network.
2909
+ *
2910
+ * This is the recommended way to initialize ArkadeSwaps.
2911
+ *
2912
+ * @param config - Configuration options. swapProvider is auto-created from the wallet's network if omitted.
2913
+ * @returns A fully initialized ArkadeSwaps instance.
2914
+ *
2915
+ * @example
2916
+ * ```ts
2917
+ * const swaps = await ArkadeSwaps.create({
2918
+ * wallet,
2919
+ * swapManager: true,
2920
+ * });
2921
+ * ```
2922
+ */
2923
+ static async create(config) {
2924
+ if (config.swapProvider) {
2925
+ return new _ArkadeSwaps(config);
2926
+ }
2927
+ const arkProvider = config.arkProvider ?? config.wallet.arkProvider;
2928
+ if (!arkProvider)
2929
+ throw new Error(
2930
+ "Ark provider is required either in wallet or config."
2931
+ );
2932
+ const arkInfo = await arkProvider.getInfo();
2933
+ const network = arkInfo.network;
2934
+ const swapProvider = new BoltzSwapProvider({ network });
2935
+ return new _ArkadeSwaps({ ...config, swapProvider });
2936
+ }
2868
2937
  constructor(config) {
2869
2938
  if (!config.wallet) throw new Error("Wallet is required.");
2870
2939
  if (!config.swapProvider) throw new Error("Swap provider is required.");
2871
2940
  this.wallet = config.wallet;
2872
- const arkProvider = config.wallet.arkProvider ?? config.arkProvider;
2941
+ const arkProvider = config.arkProvider ?? config.wallet.arkProvider;
2873
2942
  if (!arkProvider)
2874
2943
  throw new Error(
2875
2944
  "Ark provider is required either in wallet or config."
2876
2945
  );
2877
2946
  this.arkProvider = arkProvider;
2878
- const indexerProvider = config.wallet.indexerProvider ?? config.indexerProvider;
2947
+ const indexerProvider = config.indexerProvider ?? config.wallet.indexerProvider;
2879
2948
  if (!indexerProvider)
2880
2949
  throw new Error(
2881
2950
  "Indexer provider is required either in wallet or config."
@@ -2887,8 +2956,8 @@ var ArkadeSwaps = class {
2887
2956
  } else {
2888
2957
  this.swapRepository = new IndexedDbSwapRepository();
2889
2958
  }
2890
- if (config.swapManager) {
2891
- const swapManagerConfig = config.swapManager === true ? {} : config.swapManager;
2959
+ if (config.swapManager !== false) {
2960
+ const swapManagerConfig = !config.swapManager || config.swapManager === true ? {} : config.swapManager;
2892
2961
  const shouldAutostart = swapManagerConfig.autoStart ?? true;
2893
2962
  this.swapManager = new SwapManager(
2894
2963
  this.swapProvider,
@@ -3005,9 +3074,11 @@ var ArkadeSwaps = class {
3005
3074
  // Lightning: Reverse swaps (receive Lightning -> Arkade)
3006
3075
  // =========================================================================
3007
3076
  /**
3008
- * Creates a Lightning invoice.
3009
- * @param args - The arguments for creating a Lightning invoice.
3010
- * @returns The response containing the created Lightning invoice.
3077
+ * Creates a Lightning invoice via a reverse swap (Lightning → Arkade).
3078
+ * @param args.amount - Invoice amount in satoshis.
3079
+ * @param args.description - Optional description for the BOLT11 invoice.
3080
+ * @returns Object containing the BOLT11 invoice, payment hash, preimage, and pending swap for monitoring.
3081
+ * @throws {SwapError} If amount is <= 0 or wallet key retrieval fails.
3011
3082
  */
3012
3083
  async createLightningInvoice(args) {
3013
3084
  const pendingSwap = await this.createReverseSwap(args);
@@ -3022,9 +3093,11 @@ var ArkadeSwaps = class {
3022
3093
  };
3023
3094
  }
3024
3095
  /**
3025
- * Creates a reverse swap.
3026
- * @param args - The arguments for creating a reverse swap.
3027
- * @returns The created pending reverse swap.
3096
+ * Creates a reverse swap (Lightning → Arkade) and saves it to storage.
3097
+ * @param args.amount - Amount in satoshis for the reverse swap.
3098
+ * @param args.description - Optional invoice description.
3099
+ * @returns The pending reverse swap, added to SwapManager if enabled.
3100
+ * @throws {SwapError} If amount is <= 0 or key retrieval fails.
3028
3101
  */
3029
3102
  async createReverseSwap(args) {
3030
3103
  if (args.amount <= 0)
@@ -3063,8 +3136,9 @@ var ArkadeSwaps = class {
3063
3136
  return pendingSwap;
3064
3137
  }
3065
3138
  /**
3066
- * Claims the VHTLC for a pending reverse swap.
3067
- * @param pendingSwap - The pending reverse swap to claim the VHTLC.
3139
+ * Claims the VHTLC for a pending reverse swap, transferring locked funds to the wallet.
3140
+ * @param pendingSwap - The reverse swap whose VHTLC should be claimed.
3141
+ * @throws {Error} If preimage is missing, VHTLC script creation fails, or no spendable VTXOs found.
3068
3142
  */
3069
3143
  async claimVHTLC(pendingSwap) {
3070
3144
  if (!pendingSwap.preimage)
@@ -3144,9 +3218,13 @@ var ArkadeSwaps = class {
3144
3218
  );
3145
3219
  }
3146
3220
  /**
3147
- * Waits for the swap to be confirmed and claims the VHTLC.
3148
- * @param pendingSwap - The pending reverse swap.
3221
+ * Waits for a reverse swap to be confirmed and claims the VHTLC.
3222
+ * Delegates to SwapManager if enabled, otherwise monitors via WebSocket.
3223
+ * @param pendingSwap - The reverse swap to monitor and claim.
3149
3224
  * @returns The transaction ID of the claimed VHTLC.
3225
+ * @throws {InvoiceExpiredError} If the Lightning invoice expires.
3226
+ * @throws {SwapExpiredError} If the swap exceeds its time limit.
3227
+ * @throws {TransactionFailedError} If the on-chain transaction fails.
3150
3228
  */
3151
3229
  async waitAndClaim(pendingSwap) {
3152
3230
  if (this.swapManager && await this.swapManager.hasSwap(pendingSwap.id)) {
@@ -3226,9 +3304,11 @@ var ArkadeSwaps = class {
3226
3304
  // Lightning: Submarine swaps (send Arkade -> Lightning)
3227
3305
  // =========================================================================
3228
3306
  /**
3229
- * Sends a Lightning payment.
3230
- * @param args - The arguments for sending a Lightning payment.
3231
- * @returns The result of the payment.
3307
+ * Sends a Lightning payment via a submarine swap (Arkade → Lightning).
3308
+ * Creates the swap, sends funds, and waits for settlement. Auto-refunds on failure.
3309
+ * @param args.invoice - BOLT11 Lightning invoice to pay.
3310
+ * @returns The amount paid, preimage (proof of payment), and transaction ID.
3311
+ * @throws {TransactionFailedError} If the payment fails (auto-refunds if possible).
3232
3312
  */
3233
3313
  async sendLightningPayment(args) {
3234
3314
  const pendingSwap = await this.createSubmarineSwap(args);
@@ -3258,9 +3338,10 @@ var ArkadeSwaps = class {
3258
3338
  }
3259
3339
  }
3260
3340
  /**
3261
- * Creates a submarine swap.
3262
- * @param args - The arguments for creating a submarine swap.
3263
- * @returns The created pending submarine swap.
3341
+ * Creates a submarine swap (Arkade → Lightning) and saves it to storage.
3342
+ * @param args.invoice - BOLT11 Lightning invoice to pay.
3343
+ * @returns The pending submarine swap, added to SwapManager if enabled.
3344
+ * @throws {SwapError} If invoice is missing or key retrieval fails.
3264
3345
  */
3265
3346
  async createSubmarineSwap(args) {
3266
3347
  const refundPublicKey = import_base9.hex.encode(
@@ -3292,8 +3373,10 @@ var ArkadeSwaps = class {
3292
3373
  return pendingSwap;
3293
3374
  }
3294
3375
  /**
3295
- * Claims the VHTLC for a pending submarine swap (aka refund).
3296
- * @param pendingSwap - The pending submarine swap to refund the VHTLC.
3376
+ * Refunds the VHTLC for a failed submarine swap, returning locked funds to the wallet.
3377
+ * Uses multi-party signatures (user + Boltz + server) for non-recoverable VTXOs.
3378
+ * @param pendingSwap - The submarine swap to refund.
3379
+ * @throws {Error} If preimage hash is unavailable, VHTLC not found, or already spent.
3297
3380
  */
3298
3381
  async refundVHTLC(pendingSwap) {
3299
3382
  const preimageHash = pendingSwap.request.invoice ? getInvoicePaymentHash(pendingSwap.request.invoice) : pendingSwap.preimageHash;
@@ -3377,9 +3460,12 @@ var ArkadeSwaps = class {
3377
3460
  );
3378
3461
  }
3379
3462
  /**
3380
- * Waits for the swap settlement.
3381
- * @param pendingSwap - The pending submarine swap.
3382
- * @returns The status of the swap settlement.
3463
+ * Waits for a submarine swap's Lightning payment to settle.
3464
+ * @param pendingSwap - The submarine swap to monitor.
3465
+ * @returns The preimage from the settled Lightning payment (proof of payment).
3466
+ * @throws {SwapExpiredError} If the swap expires.
3467
+ * @throws {InvoiceFailedToPayError} If Boltz fails to route the payment.
3468
+ * @throws {TransactionLockupFailedError} If the lockup transaction fails.
3383
3469
  */
3384
3470
  async waitForSwapSettlement(pendingSwap) {
3385
3471
  return new Promise((resolve, reject) => {
@@ -3450,8 +3536,12 @@ var ArkadeSwaps = class {
3450
3536
  // =========================================================================
3451
3537
  /**
3452
3538
  * Creates a chain swap from ARK to BTC.
3453
- * @param args - Swap arguments.
3454
- * @returns The payment details and pending chain swap.
3539
+ * @param args.btcAddress - Destination Bitcoin address.
3540
+ * @param args.senderLockAmount - Exact amount sender locks (receiver gets less after fees). Specify this OR receiverLockAmount.
3541
+ * @param args.receiverLockAmount - Exact amount receiver gets (sender pays more). Specify this OR senderLockAmount.
3542
+ * @param args.feeSatsPerByte - Fee rate for the BTC claim transaction (default: 1).
3543
+ * @returns The ARK lockup address, amount to pay, and pending swap.
3544
+ * @throws {SwapError} If chain swap verification fails.
3455
3545
  */
3456
3546
  async arkToBtc(args) {
3457
3547
  const pendingSwap = await this.createChainSwap({
@@ -3743,8 +3833,11 @@ var ArkadeSwaps = class {
3743
3833
  // =========================================================================
3744
3834
  /**
3745
3835
  * Creates a chain swap from BTC to ARK.
3746
- * @param args - Swap arguments.
3747
- * @returns The pending chain swap and payment details.
3836
+ * @param args.feeSatsPerByte - Fee rate for BTC transactions (default: 1).
3837
+ * @param args.senderLockAmount - Exact BTC amount to lock. Specify this OR receiverLockAmount.
3838
+ * @param args.receiverLockAmount - Exact ARK amount to receive. Specify this OR senderLockAmount.
3839
+ * @returns The BTC lockup address, amount to pay, and pending swap.
3840
+ * @throws {SwapError} If chain swap verification fails.
3748
3841
  */
3749
3842
  async btcToArk(args) {
3750
3843
  const pendingSwap = await this.createChainSwap({
@@ -4286,6 +4379,7 @@ var ArkadeSwaps = class {
4286
4379
  );
4287
4380
  if (!publicKey) throw new Error("Failed to get public key from wallet");
4288
4381
  const fees = boltzFees ?? await this.swapProvider.getFees();
4382
+ const chainSwaps = [];
4289
4383
  const reverseSwaps = [];
4290
4384
  const submarineSwaps = [];
4291
4385
  const restoredSwaps = await this.swapProvider.restoreSwaps(publicKey);
@@ -4378,9 +4472,45 @@ var ArkadeSwaps = class {
4378
4472
  }
4379
4473
  }
4380
4474
  });
4475
+ } else if (isRestoredChainSwap(swap)) {
4476
+ const {
4477
+ amount,
4478
+ lockupAddress,
4479
+ serverPublicKey,
4480
+ timeoutBlockHeight
4481
+ } = swap.refundDetails;
4482
+ chainSwaps.push({
4483
+ id,
4484
+ type: "chain",
4485
+ createdAt,
4486
+ preimage: "",
4487
+ ephemeralKey: "",
4488
+ feeSatsPerByte: 1,
4489
+ amount,
4490
+ status,
4491
+ request: {
4492
+ to: swap.to,
4493
+ from: swap.from,
4494
+ preimageHash: swap.preimageHash,
4495
+ claimPublicKey: "",
4496
+ feeSatsPerByte: 1,
4497
+ refundPublicKey: "",
4498
+ serverLockAmount: amount,
4499
+ userLockAmount: amount
4500
+ },
4501
+ response: {
4502
+ id,
4503
+ lockupDetails: {
4504
+ amount,
4505
+ lockupAddress,
4506
+ serverPublicKey,
4507
+ timeoutBlockHeight
4508
+ }
4509
+ }
4510
+ });
4381
4511
  }
4382
4512
  }
4383
- return { reverseSwaps, submarineSwaps };
4513
+ return { chainSwaps, reverseSwaps, submarineSwaps };
4384
4514
  }
4385
4515
  /**
4386
4516
  * Enrich a restored reverse swap with its preimage.
package/dist/index.d.cts CHANGED
@@ -1,46 +1,74 @@
1
- import { I as IArkadeSwaps } from './arkade-swaps-Brpa88Fg.cjs';
2
- export { A as ArkadeSwaps } from './arkade-swaps-Brpa88Fg.cjs';
3
- import { P as PendingSwap, D as DecodedInvoice, a as PendingChainSwap, b as PendingReverseSwap, c as PendingSubmarineSwap, A as ArkadeSwapsConfig, N as Network, C as CreateLightningInvoiceRequest, S as SendLightningPaymentRequest, F as FeesResponse, d as Chain, e as CreateLightningInvoiceResponse, f as SendLightningPaymentResponse, g as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, h as ArkToBtcResponse, B as BtcToArkResponse, i as SwapRepository, j as SwapManagerClient, k as GetSwapsFilter } from './types-BRYTZH1Z.cjs';
4
- export { l as BoltzSwapProvider, m as BoltzSwapStatus, W as IncomingPaymentSubscription, V as SwapManager, _ as SwapManagerCallbacks, Y as SwapManagerConfig, Z as SwapManagerEvents, X as Vtxo, n as isChainClaimableStatus, o as isChainFailedStatus, p as isChainFinalStatus, q as isChainPendingStatus, r as isChainRefundableStatus, s as isChainSignableStatus, t as isChainSuccessStatus, u as isChainSwapClaimable, v as isChainSwapRefundable, w as isPendingChainSwap, x as isPendingReverseSwap, y as isPendingSubmarineSwap, z as isReverseClaimableStatus, E as isReverseFailedStatus, H as isReverseFinalStatus, I as isReversePendingStatus, J as isReverseSuccessStatus, K as isReverseSwapClaimable, M as isSubmarineFailedStatus, O as isSubmarineFinalStatus, Q as isSubmarinePendingStatus, T as isSubmarineRefundableStatus, R as isSubmarineSuccessStatus, U as isSubmarineSwapRefundable } from './types-BRYTZH1Z.cjs';
1
+ import { I as IArkadeSwaps } from './arkade-swaps-w-cm-cPg.cjs';
2
+ export { A as ArkadeSwaps } from './arkade-swaps-w-cm-cPg.cjs';
3
+ import { P as PendingSwap, D as DecodedInvoice, a as PendingChainSwap, b as PendingReverseSwap, c as PendingSubmarineSwap, A as ArkadeSwapsConfig, N as Network, C as CreateLightningInvoiceRequest, S as SendLightningPaymentRequest, F as FeesResponse, d as Chain, e as CreateLightningInvoiceResponse, f as SendLightningPaymentResponse, g as ChainFeesResponse, L as LimitsResponse, G as GetSwapStatusResponse, h as ArkToBtcResponse, B as BtcToArkResponse, i as SwapRepository, j as SwapManagerClient, k as GetSwapsFilter } from './types-t0r41rlw.cjs';
4
+ export { X as ArkadeSwapsCreateConfig, l as BoltzSwapProvider, m as BoltzSwapStatus, W as IncomingPaymentSubscription, V as SwapManager, $ as SwapManagerCallbacks, Z as SwapManagerConfig, _ as SwapManagerEvents, Y as Vtxo, n as isChainClaimableStatus, o as isChainFailedStatus, p as isChainFinalStatus, q as isChainPendingStatus, r as isChainRefundableStatus, s as isChainSignableStatus, t as isChainSuccessStatus, u as isChainSwapClaimable, v as isChainSwapRefundable, w as isPendingChainSwap, x as isPendingReverseSwap, y as isPendingSubmarineSwap, z as isReverseClaimableStatus, E as isReverseFailedStatus, H as isReverseFinalStatus, I as isReversePendingStatus, J as isReverseSuccessStatus, K as isReverseSwapClaimable, M as isSubmarineFailedStatus, O as isSubmarineFinalStatus, Q as isSubmarinePendingStatus, T as isSubmarineRefundableStatus, R as isSubmarineSuccessStatus, U as isSubmarineSwapRefundable } from './types-t0r41rlw.cjs';
5
5
  import { Transaction } from '@scure/btc-signer';
6
6
  import { MessageHandler, RequestEnvelope, ArkInfo, ResponseEnvelope, IWallet, IReadonlyWallet, VHTLC, Identity, ArkTxInput } from '@arkade-os/sdk';
7
7
  import { TransactionOutput } from '@scure/btc-signer/psbt.js';
8
8
 
9
+ /** Options for constructing swap errors. */
9
10
  interface ErrorOptions {
11
+ /** Custom error message (overrides the default). */
10
12
  message?: string;
13
+ /** Whether the swap's funds can still be claimed. */
11
14
  isClaimable?: boolean;
15
+ /** Whether the swap's funds can be refunded. */
12
16
  isRefundable?: boolean;
17
+ /** The associated pending swap, if available. */
13
18
  pendingSwap?: PendingSwap;
14
19
  }
20
+ /**
21
+ * Base error class for all swap-related errors.
22
+ * Extends Error with swap-specific metadata (`isClaimable`, `isRefundable`, `pendingSwap`).
23
+ */
15
24
  declare class SwapError extends Error {
25
+ /** Whether the swap can still be claimed (default: false). */
16
26
  isClaimable: boolean;
27
+ /** Whether the swap can be refunded (default: false). */
17
28
  isRefundable: boolean;
29
+ /** The pending swap associated with this error, if available. */
18
30
  pendingSwap?: PendingSwap;
19
31
  constructor(options?: ErrorOptions);
20
32
  }
33
+ /** Thrown when a Lightning invoice expires before being paid. The swap may be refundable. */
21
34
  declare class InvoiceExpiredError extends SwapError {
22
35
  constructor(options?: ErrorOptions);
23
36
  }
37
+ /** Thrown when Boltz fails to route the Lightning payment to the destination. Typically refundable. */
24
38
  declare class InvoiceFailedToPayError extends SwapError {
25
39
  constructor(options?: ErrorOptions);
26
40
  }
41
+ /** Thrown when the wallet does not have enough funds to complete the swap. */
27
42
  declare class InsufficientFundsError extends SwapError {
28
43
  constructor(options?: ErrorOptions);
29
44
  }
45
+ /**
46
+ * Thrown for HTTP/network failures when communicating with the Boltz API.
47
+ * Not a SwapError — does not carry swap metadata.
48
+ */
30
49
  declare class NetworkError extends Error {
50
+ /** HTTP status code from the failed request, if available. */
31
51
  statusCode?: number;
52
+ /** Raw error payload from the Boltz API, if available. */
32
53
  errorData?: any;
33
54
  constructor(message: string, statusCode?: number, errorData?: any);
34
55
  }
56
+ /** Thrown when the Boltz API returns a response that doesn't match the expected schema. */
35
57
  declare class SchemaError extends SwapError {
36
58
  constructor(options?: ErrorOptions);
37
59
  }
60
+ /** Thrown when a swap exceeds its time limit. May be refundable depending on swap type. */
38
61
  declare class SwapExpiredError extends SwapError {
39
62
  constructor(options?: ErrorOptions);
40
63
  }
64
+ /** Thrown when an on-chain or off-chain transaction fails. */
41
65
  declare class TransactionFailedError extends SwapError {
42
66
  constructor(options?: ErrorOptions);
43
67
  }
68
+ /**
69
+ * Thrown when a submarine swap's Lightning payment settles but retrieving the
70
+ * preimage from Boltz fails. The payment was made but proof-of-payment is unavailable.
71
+ */
44
72
  declare class PreimageFetchError extends SwapError {
45
73
  constructor(options?: ErrorOptions);
46
74
  }
@@ -177,6 +205,7 @@ type RequestRestoreSwaps = RequestEnvelope & {
177
205
  type ResponseRestoreSwaps = ResponseEnvelope & {
178
206
  type: "SWAPS_RESTORED";
179
207
  payload: {
208
+ chainSwaps: PendingChainSwap[];
180
209
  reverseSwaps: PendingReverseSwap[];
181
210
  submarineSwaps: PendingSubmarineSwap[];
182
211
  };
@@ -541,6 +570,7 @@ declare class ServiceWorkerArkadeSwaps implements IArkadeSwaps {
541
570
  preimage: string;
542
571
  }>;
543
572
  restoreSwaps(boltzFees?: FeesResponse): Promise<{
573
+ chainSwaps: PendingChainSwap[];
544
574
  reverseSwaps: PendingReverseSwap[];
545
575
  submarineSwaps: PendingSubmarineSwap[];
546
576
  }>;