@arkade-os/boltz-swap 0.3.32 → 0.3.34
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 +22 -26
- package/dist/{arkade-swaps-CS8FZSVL.d.cts → arkade-swaps-BXAD1s8j.d.ts} +69 -8
- package/dist/{arkade-swaps-WiKCanCL.d.ts → arkade-swaps-CfMets16.d.cts} +69 -8
- package/dist/{chunk-NHBWNN6H.js → chunk-5K2FS2FE.js} +8 -27
- package/dist/chunk-SJQJQO7P.js +25 -0
- package/dist/{chunk-B3Q4TFWT.js → chunk-TDBUZE4N.js} +817 -866
- package/dist/expo/background.cjs +840 -892
- package/dist/expo/background.d.cts +3 -3
- package/dist/expo/background.d.ts +3 -3
- package/dist/expo/background.js +9 -20
- package/dist/expo/index.cjs +840 -870
- package/dist/expo/index.d.cts +8 -6
- package/dist/expo/index.d.ts +8 -6
- package/dist/expo/index.js +17 -20
- package/dist/index.cjs +1034 -1022
- package/dist/index.d.cts +95 -11
- package/dist/index.d.ts +95 -11
- package/dist/index.js +164 -119
- package/dist/repositories/realm/index.cjs +10 -22
- package/dist/repositories/realm/index.d.cts +7 -5
- package/dist/repositories/realm/index.d.ts +7 -5
- package/dist/repositories/realm/index.js +8 -22
- package/dist/repositories/sqlite/index.cjs +12 -23
- package/dist/repositories/sqlite/index.d.cts +1 -1
- package/dist/repositories/sqlite/index.d.ts +1 -1
- package/dist/repositories/sqlite/index.js +10 -23
- package/dist/{swapsPollProcessor-BF3uTFae.d.cts → swapsPollProcessor-BpAqG0V6.d.cts} +3 -3
- package/dist/{swapsPollProcessor-wYOMzldd.d.ts → swapsPollProcessor-DFVOAy_-.d.ts} +3 -3
- package/dist/{types-BBI7-KJ0.d.cts → types--axEWA8c.d.cts} +42 -4
- package/dist/{types-BBI7-KJ0.d.ts → types--axEWA8c.d.ts} +42 -4
- package/package.json +10 -25
package/dist/index.cjs
CHANGED
|
@@ -35,12 +35,14 @@ __export(index_exports, {
|
|
|
35
35
|
ArkadeSwapsMessageHandler: () => ArkadeSwapsMessageHandler,
|
|
36
36
|
BoltzRefundError: () => BoltzRefundError,
|
|
37
37
|
BoltzSwapProvider: () => BoltzSwapProvider,
|
|
38
|
+
InMemorySwapRepository: () => InMemorySwapRepository,
|
|
38
39
|
IndexedDbSwapRepository: () => IndexedDbSwapRepository,
|
|
39
40
|
InsufficientFundsError: () => InsufficientFundsError,
|
|
40
41
|
InvoiceExpiredError: () => InvoiceExpiredError,
|
|
41
42
|
InvoiceFailedToPayError: () => InvoiceFailedToPayError,
|
|
42
43
|
NetworkError: () => NetworkError,
|
|
43
44
|
PreimageFetchError: () => PreimageFetchError,
|
|
45
|
+
QuoteRejectedError: () => QuoteRejectedError,
|
|
44
46
|
SchemaError: () => SchemaError,
|
|
45
47
|
ServiceWorkerArkadeLightning: () => ServiceWorkerArkadeSwaps,
|
|
46
48
|
ServiceWorkerArkadeSwaps: () => ServiceWorkerArkadeSwaps,
|
|
@@ -99,7 +101,10 @@ var SwapError = class extends Error {
|
|
|
99
101
|
/** The pending swap associated with this error, if available. */
|
|
100
102
|
pendingSwap;
|
|
101
103
|
constructor(options = {}) {
|
|
102
|
-
super(
|
|
104
|
+
super(
|
|
105
|
+
options.message ?? "Error during swap.",
|
|
106
|
+
options.cause !== void 0 ? { cause: options.cause } : void 0
|
|
107
|
+
);
|
|
103
108
|
this.name = "SwapError";
|
|
104
109
|
this.isClaimable = options.isClaimable ?? false;
|
|
105
110
|
this.isRefundable = options.isRefundable ?? false;
|
|
@@ -191,6 +196,100 @@ var TransactionRefundedError = class extends SwapError {
|
|
|
191
196
|
this.name = "TransactionRefundedError";
|
|
192
197
|
}
|
|
193
198
|
};
|
|
199
|
+
var QuoteRejectedError = class _QuoteRejectedError extends SwapError {
|
|
200
|
+
reason;
|
|
201
|
+
quotedAmount;
|
|
202
|
+
floor;
|
|
203
|
+
constructor(options) {
|
|
204
|
+
super({
|
|
205
|
+
message: options.message ?? _QuoteRejectedError.defaultMessage(options),
|
|
206
|
+
...options
|
|
207
|
+
});
|
|
208
|
+
this.name = "QuoteRejectedError";
|
|
209
|
+
this.reason = options.reason;
|
|
210
|
+
this.quotedAmount = "quotedAmount" in options ? options.quotedAmount : void 0;
|
|
211
|
+
this.floor = "floor" in options ? options.floor : void 0;
|
|
212
|
+
}
|
|
213
|
+
static defaultMessage(options) {
|
|
214
|
+
switch (options.reason) {
|
|
215
|
+
case "below_floor":
|
|
216
|
+
return `Boltz quote ${options.quotedAmount} is below acceptable floor ${options.floor}`;
|
|
217
|
+
case "non_positive":
|
|
218
|
+
return `Boltz quote ${options.quotedAmount} is not positive`;
|
|
219
|
+
case "non_safe_integer":
|
|
220
|
+
return `Boltz quote ${options.quotedAmount} is not a safe positive satoshi integer`;
|
|
221
|
+
case "no_baseline":
|
|
222
|
+
return "Cannot accept quote: no minAcceptableAmount and no stored pending swap";
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Serialize into a plain `Error` whose `.message` carries the full
|
|
227
|
+
* rejection payload as JSON behind a marker prefix. Structured clone
|
|
228
|
+
* (used by `postMessage` between page and service worker) preserves
|
|
229
|
+
* `Error.message` reliably but strips custom `.name` and own properties,
|
|
230
|
+
* so we move the typed data into the message field for transport.
|
|
231
|
+
*/
|
|
232
|
+
toTransportError() {
|
|
233
|
+
return new Error(
|
|
234
|
+
QUOTE_REJECTION_TRANSPORT_PREFIX + JSON.stringify({
|
|
235
|
+
reason: this.reason,
|
|
236
|
+
message: this.message,
|
|
237
|
+
quotedAmount: this.quotedAmount,
|
|
238
|
+
floor: this.floor
|
|
239
|
+
})
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Inverse of `toTransportError`. Returns a real `QuoteRejectedError` if
|
|
244
|
+
* `error` carries the transport prefix, else `null`.
|
|
245
|
+
*/
|
|
246
|
+
static fromTransportError(error) {
|
|
247
|
+
if (!(error instanceof Error) || !error.message.startsWith(QUOTE_REJECTION_TRANSPORT_PREFIX)) {
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
const payload = error.message.slice(QUOTE_REJECTION_TRANSPORT_PREFIX.length);
|
|
251
|
+
let data;
|
|
252
|
+
try {
|
|
253
|
+
data = JSON.parse(payload);
|
|
254
|
+
} catch {
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
if (typeof data.reason !== "string" || !QUOTE_REJECTION_REASONS.has(data.reason)) {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
const message = typeof data.message === "string" ? data.message : void 0;
|
|
261
|
+
const reason = data.reason;
|
|
262
|
+
const quotedAmount = typeof data.quotedAmount === "number" ? data.quotedAmount : null;
|
|
263
|
+
const floor = typeof data.floor === "number" ? data.floor : null;
|
|
264
|
+
switch (reason) {
|
|
265
|
+
case "below_floor":
|
|
266
|
+
if (quotedAmount === null || floor === null) return null;
|
|
267
|
+
return new _QuoteRejectedError({
|
|
268
|
+
reason,
|
|
269
|
+
quotedAmount,
|
|
270
|
+
floor,
|
|
271
|
+
message
|
|
272
|
+
});
|
|
273
|
+
case "non_positive":
|
|
274
|
+
case "non_safe_integer":
|
|
275
|
+
if (quotedAmount === null) return null;
|
|
276
|
+
return new _QuoteRejectedError({
|
|
277
|
+
reason,
|
|
278
|
+
quotedAmount,
|
|
279
|
+
message
|
|
280
|
+
});
|
|
281
|
+
case "no_baseline":
|
|
282
|
+
return new _QuoteRejectedError({ reason, message });
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
var QUOTE_REJECTION_TRANSPORT_PREFIX = "QUOTE_REJECTED::";
|
|
287
|
+
var QUOTE_REJECTION_REASONS = /* @__PURE__ */ new Set([
|
|
288
|
+
"below_floor",
|
|
289
|
+
"non_positive",
|
|
290
|
+
"non_safe_integer",
|
|
291
|
+
"no_baseline"
|
|
292
|
+
]);
|
|
194
293
|
var BoltzRefundError = class extends Error {
|
|
195
294
|
constructor(message, cause) {
|
|
196
295
|
super(message);
|
|
@@ -206,18 +305,10 @@ var import_sdk8 = require("@arkade-os/sdk");
|
|
|
206
305
|
var import_sdk = require("@arkade-os/sdk");
|
|
207
306
|
var import_base = require("@scure/base");
|
|
208
307
|
var isSubmarineFailedStatus = (status) => {
|
|
209
|
-
return [
|
|
210
|
-
"invoice.failedToPay",
|
|
211
|
-
"transaction.lockupFailed",
|
|
212
|
-
"swap.expired"
|
|
213
|
-
].includes(status);
|
|
308
|
+
return ["invoice.failedToPay", "transaction.lockupFailed", "swap.expired"].includes(status);
|
|
214
309
|
};
|
|
215
310
|
var isSubmarineFinalStatus = (status) => {
|
|
216
|
-
return [
|
|
217
|
-
"invoice.failedToPay",
|
|
218
|
-
"transaction.claimed",
|
|
219
|
-
"swap.expired"
|
|
220
|
-
].includes(status);
|
|
311
|
+
return ["invoice.failedToPay", "transaction.claimed", "swap.expired"].includes(status);
|
|
221
312
|
};
|
|
222
313
|
var isSubmarinePendingStatus = (status) => {
|
|
223
314
|
return [
|
|
@@ -231,11 +322,7 @@ var isSubmarinePendingStatus = (status) => {
|
|
|
231
322
|
].includes(status);
|
|
232
323
|
};
|
|
233
324
|
var isSubmarineRefundableStatus = (status) => {
|
|
234
|
-
return [
|
|
235
|
-
"invoice.failedToPay",
|
|
236
|
-
"transaction.lockupFailed",
|
|
237
|
-
"swap.expired"
|
|
238
|
-
].includes(status);
|
|
325
|
+
return ["invoice.failedToPay", "transaction.lockupFailed", "swap.expired"].includes(status);
|
|
239
326
|
};
|
|
240
327
|
var isSubmarineSuccessStatus = (status) => {
|
|
241
328
|
return status === "transaction.claimed";
|
|
@@ -259,11 +346,7 @@ var isReverseFinalStatus = (status) => {
|
|
|
259
346
|
].includes(status);
|
|
260
347
|
};
|
|
261
348
|
var isReversePendingStatus = (status) => {
|
|
262
|
-
return [
|
|
263
|
-
"swap.created",
|
|
264
|
-
"transaction.mempool",
|
|
265
|
-
"transaction.confirmed"
|
|
266
|
-
].includes(status);
|
|
349
|
+
return ["swap.created", "transaction.mempool", "transaction.confirmed"].includes(status);
|
|
267
350
|
};
|
|
268
351
|
var isReverseClaimableStatus = (status) => {
|
|
269
352
|
return ["transaction.mempool", "transaction.confirmed"].includes(status);
|
|
@@ -275,10 +358,7 @@ var isChainFailedStatus = (status) => {
|
|
|
275
358
|
return ["transaction.failed", "swap.expired"].includes(status);
|
|
276
359
|
};
|
|
277
360
|
var isChainClaimableStatus = (status) => {
|
|
278
|
-
return [
|
|
279
|
-
"transaction.server.mempool",
|
|
280
|
-
"transaction.server.confirmed"
|
|
281
|
-
].includes(status);
|
|
361
|
+
return ["transaction.server.mempool", "transaction.server.confirmed"].includes(status);
|
|
282
362
|
};
|
|
283
363
|
var isChainFinalStatus = (status) => {
|
|
284
364
|
return [
|
|
@@ -417,8 +497,7 @@ var BASE_URLS = {
|
|
|
417
497
|
var isSwapNotFoundBody = (error) => {
|
|
418
498
|
const needle = "could not find swap";
|
|
419
499
|
const fromJson = error.errorData?.error;
|
|
420
|
-
if (typeof fromJson === "string" && fromJson.toLowerCase().includes(needle))
|
|
421
|
-
return true;
|
|
500
|
+
if (typeof fromJson === "string" && fromJson.toLowerCase().includes(needle)) return true;
|
|
422
501
|
return error.message.toLowerCase().includes(needle);
|
|
423
502
|
};
|
|
424
503
|
var BoltzSwapProvider = class {
|
|
@@ -432,10 +511,7 @@ var BoltzSwapProvider = class {
|
|
|
432
511
|
this.network = config.network;
|
|
433
512
|
this.referralId = config.referralId ?? "arkade-ts-sdk";
|
|
434
513
|
const apiUrl = config.apiUrl || BASE_URLS[config.network];
|
|
435
|
-
if (!apiUrl)
|
|
436
|
-
throw new Error(
|
|
437
|
-
`API URL is required for network: ${config.network}`
|
|
438
|
-
);
|
|
514
|
+
if (!apiUrl) throw new Error(`API URL is required for network: ${config.network}`);
|
|
439
515
|
this.apiUrl = apiUrl;
|
|
440
516
|
this.wsUrl = this.apiUrl.replace(/^http(s)?:\/\//, "ws$1://").replace("9069", "9004") + "/v2/ws";
|
|
441
517
|
}
|
|
@@ -454,10 +530,7 @@ var BoltzSwapProvider = class {
|
|
|
454
530
|
/** Returns current Lightning swap fees (submarine + reverse) from Boltz. */
|
|
455
531
|
async getFees() {
|
|
456
532
|
const [submarine, reverse] = await Promise.all([
|
|
457
|
-
this.request(
|
|
458
|
-
"/v2/swap/submarine",
|
|
459
|
-
"GET"
|
|
460
|
-
),
|
|
533
|
+
this.request("/v2/swap/submarine", "GET"),
|
|
461
534
|
this.request("/v2/swap/reverse", "GET")
|
|
462
535
|
]);
|
|
463
536
|
if (!isGetSubmarinePairsResponse(submarine))
|
|
@@ -477,10 +550,7 @@ var BoltzSwapProvider = class {
|
|
|
477
550
|
}
|
|
478
551
|
/** Returns current Lightning swap min/max limits from Boltz. */
|
|
479
552
|
async getLimits() {
|
|
480
|
-
const response = await this.request(
|
|
481
|
-
"/v2/swap/submarine",
|
|
482
|
-
"GET"
|
|
483
|
-
);
|
|
553
|
+
const response = await this.request("/v2/swap/submarine", "GET");
|
|
484
554
|
if (!isGetSubmarinePairsResponse(response))
|
|
485
555
|
throw new SchemaError({ message: "error fetching limits" });
|
|
486
556
|
return {
|
|
@@ -490,10 +560,7 @@ var BoltzSwapProvider = class {
|
|
|
490
560
|
}
|
|
491
561
|
/** Returns the current BTC chain tip height from Boltz. */
|
|
492
562
|
async getChainHeight() {
|
|
493
|
-
const response = await this.request(
|
|
494
|
-
"/v2/chain/heights",
|
|
495
|
-
"GET"
|
|
496
|
-
);
|
|
563
|
+
const response = await this.request("/v2/chain/heights", "GET");
|
|
497
564
|
if (typeof response?.BTC !== "number")
|
|
498
565
|
throw new SchemaError({
|
|
499
566
|
message: "error fetching chain heights"
|
|
@@ -523,10 +590,7 @@ var BoltzSwapProvider = class {
|
|
|
523
590
|
async getSwapStatus(id) {
|
|
524
591
|
let response;
|
|
525
592
|
try {
|
|
526
|
-
response = await this.request(
|
|
527
|
-
`/v2/swap/${id}`,
|
|
528
|
-
"GET"
|
|
529
|
-
);
|
|
593
|
+
response = await this.request(`/v2/swap/${id}`, "GET");
|
|
530
594
|
} catch (error) {
|
|
531
595
|
if (error instanceof NetworkError && error.statusCode === 404 && isSwapNotFoundBody(error)) {
|
|
532
596
|
throw new SwapNotFoundError(id, error.errorData);
|
|
@@ -622,12 +686,10 @@ var BoltzSwapProvider = class {
|
|
|
622
686
|
throw new SwapError({ message: "Invalid 'to' chain" });
|
|
623
687
|
if (["BTC", "ARK"].indexOf(from) === -1)
|
|
624
688
|
throw new SwapError({ message: "Invalid 'from' chain" });
|
|
625
|
-
if (to === from)
|
|
626
|
-
throw new SwapError({ message: "Invalid swap direction" });
|
|
689
|
+
if (to === from) throw new SwapError({ message: "Invalid swap direction" });
|
|
627
690
|
if (!preimageHash || preimageHash.length != 64)
|
|
628
691
|
throw new SwapError({ message: "Invalid preimageHash" });
|
|
629
|
-
if (feeSatsPerByte <= 0)
|
|
630
|
-
throw new SwapError({ message: "Invalid feeSatsPerByte" });
|
|
692
|
+
if (feeSatsPerByte <= 0) throw new SwapError({ message: "Invalid feeSatsPerByte" });
|
|
631
693
|
if (serverLockAmount !== void 0 && userLockAmount !== void 0 || serverLockAmount === void 0 && userLockAmount === void 0)
|
|
632
694
|
throw new SwapError({
|
|
633
695
|
message: "Either serverLockAmount or userLockAmount must be provided"
|
|
@@ -682,12 +744,8 @@ var BoltzSwapProvider = class {
|
|
|
682
744
|
message: "Error refunding submarine swap"
|
|
683
745
|
});
|
|
684
746
|
return {
|
|
685
|
-
transaction: import_sdk.Transaction.fromPSBT(
|
|
686
|
-
|
|
687
|
-
),
|
|
688
|
-
checkpoint: import_sdk.Transaction.fromPSBT(
|
|
689
|
-
import_base.base64.decode(response.checkpoint)
|
|
690
|
-
)
|
|
747
|
+
transaction: import_sdk.Transaction.fromPSBT(import_base.base64.decode(response.transaction)),
|
|
748
|
+
checkpoint: import_sdk.Transaction.fromPSBT(import_base.base64.decode(response.checkpoint))
|
|
691
749
|
};
|
|
692
750
|
}
|
|
693
751
|
/** Requests Boltz co-signature for a chain swap refund. Returns signed transaction + checkpoint. */
|
|
@@ -706,53 +764,53 @@ var BoltzSwapProvider = class {
|
|
|
706
764
|
message: "Error refunding chain swap"
|
|
707
765
|
});
|
|
708
766
|
return {
|
|
709
|
-
transaction: import_sdk.Transaction.fromPSBT(
|
|
710
|
-
|
|
711
|
-
),
|
|
712
|
-
checkpoint: import_sdk.Transaction.fromPSBT(
|
|
713
|
-
import_base.base64.decode(response.checkpoint)
|
|
714
|
-
)
|
|
767
|
+
transaction: import_sdk.Transaction.fromPSBT(import_base.base64.decode(response.transaction)),
|
|
768
|
+
checkpoint: import_sdk.Transaction.fromPSBT(import_base.base64.decode(response.checkpoint))
|
|
715
769
|
};
|
|
716
770
|
}
|
|
717
|
-
/**
|
|
771
|
+
/**
|
|
772
|
+
* Monitors swap status updates and forwards them to the update callback.
|
|
773
|
+
* Prefers a WebSocket subscription; on connection error or premature close
|
|
774
|
+
* it falls back to REST polling so callers don't fail when the WS endpoint
|
|
775
|
+
* is flaky (observed in CI). Resolves when the swap reaches a terminal
|
|
776
|
+
* status.
|
|
777
|
+
*/
|
|
718
778
|
async monitorSwap(swapId, update) {
|
|
719
779
|
return new Promise((resolve, reject) => {
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
);
|
|
780
|
+
let settled = false;
|
|
781
|
+
let lastStatus = null;
|
|
782
|
+
let pollTimer = null;
|
|
783
|
+
let webSocket = null;
|
|
784
|
+
let connectionTimeout = null;
|
|
785
|
+
const cleanup = () => {
|
|
786
|
+
if (connectionTimeout) {
|
|
787
|
+
clearTimeout(connectionTimeout);
|
|
788
|
+
connectionTimeout = null;
|
|
789
|
+
}
|
|
790
|
+
if (pollTimer) {
|
|
791
|
+
clearInterval(pollTimer);
|
|
792
|
+
pollTimer = null;
|
|
793
|
+
}
|
|
794
|
+
if (webSocket) {
|
|
795
|
+
try {
|
|
796
|
+
webSocket.close();
|
|
797
|
+
} catch {
|
|
798
|
+
}
|
|
799
|
+
webSocket = null;
|
|
800
|
+
}
|
|
742
801
|
};
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
802
|
+
const finish = (err) => {
|
|
803
|
+
if (settled) return;
|
|
804
|
+
settled = true;
|
|
805
|
+
cleanup();
|
|
806
|
+
if (err) reject(err);
|
|
807
|
+
else resolve();
|
|
746
808
|
};
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
if (
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
reject(new SwapError({ message: msg.args[0].error }));
|
|
753
|
-
}
|
|
754
|
-
const status = msg.args[0].status;
|
|
755
|
-
const negotiable = status === "transaction.lockupFailed" && msg.args[0].failureDetails?.actual !== void 0 && msg.args[0].failureDetails?.expected !== void 0;
|
|
809
|
+
const handleStatus = (status, data) => {
|
|
810
|
+
if (settled) return;
|
|
811
|
+
if (status === lastStatus) return;
|
|
812
|
+
lastStatus = status;
|
|
813
|
+
const negotiable = status === "transaction.lockupFailed" && data?.failureDetails?.actual !== void 0 && data?.failureDetails?.expected !== void 0;
|
|
756
814
|
switch (status) {
|
|
757
815
|
case "invoice.settled":
|
|
758
816
|
case "transaction.claimed":
|
|
@@ -761,13 +819,13 @@ var BoltzSwapProvider = class {
|
|
|
761
819
|
case "invoice.failedToPay":
|
|
762
820
|
case "transaction.failed":
|
|
763
821
|
case "swap.expired":
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
822
|
+
update(status, data);
|
|
823
|
+
finish();
|
|
824
|
+
return;
|
|
767
825
|
case "transaction.lockupFailed":
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
826
|
+
update(status, data);
|
|
827
|
+
if (!negotiable) finish();
|
|
828
|
+
return;
|
|
771
829
|
case "invoice.paid":
|
|
772
830
|
case "invoice.pending":
|
|
773
831
|
case "invoice.set":
|
|
@@ -777,9 +835,77 @@ var BoltzSwapProvider = class {
|
|
|
777
835
|
case "transaction.claim.pending":
|
|
778
836
|
case "transaction.server.mempool":
|
|
779
837
|
case "transaction.server.confirmed":
|
|
780
|
-
update(status,
|
|
838
|
+
update(status, data);
|
|
839
|
+
return;
|
|
781
840
|
}
|
|
782
841
|
};
|
|
842
|
+
const startPolling = () => {
|
|
843
|
+
if (settled || pollTimer) return;
|
|
844
|
+
const poll = async () => {
|
|
845
|
+
if (settled) return;
|
|
846
|
+
try {
|
|
847
|
+
const result = await this.getSwapStatus(swapId);
|
|
848
|
+
handleStatus(result.status, { ...result, id: swapId });
|
|
849
|
+
} catch {
|
|
850
|
+
}
|
|
851
|
+
};
|
|
852
|
+
pollTimer = setInterval(poll, 1e3);
|
|
853
|
+
poll();
|
|
854
|
+
};
|
|
855
|
+
try {
|
|
856
|
+
webSocket = new globalThis.WebSocket(this.wsUrl);
|
|
857
|
+
connectionTimeout = setTimeout(() => {
|
|
858
|
+
try {
|
|
859
|
+
webSocket?.close();
|
|
860
|
+
} catch {
|
|
861
|
+
}
|
|
862
|
+
webSocket = null;
|
|
863
|
+
startPolling();
|
|
864
|
+
}, 5e3);
|
|
865
|
+
webSocket.onerror = () => {
|
|
866
|
+
if (connectionTimeout) {
|
|
867
|
+
clearTimeout(connectionTimeout);
|
|
868
|
+
connectionTimeout = null;
|
|
869
|
+
}
|
|
870
|
+
webSocket = null;
|
|
871
|
+
startPolling();
|
|
872
|
+
};
|
|
873
|
+
webSocket.onopen = () => {
|
|
874
|
+
if (connectionTimeout) {
|
|
875
|
+
clearTimeout(connectionTimeout);
|
|
876
|
+
connectionTimeout = null;
|
|
877
|
+
}
|
|
878
|
+
webSocket?.send(
|
|
879
|
+
JSON.stringify({
|
|
880
|
+
op: "subscribe",
|
|
881
|
+
channel: "swap.update",
|
|
882
|
+
args: [swapId]
|
|
883
|
+
})
|
|
884
|
+
);
|
|
885
|
+
};
|
|
886
|
+
webSocket.onclose = () => {
|
|
887
|
+
if (connectionTimeout) {
|
|
888
|
+
clearTimeout(connectionTimeout);
|
|
889
|
+
connectionTimeout = null;
|
|
890
|
+
}
|
|
891
|
+
if (!settled && !pollTimer) startPolling();
|
|
892
|
+
};
|
|
893
|
+
webSocket.onmessage = (rawMsg) => {
|
|
894
|
+
try {
|
|
895
|
+
const msg = JSON.parse(rawMsg.data);
|
|
896
|
+
if (msg.event !== "update" || msg.args?.[0]?.id !== swapId) return;
|
|
897
|
+
if (msg.args[0].error) {
|
|
898
|
+
finish(new SwapError({ message: msg.args[0].error }));
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
handleStatus(msg.args[0].status, msg.args[0]);
|
|
902
|
+
} catch {
|
|
903
|
+
}
|
|
904
|
+
};
|
|
905
|
+
} catch {
|
|
906
|
+
webSocket = null;
|
|
907
|
+
startPolling();
|
|
908
|
+
}
|
|
783
909
|
});
|
|
784
910
|
}
|
|
785
911
|
/** Returns current chain swap fees for a given pair (e.g. ARK→BTC). */
|
|
@@ -787,10 +913,7 @@ var BoltzSwapProvider = class {
|
|
|
787
913
|
if (from === to) {
|
|
788
914
|
throw new SwapError({ message: "Invalid chain pair" });
|
|
789
915
|
}
|
|
790
|
-
const response = await this.request(
|
|
791
|
-
"/v2/swap/chain",
|
|
792
|
-
"GET"
|
|
793
|
-
);
|
|
916
|
+
const response = await this.request("/v2/swap/chain", "GET");
|
|
794
917
|
if (!isGetChainPairsResponse(response))
|
|
795
918
|
throw new SchemaError({ message: "error fetching fees" });
|
|
796
919
|
if (!response[from]?.[to]) {
|
|
@@ -805,10 +928,7 @@ var BoltzSwapProvider = class {
|
|
|
805
928
|
if (from === to) {
|
|
806
929
|
throw new SwapError({ message: "Invalid chain pair" });
|
|
807
930
|
}
|
|
808
|
-
const response = await this.request(
|
|
809
|
-
"/v2/swap/chain",
|
|
810
|
-
"GET"
|
|
811
|
-
);
|
|
931
|
+
const response = await this.request("/v2/swap/chain", "GET");
|
|
812
932
|
if (!isGetChainPairsResponse(response))
|
|
813
933
|
throw new SchemaError({ message: "error fetching limits" });
|
|
814
934
|
if (!response[from]?.[to]) {
|
|
@@ -937,9 +1057,7 @@ var BoltzSwapProvider = class {
|
|
|
937
1057
|
return await response.json();
|
|
938
1058
|
} catch (error) {
|
|
939
1059
|
if (error instanceof NetworkError) throw error;
|
|
940
|
-
throw new NetworkError(
|
|
941
|
-
`Request to ${url} failed: ${error.message}`
|
|
942
|
-
);
|
|
1060
|
+
throw new NetworkError(`Request to ${url} failed: ${error.message}`);
|
|
943
1061
|
}
|
|
944
1062
|
}
|
|
945
1063
|
};
|
|
@@ -961,8 +1079,7 @@ var findKeyIndex = (keys, target) => keys.findIndex((k) => (0, import_utils.equa
|
|
|
961
1079
|
var assertPublicKeys = (keys) => {
|
|
962
1080
|
const seen = /* @__PURE__ */ new Set();
|
|
963
1081
|
for (const key of keys) {
|
|
964
|
-
if (key.length !== 33)
|
|
965
|
-
throw new Error(`public key must be 33 bytes, got ${key.length}`);
|
|
1082
|
+
if (key.length !== 33) throw new Error(`public key must be 33 bytes, got ${key.length}`);
|
|
966
1083
|
const enc = import_base2.hex.encode(key);
|
|
967
1084
|
if (seen.has(enc)) throw new Error(`duplicate public key ${enc}`);
|
|
968
1085
|
seen.add(enc);
|
|
@@ -970,9 +1087,7 @@ var assertPublicKeys = (keys) => {
|
|
|
970
1087
|
};
|
|
971
1088
|
var aggregateKeys = (publicKeys, tweak) => {
|
|
972
1089
|
assertPublicKeys([...publicKeys]);
|
|
973
|
-
return (0, import_musig2.keyAggExport)(
|
|
974
|
-
(0, import_musig2.keyAggregate)([...publicKeys], tweak ? [tweak] : [], tweak ? [true] : [])
|
|
975
|
-
);
|
|
1090
|
+
return (0, import_musig2.keyAggExport)((0, import_musig2.keyAggregate)([...publicKeys], tweak ? [tweak] : [], tweak ? [true] : []));
|
|
976
1091
|
};
|
|
977
1092
|
var MusigKeyAgg = class _MusigKeyAgg {
|
|
978
1093
|
constructor(privateKey, myPublicKey, publicKeys, myIndex, aggPubkey, internalKey, _tweak) {
|
|
@@ -1019,18 +1134,12 @@ var MusigWithMessage = class {
|
|
|
1019
1134
|
this.msg = msg;
|
|
1020
1135
|
}
|
|
1021
1136
|
generateNonce() {
|
|
1022
|
-
const nonce = (0, import_musig2.nonceGen)(
|
|
1023
|
-
this.myPublicKey,
|
|
1024
|
-
this.privateKey,
|
|
1025
|
-
this.aggPubkey,
|
|
1026
|
-
this.msg
|
|
1027
|
-
);
|
|
1137
|
+
const nonce = (0, import_musig2.nonceGen)(this.myPublicKey, this.privateKey, this.aggPubkey, this.msg);
|
|
1028
1138
|
return new MusigWithNonce(
|
|
1029
1139
|
this.privateKey,
|
|
1030
1140
|
this.myPublicKey,
|
|
1031
1141
|
this.publicKeys,
|
|
1032
1142
|
this.myIndex,
|
|
1033
|
-
this.aggPubkey,
|
|
1034
1143
|
this.tweak,
|
|
1035
1144
|
this.msg,
|
|
1036
1145
|
nonce
|
|
@@ -1038,12 +1147,11 @@ var MusigWithMessage = class {
|
|
|
1038
1147
|
}
|
|
1039
1148
|
};
|
|
1040
1149
|
var MusigWithNonce = class {
|
|
1041
|
-
constructor(privateKey, myPublicKey, publicKeys, myIndex,
|
|
1150
|
+
constructor(privateKey, myPublicKey, publicKeys, myIndex, tweak, msg, nonce) {
|
|
1042
1151
|
this.privateKey = privateKey;
|
|
1043
1152
|
this.myPublicKey = myPublicKey;
|
|
1044
1153
|
this.publicKeys = publicKeys;
|
|
1045
1154
|
this.myIndex = myIndex;
|
|
1046
|
-
this.aggPubkey = aggPubkey;
|
|
1047
1155
|
this.tweak = tweak;
|
|
1048
1156
|
this.msg = msg;
|
|
1049
1157
|
this.nonce = nonce;
|
|
@@ -1075,10 +1183,8 @@ var MusigWithNonce = class {
|
|
|
1075
1183
|
const aggregatedNonce = (0, import_musig2.nonceAggregate)([...ordered]);
|
|
1076
1184
|
return new MusigNoncesAggregated(
|
|
1077
1185
|
this.privateKey,
|
|
1078
|
-
this.myPublicKey,
|
|
1079
1186
|
this.publicKeys,
|
|
1080
1187
|
this.myIndex,
|
|
1081
|
-
this.aggPubkey,
|
|
1082
1188
|
this.tweak,
|
|
1083
1189
|
this.msg,
|
|
1084
1190
|
this.nonce,
|
|
@@ -1088,12 +1194,10 @@ var MusigWithNonce = class {
|
|
|
1088
1194
|
}
|
|
1089
1195
|
};
|
|
1090
1196
|
var MusigNoncesAggregated = class {
|
|
1091
|
-
constructor(privateKey,
|
|
1197
|
+
constructor(privateKey, publicKeys, myIndex, tweak, msg, nonce, pubNonces, aggregatedNonce) {
|
|
1092
1198
|
this.privateKey = privateKey;
|
|
1093
|
-
this.myPublicKey = myPublicKey;
|
|
1094
1199
|
this.publicKeys = publicKeys;
|
|
1095
1200
|
this.myIndex = myIndex;
|
|
1096
|
-
this.aggPubkey = aggPubkey;
|
|
1097
1201
|
this.tweak = tweak;
|
|
1098
1202
|
this.msg = msg;
|
|
1099
1203
|
this.nonce = nonce;
|
|
@@ -1139,11 +1243,7 @@ var MusigSession = class {
|
|
|
1139
1243
|
const index = typeof publicKeyOrIndex === "number" ? publicKeyOrIndex : findKeyIndex(this.publicKeys, publicKeyOrIndex);
|
|
1140
1244
|
if (index < 0 || index >= this.publicKeys.length)
|
|
1141
1245
|
throw new Error("public key not found or index out of range");
|
|
1142
|
-
if (!this.session.partialSigVerify(
|
|
1143
|
-
signature,
|
|
1144
|
-
[...this.pubNonces],
|
|
1145
|
-
index
|
|
1146
|
-
)) {
|
|
1246
|
+
if (!this.session.partialSigVerify(signature, [...this.pubNonces], index)) {
|
|
1147
1247
|
throw new Error("invalid partial signature");
|
|
1148
1248
|
}
|
|
1149
1249
|
this.partialSignatures[index] = signature;
|
|
@@ -1152,12 +1252,7 @@ var MusigSession = class {
|
|
|
1152
1252
|
signPartial() {
|
|
1153
1253
|
const sig = this.session.sign(this.nonce.secret, this.privateKey, true);
|
|
1154
1254
|
this.partialSignatures[this.myIndex] = sig;
|
|
1155
|
-
return new MusigSigned(
|
|
1156
|
-
this.session,
|
|
1157
|
-
[...this.partialSignatures],
|
|
1158
|
-
sig,
|
|
1159
|
-
this.nonce.public
|
|
1160
|
-
);
|
|
1255
|
+
return new MusigSigned(this.session, [...this.partialSignatures], sig, this.nonce.public);
|
|
1161
1256
|
}
|
|
1162
1257
|
};
|
|
1163
1258
|
var MusigSigned = class {
|
|
@@ -1171,14 +1266,11 @@ var MusigSigned = class {
|
|
|
1171
1266
|
if (this.partialSignatures.some((s) => s === null)) {
|
|
1172
1267
|
throw new Error("not all partial signatures are set");
|
|
1173
1268
|
}
|
|
1174
|
-
return this.session.partialSigAgg(
|
|
1175
|
-
this.partialSignatures
|
|
1176
|
-
);
|
|
1269
|
+
return this.session.partialSigAgg(this.partialSignatures);
|
|
1177
1270
|
}
|
|
1178
1271
|
};
|
|
1179
1272
|
var create = (privateKey, publicKeys) => {
|
|
1180
|
-
if (publicKeys.length < 2)
|
|
1181
|
-
throw new Error("need at least 2 keys to aggregate");
|
|
1273
|
+
if (publicKeys.length < 2) throw new Error("need at least 2 keys to aggregate");
|
|
1182
1274
|
const keys = [...publicKeys];
|
|
1183
1275
|
assertPublicKeys(keys);
|
|
1184
1276
|
Object.freeze(keys);
|
|
@@ -1186,14 +1278,7 @@ var create = (privateKey, publicKeys) => {
|
|
|
1186
1278
|
const myIndex = findKeyIndex(keys, myPublicKey);
|
|
1187
1279
|
if (myIndex === -1) throw new Error("our key is not in publicKeys");
|
|
1188
1280
|
const aggPubkey = aggregateKeys(keys);
|
|
1189
|
-
return new MusigKeyAgg(
|
|
1190
|
-
privateKey,
|
|
1191
|
-
myPublicKey,
|
|
1192
|
-
keys,
|
|
1193
|
-
myIndex,
|
|
1194
|
-
aggPubkey,
|
|
1195
|
-
aggPubkey
|
|
1196
|
-
);
|
|
1281
|
+
return new MusigKeyAgg(privateKey, myPublicKey, keys, myIndex, aggPubkey, aggPubkey);
|
|
1197
1282
|
};
|
|
1198
1283
|
|
|
1199
1284
|
// src/utils/boltz-swap-tx.ts
|
|
@@ -1269,9 +1354,7 @@ var taprootHashTree = (tree) => {
|
|
|
1269
1354
|
};
|
|
1270
1355
|
var tweakMusig = (musig, tree) => {
|
|
1271
1356
|
const tweak = taprootHashTree(tree).hash;
|
|
1272
|
-
return musig.xonlyTweakAdd(
|
|
1273
|
-
import_secp256k12.schnorr.utils.taggedHash("TapTweak", musig.aggPubkey, tweak)
|
|
1274
|
-
);
|
|
1357
|
+
return musig.xonlyTweakAdd(import_secp256k12.schnorr.utils.taggedHash("TapTweak", musig.aggPubkey, tweak));
|
|
1275
1358
|
};
|
|
1276
1359
|
var toXOnly = (pubKey) => {
|
|
1277
1360
|
if (pubKey.length === 32) return pubKey;
|
|
@@ -1283,9 +1366,7 @@ var toXOnly = (pubKey) => {
|
|
|
1283
1366
|
}
|
|
1284
1367
|
return pubKey.subarray(1, 33);
|
|
1285
1368
|
}
|
|
1286
|
-
throw new Error(
|
|
1287
|
-
`Invalid public key length: expected 32 or 33 bytes, got ${pubKey.length}`
|
|
1288
|
-
);
|
|
1369
|
+
throw new Error(`Invalid public key length: expected 32 or 33 bytes, got ${pubKey.length}`);
|
|
1289
1370
|
};
|
|
1290
1371
|
var p2trScript = (publicKey) => import_btc_signer.Script.encode(["OP_1", toXOnly(publicKey)]);
|
|
1291
1372
|
var detectSwapOutput = (tweakedKey, transaction) => {
|
|
@@ -1300,8 +1381,7 @@ var detectSwapOutput = (tweakedKey, transaction) => {
|
|
|
1300
1381
|
};
|
|
1301
1382
|
var DUMMY_TAPROOT_SIGNATURE = new Uint8Array(64);
|
|
1302
1383
|
var constructClaimTransaction = (utxo, destinationScript, fee) => {
|
|
1303
|
-
if (fee < BigInt(0) || fee >= utxo.amount)
|
|
1304
|
-
throw new Error("fee exceeds utxo amount");
|
|
1384
|
+
if (fee < BigInt(0) || fee >= utxo.amount) throw new Error("fee exceeds utxo amount");
|
|
1305
1385
|
const tx = new import_btc_signer.Transaction({ version: 2 });
|
|
1306
1386
|
tx.addOutput({
|
|
1307
1387
|
amount: utxo.amount - fee,
|
|
@@ -1320,9 +1400,7 @@ var constructClaimTransaction = (utxo, destinationScript, fee) => {
|
|
|
1320
1400
|
};
|
|
1321
1401
|
var targetFee = (satPerVbyte, constructTx) => {
|
|
1322
1402
|
const tx = constructTx(BigInt(1));
|
|
1323
|
-
return constructTx(
|
|
1324
|
-
BigInt(Math.ceil((tx.vsize + tx.inputsLength) * satPerVbyte))
|
|
1325
|
-
);
|
|
1403
|
+
return constructTx(BigInt(Math.ceil((tx.vsize + tx.inputsLength) * satPerVbyte)));
|
|
1326
1404
|
};
|
|
1327
1405
|
|
|
1328
1406
|
// src/utils/decoding.ts
|
|
@@ -1330,9 +1408,7 @@ var import_light_bolt11_decoder = __toESM(require("light-bolt11-decoder"), 1);
|
|
|
1330
1408
|
var import_sdk2 = require("@arkade-os/sdk");
|
|
1331
1409
|
var decodeInvoice = (invoice) => {
|
|
1332
1410
|
const decoded = import_light_bolt11_decoder.default.decode(invoice);
|
|
1333
|
-
const millisats = Number(
|
|
1334
|
-
decoded.sections.find((s) => s.name === "amount")?.value ?? "0"
|
|
1335
|
-
);
|
|
1411
|
+
const millisats = Number(decoded.sections.find((s) => s.name === "amount")?.value ?? "0");
|
|
1336
1412
|
return {
|
|
1337
1413
|
expiry: decoded.expiry ?? 3600,
|
|
1338
1414
|
amountSats: Math.floor(millisats / 1e3),
|
|
@@ -1406,10 +1482,7 @@ function extractTimeLockFromLeafOutput(scriptHex) {
|
|
|
1406
1482
|
const data = opcodes[hasCSV - 1];
|
|
1407
1483
|
if (data instanceof Uint8Array) {
|
|
1408
1484
|
const dataBytes = new Uint8Array(data).reverse();
|
|
1409
|
-
const {
|
|
1410
|
-
blocks,
|
|
1411
|
-
seconds
|
|
1412
|
-
} = import_bip68.default.decode(
|
|
1485
|
+
const { blocks, seconds } = import_bip68.default.decode(
|
|
1413
1486
|
parseInt(import_base5.hex.encode(dataBytes), 16)
|
|
1414
1487
|
);
|
|
1415
1488
|
return blocks ?? seconds ?? 0;
|
|
@@ -1445,6 +1518,13 @@ var SwapManager = class _SwapManager {
|
|
|
1445
1518
|
* enough that a real "swap unknown to this provider" surfaces quickly.
|
|
1446
1519
|
*/
|
|
1447
1520
|
static NOT_FOUND_THRESHOLD = 10;
|
|
1521
|
+
/**
|
|
1522
|
+
* Delay between re-attempts of a chain refund that left VTXOs deferred
|
|
1523
|
+
* (e.g. pre-CLTV recoverable VTXO, or Boltz 3-of-3 rejected before CLTV
|
|
1524
|
+
* has elapsed). Boltz won't send another status update once the swap
|
|
1525
|
+
* is `swap.expired`, so the manager owns the local retry cadence.
|
|
1526
|
+
*/
|
|
1527
|
+
static REFUND_RETRY_DELAY_MS = 6e4;
|
|
1448
1528
|
swapProvider;
|
|
1449
1529
|
config;
|
|
1450
1530
|
// Event listeners storage (supports multiple listeners per event)
|
|
@@ -1463,6 +1543,11 @@ var SwapManager = class _SwapManager {
|
|
|
1463
1543
|
reconnectTimer = null;
|
|
1464
1544
|
initialPollTimer = null;
|
|
1465
1545
|
pollRetryTimers = /* @__PURE__ */ new Map();
|
|
1546
|
+
// Per-swap retry timers for chain refunds that left work undone
|
|
1547
|
+
// (refundArk returned `skipped > 0`). The swap is held in
|
|
1548
|
+
// `monitoredSwaps` past its terminal Boltz status until the local
|
|
1549
|
+
// refund completes or the manager stops.
|
|
1550
|
+
refundRetryTimers = /* @__PURE__ */ new Map();
|
|
1466
1551
|
// Per-swap counter of consecutive `SwapNotFoundError` responses from
|
|
1467
1552
|
// `getSwapStatus`. Reset on any successful poll. Once a swap reaches
|
|
1468
1553
|
// `NOT_FOUND_THRESHOLD` consecutive 404s the safety net trips and the
|
|
@@ -1516,9 +1601,7 @@ var SwapManager = class _SwapManager {
|
|
|
1516
1601
|
this.wsConnectedListeners.add(config.events.onWebSocketConnected);
|
|
1517
1602
|
}
|
|
1518
1603
|
if (config.events?.onWebSocketDisconnected) {
|
|
1519
|
-
this.wsDisconnectedListeners.add(
|
|
1520
|
-
config.events.onWebSocketDisconnected
|
|
1521
|
-
);
|
|
1604
|
+
this.wsDisconnectedListeners.add(config.events.onWebSocketDisconnected);
|
|
1522
1605
|
}
|
|
1523
1606
|
this.currentReconnectDelay = this.config.reconnectDelayMs;
|
|
1524
1607
|
this.currentPollRetryDelay = this.config.pollRetryDelayMs;
|
|
@@ -1661,6 +1744,10 @@ var SwapManager = class _SwapManager {
|
|
|
1661
1744
|
clearTimeout(timer);
|
|
1662
1745
|
}
|
|
1663
1746
|
this.pollRetryTimers.clear();
|
|
1747
|
+
for (const timer of this.refundRetryTimers.values()) {
|
|
1748
|
+
clearTimeout(timer);
|
|
1749
|
+
}
|
|
1750
|
+
this.refundRetryTimers.clear();
|
|
1664
1751
|
this.notFoundCounts.clear();
|
|
1665
1752
|
}
|
|
1666
1753
|
/**
|
|
@@ -1669,9 +1756,7 @@ var SwapManager = class _SwapManager {
|
|
|
1669
1756
|
*/
|
|
1670
1757
|
setPollInterval(ms) {
|
|
1671
1758
|
if (ms <= 0) {
|
|
1672
|
-
throw new RangeError(
|
|
1673
|
-
`setPollInterval: ms must be a positive number, got ${ms}`
|
|
1674
|
-
);
|
|
1759
|
+
throw new RangeError(`setPollInterval: ms must be a positive number, got ${ms}`);
|
|
1675
1760
|
}
|
|
1676
1761
|
const cappedInterval = Math.min(ms, this.config.maxPollIntervalMs);
|
|
1677
1762
|
if (cappedInterval !== ms) {
|
|
@@ -1680,10 +1765,7 @@ var SwapManager = class _SwapManager {
|
|
|
1680
1765
|
);
|
|
1681
1766
|
}
|
|
1682
1767
|
this.config.pollInterval = cappedInterval;
|
|
1683
|
-
this.currentPollRetryDelay = Math.min(
|
|
1684
|
-
cappedInterval,
|
|
1685
|
-
this.config.pollRetryDelayMs
|
|
1686
|
-
);
|
|
1768
|
+
this.currentPollRetryDelay = Math.min(cappedInterval, this.config.pollRetryDelayMs);
|
|
1687
1769
|
if (this.isRunning) {
|
|
1688
1770
|
if (this.usePollingFallback) {
|
|
1689
1771
|
this.startPollingFallback();
|
|
@@ -1722,6 +1804,11 @@ var SwapManager = class _SwapManager {
|
|
|
1722
1804
|
clearTimeout(retryTimer);
|
|
1723
1805
|
this.pollRetryTimers.delete(swapId);
|
|
1724
1806
|
}
|
|
1807
|
+
const refundRetryTimer = this.refundRetryTimers.get(swapId);
|
|
1808
|
+
if (refundRetryTimer) {
|
|
1809
|
+
clearTimeout(refundRetryTimer);
|
|
1810
|
+
this.refundRetryTimers.delete(swapId);
|
|
1811
|
+
}
|
|
1725
1812
|
this.notFoundCounts.delete(swapId);
|
|
1726
1813
|
logger.log(`Removed swap ${swapId} from monitoring`);
|
|
1727
1814
|
}
|
|
@@ -1768,9 +1855,7 @@ var SwapManager = class _SwapManager {
|
|
|
1768
1855
|
}
|
|
1769
1856
|
if (this.isFinalStatus(swap)) {
|
|
1770
1857
|
if (isPendingReverseSwap(swap)) {
|
|
1771
|
-
const response = await this.swapProvider.getReverseSwapTxId(
|
|
1772
|
-
swap.id
|
|
1773
|
-
);
|
|
1858
|
+
const response = await this.swapProvider.getReverseSwapTxId(swap.id);
|
|
1774
1859
|
return { txid: response.id };
|
|
1775
1860
|
}
|
|
1776
1861
|
if (isPendingSubmarineSwap(swap)) {
|
|
@@ -1787,31 +1872,19 @@ var SwapManager = class _SwapManager {
|
|
|
1787
1872
|
if (updatedSwap.status === "invoice.settled") {
|
|
1788
1873
|
this.swapProvider.getReverseSwapTxId(updatedSwap.id).then((response) => resolve({ txid: response.id })).catch((error) => reject(error));
|
|
1789
1874
|
} else {
|
|
1790
|
-
reject(
|
|
1791
|
-
new Error(
|
|
1792
|
-
`Swap failed with status: ${updatedSwap.status}`
|
|
1793
|
-
)
|
|
1794
|
-
);
|
|
1875
|
+
reject(new Error(`Swap failed with status: ${updatedSwap.status}`));
|
|
1795
1876
|
}
|
|
1796
1877
|
} else if (isPendingSubmarineSwap(updatedSwap)) {
|
|
1797
1878
|
if (updatedSwap.status === "transaction.claimed") {
|
|
1798
1879
|
resolve({ txid: updatedSwap.id });
|
|
1799
1880
|
} else {
|
|
1800
|
-
reject(
|
|
1801
|
-
new Error(
|
|
1802
|
-
`Swap failed with status: ${updatedSwap.status}`
|
|
1803
|
-
)
|
|
1804
|
-
);
|
|
1881
|
+
reject(new Error(`Swap failed with status: ${updatedSwap.status}`));
|
|
1805
1882
|
}
|
|
1806
1883
|
} else if (isPendingChainSwap(updatedSwap)) {
|
|
1807
1884
|
if (updatedSwap.status === "transaction.claimed") {
|
|
1808
1885
|
resolve({ txid: updatedSwap.id });
|
|
1809
1886
|
} else {
|
|
1810
|
-
reject(
|
|
1811
|
-
new Error(
|
|
1812
|
-
`Swap failed with status: ${updatedSwap.status}`
|
|
1813
|
-
)
|
|
1814
|
-
);
|
|
1887
|
+
reject(new Error(`Swap failed with status: ${updatedSwap.status}`));
|
|
1815
1888
|
}
|
|
1816
1889
|
}
|
|
1817
1890
|
};
|
|
@@ -1854,16 +1927,12 @@ var SwapManager = class _SwapManager {
|
|
|
1854
1927
|
const connectionTimeout = setTimeout(() => {
|
|
1855
1928
|
logger.error("WebSocket connection timeout");
|
|
1856
1929
|
this.websocket?.close();
|
|
1857
|
-
this.enterPollingFallback(
|
|
1858
|
-
new NetworkError("WebSocket connection failed")
|
|
1859
|
-
);
|
|
1930
|
+
this.enterPollingFallback(new NetworkError("WebSocket connection failed"));
|
|
1860
1931
|
}, 1e4);
|
|
1861
1932
|
this.websocket.onerror = (error) => {
|
|
1862
1933
|
clearTimeout(connectionTimeout);
|
|
1863
1934
|
logger.error("WebSocket error:", error);
|
|
1864
|
-
this.enterPollingFallback(
|
|
1865
|
-
new NetworkError("WebSocket connection failed")
|
|
1866
|
-
);
|
|
1935
|
+
this.enterPollingFallback(new NetworkError("WebSocket connection failed"));
|
|
1867
1936
|
};
|
|
1868
1937
|
this.websocket.onopen = () => {
|
|
1869
1938
|
clearTimeout(connectionTimeout);
|
|
@@ -1903,9 +1972,7 @@ var SwapManager = class _SwapManager {
|
|
|
1903
1972
|
};
|
|
1904
1973
|
} catch (error) {
|
|
1905
1974
|
logger.error("Failed to create WebSocket:", error);
|
|
1906
|
-
this.enterPollingFallback(
|
|
1907
|
-
new NetworkError("WebSocket connection failed")
|
|
1908
|
-
);
|
|
1975
|
+
this.enterPollingFallback(new NetworkError("WebSocket connection failed"));
|
|
1909
1976
|
}
|
|
1910
1977
|
}
|
|
1911
1978
|
/**
|
|
@@ -1940,11 +2007,8 @@ var SwapManager = class _SwapManager {
|
|
|
1940
2007
|
* Schedule WebSocket reconnection with exponential backoff
|
|
1941
2008
|
*/
|
|
1942
2009
|
scheduleReconnect() {
|
|
1943
|
-
if (this.reconnectTimer || this.webSocketUnavailable || !this.hasWebSocketSupport())
|
|
1944
|
-
|
|
1945
|
-
logger.log(
|
|
1946
|
-
`Scheduling WebSocket reconnect in ${this.currentReconnectDelay}ms`
|
|
1947
|
-
);
|
|
2010
|
+
if (this.reconnectTimer || this.webSocketUnavailable || !this.hasWebSocketSupport()) return;
|
|
2011
|
+
logger.log(`Scheduling WebSocket reconnect in ${this.currentReconnectDelay}ms`);
|
|
1948
2012
|
this.reconnectTimer = setTimeout(() => {
|
|
1949
2013
|
this.reconnectTimer = null;
|
|
1950
2014
|
this.isReconnecting = false;
|
|
@@ -1959,8 +2023,7 @@ var SwapManager = class _SwapManager {
|
|
|
1959
2023
|
* Subscribe to a specific swap ID on the WebSocket
|
|
1960
2024
|
*/
|
|
1961
2025
|
subscribeToSwap(swapId) {
|
|
1962
|
-
if (!this.websocket || this.websocket.readyState !== WebSocket.OPEN)
|
|
1963
|
-
return;
|
|
2026
|
+
if (!this.websocket || this.websocket.readyState !== WebSocket.OPEN) return;
|
|
1964
2027
|
this.websocket.send(
|
|
1965
2028
|
JSON.stringify({
|
|
1966
2029
|
op: "subscribe",
|
|
@@ -1983,9 +2046,7 @@ var SwapManager = class _SwapManager {
|
|
|
1983
2046
|
if (msg.args[0].error) {
|
|
1984
2047
|
logger.error(`Swap ${swapId} error:`, msg.args[0].error);
|
|
1985
2048
|
const error = new Error(msg.args[0].error);
|
|
1986
|
-
this.swapFailedListeners.forEach(
|
|
1987
|
-
(listener) => listener(swap, error)
|
|
1988
|
-
);
|
|
2049
|
+
this.swapFailedListeners.forEach((listener) => listener(swap, error));
|
|
1989
2050
|
return;
|
|
1990
2051
|
}
|
|
1991
2052
|
const newStatus = msg.args[0].status;
|
|
@@ -2003,19 +2064,14 @@ var SwapManager = class _SwapManager {
|
|
|
2003
2064
|
const oldStatus = swap.status;
|
|
2004
2065
|
if (oldStatus === newStatus) return;
|
|
2005
2066
|
swap.status = newStatus;
|
|
2006
|
-
this.swapUpdateListeners.forEach(
|
|
2007
|
-
(listener) => listener(swap, oldStatus)
|
|
2008
|
-
);
|
|
2067
|
+
this.swapUpdateListeners.forEach((listener) => listener(swap, oldStatus));
|
|
2009
2068
|
const subscribers = this.swapSubscriptions.get(swap.id);
|
|
2010
2069
|
if (subscribers) {
|
|
2011
2070
|
subscribers.forEach((callback) => {
|
|
2012
2071
|
try {
|
|
2013
2072
|
callback(swap, oldStatus);
|
|
2014
2073
|
} catch (error) {
|
|
2015
|
-
logger.error(
|
|
2016
|
-
`Error in swap subscription callback for ${swap.id}:`,
|
|
2017
|
-
error
|
|
2018
|
-
);
|
|
2074
|
+
logger.error(`Error in swap subscription callback for ${swap.id}:`, error);
|
|
2019
2075
|
}
|
|
2020
2076
|
});
|
|
2021
2077
|
}
|
|
@@ -2024,15 +2080,57 @@ var SwapManager = class _SwapManager {
|
|
|
2024
2080
|
await this.executeAutonomousAction(swap);
|
|
2025
2081
|
}
|
|
2026
2082
|
if (this.isFinalStatus(swap)) {
|
|
2027
|
-
this.
|
|
2028
|
-
|
|
2029
|
-
const retryTimer = this.pollRetryTimers.get(swap.id);
|
|
2030
|
-
if (retryTimer) {
|
|
2031
|
-
clearTimeout(retryTimer);
|
|
2032
|
-
this.pollRetryTimers.delete(swap.id);
|
|
2083
|
+
if (this.refundRetryTimers.has(swap.id)) {
|
|
2084
|
+
return;
|
|
2033
2085
|
}
|
|
2034
|
-
this.
|
|
2086
|
+
this.finalizeMonitoredSwap(swap);
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
/**
|
|
2090
|
+
* Drop a swap from monitoring and emit the terminal completion event.
|
|
2091
|
+
* Shared between the on-status-update finalization path and the
|
|
2092
|
+
* refund-retry finalization path (used when a previously-deferred
|
|
2093
|
+
* chain refund has finished its remaining work).
|
|
2094
|
+
*/
|
|
2095
|
+
finalizeMonitoredSwap(swap) {
|
|
2096
|
+
if (!this.monitoredSwaps.has(swap.id)) return;
|
|
2097
|
+
this.monitoredSwaps.delete(swap.id);
|
|
2098
|
+
this.swapSubscriptions.delete(swap.id);
|
|
2099
|
+
const retryTimer = this.pollRetryTimers.get(swap.id);
|
|
2100
|
+
if (retryTimer) {
|
|
2101
|
+
clearTimeout(retryTimer);
|
|
2102
|
+
this.pollRetryTimers.delete(swap.id);
|
|
2035
2103
|
}
|
|
2104
|
+
const refundRetry = this.refundRetryTimers.get(swap.id);
|
|
2105
|
+
if (refundRetry) {
|
|
2106
|
+
clearTimeout(refundRetry);
|
|
2107
|
+
this.refundRetryTimers.delete(swap.id);
|
|
2108
|
+
}
|
|
2109
|
+
this.swapCompletedListeners.forEach((listener) => listener(swap));
|
|
2110
|
+
}
|
|
2111
|
+
/**
|
|
2112
|
+
* Schedule another `executeAutonomousAction` run for a chain swap whose
|
|
2113
|
+
* refund left VTXOs deferred. After the retry completes, if no further
|
|
2114
|
+
* deferral was reported, finalize monitoring cleanup.
|
|
2115
|
+
*/
|
|
2116
|
+
scheduleRefundRetry(swap, delayMs) {
|
|
2117
|
+
const existing = this.refundRetryTimers.get(swap.id);
|
|
2118
|
+
if (existing) clearTimeout(existing);
|
|
2119
|
+
this.refundRetryTimers.set(
|
|
2120
|
+
swap.id,
|
|
2121
|
+
setTimeout(async () => {
|
|
2122
|
+
this.refundRetryTimers.delete(swap.id);
|
|
2123
|
+
if (!this.isRunning) return;
|
|
2124
|
+
if (!this.monitoredSwaps.has(swap.id)) return;
|
|
2125
|
+
try {
|
|
2126
|
+
await this.executeAutonomousAction(swap);
|
|
2127
|
+
} finally {
|
|
2128
|
+
if (!this.refundRetryTimers.has(swap.id) && this.isFinalStatus(swap)) {
|
|
2129
|
+
this.finalizeMonitoredSwap(swap);
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
}, delayMs)
|
|
2133
|
+
);
|
|
2036
2134
|
}
|
|
2037
2135
|
/**
|
|
2038
2136
|
* Execute autonomous action based on swap status
|
|
@@ -2040,9 +2138,7 @@ var SwapManager = class _SwapManager {
|
|
|
2040
2138
|
*/
|
|
2041
2139
|
async executeAutonomousAction(swap) {
|
|
2042
2140
|
if (this.swapsInProgress.has(swap.id)) {
|
|
2043
|
-
logger.log(
|
|
2044
|
-
`Swap ${swap.id} is already being processed, skipping autonomous action`
|
|
2045
|
-
);
|
|
2141
|
+
logger.log(`Swap ${swap.id} is already being processed, skipping autonomous action`);
|
|
2046
2142
|
return;
|
|
2047
2143
|
}
|
|
2048
2144
|
try {
|
|
@@ -2057,9 +2153,7 @@ var SwapManager = class _SwapManager {
|
|
|
2057
2153
|
if (isReverseClaimableStatus(swap.status)) {
|
|
2058
2154
|
logger.log(`Auto-claiming reverse swap ${swap.id}`);
|
|
2059
2155
|
await this.executeClaimAction(swap);
|
|
2060
|
-
this.actionExecutedListeners.forEach(
|
|
2061
|
-
(listener) => listener(swap, "claim")
|
|
2062
|
-
);
|
|
2156
|
+
this.actionExecutedListeners.forEach((listener) => listener(swap, "claim"));
|
|
2063
2157
|
}
|
|
2064
2158
|
} else if (isPendingSubmarineSwap(swap)) {
|
|
2065
2159
|
if (!swap.request?.invoice || swap.request.invoice.length === 0) {
|
|
@@ -2071,9 +2165,7 @@ var SwapManager = class _SwapManager {
|
|
|
2071
2165
|
if (isSubmarineRefundableStatus(swap.status)) {
|
|
2072
2166
|
logger.log(`Auto-refunding submarine swap ${swap.id}`);
|
|
2073
2167
|
await this.executeRefundAction(swap);
|
|
2074
|
-
this.actionExecutedListeners.forEach(
|
|
2075
|
-
(listener) => listener(swap, "refund")
|
|
2076
|
-
);
|
|
2168
|
+
this.actionExecutedListeners.forEach((listener) => listener(swap, "refund"));
|
|
2077
2169
|
}
|
|
2078
2170
|
} else if (isPendingChainSwap(swap)) {
|
|
2079
2171
|
if (isChainClaimableStatus(swap.status)) {
|
|
@@ -2093,10 +2185,27 @@ var SwapManager = class _SwapManager {
|
|
|
2093
2185
|
} else if (isChainRefundableStatus(swap.status)) {
|
|
2094
2186
|
if (swap.request.from === "ARK") {
|
|
2095
2187
|
logger.log(`Auto-refunding ARK chain swap ${swap.id}`);
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
(
|
|
2099
|
-
|
|
2188
|
+
try {
|
|
2189
|
+
const outcome = await this.executeRefundArkAction(swap);
|
|
2190
|
+
if (outcome && outcome.skipped > 0) {
|
|
2191
|
+
logger.log(
|
|
2192
|
+
`Chain swap ${swap.id}: ${outcome.skipped} VTXO(s) deferred \u2014 scheduling refund retry`
|
|
2193
|
+
);
|
|
2194
|
+
this.scheduleRefundRetry(swap, _SwapManager.REFUND_RETRY_DELAY_MS);
|
|
2195
|
+
}
|
|
2196
|
+
this.actionExecutedListeners.forEach(
|
|
2197
|
+
(listener) => listener(swap, "refundArk")
|
|
2198
|
+
);
|
|
2199
|
+
} catch (error) {
|
|
2200
|
+
logger.error(
|
|
2201
|
+
`Auto-refunding ARK chain swap ${swap.id} failed; scheduling retry`,
|
|
2202
|
+
error
|
|
2203
|
+
);
|
|
2204
|
+
this.swapFailedListeners.forEach(
|
|
2205
|
+
(listener) => listener(swap, error)
|
|
2206
|
+
);
|
|
2207
|
+
this.scheduleRefundRetry(swap, _SwapManager.REFUND_RETRY_DELAY_MS);
|
|
2208
|
+
}
|
|
2100
2209
|
}
|
|
2101
2210
|
if (swap.request.from === "BTC") {
|
|
2102
2211
|
logger.warn(
|
|
@@ -2123,13 +2232,8 @@ var SwapManager = class _SwapManager {
|
|
|
2123
2232
|
}
|
|
2124
2233
|
}
|
|
2125
2234
|
} catch (error) {
|
|
2126
|
-
logger.error(
|
|
2127
|
-
|
|
2128
|
-
error
|
|
2129
|
-
);
|
|
2130
|
-
this.swapFailedListeners.forEach(
|
|
2131
|
-
(listener) => listener(swap, error)
|
|
2132
|
-
);
|
|
2235
|
+
logger.error(`Failed to execute autonomous action for swap ${swap.id}:`, error);
|
|
2236
|
+
this.swapFailedListeners.forEach((listener) => listener(swap, error));
|
|
2133
2237
|
} finally {
|
|
2134
2238
|
this.swapsInProgress.delete(swap.id);
|
|
2135
2239
|
}
|
|
@@ -2182,7 +2286,7 @@ var SwapManager = class _SwapManager {
|
|
|
2182
2286
|
logger.error("refundArk callback not set");
|
|
2183
2287
|
return;
|
|
2184
2288
|
}
|
|
2185
|
-
|
|
2289
|
+
return this.refundArkCallback(swap);
|
|
2186
2290
|
}
|
|
2187
2291
|
/**
|
|
2188
2292
|
* Execute sign server claim action for chain swap.
|
|
@@ -2230,9 +2334,7 @@ var SwapManager = class _SwapManager {
|
|
|
2230
2334
|
logger.log(`Resuming chain refund for swap ${swap.id}`);
|
|
2231
2335
|
await this.executeAutonomousAction(swap);
|
|
2232
2336
|
} else if (isPendingChainSwap(swap) && swap.request.to === "ARK" && isChainSignableStatus(swap.status)) {
|
|
2233
|
-
logger.log(
|
|
2234
|
-
`Resuming server claim signing for swap ${swap.id}`
|
|
2235
|
-
);
|
|
2337
|
+
logger.log(`Resuming server claim signing for swap ${swap.id}`);
|
|
2236
2338
|
await this.executeAutonomousAction(swap);
|
|
2237
2339
|
}
|
|
2238
2340
|
} catch (error) {
|
|
@@ -2284,16 +2386,12 @@ var SwapManager = class _SwapManager {
|
|
|
2284
2386
|
*/
|
|
2285
2387
|
async pollAllSwaps() {
|
|
2286
2388
|
if (this.monitoredSwaps.size === 0) return;
|
|
2287
|
-
const pollPromises = Array.from(this.monitoredSwaps.values()).map(
|
|
2288
|
-
(swap) => this.pollSingleSwap(swap)
|
|
2289
|
-
);
|
|
2389
|
+
const pollPromises = Array.from(this.monitoredSwaps.values()).filter((swap) => !this.refundRetryTimers.has(swap.id)).map((swap) => this.pollSingleSwap(swap));
|
|
2290
2390
|
await Promise.allSettled(pollPromises);
|
|
2291
2391
|
}
|
|
2292
2392
|
async pollSingleSwap(swap) {
|
|
2293
2393
|
try {
|
|
2294
|
-
const statusResponse = await this.swapProvider.getSwapStatus(
|
|
2295
|
-
swap.id
|
|
2296
|
-
);
|
|
2394
|
+
const statusResponse = await this.swapProvider.getSwapStatus(swap.id);
|
|
2297
2395
|
this.notFoundCounts.delete(swap.id);
|
|
2298
2396
|
if (statusResponse.status !== swap.status) {
|
|
2299
2397
|
await this.handleSwapStatusUpdate(swap, statusResponse.status);
|
|
@@ -2304,9 +2402,7 @@ var SwapManager = class _SwapManager {
|
|
|
2304
2402
|
return;
|
|
2305
2403
|
}
|
|
2306
2404
|
if (error instanceof NetworkError && error.statusCode === 429) {
|
|
2307
|
-
logger.warn(
|
|
2308
|
-
`Rate-limited polling swap ${swap.id}, retrying in 2s`
|
|
2309
|
-
);
|
|
2405
|
+
logger.warn(`Rate-limited polling swap ${swap.id}, retrying in 2s`);
|
|
2310
2406
|
const existing = this.pollRetryTimers.get(swap.id);
|
|
2311
2407
|
if (existing) clearTimeout(existing);
|
|
2312
2408
|
this.pollRetryTimers.set(
|
|
@@ -2314,25 +2410,17 @@ var SwapManager = class _SwapManager {
|
|
|
2314
2410
|
setTimeout(async () => {
|
|
2315
2411
|
this.pollRetryTimers.delete(swap.id);
|
|
2316
2412
|
try {
|
|
2317
|
-
const retry = await this.swapProvider.getSwapStatus(
|
|
2318
|
-
swap.id
|
|
2319
|
-
);
|
|
2413
|
+
const retry = await this.swapProvider.getSwapStatus(swap.id);
|
|
2320
2414
|
this.notFoundCounts.delete(swap.id);
|
|
2321
2415
|
if (retry.status !== swap.status) {
|
|
2322
|
-
await this.handleSwapStatusUpdate(
|
|
2323
|
-
swap,
|
|
2324
|
-
retry.status
|
|
2325
|
-
);
|
|
2416
|
+
await this.handleSwapStatusUpdate(swap, retry.status);
|
|
2326
2417
|
}
|
|
2327
2418
|
} catch (retryError) {
|
|
2328
2419
|
if (retryError instanceof SwapNotFoundError) {
|
|
2329
2420
|
await this.handleSwapNotFound(swap);
|
|
2330
2421
|
return;
|
|
2331
2422
|
}
|
|
2332
|
-
logger.error(
|
|
2333
|
-
`Retry poll for swap ${swap.id} also failed:`,
|
|
2334
|
-
retryError
|
|
2335
|
-
);
|
|
2423
|
+
logger.error(`Retry poll for swap ${swap.id} also failed:`, retryError);
|
|
2336
2424
|
}
|
|
2337
2425
|
}, 2e3)
|
|
2338
2426
|
);
|
|
@@ -2351,6 +2439,7 @@ var SwapManager = class _SwapManager {
|
|
|
2351
2439
|
* Boltz endpoint).
|
|
2352
2440
|
*/
|
|
2353
2441
|
async handleSwapNotFound(swap) {
|
|
2442
|
+
if (this.refundRetryTimers.has(swap.id)) return;
|
|
2354
2443
|
const count = (this.notFoundCounts.get(swap.id) ?? 0) + 1;
|
|
2355
2444
|
this.notFoundCounts.set(swap.id, count);
|
|
2356
2445
|
logger.warn(
|
|
@@ -2371,6 +2460,7 @@ var SwapManager = class _SwapManager {
|
|
|
2371
2460
|
* 404s without recovering anything.
|
|
2372
2461
|
*/
|
|
2373
2462
|
async markSwapAsUnknownToProvider(swap) {
|
|
2463
|
+
if (this.refundRetryTimers.has(swap.id)) return;
|
|
2374
2464
|
if (!this.monitoredSwaps.has(swap.id)) {
|
|
2375
2465
|
this.notFoundCounts.delete(swap.id);
|
|
2376
2466
|
return;
|
|
@@ -2383,10 +2473,13 @@ var SwapManager = class _SwapManager {
|
|
|
2383
2473
|
clearTimeout(retryTimer);
|
|
2384
2474
|
this.pollRetryTimers.delete(swap.id);
|
|
2385
2475
|
}
|
|
2476
|
+
const refundRetryTimer = this.refundRetryTimers.get(swap.id);
|
|
2477
|
+
if (refundRetryTimer) {
|
|
2478
|
+
clearTimeout(refundRetryTimer);
|
|
2479
|
+
this.refundRetryTimers.delete(swap.id);
|
|
2480
|
+
}
|
|
2386
2481
|
this.notFoundCounts.delete(swap.id);
|
|
2387
|
-
this.swapUpdateListeners.forEach(
|
|
2388
|
-
(listener) => listener(swap, oldStatus)
|
|
2389
|
-
);
|
|
2482
|
+
this.swapUpdateListeners.forEach((listener) => listener(swap, oldStatus));
|
|
2390
2483
|
const subscribers = this.swapSubscriptions.get(swap.id);
|
|
2391
2484
|
if (subscribers) {
|
|
2392
2485
|
subscribers.forEach((callback) => {
|
|
@@ -2451,9 +2544,7 @@ async function saveSwap(swap, saver) {
|
|
|
2451
2544
|
if (saver.saveSubmarineSwap) {
|
|
2452
2545
|
await saver.saveSubmarineSwap(swap);
|
|
2453
2546
|
} else {
|
|
2454
|
-
console.warn(
|
|
2455
|
-
"No saveSubmarineSwap handler provided, swap not saved"
|
|
2456
|
-
);
|
|
2547
|
+
console.warn("No saveSubmarineSwap handler provided, swap not saved");
|
|
2457
2548
|
}
|
|
2458
2549
|
} else if (isPendingChainSwap(swap)) {
|
|
2459
2550
|
if (saver.saveChainSwap) {
|
|
@@ -2517,6 +2608,26 @@ function enrichSubmarineSwapInvoice(swap, invoice) {
|
|
|
2517
2608
|
return swap;
|
|
2518
2609
|
}
|
|
2519
2610
|
|
|
2611
|
+
// src/repositories/swap-repository.ts
|
|
2612
|
+
function hasImpossibleSwapsFilter(filter) {
|
|
2613
|
+
if (!filter) return false;
|
|
2614
|
+
return Array.isArray(filter.id) && filter.id.length === 0 || Array.isArray(filter.status) && filter.status.length === 0 || Array.isArray(filter.type) && filter.type.length === 0;
|
|
2615
|
+
}
|
|
2616
|
+
function matchesCriterion(value, criterion) {
|
|
2617
|
+
if (criterion === void 0) return true;
|
|
2618
|
+
return Array.isArray(criterion) ? criterion.includes(value) : value === criterion;
|
|
2619
|
+
}
|
|
2620
|
+
function applySwapsFilter(swaps, filter) {
|
|
2621
|
+
return swaps.filter(
|
|
2622
|
+
(swap) => !!swap && matchesCriterion(swap.id, filter.id) && matchesCriterion(swap.status, filter.status) && matchesCriterion(swap.type, filter.type)
|
|
2623
|
+
);
|
|
2624
|
+
}
|
|
2625
|
+
function applyCreatedAtOrder(swaps, filter) {
|
|
2626
|
+
if (filter?.orderBy !== "createdAt") return swaps;
|
|
2627
|
+
const direction = filter.orderDirection === "asc" ? 1 : -1;
|
|
2628
|
+
return swaps.slice().sort((a, b) => (a.createdAt - b.createdAt) * direction);
|
|
2629
|
+
}
|
|
2630
|
+
|
|
2520
2631
|
// src/repositories/IndexedDb/swap-repository.ts
|
|
2521
2632
|
var import_sdk4 = require("@arkade-os/sdk");
|
|
2522
2633
|
var DEFAULT_DB_NAME = "arkade-boltz-swap";
|
|
@@ -2532,6 +2643,10 @@ function initDatabase(db) {
|
|
|
2532
2643
|
swapStore.createIndex("createdAt", "createdAt", { unique: false });
|
|
2533
2644
|
}
|
|
2534
2645
|
}
|
|
2646
|
+
function asArray(v) {
|
|
2647
|
+
if (v === void 0) return void 0;
|
|
2648
|
+
return Array.isArray(v) ? v : [v];
|
|
2649
|
+
}
|
|
2535
2650
|
var IndexedDbSwapRepository = class {
|
|
2536
2651
|
constructor(dbName = DEFAULT_DB_NAME) {
|
|
2537
2652
|
this.dbName = dbName;
|
|
@@ -2546,10 +2661,7 @@ var IndexedDbSwapRepository = class {
|
|
|
2546
2661
|
async saveSwap(swap) {
|
|
2547
2662
|
const db = await this.getDB();
|
|
2548
2663
|
return new Promise((resolve, reject) => {
|
|
2549
|
-
const transaction = db.transaction(
|
|
2550
|
-
[STORE_SWAPS_STATE],
|
|
2551
|
-
"readwrite"
|
|
2552
|
-
);
|
|
2664
|
+
const transaction = db.transaction([STORE_SWAPS_STATE], "readwrite");
|
|
2553
2665
|
const store = transaction.objectStore(STORE_SWAPS_STATE);
|
|
2554
2666
|
const request = store.put(swap);
|
|
2555
2667
|
request.onsuccess = () => resolve();
|
|
@@ -2559,10 +2671,7 @@ var IndexedDbSwapRepository = class {
|
|
|
2559
2671
|
async deleteSwap(id) {
|
|
2560
2672
|
const db = await this.getDB();
|
|
2561
2673
|
return new Promise((resolve, reject) => {
|
|
2562
|
-
const transaction = db.transaction(
|
|
2563
|
-
[STORE_SWAPS_STATE],
|
|
2564
|
-
"readwrite"
|
|
2565
|
-
);
|
|
2674
|
+
const transaction = db.transaction([STORE_SWAPS_STATE], "readwrite");
|
|
2566
2675
|
const store = transaction.objectStore(STORE_SWAPS_STATE);
|
|
2567
2676
|
const request = store.delete(id);
|
|
2568
2677
|
request.onsuccess = () => resolve();
|
|
@@ -2575,10 +2684,7 @@ var IndexedDbSwapRepository = class {
|
|
|
2575
2684
|
async clear() {
|
|
2576
2685
|
const db = await this.getDB();
|
|
2577
2686
|
return new Promise((resolve, reject) => {
|
|
2578
|
-
const transaction = db.transaction(
|
|
2579
|
-
[STORE_SWAPS_STATE],
|
|
2580
|
-
"readwrite"
|
|
2581
|
-
);
|
|
2687
|
+
const transaction = db.transaction([STORE_SWAPS_STATE], "readwrite");
|
|
2582
2688
|
const store = transaction.objectStore(STORE_SWAPS_STATE);
|
|
2583
2689
|
const request = store.clear();
|
|
2584
2690
|
request.onsuccess = () => resolve();
|
|
@@ -2595,11 +2701,10 @@ var IndexedDbSwapRepository = class {
|
|
|
2595
2701
|
request.onsuccess = () => resolve(request.result ?? []);
|
|
2596
2702
|
})
|
|
2597
2703
|
);
|
|
2598
|
-
return Promise.all(requests).then(
|
|
2599
|
-
(results) => results.flatMap((result) => result)
|
|
2600
|
-
);
|
|
2704
|
+
return Promise.all(requests).then((results) => results.flatMap((result) => result));
|
|
2601
2705
|
}
|
|
2602
2706
|
async getAllSwapsFromStore(filter) {
|
|
2707
|
+
if (hasImpossibleSwapsFilter(filter)) return [];
|
|
2603
2708
|
const db = await this.getDB();
|
|
2604
2709
|
const store = db.transaction([STORE_SWAPS_STATE], "readonly").objectStore(STORE_SWAPS_STATE);
|
|
2605
2710
|
if (!filter || Object.keys(filter).length === 0) {
|
|
@@ -2609,9 +2714,8 @@ var IndexedDbSwapRepository = class {
|
|
|
2609
2714
|
request.onerror = () => reject(request.error);
|
|
2610
2715
|
});
|
|
2611
2716
|
}
|
|
2612
|
-
const
|
|
2613
|
-
if (
|
|
2614
|
-
const ids = normalizedFilter.get("id");
|
|
2717
|
+
const ids = asArray(filter.id);
|
|
2718
|
+
if (ids) {
|
|
2615
2719
|
const swaps = await Promise.all(
|
|
2616
2720
|
ids.map(
|
|
2617
2721
|
(id) => new Promise((resolve, reject) => {
|
|
@@ -2621,34 +2725,17 @@ var IndexedDbSwapRepository = class {
|
|
|
2621
2725
|
})
|
|
2622
2726
|
)
|
|
2623
2727
|
);
|
|
2624
|
-
return
|
|
2625
|
-
this.applySwapsFilter(swaps, normalizedFilter),
|
|
2626
|
-
filter
|
|
2627
|
-
);
|
|
2728
|
+
return applyCreatedAtOrder(applySwapsFilter(swaps, filter), filter);
|
|
2628
2729
|
}
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
const swaps = await this.getSwapsByIndexValues(
|
|
2632
|
-
|
|
2633
|
-
"type",
|
|
2634
|
-
types
|
|
2635
|
-
);
|
|
2636
|
-
return this.sortIfNeeded(
|
|
2637
|
-
this.applySwapsFilter(swaps, normalizedFilter),
|
|
2638
|
-
filter
|
|
2639
|
-
);
|
|
2730
|
+
const types = asArray(filter.type);
|
|
2731
|
+
if (types) {
|
|
2732
|
+
const swaps = await this.getSwapsByIndexValues(store, "type", types);
|
|
2733
|
+
return applyCreatedAtOrder(applySwapsFilter(swaps, filter), filter);
|
|
2640
2734
|
}
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
const swaps = await this.getSwapsByIndexValues(
|
|
2644
|
-
|
|
2645
|
-
"status",
|
|
2646
|
-
ids
|
|
2647
|
-
);
|
|
2648
|
-
return this.sortIfNeeded(
|
|
2649
|
-
this.applySwapsFilter(swaps, normalizedFilter),
|
|
2650
|
-
filter
|
|
2651
|
-
);
|
|
2735
|
+
const statuses = asArray(filter.status);
|
|
2736
|
+
if (statuses) {
|
|
2737
|
+
const swaps = await this.getSwapsByIndexValues(store, "status", statuses);
|
|
2738
|
+
return applyCreatedAtOrder(applySwapsFilter(swaps, filter), filter);
|
|
2652
2739
|
}
|
|
2653
2740
|
if (filter.orderBy === "createdAt") {
|
|
2654
2741
|
return this.getAllSwapsByCreatedAt(store, filter.orderDirection);
|
|
@@ -2658,22 +2745,7 @@ var IndexedDbSwapRepository = class {
|
|
|
2658
2745
|
request.onsuccess = () => resolve(request.result ?? []);
|
|
2659
2746
|
request.onerror = () => reject(request.error);
|
|
2660
2747
|
});
|
|
2661
|
-
return
|
|
2662
|
-
this.applySwapsFilter(allSwaps, normalizedFilter),
|
|
2663
|
-
filter
|
|
2664
|
-
);
|
|
2665
|
-
}
|
|
2666
|
-
applySwapsFilter(swaps, filter) {
|
|
2667
|
-
return swaps.filter((swap) => {
|
|
2668
|
-
if (swap === void 0) return false;
|
|
2669
|
-
if (filter.has("id") && !filter.get("id")?.includes(swap.id))
|
|
2670
|
-
return false;
|
|
2671
|
-
if (filter.has("status") && !filter.get("status")?.includes(swap.status))
|
|
2672
|
-
return false;
|
|
2673
|
-
if (filter.has("type") && !filter.get("type")?.includes(swap.type))
|
|
2674
|
-
return false;
|
|
2675
|
-
return true;
|
|
2676
|
-
});
|
|
2748
|
+
return applyCreatedAtOrder(applySwapsFilter(allSwaps, filter), filter);
|
|
2677
2749
|
}
|
|
2678
2750
|
async getAllSwapsByCreatedAt(store, orderDirection) {
|
|
2679
2751
|
const index = store.index("createdAt");
|
|
@@ -2693,30 +2765,12 @@ var IndexedDbSwapRepository = class {
|
|
|
2693
2765
|
};
|
|
2694
2766
|
});
|
|
2695
2767
|
}
|
|
2696
|
-
sortIfNeeded(swaps, filter) {
|
|
2697
|
-
if (filter?.orderBy !== "createdAt") return swaps;
|
|
2698
|
-
const direction = filter.orderDirection === "asc" ? 1 : -1;
|
|
2699
|
-
return swaps.slice().sort((a, b) => (a.createdAt - b.createdAt) * direction);
|
|
2700
|
-
}
|
|
2701
2768
|
async [Symbol.asyncDispose]() {
|
|
2702
2769
|
if (!this.db) return;
|
|
2703
2770
|
await (0, import_sdk4.closeDatabase)(this.dbName);
|
|
2704
2771
|
this.db = null;
|
|
2705
2772
|
}
|
|
2706
2773
|
};
|
|
2707
|
-
var FILTER_FIELDS = ["id", "status", "type"];
|
|
2708
|
-
function normalizeFilter(filter) {
|
|
2709
|
-
const res = /* @__PURE__ */ new Map();
|
|
2710
|
-
FILTER_FIELDS.forEach((current) => {
|
|
2711
|
-
if (!filter?.[current]) return;
|
|
2712
|
-
if (Array.isArray(filter[current])) {
|
|
2713
|
-
res.set(current, filter[current]);
|
|
2714
|
-
} else {
|
|
2715
|
-
res.set(current, [filter[current]]);
|
|
2716
|
-
}
|
|
2717
|
-
});
|
|
2718
|
-
return res;
|
|
2719
|
-
}
|
|
2720
2774
|
|
|
2721
2775
|
// src/utils/identity.ts
|
|
2722
2776
|
var import_sdk5 = require("@arkade-os/sdk");
|
|
@@ -2728,13 +2782,8 @@ function claimVHTLCIdentity(identity, preimage) {
|
|
|
2728
2782
|
let signedTx = await identity.sign(cpy, inputIndexes);
|
|
2729
2783
|
signedTx = import_sdk5.Transaction.fromPSBT(signedTx.toPSBT());
|
|
2730
2784
|
if (preimage) {
|
|
2731
|
-
for (const inputIndex of inputIndexes || Array.from(
|
|
2732
|
-
|
|
2733
|
-
(_, i) => i
|
|
2734
|
-
)) {
|
|
2735
|
-
(0, import_sdk5.setArkPsbtField)(signedTx, inputIndex, import_sdk5.ConditionWitness, [
|
|
2736
|
-
preimage
|
|
2737
|
-
]);
|
|
2785
|
+
for (const inputIndex of inputIndexes || Array.from({ length: signedTx.inputsLength }, (_, i) => i)) {
|
|
2786
|
+
(0, import_sdk5.setArkPsbtField)(signedTx, inputIndex, import_sdk5.ConditionWitness, [preimage]);
|
|
2738
2787
|
}
|
|
2739
2788
|
}
|
|
2740
2789
|
return signedTx;
|
|
@@ -2789,17 +2838,13 @@ function createVHTLCBatchHandler(intentId, vhtlc, arkProvider, identity, session
|
|
|
2789
2838
|
if (!sweepTapTreeRoot) {
|
|
2790
2839
|
throw new Error("Sweep tap tree root not set");
|
|
2791
2840
|
}
|
|
2792
|
-
const xOnlyPublicKeys = event.cosignersPublicKeys.map(
|
|
2793
|
-
(k) => k.slice(2)
|
|
2794
|
-
);
|
|
2841
|
+
const xOnlyPublicKeys = event.cosignersPublicKeys.map((k) => k.slice(2));
|
|
2795
2842
|
const signerPublicKey = await session.getPublicKey();
|
|
2796
2843
|
const xonlySignerPublicKey = signerPublicKey.subarray(1);
|
|
2797
2844
|
if (!xOnlyPublicKeys.includes(import_base7.hex.encode(xonlySignerPublicKey))) {
|
|
2798
2845
|
return { skip: true };
|
|
2799
2846
|
}
|
|
2800
|
-
const commitmentTx = import_sdk6.Transaction.fromPSBT(
|
|
2801
|
-
import_base7.base64.decode(event.unsignedCommitmentTx)
|
|
2802
|
-
);
|
|
2847
|
+
const commitmentTx = import_sdk6.Transaction.fromPSBT(import_base7.base64.decode(event.unsignedCommitmentTx));
|
|
2803
2848
|
(0, import_sdk6.validateVtxoTxGraph)(vtxoTree, commitmentTx, sweepTapTreeRoot);
|
|
2804
2849
|
const sharedOutput = commitmentTx.getOutput(0);
|
|
2805
2850
|
if (!sharedOutput?.amount) {
|
|
@@ -2815,18 +2860,11 @@ function createVHTLCBatchHandler(intentId, vhtlc, arkProvider, identity, session
|
|
|
2815
2860
|
if (!session) {
|
|
2816
2861
|
return { fullySigned: true };
|
|
2817
2862
|
}
|
|
2818
|
-
const { hasAllNonces } = await session.aggregatedNonces(
|
|
2819
|
-
event.txid,
|
|
2820
|
-
event.nonces
|
|
2821
|
-
);
|
|
2863
|
+
const { hasAllNonces } = await session.aggregatedNonces(event.txid, event.nonces);
|
|
2822
2864
|
if (!hasAllNonces) return { fullySigned: false };
|
|
2823
2865
|
const signatures = await session.sign();
|
|
2824
2866
|
const pubkey = import_base7.hex.encode(await session.getPublicKey());
|
|
2825
|
-
await arkProvider.submitTreeSignatures(
|
|
2826
|
-
event.id,
|
|
2827
|
-
pubkey,
|
|
2828
|
-
signatures
|
|
2829
|
-
);
|
|
2867
|
+
await arkProvider.submitTreeSignatures(event.id, pubkey, signatures);
|
|
2830
2868
|
return { fullySigned: true };
|
|
2831
2869
|
},
|
|
2832
2870
|
onBatchFinalization: async (event, _, connectorTree) => {
|
|
@@ -2834,9 +2872,7 @@ function createVHTLCBatchHandler(intentId, vhtlc, arkProvider, identity, session
|
|
|
2834
2872
|
return;
|
|
2835
2873
|
}
|
|
2836
2874
|
if (!connectorTree) {
|
|
2837
|
-
throw new Error(
|
|
2838
|
-
"BatchFinalizationEvent: expected connector tree to be defined"
|
|
2839
|
-
);
|
|
2875
|
+
throw new Error("BatchFinalizationEvent: expected connector tree to be defined");
|
|
2840
2876
|
}
|
|
2841
2877
|
(0, import_sdk6.validateConnectorsTxGraph)(event.commitmentTx, connectorTree);
|
|
2842
2878
|
const connectors = connectorTree.leaves();
|
|
@@ -2851,9 +2887,7 @@ function createVHTLCBatchHandler(intentId, vhtlc, arkProvider, identity, session
|
|
|
2851
2887
|
connectors[connectorIndex]
|
|
2852
2888
|
);
|
|
2853
2889
|
const signedForfeitTx = await identity.sign(forfeitTx);
|
|
2854
|
-
await arkProvider.submitSignedForfeitTxs([
|
|
2855
|
-
import_base7.base64.encode(signedForfeitTx.toPSBT())
|
|
2856
|
-
]);
|
|
2890
|
+
await arkProvider.submitSignedForfeitTxs([import_base7.base64.encode(signedForfeitTx.toPSBT())]);
|
|
2857
2891
|
}
|
|
2858
2892
|
};
|
|
2859
2893
|
}
|
|
@@ -2913,36 +2947,22 @@ var createVHTLCScript = (args) => {
|
|
|
2913
2947
|
serverPubkey,
|
|
2914
2948
|
timeoutBlockHeights: vhtlcTimeouts
|
|
2915
2949
|
} = args;
|
|
2916
|
-
const receiverXOnlyPublicKey = normalizeToXOnlyKey(
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
);
|
|
2920
|
-
const senderXOnlyPublicKey = normalizeToXOnlyKey(
|
|
2921
|
-
import_base8.hex.decode(senderPubkey),
|
|
2922
|
-
"sender"
|
|
2923
|
-
);
|
|
2924
|
-
const serverXOnlyPublicKey = normalizeToXOnlyKey(
|
|
2925
|
-
import_base8.hex.decode(serverPubkey),
|
|
2926
|
-
"server"
|
|
2927
|
-
);
|
|
2950
|
+
const receiverXOnlyPublicKey = normalizeToXOnlyKey(import_base8.hex.decode(receiverPubkey), "receiver");
|
|
2951
|
+
const senderXOnlyPublicKey = normalizeToXOnlyKey(import_base8.hex.decode(senderPubkey), "sender");
|
|
2952
|
+
const serverXOnlyPublicKey = normalizeToXOnlyKey(import_base8.hex.decode(serverPubkey), "server");
|
|
2928
2953
|
const vhtlcScript = new import_sdk7.VHTLC.Script({
|
|
2929
2954
|
preimageHash: (0, import_legacy.ripemd160)(preimageHash),
|
|
2930
2955
|
sender: senderXOnlyPublicKey,
|
|
2931
2956
|
receiver: receiverXOnlyPublicKey,
|
|
2932
2957
|
server: serverXOnlyPublicKey,
|
|
2933
2958
|
refundLocktime: BigInt(vhtlcTimeouts.refund),
|
|
2934
|
-
unilateralClaimDelay: toBip68RelativeTimelock(
|
|
2935
|
-
|
|
2936
|
-
),
|
|
2937
|
-
unilateralRefundDelay: toBip68RelativeTimelock(
|
|
2938
|
-
vhtlcTimeouts.unilateralRefund
|
|
2939
|
-
),
|
|
2959
|
+
unilateralClaimDelay: toBip68RelativeTimelock(vhtlcTimeouts.unilateralClaim),
|
|
2960
|
+
unilateralRefundDelay: toBip68RelativeTimelock(vhtlcTimeouts.unilateralRefund),
|
|
2940
2961
|
unilateralRefundWithoutReceiverDelay: toBip68RelativeTimelock(
|
|
2941
2962
|
vhtlcTimeouts.unilateralRefundWithoutReceiver
|
|
2942
2963
|
)
|
|
2943
2964
|
});
|
|
2944
|
-
if (!vhtlcScript.claimScript)
|
|
2945
|
-
throw new Error("Failed to create VHTLC script");
|
|
2965
|
+
if (!vhtlcScript.claimScript) throw new Error("Failed to create VHTLC script");
|
|
2946
2966
|
const hrp = network === "bitcoin" ? "ark" : "tark";
|
|
2947
2967
|
const vhtlcAddress = vhtlcScript.address(hrp, serverXOnlyPublicKey).encode();
|
|
2948
2968
|
return { vhtlcScript, vhtlcAddress };
|
|
@@ -2976,11 +2996,7 @@ var joinBatch = async (arkProvider, identity, input, output, {
|
|
|
2976
2996
|
unknown: [import_sdk7.VtxoTaprootTree.encode(input.tapTree)],
|
|
2977
2997
|
sequence: (0, import_sdk7.getSequence)(input.tapLeafScript)
|
|
2978
2998
|
};
|
|
2979
|
-
const registerIntent = import_sdk7.Intent.create(
|
|
2980
|
-
intentMessage,
|
|
2981
|
-
[intentInput],
|
|
2982
|
-
[output]
|
|
2983
|
-
);
|
|
2999
|
+
const registerIntent = import_sdk7.Intent.create(intentMessage, [intentInput], [output]);
|
|
2984
3000
|
const deleteIntent = import_sdk7.Intent.create(deleteMessage, [intentInput]);
|
|
2985
3001
|
const [signedRegisterIntent, signedDeleteIntent] = await Promise.all([
|
|
2986
3002
|
identity.sign(registerIntent),
|
|
@@ -3004,14 +3020,8 @@ var joinBatch = async (arkProvider, identity, input, output, {
|
|
|
3004
3020
|
normalizeToXOnlyKey(forfeitPubkey, "forfeit"),
|
|
3005
3021
|
isRecoverable2 ? void 0 : import_btc_signer4.OutScript.encode(decodedAddress)
|
|
3006
3022
|
);
|
|
3007
|
-
const topics = [
|
|
3008
|
-
|
|
3009
|
-
`${input.txid}:${input.vout}`
|
|
3010
|
-
];
|
|
3011
|
-
const eventStream = arkProvider.getEventStream(
|
|
3012
|
-
abortController.signal,
|
|
3013
|
-
topics
|
|
3014
|
-
);
|
|
3023
|
+
const topics = [import_base8.hex.encode(signerPublicKey), `${input.txid}:${input.vout}`];
|
|
3024
|
+
const eventStream = arkProvider.getEventStream(abortController.signal, topics);
|
|
3015
3025
|
const commitmentTxid = await import_sdk7.Batch.join(eventStream, handler, {
|
|
3016
3026
|
abortController
|
|
3017
3027
|
});
|
|
@@ -3032,14 +3042,8 @@ var joinBatch = async (arkProvider, identity, input, output, {
|
|
|
3032
3042
|
};
|
|
3033
3043
|
var claimVHTLCwithOffchainTx = async (identity, vhtlcScript, serverXOnlyPublicKey, input, output, arkInfo, arkProvider) => {
|
|
3034
3044
|
const rawCheckpointTapscript = import_base8.hex.decode(arkInfo.checkpointTapscript);
|
|
3035
|
-
const serverUnrollScript = import_sdk7.CSVMultisigTapscript.decode(
|
|
3036
|
-
|
|
3037
|
-
);
|
|
3038
|
-
const { arkTx, checkpoints } = (0, import_sdk7.buildOffchainTx)(
|
|
3039
|
-
[input],
|
|
3040
|
-
[output],
|
|
3041
|
-
serverUnrollScript
|
|
3042
|
-
);
|
|
3045
|
+
const serverUnrollScript = import_sdk7.CSVMultisigTapscript.decode(rawCheckpointTapscript);
|
|
3046
|
+
const { arkTx, checkpoints } = (0, import_sdk7.buildOffchainTx)([input], [output], serverUnrollScript);
|
|
3043
3047
|
const signedArkTx = await identity.sign(arkTx);
|
|
3044
3048
|
const { arkTxid, finalArkTx, signedCheckpointTxs } = await arkProvider.submitTx(
|
|
3045
3049
|
import_base8.base64.encode(signedArkTx.toPSBT()),
|
|
@@ -3047,9 +3051,7 @@ var claimVHTLCwithOffchainTx = async (identity, vhtlcScript, serverXOnlyPublicKe
|
|
|
3047
3051
|
);
|
|
3048
3052
|
const finalTx = import_sdk7.Transaction.fromPSBT(import_base8.base64.decode(finalArkTx));
|
|
3049
3053
|
const serverPubkeyHex = import_base8.hex.encode(serverXOnlyPublicKey);
|
|
3050
|
-
const claimLeafHash = (0, import_payment3.tapLeafHash)(
|
|
3051
|
-
scriptFromTapLeafScript(vhtlcScript.claim())
|
|
3052
|
-
);
|
|
3054
|
+
const claimLeafHash = (0, import_payment3.tapLeafHash)(scriptFromTapLeafScript(vhtlcScript.claim()));
|
|
3053
3055
|
for (let i = 0; i < finalTx.inputsLength; i++) {
|
|
3054
3056
|
if (!verifySignatures(finalTx, i, [serverPubkeyHex], claimLeafHash)) {
|
|
3055
3057
|
throw new Error("Invalid final Ark transaction");
|
|
@@ -3059,13 +3061,9 @@ var claimVHTLCwithOffchainTx = async (identity, vhtlcScript, serverXOnlyPublicKe
|
|
|
3059
3061
|
signedCheckpointTxs.map(async (c, idx) => {
|
|
3060
3062
|
const tx = import_sdk7.Transaction.fromPSBT(import_base8.base64.decode(c));
|
|
3061
3063
|
const checkpointLeaf = checkpoints[idx].getInput(0).tapLeafScript[0];
|
|
3062
|
-
const cpLeafHash = (0, import_payment3.tapLeafHash)(
|
|
3063
|
-
scriptFromTapLeafScript(checkpointLeaf)
|
|
3064
|
-
);
|
|
3064
|
+
const cpLeafHash = (0, import_payment3.tapLeafHash)(scriptFromTapLeafScript(checkpointLeaf));
|
|
3065
3065
|
if (!verifySignatures(tx, 0, [serverPubkeyHex], cpLeafHash)) {
|
|
3066
|
-
throw new Error(
|
|
3067
|
-
"Invalid server signature in checkpoint transaction"
|
|
3068
|
-
);
|
|
3066
|
+
throw new Error("Invalid server signature in checkpoint transaction");
|
|
3069
3067
|
}
|
|
3070
3068
|
const signedCheckpoint = await identity.sign(tx, [0]);
|
|
3071
3069
|
return import_base8.base64.encode(signedCheckpoint.toPSBT());
|
|
@@ -3075,61 +3073,37 @@ var claimVHTLCwithOffchainTx = async (identity, vhtlcScript, serverXOnlyPublicKe
|
|
|
3075
3073
|
};
|
|
3076
3074
|
var refundVHTLCwithOffchainTx = async (swapId, identity, arkProvider, boltzXOnlyPublicKey, ourXOnlyPublicKey, serverXOnlyPublicKey, input, output, arkInfo, refundFunc) => {
|
|
3077
3075
|
const rawCheckpointTapscript = import_base8.hex.decode(arkInfo.checkpointTapscript);
|
|
3078
|
-
const serverUnrollScript = import_sdk7.CSVMultisigTapscript.decode(
|
|
3079
|
-
|
|
3076
|
+
const serverUnrollScript = import_sdk7.CSVMultisigTapscript.decode(rawCheckpointTapscript);
|
|
3077
|
+
const { arkTx: unsignedRefundTx, checkpoints: checkpointPtxs } = (0, import_sdk7.buildOffchainTx)(
|
|
3078
|
+
[input],
|
|
3079
|
+
[output],
|
|
3080
|
+
serverUnrollScript
|
|
3080
3081
|
);
|
|
3081
|
-
const { arkTx: unsignedRefundTx, checkpoints: checkpointPtxs } = (0, import_sdk7.buildOffchainTx)([input], [output], serverUnrollScript);
|
|
3082
3082
|
if (checkpointPtxs.length !== 1)
|
|
3083
|
-
throw new Error(
|
|
3084
|
-
`Expected one checkpoint transaction, got ${checkpointPtxs.length}`
|
|
3085
|
-
);
|
|
3083
|
+
throw new Error(`Expected one checkpoint transaction, got ${checkpointPtxs.length}`);
|
|
3086
3084
|
const unsignedCheckpointTx = checkpointPtxs[0];
|
|
3087
3085
|
let boltzSignedRefundTx;
|
|
3088
3086
|
let boltzSignedCheckpointTx;
|
|
3089
3087
|
try {
|
|
3090
|
-
const result = await refundFunc(
|
|
3091
|
-
swapId,
|
|
3092
|
-
unsignedRefundTx,
|
|
3093
|
-
unsignedCheckpointTx
|
|
3094
|
-
);
|
|
3088
|
+
const result = await refundFunc(swapId, unsignedRefundTx, unsignedCheckpointTx);
|
|
3095
3089
|
boltzSignedRefundTx = result.transaction;
|
|
3096
3090
|
boltzSignedCheckpointTx = result.checkpoint;
|
|
3097
3091
|
} catch (error) {
|
|
3098
|
-
throw new BoltzRefundError(
|
|
3099
|
-
`Boltz rejected refund for swap ${swapId}`,
|
|
3100
|
-
error
|
|
3101
|
-
);
|
|
3092
|
+
throw new BoltzRefundError(`Boltz rejected refund for swap ${swapId}`, error);
|
|
3102
3093
|
}
|
|
3103
3094
|
const boltzXOnlyPublicKeyHex = import_base8.hex.encode(boltzXOnlyPublicKey);
|
|
3104
|
-
const refundLeafHash = (0, import_payment3.tapLeafHash)(
|
|
3105
|
-
|
|
3106
|
-
);
|
|
3107
|
-
if (!verifySignatures(
|
|
3108
|
-
boltzSignedRefundTx,
|
|
3109
|
-
0,
|
|
3110
|
-
[boltzXOnlyPublicKeyHex],
|
|
3111
|
-
refundLeafHash
|
|
3112
|
-
)) {
|
|
3095
|
+
const refundLeafHash = (0, import_payment3.tapLeafHash)(scriptFromTapLeafScript(input.tapLeafScript));
|
|
3096
|
+
if (!verifySignatures(boltzSignedRefundTx, 0, [boltzXOnlyPublicKeyHex], refundLeafHash)) {
|
|
3113
3097
|
throw new Error("Invalid Boltz signature in refund transaction");
|
|
3114
3098
|
}
|
|
3115
3099
|
const checkpointLeaf = unsignedCheckpointTx.getInput(0).tapLeafScript[0];
|
|
3116
|
-
const checkpointLeafHash = (0, import_payment3.tapLeafHash)(
|
|
3117
|
-
|
|
3118
|
-
);
|
|
3119
|
-
if (!verifySignatures(
|
|
3120
|
-
boltzSignedCheckpointTx,
|
|
3121
|
-
0,
|
|
3122
|
-
[boltzXOnlyPublicKeyHex],
|
|
3123
|
-
checkpointLeafHash
|
|
3124
|
-
)) {
|
|
3100
|
+
const checkpointLeafHash = (0, import_payment3.tapLeafHash)(scriptFromTapLeafScript(checkpointLeaf));
|
|
3101
|
+
if (!verifySignatures(boltzSignedCheckpointTx, 0, [boltzXOnlyPublicKeyHex], checkpointLeafHash)) {
|
|
3125
3102
|
throw new Error("Invalid Boltz signature in checkpoint transaction");
|
|
3126
3103
|
}
|
|
3127
3104
|
const signedRefundTx = await identity.sign(unsignedRefundTx);
|
|
3128
3105
|
const signedCheckpointTx = await identity.sign(unsignedCheckpointTx);
|
|
3129
|
-
const combinedSignedRefundTx = (0, import_sdk7.combineTapscriptSigs)(
|
|
3130
|
-
boltzSignedRefundTx,
|
|
3131
|
-
signedRefundTx
|
|
3132
|
-
);
|
|
3106
|
+
const combinedSignedRefundTx = (0, import_sdk7.combineTapscriptSigs)(boltzSignedRefundTx, signedRefundTx);
|
|
3133
3107
|
const combinedSignedCheckpointTx = (0, import_sdk7.combineTapscriptSigs)(
|
|
3134
3108
|
boltzSignedCheckpointTx,
|
|
3135
3109
|
signedCheckpointTx
|
|
@@ -3153,25 +3127,16 @@ var refundVHTLCwithOffchainTx = async (swapId, identity, arkProvider, boltzXOnly
|
|
|
3153
3127
|
`Expected one signed checkpoint transaction, got ${signedCheckpointTxs.length}`
|
|
3154
3128
|
);
|
|
3155
3129
|
}
|
|
3156
|
-
const serverSignedCheckpointTx = import_sdk7.Transaction.fromPSBT(
|
|
3157
|
-
import_base8.base64.decode(signedCheckpointTxs[0])
|
|
3158
|
-
);
|
|
3130
|
+
const serverSignedCheckpointTx = import_sdk7.Transaction.fromPSBT(import_base8.base64.decode(signedCheckpointTxs[0]));
|
|
3159
3131
|
const serverPubkeyHex = import_base8.hex.encode(serverXOnlyPublicKey);
|
|
3160
|
-
if (!verifySignatures(
|
|
3161
|
-
serverSignedCheckpointTx,
|
|
3162
|
-
0,
|
|
3163
|
-
[serverPubkeyHex],
|
|
3164
|
-
checkpointLeafHash
|
|
3165
|
-
)) {
|
|
3132
|
+
if (!verifySignatures(serverSignedCheckpointTx, 0, [serverPubkeyHex], checkpointLeafHash)) {
|
|
3166
3133
|
throw new Error("Invalid server signature in checkpoint transaction");
|
|
3167
3134
|
}
|
|
3168
3135
|
const finalCheckpointTx = (0, import_sdk7.combineTapscriptSigs)(
|
|
3169
3136
|
combinedSignedCheckpointTx,
|
|
3170
3137
|
serverSignedCheckpointTx
|
|
3171
3138
|
);
|
|
3172
|
-
await arkProvider.finalizeTx(arkTxid, [
|
|
3173
|
-
import_base8.base64.encode(finalCheckpointTx.toPSBT())
|
|
3174
|
-
]);
|
|
3139
|
+
await arkProvider.finalizeTx(arkTxid, [import_base8.base64.encode(finalCheckpointTx.toPSBT())]);
|
|
3175
3140
|
};
|
|
3176
3141
|
function scriptFromTapLeafScript(leaf) {
|
|
3177
3142
|
return leaf[1].subarray(0, leaf[1].length - 1);
|
|
@@ -3179,21 +3144,21 @@ function scriptFromTapLeafScript(leaf) {
|
|
|
3179
3144
|
|
|
3180
3145
|
// src/arkade-swaps.ts
|
|
3181
3146
|
var dedupeVtxos = (vtxos) => [
|
|
3182
|
-
...new Map(
|
|
3183
|
-
vtxos.map((vtxo) => [`${vtxo.txid}:${vtxo.vout}`, vtxo])
|
|
3184
|
-
).values()
|
|
3147
|
+
...new Map(vtxos.map((vtxo) => [`${vtxo.txid}:${vtxo.vout}`, vtxo])).values()
|
|
3185
3148
|
];
|
|
3186
3149
|
var hasNonEmptyString = (value) => typeof value === "string" && value.length > 0;
|
|
3187
3150
|
var canRecoverViaBoltz3of3 = (refundableVtxos, swap) => {
|
|
3188
3151
|
const hasRequiredSwapMetadata = hasNonEmptyString(swap.id) && hasNonEmptyString(swap.request.refundPublicKey) && hasNonEmptyString(swap.response.address) && hasNonEmptyString(swap.response.claimPublicKey) && !!swap.response.timeoutBlockHeights;
|
|
3189
3152
|
if (!hasRequiredSwapMetadata) return false;
|
|
3190
|
-
return refundableVtxos.some(
|
|
3191
|
-
(vtxo) => !vtxo.isSpent && !(0, import_sdk8.isRecoverable)(vtxo)
|
|
3192
|
-
);
|
|
3153
|
+
return refundableVtxos.some((vtxo) => !vtxo.isSpent && !(0, import_sdk8.isRecoverable)(vtxo));
|
|
3193
3154
|
};
|
|
3194
3155
|
var isSubmarineRefundLocktimeReached = (refundTimestamp) => Math.floor(Date.now() / 1e3) >= refundTimestamp;
|
|
3195
3156
|
var CLAIM_VTXO_RETRY_ATTEMPTS = 3;
|
|
3196
3157
|
var CLAIM_VTXO_RETRY_DELAY_MS = 500;
|
|
3158
|
+
var quoteOptionsForSwap = (swap) => {
|
|
3159
|
+
const amount = swap.response?.claimDetails?.amount;
|
|
3160
|
+
return typeof amount === "number" ? { minAcceptableAmount: amount } : void 0;
|
|
3161
|
+
};
|
|
3197
3162
|
var ArkadeSwaps = class _ArkadeSwaps {
|
|
3198
3163
|
/** The Arkade wallet instance used for signing and address generation. */
|
|
3199
3164
|
wallet;
|
|
@@ -3229,10 +3194,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3229
3194
|
return new _ArkadeSwaps(config);
|
|
3230
3195
|
}
|
|
3231
3196
|
const arkProvider = config.arkProvider ?? config.wallet.arkProvider;
|
|
3232
|
-
if (!arkProvider)
|
|
3233
|
-
throw new Error(
|
|
3234
|
-
"Ark provider is required either in wallet or config."
|
|
3235
|
-
);
|
|
3197
|
+
if (!arkProvider) throw new Error("Ark provider is required either in wallet or config.");
|
|
3236
3198
|
const arkInfo = await arkProvider.getInfo();
|
|
3237
3199
|
const network = arkInfo.network;
|
|
3238
3200
|
const swapProvider = new BoltzSwapProvider({ network });
|
|
@@ -3243,16 +3205,11 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3243
3205
|
if (!config.swapProvider) throw new Error("Swap provider is required.");
|
|
3244
3206
|
this.wallet = config.wallet;
|
|
3245
3207
|
const arkProvider = config.arkProvider ?? config.wallet.arkProvider;
|
|
3246
|
-
if (!arkProvider)
|
|
3247
|
-
throw new Error(
|
|
3248
|
-
"Ark provider is required either in wallet or config."
|
|
3249
|
-
);
|
|
3208
|
+
if (!arkProvider) throw new Error("Ark provider is required either in wallet or config.");
|
|
3250
3209
|
this.arkProvider = arkProvider;
|
|
3251
3210
|
const indexerProvider = config.indexerProvider ?? config.wallet.indexerProvider;
|
|
3252
3211
|
if (!indexerProvider)
|
|
3253
|
-
throw new Error(
|
|
3254
|
-
"Indexer provider is required either in wallet or config."
|
|
3255
|
-
);
|
|
3212
|
+
throw new Error("Indexer provider is required either in wallet or config.");
|
|
3256
3213
|
this.indexerProvider = indexerProvider;
|
|
3257
3214
|
this.swapProvider = config.swapProvider;
|
|
3258
3215
|
if (config.swapRepository) {
|
|
@@ -3263,10 +3220,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3263
3220
|
if (config.swapManager !== false) {
|
|
3264
3221
|
const swapManagerConfig = !config.swapManager || config.swapManager === true ? {} : config.swapManager;
|
|
3265
3222
|
const shouldAutostart = swapManagerConfig.autoStart ?? true;
|
|
3266
|
-
this.swapManager = new SwapManager(
|
|
3267
|
-
this.swapProvider,
|
|
3268
|
-
swapManagerConfig
|
|
3269
|
-
);
|
|
3223
|
+
this.swapManager = new SwapManager(this.swapProvider, swapManagerConfig);
|
|
3270
3224
|
this.swapManager.setCallbacks({
|
|
3271
3225
|
claim: async (swap) => {
|
|
3272
3226
|
await this.claimVHTLC(swap);
|
|
@@ -3281,7 +3235,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3281
3235
|
await this.claimBtc(swap);
|
|
3282
3236
|
},
|
|
3283
3237
|
refundArk: async (swap) => {
|
|
3284
|
-
|
|
3238
|
+
return this.refundArk(swap);
|
|
3285
3239
|
},
|
|
3286
3240
|
signServerClaim: async (swap) => {
|
|
3287
3241
|
await this.signCooperativeClaimForServer(swap);
|
|
@@ -3414,19 +3368,15 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3414
3368
|
* @throws {SwapError} If amount is <= 0 or key retrieval fails.
|
|
3415
3369
|
*/
|
|
3416
3370
|
async createReverseSwap(args) {
|
|
3417
|
-
if (args.amount <= 0)
|
|
3418
|
-
|
|
3419
|
-
const claimPublicKey = import_base9.hex.encode(
|
|
3420
|
-
await this.wallet.identity.compressedPublicKey()
|
|
3421
|
-
);
|
|
3371
|
+
if (args.amount <= 0) throw new SwapError({ message: "Amount must be greater than 0" });
|
|
3372
|
+
const claimPublicKey = import_base9.hex.encode(await this.wallet.identity.compressedPublicKey());
|
|
3422
3373
|
if (!claimPublicKey)
|
|
3423
3374
|
throw new SwapError({
|
|
3424
3375
|
message: "Failed to get claim public key from wallet"
|
|
3425
3376
|
});
|
|
3426
3377
|
const preimage = (0, import_utils3.randomBytes)(32);
|
|
3427
3378
|
const preimageHash = import_base9.hex.encode((0, import_sha23.sha256)(preimage));
|
|
3428
|
-
if (!preimageHash)
|
|
3429
|
-
throw new SwapError({ message: "Failed to get preimage hash" });
|
|
3379
|
+
if (!preimageHash) throw new SwapError({ message: "Failed to get preimage hash" });
|
|
3430
3380
|
const swapRequest = {
|
|
3431
3381
|
invoiceAmount: args.amount,
|
|
3432
3382
|
claimPublicKey,
|
|
@@ -3456,18 +3406,14 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3456
3406
|
*/
|
|
3457
3407
|
async claimVHTLC(pendingSwap) {
|
|
3458
3408
|
if (!pendingSwap.preimage)
|
|
3459
|
-
throw new Error(
|
|
3460
|
-
`Swap ${pendingSwap.id}: preimage is required to claim VHTLC`
|
|
3461
|
-
);
|
|
3409
|
+
throw new Error(`Swap ${pendingSwap.id}: preimage is required to claim VHTLC`);
|
|
3462
3410
|
const {
|
|
3463
3411
|
refundPublicKey,
|
|
3464
3412
|
lockupAddress,
|
|
3465
3413
|
timeoutBlockHeights: vhtlcTimeouts
|
|
3466
3414
|
} = pendingSwap.response;
|
|
3467
3415
|
if (!refundPublicKey || !lockupAddress || !vhtlcTimeouts)
|
|
3468
|
-
throw new Error(
|
|
3469
|
-
`Swap ${pendingSwap.id}: incomplete reverse swap response`
|
|
3470
|
-
);
|
|
3416
|
+
throw new Error(`Swap ${pendingSwap.id}: incomplete reverse swap response`);
|
|
3471
3417
|
const preimage = import_base9.hex.decode(pendingSwap.preimage);
|
|
3472
3418
|
const arkInfo = await this.arkProvider.getInfo();
|
|
3473
3419
|
const address = await this.wallet.getAddress();
|
|
@@ -3502,58 +3448,67 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3502
3448
|
throw new Error(
|
|
3503
3449
|
`Swap ${pendingSwap.id}: VHTLC address mismatch. Expected ${lockupAddress}, got ${vhtlcAddress}`
|
|
3504
3450
|
);
|
|
3505
|
-
let
|
|
3451
|
+
let unspentVtxos = [];
|
|
3452
|
+
let rawVtxos = [];
|
|
3506
3453
|
for (let attempt = 1; attempt <= CLAIM_VTXO_RETRY_ATTEMPTS; attempt++) {
|
|
3507
|
-
const
|
|
3454
|
+
const result = await this.indexerProvider.getVtxos({
|
|
3508
3455
|
scripts: [import_base9.hex.encode(vhtlcScript.pkScript)]
|
|
3509
3456
|
});
|
|
3510
|
-
|
|
3511
|
-
|
|
3457
|
+
rawVtxos = result.vtxos;
|
|
3458
|
+
unspentVtxos = result.vtxos.filter((vtxo) => !vtxo.isSpent);
|
|
3459
|
+
if (unspentVtxos.length > 0) {
|
|
3512
3460
|
break;
|
|
3513
3461
|
}
|
|
3514
3462
|
if (attempt < CLAIM_VTXO_RETRY_ATTEMPTS) {
|
|
3515
|
-
await new Promise(
|
|
3516
|
-
(resolve) => setTimeout(resolve, CLAIM_VTXO_RETRY_DELAY_MS)
|
|
3517
|
-
);
|
|
3463
|
+
await new Promise((resolve) => setTimeout(resolve, CLAIM_VTXO_RETRY_DELAY_MS));
|
|
3518
3464
|
}
|
|
3519
3465
|
}
|
|
3520
|
-
if (
|
|
3521
|
-
|
|
3522
|
-
`Swap ${pendingSwap.id}: no spendable virtual coins found`
|
|
3523
|
-
|
|
3524
|
-
}
|
|
3525
|
-
if (vtxo.isSpent) {
|
|
3466
|
+
if (unspentVtxos.length === 0) {
|
|
3467
|
+
if (rawVtxos.length === 0) {
|
|
3468
|
+
throw new Error(`Swap ${pendingSwap.id}: no spendable virtual coins found`);
|
|
3469
|
+
}
|
|
3526
3470
|
throw new Error(`Swap ${pendingSwap.id}: VHTLC is already spent`);
|
|
3527
3471
|
}
|
|
3528
|
-
const
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3472
|
+
const vhtlcIdentity = claimVHTLCIdentity(this.wallet.identity, preimage);
|
|
3473
|
+
const outputScript = import_sdk8.ArkAddress.decode(address).pkScript;
|
|
3474
|
+
const claimErrors = [];
|
|
3475
|
+
let usedOffchainClaim = false;
|
|
3476
|
+
for (const vtxo of unspentVtxos) {
|
|
3477
|
+
const input = {
|
|
3478
|
+
...vtxo,
|
|
3479
|
+
tapLeafScript: vhtlcScript.claim(),
|
|
3480
|
+
tapTree: vhtlcScript.encode()
|
|
3481
|
+
};
|
|
3482
|
+
const output = {
|
|
3483
|
+
amount: BigInt(vtxo.value),
|
|
3484
|
+
script: outputScript
|
|
3485
|
+
};
|
|
3486
|
+
try {
|
|
3487
|
+
if ((0, import_sdk8.isRecoverable)(vtxo)) {
|
|
3488
|
+
await this.joinBatch(vhtlcIdentity, input, output, arkInfo);
|
|
3489
|
+
} else {
|
|
3490
|
+
await claimVHTLCwithOffchainTx(
|
|
3491
|
+
vhtlcIdentity,
|
|
3492
|
+
vhtlcScript,
|
|
3493
|
+
serverXOnly,
|
|
3494
|
+
input,
|
|
3495
|
+
output,
|
|
3496
|
+
arkInfo,
|
|
3497
|
+
this.arkProvider
|
|
3498
|
+
);
|
|
3499
|
+
usedOffchainClaim = true;
|
|
3500
|
+
}
|
|
3501
|
+
} catch (error) {
|
|
3502
|
+
claimErrors.push({ vtxo, error });
|
|
3503
|
+
}
|
|
3504
|
+
}
|
|
3505
|
+
if (claimErrors.length > 0) {
|
|
3506
|
+
const details = claimErrors.map(({ vtxo, error }) => `${vtxo.txid}:${vtxo.vout} (${error.message})`).join("; ");
|
|
3507
|
+
throw new Error(
|
|
3508
|
+
`Swap ${pendingSwap.id}: failed to claim ${claimErrors.length}/${unspentVtxos.length} VTXOs: ${details}`
|
|
3554
3509
|
);
|
|
3555
|
-
finalStatus = (await this.getSwapStatus(pendingSwap.id)).status;
|
|
3556
3510
|
}
|
|
3511
|
+
const finalStatus = usedOffchainClaim ? (await this.getSwapStatus(pendingSwap.id)).status : "transaction.claimed";
|
|
3557
3512
|
await updateReverseSwapStatus(
|
|
3558
3513
|
pendingSwap,
|
|
3559
3514
|
finalStatus,
|
|
@@ -3656,9 +3611,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3656
3611
|
async sendLightningPayment(args) {
|
|
3657
3612
|
const pendingSwap = await this.createSubmarineSwap(args);
|
|
3658
3613
|
if (!pendingSwap.response.address)
|
|
3659
|
-
throw new Error(
|
|
3660
|
-
`Swap ${pendingSwap.id}: missing address in submarine swap response`
|
|
3661
|
-
);
|
|
3614
|
+
throw new Error(`Swap ${pendingSwap.id}: missing address in submarine swap response`);
|
|
3662
3615
|
await this.savePendingSubmarineSwap(pendingSwap);
|
|
3663
3616
|
const txid = await this.wallet.send({
|
|
3664
3617
|
address: pendingSwap.response.address,
|
|
@@ -3691,9 +3644,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3691
3644
|
* @throws {SwapError} If invoice is missing or key retrieval fails.
|
|
3692
3645
|
*/
|
|
3693
3646
|
async createSubmarineSwap(args) {
|
|
3694
|
-
const refundPublicKey = import_base9.hex.encode(
|
|
3695
|
-
await this.wallet.identity.compressedPublicKey()
|
|
3696
|
-
);
|
|
3647
|
+
const refundPublicKey = import_base9.hex.encode(await this.wallet.identity.compressedPublicKey());
|
|
3697
3648
|
if (!refundPublicKey)
|
|
3698
3649
|
throw new SwapError({
|
|
3699
3650
|
message: "Failed to get refund public key from wallet"
|
|
@@ -3731,9 +3682,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3731
3682
|
async buildSubmarineVHTLCContext(swap, arkInfo) {
|
|
3732
3683
|
const preimageHash = swap.request.invoice ? getInvoicePaymentHash(swap.request.invoice) : swap.preimageHash;
|
|
3733
3684
|
if (!preimageHash)
|
|
3734
|
-
throw new Error(
|
|
3735
|
-
`Swap ${swap.id}: preimage hash is required to refund VHTLC`
|
|
3736
|
-
);
|
|
3685
|
+
throw new Error(`Swap ${swap.id}: preimage hash is required to refund VHTLC`);
|
|
3737
3686
|
const resolvedArkInfo = arkInfo ?? await this.arkProvider.getInfo();
|
|
3738
3687
|
const ourXOnlyPublicKey = normalizeToXOnlyKey(
|
|
3739
3688
|
await this.wallet.identity.xOnlyPublicKey(),
|
|
@@ -3747,9 +3696,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3747
3696
|
);
|
|
3748
3697
|
const { claimPublicKey, timeoutBlockHeights: vhtlcTimeouts } = swap.response;
|
|
3749
3698
|
if (!claimPublicKey || !vhtlcTimeouts)
|
|
3750
|
-
throw new Error(
|
|
3751
|
-
`Swap ${swap.id}: incomplete submarine swap response`
|
|
3752
|
-
);
|
|
3699
|
+
throw new Error(`Swap ${swap.id}: incomplete submarine swap response`);
|
|
3753
3700
|
const boltzXOnlyPublicKey = normalizeToXOnlyKey(
|
|
3754
3701
|
import_base9.hex.decode(claimPublicKey),
|
|
3755
3702
|
"boltz",
|
|
@@ -3764,9 +3711,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3764
3711
|
timeoutBlockHeights: vhtlcTimeouts
|
|
3765
3712
|
});
|
|
3766
3713
|
if (!vhtlcScript.claimScript)
|
|
3767
|
-
throw new Error(
|
|
3768
|
-
`Swap ${swap.id}: failed to create VHTLC script for submarine swap`
|
|
3769
|
-
);
|
|
3714
|
+
throw new Error(`Swap ${swap.id}: failed to create VHTLC script for submarine swap`);
|
|
3770
3715
|
if (vhtlcAddress !== swap.response.address)
|
|
3771
3716
|
throw new Error(
|
|
3772
3717
|
`VHTLC address mismatch for swap ${swap.id}: expected ${swap.response.address}, got ${vhtlcAddress}`
|
|
@@ -3805,10 +3750,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3805
3750
|
recoverableOnly: true
|
|
3806
3751
|
})
|
|
3807
3752
|
]);
|
|
3808
|
-
const refundableVtxos = dedupeVtxos([
|
|
3809
|
-
...spendableResult.vtxos,
|
|
3810
|
-
...recoverableResult.vtxos
|
|
3811
|
-
]);
|
|
3753
|
+
const refundableVtxos = dedupeVtxos([...spendableResult.vtxos, ...recoverableResult.vtxos]);
|
|
3812
3754
|
let diagnostic;
|
|
3813
3755
|
if (refundableVtxos.length === 0) {
|
|
3814
3756
|
const { vtxos: allVtxos } = await this.indexerProvider.getVtxos({
|
|
@@ -3828,13 +3770,8 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3828
3770
|
submarineRecoveryInfoFromLookup(swap, lookup) {
|
|
3829
3771
|
const { refundableVtxos, diagnostic, vhtlcTimeouts } = lookup;
|
|
3830
3772
|
if (refundableVtxos.length > 0) {
|
|
3831
|
-
const cltvSatisfied = isSubmarineRefundLocktimeReached(
|
|
3832
|
-
|
|
3833
|
-
);
|
|
3834
|
-
const amountSats = refundableVtxos.reduce(
|
|
3835
|
-
(sum, vtxo) => sum + Number(vtxo.value),
|
|
3836
|
-
0
|
|
3837
|
-
);
|
|
3773
|
+
const cltvSatisfied = isSubmarineRefundLocktimeReached(vhtlcTimeouts.refund);
|
|
3774
|
+
const amountSats = refundableVtxos.reduce((sum, vtxo) => sum + Number(vtxo.value), 0);
|
|
3838
3775
|
const isRecoverable2 = cltvSatisfied || canRecoverViaBoltz3of3(refundableVtxos, swap);
|
|
3839
3776
|
return {
|
|
3840
3777
|
swap,
|
|
@@ -3898,19 +3835,13 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3898
3835
|
);
|
|
3899
3836
|
}
|
|
3900
3837
|
if (diagnostic.allSpent) {
|
|
3901
|
-
throw new Error(
|
|
3902
|
-
`Swap ${pendingSwap.id}: VHTLC is already spent`
|
|
3903
|
-
);
|
|
3838
|
+
throw new Error(`Swap ${pendingSwap.id}: VHTLC is already spent`);
|
|
3904
3839
|
}
|
|
3905
|
-
throw new Error(
|
|
3906
|
-
`Swap ${pendingSwap.id}: VHTLC has no refundable VTXOs yet`
|
|
3907
|
-
);
|
|
3840
|
+
throw new Error(`Swap ${pendingSwap.id}: VHTLC has no refundable VTXOs yet`);
|
|
3908
3841
|
}
|
|
3909
3842
|
const outputScript = import_sdk8.ArkAddress.decode(address).pkScript;
|
|
3910
3843
|
const refundWithoutReceiverLeaf = vhtlcScript.refundWithoutReceiver();
|
|
3911
|
-
const cltvSatisfied = isSubmarineRefundLocktimeReached(
|
|
3912
|
-
vhtlcTimeouts.refund
|
|
3913
|
-
);
|
|
3844
|
+
const cltvSatisfied = isSubmarineRefundLocktimeReached(vhtlcTimeouts.refund);
|
|
3914
3845
|
let boltzCallCount = 0;
|
|
3915
3846
|
let sweptCount = 0;
|
|
3916
3847
|
let skippedCount = 0;
|
|
@@ -3952,6 +3883,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3952
3883
|
if (boltzCallCount > 0) {
|
|
3953
3884
|
await new Promise((r) => setTimeout(r, 2e3));
|
|
3954
3885
|
}
|
|
3886
|
+
boltzCallCount++;
|
|
3955
3887
|
await refundVHTLCwithOffchainTx(
|
|
3956
3888
|
pendingSwap.id,
|
|
3957
3889
|
this.wallet.identity,
|
|
@@ -3962,11 +3894,8 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3962
3894
|
input,
|
|
3963
3895
|
output,
|
|
3964
3896
|
arkInfo,
|
|
3965
|
-
this.swapProvider.refundSubmarineSwap.bind(
|
|
3966
|
-
this.swapProvider
|
|
3967
|
-
)
|
|
3897
|
+
this.swapProvider.refundSubmarineSwap.bind(this.swapProvider)
|
|
3968
3898
|
);
|
|
3969
|
-
boltzCallCount++;
|
|
3970
3899
|
sweptCount++;
|
|
3971
3900
|
} catch (error) {
|
|
3972
3901
|
if (!(error instanceof BoltzRefundError)) {
|
|
@@ -3987,13 +3916,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
3987
3916
|
tapLeafScript: refundWithoutReceiverLeaf,
|
|
3988
3917
|
tapTree: vhtlcScript.encode()
|
|
3989
3918
|
};
|
|
3990
|
-
await this.joinBatch(
|
|
3991
|
-
this.wallet.identity,
|
|
3992
|
-
fallbackInput,
|
|
3993
|
-
output,
|
|
3994
|
-
arkInfo,
|
|
3995
|
-
false
|
|
3996
|
-
);
|
|
3919
|
+
await this.joinBatch(this.wallet.identity, fallbackInput, output, arkInfo, false);
|
|
3997
3920
|
sweptCount++;
|
|
3998
3921
|
}
|
|
3999
3922
|
}
|
|
@@ -4089,10 +4012,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4089
4012
|
try {
|
|
4090
4013
|
return {
|
|
4091
4014
|
swap,
|
|
4092
|
-
context: await this.buildSubmarineVHTLCContext(
|
|
4093
|
-
swap,
|
|
4094
|
-
arkInfo
|
|
4095
|
-
)
|
|
4015
|
+
context: await this.buildSubmarineVHTLCContext(swap, arkInfo)
|
|
4096
4016
|
};
|
|
4097
4017
|
} catch (err) {
|
|
4098
4018
|
return {
|
|
@@ -4105,9 +4025,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4105
4025
|
const valid = prepared.filter(
|
|
4106
4026
|
(item) => "context" in item
|
|
4107
4027
|
);
|
|
4108
|
-
const scripts = [
|
|
4109
|
-
...new Set(valid.map(({ context }) => context.vhtlcPkScriptHex))
|
|
4110
|
-
];
|
|
4028
|
+
const scripts = [...new Set(valid.map(({ context }) => context.vhtlcPkScriptHex))];
|
|
4111
4029
|
const refundableByScript = /* @__PURE__ */ new Map();
|
|
4112
4030
|
if (scripts.length > 0) {
|
|
4113
4031
|
const [spendableResult, recoverableResult] = await Promise.all([
|
|
@@ -4142,9 +4060,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4142
4060
|
error: item.error
|
|
4143
4061
|
};
|
|
4144
4062
|
}
|
|
4145
|
-
const refundableVtxos = refundableByScript.get(
|
|
4146
|
-
item.context.vhtlcPkScriptHex.toLowerCase()
|
|
4147
|
-
) ?? [];
|
|
4063
|
+
const refundableVtxos = refundableByScript.get(item.context.vhtlcPkScriptHex.toLowerCase()) ?? [];
|
|
4148
4064
|
return this.submarineRecoveryInfoFromLookup(item.swap, {
|
|
4149
4065
|
...item.context,
|
|
4150
4066
|
refundableVtxos
|
|
@@ -4323,9 +4239,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4323
4239
|
*/
|
|
4324
4240
|
async waitAndClaimBtc(pendingSwap) {
|
|
4325
4241
|
if (this.swapManager && await this.swapManager.hasSwap(pendingSwap.id)) {
|
|
4326
|
-
const { txid } = await this.swapManager.waitForSwapCompletion(
|
|
4327
|
-
pendingSwap.id
|
|
4328
|
-
);
|
|
4242
|
+
const { txid } = await this.swapManager.waitForSwapCompletion(pendingSwap.id);
|
|
4329
4243
|
return { txid };
|
|
4330
4244
|
}
|
|
4331
4245
|
return new Promise((resolve, reject) => {
|
|
@@ -4352,24 +4266,25 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4352
4266
|
}
|
|
4353
4267
|
case "transaction.claimed":
|
|
4354
4268
|
await updateSwapStatus();
|
|
4355
|
-
const claimedStatus = await this.getSwapStatus(
|
|
4356
|
-
pendingSwap.id
|
|
4357
|
-
);
|
|
4269
|
+
const claimedStatus = await this.getSwapStatus(pendingSwap.id);
|
|
4358
4270
|
resolve({
|
|
4359
4271
|
txid: claimedStatus.transaction?.id ?? ""
|
|
4360
4272
|
});
|
|
4361
4273
|
break;
|
|
4362
4274
|
case "transaction.lockupFailed":
|
|
4363
4275
|
await updateSwapStatus();
|
|
4364
|
-
await this.quoteSwap(swap.response.id).catch(
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4276
|
+
await this.quoteSwap(swap.response.id, quoteOptionsForSwap(swap)).catch(
|
|
4277
|
+
(err) => {
|
|
4278
|
+
reject(
|
|
4279
|
+
new SwapError({
|
|
4280
|
+
message: `Failed to renegotiate quote: ${err.message}`,
|
|
4281
|
+
isRefundable: true,
|
|
4282
|
+
pendingSwap: swap,
|
|
4283
|
+
cause: err
|
|
4284
|
+
})
|
|
4285
|
+
);
|
|
4286
|
+
}
|
|
4287
|
+
);
|
|
4373
4288
|
break;
|
|
4374
4289
|
case "swap.expired":
|
|
4375
4290
|
await updateSwapStatus();
|
|
@@ -4407,30 +4322,18 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4407
4322
|
*/
|
|
4408
4323
|
async claimBtc(pendingSwap) {
|
|
4409
4324
|
if (!pendingSwap.toAddress)
|
|
4410
|
-
throw new Error(
|
|
4411
|
-
`Swap ${pendingSwap.id}: destination address is required`
|
|
4412
|
-
);
|
|
4325
|
+
throw new Error(`Swap ${pendingSwap.id}: destination address is required`);
|
|
4413
4326
|
if (!pendingSwap.response.claimDetails.swapTree)
|
|
4414
|
-
throw new Error(
|
|
4415
|
-
`Swap ${pendingSwap.id}: missing swap tree in claim details`
|
|
4416
|
-
);
|
|
4327
|
+
throw new Error(`Swap ${pendingSwap.id}: missing swap tree in claim details`);
|
|
4417
4328
|
if (!pendingSwap.response.claimDetails.serverPublicKey)
|
|
4418
|
-
throw new Error(
|
|
4419
|
-
`Swap ${pendingSwap.id}: missing server public key in claim details`
|
|
4420
|
-
);
|
|
4329
|
+
throw new Error(`Swap ${pendingSwap.id}: missing server public key in claim details`);
|
|
4421
4330
|
const swapStatus = await this.getSwapStatus(pendingSwap.id);
|
|
4422
4331
|
if (!swapStatus.transaction?.hex)
|
|
4423
|
-
throw new Error(
|
|
4424
|
-
|
|
4425
|
-
);
|
|
4426
|
-
const lockupTx = import_btc_signer5.Transaction.fromRaw(
|
|
4427
|
-
import_base9.hex.decode(swapStatus.transaction.hex)
|
|
4428
|
-
);
|
|
4332
|
+
throw new Error(`Swap ${pendingSwap.id}: BTC transaction hex is required`);
|
|
4333
|
+
const lockupTx = import_btc_signer5.Transaction.fromRaw(import_base9.hex.decode(swapStatus.transaction.hex));
|
|
4429
4334
|
const arkInfo = await this.arkProvider.getInfo();
|
|
4430
4335
|
const network = arkInfo.network === "bitcoin" ? import_utils4.NETWORK : arkInfo.network === "mutinynet" ? MUTINYNET_NETWORK : REGTEST_NETWORK;
|
|
4431
|
-
const swapTree = deserializeSwapTree(
|
|
4432
|
-
pendingSwap.response.claimDetails.swapTree
|
|
4433
|
-
);
|
|
4336
|
+
const swapTree = deserializeSwapTree(pendingSwap.response.claimDetails.swapTree);
|
|
4434
4337
|
const musig = tweakMusig(
|
|
4435
4338
|
create(import_base9.hex.decode(pendingSwap.ephemeralKey), [
|
|
4436
4339
|
import_base9.hex.decode(pendingSwap.response.claimDetails.serverPublicKey),
|
|
@@ -4451,19 +4354,14 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4451
4354
|
vout: swapOutput.vout,
|
|
4452
4355
|
transactionId: lockupTx.id
|
|
4453
4356
|
},
|
|
4454
|
-
import_btc_signer5.OutScript.encode(
|
|
4455
|
-
(0, import_btc_signer5.Address)(network).decode(pendingSwap.toAddress)
|
|
4456
|
-
),
|
|
4357
|
+
import_btc_signer5.OutScript.encode((0, import_btc_signer5.Address)(network).decode(pendingSwap.toAddress)),
|
|
4457
4358
|
feeToDeliverExactAmount > fee ? feeToDeliverExactAmount : fee
|
|
4458
4359
|
)
|
|
4459
4360
|
);
|
|
4460
4361
|
const musigMessage = musig.message(
|
|
4461
|
-
claimTx.preimageWitnessV1(
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
import_btc_signer5.SigHash.DEFAULT,
|
|
4465
|
-
[swapOutput.amount]
|
|
4466
|
-
)
|
|
4362
|
+
claimTx.preimageWitnessV1(0, [swapOutput.script], import_btc_signer5.SigHash.DEFAULT, [
|
|
4363
|
+
swapOutput.amount
|
|
4364
|
+
])
|
|
4467
4365
|
).generateNonce();
|
|
4468
4366
|
const signedTxData = await this.swapProvider.postChainClaimDetails(
|
|
4469
4367
|
pendingSwap.response.id,
|
|
@@ -4477,14 +4375,10 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4477
4375
|
}
|
|
4478
4376
|
);
|
|
4479
4377
|
if (!signedTxData.pubNonce || !signedTxData.partialSignature)
|
|
4480
|
-
throw new Error(
|
|
4481
|
-
`Swap ${pendingSwap.id}: invalid signature data from server`
|
|
4482
|
-
);
|
|
4378
|
+
throw new Error(`Swap ${pendingSwap.id}: invalid signature data from server`);
|
|
4483
4379
|
const musigSession = musigMessage.aggregateNonces([
|
|
4484
4380
|
[
|
|
4485
|
-
import_base9.hex.decode(
|
|
4486
|
-
pendingSwap.response.claimDetails.serverPublicKey
|
|
4487
|
-
),
|
|
4381
|
+
import_base9.hex.decode(pendingSwap.response.claimDetails.serverPublicKey),
|
|
4488
4382
|
import_base9.hex.decode(signedTxData.pubNonce)
|
|
4489
4383
|
]
|
|
4490
4384
|
]).initializeSession();
|
|
@@ -4499,18 +4393,23 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4499
4393
|
await this.swapProvider.postBtcTransaction(claimTx.hex);
|
|
4500
4394
|
}
|
|
4501
4395
|
/**
|
|
4502
|
-
* When an ARK to BTC swap fails, refund
|
|
4396
|
+
* When an ARK to BTC swap fails, refund every unspent VTXO at the chain
|
|
4397
|
+
* swap's ARK lockup address.
|
|
4398
|
+
*
|
|
4399
|
+
* Path selection per VTXO:
|
|
4400
|
+
* - CLTV has elapsed → `refundWithoutReceiver` via `joinBatch` (no Boltz).
|
|
4401
|
+
* - Pre-CLTV recoverable → skipped (Boltz can't co-sign swept-batch refund).
|
|
4402
|
+
* - Pre-CLTV non-recoverable → cooperative 3-of-3 refund via Boltz.
|
|
4403
|
+
*
|
|
4503
4404
|
* @param pendingSwap - The pending chain swap to refund.
|
|
4405
|
+
* @returns Counts of VTXOs swept vs. deferred. A `swept: 0` outcome means
|
|
4406
|
+
* the call was a no-op — callers should retry after CLTV.
|
|
4504
4407
|
*/
|
|
4505
4408
|
async refundArk(pendingSwap) {
|
|
4506
4409
|
if (!pendingSwap.response.lockupDetails.serverPublicKey)
|
|
4507
|
-
throw new Error(
|
|
4508
|
-
`Swap ${pendingSwap.id}: missing server public key in lockup details`
|
|
4509
|
-
);
|
|
4410
|
+
throw new Error(`Swap ${pendingSwap.id}: missing server public key in lockup details`);
|
|
4510
4411
|
if (!pendingSwap.response.lockupDetails.timeouts)
|
|
4511
|
-
throw new Error(
|
|
4512
|
-
`Swap ${pendingSwap.id}: missing timeouts in lockup details`
|
|
4513
|
-
);
|
|
4412
|
+
throw new Error(`Swap ${pendingSwap.id}: missing timeouts in lockup details`);
|
|
4514
4413
|
const arkInfo = await this.arkProvider.getInfo();
|
|
4515
4414
|
const address = await this.wallet.getAddress();
|
|
4516
4415
|
const ourXOnlyPublicKey = normalizeToXOnlyKey(
|
|
@@ -4528,21 +4427,6 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4528
4427
|
"boltz",
|
|
4529
4428
|
pendingSwap.id
|
|
4530
4429
|
);
|
|
4531
|
-
const vhtlcPkScript = import_sdk8.ArkAddress.decode(
|
|
4532
|
-
pendingSwap.response.lockupDetails.lockupAddress
|
|
4533
|
-
).pkScript;
|
|
4534
|
-
const { vtxos } = await this.indexerProvider.getVtxos({
|
|
4535
|
-
scripts: [import_base9.hex.encode(vhtlcPkScript)]
|
|
4536
|
-
});
|
|
4537
|
-
if (vtxos.length === 0) {
|
|
4538
|
-
throw new Error(
|
|
4539
|
-
`Swap ${pendingSwap.id}: VHTLC not found for address ${pendingSwap.response.lockupDetails.lockupAddress}`
|
|
4540
|
-
);
|
|
4541
|
-
}
|
|
4542
|
-
const vtxo = vtxos[0];
|
|
4543
|
-
if (vtxo.isSpent) {
|
|
4544
|
-
throw new Error(`Swap ${pendingSwap.id}: VHTLC is already spent`);
|
|
4545
|
-
}
|
|
4546
4430
|
const { vhtlcAddress, vhtlcScript } = this.createVHTLCScript({
|
|
4547
4431
|
network: arkInfo.network,
|
|
4548
4432
|
preimageHash: import_base9.hex.decode(pendingSwap.request.preimageHash),
|
|
@@ -4552,45 +4436,111 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4552
4436
|
timeoutBlockHeights: pendingSwap.response.lockupDetails.timeouts
|
|
4553
4437
|
});
|
|
4554
4438
|
if (!vhtlcScript.refundScript)
|
|
4555
|
-
throw new Error(
|
|
4556
|
-
`Swap ${pendingSwap.id}: failed to create VHTLC script for chain swap`
|
|
4557
|
-
);
|
|
4439
|
+
throw new Error(`Swap ${pendingSwap.id}: failed to create VHTLC script for chain swap`);
|
|
4558
4440
|
if (pendingSwap.response.lockupDetails.lockupAddress !== vhtlcAddress) {
|
|
4559
4441
|
throw new SwapError({
|
|
4560
4442
|
message: "Unable to claim: invalid VHTLC address"
|
|
4561
4443
|
});
|
|
4562
4444
|
}
|
|
4563
|
-
const
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
const output = {
|
|
4570
|
-
amount: BigInt(vtxo.value),
|
|
4571
|
-
script: import_sdk8.ArkAddress.decode(address).pkScript
|
|
4572
|
-
};
|
|
4573
|
-
if (isRecoverableVtxo) {
|
|
4574
|
-
await this.joinBatch(this.wallet.identity, input, output, arkInfo);
|
|
4575
|
-
} else {
|
|
4576
|
-
await refundVHTLCwithOffchainTx(
|
|
4577
|
-
pendingSwap.id,
|
|
4578
|
-
this.wallet.identity,
|
|
4579
|
-
this.arkProvider,
|
|
4580
|
-
boltzXOnlyPublicKey,
|
|
4581
|
-
ourXOnlyPublicKey,
|
|
4582
|
-
serverXOnlyPublicKey,
|
|
4583
|
-
input,
|
|
4584
|
-
output,
|
|
4585
|
-
arkInfo,
|
|
4586
|
-
this.swapProvider.refundChainSwap.bind(this.swapProvider)
|
|
4445
|
+
const { vtxos } = await this.indexerProvider.getVtxos({
|
|
4446
|
+
scripts: [import_base9.hex.encode(vhtlcScript.pkScript)]
|
|
4447
|
+
});
|
|
4448
|
+
if (vtxos.length === 0) {
|
|
4449
|
+
throw new Error(
|
|
4450
|
+
`Swap ${pendingSwap.id}: VHTLC not found for address ${pendingSwap.response.lockupDetails.lockupAddress}`
|
|
4587
4451
|
);
|
|
4588
4452
|
}
|
|
4453
|
+
const unspentVtxos = vtxos.filter((vtxo) => !vtxo.isSpent);
|
|
4454
|
+
if (unspentVtxos.length === 0) {
|
|
4455
|
+
throw new Error(`Swap ${pendingSwap.id}: VHTLC is already spent`);
|
|
4456
|
+
}
|
|
4457
|
+
const outputScript = import_sdk8.ArkAddress.decode(address).pkScript;
|
|
4458
|
+
const refundWithoutReceiverLeaf = vhtlcScript.refundWithoutReceiver();
|
|
4459
|
+
const refundLocktime = pendingSwap.response.lockupDetails.timeouts.refund;
|
|
4460
|
+
let boltzCallCount = 0;
|
|
4461
|
+
let sweptCount = 0;
|
|
4462
|
+
let skippedCount = 0;
|
|
4463
|
+
for (const vtxo of unspentVtxos) {
|
|
4464
|
+
const isRecoverableVtxo = (0, import_sdk8.isRecoverable)(vtxo);
|
|
4465
|
+
const output = {
|
|
4466
|
+
amount: BigInt(vtxo.value),
|
|
4467
|
+
script: outputScript
|
|
4468
|
+
};
|
|
4469
|
+
if (isSubmarineRefundLocktimeReached(refundLocktime)) {
|
|
4470
|
+
const input2 = {
|
|
4471
|
+
...vtxo,
|
|
4472
|
+
tapLeafScript: refundWithoutReceiverLeaf,
|
|
4473
|
+
tapTree: vhtlcScript.encode()
|
|
4474
|
+
};
|
|
4475
|
+
await this.joinBatch(
|
|
4476
|
+
this.wallet.identity,
|
|
4477
|
+
input2,
|
|
4478
|
+
output,
|
|
4479
|
+
arkInfo,
|
|
4480
|
+
isRecoverableVtxo
|
|
4481
|
+
);
|
|
4482
|
+
sweptCount++;
|
|
4483
|
+
continue;
|
|
4484
|
+
}
|
|
4485
|
+
if (isRecoverableVtxo) {
|
|
4486
|
+
logger.error(
|
|
4487
|
+
`Swap ${pendingSwap.id}: recoverable VTXO ${vtxo.txid}:${vtxo.vout} cannot be refunded yet \u2014 refundWithoutReceiver locktime has not passed (refundLocktime=${refundLocktime}, currentTimestamp=${Math.floor(Date.now() / 1e3)}). Refund will be retried after locktime.`
|
|
4488
|
+
);
|
|
4489
|
+
skippedCount++;
|
|
4490
|
+
continue;
|
|
4491
|
+
}
|
|
4492
|
+
const input = {
|
|
4493
|
+
...vtxo,
|
|
4494
|
+
tapLeafScript: vhtlcScript.refund(),
|
|
4495
|
+
tapTree: vhtlcScript.encode()
|
|
4496
|
+
};
|
|
4497
|
+
try {
|
|
4498
|
+
if (boltzCallCount > 0) {
|
|
4499
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
4500
|
+
}
|
|
4501
|
+
boltzCallCount++;
|
|
4502
|
+
await refundVHTLCwithOffchainTx(
|
|
4503
|
+
pendingSwap.id,
|
|
4504
|
+
this.wallet.identity,
|
|
4505
|
+
this.arkProvider,
|
|
4506
|
+
boltzXOnlyPublicKey,
|
|
4507
|
+
ourXOnlyPublicKey,
|
|
4508
|
+
serverXOnlyPublicKey,
|
|
4509
|
+
input,
|
|
4510
|
+
output,
|
|
4511
|
+
arkInfo,
|
|
4512
|
+
this.swapProvider.refundChainSwap.bind(this.swapProvider)
|
|
4513
|
+
);
|
|
4514
|
+
sweptCount++;
|
|
4515
|
+
} catch (error) {
|
|
4516
|
+
if (!(error instanceof BoltzRefundError)) {
|
|
4517
|
+
throw error;
|
|
4518
|
+
}
|
|
4519
|
+
if (!isSubmarineRefundLocktimeReached(refundLocktime)) {
|
|
4520
|
+
logger.error(
|
|
4521
|
+
`Swap ${pendingSwap.id}: Boltz rejected VTXO outpoint and refundWithoutReceiver locktime has not passed yet (currentTimestamp=${Math.floor(Date.now() / 1e3)}, locktime=${refundLocktime}). Refund will be retried after locktime.`
|
|
4522
|
+
);
|
|
4523
|
+
skippedCount++;
|
|
4524
|
+
continue;
|
|
4525
|
+
}
|
|
4526
|
+
logger.warn(
|
|
4527
|
+
`Swap ${pendingSwap.id}: Boltz rejected VTXO outpoint, falling back to refundWithoutReceiver via joinBatch`
|
|
4528
|
+
);
|
|
4529
|
+
const fallbackInput = {
|
|
4530
|
+
...vtxo,
|
|
4531
|
+
tapLeafScript: refundWithoutReceiverLeaf,
|
|
4532
|
+
tapTree: vhtlcScript.encode()
|
|
4533
|
+
};
|
|
4534
|
+
await this.joinBatch(this.wallet.identity, fallbackInput, output, arkInfo, false);
|
|
4535
|
+
sweptCount++;
|
|
4536
|
+
}
|
|
4537
|
+
}
|
|
4589
4538
|
const finalStatus = await this.getSwapStatus(pendingSwap.id);
|
|
4590
4539
|
await this.savePendingChainSwap({
|
|
4591
4540
|
...pendingSwap,
|
|
4592
4541
|
status: finalStatus.status
|
|
4593
4542
|
});
|
|
4543
|
+
return { swept: sweptCount, skipped: skippedCount };
|
|
4594
4544
|
}
|
|
4595
4545
|
// =========================================================================
|
|
4596
4546
|
// Chain swaps: BTC -> ARK
|
|
@@ -4635,9 +4585,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4635
4585
|
*/
|
|
4636
4586
|
async waitAndClaimArk(pendingSwap) {
|
|
4637
4587
|
if (this.swapManager && await this.swapManager.hasSwap(pendingSwap.id)) {
|
|
4638
|
-
const { txid } = await this.swapManager.waitForSwapCompletion(
|
|
4639
|
-
pendingSwap.id
|
|
4640
|
-
);
|
|
4588
|
+
const { txid } = await this.swapManager.waitForSwapCompletion(pendingSwap.id);
|
|
4641
4589
|
return { txid };
|
|
4642
4590
|
}
|
|
4643
4591
|
return new Promise((resolve, reject) => {
|
|
@@ -4658,37 +4606,33 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4658
4606
|
break;
|
|
4659
4607
|
case "transaction.claimed":
|
|
4660
4608
|
await updateSwapStatus();
|
|
4661
|
-
const claimedStatus = await this.getSwapStatus(
|
|
4662
|
-
pendingSwap.id
|
|
4663
|
-
);
|
|
4609
|
+
const claimedStatus = await this.getSwapStatus(pendingSwap.id);
|
|
4664
4610
|
resolve({
|
|
4665
4611
|
txid: claimedStatus.transaction?.id ?? ""
|
|
4666
4612
|
});
|
|
4667
4613
|
break;
|
|
4668
4614
|
case "transaction.claim.pending":
|
|
4669
4615
|
await updateSwapStatus();
|
|
4670
|
-
await this.signCooperativeClaimForServer(swap).catch(
|
|
4616
|
+
await this.signCooperativeClaimForServer(swap).catch((err) => {
|
|
4617
|
+
logger.error(`Failed to sign cooperative claim for ${swap.id}:`, err);
|
|
4618
|
+
});
|
|
4619
|
+
break;
|
|
4620
|
+
case "transaction.lockupFailed":
|
|
4621
|
+
await updateSwapStatus();
|
|
4622
|
+
await this.quoteSwap(swap.response.id, quoteOptionsForSwap(swap)).catch(
|
|
4671
4623
|
(err) => {
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4624
|
+
reject(
|
|
4625
|
+
new SwapError({
|
|
4626
|
+
message: `Failed to renegotiate quote: ${err.message}`,
|
|
4627
|
+
isRefundable: false,
|
|
4628
|
+
// TODO btc refund not implemented yet
|
|
4629
|
+
pendingSwap: swap,
|
|
4630
|
+
cause: err
|
|
4631
|
+
})
|
|
4675
4632
|
);
|
|
4676
4633
|
}
|
|
4677
4634
|
);
|
|
4678
4635
|
break;
|
|
4679
|
-
case "transaction.lockupFailed":
|
|
4680
|
-
await updateSwapStatus();
|
|
4681
|
-
await this.quoteSwap(swap.response.id).catch((err) => {
|
|
4682
|
-
reject(
|
|
4683
|
-
new SwapError({
|
|
4684
|
-
message: `Failed to renegotiate quote: ${err.message}`,
|
|
4685
|
-
isRefundable: false,
|
|
4686
|
-
// TODO btc refund not implemented yet
|
|
4687
|
-
pendingSwap: swap
|
|
4688
|
-
})
|
|
4689
|
-
);
|
|
4690
|
-
});
|
|
4691
|
-
break;
|
|
4692
4636
|
case "swap.expired":
|
|
4693
4637
|
await updateSwapStatus();
|
|
4694
4638
|
reject(
|
|
@@ -4728,17 +4672,11 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4728
4672
|
*/
|
|
4729
4673
|
async claimArk(pendingSwap) {
|
|
4730
4674
|
if (!pendingSwap.toAddress)
|
|
4731
|
-
throw new Error(
|
|
4732
|
-
`Swap ${pendingSwap.id}: destination address is required`
|
|
4733
|
-
);
|
|
4675
|
+
throw new Error(`Swap ${pendingSwap.id}: destination address is required`);
|
|
4734
4676
|
if (!pendingSwap.response.claimDetails.serverPublicKey)
|
|
4735
|
-
throw new Error(
|
|
4736
|
-
`Swap ${pendingSwap.id}: missing server public key in claim details`
|
|
4737
|
-
);
|
|
4677
|
+
throw new Error(`Swap ${pendingSwap.id}: missing server public key in claim details`);
|
|
4738
4678
|
if (!pendingSwap.response.claimDetails.timeouts)
|
|
4739
|
-
throw new Error(
|
|
4740
|
-
`Swap ${pendingSwap.id}: missing timeouts in claim details`
|
|
4741
|
-
);
|
|
4679
|
+
throw new Error(`Swap ${pendingSwap.id}: missing timeouts in claim details`);
|
|
4742
4680
|
const arkInfo = await this.arkProvider.getInfo();
|
|
4743
4681
|
const preimage = import_base9.hex.decode(pendingSwap.preimage);
|
|
4744
4682
|
const address = await this.wallet.getAddress();
|
|
@@ -4750,10 +4688,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4750
4688
|
pendingSwap.response.claimDetails.serverPublicKey,
|
|
4751
4689
|
"sender"
|
|
4752
4690
|
);
|
|
4753
|
-
const serverXOnlyPublicKey = normalizeToXOnlyKey(
|
|
4754
|
-
arkInfo.signerPubkey,
|
|
4755
|
-
"server"
|
|
4756
|
-
);
|
|
4691
|
+
const serverXOnlyPublicKey = normalizeToXOnlyKey(arkInfo.signerPubkey, "server");
|
|
4757
4692
|
const { vhtlcAddress, vhtlcScript } = this.createVHTLCScript({
|
|
4758
4693
|
network: arkInfo.network,
|
|
4759
4694
|
preimageHash: import_base9.hex.decode(pendingSwap.request.preimageHash),
|
|
@@ -4763,9 +4698,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4763
4698
|
timeoutBlockHeights: pendingSwap.response.claimDetails.timeouts
|
|
4764
4699
|
});
|
|
4765
4700
|
if (!vhtlcScript.claimScript)
|
|
4766
|
-
throw new Error(
|
|
4767
|
-
`Swap ${pendingSwap.id}: failed to create VHTLC script for chain swap`
|
|
4768
|
-
);
|
|
4701
|
+
throw new Error(`Swap ${pendingSwap.id}: failed to create VHTLC script for chain swap`);
|
|
4769
4702
|
if (pendingSwap.response.claimDetails.lockupAddress !== vhtlcAddress) {
|
|
4770
4703
|
throw new SwapError({
|
|
4771
4704
|
message: "Unable to claim: invalid VHTLC address"
|
|
@@ -4782,15 +4715,11 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4782
4715
|
break;
|
|
4783
4716
|
}
|
|
4784
4717
|
if (attempt < CLAIM_VTXO_RETRY_ATTEMPTS) {
|
|
4785
|
-
await new Promise(
|
|
4786
|
-
(resolve) => setTimeout(resolve, CLAIM_VTXO_RETRY_DELAY_MS)
|
|
4787
|
-
);
|
|
4718
|
+
await new Promise((resolve) => setTimeout(resolve, CLAIM_VTXO_RETRY_DELAY_MS));
|
|
4788
4719
|
}
|
|
4789
4720
|
}
|
|
4790
4721
|
if (!vtxo) {
|
|
4791
|
-
throw new Error(
|
|
4792
|
-
`Swap ${pendingSwap.id}: no spendable virtual coins found`
|
|
4793
|
-
);
|
|
4722
|
+
throw new Error(`Swap ${pendingSwap.id}: no spendable virtual coins found`);
|
|
4794
4723
|
}
|
|
4795
4724
|
const input = {
|
|
4796
4725
|
...vtxo,
|
|
@@ -4801,10 +4730,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4801
4730
|
amount: BigInt(vtxo.value),
|
|
4802
4731
|
script: import_sdk8.ArkAddress.decode(address).pkScript
|
|
4803
4732
|
};
|
|
4804
|
-
const vhtlcIdentity = claimVHTLCIdentity(
|
|
4805
|
-
this.wallet.identity,
|
|
4806
|
-
preimage
|
|
4807
|
-
);
|
|
4733
|
+
const vhtlcIdentity = claimVHTLCIdentity(this.wallet.identity, preimage);
|
|
4808
4734
|
if ((0, import_sdk8.isRecoverable)(vtxo)) {
|
|
4809
4735
|
await this.joinBatch(vhtlcIdentity, input, output, arkInfo);
|
|
4810
4736
|
} else {
|
|
@@ -4830,16 +4756,10 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4830
4756
|
*/
|
|
4831
4757
|
async signCooperativeClaimForServer(pendingSwap) {
|
|
4832
4758
|
if (!pendingSwap.response.lockupDetails.swapTree)
|
|
4833
|
-
throw new Error(
|
|
4834
|
-
`Swap ${pendingSwap.id}: missing swap tree in lockup details`
|
|
4835
|
-
);
|
|
4759
|
+
throw new Error(`Swap ${pendingSwap.id}: missing swap tree in lockup details`);
|
|
4836
4760
|
if (!pendingSwap.response.lockupDetails.serverPublicKey)
|
|
4837
|
-
throw new Error(
|
|
4838
|
-
|
|
4839
|
-
);
|
|
4840
|
-
const claimDetails = await this.swapProvider.getChainClaimDetails(
|
|
4841
|
-
pendingSwap.id
|
|
4842
|
-
);
|
|
4761
|
+
throw new Error(`Swap ${pendingSwap.id}: missing server public key in lockup details`);
|
|
4762
|
+
const claimDetails = await this.swapProvider.getChainClaimDetails(pendingSwap.id);
|
|
4843
4763
|
const serverPubKey = pendingSwap.response.lockupDetails.serverPublicKey;
|
|
4844
4764
|
if (claimDetails.publicKey !== serverPubKey) {
|
|
4845
4765
|
throw new Error(
|
|
@@ -4855,9 +4775,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4855
4775
|
);
|
|
4856
4776
|
const musigNonces = musig.message(import_base9.hex.decode(claimDetails.transactionHash)).generateNonce().aggregateNonces([
|
|
4857
4777
|
[
|
|
4858
|
-
import_base9.hex.decode(
|
|
4859
|
-
pendingSwap.response.lockupDetails.serverPublicKey
|
|
4860
|
-
),
|
|
4778
|
+
import_base9.hex.decode(pendingSwap.response.lockupDetails.serverPublicKey),
|
|
4861
4779
|
import_base9.hex.decode(claimDetails.pubNonce)
|
|
4862
4780
|
]
|
|
4863
4781
|
]).initializeSession();
|
|
@@ -4876,10 +4794,8 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4876
4794
|
* @returns The transaction ID of the claim.
|
|
4877
4795
|
*/
|
|
4878
4796
|
async waitAndClaimChain(pendingSwap) {
|
|
4879
|
-
if (pendingSwap.request.to === "ARK")
|
|
4880
|
-
|
|
4881
|
-
if (pendingSwap.request.to === "BTC")
|
|
4882
|
-
return this.waitAndClaimBtc(pendingSwap);
|
|
4797
|
+
if (pendingSwap.request.to === "ARK") return this.waitAndClaimArk(pendingSwap);
|
|
4798
|
+
if (pendingSwap.request.to === "BTC") return this.waitAndClaimBtc(pendingSwap);
|
|
4883
4799
|
throw new SwapError({
|
|
4884
4800
|
message: `Unsupported swap destination: ${pendingSwap.request.to}`
|
|
4885
4801
|
});
|
|
@@ -4894,11 +4810,9 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4894
4810
|
*/
|
|
4895
4811
|
async createChainSwap(args) {
|
|
4896
4812
|
const { to, from, receiverLockAmount, senderLockAmount, toAddress } = args;
|
|
4897
|
-
if (!toAddress)
|
|
4898
|
-
throw new SwapError({ message: "Destination address is required" });
|
|
4813
|
+
if (!toAddress) throw new SwapError({ message: "Destination address is required" });
|
|
4899
4814
|
const feeSatsPerByte = args.feeSatsPerByte ?? 1;
|
|
4900
|
-
if (feeSatsPerByte <= 0)
|
|
4901
|
-
throw new SwapError({ message: "Invalid feeSatsPerByte" });
|
|
4815
|
+
if (feeSatsPerByte <= 0) throw new SwapError({ message: "Invalid feeSatsPerByte" });
|
|
4902
4816
|
let amount, serverLockAmount, userLockAmount;
|
|
4903
4817
|
if (receiverLockAmount) {
|
|
4904
4818
|
amount = receiverLockAmount;
|
|
@@ -4913,8 +4827,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4913
4827
|
}
|
|
4914
4828
|
const preimage = (0, import_utils3.randomBytes)(32);
|
|
4915
4829
|
const preimageHash = import_base9.hex.encode((0, import_sha23.sha256)(preimage));
|
|
4916
|
-
if (!preimageHash)
|
|
4917
|
-
throw new SwapError({ message: "Failed to get preimage hash" });
|
|
4830
|
+
if (!preimageHash) throw new SwapError({ message: "Failed to get preimage hash" });
|
|
4918
4831
|
const ephemeralKey = import_secp256k13.secp256k1.utils.randomSecretKey();
|
|
4919
4832
|
const refundPublicKey = to === "ARK" ? import_base9.hex.encode(import_secp256k13.secp256k1.getPublicKey(ephemeralKey)) : import_base9.hex.encode(await this.wallet.identity.compressedPublicKey());
|
|
4920
4833
|
if (!refundPublicKey)
|
|
@@ -4963,30 +4876,20 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
4963
4876
|
const { to, from, swap, arkInfo } = args;
|
|
4964
4877
|
if (from === "ARK") {
|
|
4965
4878
|
if (!swap.response.lockupDetails.serverPublicKey)
|
|
4966
|
-
throw new Error(
|
|
4967
|
-
`Swap ${swap.id}: missing serverPublicKey in lockup details`
|
|
4968
|
-
);
|
|
4879
|
+
throw new Error(`Swap ${swap.id}: missing serverPublicKey in lockup details`);
|
|
4969
4880
|
if (!swap.response.lockupDetails.timeouts)
|
|
4970
|
-
throw new Error(
|
|
4971
|
-
`Swap ${swap.id}: missing timeouts in lockup details`
|
|
4972
|
-
);
|
|
4881
|
+
throw new Error(`Swap ${swap.id}: missing timeouts in lockup details`);
|
|
4973
4882
|
}
|
|
4974
4883
|
if (to === "ARK") {
|
|
4975
4884
|
if (!swap.response.claimDetails.serverPublicKey)
|
|
4976
|
-
throw new Error(
|
|
4977
|
-
`Swap ${swap.id}: missing serverPublicKey in claim details`
|
|
4978
|
-
);
|
|
4885
|
+
throw new Error(`Swap ${swap.id}: missing serverPublicKey in claim details`);
|
|
4979
4886
|
if (!swap.response.claimDetails.timeouts)
|
|
4980
|
-
throw new Error(
|
|
4981
|
-
`Swap ${swap.id}: missing timeouts in claim details`
|
|
4982
|
-
);
|
|
4887
|
+
throw new Error(`Swap ${swap.id}: missing timeouts in claim details`);
|
|
4983
4888
|
}
|
|
4984
4889
|
const lockupAddress = to === "ARK" ? swap.response.claimDetails.lockupAddress : swap.response.lockupDetails.lockupAddress;
|
|
4985
4890
|
const receiverPubkey = to === "ARK" ? swap.request.claimPublicKey : swap.response.lockupDetails.serverPublicKey;
|
|
4986
4891
|
const senderPubkey = to === "ARK" ? swap.response.claimDetails.serverPublicKey : swap.request.refundPublicKey;
|
|
4987
|
-
const serverPubkey = import_base9.hex.encode(
|
|
4988
|
-
normalizeToXOnlyKey(arkInfo.signerPubkey, "server")
|
|
4989
|
-
);
|
|
4892
|
+
const serverPubkey = import_base9.hex.encode(normalizeToXOnlyKey(arkInfo.signerPubkey, "server"));
|
|
4990
4893
|
const vhtlcTimeouts = to === "ARK" ? swap.response.claimDetails.timeouts : swap.response.lockupDetails.timeouts;
|
|
4991
4894
|
const { vhtlcAddress } = this.createVHTLCScript({
|
|
4992
4895
|
network: arkInfo.network,
|
|
@@ -5004,15 +4907,122 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
5004
4907
|
return true;
|
|
5005
4908
|
}
|
|
5006
4909
|
/**
|
|
5007
|
-
* Renegotiates the quote for an existing swap.
|
|
4910
|
+
* Renegotiates the quote for an existing chain swap. Convenience wrapper
|
|
4911
|
+
* over `getSwapQuote` + `acceptSwapQuote` with a safety floor.
|
|
4912
|
+
*
|
|
4913
|
+
* The floor is resolved in order:
|
|
4914
|
+
* 1. `options.minAcceptableAmount` if provided.
|
|
4915
|
+
* 2. The original `response.claimDetails.amount` of the stored
|
|
4916
|
+
* pending swap (Boltz-confirmed server-lock amount at creation).
|
|
4917
|
+
* 3. Otherwise throws `QuoteRejectedError({ reason: "no_baseline" })`.
|
|
4918
|
+
*
|
|
4919
|
+
* `options.maxSlippageBps` (default 0) relaxes the floor by basis points.
|
|
4920
|
+
* Quotes ≤ 0 are always rejected. On rejection the acceptance is NOT
|
|
4921
|
+
* posted to Boltz.
|
|
4922
|
+
*
|
|
4923
|
+
* Prefer `getSwapQuote` / `acceptSwapQuote` for callers that want to
|
|
4924
|
+
* inspect the quote before committing.
|
|
4925
|
+
*
|
|
5008
4926
|
* @param swapId - The ID of the swap.
|
|
4927
|
+
* @param options - Optional floor and slippage configuration.
|
|
5009
4928
|
* @returns The accepted quote amount.
|
|
4929
|
+
* @throws QuoteRejectedError if the quote is non-positive, below the
|
|
4930
|
+
* effective floor, or no baseline is available.
|
|
4931
|
+
*/
|
|
4932
|
+
async quoteSwap(swapId, options) {
|
|
4933
|
+
const effectiveFloor = await this.resolveEffectiveFloor(swapId, options);
|
|
4934
|
+
const amount = await this.getSwapQuote(swapId);
|
|
4935
|
+
this.validateQuote(amount, effectiveFloor);
|
|
4936
|
+
await this.swapProvider.postChainQuote(swapId, { amount });
|
|
4937
|
+
return amount;
|
|
4938
|
+
}
|
|
4939
|
+
/**
|
|
4940
|
+
* Fetches a renegotiated quote from Boltz without accepting it.
|
|
4941
|
+
* Pair with `acceptSwapQuote` to commit a specific value.
|
|
5010
4942
|
*/
|
|
5011
|
-
async
|
|
4943
|
+
async getSwapQuote(swapId) {
|
|
5012
4944
|
const { amount } = await this.swapProvider.getChainQuote(swapId);
|
|
4945
|
+
return amount;
|
|
4946
|
+
}
|
|
4947
|
+
/**
|
|
4948
|
+
* Accepts a quote amount for an existing chain swap, after validating it
|
|
4949
|
+
* against the configured floor. See `quoteSwap` for floor-resolution rules.
|
|
4950
|
+
*
|
|
4951
|
+
* @throws QuoteRejectedError if `amount` ≤ 0, below the effective floor,
|
|
4952
|
+
* or no baseline is available.
|
|
4953
|
+
*/
|
|
4954
|
+
async acceptSwapQuote(swapId, amount, options) {
|
|
4955
|
+
const effectiveFloor = await this.resolveEffectiveFloor(swapId, options);
|
|
4956
|
+
this.validateQuote(amount, effectiveFloor);
|
|
5013
4957
|
await this.swapProvider.postChainQuote(swapId, { amount });
|
|
5014
4958
|
return amount;
|
|
5015
4959
|
}
|
|
4960
|
+
async resolveEffectiveFloor(swapId, options) {
|
|
4961
|
+
this.validateQuoteOptions(options);
|
|
4962
|
+
const floor = await this.resolveQuoteFloor(swapId, options);
|
|
4963
|
+
const slippageBps = options?.maxSlippageBps ?? 0;
|
|
4964
|
+
const effectiveFloor = Math.floor(floor - floor * slippageBps / 1e4);
|
|
4965
|
+
if (effectiveFloor < 1) {
|
|
4966
|
+
throw new TypeError(
|
|
4967
|
+
`Invalid quote configuration: maxSlippageBps=${slippageBps} reduces floor ${floor} below 1 sat`
|
|
4968
|
+
);
|
|
4969
|
+
}
|
|
4970
|
+
return effectiveFloor;
|
|
4971
|
+
}
|
|
4972
|
+
async resolveQuoteFloor(swapId, options) {
|
|
4973
|
+
if (options?.minAcceptableAmount !== void 0) {
|
|
4974
|
+
return options.minAcceptableAmount;
|
|
4975
|
+
}
|
|
4976
|
+
const swaps = await this.swapRepository.getAllSwaps({
|
|
4977
|
+
id: swapId,
|
|
4978
|
+
type: "chain"
|
|
4979
|
+
});
|
|
4980
|
+
const stored = swaps[0];
|
|
4981
|
+
const amount = stored?.response?.claimDetails?.amount;
|
|
4982
|
+
if (typeof amount !== "number") {
|
|
4983
|
+
throw new QuoteRejectedError({ reason: "no_baseline" });
|
|
4984
|
+
}
|
|
4985
|
+
return amount;
|
|
4986
|
+
}
|
|
4987
|
+
validateQuoteOptions(options) {
|
|
4988
|
+
if (options?.minAcceptableAmount !== void 0) {
|
|
4989
|
+
const v = options.minAcceptableAmount;
|
|
4990
|
+
if (!Number.isInteger(v) || v <= 0) {
|
|
4991
|
+
throw new TypeError(
|
|
4992
|
+
`Invalid minAcceptableAmount: ${v} \u2014 must be a positive integer`
|
|
4993
|
+
);
|
|
4994
|
+
}
|
|
4995
|
+
}
|
|
4996
|
+
if (options?.maxSlippageBps !== void 0) {
|
|
4997
|
+
const v = options.maxSlippageBps;
|
|
4998
|
+
if (!Number.isInteger(v) || v < 0 || v > 1e4) {
|
|
4999
|
+
throw new TypeError(
|
|
5000
|
+
`Invalid maxSlippageBps: ${v} \u2014 must be an integer in [0, 10000]`
|
|
5001
|
+
);
|
|
5002
|
+
}
|
|
5003
|
+
}
|
|
5004
|
+
}
|
|
5005
|
+
validateQuote(amount, effectiveFloor) {
|
|
5006
|
+
if (!Number.isSafeInteger(amount)) {
|
|
5007
|
+
throw new QuoteRejectedError({
|
|
5008
|
+
reason: "non_safe_integer",
|
|
5009
|
+
quotedAmount: amount
|
|
5010
|
+
});
|
|
5011
|
+
}
|
|
5012
|
+
if (amount <= 0) {
|
|
5013
|
+
throw new QuoteRejectedError({
|
|
5014
|
+
reason: "non_positive",
|
|
5015
|
+
quotedAmount: amount
|
|
5016
|
+
});
|
|
5017
|
+
}
|
|
5018
|
+
if (amount < effectiveFloor) {
|
|
5019
|
+
throw new QuoteRejectedError({
|
|
5020
|
+
reason: "below_floor",
|
|
5021
|
+
quotedAmount: amount,
|
|
5022
|
+
floor: effectiveFloor
|
|
5023
|
+
});
|
|
5024
|
+
}
|
|
5025
|
+
}
|
|
5016
5026
|
// =========================================================================
|
|
5017
5027
|
// Shared utilities
|
|
5018
5028
|
// =========================================================================
|
|
@@ -5026,14 +5036,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
5026
5036
|
* @returns The commitment transaction ID.
|
|
5027
5037
|
*/
|
|
5028
5038
|
async joinBatch(identity, input, output, arkInfo, isRecoverable2 = true) {
|
|
5029
|
-
return joinBatch(
|
|
5030
|
-
this.arkProvider,
|
|
5031
|
-
identity,
|
|
5032
|
-
input,
|
|
5033
|
-
output,
|
|
5034
|
-
arkInfo,
|
|
5035
|
-
isRecoverable2
|
|
5036
|
-
);
|
|
5039
|
+
return joinBatch(this.arkProvider, identity, input, output, arkInfo, isRecoverable2);
|
|
5037
5040
|
}
|
|
5038
5041
|
/**
|
|
5039
5042
|
* Creates a VHTLC script for the swap.
|
|
@@ -5071,9 +5074,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
5071
5074
|
async getPendingSubmarineSwaps() {
|
|
5072
5075
|
const swaps = await this.getPendingSubmarineSwapsFromStorage();
|
|
5073
5076
|
if (!swaps) return [];
|
|
5074
|
-
return swaps.filter(
|
|
5075
|
-
(swap) => swap.status === "invoice.set"
|
|
5076
|
-
);
|
|
5077
|
+
return swaps.filter((swap) => swap.status === "invoice.set");
|
|
5077
5078
|
}
|
|
5078
5079
|
/**
|
|
5079
5080
|
* Returns pending reverse swaps (those with status `swap.created`).
|
|
@@ -5081,9 +5082,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
5081
5082
|
async getPendingReverseSwaps() {
|
|
5082
5083
|
const swaps = await this.getPendingReverseSwapsFromStorage();
|
|
5083
5084
|
if (!swaps) return [];
|
|
5084
|
-
return swaps.filter(
|
|
5085
|
-
(swap) => swap.status === "swap.created"
|
|
5086
|
-
);
|
|
5085
|
+
return swaps.filter((swap) => swap.status === "swap.created");
|
|
5087
5086
|
}
|
|
5088
5087
|
/**
|
|
5089
5088
|
* Returns pending chain swaps (those with status `swap.created`).
|
|
@@ -5122,10 +5121,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
5122
5121
|
this.savePendingReverseSwap.bind(this)
|
|
5123
5122
|
)
|
|
5124
5123
|
).catch((error) => {
|
|
5125
|
-
logger.error(
|
|
5126
|
-
`Failed to refresh swap status for ${swap.id}:`,
|
|
5127
|
-
error
|
|
5128
|
-
);
|
|
5124
|
+
logger.error(`Failed to refresh swap status for ${swap.id}:`, error);
|
|
5129
5125
|
})
|
|
5130
5126
|
);
|
|
5131
5127
|
}
|
|
@@ -5139,23 +5135,15 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
5139
5135
|
this.savePendingSubmarineSwap.bind(this)
|
|
5140
5136
|
)
|
|
5141
5137
|
).catch((error) => {
|
|
5142
|
-
logger.error(
|
|
5143
|
-
`Failed to refresh swap status for ${swap.id}:`,
|
|
5144
|
-
error
|
|
5145
|
-
);
|
|
5138
|
+
logger.error(`Failed to refresh swap status for ${swap.id}:`, error);
|
|
5146
5139
|
})
|
|
5147
5140
|
);
|
|
5148
5141
|
}
|
|
5149
5142
|
for (const swap of await this.getPendingChainSwapsFromStorage()) {
|
|
5150
5143
|
if (isChainFinalStatus(swap.status)) continue;
|
|
5151
5144
|
promises.push(
|
|
5152
|
-
this.getSwapStatus(swap.id).then(
|
|
5153
|
-
(
|
|
5154
|
-
).catch((error) => {
|
|
5155
|
-
logger.error(
|
|
5156
|
-
`Failed to refresh swap status for ${swap.id}:`,
|
|
5157
|
-
error
|
|
5158
|
-
);
|
|
5145
|
+
this.getSwapStatus(swap.id).then(({ status }) => this.savePendingChainSwap({ ...swap, status })).catch((error) => {
|
|
5146
|
+
logger.error(`Failed to refresh swap status for ${swap.id}:`, error);
|
|
5159
5147
|
})
|
|
5160
5148
|
);
|
|
5161
5149
|
}
|
|
@@ -5172,9 +5160,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
5172
5160
|
* display/monitoring and are not automatically wired into the SwapManager.
|
|
5173
5161
|
*/
|
|
5174
5162
|
async restoreSwaps(boltzFees) {
|
|
5175
|
-
const publicKey = import_base9.hex.encode(
|
|
5176
|
-
await this.wallet.identity.compressedPublicKey()
|
|
5177
|
-
);
|
|
5163
|
+
const publicKey = import_base9.hex.encode(await this.wallet.identity.compressedPublicKey());
|
|
5178
5164
|
if (!publicKey) throw new Error("Failed to get public key from wallet");
|
|
5179
5165
|
const fees = boltzFees ?? await this.swapProvider.getFees();
|
|
5180
5166
|
const chainSwaps = [];
|
|
@@ -5226,25 +5212,14 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
5226
5212
|
preimage: ""
|
|
5227
5213
|
});
|
|
5228
5214
|
} else if (isRestoredSubmarineSwap(swap)) {
|
|
5229
|
-
const {
|
|
5230
|
-
amount,
|
|
5231
|
-
lockupAddress,
|
|
5232
|
-
serverPublicKey,
|
|
5233
|
-
tree,
|
|
5234
|
-
timeoutBlockHeights
|
|
5235
|
-
} = swap.refundDetails;
|
|
5215
|
+
const { amount, lockupAddress, serverPublicKey, tree, timeoutBlockHeights } = swap.refundDetails;
|
|
5236
5216
|
let preimage = "";
|
|
5237
5217
|
if (!isSubmarineFinalStatus(status)) {
|
|
5238
5218
|
try {
|
|
5239
|
-
const data = await this.swapProvider.getSwapPreimage(
|
|
5240
|
-
swap.id
|
|
5241
|
-
);
|
|
5219
|
+
const data = await this.swapProvider.getSwapPreimage(swap.id);
|
|
5242
5220
|
preimage = data.preimage;
|
|
5243
5221
|
} catch (error) {
|
|
5244
|
-
logger.warn(
|
|
5245
|
-
`Failed to restore preimage for submarine swap ${id}`,
|
|
5246
|
-
error
|
|
5247
|
-
);
|
|
5222
|
+
logger.warn(`Failed to restore preimage for submarine swap ${id}`, error);
|
|
5248
5223
|
}
|
|
5249
5224
|
}
|
|
5250
5225
|
submarineSwaps.push({
|
|
@@ -5282,12 +5257,7 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
5282
5257
|
} else if (isRestoredChainSwap(swap)) {
|
|
5283
5258
|
const refundDetails = swap.refundDetails;
|
|
5284
5259
|
if (!refundDetails) continue;
|
|
5285
|
-
const {
|
|
5286
|
-
amount,
|
|
5287
|
-
lockupAddress,
|
|
5288
|
-
serverPublicKey,
|
|
5289
|
-
timeoutBlockHeight
|
|
5290
|
-
} = refundDetails;
|
|
5260
|
+
const { amount, lockupAddress, serverPublicKey, timeoutBlockHeight } = refundDetails;
|
|
5291
5261
|
chainSwaps.push({
|
|
5292
5262
|
id,
|
|
5293
5263
|
type: "chain",
|
|
@@ -5337,6 +5307,12 @@ var ArkadeSwaps = class _ArkadeSwaps {
|
|
|
5337
5307
|
|
|
5338
5308
|
// src/serviceWorker/arkade-swaps-message-handler.ts
|
|
5339
5309
|
var import_sdk9 = require("@arkade-os/sdk");
|
|
5310
|
+
function toQuoteTransportError(error) {
|
|
5311
|
+
if (error instanceof QuoteRejectedError) {
|
|
5312
|
+
return error.toTransportError();
|
|
5313
|
+
}
|
|
5314
|
+
return error;
|
|
5315
|
+
}
|
|
5340
5316
|
var DEFAULT_MESSAGE_TAG = "ARKADE_SWAPS_UPDATER";
|
|
5341
5317
|
var HANDLER_NOT_INITIALIZED = "ArkadeSwaps handler not initialized";
|
|
5342
5318
|
var HandlerNotInitializedError = class extends Error {
|
|
@@ -5452,9 +5428,7 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5452
5428
|
try {
|
|
5453
5429
|
switch (message.type) {
|
|
5454
5430
|
case "CREATE_LIGHTNING_INVOICE": {
|
|
5455
|
-
const res = await this.handler.createLightningInvoice(
|
|
5456
|
-
message.payload
|
|
5457
|
-
);
|
|
5431
|
+
const res = await this.handler.createLightningInvoice(message.payload);
|
|
5458
5432
|
return this.tagged({
|
|
5459
5433
|
id,
|
|
5460
5434
|
type: "LIGHTNING_INVOICE_CREATED",
|
|
@@ -5462,9 +5436,7 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5462
5436
|
});
|
|
5463
5437
|
}
|
|
5464
5438
|
case "SEND_LIGHTNING_PAYMENT": {
|
|
5465
|
-
const res = await this.handler.sendLightningPayment(
|
|
5466
|
-
message.payload
|
|
5467
|
-
);
|
|
5439
|
+
const res = await this.handler.sendLightningPayment(message.payload);
|
|
5468
5440
|
return this.tagged({
|
|
5469
5441
|
id,
|
|
5470
5442
|
type: "LIGHTNING_PAYMENT_SENT",
|
|
@@ -5472,9 +5444,7 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5472
5444
|
});
|
|
5473
5445
|
}
|
|
5474
5446
|
case "CREATE_SUBMARINE_SWAP": {
|
|
5475
|
-
const res = await this.handler.createSubmarineSwap(
|
|
5476
|
-
message.payload
|
|
5477
|
-
);
|
|
5447
|
+
const res = await this.handler.createSubmarineSwap(message.payload);
|
|
5478
5448
|
return this.tagged({
|
|
5479
5449
|
id,
|
|
5480
5450
|
type: "SUBMARINE_SWAP_CREATED",
|
|
@@ -5482,9 +5452,7 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5482
5452
|
});
|
|
5483
5453
|
}
|
|
5484
5454
|
case "CREATE_REVERSE_SWAP": {
|
|
5485
|
-
const res = await this.handler.createReverseSwap(
|
|
5486
|
-
message.payload
|
|
5487
|
-
);
|
|
5455
|
+
const res = await this.handler.createReverseSwap(message.payload);
|
|
5488
5456
|
return this.tagged({
|
|
5489
5457
|
id,
|
|
5490
5458
|
type: "REVERSE_SWAP_CREATED",
|
|
@@ -5495,9 +5463,7 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5495
5463
|
await this.handler.claimVHTLC(message.payload);
|
|
5496
5464
|
return this.tagged({ id, type: "VHTLC_CLAIMED" });
|
|
5497
5465
|
case "REFUND_VHTLC": {
|
|
5498
|
-
const outcome = await this.handler.refundVHTLC(
|
|
5499
|
-
message.payload
|
|
5500
|
-
);
|
|
5466
|
+
const outcome = await this.handler.refundVHTLC(message.payload);
|
|
5501
5467
|
return this.tagged({
|
|
5502
5468
|
id,
|
|
5503
5469
|
type: "VHTLC_REFUNDED",
|
|
@@ -5505,9 +5471,7 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5505
5471
|
});
|
|
5506
5472
|
}
|
|
5507
5473
|
case "INSPECT_SUBMARINE_RECOVERY": {
|
|
5508
|
-
const info = await this.handler.inspectSubmarineRecovery(
|
|
5509
|
-
message.payload
|
|
5510
|
-
);
|
|
5474
|
+
const info = await this.handler.inspectSubmarineRecovery(message.payload);
|
|
5511
5475
|
return this.tagged({
|
|
5512
5476
|
id,
|
|
5513
5477
|
type: "SUBMARINE_RECOVERY_INSPECTED",
|
|
@@ -5523,9 +5487,7 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5523
5487
|
});
|
|
5524
5488
|
}
|
|
5525
5489
|
case "RECOVER_SUBMARINE_FUNDS": {
|
|
5526
|
-
const outcome = await this.handler.recoverSubmarineFunds(
|
|
5527
|
-
message.payload
|
|
5528
|
-
);
|
|
5490
|
+
const outcome = await this.handler.recoverSubmarineFunds(message.payload);
|
|
5529
5491
|
return this.tagged({
|
|
5530
5492
|
id,
|
|
5531
5493
|
type: "SUBMARINE_FUNDS_RECOVERED",
|
|
@@ -5533,9 +5495,7 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5533
5495
|
});
|
|
5534
5496
|
}
|
|
5535
5497
|
case "RECOVER_ALL_SUBMARINE_FUNDS": {
|
|
5536
|
-
const results = await this.handler.recoverAllSubmarineFunds(
|
|
5537
|
-
message.payload
|
|
5538
|
-
);
|
|
5498
|
+
const results = await this.handler.recoverAllSubmarineFunds(message.payload);
|
|
5539
5499
|
return this.tagged({
|
|
5540
5500
|
id,
|
|
5541
5501
|
type: "ALL_SUBMARINE_FUNDS_RECOVERED",
|
|
@@ -5543,9 +5503,7 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5543
5503
|
});
|
|
5544
5504
|
}
|
|
5545
5505
|
case "WAIT_AND_CLAIM": {
|
|
5546
|
-
const res = await this.handler.waitAndClaim(
|
|
5547
|
-
message.payload
|
|
5548
|
-
);
|
|
5506
|
+
const res = await this.handler.waitAndClaim(message.payload);
|
|
5549
5507
|
return this.tagged({
|
|
5550
5508
|
id,
|
|
5551
5509
|
type: "WAIT_AND_CLAIMED",
|
|
@@ -5553,9 +5511,7 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5553
5511
|
});
|
|
5554
5512
|
}
|
|
5555
5513
|
case "WAIT_FOR_SWAP_SETTLEMENT": {
|
|
5556
|
-
const res = await this.handler.waitForSwapSettlement(
|
|
5557
|
-
message.payload
|
|
5558
|
-
);
|
|
5514
|
+
const res = await this.handler.waitForSwapSettlement(message.payload);
|
|
5559
5515
|
return this.tagged({
|
|
5560
5516
|
id,
|
|
5561
5517
|
type: "SWAP_SETTLED",
|
|
@@ -5563,9 +5519,7 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5563
5519
|
});
|
|
5564
5520
|
}
|
|
5565
5521
|
case "RESTORE_SWAPS": {
|
|
5566
|
-
const res = await this.handler.restoreSwaps(
|
|
5567
|
-
message.payload
|
|
5568
|
-
);
|
|
5522
|
+
const res = await this.handler.restoreSwaps(message.payload);
|
|
5569
5523
|
return this.tagged({
|
|
5570
5524
|
id,
|
|
5571
5525
|
type: "SWAPS_RESTORED",
|
|
@@ -5595,23 +5549,15 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5595
5549
|
});
|
|
5596
5550
|
}
|
|
5597
5551
|
case "GET_FEES": {
|
|
5598
|
-
const res = message.payload ? await this.handler.getFees(
|
|
5599
|
-
message.payload.from,
|
|
5600
|
-
message.payload.to
|
|
5601
|
-
) : await this.handler.getFees();
|
|
5552
|
+
const res = message.payload ? await this.handler.getFees(message.payload.from, message.payload.to) : await this.handler.getFees();
|
|
5602
5553
|
return this.tagged({ id, type: "FEES", payload: res });
|
|
5603
5554
|
}
|
|
5604
5555
|
case "GET_LIMITS": {
|
|
5605
|
-
const res = message.payload ? await this.handler.getLimits(
|
|
5606
|
-
message.payload.from,
|
|
5607
|
-
message.payload.to
|
|
5608
|
-
) : await this.handler.getLimits();
|
|
5556
|
+
const res = message.payload ? await this.handler.getLimits(message.payload.from, message.payload.to) : await this.handler.getLimits();
|
|
5609
5557
|
return this.tagged({ id, type: "LIMITS", payload: res });
|
|
5610
5558
|
}
|
|
5611
5559
|
case "GET_SWAP_STATUS": {
|
|
5612
|
-
const res = await this.handler.getSwapStatus(
|
|
5613
|
-
message.payload.swapId
|
|
5614
|
-
);
|
|
5560
|
+
const res = await this.handler.getSwapStatus(message.payload.swapId);
|
|
5615
5561
|
return this.tagged({
|
|
5616
5562
|
id,
|
|
5617
5563
|
type: "SWAP_STATUS",
|
|
@@ -5670,9 +5616,7 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5670
5616
|
});
|
|
5671
5617
|
}
|
|
5672
5618
|
case "CREATE_CHAIN_SWAP": {
|
|
5673
|
-
const res = await this.handler.createChainSwap(
|
|
5674
|
-
message.payload
|
|
5675
|
-
);
|
|
5619
|
+
const res = await this.handler.createChainSwap(message.payload);
|
|
5676
5620
|
return this.tagged({
|
|
5677
5621
|
id,
|
|
5678
5622
|
type: "CHAIN_SWAP_CREATED",
|
|
@@ -5680,9 +5624,7 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5680
5624
|
});
|
|
5681
5625
|
}
|
|
5682
5626
|
case "WAIT_AND_CLAIM_CHAIN": {
|
|
5683
|
-
const res = await this.handler.waitAndClaimChain(
|
|
5684
|
-
message.payload
|
|
5685
|
-
);
|
|
5627
|
+
const res = await this.handler.waitAndClaimChain(message.payload);
|
|
5686
5628
|
return this.tagged({
|
|
5687
5629
|
id,
|
|
5688
5630
|
type: "CHAIN_CLAIMED",
|
|
@@ -5690,9 +5632,7 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5690
5632
|
});
|
|
5691
5633
|
}
|
|
5692
5634
|
case "WAIT_AND_CLAIM_ARK": {
|
|
5693
|
-
const res = await this.handler.waitAndClaimArk(
|
|
5694
|
-
message.payload
|
|
5695
|
-
);
|
|
5635
|
+
const res = await this.handler.waitAndClaimArk(message.payload);
|
|
5696
5636
|
return this.tagged({
|
|
5697
5637
|
id,
|
|
5698
5638
|
type: "ARK_CLAIMED",
|
|
@@ -5700,9 +5640,7 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5700
5640
|
});
|
|
5701
5641
|
}
|
|
5702
5642
|
case "WAIT_AND_CLAIM_BTC": {
|
|
5703
|
-
const res = await this.handler.waitAndClaimBtc(
|
|
5704
|
-
message.payload
|
|
5705
|
-
);
|
|
5643
|
+
const res = await this.handler.waitAndClaimBtc(message.payload);
|
|
5706
5644
|
return this.tagged({
|
|
5707
5645
|
id,
|
|
5708
5646
|
type: "BTC_CLAIMED",
|
|
@@ -5715,13 +5653,16 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5715
5653
|
case "CLAIM_BTC":
|
|
5716
5654
|
await this.handler.claimBtc(message.payload);
|
|
5717
5655
|
return this.tagged({ id, type: "BTC_CLAIM_EXECUTED" });
|
|
5718
|
-
case "REFUND_ARK":
|
|
5719
|
-
await this.handler.refundArk(message.payload);
|
|
5720
|
-
return this.tagged({
|
|
5656
|
+
case "REFUND_ARK": {
|
|
5657
|
+
const outcome = await this.handler.refundArk(message.payload);
|
|
5658
|
+
return this.tagged({
|
|
5659
|
+
id,
|
|
5660
|
+
type: "ARK_REFUND_EXECUTED",
|
|
5661
|
+
payload: outcome
|
|
5662
|
+
});
|
|
5663
|
+
}
|
|
5721
5664
|
case "SIGN_SERVER_CLAIM":
|
|
5722
|
-
await this.handler.signCooperativeClaimForServer(
|
|
5723
|
-
message.payload
|
|
5724
|
-
);
|
|
5665
|
+
await this.handler.signCooperativeClaimForServer(message.payload);
|
|
5725
5666
|
return this.tagged({ id, type: "SERVER_CLAIM_SIGNED" });
|
|
5726
5667
|
case "VERIFY_CHAIN_SWAP": {
|
|
5727
5668
|
const verified = await this.handler.verifyChainSwap({
|
|
@@ -5734,14 +5675,47 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5734
5675
|
});
|
|
5735
5676
|
}
|
|
5736
5677
|
case "QUOTE_SWAP": {
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5678
|
+
try {
|
|
5679
|
+
const amount = await this.handler.quoteSwap(
|
|
5680
|
+
message.payload.swapId,
|
|
5681
|
+
message.payload.options
|
|
5682
|
+
);
|
|
5683
|
+
return this.tagged({
|
|
5684
|
+
id,
|
|
5685
|
+
type: "SWAP_QUOTED",
|
|
5686
|
+
payload: { amount }
|
|
5687
|
+
});
|
|
5688
|
+
} catch (e) {
|
|
5689
|
+
throw toQuoteTransportError(e);
|
|
5690
|
+
}
|
|
5691
|
+
}
|
|
5692
|
+
case "GET_SWAP_QUOTE": {
|
|
5693
|
+
try {
|
|
5694
|
+
const amount = await this.handler.getSwapQuote(message.payload.swapId);
|
|
5695
|
+
return this.tagged({
|
|
5696
|
+
id,
|
|
5697
|
+
type: "SWAP_QUOTE_RETRIEVED",
|
|
5698
|
+
payload: { amount }
|
|
5699
|
+
});
|
|
5700
|
+
} catch (e) {
|
|
5701
|
+
throw toQuoteTransportError(e);
|
|
5702
|
+
}
|
|
5703
|
+
}
|
|
5704
|
+
case "ACCEPT_SWAP_QUOTE": {
|
|
5705
|
+
try {
|
|
5706
|
+
const amount = await this.handler.acceptSwapQuote(
|
|
5707
|
+
message.payload.swapId,
|
|
5708
|
+
message.payload.amount,
|
|
5709
|
+
message.payload.options
|
|
5710
|
+
);
|
|
5711
|
+
return this.tagged({
|
|
5712
|
+
id,
|
|
5713
|
+
type: "SWAP_QUOTE_ACCEPTED",
|
|
5714
|
+
payload: { amount }
|
|
5715
|
+
});
|
|
5716
|
+
} catch (e) {
|
|
5717
|
+
throw toQuoteTransportError(e);
|
|
5718
|
+
}
|
|
5745
5719
|
}
|
|
5746
5720
|
/* --- SwapManager methods --- */
|
|
5747
5721
|
case "SM-START": {
|
|
@@ -5757,9 +5731,7 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5757
5731
|
return this.tagged({ id, type: "SM-SWAP_ADDED" });
|
|
5758
5732
|
}
|
|
5759
5733
|
case "SM-REMOVE_SWAP": {
|
|
5760
|
-
await this.getSwapManagerOrThrow().removeSwap(
|
|
5761
|
-
message.payload.swapId
|
|
5762
|
-
);
|
|
5734
|
+
await this.getSwapManagerOrThrow().removeSwap(message.payload.swapId);
|
|
5763
5735
|
return this.tagged({ id, type: "SM-SWAP_REMOVED" });
|
|
5764
5736
|
}
|
|
5765
5737
|
case "SM-GET_PENDING_SWAPS": {
|
|
@@ -5771,9 +5743,7 @@ var ArkadeSwapsMessageHandler = class _ArkadeSwapsMessageHandler {
|
|
|
5771
5743
|
});
|
|
5772
5744
|
}
|
|
5773
5745
|
case "SM-HAS_SWAP": {
|
|
5774
|
-
const has = await this.getSwapManagerOrThrow().hasSwap(
|
|
5775
|
-
message.payload.swapId
|
|
5776
|
-
);
|
|
5746
|
+
const has = await this.getSwapManagerOrThrow().hasSwap(message.payload.swapId);
|
|
5777
5747
|
return this.tagged({
|
|
5778
5748
|
id,
|
|
5779
5749
|
type: "SM-HAS_SWAP_RESULT",
|
|
@@ -5893,6 +5863,11 @@ function isMessageBusNotInitializedError(error) {
|
|
|
5893
5863
|
function isHandlerNotInitializedError(error) {
|
|
5894
5864
|
return error instanceof Error && error.message.includes(HANDLER_NOT_INITIALIZED);
|
|
5895
5865
|
}
|
|
5866
|
+
function rethrowIfQuoteRejected(error) {
|
|
5867
|
+
if (error instanceof QuoteRejectedError) throw error;
|
|
5868
|
+
const rebuilt = QuoteRejectedError.fromTransportError(error);
|
|
5869
|
+
if (rebuilt) throw rebuilt;
|
|
5870
|
+
}
|
|
5896
5871
|
var DEFAULT_MESSAGE_TIMEOUT_MS = 3e4;
|
|
5897
5872
|
var NO_MESSAGE_TIMEOUT_MS = 0;
|
|
5898
5873
|
var DEDUPABLE_REQUEST_TYPES = /* @__PURE__ */ new Set([
|
|
@@ -5949,7 +5924,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
5949
5924
|
};
|
|
5950
5925
|
const initMessage = {
|
|
5951
5926
|
tag: messageTag,
|
|
5952
|
-
id: getRandomId(),
|
|
5927
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
5953
5928
|
type: "INIT_ARKADE_SWAPS",
|
|
5954
5929
|
payload: initPayload
|
|
5955
5930
|
};
|
|
@@ -5962,7 +5937,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
5962
5937
|
throw new Error("SwapManager is not enabled.");
|
|
5963
5938
|
}
|
|
5964
5939
|
await this.sendMessage({
|
|
5965
|
-
id: getRandomId(),
|
|
5940
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
5966
5941
|
tag: this.messageTag,
|
|
5967
5942
|
type: "SM-START"
|
|
5968
5943
|
});
|
|
@@ -5970,7 +5945,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
5970
5945
|
async stopSwapManager() {
|
|
5971
5946
|
if (!this.withSwapManager) return;
|
|
5972
5947
|
await this.sendMessage({
|
|
5973
|
-
id: getRandomId(),
|
|
5948
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
5974
5949
|
tag: this.messageTag,
|
|
5975
5950
|
type: "SM-STOP"
|
|
5976
5951
|
});
|
|
@@ -5985,21 +5960,21 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
5985
5960
|
const proxy = {
|
|
5986
5961
|
start: async () => {
|
|
5987
5962
|
await send({
|
|
5988
|
-
id: getRandomId(),
|
|
5963
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
5989
5964
|
tag,
|
|
5990
5965
|
type: "SM-START"
|
|
5991
5966
|
});
|
|
5992
5967
|
},
|
|
5993
5968
|
stop: async () => {
|
|
5994
5969
|
await send({
|
|
5995
|
-
id: getRandomId(),
|
|
5970
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
5996
5971
|
tag,
|
|
5997
5972
|
type: "SM-STOP"
|
|
5998
5973
|
});
|
|
5999
5974
|
},
|
|
6000
5975
|
addSwap: async (swap) => {
|
|
6001
5976
|
await send({
|
|
6002
|
-
id: getRandomId(),
|
|
5977
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6003
5978
|
tag,
|
|
6004
5979
|
type: "SM-ADD_SWAP",
|
|
6005
5980
|
payload: swap
|
|
@@ -6007,7 +5982,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6007
5982
|
},
|
|
6008
5983
|
removeSwap: async (swapId) => {
|
|
6009
5984
|
await send({
|
|
6010
|
-
id: getRandomId(),
|
|
5985
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6011
5986
|
tag,
|
|
6012
5987
|
type: "SM-REMOVE_SWAP",
|
|
6013
5988
|
payload: { swapId }
|
|
@@ -6015,7 +5990,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6015
5990
|
},
|
|
6016
5991
|
getPendingSwaps: async () => {
|
|
6017
5992
|
const res = await send({
|
|
6018
|
-
id: getRandomId(),
|
|
5993
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6019
5994
|
tag,
|
|
6020
5995
|
type: "SM-GET_PENDING_SWAPS"
|
|
6021
5996
|
});
|
|
@@ -6023,7 +5998,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6023
5998
|
},
|
|
6024
5999
|
hasSwap: async (swapId) => {
|
|
6025
6000
|
const res = await send({
|
|
6026
|
-
id: getRandomId(),
|
|
6001
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6027
6002
|
tag,
|
|
6028
6003
|
type: "SM-HAS_SWAP",
|
|
6029
6004
|
payload: { swapId }
|
|
@@ -6032,7 +6007,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6032
6007
|
},
|
|
6033
6008
|
isProcessing: async (swapId) => {
|
|
6034
6009
|
const res = await send({
|
|
6035
|
-
id: getRandomId(),
|
|
6010
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6036
6011
|
tag,
|
|
6037
6012
|
type: "SM-IS_PROCESSING",
|
|
6038
6013
|
payload: { swapId }
|
|
@@ -6041,7 +6016,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6041
6016
|
},
|
|
6042
6017
|
getStats: async () => {
|
|
6043
6018
|
const res = await send({
|
|
6044
|
-
id: getRandomId(),
|
|
6019
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6045
6020
|
tag,
|
|
6046
6021
|
type: "SM-GET_STATS"
|
|
6047
6022
|
});
|
|
@@ -6049,7 +6024,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6049
6024
|
},
|
|
6050
6025
|
waitForSwapCompletion: async (swapId) => {
|
|
6051
6026
|
const res = await send({
|
|
6052
|
-
id: getRandomId(),
|
|
6027
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6053
6028
|
tag,
|
|
6054
6029
|
type: "SM-WAIT_FOR_COMPLETION",
|
|
6055
6030
|
payload: { swapId }
|
|
@@ -6113,7 +6088,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6113
6088
|
async createLightningInvoice(args) {
|
|
6114
6089
|
try {
|
|
6115
6090
|
const res = await this.sendMessage({
|
|
6116
|
-
id: getRandomId(),
|
|
6091
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6117
6092
|
tag: this.messageTag,
|
|
6118
6093
|
type: "CREATE_LIGHTNING_INVOICE",
|
|
6119
6094
|
payload: args
|
|
@@ -6126,7 +6101,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6126
6101
|
async sendLightningPayment(args) {
|
|
6127
6102
|
try {
|
|
6128
6103
|
const res = await this.sendMessage({
|
|
6129
|
-
id: getRandomId(),
|
|
6104
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6130
6105
|
tag: this.messageTag,
|
|
6131
6106
|
type: "SEND_LIGHTNING_PAYMENT",
|
|
6132
6107
|
payload: args
|
|
@@ -6139,7 +6114,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6139
6114
|
async createSubmarineSwap(args) {
|
|
6140
6115
|
try {
|
|
6141
6116
|
const res = await this.sendMessage({
|
|
6142
|
-
id: getRandomId(),
|
|
6117
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6143
6118
|
tag: this.messageTag,
|
|
6144
6119
|
type: "CREATE_SUBMARINE_SWAP",
|
|
6145
6120
|
payload: args
|
|
@@ -6152,7 +6127,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6152
6127
|
async createReverseSwap(args) {
|
|
6153
6128
|
try {
|
|
6154
6129
|
const res = await this.sendMessage({
|
|
6155
|
-
id: getRandomId(),
|
|
6130
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6156
6131
|
tag: this.messageTag,
|
|
6157
6132
|
type: "CREATE_REVERSE_SWAP",
|
|
6158
6133
|
payload: args
|
|
@@ -6164,7 +6139,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6164
6139
|
}
|
|
6165
6140
|
async claimVHTLC(pendingSwap) {
|
|
6166
6141
|
await this.sendMessage({
|
|
6167
|
-
id: getRandomId(),
|
|
6142
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6168
6143
|
tag: this.messageTag,
|
|
6169
6144
|
type: "CLAIM_VHTLC",
|
|
6170
6145
|
payload: pendingSwap
|
|
@@ -6172,7 +6147,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6172
6147
|
}
|
|
6173
6148
|
async refundVHTLC(pendingSwap) {
|
|
6174
6149
|
const res = await this.sendMessage({
|
|
6175
|
-
id: getRandomId(),
|
|
6150
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6176
6151
|
tag: this.messageTag,
|
|
6177
6152
|
type: "REFUND_VHTLC",
|
|
6178
6153
|
payload: pendingSwap
|
|
@@ -6181,7 +6156,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6181
6156
|
}
|
|
6182
6157
|
async inspectSubmarineRecovery(swap) {
|
|
6183
6158
|
const res = await this.sendMessage({
|
|
6184
|
-
id: getRandomId(),
|
|
6159
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6185
6160
|
tag: this.messageTag,
|
|
6186
6161
|
type: "INSPECT_SUBMARINE_RECOVERY",
|
|
6187
6162
|
payload: swap
|
|
@@ -6190,7 +6165,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6190
6165
|
}
|
|
6191
6166
|
async scanRecoverableSubmarineSwaps() {
|
|
6192
6167
|
const res = await this.sendMessage({
|
|
6193
|
-
id: getRandomId(),
|
|
6168
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6194
6169
|
tag: this.messageTag,
|
|
6195
6170
|
type: "SCAN_RECOVERABLE_SUBMARINE_SWAPS"
|
|
6196
6171
|
});
|
|
@@ -6198,7 +6173,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6198
6173
|
}
|
|
6199
6174
|
async recoverSubmarineFunds(swap) {
|
|
6200
6175
|
const res = await this.sendMessage({
|
|
6201
|
-
id: getRandomId(),
|
|
6176
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6202
6177
|
tag: this.messageTag,
|
|
6203
6178
|
type: "RECOVER_SUBMARINE_FUNDS",
|
|
6204
6179
|
payload: swap
|
|
@@ -6207,7 +6182,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6207
6182
|
}
|
|
6208
6183
|
async recoverAllSubmarineFunds(swaps) {
|
|
6209
6184
|
const res = await this.sendMessage({
|
|
6210
|
-
id: getRandomId(),
|
|
6185
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6211
6186
|
tag: this.messageTag,
|
|
6212
6187
|
type: "RECOVER_ALL_SUBMARINE_FUNDS",
|
|
6213
6188
|
payload: swaps
|
|
@@ -6217,7 +6192,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6217
6192
|
async waitAndClaim(pendingSwap) {
|
|
6218
6193
|
try {
|
|
6219
6194
|
const res = await this.sendMessage({
|
|
6220
|
-
id: getRandomId(),
|
|
6195
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6221
6196
|
tag: this.messageTag,
|
|
6222
6197
|
type: "WAIT_AND_CLAIM",
|
|
6223
6198
|
payload: pendingSwap
|
|
@@ -6232,7 +6207,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6232
6207
|
async waitForSwapSettlement(pendingSwap) {
|
|
6233
6208
|
try {
|
|
6234
6209
|
const res = await this.sendMessage({
|
|
6235
|
-
id: getRandomId(),
|
|
6210
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6236
6211
|
tag: this.messageTag,
|
|
6237
6212
|
type: "WAIT_FOR_SWAP_SETTLEMENT",
|
|
6238
6213
|
payload: pendingSwap
|
|
@@ -6245,7 +6220,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6245
6220
|
async restoreSwaps(boltzFees) {
|
|
6246
6221
|
try {
|
|
6247
6222
|
const res = await this.sendMessage({
|
|
6248
|
-
id: getRandomId(),
|
|
6223
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6249
6224
|
tag: this.messageTag,
|
|
6250
6225
|
type: "RESTORE_SWAPS",
|
|
6251
6226
|
payload: boltzFees
|
|
@@ -6258,7 +6233,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6258
6233
|
async arkToBtc(args) {
|
|
6259
6234
|
try {
|
|
6260
6235
|
const res = await this.sendMessage({
|
|
6261
|
-
id: getRandomId(),
|
|
6236
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6262
6237
|
tag: this.messageTag,
|
|
6263
6238
|
type: "ARK_TO_BTC",
|
|
6264
6239
|
payload: args
|
|
@@ -6273,7 +6248,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6273
6248
|
async btcToArk(args) {
|
|
6274
6249
|
try {
|
|
6275
6250
|
const res = await this.sendMessage({
|
|
6276
|
-
id: getRandomId(),
|
|
6251
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6277
6252
|
tag: this.messageTag,
|
|
6278
6253
|
type: "BTC_TO_ARK",
|
|
6279
6254
|
payload: args
|
|
@@ -6288,7 +6263,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6288
6263
|
async createChainSwap(args) {
|
|
6289
6264
|
try {
|
|
6290
6265
|
const res = await this.sendMessage({
|
|
6291
|
-
id: getRandomId(),
|
|
6266
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6292
6267
|
tag: this.messageTag,
|
|
6293
6268
|
type: "CREATE_CHAIN_SWAP",
|
|
6294
6269
|
payload: args
|
|
@@ -6301,7 +6276,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6301
6276
|
async waitAndClaimChain(pendingSwap) {
|
|
6302
6277
|
try {
|
|
6303
6278
|
const res = await this.sendMessage({
|
|
6304
|
-
id: getRandomId(),
|
|
6279
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6305
6280
|
tag: this.messageTag,
|
|
6306
6281
|
type: "WAIT_AND_CLAIM_CHAIN",
|
|
6307
6282
|
payload: pendingSwap
|
|
@@ -6316,7 +6291,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6316
6291
|
async waitAndClaimArk(pendingSwap) {
|
|
6317
6292
|
try {
|
|
6318
6293
|
const res = await this.sendMessage({
|
|
6319
|
-
id: getRandomId(),
|
|
6294
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6320
6295
|
tag: this.messageTag,
|
|
6321
6296
|
type: "WAIT_AND_CLAIM_ARK",
|
|
6322
6297
|
payload: pendingSwap
|
|
@@ -6331,7 +6306,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6331
6306
|
async waitAndClaimBtc(pendingSwap) {
|
|
6332
6307
|
try {
|
|
6333
6308
|
const res = await this.sendMessage({
|
|
6334
|
-
id: getRandomId(),
|
|
6309
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6335
6310
|
tag: this.messageTag,
|
|
6336
6311
|
type: "WAIT_AND_CLAIM_BTC",
|
|
6337
6312
|
payload: pendingSwap
|
|
@@ -6345,7 +6320,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6345
6320
|
}
|
|
6346
6321
|
async claimArk(pendingSwap) {
|
|
6347
6322
|
await this.sendMessage({
|
|
6348
|
-
id: getRandomId(),
|
|
6323
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6349
6324
|
tag: this.messageTag,
|
|
6350
6325
|
type: "CLAIM_ARK",
|
|
6351
6326
|
payload: pendingSwap
|
|
@@ -6353,23 +6328,24 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6353
6328
|
}
|
|
6354
6329
|
async claimBtc(pendingSwap) {
|
|
6355
6330
|
await this.sendMessage({
|
|
6356
|
-
id: getRandomId(),
|
|
6331
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6357
6332
|
tag: this.messageTag,
|
|
6358
6333
|
type: "CLAIM_BTC",
|
|
6359
6334
|
payload: pendingSwap
|
|
6360
6335
|
});
|
|
6361
6336
|
}
|
|
6362
6337
|
async refundArk(pendingSwap) {
|
|
6363
|
-
await this.sendMessage({
|
|
6364
|
-
id: getRandomId(),
|
|
6338
|
+
const res = await this.sendMessage({
|
|
6339
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6365
6340
|
tag: this.messageTag,
|
|
6366
6341
|
type: "REFUND_ARK",
|
|
6367
6342
|
payload: pendingSwap
|
|
6368
6343
|
});
|
|
6344
|
+
return res.payload;
|
|
6369
6345
|
}
|
|
6370
6346
|
async signCooperativeClaimForServer(pendingSwap) {
|
|
6371
6347
|
await this.sendMessage({
|
|
6372
|
-
id: getRandomId(),
|
|
6348
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6373
6349
|
tag: this.messageTag,
|
|
6374
6350
|
type: "SIGN_SERVER_CLAIM",
|
|
6375
6351
|
payload: pendingSwap
|
|
@@ -6378,7 +6354,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6378
6354
|
async verifyChainSwap(args) {
|
|
6379
6355
|
try {
|
|
6380
6356
|
const res = await this.sendMessage({
|
|
6381
|
-
id: getRandomId(),
|
|
6357
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6382
6358
|
tag: this.messageTag,
|
|
6383
6359
|
type: "VERIFY_CHAIN_SWAP",
|
|
6384
6360
|
payload: {
|
|
@@ -6393,19 +6369,48 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6393
6369
|
throw new Error("Cannot verify chain swap", { cause: e });
|
|
6394
6370
|
}
|
|
6395
6371
|
}
|
|
6396
|
-
async quoteSwap(swapId) {
|
|
6372
|
+
async quoteSwap(swapId, options) {
|
|
6397
6373
|
try {
|
|
6398
6374
|
const res = await this.sendMessage({
|
|
6399
|
-
id: getRandomId(),
|
|
6375
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6400
6376
|
tag: this.messageTag,
|
|
6401
6377
|
type: "QUOTE_SWAP",
|
|
6402
|
-
payload: { swapId }
|
|
6378
|
+
payload: { swapId, options }
|
|
6403
6379
|
});
|
|
6404
6380
|
return res.payload.amount;
|
|
6405
6381
|
} catch (e) {
|
|
6382
|
+
rethrowIfQuoteRejected(e);
|
|
6406
6383
|
throw new Error("Cannot quote swap", { cause: e });
|
|
6407
6384
|
}
|
|
6408
6385
|
}
|
|
6386
|
+
async getSwapQuote(swapId) {
|
|
6387
|
+
try {
|
|
6388
|
+
const res = await this.sendMessage({
|
|
6389
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6390
|
+
tag: this.messageTag,
|
|
6391
|
+
type: "GET_SWAP_QUOTE",
|
|
6392
|
+
payload: { swapId }
|
|
6393
|
+
});
|
|
6394
|
+
return res.payload.amount;
|
|
6395
|
+
} catch (e) {
|
|
6396
|
+
rethrowIfQuoteRejected(e);
|
|
6397
|
+
throw new Error("Cannot get swap quote", { cause: e });
|
|
6398
|
+
}
|
|
6399
|
+
}
|
|
6400
|
+
async acceptSwapQuote(swapId, amount, options) {
|
|
6401
|
+
try {
|
|
6402
|
+
const res = await this.sendMessage({
|
|
6403
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6404
|
+
tag: this.messageTag,
|
|
6405
|
+
type: "ACCEPT_SWAP_QUOTE",
|
|
6406
|
+
payload: { swapId, amount, options }
|
|
6407
|
+
});
|
|
6408
|
+
return res.payload.amount;
|
|
6409
|
+
} catch (e) {
|
|
6410
|
+
rethrowIfQuoteRejected(e);
|
|
6411
|
+
throw new Error("Cannot accept swap quote", { cause: e });
|
|
6412
|
+
}
|
|
6413
|
+
}
|
|
6409
6414
|
enrichReverseSwapPreimage(swap, preimage) {
|
|
6410
6415
|
return enrichReverseSwapPreimage(swap, preimage);
|
|
6411
6416
|
}
|
|
@@ -6413,9 +6418,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6413
6418
|
return enrichSubmarineSwapInvoice(swap, invoice);
|
|
6414
6419
|
}
|
|
6415
6420
|
createVHTLCScript(_args) {
|
|
6416
|
-
throw new Error(
|
|
6417
|
-
"createVHTLCScript is not supported via service worker"
|
|
6418
|
-
);
|
|
6421
|
+
throw new Error("createVHTLCScript is not supported via service worker");
|
|
6419
6422
|
}
|
|
6420
6423
|
async joinBatch(_identity, _input, _output, _arkInfo, _isRecoverable = true) {
|
|
6421
6424
|
throw new Error("joinBatch is not supported via service worker");
|
|
@@ -6426,7 +6429,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6426
6429
|
}
|
|
6427
6430
|
try {
|
|
6428
6431
|
const res = await this.sendMessage({
|
|
6429
|
-
id: getRandomId(),
|
|
6432
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6430
6433
|
tag: this.messageTag,
|
|
6431
6434
|
type: "GET_FEES",
|
|
6432
6435
|
...from !== void 0 && to !== void 0 ? { payload: { from, to } } : {}
|
|
@@ -6442,7 +6445,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6442
6445
|
}
|
|
6443
6446
|
try {
|
|
6444
6447
|
const res = await this.sendMessage({
|
|
6445
|
-
id: getRandomId(),
|
|
6448
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6446
6449
|
tag: this.messageTag,
|
|
6447
6450
|
type: "GET_LIMITS",
|
|
6448
6451
|
...from !== void 0 && to !== void 0 ? { payload: { from, to } } : {}
|
|
@@ -6455,7 +6458,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6455
6458
|
async getSwapStatus(swapId) {
|
|
6456
6459
|
try {
|
|
6457
6460
|
const res = await this.sendMessage({
|
|
6458
|
-
id: getRandomId(),
|
|
6461
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6459
6462
|
tag: this.messageTag,
|
|
6460
6463
|
type: "GET_SWAP_STATUS",
|
|
6461
6464
|
payload: { swapId }
|
|
@@ -6468,7 +6471,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6468
6471
|
async getPendingSubmarineSwaps() {
|
|
6469
6472
|
try {
|
|
6470
6473
|
const res = await this.sendMessage({
|
|
6471
|
-
id: getRandomId(),
|
|
6474
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6472
6475
|
tag: this.messageTag,
|
|
6473
6476
|
type: "GET_PENDING_SUBMARINE_SWAPS"
|
|
6474
6477
|
});
|
|
@@ -6482,7 +6485,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6482
6485
|
async getPendingReverseSwaps() {
|
|
6483
6486
|
try {
|
|
6484
6487
|
const res = await this.sendMessage({
|
|
6485
|
-
id: getRandomId(),
|
|
6488
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6486
6489
|
tag: this.messageTag,
|
|
6487
6490
|
type: "GET_PENDING_REVERSE_SWAPS"
|
|
6488
6491
|
});
|
|
@@ -6494,7 +6497,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6494
6497
|
async getPendingChainSwaps() {
|
|
6495
6498
|
try {
|
|
6496
6499
|
const res = await this.sendMessage({
|
|
6497
|
-
id: getRandomId(),
|
|
6500
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6498
6501
|
tag: this.messageTag,
|
|
6499
6502
|
type: "GET_PENDING_CHAIN_SWAPS"
|
|
6500
6503
|
});
|
|
@@ -6506,7 +6509,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6506
6509
|
async getSwapHistory() {
|
|
6507
6510
|
try {
|
|
6508
6511
|
const res = await this.sendMessage({
|
|
6509
|
-
id: getRandomId(),
|
|
6512
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6510
6513
|
tag: this.messageTag,
|
|
6511
6514
|
type: "GET_SWAP_HISTORY"
|
|
6512
6515
|
});
|
|
@@ -6517,7 +6520,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6517
6520
|
}
|
|
6518
6521
|
async refreshSwapsStatus() {
|
|
6519
6522
|
await this.sendMessage({
|
|
6520
|
-
id: getRandomId(),
|
|
6523
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6521
6524
|
tag: this.messageTag,
|
|
6522
6525
|
type: "REFRESH_SWAPS_STATUS"
|
|
6523
6526
|
});
|
|
@@ -6545,10 +6548,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6545
6548
|
return new Promise((resolve, reject) => {
|
|
6546
6549
|
const cleanup = () => {
|
|
6547
6550
|
clearTimeout(timeoutId);
|
|
6548
|
-
navigator.serviceWorker.removeEventListener(
|
|
6549
|
-
"message",
|
|
6550
|
-
messageHandler
|
|
6551
|
-
);
|
|
6551
|
+
navigator.serviceWorker.removeEventListener("message", messageHandler);
|
|
6552
6552
|
};
|
|
6553
6553
|
const timeoutId = timeoutMs > 0 ? setTimeout(() => {
|
|
6554
6554
|
cleanup();
|
|
@@ -6590,21 +6590,14 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6590
6590
|
pingServiceWorker() {
|
|
6591
6591
|
if (this.pingPromise) return this.pingPromise;
|
|
6592
6592
|
this.pingPromise = new Promise((resolve, reject) => {
|
|
6593
|
-
const pingId = getRandomId();
|
|
6593
|
+
const pingId = (0, import_sdk10.getRandomId)();
|
|
6594
6594
|
const cleanup = () => {
|
|
6595
6595
|
clearTimeout(timeoutId);
|
|
6596
|
-
navigator.serviceWorker.removeEventListener(
|
|
6597
|
-
"message",
|
|
6598
|
-
onMessage
|
|
6599
|
-
);
|
|
6596
|
+
navigator.serviceWorker.removeEventListener("message", onMessage);
|
|
6600
6597
|
};
|
|
6601
6598
|
const timeoutId = setTimeout(() => {
|
|
6602
6599
|
cleanup();
|
|
6603
|
-
reject(
|
|
6604
|
-
new import_sdk10.ServiceWorkerTimeoutError(
|
|
6605
|
-
"Service worker ping timed out"
|
|
6606
|
-
)
|
|
6607
|
-
);
|
|
6600
|
+
reject(new import_sdk10.ServiceWorkerTimeoutError("Service worker ping timed out"));
|
|
6608
6601
|
}, 2e3);
|
|
6609
6602
|
const onMessage = (event) => {
|
|
6610
6603
|
if (event.data?.id === pingId && event.data?.tag === "PONG") {
|
|
@@ -6632,9 +6625,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6632
6625
|
await this.reinitialize();
|
|
6633
6626
|
}
|
|
6634
6627
|
}
|
|
6635
|
-
const timeoutMs = LONG_RUNNING_ARKADE_SWAPS_REQUEST_TYPES.has(
|
|
6636
|
-
request.type
|
|
6637
|
-
) ? NO_MESSAGE_TIMEOUT_MS : DEFAULT_MESSAGE_TIMEOUT_MS;
|
|
6628
|
+
const timeoutMs = LONG_RUNNING_ARKADE_SWAPS_REQUEST_TYPES.has(request.type) ? NO_MESSAGE_TIMEOUT_MS : DEFAULT_MESSAGE_TIMEOUT_MS;
|
|
6638
6629
|
const maxRetries = 2;
|
|
6639
6630
|
for (let attempt = 0; ; attempt++) {
|
|
6640
6631
|
try {
|
|
@@ -6657,13 +6648,10 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6657
6648
|
const initMessage = {
|
|
6658
6649
|
tag: this.messageTag,
|
|
6659
6650
|
type: "INIT_ARKADE_SWAPS",
|
|
6660
|
-
id: getRandomId(),
|
|
6651
|
+
id: (0, import_sdk10.getRandomId)(),
|
|
6661
6652
|
payload: this.initPayload
|
|
6662
6653
|
};
|
|
6663
|
-
await this.sendMessageDirect(
|
|
6664
|
-
initMessage,
|
|
6665
|
-
DEFAULT_MESSAGE_TIMEOUT_MS
|
|
6666
|
-
);
|
|
6654
|
+
await this.sendMessageDirect(initMessage, DEFAULT_MESSAGE_TIMEOUT_MS);
|
|
6667
6655
|
})().finally(() => {
|
|
6668
6656
|
this.reinitPromise = null;
|
|
6669
6657
|
});
|
|
@@ -6672,10 +6660,7 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6672
6660
|
initEventStream() {
|
|
6673
6661
|
if (this.eventListenerInitialized) return;
|
|
6674
6662
|
this.eventListenerInitialized = true;
|
|
6675
|
-
navigator.serviceWorker.addEventListener(
|
|
6676
|
-
"message",
|
|
6677
|
-
this.handleEventMessage
|
|
6678
|
-
);
|
|
6663
|
+
navigator.serviceWorker.addEventListener("message", this.handleEventMessage);
|
|
6679
6664
|
}
|
|
6680
6665
|
handleEventMessage = (event) => {
|
|
6681
6666
|
const data = event.data;
|
|
@@ -6722,9 +6707,6 @@ var ServiceWorkerArkadeSwaps = class _ServiceWorkerArkadeSwaps {
|
|
|
6722
6707
|
}
|
|
6723
6708
|
};
|
|
6724
6709
|
};
|
|
6725
|
-
function getRandomId() {
|
|
6726
|
-
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
6727
|
-
}
|
|
6728
6710
|
|
|
6729
6711
|
// src/repositories/migrationFromContracts.ts
|
|
6730
6712
|
var MIGRATION_KEY = "migration-from-storage-adapter-swaps";
|
|
@@ -6734,8 +6716,14 @@ async function migrateToSwapRepository(storageAdapter, fresh) {
|
|
|
6734
6716
|
if (migration === "done") {
|
|
6735
6717
|
return false;
|
|
6736
6718
|
}
|
|
6737
|
-
const reverseSwaps = await getContractCollection(
|
|
6738
|
-
|
|
6719
|
+
const reverseSwaps = await getContractCollection(
|
|
6720
|
+
storageAdapter,
|
|
6721
|
+
"reverseSwaps"
|
|
6722
|
+
);
|
|
6723
|
+
const submarineSwaps = await getContractCollection(
|
|
6724
|
+
storageAdapter,
|
|
6725
|
+
"submarineSwaps"
|
|
6726
|
+
);
|
|
6739
6727
|
for (const swap of reverseSwaps) {
|
|
6740
6728
|
await fresh.saveSwap(swap);
|
|
6741
6729
|
}
|
|
@@ -6745,9 +6733,7 @@ async function migrateToSwapRepository(storageAdapter, fresh) {
|
|
|
6745
6733
|
await storageAdapter.setItem(MIGRATION_KEY, "done");
|
|
6746
6734
|
return true;
|
|
6747
6735
|
} catch (error) {
|
|
6748
|
-
if (error instanceof Error && error.message.includes(
|
|
6749
|
-
"One of the specified object stores was not found."
|
|
6750
|
-
)) {
|
|
6736
|
+
if (error instanceof Error && error.message.includes("One of the specified object stores was not found.")) {
|
|
6751
6737
|
return false;
|
|
6752
6738
|
}
|
|
6753
6739
|
throw error;
|
|
@@ -6765,6 +6751,30 @@ async function getContractCollection(storage, contractType) {
|
|
|
6765
6751
|
);
|
|
6766
6752
|
}
|
|
6767
6753
|
}
|
|
6754
|
+
|
|
6755
|
+
// src/repositories/inMemory/swap-repository.ts
|
|
6756
|
+
var InMemorySwapRepository = class {
|
|
6757
|
+
version = 1;
|
|
6758
|
+
swaps = /* @__PURE__ */ new Map();
|
|
6759
|
+
async saveSwap(swap) {
|
|
6760
|
+
this.swaps.set(swap.id, swap);
|
|
6761
|
+
}
|
|
6762
|
+
async deleteSwap(id) {
|
|
6763
|
+
this.swaps.delete(id);
|
|
6764
|
+
}
|
|
6765
|
+
async getAllSwaps(filter) {
|
|
6766
|
+
const swaps = [...this.swaps.values()];
|
|
6767
|
+
if (!filter || Object.keys(filter).length === 0) return swaps;
|
|
6768
|
+
const filtered = applySwapsFilter(swaps, filter);
|
|
6769
|
+
return applyCreatedAtOrder(filtered, filter);
|
|
6770
|
+
}
|
|
6771
|
+
async clear() {
|
|
6772
|
+
this.swaps.clear();
|
|
6773
|
+
}
|
|
6774
|
+
async [Symbol.asyncDispose]() {
|
|
6775
|
+
await this.clear();
|
|
6776
|
+
}
|
|
6777
|
+
};
|
|
6768
6778
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6769
6779
|
0 && (module.exports = {
|
|
6770
6780
|
ArkadeLightningMessageHandler,
|
|
@@ -6772,12 +6782,14 @@ async function getContractCollection(storage, contractType) {
|
|
|
6772
6782
|
ArkadeSwapsMessageHandler,
|
|
6773
6783
|
BoltzRefundError,
|
|
6774
6784
|
BoltzSwapProvider,
|
|
6785
|
+
InMemorySwapRepository,
|
|
6775
6786
|
IndexedDbSwapRepository,
|
|
6776
6787
|
InsufficientFundsError,
|
|
6777
6788
|
InvoiceExpiredError,
|
|
6778
6789
|
InvoiceFailedToPayError,
|
|
6779
6790
|
NetworkError,
|
|
6780
6791
|
PreimageFetchError,
|
|
6792
|
+
QuoteRejectedError,
|
|
6781
6793
|
SchemaError,
|
|
6782
6794
|
ServiceWorkerArkadeLightning,
|
|
6783
6795
|
ServiceWorkerArkadeSwaps,
|