@atomiqlabs/sdk 8.3.6 → 8.4.3
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/dist/bitcoin/wallet/BitcoinWallet.d.ts +3 -2
- package/dist/bitcoin/wallet/BitcoinWallet.js +15 -1
- package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.d.ts +25 -3
- package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.js +51 -2
- package/dist/intermediaries/apis/IntermediaryAPI.d.ts +2 -0
- package/dist/intermediaries/apis/IntermediaryAPI.js +2 -0
- package/dist/swapper/Swapper.d.ts +2 -1
- package/dist/swapper/Swapper.js +4 -3
- package/dist/swaps/ISwap.d.ts +20 -0
- package/dist/swaps/ISwap.js +10 -0
- package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +12 -0
- package/dist/swaps/escrow_swaps/IEscrowSwap.js +18 -0
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +50 -4
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +62 -8
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +4 -1
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +23 -4
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +85 -3
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +109 -5
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +2 -0
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +30 -4
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +44 -3
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +62 -4
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +31 -2
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +59 -2
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +47 -1
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +63 -3
- package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +20 -2
- package/dist/swaps/trusted/ln/LnForGasSwap.js +27 -1
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +20 -3
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.js +31 -1
- package/dist/types/SwapStateInfo.d.ts +5 -0
- package/dist/types/SwapStateInfo.js +2 -0
- package/package.json +3 -1
- package/src/bitcoin/wallet/BitcoinWallet.ts +21 -4
- package/src/bitcoin/wallet/SingleAddressBitcoinWallet.ts +60 -5
- package/src/intermediaries/apis/IntermediaryAPI.ts +5 -1
- package/src/swapper/Swapper.ts +5 -2
- package/src/swaps/ISwap.ts +29 -0
- package/src/swaps/escrow_swaps/IEscrowSwap.ts +20 -0
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +73 -10
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +28 -3
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +127 -9
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +35 -4
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +75 -6
- package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +62 -4
- package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +81 -4
- package/src/swaps/trusted/ln/LnForGasSwap.ts +36 -2
- package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +43 -3
- package/src/types/SwapStateInfo.ts +6 -0
|
@@ -12,7 +12,7 @@ import { FeeType } from "../../../enums/FeeType";
|
|
|
12
12
|
import { TokenAmount } from "../../../types/TokenAmount";
|
|
13
13
|
import { BtcToken, SCToken } from "../../../types/Token";
|
|
14
14
|
import { LoggerType } from "../../../utils/Logger";
|
|
15
|
-
import { SwapExecutionActionBitcoin } from "../../../types/SwapExecutionAction";
|
|
15
|
+
import { SwapExecutionAction, SwapExecutionActionBitcoin } from "../../../types/SwapExecutionAction";
|
|
16
16
|
/**
|
|
17
17
|
* State enum for trusted on-chain gas swaps
|
|
18
18
|
*
|
|
@@ -32,7 +32,7 @@ export declare enum OnchainForGasSwapState {
|
|
|
32
32
|
*/
|
|
33
33
|
REFUNDED = -1,
|
|
34
34
|
/**
|
|
35
|
-
* Swap was created
|
|
35
|
+
* Swap was created, send the BTC to the swap address
|
|
36
36
|
*/
|
|
37
37
|
PR_CREATED = 0,
|
|
38
38
|
/**
|
|
@@ -61,8 +61,16 @@ export declare function isOnchainForGasSwapInit(obj: any): obj is OnchainForGasS
|
|
|
61
61
|
*
|
|
62
62
|
* @category Swaps/Trusted Gas Swaps
|
|
63
63
|
*/
|
|
64
|
-
export declare class OnchainForGasSwap<T extends ChainType = ChainType> extends ISwap<T, OnchainForGasSwapTypeDefinition<T
|
|
64
|
+
export declare class OnchainForGasSwap<T extends ChainType = ChainType> extends ISwap<T, OnchainForGasSwapTypeDefinition<T>, OnchainForGasSwapState> implements IAddressSwap, IBTCWalletSwap {
|
|
65
65
|
protected readonly TYPE: SwapType.TRUSTED_FROM_BTC;
|
|
66
|
+
/**
|
|
67
|
+
* @internal
|
|
68
|
+
*/
|
|
69
|
+
protected readonly swapStateDescription: Record<OnchainForGasSwapState, string>;
|
|
70
|
+
/**
|
|
71
|
+
* @internal
|
|
72
|
+
*/
|
|
73
|
+
protected readonly swapStateName: (state: number) => string;
|
|
66
74
|
/**
|
|
67
75
|
* @internal
|
|
68
76
|
*/
|
|
@@ -259,6 +267,15 @@ export declare class OnchainForGasSwap<T extends ChainType = ChainType> extends
|
|
|
259
267
|
}): Promise<[
|
|
260
268
|
SwapExecutionActionBitcoin<"ADDRESS" | "FUNDED_PSBT">
|
|
261
269
|
]>;
|
|
270
|
+
/**
|
|
271
|
+
* @inheritDoc
|
|
272
|
+
*
|
|
273
|
+
* @param options.bitcoinWallet Optional bitcoin wallet address specification to return a funded PSBT,
|
|
274
|
+
* if not provided an address is returned instead.
|
|
275
|
+
*/
|
|
276
|
+
getCurrentActions(options?: {
|
|
277
|
+
bitcoinWallet?: MinimalBitcoinWalletInterface;
|
|
278
|
+
}): Promise<SwapExecutionAction<T>[]>;
|
|
262
279
|
/**
|
|
263
280
|
* Queries the intermediary (LP) node for the state of the swap
|
|
264
281
|
*
|
|
@@ -37,7 +37,7 @@ var OnchainForGasSwapState;
|
|
|
37
37
|
*/
|
|
38
38
|
OnchainForGasSwapState[OnchainForGasSwapState["REFUNDED"] = -1] = "REFUNDED";
|
|
39
39
|
/**
|
|
40
|
-
* Swap was created
|
|
40
|
+
* Swap was created, send the BTC to the swap address
|
|
41
41
|
*/
|
|
42
42
|
OnchainForGasSwapState[OnchainForGasSwapState["PR_CREATED"] = 0] = "PR_CREATED";
|
|
43
43
|
/**
|
|
@@ -49,6 +49,14 @@ var OnchainForGasSwapState;
|
|
|
49
49
|
*/
|
|
50
50
|
OnchainForGasSwapState[OnchainForGasSwapState["REFUNDABLE"] = 2] = "REFUNDABLE";
|
|
51
51
|
})(OnchainForGasSwapState = exports.OnchainForGasSwapState || (exports.OnchainForGasSwapState = {}));
|
|
52
|
+
const OnchainForGasSwapStateDescription = {
|
|
53
|
+
[OnchainForGasSwapState.EXPIRED]: "The swap quote expired without user sending in the BTC",
|
|
54
|
+
[OnchainForGasSwapState.FAILED]: "The swap has failed after the intermediary already received the BTC on the source chain",
|
|
55
|
+
[OnchainForGasSwapState.REFUNDED]: "Swap was refunded and BTC returned to the user's refund address",
|
|
56
|
+
[OnchainForGasSwapState.PR_CREATED]: "Swap was created, send the BTC to the swap address",
|
|
57
|
+
[OnchainForGasSwapState.FINISHED]: "The swap is finished after the intermediary sent funds on the destination chain",
|
|
58
|
+
[OnchainForGasSwapState.REFUNDABLE]: "Swap is refundable because the intermediary cannot honor the swap request on the destination chain",
|
|
59
|
+
};
|
|
52
60
|
function isOnchainForGasSwapInit(obj) {
|
|
53
61
|
return typeof (obj.paymentHash) === "string" &&
|
|
54
62
|
typeof (obj.sequence) === "bigint" &&
|
|
@@ -73,6 +81,14 @@ class OnchainForGasSwap extends ISwap_1.ISwap {
|
|
|
73
81
|
initOrObj.url += "/frombtc_trusted";
|
|
74
82
|
super(wrapper, initOrObj);
|
|
75
83
|
this.TYPE = SwapType_1.SwapType.TRUSTED_FROM_BTC;
|
|
84
|
+
/**
|
|
85
|
+
* @internal
|
|
86
|
+
*/
|
|
87
|
+
this.swapStateDescription = OnchainForGasSwapStateDescription;
|
|
88
|
+
/**
|
|
89
|
+
* @internal
|
|
90
|
+
*/
|
|
91
|
+
this.swapStateName = (state) => OnchainForGasSwapState[state];
|
|
76
92
|
this.wrapper = wrapper;
|
|
77
93
|
if (isOnchainForGasSwapInit(initOrObj)) {
|
|
78
94
|
this.paymentHash = initOrObj.paymentHash;
|
|
@@ -437,6 +453,20 @@ class OnchainForGasSwap extends ISwap_1.ISwap {
|
|
|
437
453
|
}
|
|
438
454
|
throw new Error("Invalid swap state to obtain execution txns, required PR_CREATED or CLAIM_COMMITED");
|
|
439
455
|
}
|
|
456
|
+
/**
|
|
457
|
+
* @inheritDoc
|
|
458
|
+
*
|
|
459
|
+
* @param options.bitcoinWallet Optional bitcoin wallet address specification to return a funded PSBT,
|
|
460
|
+
* if not provided an address is returned instead.
|
|
461
|
+
*/
|
|
462
|
+
async getCurrentActions(options) {
|
|
463
|
+
try {
|
|
464
|
+
return await this.txsExecute(options);
|
|
465
|
+
}
|
|
466
|
+
catch (e) {
|
|
467
|
+
return [];
|
|
468
|
+
}
|
|
469
|
+
}
|
|
440
470
|
//////////////////////////////
|
|
441
471
|
//// Payment
|
|
442
472
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atomiqlabs/sdk",
|
|
3
|
-
"version": "8.3
|
|
3
|
+
"version": "8.4.3",
|
|
4
4
|
"description": "atomiq labs SDK for cross-chain swaps between smart chains and bitcoin",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types:": "./dist/index.d.ts",
|
|
@@ -30,6 +30,8 @@
|
|
|
30
30
|
"@noble/ciphers": "^1.2.1",
|
|
31
31
|
"@noble/hashes": "^1.7.1",
|
|
32
32
|
"@scure/base": "^1.2.4",
|
|
33
|
+
"@scure/bip32": "^2.0.1",
|
|
34
|
+
"@scure/bip39": "^2.0.1",
|
|
33
35
|
"@scure/btc-signer": "1.7.0",
|
|
34
36
|
"buffer": "6.0.3",
|
|
35
37
|
"events": "3.3.0"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {coinSelect, maxSendable, CoinselectAddressTypes, CoinselectTxInput} from "../coinselect2";
|
|
2
|
-
import {BTC_NETWORK} from "@scure/btc-signer/utils"
|
|
2
|
+
import {BTC_NETWORK, NETWORK, TEST_NETWORK} from "@scure/btc-signer/utils"
|
|
3
3
|
import {p2wpkh, OutScript, Transaction, p2tr, Address} from "@scure/btc-signer";
|
|
4
4
|
import {IBitcoinWallet} from "./IBitcoinWallet";
|
|
5
5
|
import {Buffer} from "buffer";
|
|
@@ -7,7 +7,7 @@ import {randomBytes} from "../../utils/Utils";
|
|
|
7
7
|
import {toCoinselectAddressType, toOutputScript} from "../../utils/BitcoinUtils";
|
|
8
8
|
import {TransactionInputUpdate} from "@scure/btc-signer/psbt";
|
|
9
9
|
import {getLogger} from "../../utils/Logger";
|
|
10
|
-
import {BitcoinRpcWithAddressIndex} from "@atomiqlabs/base";
|
|
10
|
+
import {BitcoinNetwork, BitcoinRpcWithAddressIndex} from "@atomiqlabs/base";
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* UTXO data structure for Bitcoin wallets
|
|
@@ -50,6 +50,16 @@ export function identifyAddressType(address: string, network: BTC_NETWORK): Coin
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
const btcNetworkMapping = {
|
|
54
|
+
[BitcoinNetwork.MAINNET]: NETWORK,
|
|
55
|
+
[BitcoinNetwork.TESTNET]: TEST_NETWORK,
|
|
56
|
+
[BitcoinNetwork.TESTNET4]: TEST_NETWORK,
|
|
57
|
+
[BitcoinNetwork.REGTEST]: {
|
|
58
|
+
...TEST_NETWORK,
|
|
59
|
+
bech32: "bcrt"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
53
63
|
const logger = getLogger("BitcoinWallet: ");
|
|
54
64
|
|
|
55
65
|
/**
|
|
@@ -65,9 +75,13 @@ export abstract class BitcoinWallet implements IBitcoinWallet {
|
|
|
65
75
|
protected feeMultiplier: number;
|
|
66
76
|
protected feeOverride?: number;
|
|
67
77
|
|
|
68
|
-
constructor(
|
|
78
|
+
constructor(
|
|
79
|
+
mempoolApi: BitcoinRpcWithAddressIndex<any>,
|
|
80
|
+
network: BitcoinNetwork | BTC_NETWORK,
|
|
81
|
+
feeMultiplier: number = 1.25, feeOverride?: number
|
|
82
|
+
) {
|
|
69
83
|
this.rpc = mempoolApi;
|
|
70
|
-
this.network = network;
|
|
84
|
+
this.network = typeof(network)==="object" ? network : BitcoinWallet.bitcoinNetworkToObject(network);
|
|
71
85
|
this.feeMultiplier = feeMultiplier;
|
|
72
86
|
this.feeOverride = feeOverride;
|
|
73
87
|
}
|
|
@@ -407,5 +421,8 @@ export abstract class BitcoinWallet implements IBitcoinWallet {
|
|
|
407
421
|
totalFee: number
|
|
408
422
|
}>;
|
|
409
423
|
|
|
424
|
+
static bitcoinNetworkToObject(network: BitcoinNetwork): BTC_NETWORK {
|
|
425
|
+
return btcNetworkMapping[network];
|
|
426
|
+
}
|
|
410
427
|
|
|
411
428
|
}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import {CoinselectAddressTypes} from "../coinselect2";
|
|
2
|
-
import {BTC_NETWORK, pubECDSA, randomPrivateKeyBytes} from "@scure/btc-signer/utils"
|
|
2
|
+
import {BTC_NETWORK, NETWORK, pubECDSA, randomPrivateKeyBytes, TEST_NETWORK} from "@scure/btc-signer/utils"
|
|
3
3
|
import {getAddress, Transaction, WIF} from "@scure/btc-signer";
|
|
4
4
|
import {Buffer} from "buffer";
|
|
5
5
|
import {identifyAddressType, BitcoinWallet} from "./BitcoinWallet";
|
|
6
|
-
import {BitcoinRpcWithAddressIndex} from "@atomiqlabs/base";
|
|
6
|
+
import {BitcoinNetwork, BitcoinRpcWithAddressIndex} from "@atomiqlabs/base";
|
|
7
|
+
import {HDKey} from "@scure/bip32";
|
|
8
|
+
import {entropyToMnemonic, generateMnemonic, mnemonicToSeed} from "@scure/bip39";
|
|
9
|
+
import {wordlist} from "@scure/bip39/wordlists/english.js";
|
|
10
|
+
import {sha256} from "@noble/hashes/sha2";
|
|
7
11
|
|
|
8
12
|
/**
|
|
9
13
|
* Bitcoin wallet implementation deriving a single address from a WIF encoded private key
|
|
@@ -19,11 +23,14 @@ export class SingleAddressBitcoinWallet extends BitcoinWallet {
|
|
|
19
23
|
|
|
20
24
|
constructor(
|
|
21
25
|
mempoolApi: BitcoinRpcWithAddressIndex<any>,
|
|
22
|
-
|
|
26
|
+
_network: BitcoinNetwork | BTC_NETWORK,
|
|
23
27
|
addressDataOrWIF: string | {address: string, publicKey: string},
|
|
24
28
|
feeMultiplier: number = 1.25,
|
|
25
29
|
feeOverride?: number
|
|
26
30
|
) {
|
|
31
|
+
const network = typeof(_network)==="object"
|
|
32
|
+
? _network
|
|
33
|
+
: BitcoinWallet.bitcoinNetworkToObject(_network);
|
|
27
34
|
super(mempoolApi, network, feeMultiplier, feeOverride);
|
|
28
35
|
if(typeof(addressDataOrWIF)==="string") {
|
|
29
36
|
try {
|
|
@@ -144,8 +151,56 @@ export class SingleAddressBitcoinWallet extends BitcoinWallet {
|
|
|
144
151
|
*
|
|
145
152
|
* @returns A WIF encoded bitcoin private key
|
|
146
153
|
*/
|
|
147
|
-
static generateRandomPrivateKey(network?: BTC_NETWORK): string {
|
|
148
|
-
|
|
154
|
+
static generateRandomPrivateKey(network?: BitcoinNetwork | BTC_NETWORK): string {
|
|
155
|
+
const networkObject = network==null || typeof(network)==="object"
|
|
156
|
+
? network
|
|
157
|
+
: BitcoinWallet.bitcoinNetworkToObject(network);
|
|
158
|
+
return WIF(networkObject).encode(randomPrivateKeyBytes());
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Generates a 12-word long mnemonic from any entropy source with 128-bits or more, the entropy is first hashed
|
|
163
|
+
* using sha256, and the first 16 bytes of the hash are used to generate the mnemonic
|
|
164
|
+
*
|
|
165
|
+
* @param entropy Entropy to use for generating the mnemonic
|
|
166
|
+
*/
|
|
167
|
+
static mnemonicFromEntropy(entropy: Buffer): string {
|
|
168
|
+
if(entropy.length<16) throw new Error("Requires at least 128-bit entropy (16 bytes)");
|
|
169
|
+
const entropyHash = Buffer.from(sha256(entropy)).subarray(0, 16);
|
|
170
|
+
return entropyToMnemonic(entropyHash, wordlist);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Generates a random 12-word long mnemonic
|
|
175
|
+
*/
|
|
176
|
+
static generateRandomMnemonic(): string {
|
|
177
|
+
return generateMnemonic(wordlist, 128)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Generates a WIF private key from mnemonic phrase
|
|
182
|
+
*
|
|
183
|
+
* @param mnemonic Mnemonic to generate the WIF key from
|
|
184
|
+
* @param network Optional bitcoin network to generate the WIF for
|
|
185
|
+
* @param derivationPath Optional custom derivation path to use for deriving the wallet
|
|
186
|
+
*/
|
|
187
|
+
static async mnemonicToPrivateKey(
|
|
188
|
+
mnemonic: string,
|
|
189
|
+
network?: BitcoinNetwork | BTC_NETWORK,
|
|
190
|
+
derivationPath?: string
|
|
191
|
+
): Promise<string> {
|
|
192
|
+
const networkObject = network==null || typeof(network)==="object"
|
|
193
|
+
? network
|
|
194
|
+
: BitcoinWallet.bitcoinNetworkToObject(network);
|
|
195
|
+
|
|
196
|
+
derivationPath = networkObject==null || networkObject.bech32===NETWORK.bech32
|
|
197
|
+
? "m/84'/0'/0'/0/0" //Mainnet
|
|
198
|
+
: "m/84'/1'/0'/0/0"; //Testnet
|
|
199
|
+
const seed = await mnemonicToSeed(mnemonic);
|
|
200
|
+
const hdKey = HDKey.fromMasterSeed(seed);
|
|
201
|
+
const privateKey = hdKey.derive(derivationPath).privateKey;
|
|
202
|
+
if(privateKey==null) throw new Error("Cannot derive private key from the mnemonic!");
|
|
203
|
+
return WIF(networkObject).encode(privateKey);
|
|
149
204
|
}
|
|
150
205
|
|
|
151
206
|
}
|
|
@@ -226,6 +226,7 @@ export type FromBTCLNResponseType = RequestSchemaResult<typeof FromBTCLNResponse
|
|
|
226
226
|
|
|
227
227
|
export type FromBTCLNInit = BaseFromBTCSwapInit & {
|
|
228
228
|
paymentHash: Buffer,
|
|
229
|
+
description?: string,
|
|
229
230
|
descriptionHash?: Buffer
|
|
230
231
|
}
|
|
231
232
|
|
|
@@ -258,6 +259,7 @@ export type FromBTCLNAutoResponseType = RequestSchemaResult<typeof FromBTCLNAuto
|
|
|
258
259
|
export type FromBTCLNAutoInit = Omit<BaseFromBTCSwapInit, "feeRate"> & {
|
|
259
260
|
paymentHash: Buffer,
|
|
260
261
|
gasToken: string,
|
|
262
|
+
description?: string,
|
|
261
263
|
descriptionHash?: Buffer,
|
|
262
264
|
gasAmount?: bigint,
|
|
263
265
|
claimerBounty?: Promise<bigint>
|
|
@@ -597,6 +599,7 @@ export class IntermediaryAPI {
|
|
|
597
599
|
amount: init.amount.toString(),
|
|
598
600
|
address: init.claimer,
|
|
599
601
|
token: init.token,
|
|
602
|
+
description: init.description ?? null,
|
|
600
603
|
descriptionHash: init.descriptionHash==null ? null : init.descriptionHash.toString("hex"),
|
|
601
604
|
exactOut: init.exactOut,
|
|
602
605
|
feeRate: init.feeRate
|
|
@@ -658,6 +661,7 @@ export class IntermediaryAPI {
|
|
|
658
661
|
amount: init.amount.toString(),
|
|
659
662
|
address: init.claimer,
|
|
660
663
|
token: init.token,
|
|
664
|
+
description: init.description ?? null,
|
|
661
665
|
descriptionHash: init.descriptionHash==null ? null : init.descriptionHash.toString("hex"),
|
|
662
666
|
exactOut: init.exactOut,
|
|
663
667
|
gasToken: init.gasToken,
|
|
@@ -937,4 +941,4 @@ export class IntermediaryAPI {
|
|
|
937
941
|
});
|
|
938
942
|
}
|
|
939
943
|
|
|
940
|
-
}
|
|
944
|
+
}
|
package/src/swapper/Swapper.ts
CHANGED
|
@@ -1185,6 +1185,7 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
|
|
|
1185
1185
|
* @param amount Amount to send in satoshis (if `exactOut=false`) or receive in token based units (if `exactOut=true`)
|
|
1186
1186
|
* @param exactOut Whether to use a exact out instead of exact in
|
|
1187
1187
|
* @param additionalParams Additional parameters sent to the LP when creating the swap
|
|
1188
|
+
* @param options Additional options for the swap
|
|
1188
1189
|
*/
|
|
1189
1190
|
async createFromBTCLNSwapViaLNURL<ChainIdentifier extends ChainIds<T>>(
|
|
1190
1191
|
chainIdentifier: ChainIdentifier,
|
|
@@ -1193,7 +1194,8 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
|
|
|
1193
1194
|
lnurl: string | LNURLWithdraw,
|
|
1194
1195
|
amount: bigint,
|
|
1195
1196
|
exactOut: boolean = false,
|
|
1196
|
-
additionalParams: Record<string, any> | undefined = this.options.defaultAdditionalParameters
|
|
1197
|
+
additionalParams: Record<string, any> | undefined = this.options.defaultAdditionalParameters,
|
|
1198
|
+
options?: FromBTCLNOptions
|
|
1197
1199
|
): Promise<FromBTCLNSwap<T[ChainIdentifier]>> {
|
|
1198
1200
|
if(this._chains[chainIdentifier]==null) throw new Error("Invalid chain identifier! Unknown chain: "+chainIdentifier);
|
|
1199
1201
|
if(typeof(lnurl)==="string" && !this.Utils.isValidLNURL(lnurl)) throw new Error("Invalid LNURL-withdraw link");
|
|
@@ -1211,6 +1213,7 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
|
|
|
1211
1213
|
typeof(lnurl)==="string" ? (lnurl.startsWith("lightning:") ? lnurl.substring(10): lnurl) : lnurl.params,
|
|
1212
1214
|
amountData,
|
|
1213
1215
|
candidates,
|
|
1216
|
+
options,
|
|
1214
1217
|
additionalParams,
|
|
1215
1218
|
abortSignal
|
|
1216
1219
|
),
|
|
@@ -1477,7 +1480,7 @@ export class Swapper<T extends MultiChain> extends EventEmitter<{
|
|
|
1477
1480
|
if(typeof(src)!=="string" && !isLNURLWithdraw(src)) throw new Error("LNURL must be a string or LNURLWithdraw object!");
|
|
1478
1481
|
return this.supportsSwapType(dstToken.chainId, SwapType.FROM_BTCLN_AUTO) ?
|
|
1479
1482
|
this.createFromBTCLNSwapNewViaLNURL(dstToken.chainId, dst, dstToken.address, src, amount, !exactIn, undefined, options as any) :
|
|
1480
|
-
this.createFromBTCLNSwapViaLNURL(dstToken.chainId, dst, dstToken.address, src, amount, !exactIn);
|
|
1483
|
+
this.createFromBTCLNSwapViaLNURL(dstToken.chainId, dst, dstToken.address, src, amount, !exactIn, undefined, options as any);
|
|
1481
1484
|
} else {
|
|
1482
1485
|
return this.supportsSwapType(dstToken.chainId, SwapType.FROM_BTCLN_AUTO) ?
|
|
1483
1486
|
this.createFromBTCLNSwapNew(dstToken.chainId, dst, dstToken.address, amount, !exactIn, undefined, options as any):
|
package/src/swaps/ISwap.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {isSCToken, Token} from "../types/Token";
|
|
|
12
12
|
import {SwapExecutionAction} from "../types/SwapExecutionAction";
|
|
13
13
|
import {LoggerType} from "../utils/Logger";
|
|
14
14
|
import {isPriceInfoType, PriceInfoType} from "../types/PriceInfoType";
|
|
15
|
+
import {SwapStateInfo} from "../types/SwapStateInfo";
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Initialization data for creating a swap
|
|
@@ -57,6 +58,17 @@ export abstract class ISwap<
|
|
|
57
58
|
* Swap type
|
|
58
59
|
*/
|
|
59
60
|
protected readonly abstract TYPE: SwapType;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Description for the states
|
|
64
|
+
* @internal
|
|
65
|
+
*/
|
|
66
|
+
protected readonly abstract swapStateDescription: Record<S, string>;
|
|
67
|
+
/**
|
|
68
|
+
* Name of the states
|
|
69
|
+
* @internal
|
|
70
|
+
*/
|
|
71
|
+
protected readonly abstract swapStateName: (state: number) => string;
|
|
60
72
|
/**
|
|
61
73
|
* Swap logger
|
|
62
74
|
* @internal
|
|
@@ -486,6 +498,23 @@ export abstract class ISwap<
|
|
|
486
498
|
return this._state;
|
|
487
499
|
}
|
|
488
500
|
|
|
501
|
+
/**
|
|
502
|
+
* Returns the current state of the swap along with the human-readable description of the state
|
|
503
|
+
*/
|
|
504
|
+
public getStateInfo(): SwapStateInfo<S> {
|
|
505
|
+
return {
|
|
506
|
+
state: this._state,
|
|
507
|
+
name: this.swapStateName(this._state),
|
|
508
|
+
description: this.swapStateDescription[this._state]
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Returns a state-dependent set of actions for the user to execute, or empty array if there is currently
|
|
514
|
+
* no action required from the user to execute.
|
|
515
|
+
*/
|
|
516
|
+
public abstract getCurrentActions(): Promise<SwapExecutionAction<T>[]>;
|
|
517
|
+
|
|
489
518
|
//////////////////////////////
|
|
490
519
|
//// Amounts & fees
|
|
491
520
|
|
|
@@ -131,6 +131,26 @@ export abstract class IEscrowSwap<
|
|
|
131
131
|
return this.getIdentifierHashString();
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
/**
|
|
135
|
+
* Returns the smart chain transaction ID of the tx that initiated the escrow
|
|
136
|
+
*/
|
|
137
|
+
getEscrowInitTxId(): string | undefined {
|
|
138
|
+
return this._commitTxId;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Returns the smart chain transaction ID of the tx that claimed (settled) the escrow
|
|
143
|
+
*/
|
|
144
|
+
getEscrowClaimTxId(): string | undefined {
|
|
145
|
+
return this._claimTxId;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Returns the smart chain transaction ID of the tx that refunded the escrow
|
|
150
|
+
*/
|
|
151
|
+
getEscrowRefundTxId(): string | undefined {
|
|
152
|
+
return this._refundTxId;
|
|
153
|
+
}
|
|
134
154
|
|
|
135
155
|
//////////////////////////////
|
|
136
156
|
//// Watchdogs
|
|
@@ -31,6 +31,7 @@ import {getLogger, LoggerType} from "../../../../utils/Logger";
|
|
|
31
31
|
import {timeoutPromise} from "../../../../utils/TimeoutUtils";
|
|
32
32
|
import {isLNURLWithdraw, LNURLWithdraw, LNURLWithdrawParamsWithUrl} from "../../../../types/lnurl/LNURLWithdraw";
|
|
33
33
|
import {sha256} from "@noble/hashes/sha2";
|
|
34
|
+
import {SwapExecutionAction} from "../../../../types/SwapExecutionAction";
|
|
34
35
|
|
|
35
36
|
/**
|
|
36
37
|
* State enum for legacy Lightning -> Smart chain swaps
|
|
@@ -80,6 +81,17 @@ export enum FromBTCLNSwapState {
|
|
|
80
81
|
CLAIM_CLAIMED = 3
|
|
81
82
|
}
|
|
82
83
|
|
|
84
|
+
const FromBTCLNSwapStateDescription = {
|
|
85
|
+
[FromBTCLNSwapState.FAILED]: "Swap has failed as the user didn't settle the HTLC on the destination before expiration",
|
|
86
|
+
[FromBTCLNSwapState.QUOTE_EXPIRED]: "Swap has expired for good and there is no way how it can be executed anymore",
|
|
87
|
+
[FromBTCLNSwapState.QUOTE_SOFT_EXPIRED]: "Swap is expired, though there is still a chance that it will be processed",
|
|
88
|
+
[FromBTCLNSwapState.EXPIRED]: "Swap HTLC on the destination chain has expired, it is not safe anymore to settle (claim) the swap on the destination smart chain.",
|
|
89
|
+
[FromBTCLNSwapState.PR_CREATED]: "Swap quote was created, pay the bolt11 lightning network invoice to initiate the swap, then use the wait till the lightning network payment is received by the intermediary (LP)",
|
|
90
|
+
[FromBTCLNSwapState.PR_PAID]: "Lightning network payment has been received by the intermediary (LP), the user can now settle the swap on the destination smart chain side.",
|
|
91
|
+
[FromBTCLNSwapState.CLAIM_COMMITED]: "Swap escrow HTLC has been created on the destination chain. Continue by claiming it.",
|
|
92
|
+
[FromBTCLNSwapState.CLAIM_CLAIMED]: "Swap successfully settled and funds received on the destination chain"
|
|
93
|
+
};
|
|
94
|
+
|
|
83
95
|
export type FromBTCLNSwapInit<T extends SwapData> = IEscrowSelfInitSwapInit<T> & {
|
|
84
96
|
pr?: string,
|
|
85
97
|
secret?: string,
|
|
@@ -109,6 +121,14 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
109
121
|
implements IAddressSwap, IClaimableSwap<T, FromBTCLNDefinition<T>, FromBTCLNSwapState> {
|
|
110
122
|
|
|
111
123
|
protected readonly TYPE = SwapType.FROM_BTCLN;
|
|
124
|
+
/**
|
|
125
|
+
* @internal
|
|
126
|
+
*/
|
|
127
|
+
protected readonly swapStateName = (state: number) => FromBTCLNSwapState[state];
|
|
128
|
+
/**
|
|
129
|
+
* @internal
|
|
130
|
+
*/
|
|
131
|
+
protected readonly swapStateDescription = FromBTCLNSwapStateDescription;
|
|
112
132
|
/**
|
|
113
133
|
* @internal
|
|
114
134
|
*/
|
|
@@ -468,6 +488,25 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
468
488
|
return this.getSwapData().getClaimHash()===claimHash;
|
|
469
489
|
}
|
|
470
490
|
|
|
491
|
+
/**
|
|
492
|
+
* Sets the secret preimage for the swap, in case it is not known already
|
|
493
|
+
*
|
|
494
|
+
* @param secret Secret preimage that matches the expected payment hash
|
|
495
|
+
*
|
|
496
|
+
* @throws {Error} If an invalid secret preimage is provided
|
|
497
|
+
*/
|
|
498
|
+
setSecretPreimage(secret: string) {
|
|
499
|
+
if(!this.isValidSecretPreimage(secret)) throw new Error("Invalid secret preimage provided, hash doesn't match!");
|
|
500
|
+
this.secret = secret;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Returns whether the secret preimage for this swap is known
|
|
505
|
+
*/
|
|
506
|
+
hasSecretPreimage(): boolean {
|
|
507
|
+
return this.secret != null;
|
|
508
|
+
}
|
|
509
|
+
|
|
471
510
|
|
|
472
511
|
//////////////////////////////
|
|
473
512
|
//// Execution
|
|
@@ -482,7 +521,7 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
482
521
|
* link, wallet is not required and the LN invoice can be paid externally as well (just pass null or undefined here)
|
|
483
522
|
* @param callbacks Callbacks to track the progress of the swap
|
|
484
523
|
* @param options Optional options for the swap like feeRate, AbortSignal, and timeouts/intervals
|
|
485
|
-
* @param secret A swap secret to use for the claim transaction, generally only needed if the swap
|
|
524
|
+
* @param options.secret A swap secret to use for the claim transaction, generally only needed if the swap
|
|
486
525
|
* was recovered from on-chain data, or the pre-image was generated outside the SDK
|
|
487
526
|
*/
|
|
488
527
|
async execute(
|
|
@@ -496,10 +535,10 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
496
535
|
},
|
|
497
536
|
options?: {
|
|
498
537
|
abortSignal?: AbortSignal,
|
|
538
|
+
secret?: string,
|
|
499
539
|
lightningTxCheckIntervalSeconds?: number,
|
|
500
540
|
delayBetweenCommitAndClaimSeconds?: number
|
|
501
|
-
}
|
|
502
|
-
secret?: string
|
|
541
|
+
}
|
|
503
542
|
): Promise<void> {
|
|
504
543
|
if(this._state===FromBTCLNSwapState.FAILED) throw new Error("Swap failed!");
|
|
505
544
|
if(this._state===FromBTCLNSwapState.EXPIRED) throw new Error("Swap HTLC expired!");
|
|
@@ -530,14 +569,14 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
530
569
|
|
|
531
570
|
if(this._state===FromBTCLNSwapState.PR_PAID || this._state===FromBTCLNSwapState.CLAIM_COMMITED) {
|
|
532
571
|
if(this.canCommitAndClaimInOneShot()) {
|
|
533
|
-
await this.commitAndClaim(dstSigner, options?.abortSignal, undefined, callbacks?.onDestinationCommitSent, callbacks?.onDestinationClaimSent, secret);
|
|
572
|
+
await this.commitAndClaim(dstSigner, options?.abortSignal, undefined, callbacks?.onDestinationCommitSent, callbacks?.onDestinationClaimSent, options?.secret);
|
|
534
573
|
} else {
|
|
535
574
|
if(this._state===FromBTCLNSwapState.PR_PAID) {
|
|
536
575
|
await this.commit(dstSigner, options?.abortSignal, undefined, callbacks?.onDestinationCommitSent);
|
|
537
576
|
if(options?.delayBetweenCommitAndClaimSeconds!=null) await timeoutPromise(options.delayBetweenCommitAndClaimSeconds * 1000, options?.abortSignal);
|
|
538
577
|
}
|
|
539
578
|
if(this._state===FromBTCLNSwapState.CLAIM_COMMITED) {
|
|
540
|
-
await this.claim(dstSigner, options?.abortSignal, callbacks?.onDestinationClaimSent, secret);
|
|
579
|
+
await this.claim(dstSigner, options?.abortSignal, callbacks?.onDestinationClaimSent, options?.secret);
|
|
541
580
|
}
|
|
542
581
|
}
|
|
543
582
|
}
|
|
@@ -555,10 +594,13 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
555
594
|
* @param options.skipChecks Skip checks like making sure init signature is still valid and swap
|
|
556
595
|
* wasn't commited yet (this is handled on swap creation, if you commit right after quoting, you
|
|
557
596
|
* can use `skipChecks=true`)
|
|
558
|
-
* @param secret A swap secret to use for the claim transaction, generally only needed if the swap
|
|
597
|
+
* @param options.secret A swap secret to use for the claim transaction, generally only needed if the swap
|
|
559
598
|
* was recovered from on-chain data, or the pre-image was generated outside the SDK
|
|
560
599
|
*/
|
|
561
|
-
async txsExecute(options?: {
|
|
600
|
+
async txsExecute(options?: {
|
|
601
|
+
skipChecks?: boolean,
|
|
602
|
+
secret?: string
|
|
603
|
+
}) {
|
|
562
604
|
if(this._state===FromBTCLNSwapState.PR_CREATED) {
|
|
563
605
|
if(!await this._verifyQuoteValid()) throw new Error("Quote already expired or close to expiry!");
|
|
564
606
|
return [
|
|
@@ -580,7 +622,7 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
580
622
|
if(this._state===FromBTCLNSwapState.PR_PAID) {
|
|
581
623
|
if(!await this._verifyQuoteValid()) throw new Error("Quote already expired or close to expiry!");
|
|
582
624
|
const txsCommit = await this.txsCommit(options?.skipChecks);
|
|
583
|
-
const txsClaim = await this._txsClaim(undefined, secret);
|
|
625
|
+
const txsClaim = await this._txsClaim(undefined, options?.secret);
|
|
584
626
|
return [
|
|
585
627
|
{
|
|
586
628
|
name: "Commit" as const,
|
|
@@ -598,7 +640,7 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
598
640
|
}
|
|
599
641
|
|
|
600
642
|
if(this._state===FromBTCLNSwapState.CLAIM_COMMITED) {
|
|
601
|
-
const txsClaim = await this.txsClaim(undefined, secret);
|
|
643
|
+
const txsClaim = await this.txsClaim(undefined, options?.secret);
|
|
602
644
|
return [
|
|
603
645
|
{
|
|
604
646
|
name: "Claim" as const,
|
|
@@ -612,6 +654,27 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
612
654
|
throw new Error("Invalid swap state to obtain execution txns, required PR_CREATED, PR_PAID or CLAIM_COMMITED");
|
|
613
655
|
}
|
|
614
656
|
|
|
657
|
+
/**
|
|
658
|
+
* @inheritDoc
|
|
659
|
+
*
|
|
660
|
+
* @param options
|
|
661
|
+
* @param options.skipChecks Skip checks like making sure init signature is still valid and swap
|
|
662
|
+
* wasn't commited yet (this is handled on swap creation, if you commit right after quoting, you
|
|
663
|
+
* can use `skipChecks=true`)
|
|
664
|
+
* @param options.secret A swap secret to use for the claim transaction, generally only needed if the swap
|
|
665
|
+
* was recovered from on-chain data, or the pre-image was generated outside the SDK
|
|
666
|
+
*/
|
|
667
|
+
async getCurrentActions(options?: {
|
|
668
|
+
skipChecks?: boolean,
|
|
669
|
+
secret?: string
|
|
670
|
+
}): Promise<SwapExecutionAction<T>[]> {
|
|
671
|
+
try {
|
|
672
|
+
return await this.txsExecute(options);
|
|
673
|
+
} catch (e) {
|
|
674
|
+
return [];
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
615
678
|
|
|
616
679
|
//////////////////////////////
|
|
617
680
|
//// Payment
|
|
@@ -1387,4 +1450,4 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
1387
1450
|
}
|
|
1388
1451
|
}
|
|
1389
1452
|
|
|
1390
|
-
}
|
|
1453
|
+
}
|