@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 +43 -0
- package/dist/index.cjs +55 -17
- package/dist/index.d.cts +10 -4
- package/dist/index.d.ts +10 -4
- package/dist/index.js +55 -17
- package/package.json +1 -1
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
172
|
+
arkProvider?: ArkProvider;
|
|
167
173
|
swapProvider: BoltzSwapProvider;
|
|
168
|
-
indexerProvider
|
|
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,
|
|
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
|
|
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
|
|
172
|
+
arkProvider?: ArkProvider;
|
|
167
173
|
swapProvider: BoltzSwapProvider;
|
|
168
|
-
indexerProvider
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|