@atomiqlabs/sdk 8.8.3 → 8.9.1
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/api/index.d.ts +1 -0
- package/api/index.js +3 -0
- package/dist/ApiList.d.ts +37 -0
- package/dist/ApiList.js +30 -0
- package/dist/api/ApiEndpoints.d.ts +393 -0
- package/dist/api/ApiEndpoints.js +2 -0
- package/dist/api/ApiParser.d.ts +10 -0
- package/dist/api/ApiParser.js +134 -0
- package/dist/api/ApiTypes.d.ts +157 -0
- package/dist/api/ApiTypes.js +75 -0
- package/dist/api/SerializedAction.d.ts +40 -0
- package/dist/api/SerializedAction.js +59 -0
- package/dist/api/SwapperApi.d.ts +50 -0
- package/dist/api/SwapperApi.js +431 -0
- package/dist/api/index.d.ts +5 -0
- package/dist/api/index.js +24 -0
- package/dist/events/UnifiedSwapEventListener.d.ts +4 -3
- package/dist/events/UnifiedSwapEventListener.js +8 -2
- package/dist/http/HttpUtils.d.ts +4 -2
- package/dist/http/HttpUtils.js +10 -4
- package/dist/http/paramcoders/client/StreamingFetchPromise.d.ts +2 -1
- package/dist/http/paramcoders/client/StreamingFetchPromise.js +3 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/intermediaries/IntermediaryDiscovery.d.ts +7 -2
- package/dist/intermediaries/IntermediaryDiscovery.js +4 -4
- package/dist/intermediaries/apis/IntermediaryAPI.d.ts +171 -14
- package/dist/intermediaries/apis/IntermediaryAPI.js +174 -28
- package/dist/intermediaries/auth/SignedKeyBasedAuth.d.ts +14 -0
- package/dist/intermediaries/auth/SignedKeyBasedAuth.js +68 -0
- package/dist/storage/IUnifiedStorage.d.ts +45 -3
- package/dist/storage/UnifiedSwapStorage.d.ts +8 -2
- package/dist/storage/UnifiedSwapStorage.js +46 -8
- package/dist/swapper/Swapper.d.ts +41 -3
- package/dist/swapper/Swapper.js +93 -48
- package/dist/swapper/SwapperUtils.d.ts +18 -2
- package/dist/swapper/SwapperUtils.js +39 -1
- package/dist/swaps/ISwap.d.ts +70 -9
- package/dist/swaps/ISwap.js +28 -6
- package/dist/swaps/ISwapWrapper.d.ts +11 -1
- package/dist/swaps/ISwapWrapper.js +23 -3
- package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +1 -1
- package/dist/swaps/escrow_swaps/IEscrowSwap.js +4 -2
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.d.ts +2 -1
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +2 -2
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.js +3 -2
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +47 -31
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +201 -67
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +6 -6
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +82 -15
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +304 -98
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +6 -6
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +75 -42
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +424 -87
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +7 -7
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +54 -11
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +214 -41
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +2 -1
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +7 -8
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +5 -5
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +76 -19
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +290 -51
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +3 -1
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +5 -5
- package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +53 -12
- package/dist/swaps/trusted/ln/LnForGasSwap.js +163 -49
- package/dist/swaps/trusted/ln/LnForGasWrapper.js +1 -2
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +14 -13
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.js +30 -47
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.d.ts +3 -1
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +4 -4
- package/dist/types/SwapExecutionAction.d.ts +141 -34
- package/dist/types/SwapExecutionAction.js +104 -0
- package/dist/types/SwapExecutionStep.d.ts +144 -0
- package/dist/types/SwapExecutionStep.js +87 -0
- package/dist/types/TokenAmount.d.ts +6 -0
- package/dist/types/TokenAmount.js +26 -1
- package/dist/utils/BitcoinUtils.d.ts +2 -0
- package/dist/utils/BitcoinUtils.js +34 -1
- package/dist/utils/Utils.d.ts +3 -1
- package/dist/utils/Utils.js +7 -1
- package/package.json +7 -4
- package/src/api/ApiEndpoints.ts +427 -0
- package/src/api/ApiParser.ts +138 -0
- package/src/api/ApiTypes.ts +229 -0
- package/src/api/SerializedAction.ts +97 -0
- package/src/api/SwapperApi.ts +545 -0
- package/src/api/index.ts +5 -0
- package/src/events/UnifiedSwapEventListener.ts +11 -3
- package/src/http/HttpUtils.ts +10 -4
- package/src/http/paramcoders/client/StreamingFetchPromise.ts +4 -2
- package/src/index.ts +1 -0
- package/src/intermediaries/IntermediaryDiscovery.ts +9 -2
- package/src/intermediaries/apis/IntermediaryAPI.ts +314 -30
- package/src/intermediaries/auth/SignedKeyBasedAuth.ts +69 -0
- package/src/storage/IUnifiedStorage.ts +45 -4
- package/src/storage/UnifiedSwapStorage.ts +42 -8
- package/src/swapper/Swapper.ts +134 -52
- package/src/swapper/SwapperUtils.ts +42 -2
- package/src/swaps/ISwap.ts +88 -16
- package/src/swaps/ISwapWrapper.ts +28 -3
- package/src/swaps/escrow_swaps/IEscrowSwap.ts +5 -3
- package/src/swaps/escrow_swaps/IEscrowSwapWrapper.ts +3 -1
- package/src/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.ts +4 -1
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +264 -67
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +6 -4
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +390 -89
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +6 -4
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +548 -94
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +7 -5
- package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +276 -45
- package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +7 -6
- package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +5 -3
- package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +393 -57
- package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +5 -3
- package/src/swaps/trusted/ln/LnForGasSwap.ts +211 -47
- package/src/swaps/trusted/ln/LnForGasWrapper.ts +1 -2
- package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +32 -51
- package/src/swaps/trusted/onchain/OnchainForGasWrapper.ts +5 -3
- package/src/types/SwapExecutionAction.ts +266 -43
- package/src/types/SwapExecutionStep.ts +224 -0
- package/src/types/TokenAmount.ts +36 -2
- package/src/utils/BitcoinUtils.ts +32 -0
- package/src/utils/Utils.ts +10 -1
- package/src/intermediaries/apis/TrustedIntermediaryAPI.ts +0 -258
|
@@ -2,9 +2,9 @@ import {decode as bolt11Decode} from "@atomiqlabs/bolt11";
|
|
|
2
2
|
import {SwapType} from "../../../enums/SwapType";
|
|
3
3
|
import {ChainType} from "@atomiqlabs/base";
|
|
4
4
|
import {LnForGasSwapTypeDefinition, LnForGasWrapper} from "./LnForGasWrapper";
|
|
5
|
-
import {toBigInt} from "../../../utils/Utils";
|
|
5
|
+
import {extendAbortController, toBigInt} from "../../../utils/Utils";
|
|
6
6
|
import {isISwapInit, ISwap, ISwapInit} from "../../ISwap";
|
|
7
|
-
import {
|
|
7
|
+
import {TrustedInvoiceStatusResponseCodes} from "../../../intermediaries/apis/IntermediaryAPI";
|
|
8
8
|
import {Fee} from "../../../types/fees/Fee";
|
|
9
9
|
import {IAddressSwap} from "../../IAddressSwap";
|
|
10
10
|
import {FeeType} from "../../../enums/FeeType";
|
|
@@ -13,7 +13,15 @@ import {TokenAmount, toTokenAmount} from "../../../types/TokenAmount";
|
|
|
13
13
|
import {BitcoinTokens, BtcToken, SCToken} from "../../../types/Token";
|
|
14
14
|
import {getLogger, LoggerType} from "../../../utils/Logger";
|
|
15
15
|
import {timeoutPromise} from "../../../utils/TimeoutUtils";
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
SwapExecutionActionSendToAddress,
|
|
18
|
+
SwapExecutionActionWait
|
|
19
|
+
} from "../../../types/SwapExecutionAction";
|
|
20
|
+
import {
|
|
21
|
+
SwapExecutionStepPayment,
|
|
22
|
+
SwapExecutionStepSettlement
|
|
23
|
+
} from "../../../types/SwapExecutionStep";
|
|
24
|
+
import {SwapStateInfo} from "../../../types/SwapStateInfo";
|
|
17
25
|
|
|
18
26
|
/**
|
|
19
27
|
* State enum for trusted Lightning gas swaps
|
|
@@ -22,38 +30,38 @@ import {SwapExecutionAction, SwapExecutionActionLightning} from "../../../types/
|
|
|
22
30
|
*/
|
|
23
31
|
export enum LnForGasSwapState {
|
|
24
32
|
/**
|
|
25
|
-
* The swap quote expired
|
|
33
|
+
* The swap quote expired before the user paid the Lightning invoice
|
|
26
34
|
*/
|
|
27
35
|
EXPIRED = -2,
|
|
28
36
|
/**
|
|
29
|
-
* The swap has failed
|
|
37
|
+
* The swap has failed before the destination payout completed, and the held Lightning invoice was released
|
|
30
38
|
*/
|
|
31
39
|
FAILED = -1,
|
|
32
40
|
/**
|
|
33
|
-
* Swap was created, pay the provided
|
|
41
|
+
* Swap was created, pay the provided Lightning invoice which will remain held until destination payout succeeds
|
|
34
42
|
*/
|
|
35
43
|
PR_CREATED = 0,
|
|
36
44
|
/**
|
|
37
|
-
*
|
|
45
|
+
* The Lightning invoice was paid and is currently held until the user receives the destination funds
|
|
38
46
|
*/
|
|
39
47
|
PR_PAID = 1,
|
|
40
48
|
/**
|
|
41
|
-
* The swap is finished after the
|
|
49
|
+
* The swap is finished after the destination payout succeeded and the held Lightning invoice was settled
|
|
42
50
|
*/
|
|
43
51
|
FINISHED = 2
|
|
44
52
|
}
|
|
45
53
|
|
|
46
54
|
const LnForGasSwapStateDescription = {
|
|
47
55
|
[LnForGasSwapState.EXPIRED]:
|
|
48
|
-
"The swap quote expired
|
|
56
|
+
"The swap quote expired before the user paid the Lightning invoice",
|
|
49
57
|
[LnForGasSwapState.FAILED]:
|
|
50
|
-
"The swap
|
|
58
|
+
"The swap failed before destination payout completed, and the held Lightning invoice was released back to the user",
|
|
51
59
|
[LnForGasSwapState.PR_CREATED]:
|
|
52
|
-
"Swap was created, pay the provided
|
|
60
|
+
"Swap was created, pay the provided Lightning invoice. The invoice will remain held until destination payout succeeds",
|
|
53
61
|
[LnForGasSwapState.PR_PAID]:
|
|
54
|
-
"
|
|
62
|
+
"The Lightning invoice was paid and is currently held. It will only settle once the user receives the destination funds",
|
|
55
63
|
[LnForGasSwapState.FINISHED]:
|
|
56
|
-
"The swap is finished after the
|
|
64
|
+
"The swap is finished after the destination payout succeeded and the held Lightning invoice was settled"
|
|
57
65
|
}
|
|
58
66
|
|
|
59
67
|
export type LnForGasSwapInit = ISwapInit & {
|
|
@@ -403,46 +411,191 @@ export class LnForGasSwap<T extends ChainType = ChainType> extends ISwap<T, LnFo
|
|
|
403
411
|
//// Payment
|
|
404
412
|
|
|
405
413
|
/**
|
|
406
|
-
* @
|
|
414
|
+
* @remarks Not supported
|
|
407
415
|
*/
|
|
408
|
-
async
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
416
|
+
async execute(): Promise<boolean> {
|
|
417
|
+
throw new Error("Not supported");
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* @internal
|
|
422
|
+
*/
|
|
423
|
+
protected async _getExecutionStatus() {
|
|
424
|
+
const state = this._state;
|
|
425
|
+
|
|
426
|
+
let lightningPaymentStatus: SwapExecutionStepPayment<"LIGHTNING">["status"] = "inactive";
|
|
427
|
+
let destinationSettlementStatus: SwapExecutionStepSettlement<T["ChainId"]>["status"] = "inactive";
|
|
428
|
+
let buildCurrentAction: () => Promise<
|
|
429
|
+
SwapExecutionActionSendToAddress<true> |
|
|
430
|
+
SwapExecutionActionWait<"LP"> |
|
|
431
|
+
undefined
|
|
432
|
+
> = async () => undefined;
|
|
433
|
+
|
|
434
|
+
switch(state) {
|
|
435
|
+
case LnForGasSwapState.PR_CREATED: {
|
|
436
|
+
const quoteValid = await this._verifyQuoteValid();
|
|
437
|
+
lightningPaymentStatus = quoteValid ? "awaiting" : "soft_expired";
|
|
438
|
+
if(quoteValid) {
|
|
439
|
+
buildCurrentAction = this._buildLightningPaymentAction.bind(this);
|
|
440
|
+
}
|
|
441
|
+
break;
|
|
442
|
+
}
|
|
443
|
+
case LnForGasSwapState.EXPIRED:
|
|
444
|
+
lightningPaymentStatus = "expired";
|
|
445
|
+
break;
|
|
446
|
+
case LnForGasSwapState.PR_PAID:
|
|
447
|
+
lightningPaymentStatus = "received";
|
|
448
|
+
destinationSettlementStatus = "waiting_lp";
|
|
449
|
+
buildCurrentAction = this._buildWaitLpAction.bind(this);
|
|
450
|
+
break;
|
|
451
|
+
case LnForGasSwapState.FAILED:
|
|
452
|
+
lightningPaymentStatus = "expired";
|
|
453
|
+
destinationSettlementStatus = "expired";
|
|
454
|
+
break;
|
|
455
|
+
case LnForGasSwapState.FINISHED:
|
|
456
|
+
lightningPaymentStatus = "confirmed";
|
|
457
|
+
destinationSettlementStatus = "settled";
|
|
458
|
+
break;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
return {
|
|
462
|
+
steps: [
|
|
412
463
|
{
|
|
413
|
-
|
|
414
|
-
|
|
464
|
+
type: "Payment",
|
|
465
|
+
side: "source",
|
|
415
466
|
chain: "LIGHTNING",
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
467
|
+
title: "Lightning payment",
|
|
468
|
+
description: "Pay the Lightning network invoice to initiate the swap",
|
|
469
|
+
status: lightningPaymentStatus
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
type: "Settlement",
|
|
473
|
+
side: "destination",
|
|
474
|
+
chain: this.chainIdentifier,
|
|
475
|
+
title: "Destination payout",
|
|
476
|
+
description: "Wait for the intermediary to send the gas tokens on the destination smart chain",
|
|
477
|
+
status: destinationSettlementStatus
|
|
478
|
+
}
|
|
479
|
+
] as [
|
|
480
|
+
SwapExecutionStepPayment<"LIGHTNING">,
|
|
481
|
+
SwapExecutionStepSettlement<T["ChainId"], never>
|
|
482
|
+
],
|
|
483
|
+
buildCurrentAction,
|
|
484
|
+
state
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* @internal
|
|
490
|
+
* @inheritDoc
|
|
491
|
+
*/
|
|
492
|
+
_submitExecutionTransactions(): Promise<string[]> {
|
|
493
|
+
throw new Error("Invalid swap state for transaction submission!");
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* @internal
|
|
498
|
+
*/
|
|
499
|
+
private async _buildLightningPaymentAction(): Promise<SwapExecutionActionSendToAddress<true>> {
|
|
500
|
+
return {
|
|
501
|
+
type: "SendToAddress",
|
|
502
|
+
name: "Deposit on Lightning",
|
|
503
|
+
description: "Pay the lightning network invoice to initiate the swap",
|
|
504
|
+
chain: "LIGHTNING",
|
|
505
|
+
txs: [{
|
|
506
|
+
type: "BOLT11_PAYMENT_REQUEST",
|
|
507
|
+
address: this.pr,
|
|
508
|
+
hyperlink: this.getHyperlink(),
|
|
509
|
+
amount: this.getInput()
|
|
510
|
+
}],
|
|
511
|
+
waitForTransactions: async (
|
|
512
|
+
maxWaitTimeSeconds?: number, pollIntervalSeconds?: number, abortSignal?: AbortSignal
|
|
513
|
+
) => {
|
|
514
|
+
const abortController = extendAbortController(
|
|
515
|
+
abortSignal, maxWaitTimeSeconds, "Timed out waiting for lightning payment"
|
|
516
|
+
);
|
|
517
|
+
let lightningTxId: string | undefined;
|
|
518
|
+
try {
|
|
519
|
+
const success = await this.waitForPayment(
|
|
520
|
+
pollIntervalSeconds, abortController.signal,
|
|
521
|
+
(txId: string) => {
|
|
522
|
+
lightningTxId = txId;
|
|
523
|
+
abortController.abort();
|
|
421
524
|
}
|
|
422
|
-
|
|
525
|
+
);
|
|
526
|
+
if(!success) throw new Error("Quote expired while waiting for lightning payment");
|
|
527
|
+
} catch (e) {
|
|
528
|
+
if(lightningTxId!=null) return lightningTxId;
|
|
529
|
+
throw e;
|
|
423
530
|
}
|
|
424
|
-
|
|
425
|
-
|
|
531
|
+
return this.getInputTxId()!;
|
|
532
|
+
}
|
|
533
|
+
} as SwapExecutionActionSendToAddress<true>;
|
|
534
|
+
}
|
|
426
535
|
|
|
427
|
-
|
|
536
|
+
/**
|
|
537
|
+
* @internal
|
|
538
|
+
*/
|
|
539
|
+
private async _buildWaitLpAction(): Promise<SwapExecutionActionWait<"LP">> {
|
|
540
|
+
return {
|
|
541
|
+
type: "Wait",
|
|
542
|
+
name: "Awaiting LP payout",
|
|
543
|
+
description: "Wait for the intermediary to send the gas tokens on the destination smart chain",
|
|
544
|
+
pollTimeSeconds: 5,
|
|
545
|
+
expectedTimeSeconds: 10,
|
|
546
|
+
wait: async (
|
|
547
|
+
maxWaitTimeSeconds?: number, pollIntervalSeconds?: number, abortSignal?: AbortSignal
|
|
548
|
+
) => {
|
|
549
|
+
const abortController = extendAbortController(
|
|
550
|
+
abortSignal, maxWaitTimeSeconds, "Timed out waiting for LP payout"
|
|
551
|
+
);
|
|
552
|
+
await this.waitForPayment(pollIntervalSeconds, abortController.signal);
|
|
553
|
+
}
|
|
554
|
+
} as SwapExecutionActionWait<"LP">;
|
|
428
555
|
}
|
|
429
556
|
|
|
430
557
|
/**
|
|
431
|
-
* @
|
|
558
|
+
* @inheritDoc
|
|
432
559
|
*/
|
|
433
|
-
async
|
|
434
|
-
|
|
560
|
+
async getExecutionAction(): Promise<
|
|
561
|
+
SwapExecutionActionSendToAddress<true> |
|
|
562
|
+
SwapExecutionActionWait<"LP"> |
|
|
563
|
+
undefined
|
|
564
|
+
> {
|
|
565
|
+
const executionStatus = await this._getExecutionStatus();
|
|
566
|
+
return executionStatus.buildCurrentAction();
|
|
435
567
|
}
|
|
436
568
|
|
|
437
569
|
/**
|
|
438
570
|
* @inheritDoc
|
|
439
571
|
*/
|
|
440
|
-
async
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
572
|
+
async getExecutionStatus(options?: {skipBuildingAction?: boolean}): Promise<{
|
|
573
|
+
steps: [
|
|
574
|
+
SwapExecutionStepPayment<"LIGHTNING">,
|
|
575
|
+
SwapExecutionStepSettlement<T["ChainId"], never>
|
|
576
|
+
],
|
|
577
|
+
currentAction:
|
|
578
|
+
SwapExecutionActionSendToAddress<true> |
|
|
579
|
+
SwapExecutionActionWait<"LP"> |
|
|
580
|
+
undefined,
|
|
581
|
+
stateInfo: SwapStateInfo<LnForGasSwapState>
|
|
582
|
+
}> {
|
|
583
|
+
const executionStatus = await this._getExecutionStatus();
|
|
584
|
+
return {
|
|
585
|
+
steps: executionStatus.steps,
|
|
586
|
+
currentAction: options?.skipBuildingAction ? undefined : await executionStatus.buildCurrentAction(),
|
|
587
|
+
stateInfo: this._getStateInfo(executionStatus.state)
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* @inheritDoc
|
|
593
|
+
*/
|
|
594
|
+
async getExecutionSteps(): Promise<[
|
|
595
|
+
SwapExecutionStepPayment<"LIGHTNING">,
|
|
596
|
+
SwapExecutionStepSettlement<T["ChainId"], never>
|
|
597
|
+
]> {
|
|
598
|
+
return (await this._getExecutionStatus()).steps;
|
|
446
599
|
}
|
|
447
600
|
|
|
448
601
|
/**
|
|
@@ -462,12 +615,12 @@ export class LnForGasSwap<T extends ChainType = ChainType> extends ISwap<T, LnFo
|
|
|
462
615
|
const paymentHash = decodedPR.tagsObject.payment_hash;
|
|
463
616
|
if(paymentHash==null) throw new Error("Invalid swap invoice, payment hash not found!");
|
|
464
617
|
|
|
465
|
-
const response = await
|
|
618
|
+
const response = await this.wrapper._lpApi.getTrustedInvoiceStatus(
|
|
466
619
|
this.url, paymentHash, this.wrapper._options.getRequestTimeout
|
|
467
620
|
);
|
|
468
621
|
this.logger.debug("checkInvoicePaid(): LP response: ", response);
|
|
469
622
|
switch(response.code) {
|
|
470
|
-
case
|
|
623
|
+
case TrustedInvoiceStatusResponseCodes.PAID:
|
|
471
624
|
this.scTxId = response.data.txId;
|
|
472
625
|
const txStatus = await this.wrapper._chain.getTxIdStatus(this.scTxId);
|
|
473
626
|
if(txStatus==="success") {
|
|
@@ -476,7 +629,7 @@ export class LnForGasSwap<T extends ChainType = ChainType> extends ISwap<T, LnFo
|
|
|
476
629
|
return true;
|
|
477
630
|
}
|
|
478
631
|
return null;
|
|
479
|
-
case
|
|
632
|
+
case TrustedInvoiceStatusResponseCodes.EXPIRED:
|
|
480
633
|
if(this._state===LnForGasSwapState.PR_CREATED) {
|
|
481
634
|
this._state = LnForGasSwapState.EXPIRED;
|
|
482
635
|
} else {
|
|
@@ -484,20 +637,20 @@ export class LnForGasSwap<T extends ChainType = ChainType> extends ISwap<T, LnFo
|
|
|
484
637
|
}
|
|
485
638
|
if(save) await this._saveAndEmit();
|
|
486
639
|
return false;
|
|
487
|
-
case
|
|
640
|
+
case TrustedInvoiceStatusResponseCodes.TX_SENT:
|
|
488
641
|
this.scTxId = response.data.txId;
|
|
489
642
|
if(this._state===LnForGasSwapState.PR_CREATED) {
|
|
490
643
|
this._state = LnForGasSwapState.PR_PAID;
|
|
491
644
|
if(save) await this._saveAndEmit();
|
|
492
645
|
}
|
|
493
646
|
return null;
|
|
494
|
-
case
|
|
647
|
+
case TrustedInvoiceStatusResponseCodes.PENDING:
|
|
495
648
|
if(this._state===LnForGasSwapState.PR_CREATED) {
|
|
496
649
|
this._state = LnForGasSwapState.PR_PAID;
|
|
497
650
|
if(save) await this._saveAndEmit();
|
|
498
651
|
}
|
|
499
652
|
return null;
|
|
500
|
-
case
|
|
653
|
+
case TrustedInvoiceStatusResponseCodes.AWAIT_PAYMENT:
|
|
501
654
|
return null;
|
|
502
655
|
default:
|
|
503
656
|
this._state = LnForGasSwapState.FAILED;
|
|
@@ -508,14 +661,17 @@ export class LnForGasSwap<T extends ChainType = ChainType> extends ISwap<T, LnFo
|
|
|
508
661
|
|
|
509
662
|
/**
|
|
510
663
|
* A blocking promise resolving when payment was received by the intermediary and client can continue,
|
|
511
|
-
* rejecting in case of failure. The swap must be in {@link LnForGasSwapState.PR_CREATED}
|
|
664
|
+
* rejecting in case of failure. The swap must be in {@link LnForGasSwapState.PR_CREATED} or
|
|
665
|
+
* {@link LnForGasSwapState.PR_PAID} state!
|
|
512
666
|
*
|
|
513
667
|
* @param checkIntervalSeconds How often to poll the intermediary for answer (default 5 seconds)
|
|
514
668
|
* @param abortSignal Abort signal
|
|
669
|
+
* @param onPaymentReceived Callback as for when the LP reports having received the ln payment
|
|
515
670
|
* @throws {Error} When in invalid state (not PR_CREATED)
|
|
516
671
|
*/
|
|
517
|
-
async waitForPayment(checkIntervalSeconds?: number, abortSignal?: AbortSignal): Promise<boolean> {
|
|
518
|
-
if(this._state!==LnForGasSwapState.PR_CREATED
|
|
672
|
+
async waitForPayment(checkIntervalSeconds?: number, abortSignal?: AbortSignal, onPaymentReceived?: (txId: string) => void): Promise<boolean> {
|
|
673
|
+
if(this._state!==LnForGasSwapState.PR_CREATED && this._state!==LnForGasSwapState.PR_PAID)
|
|
674
|
+
throw new Error("Must be in PR_CREATED or PR_PAID state!");
|
|
519
675
|
|
|
520
676
|
if(!this.initiated) {
|
|
521
677
|
this.initiated = true;
|
|
@@ -524,9 +680,17 @@ export class LnForGasSwap<T extends ChainType = ChainType> extends ISwap<T, LnFo
|
|
|
524
680
|
|
|
525
681
|
while(!abortSignal?.aborted && (this._state===LnForGasSwapState.PR_CREATED || this._state===LnForGasSwapState.PR_PAID)) {
|
|
526
682
|
await this.checkInvoicePaid(true);
|
|
683
|
+
if((this._state as LnForGasSwapState)===LnForGasSwapState.PR_PAID) {
|
|
684
|
+
if(onPaymentReceived!=null) {
|
|
685
|
+
onPaymentReceived(this.getInputTxId()!);
|
|
686
|
+
onPaymentReceived = undefined; // Set to null so it only triggers once
|
|
687
|
+
}
|
|
688
|
+
}
|
|
527
689
|
if(this._state===LnForGasSwapState.PR_CREATED || this._state===LnForGasSwapState.PR_PAID) await timeoutPromise((checkIntervalSeconds ?? 5)*1000, abortSignal);
|
|
528
690
|
}
|
|
529
691
|
|
|
692
|
+
if(abortSignal!=null) abortSignal.throwIfAborted();
|
|
693
|
+
|
|
530
694
|
if(this.isFailed()) throw new Error("Swap failed");
|
|
531
695
|
return !this.isQuoteExpired();
|
|
532
696
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {LnForGasSwap, LnForGasSwapInit, LnForGasSwapState} from "./LnForGasSwap";
|
|
2
2
|
import {ISwapWrapper, SwapTypeDefinition} from "../../ISwapWrapper";
|
|
3
|
-
import {TrustedIntermediaryAPI} from "../../../intermediaries/apis/TrustedIntermediaryAPI";
|
|
4
3
|
import {decode as bolt11Decode} from "@atomiqlabs/bolt11";
|
|
5
4
|
import {IntermediaryError} from "../../../errors/IntermediaryError";
|
|
6
5
|
import {ChainType} from "@atomiqlabs/base";
|
|
@@ -50,7 +49,7 @@ export class LnForGasWrapper<T extends ChainType> extends ISwapWrapper<T, LnForG
|
|
|
50
49
|
|
|
51
50
|
const token = this._chain.getNativeCurrencyAddress();
|
|
52
51
|
|
|
53
|
-
const resp = await
|
|
52
|
+
const resp = await this._lpApi.initTrustedFromBTCLN(this.chainIdentifier, lpUrl, {
|
|
54
53
|
address: recipient,
|
|
55
54
|
amount,
|
|
56
55
|
token
|
|
@@ -3,7 +3,7 @@ import {ChainType} from "@atomiqlabs/base";
|
|
|
3
3
|
import {toBigInt} from "../../../utils/Utils";
|
|
4
4
|
import {parsePsbtTransaction, toOutputScript} from "../../../utils/BitcoinUtils";
|
|
5
5
|
import {isISwapInit, ISwap, ISwapInit} from "../../ISwap";
|
|
6
|
-
import {
|
|
6
|
+
import {TrustedAddressStatusResponseCodes} from "../../../intermediaries/apis/IntermediaryAPI";
|
|
7
7
|
import {OnchainForGasSwapTypeDefinition, OnchainForGasWrapper} from "./OnchainForGasWrapper";
|
|
8
8
|
import {Fee} from "../../../types/fees/Fee";
|
|
9
9
|
import {IBitcoinWallet, isIBitcoinWallet} from "../../../bitcoin/wallet/IBitcoinWallet";
|
|
@@ -23,7 +23,6 @@ import {BitcoinTokens, BtcToken, SCToken} from "../../../types/Token";
|
|
|
23
23
|
import {getLogger, LoggerType} from "../../../utils/Logger";
|
|
24
24
|
import {timeoutPromise} from "../../../utils/TimeoutUtils";
|
|
25
25
|
import {toBitcoinWallet} from "../../../utils/BitcoinWalletUtils";
|
|
26
|
-
import {SwapExecutionAction, SwapExecutionActionBitcoin} from "../../../types/SwapExecutionAction";
|
|
27
26
|
|
|
28
27
|
/**
|
|
29
28
|
* State enum for trusted on-chain gas swaps
|
|
@@ -562,57 +561,39 @@ export class OnchainForGasSwap<T extends ChainType = ChainType> extends ISwap<T,
|
|
|
562
561
|
* @param options.bitcoinWallet Optional bitcoin wallet address specification to return a funded PSBT,
|
|
563
562
|
* if not provided an address is returned instead.
|
|
564
563
|
*/
|
|
565
|
-
async
|
|
564
|
+
async getExecutionAction(options?: {
|
|
566
565
|
bitcoinWallet?: MinimalBitcoinWalletInterface
|
|
567
|
-
}): Promise<
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
if(this._state===OnchainForGasSwapState.PR_CREATED) {
|
|
571
|
-
if(!await this._verifyQuoteValid()) throw new Error("Quote already expired or close to expiry!");
|
|
572
|
-
return [
|
|
573
|
-
{
|
|
574
|
-
name: "Payment" as const,
|
|
575
|
-
description: "Send funds to the bitcoin swap address",
|
|
576
|
-
chain: "BITCOIN",
|
|
577
|
-
txs: [
|
|
578
|
-
options?.bitcoinWallet==null ? {
|
|
579
|
-
address: this.address,
|
|
580
|
-
amount: Number(this.inputAmount),
|
|
581
|
-
hyperlink: this.getHyperlink(),
|
|
582
|
-
type: "ADDRESS"
|
|
583
|
-
} : {
|
|
584
|
-
...await this.getFundedPsbt(options.bitcoinWallet),
|
|
585
|
-
type: "FUNDED_PSBT"
|
|
586
|
-
}
|
|
587
|
-
]
|
|
588
|
-
}
|
|
589
|
-
];
|
|
590
|
-
}
|
|
566
|
+
}): Promise<never> {
|
|
567
|
+
throw new Error("Not supported");
|
|
568
|
+
}
|
|
591
569
|
|
|
592
|
-
|
|
570
|
+
/**
|
|
571
|
+
* @inheritDoc
|
|
572
|
+
*/
|
|
573
|
+
async getExecutionSteps(): Promise<never> {
|
|
574
|
+
throw new Error("Not supported");
|
|
593
575
|
}
|
|
594
576
|
|
|
595
577
|
/**
|
|
596
|
-
* @
|
|
578
|
+
* @inheritDoc
|
|
597
579
|
*/
|
|
598
|
-
async
|
|
580
|
+
async getExecutionStatus(): Promise<never> {
|
|
599
581
|
throw new Error("Not supported");
|
|
600
582
|
}
|
|
601
583
|
|
|
602
584
|
/**
|
|
585
|
+
* @internal
|
|
603
586
|
* @inheritDoc
|
|
604
|
-
*
|
|
605
|
-
* @param options.bitcoinWallet Optional bitcoin wallet address specification to return a funded PSBT,
|
|
606
|
-
* if not provided an address is returned instead.
|
|
607
587
|
*/
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
588
|
+
_submitExecutionTransactions(): Promise<string[]> {
|
|
589
|
+
throw new Error("Not supported");
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* @remarks Not supported
|
|
594
|
+
*/
|
|
595
|
+
async execute(): Promise<boolean> {
|
|
596
|
+
throw new Error("Not supported");
|
|
616
597
|
}
|
|
617
598
|
|
|
618
599
|
//////////////////////////////
|
|
@@ -635,20 +616,20 @@ export class OnchainForGasSwap<T extends ChainType = ChainType> extends ISwap<T,
|
|
|
635
616
|
if(this._state===OnchainForGasSwapState.FINISHED) return false;
|
|
636
617
|
if(this.url==null) return false;
|
|
637
618
|
|
|
638
|
-
const response = await
|
|
619
|
+
const response = await this.wrapper._lpApi.getTrustedAddressStatus(
|
|
639
620
|
this.url, this.paymentHash, this.sequence, this.wrapper._options.getRequestTimeout
|
|
640
621
|
);
|
|
641
622
|
switch(response.code) {
|
|
642
|
-
case
|
|
623
|
+
case TrustedAddressStatusResponseCodes.AWAIT_PAYMENT:
|
|
643
624
|
if(this.txId!=null) {
|
|
644
625
|
this.txId = undefined;
|
|
645
626
|
if(save) await this._save();
|
|
646
627
|
return true;
|
|
647
628
|
}
|
|
648
629
|
return false;
|
|
649
|
-
case
|
|
650
|
-
case
|
|
651
|
-
case
|
|
630
|
+
case TrustedAddressStatusResponseCodes.AWAIT_CONFIRMATION:
|
|
631
|
+
case TrustedAddressStatusResponseCodes.PENDING:
|
|
632
|
+
case TrustedAddressStatusResponseCodes.TX_SENT:
|
|
652
633
|
const inputAmount = BigInt(response.data.adjustedAmount);
|
|
653
634
|
const outputAmount = BigInt(response.data.adjustedTotal);
|
|
654
635
|
const adjustedFee = response.data.adjustedFee==null ? null : BigInt(response.data.adjustedFee);
|
|
@@ -668,7 +649,7 @@ export class OnchainForGasSwap<T extends ChainType = ChainType> extends ISwap<T,
|
|
|
668
649
|
return true;
|
|
669
650
|
}
|
|
670
651
|
return false;
|
|
671
|
-
case
|
|
652
|
+
case TrustedAddressStatusResponseCodes.PAID:
|
|
672
653
|
const txStatus = await this.wrapper._chain.getTxIdStatus(response.data.txId);
|
|
673
654
|
if(txStatus==="success") {
|
|
674
655
|
this._state = OnchainForGasSwapState.FINISHED;
|
|
@@ -677,16 +658,16 @@ export class OnchainForGasSwap<T extends ChainType = ChainType> extends ISwap<T,
|
|
|
677
658
|
return true;
|
|
678
659
|
}
|
|
679
660
|
return false;
|
|
680
|
-
case
|
|
661
|
+
case TrustedAddressStatusResponseCodes.EXPIRED:
|
|
681
662
|
this._state = OnchainForGasSwapState.EXPIRED;
|
|
682
663
|
if(save) await this._saveAndEmit();
|
|
683
664
|
return true;
|
|
684
|
-
case
|
|
665
|
+
case TrustedAddressStatusResponseCodes.REFUNDABLE:
|
|
685
666
|
if(this._state===OnchainForGasSwapState.REFUNDABLE) return null;
|
|
686
667
|
this._state = OnchainForGasSwapState.REFUNDABLE;
|
|
687
668
|
if(save) await this._saveAndEmit();
|
|
688
669
|
return true;
|
|
689
|
-
case
|
|
670
|
+
case TrustedAddressStatusResponseCodes.REFUNDED:
|
|
690
671
|
this._state = OnchainForGasSwapState.REFUNDED;
|
|
691
672
|
this.refundTxId = response.data.txId;
|
|
692
673
|
if(save) await this._saveAndEmit();
|
|
@@ -710,7 +691,7 @@ export class OnchainForGasSwap<T extends ChainType = ChainType> extends ISwap<T,
|
|
|
710
691
|
return;
|
|
711
692
|
}
|
|
712
693
|
if(this.url==null) throw new Error("LP URL not known, cannot set refund address!");
|
|
713
|
-
await
|
|
694
|
+
await this.wrapper._lpApi.setTrustedRefundAddress(
|
|
714
695
|
this.url, this.paymentHash, this.sequence, refundAddress, this.wrapper._options.getRequestTimeout
|
|
715
696
|
);
|
|
716
697
|
this.refundAddress = refundAddress;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {ISwapWrapper, ISwapWrapperOptions, SwapTypeDefinition, WrapperCtorTokens} from "../../ISwapWrapper";
|
|
2
|
-
import {TrustedIntermediaryAPI} from "../../../intermediaries/apis/TrustedIntermediaryAPI";
|
|
3
2
|
import {IntermediaryError} from "../../../errors/IntermediaryError";
|
|
4
3
|
import {BitcoinRpcWithAddressIndex, ChainType} from "@atomiqlabs/base";
|
|
5
4
|
import {OnchainForGasSwap, OnchainForGasSwapInit, OnchainForGasSwapState} from "./OnchainForGasSwap";
|
|
@@ -11,6 +10,7 @@ import {UnifiedSwapEventListener} from "../../../events/UnifiedSwapEventListener
|
|
|
11
10
|
import {UnifiedSwapStorage} from "../../../storage/UnifiedSwapStorage";
|
|
12
11
|
import {ISwap} from "../../ISwap";
|
|
13
12
|
import {BTC_NETWORK} from "@scure/btc-signer/utils";
|
|
13
|
+
import {IntermediaryAPI} from "../../../intermediaries/apis/IntermediaryAPI";
|
|
14
14
|
|
|
15
15
|
export type OnchainForGasWrapperOptions = ISwapWrapperOptions & {
|
|
16
16
|
bitcoinNetwork: BTC_NETWORK
|
|
@@ -57,6 +57,7 @@ export class OnchainForGasWrapper<T extends ChainType> extends ISwapWrapper<T, O
|
|
|
57
57
|
* @param prices Pricing to use
|
|
58
58
|
* @param tokens
|
|
59
59
|
* @param btcRpc Bitcoin RPC which also supports getting transactions by txoHash
|
|
60
|
+
* @param lpApi
|
|
60
61
|
* @param options
|
|
61
62
|
* @param events Instance to use for emitting events
|
|
62
63
|
*/
|
|
@@ -68,10 +69,11 @@ export class OnchainForGasWrapper<T extends ChainType> extends ISwapWrapper<T, O
|
|
|
68
69
|
prices: ISwapPrice,
|
|
69
70
|
tokens: WrapperCtorTokens,
|
|
70
71
|
btcRpc: BitcoinRpcWithAddressIndex<any>,
|
|
72
|
+
lpApi: IntermediaryAPI,
|
|
71
73
|
options: OnchainForGasWrapperOptions,
|
|
72
74
|
events?: EventEmitter<{swapState: [ISwap]}>
|
|
73
75
|
) {
|
|
74
|
-
super(chainIdentifier, unifiedStorage, unifiedChainEvents, chain, prices, tokens, options, events);
|
|
76
|
+
super(chainIdentifier, unifiedStorage, unifiedChainEvents, chain, prices, tokens, lpApi, options, events);
|
|
75
77
|
this._btcRpc = btcRpc;
|
|
76
78
|
}
|
|
77
79
|
|
|
@@ -91,7 +93,7 @@ export class OnchainForGasWrapper<T extends ChainType> extends ISwapWrapper<T, O
|
|
|
91
93
|
|
|
92
94
|
const token = this._chain.getNativeCurrencyAddress();
|
|
93
95
|
|
|
94
|
-
const resp = await
|
|
96
|
+
const resp = await this._lpApi.initTrustedFromBTC(this.chainIdentifier, lpUrl, {
|
|
95
97
|
address: recipient,
|
|
96
98
|
amount,
|
|
97
99
|
refundAddress,
|