@arkade-os/boltz-swap 0.1.5 → 0.1.8

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/README.md CHANGED
@@ -50,6 +50,49 @@ const arkadeLightning = new ArkadeLightning({
50
50
  });
51
51
  ```
52
52
 
53
+ ## Wallet class Compatibility
54
+
55
+ This library supports both wallet interface patterns:
56
+
57
+ ### Wallet (with optional nested identity and providers)
58
+
59
+ ```typescript
60
+ import { Wallet } from '@arkade-os/sdk';
61
+
62
+ const wallet = await Wallet.create({
63
+ identity,
64
+ arkServerUrl: 'https://mutinynet.arkade.sh',
65
+ });
66
+
67
+ // Wallet may have built-in providers
68
+ const arkadeLightning = new ArkadeLightning({
69
+ wallet,
70
+ swapProvider,
71
+ // arkProvider and indexerProvider can be provided here if wallet doesn't have them
72
+ });
73
+ ```
74
+
75
+ ### ServiceWorkerWallet (legacy interface)
76
+
77
+ ```typescript
78
+ import { RestArkProvider, RestIndexerProvider } from '@arkade-os/sdk';
79
+
80
+ // ServiceWorkerWallet has identity methods spread directly (no nested identity)
81
+ const serviceWorkerWallet = new ServiceWorkerWallet(serviceWorker);
82
+ await serviceWorkerWallet.init({
83
+ privateKey: 'your_private_key_hex',
84
+ arkServerUrl: 'https://ark.example.com'
85
+ });
86
+
87
+ // Must provide external providers for ServiceWorkerWallet (it doesn't have them)
88
+ const arkadeLightning = new ArkadeLightning({
89
+ wallet: serviceWorkerWallet,
90
+ arkProvider: new RestArkProvider('https://ark.example.com'),
91
+ indexerProvider: new RestIndexerProvider('https://indexer.example.com'),
92
+ swapProvider,
93
+ });
94
+ ```
95
+
53
96
  ## Storage
54
97
 
55
98
  By default this library doesn't store pending swaps.
package/dist/index.cjs CHANGED
@@ -119,6 +119,11 @@ var TransactionRefundedError = class extends SwapError {
119
119
  var import_sdk = require("@arkade-os/sdk");
120
120
  var import_sha2 = require("@noble/hashes/sha2");
121
121
  var import_base = require("@scure/base");
122
+
123
+ // src/types.ts
124
+ var isWalletWithNestedIdentity = (w) => !!w.identity && typeof w.identity?.xOnlyPublicKey === "function";
125
+
126
+ // src/arkade-lightning.ts
122
127
  var import_utils = require("@noble/hashes/utils");
123
128
  var import_btc_signer = require("@scure/btc-signer");
124
129
  var import_legacy = require("@noble/hashes/legacy");
@@ -143,6 +148,26 @@ var getInvoicePaymentHash = (invoice) => {
143
148
  };
144
149
 
145
150
  // src/arkade-lightning.ts
151
+ function getIdentity(wallet) {
152
+ if (isWalletWithNestedIdentity(wallet)) {
153
+ return wallet.identity;
154
+ }
155
+ return wallet;
156
+ }
157
+ function getXOnlyPublicKey(wallet) {
158
+ return getIdentity(wallet).xOnlyPublicKey();
159
+ }
160
+ function getSignerSession(wallet) {
161
+ const identity = getIdentity(wallet);
162
+ const signerSession = identity?.signerSession;
163
+ if (typeof signerSession === "function") {
164
+ return signerSession();
165
+ }
166
+ return signerSession;
167
+ }
168
+ async function signTransaction(wallet, tx, inputIndexes) {
169
+ return getIdentity(wallet).sign(tx, inputIndexes);
170
+ }
146
171
  var ArkadeLightning = class {
147
172
  wallet;
148
173
  arkProvider;
@@ -151,14 +176,16 @@ var ArkadeLightning = class {
151
176
  indexerProvider;
152
177
  constructor(config) {
153
178
  if (!config.wallet) throw new Error("Wallet is required.");
154
- if (!config.arkProvider) throw new Error("Ark provider is required.");
155
179
  if (!config.swapProvider) throw new Error("Swap provider is required.");
156
- if (!config.indexerProvider) throw new Error("Indexer provider is required.");
157
180
  this.wallet = config.wallet;
158
- this.arkProvider = config.arkProvider;
181
+ const arkProvider = config.wallet.arkProvider ?? config.arkProvider;
182
+ if (!arkProvider) throw new Error("Ark provider is required either in wallet or config.");
183
+ this.arkProvider = arkProvider;
184
+ const indexerProvider = config.wallet.indexerProvider ?? config.indexerProvider;
185
+ if (!indexerProvider) throw new Error("Indexer provider is required either in wallet or config.");
186
+ this.indexerProvider = indexerProvider;
159
187
  this.swapProvider = config.swapProvider;
160
188
  this.storageProvider = config.storageProvider ?? null;
161
- this.indexerProvider = config.indexerProvider;
162
189
  }
163
190
  // receive from lightning = reverse submarine swap
164
191
  //
@@ -193,10 +220,10 @@ var ArkadeLightning = class {
193
220
  async sendLightningPayment(args) {
194
221
  return new Promise((resolve, reject) => {
195
222
  this.createSubmarineSwap(args).then((pendingSwap) => {
196
- if (args.maxFeeSats) {
197
- const invoiceAmount = decodeInvoice(args.invoice).amountSats;
223
+ if (args.maxFeeSats != null) {
224
+ const invoiceAmount = decodeInvoice(args.invoice).amountSats ?? 0;
198
225
  const fees = pendingSwap.response.expectedAmount - invoiceAmount;
199
- if (fees > args.maxFeeSats) {
226
+ if (invoiceAmount > 0 && fees > args.maxFeeSats) {
200
227
  reject(new SwapError({ message: `Swap fees ${fees} exceed max allowed ${args.maxFeeSats}` }));
201
228
  }
202
229
  }
@@ -222,7 +249,7 @@ var ArkadeLightning = class {
222
249
  }
223
250
  // create submarine swap
224
251
  async createSubmarineSwap(args) {
225
- const refundPublicKey = import_base.hex.encode(this.wallet.xOnlyPublicKey());
252
+ const refundPublicKey = import_base.hex.encode(getXOnlyPublicKey(this.wallet));
226
253
  if (!refundPublicKey) throw new SwapError({ message: "Failed to get refund public key from wallet" });
227
254
  const invoice = args.invoice;
228
255
  if (!invoice) throw new SwapError({ message: "Invoice is required" });
@@ -244,7 +271,7 @@ var ArkadeLightning = class {
244
271
  // create reverse submarine swap
245
272
  async createReverseSwap(args) {
246
273
  if (args.amount <= 0) throw new SwapError({ message: "Amount must be greater than 0" });
247
- const claimPublicKey = import_base.hex.encode(this.wallet.xOnlyPublicKey());
274
+ const claimPublicKey = import_base.hex.encode(getXOnlyPublicKey(this.wallet));
248
275
  if (!claimPublicKey) throw new SwapError({ message: "Failed to get claim public key from wallet" });
249
276
  const preimage = (0, import_utils.randomBytes)(32);
250
277
  const preimageHash = import_base.hex.encode((0, import_sha2.sha256)(preimage));
@@ -271,7 +298,7 @@ var ArkadeLightning = class {
271
298
  const preimage = import_base.hex.decode(pendingSwap.preimage);
272
299
  const aspInfo = await this.arkProvider.getInfo();
273
300
  const address = await this.wallet.getAddress();
274
- let receiverXOnlyPublicKey = this.wallet.xOnlyPublicKey();
301
+ let receiverXOnlyPublicKey = getXOnlyPublicKey(this.wallet);
275
302
  if (receiverXOnlyPublicKey.length == 33) {
276
303
  receiverXOnlyPublicKey = receiverXOnlyPublicKey.slice(1);
277
304
  } else if (receiverXOnlyPublicKey.length !== 32) {
@@ -302,13 +329,13 @@ var ArkadeLightning = class {
302
329
  const vhtlcIdentity = {
303
330
  sign: async (tx, inputIndexes) => {
304
331
  const cpy = tx.clone();
305
- let signedTx = await this.wallet.sign(cpy, inputIndexes);
332
+ let signedTx = await signTransaction(this.wallet, cpy, inputIndexes);
306
333
  signedTx = import_btc_signer.Transaction.fromPSBT(signedTx.toPSBT(), { allowUnknown: true });
307
334
  (0, import_sdk.setArkPsbtField)(signedTx, 0, import_sdk.ConditionWitness, [preimage]);
308
335
  return signedTx;
309
336
  },
310
337
  xOnlyPublicKey: receiverXOnlyPublicKey,
311
- signerSession: this.wallet.signerSession
338
+ signerSession: getSignerSession(this.wallet)
312
339
  };
313
340
  const serverUnrollScript = import_sdk.CSVMultisigTapscript.encode({
314
341
  pubkeys: [serverXOnlyPublicKey],
@@ -360,7 +387,7 @@ var ArkadeLightning = class {
360
387
  const aspInfo = await this.arkProvider.getInfo();
361
388
  const address = await this.wallet.getAddress();
362
389
  if (!address) throw new Error("Failed to get ark address from service worker wallet");
363
- let receiverXOnlyPublicKey = this.wallet.xOnlyPublicKey();
390
+ let receiverXOnlyPublicKey = getXOnlyPublicKey(this.wallet);
364
391
  if (receiverXOnlyPublicKey.length == 33) {
365
392
  receiverXOnlyPublicKey = receiverXOnlyPublicKey.slice(1);
366
393
  } else if (receiverXOnlyPublicKey.length !== 32) {
@@ -376,7 +403,7 @@ var ArkadeLightning = class {
376
403
  network: aspInfo.network,
377
404
  preimageHash: import_base.hex.decode(getInvoicePaymentHash(pendingSwap.request.invoice)),
378
405
  receiverPubkey: pendingSwap.response.claimPublicKey,
379
- senderPubkey: import_base.hex.encode(this.wallet.xOnlyPublicKey()),
406
+ senderPubkey: import_base.hex.encode(getXOnlyPublicKey(this.wallet)),
380
407
  serverPubkey: aspInfo.signerPubkey,
381
408
  timeoutBlockHeights: pendingSwap.response.timeoutBlockHeights
382
409
  });
@@ -392,11 +419,11 @@ var ArkadeLightning = class {
392
419
  const vhtlcIdentity = {
393
420
  sign: async (tx, inputIndexes) => {
394
421
  const cpy = tx.clone();
395
- let signedTx = await this.wallet.sign(cpy, inputIndexes);
422
+ let signedTx = await signTransaction(this.wallet, cpy, inputIndexes);
396
423
  return import_btc_signer.Transaction.fromPSBT(signedTx.toPSBT(), { allowUnknown: true });
397
424
  },
398
425
  xOnlyPublicKey: receiverXOnlyPublicKey,
399
- signerSession: this.wallet.signerSession
426
+ signerSession: getSignerSession(this.wallet)
400
427
  };
401
428
  const serverUnrollScript = import_sdk.CSVMultisigTapscript.encode({
402
429
  pubkeys: [serverXOnlyPublicKey],
@@ -490,21 +517,27 @@ var ArkadeLightning = class {
490
517
  */
491
518
  async waitForSwapSettlement(pendingSwap) {
492
519
  return new Promise((resolve, reject) => {
520
+ let isResolved = false;
493
521
  const onStatusUpdate = async (status) => {
522
+ if (isResolved) return;
494
523
  switch (status) {
495
524
  case "swap.expired":
525
+ isResolved = true;
496
526
  this.storageProvider?.savePendingSubmarineSwap({ ...pendingSwap, status });
497
527
  reject(new SwapExpiredError({ isRefundable: true, pendingSwap }));
498
528
  break;
499
529
  case "invoice.failedToPay":
530
+ isResolved = true;
500
531
  this.storageProvider?.savePendingSubmarineSwap({ ...pendingSwap, status });
501
532
  reject(new InvoiceFailedToPayError({ isRefundable: true, pendingSwap }));
502
533
  break;
503
534
  case "transaction.lockupFailed":
535
+ isResolved = true;
504
536
  this.storageProvider?.savePendingSubmarineSwap({ ...pendingSwap, status });
505
537
  reject(new TransactionLockupFailedError({ isRefundable: true, pendingSwap }));
506
538
  break;
507
539
  case "transaction.claimed": {
540
+ isResolved = true;
508
541
  const { preimage } = await this.swapProvider.getSwapPreimage(pendingSwap.response.id);
509
542
  this.storageProvider?.savePendingSubmarineSwap({ ...pendingSwap, preimage, status });
510
543
  resolve({ preimage });
@@ -515,7 +548,12 @@ var ArkadeLightning = class {
515
548
  break;
516
549
  }
517
550
  };
518
- this.swapProvider.monitorSwap(pendingSwap.response.id, onStatusUpdate);
551
+ this.swapProvider.monitorSwap(pendingSwap.response.id, onStatusUpdate).catch((error) => {
552
+ if (!isResolved) {
553
+ isResolved = true;
554
+ reject(error);
555
+ }
556
+ });
519
557
  });
520
558
  }
521
559
  // validators
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { IWallet, Identity, RestArkProvider, RestIndexerProvider, VHTLC } from '@arkade-os/sdk';
1
+ import { IWallet, ArkProvider, IndexerProvider, Identity, VHTLC } from '@arkade-os/sdk';
2
2
 
3
3
  interface StorageOptions {
4
4
  storagePath?: string;
@@ -119,7 +119,13 @@ interface Vtxo {
119
119
  locktime: number;
120
120
  };
121
121
  }
122
- type Wallet = IWallet & Identity;
122
+ type WalletWithNestedIdentity = IWallet & {
123
+ arkProvider?: ArkProvider;
124
+ indexerProvider?: IndexerProvider;
125
+ identity: Identity;
126
+ };
127
+ type ServiceWorkerWallet = IWallet & Identity;
128
+ type Wallet = WalletWithNestedIdentity | ServiceWorkerWallet;
123
129
  type Network = 'bitcoin' | 'mutinynet' | 'regtest' | 'testnet';
124
130
  interface CreateLightningInvoiceRequest {
125
131
  amount: number;
@@ -163,9 +169,9 @@ interface RefundHandler {
163
169
  }
164
170
  interface ArkadeLightningConfig {
165
171
  wallet: Wallet;
166
- arkProvider: RestArkProvider;
172
+ arkProvider?: ArkProvider;
167
173
  swapProvider: BoltzSwapProvider;
168
- indexerProvider: RestIndexerProvider;
174
+ indexerProvider?: IndexerProvider;
169
175
  feeConfig?: Partial<FeeConfig>;
170
176
  refundHandler?: RefundHandler;
171
177
  storageProvider?: StorageProvider | null;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { IWallet, Identity, RestArkProvider, RestIndexerProvider, VHTLC } from '@arkade-os/sdk';
1
+ import { IWallet, ArkProvider, IndexerProvider, Identity, VHTLC } from '@arkade-os/sdk';
2
2
 
3
3
  interface StorageOptions {
4
4
  storagePath?: string;
@@ -119,7 +119,13 @@ interface Vtxo {
119
119
  locktime: number;
120
120
  };
121
121
  }
122
- type Wallet = IWallet & Identity;
122
+ type WalletWithNestedIdentity = IWallet & {
123
+ arkProvider?: ArkProvider;
124
+ indexerProvider?: IndexerProvider;
125
+ identity: Identity;
126
+ };
127
+ type ServiceWorkerWallet = IWallet & Identity;
128
+ type Wallet = WalletWithNestedIdentity | ServiceWorkerWallet;
123
129
  type Network = 'bitcoin' | 'mutinynet' | 'regtest' | 'testnet';
124
130
  interface CreateLightningInvoiceRequest {
125
131
  amount: number;
@@ -163,9 +169,9 @@ interface RefundHandler {
163
169
  }
164
170
  interface ArkadeLightningConfig {
165
171
  wallet: Wallet;
166
- arkProvider: RestArkProvider;
172
+ arkProvider?: ArkProvider;
167
173
  swapProvider: BoltzSwapProvider;
168
- indexerProvider: RestIndexerProvider;
174
+ indexerProvider?: IndexerProvider;
169
175
  feeConfig?: Partial<FeeConfig>;
170
176
  refundHandler?: RefundHandler;
171
177
  storageProvider?: StorageProvider | null;
package/dist/index.js CHANGED
@@ -77,6 +77,11 @@ import {
77
77
  } from "@arkade-os/sdk";
78
78
  import { sha256 } from "@noble/hashes/sha2";
79
79
  import { base64, hex } from "@scure/base";
80
+
81
+ // src/types.ts
82
+ var isWalletWithNestedIdentity = (w) => !!w.identity && typeof w.identity?.xOnlyPublicKey === "function";
83
+
84
+ // src/arkade-lightning.ts
80
85
  import { randomBytes } from "@noble/hashes/utils";
81
86
  import { Transaction } from "@scure/btc-signer";
82
87
  import { ripemd160 } from "@noble/hashes/legacy";
@@ -101,6 +106,26 @@ var getInvoicePaymentHash = (invoice) => {
101
106
  };
102
107
 
103
108
  // src/arkade-lightning.ts
109
+ function getIdentity(wallet) {
110
+ if (isWalletWithNestedIdentity(wallet)) {
111
+ return wallet.identity;
112
+ }
113
+ return wallet;
114
+ }
115
+ function getXOnlyPublicKey(wallet) {
116
+ return getIdentity(wallet).xOnlyPublicKey();
117
+ }
118
+ function getSignerSession(wallet) {
119
+ const identity = getIdentity(wallet);
120
+ const signerSession = identity?.signerSession;
121
+ if (typeof signerSession === "function") {
122
+ return signerSession();
123
+ }
124
+ return signerSession;
125
+ }
126
+ async function signTransaction(wallet, tx, inputIndexes) {
127
+ return getIdentity(wallet).sign(tx, inputIndexes);
128
+ }
104
129
  var ArkadeLightning = class {
105
130
  wallet;
106
131
  arkProvider;
@@ -109,14 +134,16 @@ var ArkadeLightning = class {
109
134
  indexerProvider;
110
135
  constructor(config) {
111
136
  if (!config.wallet) throw new Error("Wallet is required.");
112
- if (!config.arkProvider) throw new Error("Ark provider is required.");
113
137
  if (!config.swapProvider) throw new Error("Swap provider is required.");
114
- if (!config.indexerProvider) throw new Error("Indexer provider is required.");
115
138
  this.wallet = config.wallet;
116
- this.arkProvider = config.arkProvider;
139
+ const arkProvider = config.wallet.arkProvider ?? config.arkProvider;
140
+ if (!arkProvider) throw new Error("Ark provider is required either in wallet or config.");
141
+ this.arkProvider = arkProvider;
142
+ const indexerProvider = config.wallet.indexerProvider ?? config.indexerProvider;
143
+ if (!indexerProvider) throw new Error("Indexer provider is required either in wallet or config.");
144
+ this.indexerProvider = indexerProvider;
117
145
  this.swapProvider = config.swapProvider;
118
146
  this.storageProvider = config.storageProvider ?? null;
119
- this.indexerProvider = config.indexerProvider;
120
147
  }
121
148
  // receive from lightning = reverse submarine swap
122
149
  //
@@ -151,10 +178,10 @@ var ArkadeLightning = class {
151
178
  async sendLightningPayment(args) {
152
179
  return new Promise((resolve, reject) => {
153
180
  this.createSubmarineSwap(args).then((pendingSwap) => {
154
- if (args.maxFeeSats) {
155
- const invoiceAmount = decodeInvoice(args.invoice).amountSats;
181
+ if (args.maxFeeSats != null) {
182
+ const invoiceAmount = decodeInvoice(args.invoice).amountSats ?? 0;
156
183
  const fees = pendingSwap.response.expectedAmount - invoiceAmount;
157
- if (fees > args.maxFeeSats) {
184
+ if (invoiceAmount > 0 && fees > args.maxFeeSats) {
158
185
  reject(new SwapError({ message: `Swap fees ${fees} exceed max allowed ${args.maxFeeSats}` }));
159
186
  }
160
187
  }
@@ -180,7 +207,7 @@ var ArkadeLightning = class {
180
207
  }
181
208
  // create submarine swap
182
209
  async createSubmarineSwap(args) {
183
- const refundPublicKey = hex.encode(this.wallet.xOnlyPublicKey());
210
+ const refundPublicKey = hex.encode(getXOnlyPublicKey(this.wallet));
184
211
  if (!refundPublicKey) throw new SwapError({ message: "Failed to get refund public key from wallet" });
185
212
  const invoice = args.invoice;
186
213
  if (!invoice) throw new SwapError({ message: "Invoice is required" });
@@ -202,7 +229,7 @@ var ArkadeLightning = class {
202
229
  // create reverse submarine swap
203
230
  async createReverseSwap(args) {
204
231
  if (args.amount <= 0) throw new SwapError({ message: "Amount must be greater than 0" });
205
- const claimPublicKey = hex.encode(this.wallet.xOnlyPublicKey());
232
+ const claimPublicKey = hex.encode(getXOnlyPublicKey(this.wallet));
206
233
  if (!claimPublicKey) throw new SwapError({ message: "Failed to get claim public key from wallet" });
207
234
  const preimage = randomBytes(32);
208
235
  const preimageHash = hex.encode(sha256(preimage));
@@ -229,7 +256,7 @@ var ArkadeLightning = class {
229
256
  const preimage = hex.decode(pendingSwap.preimage);
230
257
  const aspInfo = await this.arkProvider.getInfo();
231
258
  const address = await this.wallet.getAddress();
232
- let receiverXOnlyPublicKey = this.wallet.xOnlyPublicKey();
259
+ let receiverXOnlyPublicKey = getXOnlyPublicKey(this.wallet);
233
260
  if (receiverXOnlyPublicKey.length == 33) {
234
261
  receiverXOnlyPublicKey = receiverXOnlyPublicKey.slice(1);
235
262
  } else if (receiverXOnlyPublicKey.length !== 32) {
@@ -260,13 +287,13 @@ var ArkadeLightning = class {
260
287
  const vhtlcIdentity = {
261
288
  sign: async (tx, inputIndexes) => {
262
289
  const cpy = tx.clone();
263
- let signedTx = await this.wallet.sign(cpy, inputIndexes);
290
+ let signedTx = await signTransaction(this.wallet, cpy, inputIndexes);
264
291
  signedTx = Transaction.fromPSBT(signedTx.toPSBT(), { allowUnknown: true });
265
292
  setArkPsbtField(signedTx, 0, ConditionWitness, [preimage]);
266
293
  return signedTx;
267
294
  },
268
295
  xOnlyPublicKey: receiverXOnlyPublicKey,
269
- signerSession: this.wallet.signerSession
296
+ signerSession: getSignerSession(this.wallet)
270
297
  };
271
298
  const serverUnrollScript = CSVMultisigTapscript.encode({
272
299
  pubkeys: [serverXOnlyPublicKey],
@@ -318,7 +345,7 @@ var ArkadeLightning = class {
318
345
  const aspInfo = await this.arkProvider.getInfo();
319
346
  const address = await this.wallet.getAddress();
320
347
  if (!address) throw new Error("Failed to get ark address from service worker wallet");
321
- let receiverXOnlyPublicKey = this.wallet.xOnlyPublicKey();
348
+ let receiverXOnlyPublicKey = getXOnlyPublicKey(this.wallet);
322
349
  if (receiverXOnlyPublicKey.length == 33) {
323
350
  receiverXOnlyPublicKey = receiverXOnlyPublicKey.slice(1);
324
351
  } else if (receiverXOnlyPublicKey.length !== 32) {
@@ -334,7 +361,7 @@ var ArkadeLightning = class {
334
361
  network: aspInfo.network,
335
362
  preimageHash: hex.decode(getInvoicePaymentHash(pendingSwap.request.invoice)),
336
363
  receiverPubkey: pendingSwap.response.claimPublicKey,
337
- senderPubkey: hex.encode(this.wallet.xOnlyPublicKey()),
364
+ senderPubkey: hex.encode(getXOnlyPublicKey(this.wallet)),
338
365
  serverPubkey: aspInfo.signerPubkey,
339
366
  timeoutBlockHeights: pendingSwap.response.timeoutBlockHeights
340
367
  });
@@ -350,11 +377,11 @@ var ArkadeLightning = class {
350
377
  const vhtlcIdentity = {
351
378
  sign: async (tx, inputIndexes) => {
352
379
  const cpy = tx.clone();
353
- let signedTx = await this.wallet.sign(cpy, inputIndexes);
380
+ let signedTx = await signTransaction(this.wallet, cpy, inputIndexes);
354
381
  return Transaction.fromPSBT(signedTx.toPSBT(), { allowUnknown: true });
355
382
  },
356
383
  xOnlyPublicKey: receiverXOnlyPublicKey,
357
- signerSession: this.wallet.signerSession
384
+ signerSession: getSignerSession(this.wallet)
358
385
  };
359
386
  const serverUnrollScript = CSVMultisigTapscript.encode({
360
387
  pubkeys: [serverXOnlyPublicKey],
@@ -448,21 +475,27 @@ var ArkadeLightning = class {
448
475
  */
449
476
  async waitForSwapSettlement(pendingSwap) {
450
477
  return new Promise((resolve, reject) => {
478
+ let isResolved = false;
451
479
  const onStatusUpdate = async (status) => {
480
+ if (isResolved) return;
452
481
  switch (status) {
453
482
  case "swap.expired":
483
+ isResolved = true;
454
484
  this.storageProvider?.savePendingSubmarineSwap({ ...pendingSwap, status });
455
485
  reject(new SwapExpiredError({ isRefundable: true, pendingSwap }));
456
486
  break;
457
487
  case "invoice.failedToPay":
488
+ isResolved = true;
458
489
  this.storageProvider?.savePendingSubmarineSwap({ ...pendingSwap, status });
459
490
  reject(new InvoiceFailedToPayError({ isRefundable: true, pendingSwap }));
460
491
  break;
461
492
  case "transaction.lockupFailed":
493
+ isResolved = true;
462
494
  this.storageProvider?.savePendingSubmarineSwap({ ...pendingSwap, status });
463
495
  reject(new TransactionLockupFailedError({ isRefundable: true, pendingSwap }));
464
496
  break;
465
497
  case "transaction.claimed": {
498
+ isResolved = true;
466
499
  const { preimage } = await this.swapProvider.getSwapPreimage(pendingSwap.response.id);
467
500
  this.storageProvider?.savePendingSubmarineSwap({ ...pendingSwap, preimage, status });
468
501
  resolve({ preimage });
@@ -473,7 +506,12 @@ var ArkadeLightning = class {
473
506
  break;
474
507
  }
475
508
  };
476
- this.swapProvider.monitorSwap(pendingSwap.response.id, onStatusUpdate);
509
+ this.swapProvider.monitorSwap(pendingSwap.response.id, onStatusUpdate).catch((error) => {
510
+ if (!isResolved) {
511
+ isResolved = true;
512
+ reject(error);
513
+ }
514
+ });
477
515
  });
478
516
  }
479
517
  // validators
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkade-os/boltz-swap",
3
- "version": "0.1.5",
3
+ "version": "0.1.8",
4
4
  "type": "module",
5
5
  "description": "A production-ready TypeScript package that brings Boltz submarine-swaps to Arkade.",
6
6
  "main": "./dist/index.js",