@atomiqlabs/sdk 8.4.4 → 8.6.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 (80) 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 +36 -24
  10. package/dist/swapper/Swapper.js +20 -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 +4 -2
  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 +13 -17
  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 +8 -6
  37. package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +12 -3
  38. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +32 -1
  39. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +8 -5
  40. package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +3 -3
  41. package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +4 -4
  42. package/dist/types/Token.d.ts +65 -25
  43. package/dist/types/Token.js +28 -13
  44. package/dist/types/TokenAmount.d.ts +2 -2
  45. package/dist/types/fees/Fee.d.ts +3 -3
  46. package/dist/utils/Utils.d.ts +1 -0
  47. package/dist/utils/Utils.js +17 -1
  48. package/package.json +1 -1
  49. package/src/enums/SwapSide.ts +16 -0
  50. package/src/index.ts +1 -0
  51. package/src/intermediaries/apis/IntermediaryAPI.ts +4 -4
  52. package/src/storage/UnifiedSwapStorage.ts +2 -0
  53. package/src/swapper/Swapper.ts +56 -40
  54. package/src/swapper/SwapperWithChain.ts +15 -10
  55. package/src/swapper/SwapperWithSigner.ts +8 -3
  56. package/src/swaps/IBTCWalletSwap.ts +1 -1
  57. package/src/swaps/ISwap.ts +5 -3
  58. package/src/swaps/ISwapWithGasDrop.ts +1 -1
  59. package/src/swaps/ISwapWrapper.ts +24 -23
  60. package/src/swaps/escrow_swaps/IEscrowSelfInitSwap.ts +3 -3
  61. package/src/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.ts +8 -8
  62. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +5 -5
  63. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +48 -22
  64. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +4 -4
  65. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +57 -21
  66. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +3 -3
  67. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +57 -22
  68. package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +7 -7
  69. package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.ts +1 -1
  70. package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +80 -37
  71. package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.ts +1 -1
  72. package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +12 -3
  73. package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +21 -9
  74. package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +53 -11
  75. package/src/swaps/trusted/ln/LnForGasSwap.ts +3 -3
  76. package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +4 -4
  77. package/src/types/Token.ts +98 -32
  78. package/src/types/TokenAmount.ts +5 -7
  79. package/src/types/fees/Fee.ts +3 -3
  80. package/src/utils/Utils.ts +18 -2
@@ -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
  */
@@ -15,11 +15,55 @@ import { LNURLPayParamsWithUrl } from "../../../../types/lnurl/LNURLPay";
15
15
  import { AllOptional } from "../../../../utils/TypeUtils";
16
16
  import { LightningInvoiceCreateService } from "../../../../types/wallets/LightningInvoiceCreateService";
17
17
  export type ToBTCLNOptions = {
18
+ /**
19
+ * HTLC expiration timeout in seconds to use when offering the HTLC to the LP. Larger expirations mean that more
20
+ * lightning network payment paths can be considered (every hop in the lightning network payment adds additional
21
+ * timeout requirement). On the other side, larger expiration also means that user's funds are locked for longer
22
+ * in case of a non-cooperative LP.
23
+ *
24
+ * Uses 5 days as default.
25
+ */
18
26
  expirySeconds?: number;
27
+ /**
28
+ * Maximum fee for routing the swap output payment through the lightning network. Higher fee percentages means that
29
+ * more payment routes can be considered (every hop in the lightning network payment adds additional fee
30
+ * requirements).
31
+ *
32
+ * The fee is express as percentage of the swap value, uses `0.2` by default which means the maximum
33
+ * routing fee is capped at 0.2% of the swap value.
34
+ *
35
+ * The full fee also contains the base component (set by `maxRoutingBaseFee` option), the resulting maximum routing
36
+ * fee rate is:
37
+ *
38
+ * `maxRoutingFee` = `maxRoutingBaseFee` sats + `value` * `maxRoutingFeePercentage`%
39
+ */
40
+ maxRoutingFeePercentage?: number;
41
+ /**
42
+ *
43
+ * Maximum base fee (in sats) for routing the swap output payment through the lightning network. Higher fee
44
+ * percentages means that more payment routes can be considered (every hop in the lightning network payment adds additional fee
45
+ * requirements).
46
+ *
47
+ * Uses 10 sats as a default.
48
+ *
49
+ * The full fee also contains the value percentage component (set by `maxRoutingFeePercentage` option), the
50
+ * resulting maximum routing fee rate is:
51
+ *
52
+ * `maxRoutingFee` = `maxRoutingBaseFee` sats + (`value` * `maxRoutingFeePercentage`%)
53
+ */
54
+ maxRoutingBaseFee?: bigint;
55
+ /**
56
+ * @deprecated Use `maxRoutingFeePercentage` and express the routing fee in percentage instead!
57
+ */
58
+ maxRoutingPPM?: bigint;
59
+ /**
60
+ * @deprecated Adjust fee with `maxRoutingFeePercentage` & `maxRoutingBaseFee` params!
61
+ */
19
62
  maxFee?: bigint | Promise<bigint>;
63
+ /**
64
+ * @deprecated Pass desired HTLC expiration timeout as `expirySeconds`
65
+ */
20
66
  expiryTimestamp?: bigint;
21
- maxRoutingPPM?: bigint;
22
- maxRoutingBaseFee?: bigint;
23
67
  };
24
68
  export type ToBTCLNWrapperOptions = ISwapWrapperOptions & {
25
69
  lightningBaseFee: number;
@@ -71,7 +115,7 @@ export declare class ToBTCLNWrapper<T extends ChainType> extends IToBTCWrapper<T
71
115
  * @param parsedPr Parsed bolt11 lightning invoice
72
116
  * @param token Smart chain token to be used in the swap
73
117
  * @param lp
74
- * @param options Swap options as passed to the swap create function
118
+ * @param calculatedOptions Swap options computed from the swap create options
75
119
  * @param data Parsed swap data returned by the LP
76
120
  * @param requiredTotal Required total to be paid on the input (for exactIn swaps)
77
121
  *
@@ -88,7 +132,7 @@ export declare class ToBTCLNWrapper<T extends ChainType> extends IToBTCWrapper<T
88
132
  * @param lp Intermediary
89
133
  * @param pr bolt11 lightning network invoice
90
134
  * @param parsedPr Parsed bolt11 lightning network invoice
91
- * @param options Options as passed to the swap create function
135
+ * @param calculatedOptions Swap options computed from the swap create options
92
136
  * @param preFetches
93
137
  * @param abort Abort signal or controller, if AbortController is passed it is used as-is, when AbortSignal is passed
94
138
  * it is extended with extendAbortController and then used
@@ -110,7 +154,9 @@ export declare class ToBTCLNWrapper<T extends ChainType> extends IToBTCWrapper<T
110
154
  * @param abortSignal Abort signal
111
155
  * @param preFetches Optional existing pre-fetch promises for the swap (only used internally for LNURL swaps)
112
156
  */
113
- create(signer: string, recipient: string, amountData: Omit<AmountData, "amount">, lps: Intermediary[], options?: ToBTCLNOptions, additionalParams?: Record<string, any>, abortSignal?: AbortSignal, preFetches?: {
157
+ create(signer: string, recipient: string, amountData: Omit<AmountData, "amount"> & {
158
+ exactIn: false;
159
+ }, lps: Intermediary[], options?: ToBTCLNOptions, additionalParams?: Record<string, any>, abortSignal?: AbortSignal, preFetches?: {
114
160
  feeRatePromise: Promise<string | undefined>;
115
161
  pricePreFetchPromise: Promise<bigint | undefined>;
116
162
  usdPricePrefetchPromise: Promise<number | undefined>;
@@ -138,7 +184,7 @@ export declare class ToBTCLNWrapper<T extends ChainType> extends IToBTCWrapper<T
138
184
  * @param lp Intermediary (LPs) to get the quote from
139
185
  * @param dummyPr Dummy minimum value bolt11 lightning invoice returned from the LNURL-pay, used to estimate
140
186
  * network fees for an actual invoice
141
- * @param options Optional additional quote options
187
+ * @param calculatedOptions Swap options computed from the swap create options
142
188
  * @param preFetches Optional existing pre-fetch promises for the swap (only used internally for LNURL swaps)
143
189
  * @param abortSignal Abort signal
144
190
  * @param additionalParams Additional params to be sent to the intermediary
@@ -23,7 +23,7 @@ const RetryUtils_1 = require("../../../../utils/RetryUtils");
23
23
  class ToBTCLNWrapper extends IToBTCWrapper_1.IToBTCWrapper {
24
24
  constructor(chainIdentifier, unifiedStorage, unifiedChainEvents, chain, contract, prices, tokens, swapDataDeserializer, options, events) {
25
25
  super(chainIdentifier, unifiedStorage, unifiedChainEvents, chain, contract, prices, tokens, swapDataDeserializer, {
26
- paymentTimeoutSeconds: options?.paymentTimeoutSeconds ?? 4 * 24 * 60 * 60,
26
+ paymentTimeoutSeconds: options?.paymentTimeoutSeconds ?? 5 * 24 * 60 * 60,
27
27
  lightningBaseFee: options?.lightningBaseFee ?? 10,
28
28
  lightningFeePPM: options?.lightningFeePPM ?? 2000
29
29
  }, events);
@@ -36,7 +36,9 @@ class ToBTCLNWrapper extends IToBTCWrapper_1.IToBTCWrapper {
36
36
  toRequiredSwapOptions(amountData, options, pricePreFetchPromise, abortSignal) {
37
37
  const expirySeconds = options?.expirySeconds ?? this._options.paymentTimeoutSeconds;
38
38
  const maxRoutingBaseFee = options?.maxRoutingBaseFee ?? BigInt(this._options.lightningBaseFee);
39
- const maxRoutingPPM = options?.maxRoutingPPM ?? BigInt(this._options.lightningFeePPM);
39
+ const maxRoutingPPM = options?.maxRoutingFeePercentage != null
40
+ ? BigInt(Math.floor(options.maxRoutingFeePercentage * 10000))
41
+ : options?.maxRoutingPPM ?? BigInt(this._options.lightningFeePPM);
40
42
  let maxFee;
41
43
  if (options?.maxFee != null) {
42
44
  maxFee = options.maxFee;
@@ -56,10 +58,7 @@ class ToBTCLNWrapper extends IToBTCWrapper_1.IToBTCWrapper {
56
58
  maxFee = this.calculateFeeForAmount(amountData.amount, maxRoutingBaseFee, maxRoutingPPM);
57
59
  }
58
60
  return {
59
- expirySeconds,
60
61
  expiryTimestamp: options?.expiryTimestamp ?? BigInt(Math.floor(Date.now() / 1000) + expirySeconds),
61
- maxRoutingBaseFee,
62
- maxRoutingPPM,
63
62
  maxFee
64
63
  };
65
64
  }
@@ -101,7 +100,7 @@ class ToBTCLNWrapper extends IToBTCWrapper_1.IToBTCWrapper {
101
100
  * @param parsedPr Parsed bolt11 lightning invoice
102
101
  * @param token Smart chain token to be used in the swap
103
102
  * @param lp
104
- * @param options Swap options as passed to the swap create function
103
+ * @param calculatedOptions Swap options computed from the swap create options
105
104
  * @param data Parsed swap data returned by the LP
106
105
  * @param requiredTotal Required total to be paid on the input (for exactIn swaps)
107
106
  *
@@ -109,8 +108,8 @@ class ToBTCLNWrapper extends IToBTCWrapper_1.IToBTCWrapper {
109
108
  *
110
109
  * @private
111
110
  */
112
- async verifyReturnedData(signer, resp, parsedPr, token, lp, options, data, requiredTotal) {
113
- if (resp.routingFeeSats > await options.maxFee)
111
+ async verifyReturnedData(signer, resp, parsedPr, token, lp, calculatedOptions, data, requiredTotal) {
112
+ if (resp.routingFeeSats > await calculatedOptions.maxFee)
114
113
  throw new IntermediaryError_1.IntermediaryError("Invalid max fee sats returned");
115
114
  if (requiredTotal != null && resp.total !== requiredTotal)
116
115
  throw new IntermediaryError_1.IntermediaryError("Invalid data returned - total amount");
@@ -119,7 +118,7 @@ class ToBTCLNWrapper extends IToBTCWrapper_1.IToBTCWrapper {
119
118
  const claimHash = this._contract.getHashForHtlc(Buffer.from(parsedPr.tagsObject.payment_hash, "hex"));
120
119
  if (data.getAmount() !== resp.total ||
121
120
  !Buffer.from(data.getClaimHash(), "hex").equals(claimHash) ||
122
- data.getExpiry() !== options.expiryTimestamp ||
121
+ data.getExpiry() !== calculatedOptions.expiryTimestamp ||
123
122
  data.getType() !== base_1.ChainSwapType.HTLC ||
124
123
  !data.isPayIn() ||
125
124
  !data.isToken(token) ||
@@ -137,7 +136,7 @@ class ToBTCLNWrapper extends IToBTCWrapper_1.IToBTCWrapper {
137
136
  * @param lp Intermediary
138
137
  * @param pr bolt11 lightning network invoice
139
138
  * @param parsedPr Parsed bolt11 lightning network invoice
140
- * @param options Options as passed to the swap create function
139
+ * @param calculatedOptions Swap options computed from the swap create options
141
140
  * @param preFetches
142
141
  * @param abort Abort signal or controller, if AbortController is passed it is used as-is, when AbortSignal is passed
143
142
  * it is extended with extendAbortController and then used
@@ -145,7 +144,7 @@ class ToBTCLNWrapper extends IToBTCWrapper_1.IToBTCWrapper {
145
144
  *
146
145
  * @private
147
146
  */
148
- async getIntermediaryQuote(signer, amountData, lp, pr, parsedPr, options, preFetches, abort, additionalParams) {
147
+ async getIntermediaryQuote(signer, amountData, lp, pr, parsedPr, calculatedOptions, preFetches, abort, additionalParams) {
149
148
  if (lp.services[SwapType_1.SwapType.TO_BTCLN] == null)
150
149
  throw new Error("LP service for processing to btcln swaps not found!");
151
150
  const abortController = abort instanceof AbortController ? abort : (0, Utils_1.extendAbortController)(abort);
@@ -155,8 +154,8 @@ class ToBTCLNWrapper extends IToBTCWrapper_1.IToBTCWrapper {
155
154
  const { signDataPrefetch, response } = IntermediaryAPI_1.IntermediaryAPI.initToBTCLN(this.chainIdentifier, lp.url, {
156
155
  offerer: signer,
157
156
  pr,
158
- maxFee: await options.maxFee,
159
- expiryTimestamp: options.expiryTimestamp,
157
+ maxFee: await calculatedOptions.maxFee,
158
+ expiryTimestamp: calculatedOptions.expiryTimestamp,
160
159
  token: amountData.token,
161
160
  feeRate: (0, Utils_1.throwIfUndefined)(preFetches.feeRatePromise),
162
161
  additionalParams
@@ -172,7 +171,7 @@ class ToBTCLNWrapper extends IToBTCWrapper_1.IToBTCWrapper {
172
171
  const totalFee = resp.swapFee + resp.maxFee;
173
172
  const data = new this._swapDataDeserializer(resp.data);
174
173
  data.setOfferer(signer);
175
- await this.verifyReturnedData(signer, resp, parsedPr, amountData.token, lp, options, data);
174
+ await this.verifyReturnedData(signer, resp, parsedPr, amountData.token, lp, calculatedOptions, data);
176
175
  const [pricingInfo, signatureExpiry, reputation] = await Promise.all([
177
176
  this.verifyReturnedPrice(lp.services[SwapType_1.SwapType.TO_BTCLN], true, amountOut, data.getAmount(), amountData.token, { networkFee: resp.maxFee }, preFetches.pricePreFetchPromise, preFetches.usdPricePrefetchPromise, abortController.signal),
178
177
  this.verifyReturnedSignature(signer, data, resp, preFetches.feeRatePromise, signDataPromise, abortController.signal),
@@ -223,16 +222,7 @@ class ToBTCLNWrapper extends IToBTCWrapper_1.IToBTCWrapper {
223
222
  if (parsedPr.millisatoshis == null)
224
223
  throw new UserError_1.UserError("Must be an invoice with amount");
225
224
  const amountOut = (BigInt(parsedPr.millisatoshis) + 999n) / 1000n;
226
- const expirySeconds = options?.expirySeconds ?? this._options.paymentTimeoutSeconds;
227
- const maxRoutingBaseFee = options?.maxRoutingBaseFee ?? BigInt(this._options.lightningBaseFee);
228
- const maxRoutingPPM = options?.maxRoutingPPM ?? BigInt(this._options.lightningFeePPM);
229
- const _options = {
230
- expirySeconds,
231
- expiryTimestamp: options?.expiryTimestamp ?? BigInt(Math.floor(Date.now() / 1000) + expirySeconds),
232
- maxRoutingBaseFee,
233
- maxRoutingPPM,
234
- maxFee: options?.maxFee ?? this.calculateFeeForAmount(amountOut, maxRoutingBaseFee, maxRoutingPPM)
235
- };
225
+ const _options = this.toRequiredSwapOptions({ ...amountData, amount: amountOut }, options);
236
226
  if (parsedPr.tagsObject.payment_hash == null)
237
227
  throw new Error("Provided lightning invoice doesn't contain payment hash field!");
238
228
  await this.checkPaymentHashWasPaid(parsedPr.tagsObject.payment_hash);
@@ -279,14 +269,14 @@ class ToBTCLNWrapper extends IToBTCWrapper_1.IToBTCWrapper {
279
269
  * @param lp Intermediary (LPs) to get the quote from
280
270
  * @param dummyPr Dummy minimum value bolt11 lightning invoice returned from the LNURL-pay, used to estimate
281
271
  * network fees for an actual invoice
282
- * @param options Optional additional quote options
272
+ * @param calculatedOptions Swap options computed from the swap create options
283
273
  * @param preFetches Optional existing pre-fetch promises for the swap (only used internally for LNURL swaps)
284
274
  * @param abortSignal Abort signal
285
275
  * @param additionalParams Additional params to be sent to the intermediary
286
276
  *
287
277
  * @private
288
278
  */
289
- async getIntermediaryQuoteExactIn(signer, amountData, invoiceCreateService, lp, dummyPr, options, preFetches, abortSignal, additionalParams) {
279
+ async getIntermediaryQuoteExactIn(signer, amountData, invoiceCreateService, lp, dummyPr, calculatedOptions, preFetches, abortSignal, additionalParams) {
290
280
  if (lp.services[SwapType_1.SwapType.TO_BTCLN] == null)
291
281
  throw new Error("LP service for processing to btcln swaps not found!");
292
282
  const abortController = (0, Utils_1.extendAbortController)(abortSignal);
@@ -298,8 +288,8 @@ class ToBTCLNWrapper extends IToBTCWrapper_1.IToBTCWrapper {
298
288
  offerer: signer,
299
289
  pr: dummyPr,
300
290
  amount: amountData.amount,
301
- maxFee: await options.maxFee,
302
- expiryTimestamp: options.expiryTimestamp,
291
+ maxFee: await calculatedOptions.maxFee,
292
+ expiryTimestamp: calculatedOptions.expiryTimestamp,
303
293
  additionalParams
304
294
  }, this._options.postRequestTimeout, abortController.signal, retryCount > 0 ? false : undefined);
305
295
  return {
@@ -331,7 +321,7 @@ class ToBTCLNWrapper extends IToBTCWrapper_1.IToBTCWrapper {
331
321
  const totalFee = resp.swapFee + resp.maxFee;
332
322
  const data = new this._swapDataDeserializer(resp.data);
333
323
  data.setOfferer(signer);
334
- await this.verifyReturnedData(signer, resp, parsedInvoice, amountData.token, lp, options, data, amountData.amount);
324
+ await this.verifyReturnedData(signer, resp, parsedInvoice, amountData.token, lp, calculatedOptions, data, amountData.amount);
335
325
  const [pricingInfo, signatureExpiry, reputation] = await Promise.all([
336
326
  this.verifyReturnedPrice(lp.services[SwapType_1.SwapType.TO_BTCLN], true, prepareResp.amount, data.getAmount(), amountData.token, { networkFee: resp.maxFee }, preFetches.pricePreFetchPromise, preFetches.usdPricePrefetchPromise, abortSignal),
337
327
  this.verifyReturnedSignature(signer, data, resp, preFetches.feeRatePromise, signDataPromise, abortController.signal),
@@ -413,7 +403,7 @@ class ToBTCLNWrapper extends IToBTCWrapper_1.IToBTCWrapper {
413
403
  throw new UserError_1.UserError("Amount more than maximum");
414
404
  }
415
405
  const invoice = await invoiceCreateService.getInvoice(Number(amountData.amount), _abortController.signal);
416
- return (await this.create(signer, invoice, amountData, lps, options, additionalParams, _abortController.signal, {
406
+ return (await this.create(signer, invoice, { ...amountData, exactIn: false }, lps, options, additionalParams, _abortController.signal, {
417
407
  feeRatePromise,
418
408
  pricePreFetchPromise,
419
409
  usdPricePrefetchPromise,
@@ -53,7 +53,7 @@ export declare class ToBTCSwap<T extends ChainType = ChainType> extends IToBTCSw
53
53
  /**
54
54
  * @inheritDoc
55
55
  */
56
- getOutput(): TokenAmount<T["ChainId"], BtcToken<false>>;
56
+ getOutput(): TokenAmount<BtcToken<false>>;
57
57
  /**
58
58
  * @inheritDoc
59
59
  */
@@ -14,7 +14,13 @@ import { ISwap } from "../../../ISwap";
14
14
  import { AmountData } from "../../../../types/AmountData";
15
15
  import { AllOptional } from "../../../../utils/TypeUtils";
16
16
  export type ToBTCOptions = {
17
+ /**
18
+ * @deprecated Ignored by the LP anyway
19
+ */
17
20
  confirmationTarget?: number;
21
+ /**
22
+ * @deprecated Default 2 confirmations should be enough for any currently supported amount by atomiq
23
+ */
18
24
  confirmations?: number;
19
25
  };
20
26
  export type ToBTCWrapperOptions = ISwapWrapperOptions & {
@@ -119,6 +119,7 @@ export declare function isSpvFromBTCSwapInit(obj: any): obj is SpvFromBTCSwapIni
119
119
  * @category Swaps/Bitcoin → Smart chain
120
120
  */
121
121
  export declare class SpvFromBTCSwap<T extends ChainType> extends ISwap<T, SpvFromBTCTypeDefinition<T>> implements IBTCWalletSwap, ISwapWithGasDrop<T>, IClaimableSwap<T, SpvFromBTCTypeDefinition<T>, SpvFromBTCSwapState> {
122
+ protected readonly currentVersion: number;
122
123
  readonly TYPE: SwapType.SPV_VAULT_FROM_BTC;
123
124
  /**
124
125
  * @internal
@@ -169,6 +170,7 @@ export declare class SpvFromBTCSwap<T extends ChainType> extends ISwap<T, SpvFro
169
170
  private readonly frontingFeeShare;
170
171
  private readonly executionFeeShare;
171
172
  private readonly gasPricingInfo?;
173
+ private posted?;
172
174
  /**
173
175
  * @internal
174
176
  */
@@ -323,7 +325,7 @@ export declare class SpvFromBTCSwap<T extends ChainType> extends ISwap<T, SpvFro
323
325
  *
324
326
  * @internal
325
327
  */
326
- protected getOutputWithoutFee(): TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
328
+ protected getOutputWithoutFee(): TokenAmount<SCToken<T["ChainId"]>, true>;
327
329
  /**
328
330
  * Returns the swap fee charged by the intermediary (LP) on this swap
329
331
  *
@@ -361,15 +363,15 @@ export declare class SpvFromBTCSwap<T extends ChainType> extends ISwap<T, SpvFro
361
363
  /**
362
364
  * @inheritDoc
363
365
  */
364
- getOutput(): TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
366
+ getOutput(): TokenAmount<SCToken<T["ChainId"]>, true>;
365
367
  /**
366
368
  * @inheritDoc
367
369
  */
368
- getGasDropOutput(): TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
370
+ getGasDropOutput(): TokenAmount<SCToken<T["ChainId"]>, true>;
369
371
  /**
370
372
  * @inheritDoc
371
373
  */
372
- getInputWithoutFee(): TokenAmount<T["ChainId"], BtcToken<false>, true>;
374
+ getInputWithoutFee(): TokenAmount<BtcToken<false>, true>;
373
375
  /**
374
376
  * @inheritDoc
375
377
  */
@@ -377,7 +379,7 @@ export declare class SpvFromBTCSwap<T extends ChainType> extends ISwap<T, SpvFro
377
379
  /**
378
380
  * @inheritDoc
379
381
  */
380
- getInput(): TokenAmount<T["ChainId"], BtcToken<false>, true>;
382
+ getInput(): TokenAmount<BtcToken<false>, true>;
381
383
  /**
382
384
  * @inheritDoc
383
385
  */
@@ -440,7 +442,7 @@ export declare class SpvFromBTCSwap<T extends ChainType> extends ISwap<T, SpvFro
440
442
  /**
441
443
  * @inheritDoc
442
444
  */
443
- estimateBitcoinFee(_bitcoinWallet: IBitcoinWallet | MinimalBitcoinWalletInterface, feeRate?: number): Promise<TokenAmount<any, BtcToken<false>, true> | null>;
445
+ estimateBitcoinFee(_bitcoinWallet: IBitcoinWallet | MinimalBitcoinWalletInterface, feeRate?: number): Promise<TokenAmount<BtcToken<false>, true> | null>;
444
446
  /**
445
447
  * @inheritDoc
446
448
  */
@@ -143,6 +143,7 @@ class SpvFromBTCSwap extends ISwap_1.ISwap {
143
143
  if (isSpvFromBTCSwapInit(initOrObject) && initOrObject.url != null)
144
144
  initOrObject.url += "/frombtc_spv";
145
145
  super(wrapper, initOrObject);
146
+ this.currentVersion = 2;
146
147
  this.TYPE = SwapType_1.SwapType.SPV_VAULT_FROM_BTC;
147
148
  /**
148
149
  * @internal
@@ -213,6 +214,7 @@ class SpvFromBTCSwap extends ISwap_1.ISwap {
213
214
  this._frontTxId = initOrObject.frontTxId;
214
215
  this.gasPricingInfo = (0, PriceInfoType_1.deserializePriceInfoType)(initOrObject.gasPricingInfo);
215
216
  this.btcTxConfirmedAt = initOrObject.btcTxConfirmedAt;
217
+ this.posted = initOrObject.posted;
216
218
  if (initOrObject.data != null)
217
219
  this._data = new this.wrapper._spvWithdrawalDataDeserializer(initOrObject.data);
218
220
  }
@@ -223,7 +225,12 @@ class SpvFromBTCSwap extends ISwap_1.ISwap {
223
225
  * @inheritDoc
224
226
  * @internal
225
227
  */
226
- upgradeVersion() { }
228
+ upgradeVersion() {
229
+ if (this.version === 1) {
230
+ this.posted = this.initiated;
231
+ this.version = 2;
232
+ }
233
+ }
227
234
  /**
228
235
  * @inheritDoc
229
236
  * @internal
@@ -723,6 +730,7 @@ class SpvFromBTCSwap extends ISwap_1.ISwap {
723
730
  }
724
731
  this._data = data;
725
732
  this.initiated = true;
733
+ this.posted = true;
726
734
  await this._saveAndEmit(SpvFromBTCSwapState.SIGNED);
727
735
  try {
728
736
  await IntermediaryAPI_1.IntermediaryAPI.initSpvFromBTC(this.chainIdentifier, this.url, {
@@ -895,7 +903,7 @@ class SpvFromBTCSwap extends ISwap_1.ISwap {
895
903
  async waitForBitcoinTransaction(updateCallback, checkIntervalSeconds, abortSignal) {
896
904
  if (this._state !== SpvFromBTCSwapState.POSTED &&
897
905
  this._state !== SpvFromBTCSwapState.BROADCASTED &&
898
- !(this._state === SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED && this.initiated))
906
+ !(this._state === SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED && this.posted))
899
907
  throw new Error("Must be in POSTED or BROADCASTED state!");
900
908
  if (this._data == null)
901
909
  throw new Error("Expected swap to have withdrawal data filled!");
@@ -1201,6 +1209,7 @@ class SpvFromBTCSwap extends ISwap_1.ISwap {
1201
1209
  executionFeeShare: this.executionFeeShare.toString(10),
1202
1210
  genesisSmartChainBlockHeight: this._genesisSmartChainBlockHeight,
1203
1211
  gasPricingInfo: (0, PriceInfoType_1.serializePriceInfoType)(this.gasPricingInfo),
1212
+ posted: this.posted,
1204
1213
  senderAddress: this._senderAddress,
1205
1214
  claimTxId: this._claimTxId,
1206
1215
  frontTxId: this._frontTxId,
@@ -1362,7 +1371,7 @@ class SpvFromBTCSwap extends ISwap_1.ISwap {
1362
1371
  return true;
1363
1372
  }
1364
1373
  }
1365
- if (this._state === SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED && !this.initiated) {
1374
+ if (this._state === SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED && !this.posted) {
1366
1375
  if (this.expiry < Date.now()) {
1367
1376
  this._state = SpvFromBTCSwapState.QUOTE_EXPIRED;
1368
1377
  if (save)
@@ -15,9 +15,40 @@ import { IClaimableSwapWrapper } from "../IClaimableSwapWrapper";
15
15
  import { AmountData } from "../../types/AmountData";
16
16
  import { AllOptional } from "../../utils/TypeUtils";
17
17
  export type SpvFromBTCOptions = {
18
- gasAmount?: bigint;
18
+ /**
19
+ * Optional additional native token to receive as an output of the swap (e.g. STRK on Starknet or cBTC on Citrea).
20
+ *
21
+ * When passed as a `bigint` it is specified in base units of the token and in `string` it is the human readable
22
+ * decimal format.
23
+ */
24
+ gasAmount?: bigint | string;
25
+ /**
26
+ * The LP enforces a minimum bitcoin fee rate in sats/vB for the swap transaction. With this config you can optionally
27
+ * limit how high of a minimum fee rate would you accept.
28
+ *
29
+ * By default the maximum allowed fee rate is calculated dynamically based on current bitcoin fee rate as:
30
+ *
31
+ * `maxAllowedBitcoinFeeRate` = 10 + `currentBitcoinFeeRate` * 1.5
32
+ */
33
+ maxAllowedBitcoinFeeRate?: number;
34
+ /**
35
+ * A flag to attach 0 watchtower fee to the swap, this would make the settlement unattractive for the watchtowers
36
+ * and therefore automatic settlement for such swaps will not be possible, you will have to settle manually
37
+ * with {@link FromBTCLNSwap.claim} or {@link FromBTCLNSwap.txsClaim} functions.
38
+ */
19
39
  unsafeZeroWatchtowerFee?: boolean;
40
+ /**
41
+ * A safety factor to use when estimating the watchtower fee to attach to the swap (this has to cover the gas fee
42
+ * of watchtowers settling the swap). A higher multiple here would mean that a swap is more attractive for
43
+ * watchtowers to settle automatically.
44
+ *
45
+ * Uses a `1.25` multiple by default (i.e. the current network fee is multiplied by 1.25 and then used to estimate
46
+ * the settlement gas fee cost)
47
+ */
20
48
  feeSafetyFactor?: number;
49
+ /**
50
+ * @deprecated Use `maxAllowedBitcoinFeeRate` instead!
51
+ */
21
52
  maxAllowedNetworkFeeRate?: number;
22
53
  };
23
54
  export type SpvFromBTCWrapperOptions = ISwapWrapperOptions & {
@@ -13,6 +13,7 @@ const RequestError_1 = require("../../errors/RequestError");
13
13
  const IntermediaryError_1 = require("../../errors/IntermediaryError");
14
14
  const btc_signer_1 = require("@scure/btc-signer");
15
15
  const RetryUtils_1 = require("../../utils/RetryUtils");
16
+ const UserError_1 = require("../../errors/UserError");
16
17
  /**
17
18
  * New spv vault (UTXO-controlled vault) based swaps for Bitcoin -> Smart chain swaps not requiring
18
19
  * any initiation on the destination chain, and with the added possibility for the user to receive
@@ -316,7 +317,7 @@ class SpvFromBTCWrapper extends ISwapWrapper_1.ISwapWrapper {
316
317
  if (resp.total !== adjustedAmount)
317
318
  throw new IntermediaryError_1.IntermediaryError("Invalid total returned");
318
319
  }
319
- if (options.gasAmount == null || options.gasAmount === 0n) {
320
+ if (options.gasAmount === 0n) {
320
321
  if (resp.totalGas !== 0n)
321
322
  throw new IntermediaryError_1.IntermediaryError("Invalid gas total returned");
322
323
  }
@@ -420,11 +421,13 @@ class SpvFromBTCWrapper extends ISwapWrapper_1.ISwapWrapper {
420
421
  */
421
422
  create(recipient, amountData, lps, options, additionalParams, abortSignal) {
422
423
  const _options = {
423
- gasAmount: options?.gasAmount ?? 0n,
424
+ gasAmount: this.parseGasAmount(options?.gasAmount),
424
425
  unsafeZeroWatchtowerFee: options?.unsafeZeroWatchtowerFee ?? false,
425
426
  feeSafetyFactor: options?.feeSafetyFactor ?? 1.25,
426
- maxAllowedNetworkFeeRate: options?.maxAllowedNetworkFeeRate ?? Infinity
427
+ maxAllowedBitcoinFeeRate: options?.maxAllowedBitcoinFeeRate ?? options?.maxAllowedNetworkFeeRate ?? Infinity
427
428
  };
429
+ if (amountData.token === this._chain.getNativeCurrencyAddress() && _options.gasAmount !== 0n)
430
+ throw new UserError_1.UserError("Cannot specify `gasAmount` for swaps to a native token!");
428
431
  const _abortController = (0, Utils_1.extendAbortController)(abortSignal);
429
432
  const pricePrefetchPromise = this.preFetchPrice(amountData, _abortController.signal);
430
433
  const usdPricePrefetchPromise = this.preFetchUsdPrice(_abortController.signal);
@@ -434,8 +437,8 @@ class SpvFromBTCWrapper extends ISwapWrapper_1.ISwapWrapper {
434
437
  undefined :
435
438
  this.preFetchPrice({ token: nativeTokenAddress }, _abortController.signal);
436
439
  const callerFeePrefetchPromise = this.preFetchCallerFeeShare(amountData, _options, pricePrefetchPromise, gasTokenPricePrefetchPromise, _abortController);
437
- const bitcoinFeeRatePromise = _options.maxAllowedNetworkFeeRate != Infinity ?
438
- Promise.resolve(_options.maxAllowedNetworkFeeRate) :
440
+ const bitcoinFeeRatePromise = _options.maxAllowedBitcoinFeeRate != Infinity ?
441
+ Promise.resolve(_options.maxAllowedBitcoinFeeRate) :
439
442
  this._btcRpc.getFeeRate().then(x => this._options.maxBtcFeeOffset + (x * this._options.maxBtcFeeMultiplier)).catch(e => {
440
443
  _abortController.abort(e);
441
444
  return undefined;
@@ -179,7 +179,7 @@ export declare class LnForGasSwap<T extends ChainType = ChainType> extends ISwap
179
179
  /**
180
180
  * @inheritDoc
181
181
  */
182
- getOutput(): TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
182
+ getOutput(): TokenAmount<SCToken<T["ChainId"]>, true>;
183
183
  /**
184
184
  * @inheritDoc
185
185
  */
@@ -187,11 +187,11 @@ export declare class LnForGasSwap<T extends ChainType = ChainType> extends ISwap
187
187
  /**
188
188
  * @inheritDoc
189
189
  */
190
- getInput(): TokenAmount<T["ChainId"], BtcToken<true>, true>;
190
+ getInput(): TokenAmount<BtcToken<true>, true>;
191
191
  /**
192
192
  * @inheritDoc
193
193
  */
194
- getInputWithoutFee(): TokenAmount<T["ChainId"], BtcToken<true>, true>;
194
+ getInputWithoutFee(): TokenAmount<BtcToken<true>, true>;
195
195
  /**
196
196
  * Returns the swap fee charged by the intermediary (LP) on this swap
197
197
  *
@@ -199,7 +199,7 @@ export declare class OnchainForGasSwap<T extends ChainType = ChainType> extends
199
199
  /**
200
200
  * @inheritDoc
201
201
  */
202
- getOutput(): TokenAmount<T["ChainId"], SCToken<T["ChainId"]>, true>;
202
+ getOutput(): TokenAmount<SCToken<T["ChainId"]>, true>;
203
203
  /**
204
204
  * @inheritDoc
205
205
  */
@@ -207,11 +207,11 @@ export declare class OnchainForGasSwap<T extends ChainType = ChainType> extends
207
207
  /**
208
208
  * @inheritDoc
209
209
  */
210
- getInput(): TokenAmount<T["ChainId"], BtcToken<false>, true>;
210
+ getInput(): TokenAmount<BtcToken<false>, true>;
211
211
  /**
212
212
  * @inheritDoc
213
213
  */
214
- getInputWithoutFee(): TokenAmount<T["ChainId"], BtcToken<false>, true>;
214
+ getInputWithoutFee(): TokenAmount<BtcToken<false>, true>;
215
215
  /**
216
216
  * Returns the swap fee charged by the intermediary (LP) on this swap
217
217
  *
@@ -255,7 +255,7 @@ export declare class OnchainForGasSwap<T extends ChainType = ChainType> extends
255
255
  /**
256
256
  * @inheritDoc
257
257
  */
258
- estimateBitcoinFee(_bitcoinWallet: IBitcoinWallet | MinimalBitcoinWalletInterface, feeRate?: number): Promise<TokenAmount<any, BtcToken<false>, true> | null>;
258
+ estimateBitcoinFee(_bitcoinWallet: IBitcoinWallet | MinimalBitcoinWalletInterface, feeRate?: number): Promise<TokenAmount<BtcToken<false>, true> | null>;
259
259
  /**
260
260
  * @inheritDoc
261
261
  */