@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.
Files changed (49) hide show
  1. package/dist/bitcoin/wallet/BitcoinWallet.d.ts +3 -2
  2. package/dist/bitcoin/wallet/BitcoinWallet.js +15 -1
  3. package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.d.ts +25 -3
  4. package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.js +51 -2
  5. package/dist/intermediaries/apis/IntermediaryAPI.d.ts +2 -0
  6. package/dist/intermediaries/apis/IntermediaryAPI.js +2 -0
  7. package/dist/swapper/Swapper.d.ts +2 -1
  8. package/dist/swapper/Swapper.js +4 -3
  9. package/dist/swaps/ISwap.d.ts +20 -0
  10. package/dist/swaps/ISwap.js +10 -0
  11. package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +12 -0
  12. package/dist/swaps/escrow_swaps/IEscrowSwap.js +18 -0
  13. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +50 -4
  14. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +62 -8
  15. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +4 -1
  16. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +23 -4
  17. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +85 -3
  18. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +109 -5
  19. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +2 -0
  20. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +30 -4
  21. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +44 -3
  22. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +62 -4
  23. package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +31 -2
  24. package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +59 -2
  25. package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +47 -1
  26. package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +63 -3
  27. package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +20 -2
  28. package/dist/swaps/trusted/ln/LnForGasSwap.js +27 -1
  29. package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +20 -3
  30. package/dist/swaps/trusted/onchain/OnchainForGasSwap.js +31 -1
  31. package/dist/types/SwapStateInfo.d.ts +5 -0
  32. package/dist/types/SwapStateInfo.js +2 -0
  33. package/package.json +3 -1
  34. package/src/bitcoin/wallet/BitcoinWallet.ts +21 -4
  35. package/src/bitcoin/wallet/SingleAddressBitcoinWallet.ts +60 -5
  36. package/src/intermediaries/apis/IntermediaryAPI.ts +5 -1
  37. package/src/swapper/Swapper.ts +5 -2
  38. package/src/swaps/ISwap.ts +29 -0
  39. package/src/swaps/escrow_swaps/IEscrowSwap.ts +20 -0
  40. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +73 -10
  41. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +28 -3
  42. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +127 -9
  43. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +35 -4
  44. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +75 -6
  45. package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +62 -4
  46. package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +81 -4
  47. package/src/swaps/trusted/ln/LnForGasSwap.ts +36 -2
  48. package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +43 -3
  49. 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>> implements IAddressSwap, IBTCWalletSwap {
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
  /**
@@ -0,0 +1,5 @@
1
+ export type SwapStateInfo<S extends number> = {
2
+ state: S;
3
+ name: string;
4
+ description: string;
5
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atomiqlabs/sdk",
3
- "version": "8.3.6",
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(mempoolApi: BitcoinRpcWithAddressIndex<any>, network: BTC_NETWORK, feeMultiplier: number = 1.25, feeOverride?: number) {
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
- network: BTC_NETWORK,
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
- return WIF(network).encode(randomPrivateKeyBytes());
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
+ }
@@ -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):
@@ -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?: { skipChecks?: boolean }, secret?: string) {
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
+ }