@atomiqlabs/sdk 8.4.4 → 8.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/README.md +8 -8
  2. package/dist/enums/SwapSide.d.ts +15 -0
  3. package/dist/enums/SwapSide.js +19 -0
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.js +1 -0
  6. package/dist/intermediaries/apis/IntermediaryAPI.d.ts +2 -2
  7. package/dist/intermediaries/apis/IntermediaryAPI.js +2 -2
  8. package/dist/storage/UnifiedSwapStorage.d.ts +2 -0
  9. package/dist/swapper/Swapper.d.ts +27 -21
  10. package/dist/swapper/Swapper.js +19 -26
  11. package/dist/swapper/SwapperWithChain.d.ts +14 -18
  12. package/dist/swapper/SwapperWithChain.js +2 -2
  13. package/dist/swapper/SwapperWithSigner.d.ts +9 -13
  14. package/dist/swaps/IBTCWalletSwap.d.ts +1 -1
  15. package/dist/swaps/ISwap.js +2 -0
  16. package/dist/swaps/ISwapWithGasDrop.d.ts +1 -1
  17. package/dist/swaps/ISwapWrapper.d.ts +12 -12
  18. package/dist/swaps/ISwapWrapper.js +22 -14
  19. package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.d.ts +3 -3
  20. package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.d.ts +8 -8
  21. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +5 -5
  22. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +23 -2
  23. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +20 -17
  24. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +4 -4
  25. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +44 -3
  26. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +9 -14
  27. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +3 -3
  28. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +20 -2
  29. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +15 -8
  30. package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +7 -7
  31. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.d.ts +1 -1
  32. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +52 -6
  33. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +20 -30
  34. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.d.ts +1 -1
  35. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +6 -0
  36. package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +6 -6
  37. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +32 -1
  38. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +8 -5
  39. package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +3 -3
  40. package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +4 -4
  41. package/dist/types/Token.d.ts +65 -25
  42. package/dist/types/Token.js +28 -13
  43. package/dist/types/TokenAmount.d.ts +2 -2
  44. package/dist/types/fees/Fee.d.ts +3 -3
  45. package/dist/utils/Utils.d.ts +1 -0
  46. package/dist/utils/Utils.js +17 -1
  47. package/package.json +1 -1
  48. package/src/enums/SwapSide.ts +16 -0
  49. package/src/index.ts +1 -0
  50. package/src/intermediaries/apis/IntermediaryAPI.ts +4 -4
  51. package/src/storage/UnifiedSwapStorage.ts +2 -0
  52. package/src/swapper/Swapper.ts +46 -37
  53. package/src/swapper/SwapperWithChain.ts +15 -10
  54. package/src/swapper/SwapperWithSigner.ts +8 -3
  55. package/src/swaps/IBTCWalletSwap.ts +1 -1
  56. package/src/swaps/ISwap.ts +2 -0
  57. package/src/swaps/ISwapWithGasDrop.ts +1 -1
  58. package/src/swaps/ISwapWrapper.ts +24 -23
  59. package/src/swaps/escrow_swaps/IEscrowSelfInitSwap.ts +3 -3
  60. package/src/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.ts +8 -8
  61. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +5 -5
  62. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +48 -22
  63. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +4 -4
  64. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +56 -20
  65. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +3 -3
  66. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +57 -22
  67. package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +7 -7
  68. package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.ts +1 -1
  69. package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +80 -37
  70. package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.ts +1 -1
  71. package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +12 -3
  72. package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +6 -6
  73. package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +53 -11
  74. package/src/swaps/trusted/ln/LnForGasSwap.ts +3 -3
  75. package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +4 -4
  76. package/src/types/Token.ts +98 -32
  77. package/src/types/TokenAmount.ts +5 -7
  78. package/src/types/fees/Fee.ts +3 -3
  79. package/src/utils/Utils.ts +18 -2
@@ -4,7 +4,6 @@ import { ChainEvent, ChainType } from "@atomiqlabs/base";
4
4
  import { EventEmitter } from "events";
5
5
  import { ISwap } from "./ISwap";
6
6
  import { ISwapPrice } from "../prices/abstract/ISwapPrice";
7
- import { ChainIds, MultiChain } from "../swapper/Swapper";
8
7
  import { UnifiedSwapEventListener } from "../events/UnifiedSwapEventListener";
9
8
  import { SwapType } from "../enums/SwapType";
10
9
  import { UnifiedSwapStorage } from "../storage/UnifiedSwapStorage";
@@ -24,17 +23,9 @@ export type ISwapWrapperOptions = {
24
23
  *
25
24
  * @category Swaps/Base
26
25
  */
27
- export type WrapperCtorTokens<T extends MultiChain = MultiChain> = {
28
- ticker: string;
29
- name: string;
30
- chains: {
31
- [chainId in ChainIds<T>]?: {
32
- address: string;
33
- decimals: number;
34
- displayDecimals?: number;
35
- };
36
- };
37
- }[];
26
+ export type WrapperCtorTokens<T extends ChainType = ChainType> = {
27
+ [tokenAddress: string]: SCToken<T["ChainId"]>;
28
+ };
38
29
  /**
39
30
  * Type definition linking wrapper and swap types
40
31
  *
@@ -135,6 +126,15 @@ export declare abstract class ISwapWrapper<T extends ChainType, D extends SwapTy
135
126
  constructor(chainIdentifier: T["ChainId"], unifiedStorage: UnifiedSwapStorage<T>, unifiedChainEvents: UnifiedSwapEventListener<T>, chain: T["ChainInterface"], prices: ISwapPrice, tokens: WrapperCtorTokens, options: O, events?: EventEmitter<{
136
127
  swapState: [ISwap];
137
128
  }>);
129
+ /**
130
+ * Parses the provided gas amount from its `string` or `bigint` representation to `bigint` base units.
131
+ *
132
+ * Defaults to `0n` if no gasAmount is provided
133
+ *
134
+ * @param gasAmount
135
+ * @internal
136
+ */
137
+ protected parseGasAmount(gasAmount?: string | bigint): bigint;
138
138
  /**
139
139
  * Pre-fetches swap price for a given swap
140
140
  *
@@ -4,6 +4,8 @@ exports.ISwapWrapper = void 0;
4
4
  const events_1 = require("events");
5
5
  const IntermediaryError_1 = require("../errors/IntermediaryError");
6
6
  const Logger_1 = require("../utils/Logger");
7
+ const TokenUtils_1 = require("../utils/TokenUtils");
8
+ const UserError_1 = require("../errors/UserError");
7
9
  /**
8
10
  * Base abstract class for swap handler implementations
9
11
  *
@@ -34,21 +36,27 @@ class ISwapWrapper {
34
36
  this._prices = prices;
35
37
  this.events = events || new events_1.EventEmitter();
36
38
  this._options = options;
37
- this._tokens = {};
38
- for (let tokenData of tokens) {
39
- const chainData = tokenData.chains[chainIdentifier];
40
- if (chainData == null)
41
- continue;
42
- this._tokens[chainData.address] = {
43
- chain: "SC",
44
- chainId: this.chainIdentifier,
45
- address: chainData.address,
46
- decimals: chainData.decimals,
47
- ticker: tokenData.ticker,
48
- name: tokenData.name,
49
- displayDecimals: chainData.displayDecimals
50
- };
39
+ this._tokens = tokens;
40
+ }
41
+ /**
42
+ * Parses the provided gas amount from its `string` or `bigint` representation to `bigint` base units.
43
+ *
44
+ * Defaults to `0n` if no gasAmount is provided
45
+ *
46
+ * @param gasAmount
47
+ * @internal
48
+ */
49
+ parseGasAmount(gasAmount) {
50
+ let result;
51
+ if (typeof (gasAmount) === "string") {
52
+ result = (0, TokenUtils_1.fromHumanReadableString)(gasAmount, this._getNativeToken());
53
+ if (result == null)
54
+ throw new UserError_1.UserError("Invalid `gasAmount` option provided, not a numerical string!");
55
+ }
56
+ else {
57
+ result = gasAmount;
51
58
  }
59
+ return result ?? 0n;
52
60
  }
53
61
  /**
54
62
  * Pre-fetches swap price for a given swap
@@ -46,15 +46,15 @@ export declare abstract class IEscrowSelfInitSwap<T extends ChainType = ChainTyp
46
46
  /**
47
47
  * Returns the transaction fee paid on the smart chain side to initiate the escrow
48
48
  */
49
- getSmartChainNetworkFee(): Promise<TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>>;
49
+ getSmartChainNetworkFee(): Promise<TokenAmount<SCToken<T["ChainId"]>, true>>;
50
50
  /**
51
51
  * Checks if the initiator/sender has enough balance on the smart chain side
52
52
  * to cover the transaction fee for processing the swap
53
53
  */
54
54
  abstract hasEnoughForTxFees(): Promise<{
55
55
  enoughBalance: boolean;
56
- balance: TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
57
- required: TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
56
+ balance: TokenAmount<SCToken<T["ChainId"]>, true>;
57
+ required: TokenAmount<SCToken<T["ChainId"]>, true>;
58
58
  }>;
59
59
  /**
60
60
  * Returns transactions for initiating (committing) the escrow on the smart chain side. After sending the
@@ -91,35 +91,35 @@ export declare abstract class IFromBTCSelfInitSwap<T extends ChainType = ChainTy
91
91
  /**
92
92
  * @inheritDoc
93
93
  */
94
- getOutput(): TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
94
+ getOutput(): TokenAmount<SCToken<T["ChainId"]>, true>;
95
95
  /**
96
96
  * @inheritDoc
97
97
  */
98
- abstract getInput(): TokenAmount<T["ChainId"], BtcToken>;
98
+ abstract getInput(): TokenAmount<BtcToken>;
99
99
  /**
100
100
  * @inheritDoc
101
101
  */
102
- getInputWithoutFee(): TokenAmount<T["ChainId"], BtcToken>;
102
+ getInputWithoutFee(): TokenAmount<BtcToken>;
103
103
  /**
104
104
  * @inheritDoc
105
105
  */
106
106
  hasEnoughForTxFees(): Promise<{
107
107
  enoughBalance: boolean;
108
- balance: TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
109
- required: TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
108
+ balance: TokenAmount<SCToken<T["ChainId"]>, true>;
109
+ required: TokenAmount<SCToken<T["ChainId"]>, true>;
110
110
  }>;
111
111
  /**
112
112
  * Returns the amount of native token of the destination chain locked up during initialization of the escrow
113
113
  * to act as a security deposit that can be taken by the intermediary (LP) if the user doesn't go through
114
114
  * with the swap
115
115
  */
116
- getSecurityDeposit(): TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
116
+ getSecurityDeposit(): TokenAmount<SCToken<T["ChainId"]>, true>;
117
117
  /**
118
118
  * Returns the total amount of native token of the destination chain locked up during initialization of the escrow.
119
119
  * This covers the security deposit and the watchtower fee (if applicable), it is calculated a maximum of those
120
120
  * two values.
121
121
  */
122
- getTotalDeposit(): TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
122
+ getTotalDeposit(): TokenAmount<SCToken<T["ChainId"]>, true>;
123
123
  /**
124
124
  * Returns transactions for initiating (committing) the escrow on the destination smart chain side, pre-locking the
125
125
  * tokens from the intermediary (LP) into an escrow.
@@ -146,7 +146,7 @@ export declare abstract class IFromBTCSelfInitSwap<T extends ChainType = ChainTy
146
146
  * Returns the transaction fee required for the claim transaction to settle the escrow on the destination
147
147
  * smart chain
148
148
  */
149
- getClaimNetworkFee(): Promise<TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>>;
149
+ getClaimNetworkFee(): Promise<TokenAmount<SCToken<T["ChainId"]>, true>>;
150
150
  /**
151
151
  * @inheritDoc
152
152
  */
@@ -237,18 +237,18 @@ export declare class FromBTCLNSwap<T extends ChainType = ChainType> extends IFro
237
237
  /**
238
238
  * @inheritDoc
239
239
  */
240
- getInput(): TokenAmount<T["ChainId"], BtcToken<true>>;
240
+ getInput(): TokenAmount<BtcToken<true>>;
241
241
  /**
242
242
  * @inheritDoc
243
243
  */
244
- getSmartChainNetworkFee(): Promise<TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>>;
244
+ getSmartChainNetworkFee(): Promise<TokenAmount<SCToken<T["ChainId"]>, true>>;
245
245
  /**
246
246
  * @inheritDoc
247
247
  */
248
248
  hasEnoughForTxFees(): Promise<{
249
249
  enoughBalance: boolean;
250
- balance: TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
251
- required: TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
250
+ balance: TokenAmount<SCToken<T["ChainId"]>, true>;
251
+ required: TokenAmount<SCToken<T["ChainId"]>, true>;
252
252
  }>;
253
253
  private isValidSecretPreimage;
254
254
  /**
@@ -422,7 +422,7 @@ export declare class FromBTCLNSwap<T extends ChainType = ChainType> extends IFro
422
422
  * Estimated transaction fee for commit & claim transactions combined, required
423
423
  * to settle the swap on the smart chain destination side.
424
424
  */
425
- getCommitAndClaimNetworkFee(): Promise<TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>>;
425
+ getCommitAndClaimNetworkFee(): Promise<TokenAmount<SCToken<T["ChainId"]>, true>>;
426
426
  /**
427
427
  * Returns whether the underlying chain supports calling commit and claim in a single call,
428
428
  * such that you can use the {@link commitAndClaim} function. If not you have to manually
@@ -18,9 +18,30 @@ import { AmountData } from "../../../../types/AmountData";
18
18
  import { LNURLWithdrawParamsWithUrl } from "../../../../types/lnurl/LNURLWithdraw";
19
19
  import { AllOptional } from "../../../../utils/TypeUtils";
20
20
  export type FromBTCLNOptions = {
21
- paymentHash?: Buffer;
21
+ /**
22
+ * Instead of letting the SDK generate the preimage/paymentHash pair internally you can pass your computed
23
+ * paymentHash here, this will create the swap with the provided payment hash. Note that you would then
24
+ * have to reveal the preimage by passing it to the {@link FromBTCLNSwap.claim} or {@link FromBTCLNSwap.txsClaim}
25
+ * functions
26
+ *
27
+ * Accepts both, a {@link Buffer} and a hexadecimal `string`
28
+ */
29
+ paymentHash?: Buffer | string;
30
+ /**
31
+ * Optional description to use for the swap lightning network invoice, keep the invoice length below 500 characters
32
+ */
22
33
  description?: string;
23
- descriptionHash?: Buffer;
34
+ /**
35
+ * Optional description hash to use for the lightning network invoice, useful when returning the invoice as part of
36
+ * an LNURL-pay service endpoint.
37
+ *
38
+ * Accepts both, a {@link Buffer} and a hexadecimal `string`
39
+ */
40
+ descriptionHash?: Buffer | string;
41
+ /**
42
+ * A flag to skip checking whether the lightning network node of the LP has enough channel liquidity to facilitate
43
+ * the swap.
44
+ */
24
45
  unsafeSkipLnNodeCheck?: boolean;
25
46
  };
26
47
  export type FromBTCLNWrapperOptions = ISwapWrapperOptions & {
@@ -155,19 +155,18 @@ class FromBTCLNWrapper extends IFromBTCLNWrapper_1.IFromBTCLNWrapper {
155
155
  create(recipient, amountData, lps, options, additionalParams, abortSignal, preFetches) {
156
156
  if (!this.isInitialized)
157
157
  throw new Error("Not initialized, call init() first!");
158
- if (options == null)
159
- options = {};
160
- options.unsafeSkipLnNodeCheck ??= this._options.unsafeSkipLnNodeCheck;
161
- if (options.paymentHash != null && options.paymentHash.length !== 32)
162
- throw new UserError_1.UserError("Invalid payment hash length, must be exactly 32 bytes!");
163
- if (options.descriptionHash != null && options.descriptionHash.length !== 32)
164
- throw new UserError_1.UserError("Invalid description hash length");
165
- if (options.description != null && buffer_1.Buffer.byteLength(options.description, "utf8") > 500)
158
+ const _options = {
159
+ paymentHash: (0, Utils_1.parseHashValueExact32Bytes)(options?.paymentHash, "payment hash"),
160
+ description: options?.description,
161
+ descriptionHash: (0, Utils_1.parseHashValueExact32Bytes)(options?.descriptionHash, "description hash"),
162
+ unsafeSkipLnNodeCheck: options?.unsafeSkipLnNodeCheck ?? this._options.unsafeSkipLnNodeCheck
163
+ };
164
+ if (_options.description != null && buffer_1.Buffer.byteLength(_options.description, "utf8") > 500)
166
165
  throw new UserError_1.UserError("Invalid description length");
167
166
  let secret;
168
167
  let paymentHash;
169
- if (options?.paymentHash != null) {
170
- paymentHash = options.paymentHash;
168
+ if (_options.paymentHash != null) {
169
+ paymentHash = _options.paymentHash;
171
170
  }
172
171
  else {
173
172
  ({ secret, paymentHash } = this.getSecretAndHash());
@@ -194,14 +193,14 @@ class FromBTCLNWrapper extends IFromBTCLNWrapper_1.IFromBTCLNWrapper {
194
193
  amount: amountData.amount,
195
194
  claimer: recipient,
196
195
  token: amountData.token.toString(),
197
- description: options?.description,
198
- descriptionHash: options?.descriptionHash,
196
+ description: _options.description,
197
+ descriptionHash: _options.descriptionHash,
199
198
  exactOut: !amountData.exactIn,
200
199
  feeRate: (0, Utils_1.throwIfUndefined)(_preFetches.feeRatePromise),
201
200
  additionalParams
202
201
  }, this._options.postRequestTimeout, abortController.signal, retryCount > 0 ? false : undefined);
203
202
  return {
204
- lnCapacityPromise: options?.unsafeSkipLnNodeCheck ? null : this.preFetchLnCapacity(lnPublicKey),
203
+ lnCapacityPromise: _options.unsafeSkipLnNodeCheck ? null : this.preFetchLnCapacity(lnPublicKey),
205
204
  resp: await response
206
205
  };
207
206
  }, undefined, RequestError_1.RequestError, abortController.signal);
@@ -212,7 +211,7 @@ class FromBTCLNWrapper extends IFromBTCLNWrapper_1.IFromBTCLNWrapper {
212
211
  throw new IntermediaryError_1.IntermediaryError("Invalid returned swap invoice, no expiry date field");
213
212
  const amountIn = (BigInt(decodedPr.millisatoshis) + 999n) / 1000n;
214
213
  try {
215
- this.verifyReturnedData(resp, amountData, lp, options ?? {}, decodedPr, paymentHash);
214
+ this.verifyReturnedData(resp, amountData, lp, _options, decodedPr, paymentHash);
216
215
  const [pricingInfo] = await Promise.all([
217
216
  this.verifyReturnedPrice(lp.services[SwapType_1.SwapType.FROM_BTCLN], false, amountIn, resp.total, amountData.token, {}, _preFetches.pricePrefetchPromise, _preFetches.usdPricePrefetchPromise, abortController.signal),
218
217
  this.verifyIntermediaryLiquidity(resp.total, (0, Utils_1.throwIfUndefined)(liquidityPromise)),
@@ -259,8 +258,12 @@ class FromBTCLNWrapper extends IFromBTCLNWrapper_1.IFromBTCLNWrapper {
259
258
  async createViaLNURL(recipient, lnurl, amountData, lps, options, additionalParams, abortSignal) {
260
259
  if (!this.isInitialized)
261
260
  throw new Error("Not initialized, call init() first!");
262
- if (options?.paymentHash != null && options.paymentHash.length !== 32)
263
- throw new UserError_1.UserError("Invalid payment hash length, must be exactly 32 bytes!");
261
+ const _options = {
262
+ paymentHash: (0, Utils_1.parseHashValueExact32Bytes)(options?.paymentHash, "payment hash"),
263
+ description: options?.description,
264
+ descriptionHash: (0, Utils_1.parseHashValueExact32Bytes)(options?.descriptionHash, "description hash"),
265
+ unsafeSkipLnNodeCheck: options?.unsafeSkipLnNodeCheck ?? this._options.unsafeSkipLnNodeCheck
266
+ };
264
267
  const abortController = (0, Utils_1.extendAbortController)(abortSignal);
265
268
  const preFetches = {
266
269
  pricePrefetchPromise: this.preFetchPrice(amountData, abortController.signal),
@@ -289,7 +292,7 @@ class FromBTCLNWrapper extends IFromBTCLNWrapper_1.IFromBTCLNWrapper {
289
292
  if ((amount * 105n / 100n) > max)
290
293
  throw new UserError_1.UserError("Amount more than LNURL-withdraw maximum");
291
294
  }
292
- return this.create(recipient, amountData, lps, options, additionalParams, abortSignal, preFetches).map(data => {
295
+ return this.create(recipient, amountData, lps, _options, additionalParams, abortSignal, preFetches).map(data => {
293
296
  return {
294
297
  quote: data.quote.then(quote => {
295
298
  quote._setLNURLData(withdrawRequest.url, withdrawRequest.k1, withdrawRequest.callback);
@@ -313,11 +313,11 @@ export declare class FromBTCLNAutoSwap<T extends ChainType = ChainType> extends
313
313
  /**
314
314
  * @inheritDoc
315
315
  */
316
- getInput(): TokenAmount<T["ChainId"], BtcToken<true>>;
316
+ getInput(): TokenAmount<BtcToken<true>>;
317
317
  /**
318
318
  * @inheritDoc
319
319
  */
320
- getInputWithoutFee(): TokenAmount<T["ChainId"], BtcToken<true>>;
320
+ getInputWithoutFee(): TokenAmount<BtcToken<true>>;
321
321
  /**
322
322
  * @inheritDoc
323
323
  */
@@ -325,11 +325,11 @@ export declare class FromBTCLNAutoSwap<T extends ChainType = ChainType> extends
325
325
  /**
326
326
  * @inheritDoc
327
327
  */
328
- getOutput(): TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
328
+ getOutput(): TokenAmount<SCToken<T["ChainId"]>, true>;
329
329
  /**
330
330
  * @inheritDoc
331
331
  */
332
- getGasDropOutput(): TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
332
+ getGasDropOutput(): TokenAmount<SCToken<T["ChainId"]>, true>;
333
333
  /**
334
334
  * Returns the swap fee charged by the intermediary (LP) on this swap
335
335
  *
@@ -18,12 +18,53 @@ import { AmountData } from "../../../../types/AmountData";
18
18
  import { LNURLWithdrawParamsWithUrl } from "../../../../types/lnurl/LNURLWithdraw";
19
19
  import { AllOptional } from "../../../../utils/TypeUtils";
20
20
  export type FromBTCLNAutoOptions = {
21
- paymentHash?: Buffer;
21
+ /**
22
+ * Instead of letting the SDK generate the preimage/paymentHash pair internally you can pass your computed
23
+ * paymentHash here, this will create the swap with the provided payment hash. Note that swaps created this way
24
+ * won't settle automatically (as the SDK is missing the preimage). Once the HTLC towards the user is created in
25
+ * the {@link FromBTCLNAutoSwapState.CLAIM_COMMITED} state, you should pass the secret preimage manually in the
26
+ * {@link FromBTCLNAutoSwap.waitTillClaimed}, {@link FromBTCLNAutoSwap.claim} or {@link FromBTCLNAutoSwap.txsClaim}
27
+ * functions.
28
+ *
29
+ * Accepts both, a {@link Buffer} and a hexadecimal `string`
30
+ */
31
+ paymentHash?: Buffer | string;
32
+ /**
33
+ * Optional description to use for the swap lightning network invoice, keep the invoice length below 500 characters
34
+ */
22
35
  description?: string;
23
- descriptionHash?: Buffer;
36
+ /**
37
+ * Optional description hash to use for the lightning network invoice, useful when returning the invoice as part of
38
+ * an LNURL-pay service endpoint.
39
+ *
40
+ * Accepts both, a {@link Buffer} and a hexadecimal `string`
41
+ */
42
+ descriptionHash?: Buffer | string;
43
+ /**
44
+ * Optional additional native token to receive as an output of the swap (e.g. STRK on Starknet or cBTC on Citrea).
45
+ * When passed as a `bigint` it is specified in base units of the token and in `string` it is the human readable
46
+ * decimal format.
47
+ */
48
+ gasAmount?: bigint | string;
49
+ /**
50
+ * A flag to skip checking whether the lightning network node of the LP has enough channel liquidity to facilitate
51
+ * the swap.
52
+ */
24
53
  unsafeSkipLnNodeCheck?: boolean;
25
- gasAmount?: bigint;
54
+ /**
55
+ * A flag to attach 0 watchtower fee to the swap, this would make the settlement unattractive for the watchtowers
56
+ * and therefore automatic settlement for such swaps will not be possible, you will have to settle manually
57
+ * with {@link FromBTCLNSwap.claim} or {@link FromBTCLNSwap.txsClaim} functions.
58
+ */
26
59
  unsafeZeroWatchtowerFee?: boolean;
60
+ /**
61
+ * A safety factor to use when estimating the watchtower fee to attach to the swap (this has to cover the gas fee
62
+ * of watchtowers settling the swap). A higher multiple here would mean that a swap is more attractive for
63
+ * watchtowers to settle automatically.
64
+ *
65
+ * Uses a `1.25` multiple by default (i.e. the current network fee is multiplied by 1.25 and then used to estimate
66
+ * the settlement gas fee cost)
67
+ */
27
68
  feeSafetyFactor?: number;
28
69
  };
29
70
  export type FromBTCLNAutoWrapperOptions = ISwapWrapperOptions & {
@@ -221,22 +221,18 @@ class FromBTCLNAutoWrapper extends IFromBTCLNWrapper_1.IFromBTCLNWrapper {
221
221
  if (!this.isInitialized)
222
222
  throw new Error("Not initialized, call init() first!");
223
223
  const _options = {
224
- paymentHash: options?.paymentHash,
224
+ paymentHash: (0, Utils_1.parseHashValueExact32Bytes)(options?.paymentHash, "payment hash"),
225
225
  unsafeSkipLnNodeCheck: options?.unsafeSkipLnNodeCheck ?? this._options.unsafeSkipLnNodeCheck,
226
- gasAmount: options?.gasAmount ?? 0n,
226
+ gasAmount: this.parseGasAmount(options?.gasAmount),
227
227
  feeSafetyFactor: options?.feeSafetyFactor ?? 1.25,
228
228
  unsafeZeroWatchtowerFee: options?.unsafeZeroWatchtowerFee ?? false,
229
229
  description: options?.description,
230
- descriptionHash: options?.descriptionHash
230
+ descriptionHash: (0, Utils_1.parseHashValueExact32Bytes)(options?.descriptionHash, "description hash")
231
231
  };
232
- if (_options.paymentHash != null && _options.paymentHash.length !== 32)
233
- throw new UserError_1.UserError("Invalid payment hash length, must be exactly 32 bytes!");
234
- if (_options.descriptionHash != null && _options.descriptionHash.length !== 32)
235
- throw new UserError_1.UserError("Invalid description hash length");
232
+ if (amountData.token === this._chain.getNativeCurrencyAddress() && _options.gasAmount !== 0n)
233
+ throw new UserError_1.UserError("Cannot specify `gasAmount` for swaps to a native token!");
236
234
  if (_options.description != null && buffer_1.Buffer.byteLength(_options.description, "utf8") > 500)
237
235
  throw new UserError_1.UserError("Invalid description length");
238
- if (preFetches == null)
239
- preFetches = {};
240
236
  let secret;
241
237
  let paymentHash;
242
238
  if (_options?.paymentHash != null) {
@@ -248,6 +244,7 @@ class FromBTCLNAutoWrapper extends IFromBTCLNWrapper_1.IFromBTCLNWrapper {
248
244
  const claimHash = this._contract.getHashForHtlc(paymentHash);
249
245
  const nativeTokenAddress = this._chain.getNativeCurrencyAddress();
250
246
  const _abortController = (0, Utils_1.extendAbortController)(abortSignal);
247
+ preFetches ??= {};
251
248
  const _preFetches = {
252
249
  pricePrefetchPromise: preFetches?.pricePrefetchPromise ?? this.preFetchPrice(amountData, _abortController.signal),
253
250
  usdPricePrefetchPromise: preFetches?.usdPricePrefetchPromise ?? this.preFetchUsdPrice(_abortController.signal),
@@ -348,16 +345,14 @@ class FromBTCLNAutoWrapper extends IFromBTCLNWrapper_1.IFromBTCLNWrapper {
348
345
  if (!this.isInitialized)
349
346
  throw new Error("Not initialized, call init() first!");
350
347
  const _options = {
351
- paymentHash: options?.paymentHash,
348
+ paymentHash: (0, Utils_1.parseHashValueExact32Bytes)(options?.paymentHash, "payment hash"),
352
349
  unsafeSkipLnNodeCheck: options?.unsafeSkipLnNodeCheck ?? this._options.unsafeSkipLnNodeCheck,
353
- gasAmount: options?.gasAmount ?? 0n,
350
+ gasAmount: this.parseGasAmount(options?.gasAmount),
354
351
  feeSafetyFactor: options?.feeSafetyFactor ?? 1.25,
355
352
  unsafeZeroWatchtowerFee: options?.unsafeZeroWatchtowerFee ?? false,
356
353
  description: options?.description,
357
- descriptionHash: options?.descriptionHash
354
+ descriptionHash: (0, Utils_1.parseHashValueExact32Bytes)(options?.descriptionHash, "description hash")
358
355
  };
359
- if (_options.paymentHash != null && _options.paymentHash.length !== 32)
360
- throw new UserError_1.UserError("Invalid payment hash length, must be exactly 32 bytes!");
361
356
  const abortController = (0, Utils_1.extendAbortController)(abortSignal);
362
357
  const preFetches = {
363
358
  pricePrefetchPromise: this.preFetchPrice(amountData, abortController.signal),
@@ -199,13 +199,13 @@ export declare class FromBTCSwap<T extends ChainType = ChainType> extends IFromB
199
199
  /**
200
200
  * @inheritDoc
201
201
  */
202
- getInput(): TokenAmount<T["ChainId"], BtcToken<false>>;
202
+ getInput(): TokenAmount<BtcToken<false>>;
203
203
  /**
204
204
  * Returns claimer bounty, acting as a reward for watchtowers to claim the swap automatically,
205
205
  * this amount is pre-funded by the user on the destination chain when the swap escrow
206
206
  * is initiated. For total pre-funded deposit amount see {@link getTotalDeposit}.
207
207
  */
208
- getClaimerBounty(): TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
208
+ getClaimerBounty(): TokenAmount<SCToken<T["ChainId"]>, true>;
209
209
  /**
210
210
  * If the required number of confirmations is not known, this function tries to infer it by looping through
211
211
  * possible confirmation targets and comparing the claim hashes
@@ -281,7 +281,7 @@ export declare class FromBTCSwap<T extends ChainType = ChainType> extends IFromB
281
281
  /**
282
282
  * @inheritDoc
283
283
  */
284
- estimateBitcoinFee(_bitcoinWallet: IBitcoinWallet | MinimalBitcoinWalletInterface, feeRate?: number): Promise<TokenAmount<any, BtcToken<false>, true> | null>;
284
+ estimateBitcoinFee(_bitcoinWallet: IBitcoinWallet | MinimalBitcoinWalletInterface, feeRate?: number): Promise<TokenAmount<BtcToken<false>, true> | null>;
285
285
  /**
286
286
  * @inheritDoc
287
287
  */
@@ -16,9 +16,27 @@ import { IFromBTCSelfInitDefinition } from "../IFromBTCSelfInitSwap";
16
16
  import { AmountData } from "../../../../types/AmountData";
17
17
  import { AllOptional } from "../../../../utils/TypeUtils";
18
18
  export type FromBTCOptions = {
19
- feeSafetyFactor?: bigint;
20
- blockSafetyFactor?: number;
19
+ /**
20
+ * A flag to attach 0 watchtower fee to the swap, this would make the settlement unattractive for the watchtowers
21
+ * and therefore automatic settlement for such swaps will not be possible, you will have to settle manually
22
+ * with {@link FromBTCLNSwap.claim} or {@link FromBTCLNSwap.txsClaim} functions.
23
+ */
21
24
  unsafeZeroWatchtowerFee?: boolean;
25
+ /**
26
+ * A safety factor to use when estimating the watchtower fee to attach to the swap (this has to cover the gas fee
27
+ * of watchtowers settling the swap). A higher multiple here would mean that a swap is more attractive for
28
+ * watchtowers to settle automatically.
29
+ *
30
+ * Uses a `1.5` multiple by default (i.e. the current network fee is multiplied by 1.5 and then used to estimate
31
+ * the settlement gas fee cost).
32
+ *
33
+ * Also accepts `bigint` for legacy reasons.
34
+ */
35
+ feeSafetyFactor?: number | bigint;
36
+ /**
37
+ * @deprecated Removed as it is deemed not necessary
38
+ */
39
+ blockSafetyFactor?: number;
22
40
  };
23
41
  export type FromBTCWrapperOptions = ISwapWrapperOptions & {
24
42
  safetyFactor: number;
@@ -137,7 +137,7 @@ class FromBTCWrapper extends IFromBTCWrapper_1.IFromBTCWrapper {
137
137
  feePerBlock: 0n,
138
138
  safetyFactor: options.blockSafetyFactor,
139
139
  startTimestamp: startTimestamp,
140
- addBlock: 0,
140
+ addBlock: 0n,
141
141
  addFee: 0n
142
142
  };
143
143
  }
@@ -155,11 +155,11 @@ class FromBTCWrapper extends IFromBTCWrapper_1.IFromBTCWrapper {
155
155
  const currentBtcRelayBlock = btcRelayData.blockheight;
156
156
  const addBlock = Math.max(currentBtcBlock - currentBtcRelayBlock, 0);
157
157
  return {
158
- feePerBlock: feePerBlock * options.feeSafetyFactor,
158
+ feePerBlock: feePerBlock * options.feeSafetyFactorPPM / 1000000n,
159
159
  safetyFactor: options.blockSafetyFactor,
160
160
  startTimestamp: startTimestamp,
161
- addBlock,
162
- addFee: claimFeeRate * options.feeSafetyFactor
161
+ addBlock: BigInt(addBlock),
162
+ addFee: claimFeeRate * options.feeSafetyFactorPPM / 1000000n
163
163
  };
164
164
  }
165
165
  catch (e) {
@@ -178,8 +178,8 @@ class FromBTCWrapper extends IFromBTCWrapper_1.IFromBTCWrapper {
178
178
  */
179
179
  getClaimerBounty(data, options, claimerBounty) {
180
180
  const tsDelta = data.getExpiry() - claimerBounty.startTimestamp;
181
- const blocksDelta = tsDelta / BigInt(this._options.bitcoinBlocktime) * BigInt(options.blockSafetyFactor);
182
- const totalBlock = blocksDelta + BigInt(claimerBounty.addBlock);
181
+ const blocksDelta = tsDelta / BigInt(this._options.bitcoinBlocktime) * options.blockSafetyFactor;
182
+ const totalBlock = blocksDelta + claimerBounty.addBlock;
183
183
  return claimerBounty.addFee + (totalBlock * claimerBounty.feePerBlock);
184
184
  }
185
185
  /**
@@ -253,9 +253,16 @@ class FromBTCWrapper extends IFromBTCWrapper_1.IFromBTCWrapper {
253
253
  * @param abortSignal Abort signal
254
254
  */
255
255
  create(recipient, amountData, lps, options, additionalParams, abortSignal) {
256
+ let feeSafetyFactorPPM = 1500000n;
257
+ if (typeof (options?.feeSafetyFactor) === "bigint") {
258
+ feeSafetyFactorPPM = options.feeSafetyFactor * 1000000n;
259
+ }
260
+ else if (typeof (options?.feeSafetyFactor) === "number") {
261
+ feeSafetyFactorPPM = BigInt(Math.floor(options.feeSafetyFactor * 1000000));
262
+ }
256
263
  const _options = {
257
- blockSafetyFactor: options?.blockSafetyFactor ?? 1,
258
- feeSafetyFactor: options?.feeSafetyFactor ?? 2n,
264
+ blockSafetyFactor: options?.blockSafetyFactor != null ? BigInt(options.blockSafetyFactor) : 1n,
265
+ feeSafetyFactorPPM,
259
266
  unsafeZeroWatchtowerFee: options?.unsafeZeroWatchtowerFee ?? false
260
267
  };
261
268
  const sequence = this.getRandomSequence();
@@ -222,18 +222,18 @@ export declare abstract class IToBTCSwap<T extends ChainType = ChainType, D exte
222
222
  /**
223
223
  * @inheritDoc
224
224
  */
225
- getInput(): TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
225
+ getInput(): TokenAmount<SCToken<T["ChainId"]>, true>;
226
226
  /**
227
227
  * @inheritDoc
228
228
  */
229
- getInputWithoutFee(): TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
229
+ getInputWithoutFee(): TokenAmount<SCToken<T["ChainId"]>, true>;
230
230
  /**
231
231
  * Checks if the initiator/sender on the source chain has enough balance to go through with the swap
232
232
  */
233
233
  hasEnoughBalance(): Promise<{
234
234
  enoughBalance: boolean;
235
- balance: TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
236
- required: TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
235
+ balance: TokenAmount<SCToken<T["ChainId"]>, true>;
236
+ required: TokenAmount<SCToken<T["ChainId"]>, true>;
237
237
  }>;
238
238
  /**
239
239
  * Checks if the initiator/sender on the source chain has enough native token balance
@@ -241,8 +241,8 @@ export declare abstract class IToBTCSwap<T extends ChainType = ChainType, D exte
241
241
  */
242
242
  hasEnoughForTxFees(): Promise<{
243
243
  enoughBalance: boolean;
244
- balance: TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
245
- required: TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
244
+ balance: TokenAmount<SCToken<T["ChainId"]>, true>;
245
+ required: TokenAmount<SCToken<T["ChainId"]>, true>;
246
246
  }>;
247
247
  /**
248
248
  * Executes the swap with the provided smart chain wallet/signer
@@ -341,7 +341,7 @@ export declare abstract class IToBTCSwap<T extends ChainType = ChainType, D exte
341
341
  /**
342
342
  * Get the estimated smart chain transaction fee of the refund transaction
343
343
  */
344
- getRefundNetworkFee(): Promise<TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>>;
344
+ getRefundNetworkFee(): Promise<TokenAmount<SCToken<T["ChainId"]>, true>>;
345
345
  /**
346
346
  * @inheritDoc
347
347
  *
@@ -61,7 +61,7 @@ export declare class ToBTCLNSwap<T extends ChainType = ChainType> extends IToBTC
61
61
  /**
62
62
  * @inheritDoc
63
63
  */
64
- getOutput(): TokenAmount<T["ChainId"], BtcToken<true>>;
64
+ getOutput(): TokenAmount<BtcToken<true>>;
65
65
  /**
66
66
  * @inheritDoc
67
67
  */