@arkade-os/boltz-swap 0.2.0-alpha.7 → 0.2.0
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 +0 -2
- package/dist/index.cjs +41 -47
- package/dist/index.d.cts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +41 -47
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -145,7 +145,6 @@ if (limits && decodedInvoice.amountSats >= limits.min && decodedInvoice.amountSa
|
|
|
145
145
|
// Amount is valid for swaps
|
|
146
146
|
const paymentResult = await arkadeLightning.sendLightningPayment({
|
|
147
147
|
invoice: invoice,
|
|
148
|
-
maxFeeSats: 1000,
|
|
149
148
|
});
|
|
150
149
|
console.log('Payment successful!');
|
|
151
150
|
} else {
|
|
@@ -253,7 +252,6 @@ console.log('Payment Hash:', invoiceDetails.paymentHash);
|
|
|
253
252
|
// Pay the Lightning invoice from your Arkade wallet
|
|
254
253
|
const paymentResult = await arkadeLightning.sendLightningPayment({
|
|
255
254
|
invoice: 'lnbc500u1pj...', // Lightning invoice string
|
|
256
|
-
maxFeeSats: 1000, // Optional: Maximum fee you're willing to pay (in sats)
|
|
257
255
|
});
|
|
258
256
|
|
|
259
257
|
console.log('Payment successful!');
|
package/dist/index.cjs
CHANGED
|
@@ -87,9 +87,13 @@ var InsufficientFundsError = class extends SwapError {
|
|
|
87
87
|
}
|
|
88
88
|
};
|
|
89
89
|
var NetworkError = class extends Error {
|
|
90
|
-
|
|
90
|
+
statusCode;
|
|
91
|
+
errorData;
|
|
92
|
+
constructor(message, statusCode, errorData) {
|
|
91
93
|
super(message);
|
|
92
94
|
this.name = "NetworkError";
|
|
95
|
+
this.statusCode = statusCode;
|
|
96
|
+
this.errorData = errorData;
|
|
93
97
|
}
|
|
94
98
|
};
|
|
95
99
|
var SchemaError = class extends SwapError {
|
|
@@ -184,9 +188,7 @@ var isCreateReverseSwapResponse = (data) => {
|
|
|
184
188
|
return data && typeof data === "object" && typeof data.id === "string" && typeof data.invoice === "string" && typeof data.onchainAmount === "number" && typeof data.lockupAddress === "string" && typeof data.refundPublicKey === "string" && data.timeoutBlockHeights && typeof data.timeoutBlockHeights === "object" && typeof data.timeoutBlockHeights.refund === "number" && typeof data.timeoutBlockHeights.unilateralClaim === "number" && typeof data.timeoutBlockHeights.unilateralRefund === "number" && typeof data.timeoutBlockHeights.unilateralRefundWithoutReceiver === "number";
|
|
185
189
|
};
|
|
186
190
|
var BASE_URLS = {
|
|
187
|
-
bitcoin: "https://boltz.arkade.sh",
|
|
188
191
|
mutinynet: "https://api.boltz.mutinynet.arkade.sh",
|
|
189
|
-
testnet: "https://boltz.testnet.arkade.sh",
|
|
190
192
|
regtest: "http://localhost:9069"
|
|
191
193
|
};
|
|
192
194
|
var BoltzSwapProvider = class {
|
|
@@ -195,11 +197,12 @@ var BoltzSwapProvider = class {
|
|
|
195
197
|
network;
|
|
196
198
|
constructor(config) {
|
|
197
199
|
this.network = config.network;
|
|
198
|
-
|
|
199
|
-
if (!
|
|
200
|
+
const apiUrl = config.apiUrl || BASE_URLS[config.network];
|
|
201
|
+
if (!apiUrl)
|
|
200
202
|
throw new Error(
|
|
201
203
|
`API URL is required for network: ${config.network}`
|
|
202
204
|
);
|
|
205
|
+
this.apiUrl = apiUrl;
|
|
203
206
|
this.wsUrl = this.apiUrl.replace(/^http(s)?:\/\//, "ws$1://").replace("9069", "9004") + "/v2/ws";
|
|
204
207
|
}
|
|
205
208
|
getApiUrl() {
|
|
@@ -397,9 +400,13 @@ var BoltzSwapProvider = class {
|
|
|
397
400
|
});
|
|
398
401
|
if (!response.ok) {
|
|
399
402
|
const errorBody = await response.text();
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
+
let errorData;
|
|
404
|
+
try {
|
|
405
|
+
errorData = JSON.parse(errorBody);
|
|
406
|
+
} catch {
|
|
407
|
+
}
|
|
408
|
+
const message = errorData ? `Boltz API error: ${response.status}` : `Boltz API error: ${response.status} ${errorBody}`;
|
|
409
|
+
throw new NetworkError(message, response.status, errorData);
|
|
403
410
|
}
|
|
404
411
|
if (response.headers.get("content-length") === "0") {
|
|
405
412
|
throw new NetworkError("Empty response from Boltz API");
|
|
@@ -478,14 +485,14 @@ var ArkadeLightning = class {
|
|
|
478
485
|
await this.wallet.contractRepository.saveToContractCollection(
|
|
479
486
|
"reverseSwaps",
|
|
480
487
|
swap,
|
|
481
|
-
"
|
|
488
|
+
"id"
|
|
482
489
|
);
|
|
483
490
|
}
|
|
484
491
|
async savePendingSubmarineSwap(swap) {
|
|
485
492
|
await this.wallet.contractRepository.saveToContractCollection(
|
|
486
493
|
"submarineSwaps",
|
|
487
494
|
swap,
|
|
488
|
-
"
|
|
495
|
+
"id"
|
|
489
496
|
);
|
|
490
497
|
}
|
|
491
498
|
async getPendingReverseSwapsFromStorage() {
|
|
@@ -537,15 +544,6 @@ var ArkadeLightning = class {
|
|
|
537
544
|
*/
|
|
538
545
|
async sendLightningPayment(args) {
|
|
539
546
|
const pendingSwap = await this.createSubmarineSwap(args);
|
|
540
|
-
if (args.maxFeeSats != null) {
|
|
541
|
-
const invoiceAmount = decodeInvoice(args.invoice).amountSats ?? 0;
|
|
542
|
-
const fees = pendingSwap.response.expectedAmount - invoiceAmount;
|
|
543
|
-
if (invoiceAmount > 0 && fees > args.maxFeeSats) {
|
|
544
|
-
throw new SwapError({
|
|
545
|
-
message: `Swap fees ${fees} exceed max allowed ${args.maxFeeSats}`
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
547
|
await this.savePendingSubmarineSwap(pendingSwap);
|
|
550
548
|
const txid = await this.wallet.sendBitcoin({
|
|
551
549
|
address: pendingSwap.response.address,
|
|
@@ -561,9 +559,7 @@ var ArkadeLightning = class {
|
|
|
561
559
|
} catch (error) {
|
|
562
560
|
if (error.isRefundable) {
|
|
563
561
|
await this.refundVHTLC(pendingSwap);
|
|
564
|
-
const finalStatus = await this.getSwapStatus(
|
|
565
|
-
pendingSwap.response.id
|
|
566
|
-
);
|
|
562
|
+
const finalStatus = await this.getSwapStatus(pendingSwap.id);
|
|
567
563
|
await this.savePendingSubmarineSwap({
|
|
568
564
|
...pendingSwap,
|
|
569
565
|
status: finalStatus.status
|
|
@@ -593,6 +589,7 @@ var ArkadeLightning = class {
|
|
|
593
589
|
};
|
|
594
590
|
const swapResponse = await this.swapProvider.createSubmarineSwap(swapRequest);
|
|
595
591
|
const pendingSwap = {
|
|
592
|
+
id: swapResponse.id,
|
|
596
593
|
type: "submarine",
|
|
597
594
|
createdAt: Math.floor(Date.now() / 1e3),
|
|
598
595
|
request: swapRequest,
|
|
@@ -629,6 +626,7 @@ var ArkadeLightning = class {
|
|
|
629
626
|
};
|
|
630
627
|
const swapResponse = await this.swapProvider.createReverseSwap(swapRequest);
|
|
631
628
|
const pendingSwap = {
|
|
629
|
+
id: swapResponse.id,
|
|
632
630
|
type: "reverse",
|
|
633
631
|
createdAt: Math.floor(Date.now() / 1e3),
|
|
634
632
|
preimage: import_base.hex.encode(preimage),
|
|
@@ -699,11 +697,9 @@ var ArkadeLightning = class {
|
|
|
699
697
|
xOnlyPublicKey: receiverXOnlyPublicKey,
|
|
700
698
|
signerSession: getSignerSession(this.wallet)
|
|
701
699
|
};
|
|
702
|
-
const
|
|
703
|
-
aspInfo.checkpointExitClosure
|
|
704
|
-
);
|
|
700
|
+
const rawCheckpointTapscript = import_base.hex.decode(aspInfo.checkpointTapscript);
|
|
705
701
|
const serverUnrollScript = import_sdk.CSVMultisigTapscript.decode(
|
|
706
|
-
|
|
702
|
+
rawCheckpointTapscript
|
|
707
703
|
);
|
|
708
704
|
const { arkTx, checkpoints } = (0, import_sdk.buildOffchainTx)(
|
|
709
705
|
[
|
|
@@ -743,7 +739,7 @@ var ArkadeLightning = class {
|
|
|
743
739
|
})
|
|
744
740
|
);
|
|
745
741
|
await this.arkProvider.finalizeTx(arkTxid, finalCheckpoints);
|
|
746
|
-
const finalStatus = await this.getSwapStatus(pendingSwap.
|
|
742
|
+
const finalStatus = await this.getSwapStatus(pendingSwap.id);
|
|
747
743
|
await this.savePendingReverseSwap({
|
|
748
744
|
...pendingSwap,
|
|
749
745
|
status: finalStatus.status
|
|
@@ -811,11 +807,9 @@ var ArkadeLightning = class {
|
|
|
811
807
|
xOnlyPublicKey: receiverXOnlyPublicKey,
|
|
812
808
|
signerSession: getSignerSession(this.wallet)
|
|
813
809
|
};
|
|
814
|
-
const
|
|
815
|
-
aspInfo.checkpointExitClosure
|
|
816
|
-
);
|
|
810
|
+
const rawCheckpointTapscript = import_base.hex.decode(aspInfo.checkpointTapscript);
|
|
817
811
|
const serverUnrollScript = import_sdk.CSVMultisigTapscript.decode(
|
|
818
|
-
|
|
812
|
+
rawCheckpointTapscript
|
|
819
813
|
);
|
|
820
814
|
const { arkTx, checkpoints } = (0, import_sdk.buildOffchainTx)(
|
|
821
815
|
[
|
|
@@ -855,7 +849,7 @@ var ArkadeLightning = class {
|
|
|
855
849
|
})
|
|
856
850
|
);
|
|
857
851
|
await this.arkProvider.finalizeTx(arkTxid, finalCheckpoints);
|
|
858
|
-
const finalStatus = await this.getSwapStatus(pendingSwap.
|
|
852
|
+
const finalStatus = await this.getSwapStatus(pendingSwap.id);
|
|
859
853
|
await this.savePendingSubmarineSwap({
|
|
860
854
|
...pendingSwap,
|
|
861
855
|
status: finalStatus.status
|
|
@@ -884,13 +878,13 @@ var ArkadeLightning = class {
|
|
|
884
878
|
status
|
|
885
879
|
});
|
|
886
880
|
const swapStatus = await this.swapProvider.getReverseSwapTxId(
|
|
887
|
-
pendingSwap.
|
|
881
|
+
pendingSwap.id
|
|
888
882
|
);
|
|
889
883
|
const txid = swapStatus.id;
|
|
890
884
|
if (!txid || txid.trim() === "") {
|
|
891
885
|
reject(
|
|
892
886
|
new SwapError({
|
|
893
|
-
message: `Transaction ID not available for settled swap ${pendingSwap.
|
|
887
|
+
message: `Transaction ID not available for settled swap ${pendingSwap.id}.`
|
|
894
888
|
})
|
|
895
889
|
);
|
|
896
890
|
break;
|
|
@@ -944,10 +938,7 @@ var ArkadeLightning = class {
|
|
|
944
938
|
break;
|
|
945
939
|
}
|
|
946
940
|
};
|
|
947
|
-
this.swapProvider.monitorSwap(
|
|
948
|
-
pendingSwap.response.id,
|
|
949
|
-
onStatusUpdate
|
|
950
|
-
);
|
|
941
|
+
this.swapProvider.monitorSwap(pendingSwap.id, onStatusUpdate);
|
|
951
942
|
});
|
|
952
943
|
}
|
|
953
944
|
/**
|
|
@@ -1006,7 +997,7 @@ var ArkadeLightning = class {
|
|
|
1006
997
|
case "transaction.claimed": {
|
|
1007
998
|
isResolved = true;
|
|
1008
999
|
const { preimage } = await this.swapProvider.getSwapPreimage(
|
|
1009
|
-
pendingSwap.
|
|
1000
|
+
pendingSwap.id
|
|
1010
1001
|
);
|
|
1011
1002
|
await this.savePendingSubmarineSwap({
|
|
1012
1003
|
...pendingSwap,
|
|
@@ -1024,7 +1015,7 @@ var ArkadeLightning = class {
|
|
|
1024
1015
|
break;
|
|
1025
1016
|
}
|
|
1026
1017
|
};
|
|
1027
|
-
this.swapProvider.monitorSwap(pendingSwap.
|
|
1018
|
+
this.swapProvider.monitorSwap(pendingSwap.id, onStatusUpdate).catch((error) => {
|
|
1028
1019
|
if (!isResolved) {
|
|
1029
1020
|
isResolved = true;
|
|
1030
1021
|
reject(error);
|
|
@@ -1095,6 +1086,7 @@ var ArkadeLightning = class {
|
|
|
1095
1086
|
`Invalid server public key length: ${serverXOnlyPublicKey.length}`
|
|
1096
1087
|
);
|
|
1097
1088
|
}
|
|
1089
|
+
const delayType = (num) => num < 512 ? "blocks" : "seconds";
|
|
1098
1090
|
const vhtlcScript = new import_sdk.VHTLC.Script({
|
|
1099
1091
|
preimageHash: (0, import_legacy.ripemd160)(preimageHash),
|
|
1100
1092
|
sender: senderXOnlyPublicKey,
|
|
@@ -1102,15 +1094,17 @@ var ArkadeLightning = class {
|
|
|
1102
1094
|
server: serverXOnlyPublicKey,
|
|
1103
1095
|
refundLocktime: BigInt(timeoutBlockHeights.refund),
|
|
1104
1096
|
unilateralClaimDelay: {
|
|
1105
|
-
type:
|
|
1097
|
+
type: delayType(timeoutBlockHeights.unilateralClaim),
|
|
1106
1098
|
value: BigInt(timeoutBlockHeights.unilateralClaim)
|
|
1107
1099
|
},
|
|
1108
1100
|
unilateralRefundDelay: {
|
|
1109
|
-
type:
|
|
1101
|
+
type: delayType(timeoutBlockHeights.unilateralRefund),
|
|
1110
1102
|
value: BigInt(timeoutBlockHeights.unilateralRefund)
|
|
1111
1103
|
},
|
|
1112
1104
|
unilateralRefundWithoutReceiverDelay: {
|
|
1113
|
-
type:
|
|
1105
|
+
type: delayType(
|
|
1106
|
+
timeoutBlockHeights.unilateralRefundWithoutReceiver
|
|
1107
|
+
),
|
|
1114
1108
|
value: BigInt(
|
|
1115
1109
|
timeoutBlockHeights.unilateralRefundWithoutReceiver
|
|
1116
1110
|
)
|
|
@@ -1195,22 +1189,22 @@ var ArkadeLightning = class {
|
|
|
1195
1189
|
async refreshSwapsStatus() {
|
|
1196
1190
|
for (const swap of await this.getPendingReverseSwapsFromStorage()) {
|
|
1197
1191
|
if (isReverseFinalStatus(swap.status)) continue;
|
|
1198
|
-
this.getSwapStatus(swap.
|
|
1192
|
+
this.getSwapStatus(swap.id).then(({ status }) => {
|
|
1199
1193
|
this.savePendingReverseSwap({ ...swap, status });
|
|
1200
1194
|
}).catch((error) => {
|
|
1201
1195
|
console.error(
|
|
1202
|
-
`Failed to refresh swap status for ${swap.
|
|
1196
|
+
`Failed to refresh swap status for ${swap.id}:`,
|
|
1203
1197
|
error
|
|
1204
1198
|
);
|
|
1205
1199
|
});
|
|
1206
1200
|
}
|
|
1207
1201
|
for (const swap of await this.getPendingSubmarineSwapsFromStorage()) {
|
|
1208
1202
|
if (isSubmarineFinalStatus(swap.status)) continue;
|
|
1209
|
-
this.getSwapStatus(swap.
|
|
1203
|
+
this.getSwapStatus(swap.id).then(({ status }) => {
|
|
1210
1204
|
this.savePendingSubmarineSwap({ ...swap, status });
|
|
1211
1205
|
}).catch((error) => {
|
|
1212
1206
|
console.error(
|
|
1213
|
-
`Failed to refresh swap status for ${swap.
|
|
1207
|
+
`Failed to refresh swap status for ${swap.id}:`,
|
|
1214
1208
|
error
|
|
1215
1209
|
);
|
|
1216
1210
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -95,7 +95,7 @@ interface Vtxo {
|
|
|
95
95
|
locktime: number;
|
|
96
96
|
};
|
|
97
97
|
}
|
|
98
|
-
type Network = "bitcoin" | "mutinynet" | "regtest" | "
|
|
98
|
+
type Network = "bitcoin" | "mutinynet" | "regtest" | "signet";
|
|
99
99
|
interface CreateLightningInvoiceRequest {
|
|
100
100
|
amount: number;
|
|
101
101
|
description?: string;
|
|
@@ -110,7 +110,6 @@ interface CreateLightningInvoiceResponse {
|
|
|
110
110
|
}
|
|
111
111
|
interface SendLightningPaymentRequest {
|
|
112
112
|
invoice: string;
|
|
113
|
-
maxFeeSats?: number;
|
|
114
113
|
}
|
|
115
114
|
interface SendLightningPaymentResponse {
|
|
116
115
|
amount: number;
|
|
@@ -118,6 +117,7 @@ interface SendLightningPaymentResponse {
|
|
|
118
117
|
txid: string;
|
|
119
118
|
}
|
|
120
119
|
interface PendingReverseSwap {
|
|
120
|
+
id: string;
|
|
121
121
|
type: "reverse";
|
|
122
122
|
createdAt: number;
|
|
123
123
|
preimage: string;
|
|
@@ -126,6 +126,7 @@ interface PendingReverseSwap {
|
|
|
126
126
|
response: CreateReverseSwapResponse;
|
|
127
127
|
}
|
|
128
128
|
interface PendingSubmarineSwap {
|
|
129
|
+
id: string;
|
|
129
130
|
type: "submarine";
|
|
130
131
|
createdAt: number;
|
|
131
132
|
preimage?: string;
|
|
@@ -367,7 +368,9 @@ declare class InsufficientFundsError extends SwapError {
|
|
|
367
368
|
constructor(options?: ErrorOptions);
|
|
368
369
|
}
|
|
369
370
|
declare class NetworkError extends Error {
|
|
370
|
-
|
|
371
|
+
statusCode?: number;
|
|
372
|
+
errorData?: any;
|
|
373
|
+
constructor(message: string, statusCode?: number, errorData?: any);
|
|
371
374
|
}
|
|
372
375
|
declare class SchemaError extends SwapError {
|
|
373
376
|
constructor(options?: ErrorOptions);
|
package/dist/index.d.ts
CHANGED
|
@@ -95,7 +95,7 @@ interface Vtxo {
|
|
|
95
95
|
locktime: number;
|
|
96
96
|
};
|
|
97
97
|
}
|
|
98
|
-
type Network = "bitcoin" | "mutinynet" | "regtest" | "
|
|
98
|
+
type Network = "bitcoin" | "mutinynet" | "regtest" | "signet";
|
|
99
99
|
interface CreateLightningInvoiceRequest {
|
|
100
100
|
amount: number;
|
|
101
101
|
description?: string;
|
|
@@ -110,7 +110,6 @@ interface CreateLightningInvoiceResponse {
|
|
|
110
110
|
}
|
|
111
111
|
interface SendLightningPaymentRequest {
|
|
112
112
|
invoice: string;
|
|
113
|
-
maxFeeSats?: number;
|
|
114
113
|
}
|
|
115
114
|
interface SendLightningPaymentResponse {
|
|
116
115
|
amount: number;
|
|
@@ -118,6 +117,7 @@ interface SendLightningPaymentResponse {
|
|
|
118
117
|
txid: string;
|
|
119
118
|
}
|
|
120
119
|
interface PendingReverseSwap {
|
|
120
|
+
id: string;
|
|
121
121
|
type: "reverse";
|
|
122
122
|
createdAt: number;
|
|
123
123
|
preimage: string;
|
|
@@ -126,6 +126,7 @@ interface PendingReverseSwap {
|
|
|
126
126
|
response: CreateReverseSwapResponse;
|
|
127
127
|
}
|
|
128
128
|
interface PendingSubmarineSwap {
|
|
129
|
+
id: string;
|
|
129
130
|
type: "submarine";
|
|
130
131
|
createdAt: number;
|
|
131
132
|
preimage?: string;
|
|
@@ -367,7 +368,9 @@ declare class InsufficientFundsError extends SwapError {
|
|
|
367
368
|
constructor(options?: ErrorOptions);
|
|
368
369
|
}
|
|
369
370
|
declare class NetworkError extends Error {
|
|
370
|
-
|
|
371
|
+
statusCode?: number;
|
|
372
|
+
errorData?: any;
|
|
373
|
+
constructor(message: string, statusCode?: number, errorData?: any);
|
|
371
374
|
}
|
|
372
375
|
declare class SchemaError extends SwapError {
|
|
373
376
|
constructor(options?: ErrorOptions);
|
package/dist/index.js
CHANGED
|
@@ -33,9 +33,13 @@ var InsufficientFundsError = class extends SwapError {
|
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
35
|
var NetworkError = class extends Error {
|
|
36
|
-
|
|
36
|
+
statusCode;
|
|
37
|
+
errorData;
|
|
38
|
+
constructor(message, statusCode, errorData) {
|
|
37
39
|
super(message);
|
|
38
40
|
this.name = "NetworkError";
|
|
41
|
+
this.statusCode = statusCode;
|
|
42
|
+
this.errorData = errorData;
|
|
39
43
|
}
|
|
40
44
|
};
|
|
41
45
|
var SchemaError = class extends SwapError {
|
|
@@ -137,9 +141,7 @@ var isCreateReverseSwapResponse = (data) => {
|
|
|
137
141
|
return data && typeof data === "object" && typeof data.id === "string" && typeof data.invoice === "string" && typeof data.onchainAmount === "number" && typeof data.lockupAddress === "string" && typeof data.refundPublicKey === "string" && data.timeoutBlockHeights && typeof data.timeoutBlockHeights === "object" && typeof data.timeoutBlockHeights.refund === "number" && typeof data.timeoutBlockHeights.unilateralClaim === "number" && typeof data.timeoutBlockHeights.unilateralRefund === "number" && typeof data.timeoutBlockHeights.unilateralRefundWithoutReceiver === "number";
|
|
138
142
|
};
|
|
139
143
|
var BASE_URLS = {
|
|
140
|
-
bitcoin: "https://boltz.arkade.sh",
|
|
141
144
|
mutinynet: "https://api.boltz.mutinynet.arkade.sh",
|
|
142
|
-
testnet: "https://boltz.testnet.arkade.sh",
|
|
143
145
|
regtest: "http://localhost:9069"
|
|
144
146
|
};
|
|
145
147
|
var BoltzSwapProvider = class {
|
|
@@ -148,11 +150,12 @@ var BoltzSwapProvider = class {
|
|
|
148
150
|
network;
|
|
149
151
|
constructor(config) {
|
|
150
152
|
this.network = config.network;
|
|
151
|
-
|
|
152
|
-
if (!
|
|
153
|
+
const apiUrl = config.apiUrl || BASE_URLS[config.network];
|
|
154
|
+
if (!apiUrl)
|
|
153
155
|
throw new Error(
|
|
154
156
|
`API URL is required for network: ${config.network}`
|
|
155
157
|
);
|
|
158
|
+
this.apiUrl = apiUrl;
|
|
156
159
|
this.wsUrl = this.apiUrl.replace(/^http(s)?:\/\//, "ws$1://").replace("9069", "9004") + "/v2/ws";
|
|
157
160
|
}
|
|
158
161
|
getApiUrl() {
|
|
@@ -350,9 +353,13 @@ var BoltzSwapProvider = class {
|
|
|
350
353
|
});
|
|
351
354
|
if (!response.ok) {
|
|
352
355
|
const errorBody = await response.text();
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
+
let errorData;
|
|
357
|
+
try {
|
|
358
|
+
errorData = JSON.parse(errorBody);
|
|
359
|
+
} catch {
|
|
360
|
+
}
|
|
361
|
+
const message = errorData ? `Boltz API error: ${response.status}` : `Boltz API error: ${response.status} ${errorBody}`;
|
|
362
|
+
throw new NetworkError(message, response.status, errorData);
|
|
356
363
|
}
|
|
357
364
|
if (response.headers.get("content-length") === "0") {
|
|
358
365
|
throw new NetworkError("Empty response from Boltz API");
|
|
@@ -431,14 +438,14 @@ var ArkadeLightning = class {
|
|
|
431
438
|
await this.wallet.contractRepository.saveToContractCollection(
|
|
432
439
|
"reverseSwaps",
|
|
433
440
|
swap,
|
|
434
|
-
"
|
|
441
|
+
"id"
|
|
435
442
|
);
|
|
436
443
|
}
|
|
437
444
|
async savePendingSubmarineSwap(swap) {
|
|
438
445
|
await this.wallet.contractRepository.saveToContractCollection(
|
|
439
446
|
"submarineSwaps",
|
|
440
447
|
swap,
|
|
441
|
-
"
|
|
448
|
+
"id"
|
|
442
449
|
);
|
|
443
450
|
}
|
|
444
451
|
async getPendingReverseSwapsFromStorage() {
|
|
@@ -490,15 +497,6 @@ var ArkadeLightning = class {
|
|
|
490
497
|
*/
|
|
491
498
|
async sendLightningPayment(args) {
|
|
492
499
|
const pendingSwap = await this.createSubmarineSwap(args);
|
|
493
|
-
if (args.maxFeeSats != null) {
|
|
494
|
-
const invoiceAmount = decodeInvoice(args.invoice).amountSats ?? 0;
|
|
495
|
-
const fees = pendingSwap.response.expectedAmount - invoiceAmount;
|
|
496
|
-
if (invoiceAmount > 0 && fees > args.maxFeeSats) {
|
|
497
|
-
throw new SwapError({
|
|
498
|
-
message: `Swap fees ${fees} exceed max allowed ${args.maxFeeSats}`
|
|
499
|
-
});
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
500
|
await this.savePendingSubmarineSwap(pendingSwap);
|
|
503
501
|
const txid = await this.wallet.sendBitcoin({
|
|
504
502
|
address: pendingSwap.response.address,
|
|
@@ -514,9 +512,7 @@ var ArkadeLightning = class {
|
|
|
514
512
|
} catch (error) {
|
|
515
513
|
if (error.isRefundable) {
|
|
516
514
|
await this.refundVHTLC(pendingSwap);
|
|
517
|
-
const finalStatus = await this.getSwapStatus(
|
|
518
|
-
pendingSwap.response.id
|
|
519
|
-
);
|
|
515
|
+
const finalStatus = await this.getSwapStatus(pendingSwap.id);
|
|
520
516
|
await this.savePendingSubmarineSwap({
|
|
521
517
|
...pendingSwap,
|
|
522
518
|
status: finalStatus.status
|
|
@@ -546,6 +542,7 @@ var ArkadeLightning = class {
|
|
|
546
542
|
};
|
|
547
543
|
const swapResponse = await this.swapProvider.createSubmarineSwap(swapRequest);
|
|
548
544
|
const pendingSwap = {
|
|
545
|
+
id: swapResponse.id,
|
|
549
546
|
type: "submarine",
|
|
550
547
|
createdAt: Math.floor(Date.now() / 1e3),
|
|
551
548
|
request: swapRequest,
|
|
@@ -582,6 +579,7 @@ var ArkadeLightning = class {
|
|
|
582
579
|
};
|
|
583
580
|
const swapResponse = await this.swapProvider.createReverseSwap(swapRequest);
|
|
584
581
|
const pendingSwap = {
|
|
582
|
+
id: swapResponse.id,
|
|
585
583
|
type: "reverse",
|
|
586
584
|
createdAt: Math.floor(Date.now() / 1e3),
|
|
587
585
|
preimage: hex.encode(preimage),
|
|
@@ -652,11 +650,9 @@ var ArkadeLightning = class {
|
|
|
652
650
|
xOnlyPublicKey: receiverXOnlyPublicKey,
|
|
653
651
|
signerSession: getSignerSession(this.wallet)
|
|
654
652
|
};
|
|
655
|
-
const
|
|
656
|
-
aspInfo.checkpointExitClosure
|
|
657
|
-
);
|
|
653
|
+
const rawCheckpointTapscript = hex.decode(aspInfo.checkpointTapscript);
|
|
658
654
|
const serverUnrollScript = CSVMultisigTapscript.decode(
|
|
659
|
-
|
|
655
|
+
rawCheckpointTapscript
|
|
660
656
|
);
|
|
661
657
|
const { arkTx, checkpoints } = buildOffchainTx(
|
|
662
658
|
[
|
|
@@ -696,7 +692,7 @@ var ArkadeLightning = class {
|
|
|
696
692
|
})
|
|
697
693
|
);
|
|
698
694
|
await this.arkProvider.finalizeTx(arkTxid, finalCheckpoints);
|
|
699
|
-
const finalStatus = await this.getSwapStatus(pendingSwap.
|
|
695
|
+
const finalStatus = await this.getSwapStatus(pendingSwap.id);
|
|
700
696
|
await this.savePendingReverseSwap({
|
|
701
697
|
...pendingSwap,
|
|
702
698
|
status: finalStatus.status
|
|
@@ -764,11 +760,9 @@ var ArkadeLightning = class {
|
|
|
764
760
|
xOnlyPublicKey: receiverXOnlyPublicKey,
|
|
765
761
|
signerSession: getSignerSession(this.wallet)
|
|
766
762
|
};
|
|
767
|
-
const
|
|
768
|
-
aspInfo.checkpointExitClosure
|
|
769
|
-
);
|
|
763
|
+
const rawCheckpointTapscript = hex.decode(aspInfo.checkpointTapscript);
|
|
770
764
|
const serverUnrollScript = CSVMultisigTapscript.decode(
|
|
771
|
-
|
|
765
|
+
rawCheckpointTapscript
|
|
772
766
|
);
|
|
773
767
|
const { arkTx, checkpoints } = buildOffchainTx(
|
|
774
768
|
[
|
|
@@ -808,7 +802,7 @@ var ArkadeLightning = class {
|
|
|
808
802
|
})
|
|
809
803
|
);
|
|
810
804
|
await this.arkProvider.finalizeTx(arkTxid, finalCheckpoints);
|
|
811
|
-
const finalStatus = await this.getSwapStatus(pendingSwap.
|
|
805
|
+
const finalStatus = await this.getSwapStatus(pendingSwap.id);
|
|
812
806
|
await this.savePendingSubmarineSwap({
|
|
813
807
|
...pendingSwap,
|
|
814
808
|
status: finalStatus.status
|
|
@@ -837,13 +831,13 @@ var ArkadeLightning = class {
|
|
|
837
831
|
status
|
|
838
832
|
});
|
|
839
833
|
const swapStatus = await this.swapProvider.getReverseSwapTxId(
|
|
840
|
-
pendingSwap.
|
|
834
|
+
pendingSwap.id
|
|
841
835
|
);
|
|
842
836
|
const txid = swapStatus.id;
|
|
843
837
|
if (!txid || txid.trim() === "") {
|
|
844
838
|
reject(
|
|
845
839
|
new SwapError({
|
|
846
|
-
message: `Transaction ID not available for settled swap ${pendingSwap.
|
|
840
|
+
message: `Transaction ID not available for settled swap ${pendingSwap.id}.`
|
|
847
841
|
})
|
|
848
842
|
);
|
|
849
843
|
break;
|
|
@@ -897,10 +891,7 @@ var ArkadeLightning = class {
|
|
|
897
891
|
break;
|
|
898
892
|
}
|
|
899
893
|
};
|
|
900
|
-
this.swapProvider.monitorSwap(
|
|
901
|
-
pendingSwap.response.id,
|
|
902
|
-
onStatusUpdate
|
|
903
|
-
);
|
|
894
|
+
this.swapProvider.monitorSwap(pendingSwap.id, onStatusUpdate);
|
|
904
895
|
});
|
|
905
896
|
}
|
|
906
897
|
/**
|
|
@@ -959,7 +950,7 @@ var ArkadeLightning = class {
|
|
|
959
950
|
case "transaction.claimed": {
|
|
960
951
|
isResolved = true;
|
|
961
952
|
const { preimage } = await this.swapProvider.getSwapPreimage(
|
|
962
|
-
pendingSwap.
|
|
953
|
+
pendingSwap.id
|
|
963
954
|
);
|
|
964
955
|
await this.savePendingSubmarineSwap({
|
|
965
956
|
...pendingSwap,
|
|
@@ -977,7 +968,7 @@ var ArkadeLightning = class {
|
|
|
977
968
|
break;
|
|
978
969
|
}
|
|
979
970
|
};
|
|
980
|
-
this.swapProvider.monitorSwap(pendingSwap.
|
|
971
|
+
this.swapProvider.monitorSwap(pendingSwap.id, onStatusUpdate).catch((error) => {
|
|
981
972
|
if (!isResolved) {
|
|
982
973
|
isResolved = true;
|
|
983
974
|
reject(error);
|
|
@@ -1048,6 +1039,7 @@ var ArkadeLightning = class {
|
|
|
1048
1039
|
`Invalid server public key length: ${serverXOnlyPublicKey.length}`
|
|
1049
1040
|
);
|
|
1050
1041
|
}
|
|
1042
|
+
const delayType = (num) => num < 512 ? "blocks" : "seconds";
|
|
1051
1043
|
const vhtlcScript = new VHTLC.Script({
|
|
1052
1044
|
preimageHash: ripemd160(preimageHash),
|
|
1053
1045
|
sender: senderXOnlyPublicKey,
|
|
@@ -1055,15 +1047,17 @@ var ArkadeLightning = class {
|
|
|
1055
1047
|
server: serverXOnlyPublicKey,
|
|
1056
1048
|
refundLocktime: BigInt(timeoutBlockHeights.refund),
|
|
1057
1049
|
unilateralClaimDelay: {
|
|
1058
|
-
type:
|
|
1050
|
+
type: delayType(timeoutBlockHeights.unilateralClaim),
|
|
1059
1051
|
value: BigInt(timeoutBlockHeights.unilateralClaim)
|
|
1060
1052
|
},
|
|
1061
1053
|
unilateralRefundDelay: {
|
|
1062
|
-
type:
|
|
1054
|
+
type: delayType(timeoutBlockHeights.unilateralRefund),
|
|
1063
1055
|
value: BigInt(timeoutBlockHeights.unilateralRefund)
|
|
1064
1056
|
},
|
|
1065
1057
|
unilateralRefundWithoutReceiverDelay: {
|
|
1066
|
-
type:
|
|
1058
|
+
type: delayType(
|
|
1059
|
+
timeoutBlockHeights.unilateralRefundWithoutReceiver
|
|
1060
|
+
),
|
|
1067
1061
|
value: BigInt(
|
|
1068
1062
|
timeoutBlockHeights.unilateralRefundWithoutReceiver
|
|
1069
1063
|
)
|
|
@@ -1148,22 +1142,22 @@ var ArkadeLightning = class {
|
|
|
1148
1142
|
async refreshSwapsStatus() {
|
|
1149
1143
|
for (const swap of await this.getPendingReverseSwapsFromStorage()) {
|
|
1150
1144
|
if (isReverseFinalStatus(swap.status)) continue;
|
|
1151
|
-
this.getSwapStatus(swap.
|
|
1145
|
+
this.getSwapStatus(swap.id).then(({ status }) => {
|
|
1152
1146
|
this.savePendingReverseSwap({ ...swap, status });
|
|
1153
1147
|
}).catch((error) => {
|
|
1154
1148
|
console.error(
|
|
1155
|
-
`Failed to refresh swap status for ${swap.
|
|
1149
|
+
`Failed to refresh swap status for ${swap.id}:`,
|
|
1156
1150
|
error
|
|
1157
1151
|
);
|
|
1158
1152
|
});
|
|
1159
1153
|
}
|
|
1160
1154
|
for (const swap of await this.getPendingSubmarineSwapsFromStorage()) {
|
|
1161
1155
|
if (isSubmarineFinalStatus(swap.status)) continue;
|
|
1162
|
-
this.getSwapStatus(swap.
|
|
1156
|
+
this.getSwapStatus(swap.id).then(({ status }) => {
|
|
1163
1157
|
this.savePendingSubmarineSwap({ ...swap, status });
|
|
1164
1158
|
}).catch((error) => {
|
|
1165
1159
|
console.error(
|
|
1166
|
-
`Failed to refresh swap status for ${swap.
|
|
1160
|
+
`Failed to refresh swap status for ${swap.id}:`,
|
|
1167
1161
|
error
|
|
1168
1162
|
);
|
|
1169
1163
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arkade-os/boltz-swap",
|
|
3
|
-
"version": "0.2.0
|
|
3
|
+
"version": "0.2.0",
|
|
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",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"author": "Arkade-OS",
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@arkade-os/sdk": "0.3.
|
|
33
|
+
"@arkade-os/sdk": "0.3.1-alpha.6",
|
|
34
34
|
"@noble/hashes": "2.0.0",
|
|
35
35
|
"@scure/base": "2.0.0",
|
|
36
36
|
"@scure/btc-signer": "2.0.1",
|