@atomiqlabs/lp-lib 12.1.0 → 13.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/dist/index.d.ts +18 -13
  2. package/dist/index.js +18 -13
  3. package/dist/plugins/IPlugin.d.ts +35 -12
  4. package/dist/plugins/PluginManager.d.ts +38 -15
  5. package/dist/plugins/PluginManager.js +33 -9
  6. package/dist/prices/BinanceSwapPrice.d.ts +1 -1
  7. package/dist/prices/BinanceSwapPrice.js +1 -1
  8. package/dist/prices/CoinGeckoSwapPrice.d.ts +1 -1
  9. package/dist/prices/CoinGeckoSwapPrice.js +1 -1
  10. package/dist/{swaps → prices}/ISwapPrice.js +4 -0
  11. package/dist/prices/OKXSwapPrice.d.ts +1 -1
  12. package/dist/prices/OKXSwapPrice.js +1 -1
  13. package/dist/swaps/SwapHandler.d.ts +20 -58
  14. package/dist/swaps/SwapHandler.js +17 -186
  15. package/dist/swaps/SwapHandlerSwap.d.ts +8 -23
  16. package/dist/swaps/SwapHandlerSwap.js +7 -39
  17. package/dist/swaps/assertions/AmountAssertions.d.ts +28 -0
  18. package/dist/swaps/assertions/AmountAssertions.js +72 -0
  19. package/dist/swaps/assertions/FromBtcAmountAssertions.d.ts +76 -0
  20. package/dist/swaps/assertions/FromBtcAmountAssertions.js +162 -0
  21. package/dist/swaps/assertions/LightningAssertions.d.ts +44 -0
  22. package/dist/swaps/assertions/LightningAssertions.js +86 -0
  23. package/dist/swaps/assertions/ToBtcAmountAssertions.d.ts +53 -0
  24. package/dist/swaps/{ToBtcBaseSwapHandler.js → assertions/ToBtcAmountAssertions.js} +20 -94
  25. package/dist/swaps/escrow/EscrowHandler.d.ts +51 -0
  26. package/dist/swaps/escrow/EscrowHandler.js +158 -0
  27. package/dist/swaps/escrow/EscrowHandlerSwap.d.ts +35 -0
  28. package/dist/swaps/escrow/EscrowHandlerSwap.js +69 -0
  29. package/dist/swaps/{FromBtcBaseSwap.d.ts → escrow/FromBtcBaseSwap.d.ts} +2 -3
  30. package/dist/swaps/{FromBtcBaseSwap.js → escrow/FromBtcBaseSwap.js} +4 -7
  31. package/dist/swaps/{FromBtcBaseSwapHandler.d.ts → escrow/FromBtcBaseSwapHandler.d.ts} +10 -49
  32. package/dist/swaps/{FromBtcBaseSwapHandler.js → escrow/FromBtcBaseSwapHandler.js} +16 -137
  33. package/dist/swaps/{ToBtcBaseSwap.d.ts → escrow/ToBtcBaseSwap.d.ts} +2 -2
  34. package/dist/swaps/{ToBtcBaseSwap.js → escrow/ToBtcBaseSwap.js} +4 -4
  35. package/dist/swaps/escrow/ToBtcBaseSwapHandler.d.ts +53 -0
  36. package/dist/swaps/escrow/ToBtcBaseSwapHandler.js +81 -0
  37. package/dist/swaps/{frombtc_abstract → escrow/frombtc_abstract}/FromBtcAbs.d.ts +4 -4
  38. package/dist/swaps/{frombtc_abstract → escrow/frombtc_abstract}/FromBtcAbs.js +15 -15
  39. package/dist/swaps/{frombtc_abstract → escrow/frombtc_abstract}/FromBtcSwapAbs.js +1 -1
  40. package/dist/swaps/{frombtcln_abstract → escrow/frombtcln_abstract}/FromBtcLnAbs.d.ts +9 -7
  41. package/dist/swaps/{frombtcln_abstract → escrow/frombtcln_abstract}/FromBtcLnAbs.js +22 -19
  42. package/dist/swaps/{frombtcln_abstract → escrow/frombtcln_abstract}/FromBtcLnSwapAbs.js +3 -3
  43. package/dist/swaps/{tobtc_abstract → escrow/tobtc_abstract}/ToBtcAbs.d.ts +4 -4
  44. package/dist/swaps/{tobtc_abstract → escrow/tobtc_abstract}/ToBtcAbs.js +14 -13
  45. package/dist/swaps/{tobtc_abstract → escrow/tobtc_abstract}/ToBtcSwapAbs.js +3 -3
  46. package/dist/swaps/{tobtcln_abstract → escrow/tobtcln_abstract}/ToBtcLnAbs.d.ts +6 -26
  47. package/dist/swaps/{tobtcln_abstract → escrow/tobtcln_abstract}/ToBtcLnAbs.js +20 -57
  48. package/dist/swaps/{tobtcln_abstract → escrow/tobtcln_abstract}/ToBtcLnSwapAbs.js +3 -3
  49. package/dist/swaps/spv_vault_swap/SpvVault.d.ts +41 -0
  50. package/dist/swaps/spv_vault_swap/SpvVault.js +111 -0
  51. package/dist/swaps/spv_vault_swap/SpvVaultSwap.d.ts +63 -0
  52. package/dist/swaps/spv_vault_swap/SpvVaultSwap.js +145 -0
  53. package/dist/swaps/spv_vault_swap/SpvVaultSwapHandler.d.ts +68 -0
  54. package/dist/swaps/spv_vault_swap/SpvVaultSwapHandler.js +469 -0
  55. package/dist/swaps/spv_vault_swap/SpvVaults.d.ts +57 -0
  56. package/dist/swaps/spv_vault_swap/SpvVaults.js +369 -0
  57. package/dist/swaps/{frombtc_trusted → trusted/frombtc_trusted}/FromBtcTrusted.d.ts +10 -13
  58. package/dist/swaps/{frombtc_trusted → trusted/frombtc_trusted}/FromBtcTrusted.js +25 -30
  59. package/dist/swaps/{frombtc_trusted → trusted/frombtc_trusted}/FromBtcTrustedSwap.d.ts +9 -4
  60. package/dist/swaps/{frombtc_trusted → trusted/frombtc_trusted}/FromBtcTrustedSwap.js +15 -7
  61. package/dist/swaps/{frombtcln_trusted → trusted/frombtcln_trusted}/FromBtcLnTrusted.d.ts +12 -14
  62. package/dist/swaps/{frombtcln_trusted → trusted/frombtcln_trusted}/FromBtcLnTrusted.js +33 -35
  63. package/dist/swaps/{frombtcln_trusted → trusted/frombtcln_trusted}/FromBtcLnTrustedSwap.d.ts +9 -4
  64. package/dist/swaps/{frombtcln_trusted → trusted/frombtcln_trusted}/FromBtcLnTrustedSwap.js +17 -7
  65. package/dist/utils/Utils.d.ts +13 -5
  66. package/dist/utils/Utils.js +23 -1
  67. package/dist/wallets/IBitcoinWallet.d.ts +6 -0
  68. package/dist/wallets/ISpvVaultSigner.d.ts +7 -0
  69. package/dist/wallets/ISpvVaultSigner.js +2 -0
  70. package/dist/wallets/ISpvVaultWallet.d.ts +42 -0
  71. package/dist/wallets/ISpvVaultWallet.js +2 -0
  72. package/package.json +2 -2
  73. package/src/index.ts +21 -15
  74. package/src/plugins/IPlugin.ts +27 -19
  75. package/src/plugins/PluginManager.ts +51 -26
  76. package/src/prices/BinanceSwapPrice.ts +1 -1
  77. package/src/prices/CoinGeckoSwapPrice.ts +1 -1
  78. package/src/{swaps → prices}/ISwapPrice.ts +4 -0
  79. package/src/prices/OKXSwapPrice.ts +1 -1
  80. package/src/swaps/SwapHandler.ts +22 -205
  81. package/src/swaps/SwapHandlerSwap.ts +10 -46
  82. package/src/swaps/assertions/AmountAssertions.ts +77 -0
  83. package/src/swaps/assertions/FromBtcAmountAssertions.ts +228 -0
  84. package/src/swaps/assertions/LightningAssertions.ts +103 -0
  85. package/src/swaps/{ToBtcBaseSwapHandler.ts → assertions/ToBtcAmountAssertions.ts} +27 -142
  86. package/src/swaps/escrow/EscrowHandler.ts +179 -0
  87. package/src/swaps/escrow/EscrowHandlerSwap.ts +87 -0
  88. package/src/swaps/{FromBtcBaseSwap.ts → escrow/FromBtcBaseSwap.ts} +4 -8
  89. package/src/swaps/{FromBtcBaseSwapHandler.ts → escrow/FromBtcBaseSwapHandler.ts} +30 -190
  90. package/src/swaps/{ToBtcBaseSwap.ts → escrow/ToBtcBaseSwap.ts} +4 -5
  91. package/src/swaps/escrow/ToBtcBaseSwapHandler.ts +130 -0
  92. package/src/swaps/{frombtc_abstract → escrow/frombtc_abstract}/FromBtcAbs.ts +20 -20
  93. package/src/swaps/{frombtc_abstract → escrow/frombtc_abstract}/FromBtcSwapAbs.ts +1 -1
  94. package/src/swaps/{frombtcln_abstract → escrow/frombtcln_abstract}/FromBtcLnAbs.ts +29 -25
  95. package/src/swaps/{frombtcln_abstract → escrow/frombtcln_abstract}/FromBtcLnSwapAbs.ts +2 -2
  96. package/src/swaps/{tobtc_abstract → escrow/tobtc_abstract}/ToBtcAbs.ts +19 -18
  97. package/src/swaps/{tobtc_abstract → escrow/tobtc_abstract}/ToBtcSwapAbs.ts +2 -2
  98. package/src/swaps/{tobtcln_abstract → escrow/tobtcln_abstract}/ToBtcLnAbs.ts +26 -66
  99. package/src/swaps/{tobtcln_abstract → escrow/tobtcln_abstract}/ToBtcLnSwapAbs.ts +2 -2
  100. package/src/swaps/spv_vault_swap/SpvVault.ts +143 -0
  101. package/src/swaps/spv_vault_swap/SpvVaultSwap.ts +207 -0
  102. package/src/swaps/spv_vault_swap/SpvVaultSwapHandler.ts +606 -0
  103. package/src/swaps/spv_vault_swap/SpvVaults.ts +441 -0
  104. package/src/swaps/{frombtc_trusted → trusted/frombtc_trusted}/FromBtcTrusted.ts +36 -51
  105. package/src/swaps/{frombtc_trusted → trusted/frombtc_trusted}/FromBtcTrustedSwap.ts +18 -8
  106. package/src/swaps/{frombtcln_trusted → trusted/frombtcln_trusted}/FromBtcLnTrusted.ts +43 -52
  107. package/src/swaps/{frombtcln_trusted → trusted/frombtcln_trusted}/FromBtcLnTrustedSwap.ts +20 -8
  108. package/src/utils/Utils.ts +27 -1
  109. package/src/wallets/IBitcoinWallet.ts +4 -0
  110. package/src/wallets/ISpvVaultSigner.ts +11 -0
  111. package/dist/swaps/FromBtcLnBaseSwapHandler.d.ts +0 -26
  112. package/dist/swaps/FromBtcLnBaseSwapHandler.js +0 -46
  113. package/dist/swaps/ToBtcBaseSwapHandler.d.ts +0 -95
  114. package/src/swaps/FromBtcLnBaseSwapHandler.ts +0 -63
  115. /package/dist/{swaps → prices}/ISwapPrice.d.ts +0 -0
  116. /package/dist/swaps/{frombtc_abstract → escrow/frombtc_abstract}/FromBtcSwapAbs.d.ts +0 -0
  117. /package/dist/swaps/{frombtcln_abstract → escrow/frombtcln_abstract}/FromBtcLnSwapAbs.d.ts +0 -0
  118. /package/dist/swaps/{tobtc_abstract → escrow/tobtc_abstract}/ToBtcSwapAbs.d.ts +0 -0
  119. /package/dist/swaps/{tobtcln_abstract → escrow/tobtcln_abstract}/ToBtcLnSwapAbs.d.ts +0 -0
@@ -1,17 +1,13 @@
1
- import {SwapHandlerSwap} from "./SwapHandlerSwap";
2
1
  import {SwapData} from "@atomiqlabs/base";
3
- import {RequestData, SwapBaseConfig, SwapHandler} from "./SwapHandler";
4
- import {IParamReader} from "../utils/paramcoders/IParamReader";
5
- import {FieldTypeEnum} from "../utils/paramcoders/SchemaVerifier";
6
- import {FromBtcLnRequestType} from "./frombtcln_abstract/FromBtcLnAbs";
7
- import {FromBtcRequestType} from "./frombtc_abstract/FromBtcAbs";
8
- import {PluginManager} from "../plugins/PluginManager";
9
- import {
10
- isPluginQuote,
11
- isQuoteSetFees
12
- } from "../plugins/IPlugin";
2
+ import {MultichainData, SwapBaseConfig} from "../SwapHandler";
3
+ import {IParamReader} from "../../utils/paramcoders/IParamReader";
4
+ import {FieldTypeEnum} from "../../utils/paramcoders/SchemaVerifier";
13
5
  import {Request} from "express";
14
- import {FromBtcLnTrustedRequestType} from "./frombtcln_trusted/FromBtcLnTrusted";
6
+ import {EscrowHandler} from "./EscrowHandler";
7
+ import {FromBtcBaseSwap} from "./FromBtcBaseSwap";
8
+ import {FromBtcAmountAssertions} from "../assertions/FromBtcAmountAssertions";
9
+ import {IIntermediaryStorage} from "../../storage/IIntermediaryStorage";
10
+ import {ISwapPrice} from "../../prices/ISwapPrice";
15
11
 
16
12
  const secondsInYear = BigInt(365*24*60*60);
17
13
 
@@ -19,10 +15,23 @@ export type FromBtcBaseConfig = SwapBaseConfig & {
19
15
  securityDepositAPY: number
20
16
  };
21
17
 
22
- export abstract class FromBtcBaseSwapHandler<V extends SwapHandlerSwap<SwapData, S>, S> extends SwapHandler<V, S> {
18
+ export abstract class FromBtcBaseSwapHandler<V extends FromBtcBaseSwap<SwapData, S>, S> extends EscrowHandler<V, S> {
23
19
 
24
20
  abstract config: FromBtcBaseConfig;
25
21
 
22
+ readonly AmountAssertions: FromBtcAmountAssertions;
23
+
24
+ constructor(
25
+ storageDirectory: IIntermediaryStorage<V>,
26
+ path: string,
27
+ chainsData: MultichainData,
28
+ swapPricing: ISwapPrice,
29
+ config: FromBtcBaseConfig
30
+ ) {
31
+ super(storageDirectory, path, chainsData, swapPricing);
32
+ this.AmountAssertions = new FromBtcAmountAssertions(config, swapPricing);
33
+ }
34
+
26
35
  /**
27
36
  * Starts a pre-fetch for swap price & security deposit price
28
37
  *
@@ -41,15 +50,15 @@ export abstract class FromBtcBaseSwapHandler<V extends SwapHandlerSwap<SwapData,
41
50
  abortController.abort(e);
42
51
  return null;
43
52
  });
44
- const {swapContract} = this.getChain(chainIdentifier);
45
- const gasTokenPricePrefetchPromise: Promise<bigint> = useToken.toString()===swapContract.getNativeCurrencyAddress().toString() ?
53
+ const {chainInterface} = this.getChain(chainIdentifier);
54
+ const gasTokenPricePrefetchPromise: Promise<bigint> = useToken.toString()===chainInterface.getNativeCurrencyAddress().toString() ?
46
55
  pricePrefetchPromise :
47
- this.swapPricing.preFetchPrice(swapContract.getNativeCurrencyAddress(), chainIdentifier).catch(e => {
56
+ this.swapPricing.preFetchPrice(chainInterface.getNativeCurrencyAddress(), chainIdentifier).catch(e => {
48
57
  this.logger.error("getFromBtcPricePrefetches(): gasTokenPricePrefetchPromise error: ", e);
49
58
  abortController.abort(e);
50
59
  return null;
51
60
  });
52
- const depositTokenPricePrefetchPromise: Promise<bigint> = depositToken===swapContract.getNativeCurrencyAddress() ?
61
+ const depositTokenPricePrefetchPromise: Promise<bigint> = depositToken===chainInterface.getNativeCurrencyAddress() ?
53
62
  gasTokenPricePrefetchPromise :
54
63
  this.swapPricing.preFetchPrice(depositToken, chainIdentifier).catch(e => {
55
64
  this.logger.error("getFromBtcPricePrefetches(): depositTokenPricePrefetchPromise error: ", e);
@@ -75,9 +84,9 @@ export abstract class FromBtcBaseSwapHandler<V extends SwapHandlerSwap<SwapData,
75
84
  abortController: AbortController
76
85
  ): Promise<bigint> {
77
86
  //Solana workaround
78
- const {swapContract} = this.getChain(chainIdentifier);
87
+ const {swapContract, chainInterface} = this.getChain(chainIdentifier);
79
88
  let feeResult: bigint;
80
- const gasToken = swapContract.getNativeCurrencyAddress();
89
+ const gasToken = chainInterface.getNativeCurrencyAddress();
81
90
  if (swapContract.getRawRefundFee != null) {
82
91
  try {
83
92
  feeResult = await swapContract.getRawRefundFee(dummySwapData);
@@ -147,9 +156,9 @@ export abstract class FromBtcBaseSwapHandler<V extends SwapHandlerSwap<SwapData,
147
156
  * @throws {DefinedRuntimeError} will throw an error if there are not enough funds in the vault
148
157
  */
149
158
  protected checkAllowedDepositToken(chainIdentifier: string, depositToken: string): void {
150
- const {swapContract, allowedDepositTokens} = this.getChain(chainIdentifier);
159
+ const {chainInterface, allowedDepositTokens} = this.getChain(chainIdentifier);
151
160
  if(allowedDepositTokens==null) {
152
- if(depositToken!==swapContract.getNativeCurrencyAddress()) throw {
161
+ if(depositToken!==chainInterface.getNativeCurrencyAddress()) throw {
153
162
  code: 20190,
154
163
  msg: "Unsupported deposit token"
155
164
  };
@@ -161,175 +170,6 @@ export abstract class FromBtcBaseSwapHandler<V extends SwapHandlerSwap<SwapData,
161
170
  }
162
171
  }
163
172
 
164
-
165
- /**
166
- * Checks minimums/maximums, calculates the fee & total amount
167
- *
168
- * @param request
169
- * @param requestedAmount
170
- * @param useToken
171
- * @throws {DefinedRuntimeError} will throw an error if the amount is outside minimum/maximum bounds
172
- */
173
- protected async preCheckAmounts(
174
- request: RequestData<FromBtcLnRequestType | FromBtcRequestType | FromBtcLnTrustedRequestType>,
175
- requestedAmount: {input: boolean, amount: bigint},
176
- useToken: string
177
- ): Promise<{
178
- baseFee: bigint,
179
- feePPM: bigint,
180
- securityDepositApyPPM?: bigint,
181
- securityDepositBaseMultiplierPPM?: bigint,
182
- }> {
183
- const res = await PluginManager.onHandlePreFromBtcQuote(
184
- request,
185
- requestedAmount,
186
- request.chainIdentifier,
187
- useToken,
188
- {minInBtc: this.config.min, maxInBtc: this.config.max},
189
- {baseFeeInBtc: this.config.baseFee, feePPM: this.config.feePPM},
190
- );
191
- if(res!=null) {
192
- this.handlePluginErrorResponses(res);
193
- if(isQuoteSetFees(res)) {
194
- return {
195
- baseFee: res.baseFee || this.config.baseFee,
196
- feePPM: res.feePPM || this.config.feePPM,
197
- securityDepositApyPPM: res.securityDepositApyPPM,
198
- securityDepositBaseMultiplierPPM: res.securityDepositBaseMultiplierPPM
199
- }
200
- }
201
- }
202
- if(requestedAmount.input) this.checkBtcAmountInBounds(requestedAmount.amount);
203
- return {
204
- baseFee: this.config.baseFee,
205
- feePPM: this.config.feePPM
206
- };
207
- }
208
-
209
- /**
210
- * Checks minimums/maximums, calculates the fee & total amount
211
- *
212
- * @param request
213
- * @param requestedAmount
214
- * @param fees
215
- * @param useToken
216
- * @param signal
217
- * @param pricePrefetchPromise
218
- * @throws {DefinedRuntimeError} will throw an error if the amount is outside minimum/maximum bounds
219
- */
220
- protected async checkFromBtcAmount(
221
- request: RequestData<FromBtcLnRequestType | FromBtcRequestType | FromBtcLnTrustedRequestType>,
222
- requestedAmount: {input: boolean, amount: bigint},
223
- fees: {baseFee: bigint, feePPM: bigint},
224
- useToken: string,
225
- signal: AbortSignal,
226
- pricePrefetchPromise: Promise<bigint> = Promise.resolve(null)
227
- ): Promise<{
228
- amountBD: bigint,
229
- swapFee: bigint, //Swap fee in BTC
230
- swapFeeInToken: bigint, //Swap fee in token on top of what should be paid out to the user
231
- totalInToken: bigint, //Total to be paid out to the user
232
- securityDepositApyPPM?: bigint,
233
- securityDepositBaseMultiplierPPM?: bigint
234
- }> {
235
- const chainIdentifier = request.chainIdentifier;
236
-
237
- let securityDepositApyPPM: bigint;
238
- let securityDepositBaseMultiplierPPM: bigint;
239
-
240
- const res = await PluginManager.onHandlePostFromBtcQuote(
241
- request,
242
- requestedAmount,
243
- chainIdentifier,
244
- useToken,
245
- {minInBtc: this.config.min, maxInBtc: this.config.max},
246
- {baseFeeInBtc: fees.baseFee, feePPM: fees.feePPM},
247
- pricePrefetchPromise
248
- );
249
- signal.throwIfAborted();
250
- if(res!=null) {
251
- this.handlePluginErrorResponses(res);
252
- if(isQuoteSetFees(res)) {
253
- if(res.baseFee!=null) fees.baseFee = res.baseFee;
254
- if(res.feePPM!=null) fees.feePPM = res.feePPM;
255
- if(res.securityDepositApyPPM!=null) securityDepositApyPPM = res.securityDepositApyPPM;
256
- if(res.securityDepositBaseMultiplierPPM!=null) securityDepositBaseMultiplierPPM = res.securityDepositBaseMultiplierPPM;
257
- }
258
- if(isPluginQuote(res)) {
259
- if(!requestedAmount.input) {
260
- return {
261
- amountBD: res.amount.amount + res.swapFee.inInputTokens,
262
- swapFee: res.swapFee.inInputTokens,
263
- swapFeeInToken: res.swapFee.inOutputTokens,
264
- totalInToken: requestedAmount.amount
265
- }
266
- } else {
267
- return {
268
- amountBD: requestedAmount.amount,
269
- swapFee: res.swapFee.inInputTokens,
270
- swapFeeInToken: res.swapFee.inOutputTokens,
271
- totalInToken: res.amount.amount
272
- }
273
- }
274
- }
275
- }
276
-
277
- let amountBD: bigint;
278
- if(!requestedAmount.input) {
279
- amountBD = await this.swapPricing.getToBtcSwapAmount(requestedAmount.amount, useToken, chainIdentifier, true, pricePrefetchPromise);
280
- signal.throwIfAborted();
281
-
282
- // amt = (amt+base_fee)/(1-fee)
283
- amountBD = (amountBD + fees.baseFee) * 1000000n / (1000000n - fees.feePPM);
284
-
285
- const tooLow = amountBD < (this.config.min * 95n / 100n);
286
- const tooHigh = amountBD > (this.config.max * 105n / 100n);
287
- if(tooLow || tooHigh) {
288
- const adjustedMin = this.config.min * (1000000n - fees.feePPM) / (1000000n - fees.baseFee);
289
- const adjustedMax = this.config.max * (1000000n - fees.feePPM) / (1000000n - fees.baseFee);
290
- const minIn = await this.swapPricing.getFromBtcSwapAmount(
291
- adjustedMin, useToken, chainIdentifier, null, pricePrefetchPromise
292
- );
293
- const maxIn = await this.swapPricing.getFromBtcSwapAmount(
294
- adjustedMax, useToken, chainIdentifier, null, pricePrefetchPromise
295
- );
296
- throw {
297
- code: tooLow ? 20003 : 20004,
298
- msg: tooLow ? "Amount too low!" : "Amount too high!",
299
- data: {
300
- min: minIn.toString(10),
301
- max: maxIn.toString(10)
302
- }
303
- };
304
- }
305
- } else {
306
- amountBD = requestedAmount.amount;
307
- this.checkBtcAmountInBounds(amountBD);
308
- }
309
-
310
- const swapFee = fees.baseFee + (amountBD * fees.feePPM / 1000000n);
311
- const swapFeeInToken = await this.swapPricing.getFromBtcSwapAmount(swapFee, useToken, chainIdentifier, true, pricePrefetchPromise);
312
- signal.throwIfAborted();
313
-
314
- let totalInToken: bigint;
315
- if(!requestedAmount.input) {
316
- totalInToken = requestedAmount.amount;
317
- } else {
318
- const amountInToken = await this.swapPricing.getFromBtcSwapAmount(requestedAmount.amount, useToken, chainIdentifier, null, pricePrefetchPromise);
319
- totalInToken = amountInToken - swapFeeInToken;
320
- signal.throwIfAborted();
321
- }
322
-
323
- return {
324
- amountBD,
325
- swapFee,
326
- swapFeeInToken,
327
- totalInToken,
328
- securityDepositApyPPM,
329
- securityDepositBaseMultiplierPPM
330
- }
331
- }
332
-
333
173
  /**
334
174
  * Signs the created swap
335
175
  *
@@ -1,9 +1,8 @@
1
- import {SwapHandlerSwap} from "./SwapHandlerSwap";
2
1
  import {SwapData} from "@atomiqlabs/base";
3
- import {deserializeBN, serializeBN} from "../utils/Utils";
2
+ import {deserializeBN, serializeBN} from "../../utils/Utils";
3
+ import {EscrowHandlerSwap} from "./EscrowHandlerSwap";
4
4
 
5
-
6
- export abstract class ToBtcBaseSwap<T extends SwapData = SwapData, S = any> extends SwapHandlerSwap<T, S> {
5
+ export abstract class ToBtcBaseSwap<T extends SwapData = SwapData, S = any> extends EscrowHandlerSwap<T, S> {
7
6
 
8
7
  amount: bigint;
9
8
 
@@ -53,7 +52,7 @@ export abstract class ToBtcBaseSwap<T extends SwapData = SwapData, S = any> exte
53
52
  }
54
53
 
55
54
  getInputAmount(): bigint {
56
- return this.data.getAmount() - this.getSwapFee().inInputToken - this.getQuotedNetworkFee().inInputToken;
55
+ return this.getTotalInputAmount() - this.getSwapFee().inInputToken - this.getQuotedNetworkFee().inInputToken;
57
56
  }
58
57
 
59
58
  getTotalInputAmount(): bigint {
@@ -0,0 +1,130 @@
1
+ import {MultichainData, SwapBaseConfig} from "../SwapHandler";
2
+ import {SwapData} from "@atomiqlabs/base";
3
+ import {ServerParamEncoder} from "../../utils/paramcoders/server/ServerParamEncoder";
4
+ import {IParamReader} from "../../utils/paramcoders/IParamReader";
5
+ import {FieldTypeEnum} from "../../utils/paramcoders/SchemaVerifier";
6
+ import {Request} from "express";
7
+ import {ToBtcBaseSwap} from "./ToBtcBaseSwap";
8
+ import {EscrowHandler} from "./EscrowHandler";
9
+ import {ToBtcAmountAssertions} from "../assertions/ToBtcAmountAssertions";
10
+ import {IIntermediaryStorage} from "../../storage/IIntermediaryStorage";
11
+ import {ISwapPrice} from "../../prices/ISwapPrice";
12
+
13
+ export type ToBtcBaseConfig = SwapBaseConfig & {
14
+ gracePeriod: bigint,
15
+ refundAuthorizationTimeout: number
16
+ };
17
+
18
+ export abstract class ToBtcBaseSwapHandler<V extends ToBtcBaseSwap<SwapData, S>, S> extends EscrowHandler<V, S> {
19
+
20
+ readonly AmountAssertions: ToBtcAmountAssertions;
21
+
22
+ readonly pdaExistsForToken: {
23
+ [chainIdentifier: string]: {
24
+ [token: string]: boolean
25
+ }
26
+ } = {};
27
+
28
+ constructor(
29
+ storageDirectory: IIntermediaryStorage<V>,
30
+ path: string,
31
+ chainsData: MultichainData,
32
+ swapPricing: ISwapPrice,
33
+ config: ToBtcBaseConfig
34
+ ) {
35
+ super(storageDirectory, path, chainsData, swapPricing);
36
+ this.AmountAssertions = new ToBtcAmountAssertions(config, swapPricing);
37
+ }
38
+
39
+ protected async checkVaultInitialized(chainIdentifier: string, token: string): Promise<void> {
40
+ if(!this.pdaExistsForToken[chainIdentifier] || !this.pdaExistsForToken[chainIdentifier][token]) {
41
+ this.logger.debug("checkVaultInitialized(): checking vault exists for chain: "+chainIdentifier+" token: "+token);
42
+ const {swapContract, signer} = this.getChain(chainIdentifier);
43
+ const reputation = await swapContract.getIntermediaryReputation(signer.getAddress(), token);
44
+ this.logger.debug("checkVaultInitialized(): vault state, chain: "+chainIdentifier+" token: "+token+" exists: "+(reputation!=null));
45
+ if(reputation!=null) {
46
+ if(this.pdaExistsForToken[chainIdentifier]==null) this.pdaExistsForToken[chainIdentifier] = {};
47
+ this.pdaExistsForToken[chainIdentifier][token] = true;
48
+ } else {
49
+ throw {
50
+ code: 20201,
51
+ msg: "Token not supported!"
52
+ };
53
+ }
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Starts pre-fetches for swap pricing & signature data
59
+ *
60
+ * @param chainIdentifier
61
+ * @param token
62
+ * @param responseStream
63
+ * @param abortController
64
+ */
65
+ protected getToBtcPrefetches(chainIdentifier: string, token: string, responseStream: ServerParamEncoder, abortController: AbortController): {
66
+ pricePrefetchPromise?: Promise<bigint>,
67
+ signDataPrefetchPromise?: Promise<any>
68
+ } {
69
+ //Fetch pricing & signature data in parallel
70
+ const pricePrefetchPromise: Promise<bigint> = this.swapPricing.preFetchPrice(token, chainIdentifier).catch(e => {
71
+ this.logger.error("getToBtcPrefetches(): pricePrefetch error", e);
72
+ abortController.abort(e);
73
+ return null;
74
+ });
75
+
76
+ return {
77
+ pricePrefetchPromise,
78
+ signDataPrefetchPromise: this.getSignDataPrefetch(chainIdentifier, abortController, responseStream)
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Signs the created swap
84
+ *
85
+ * @param chainIdentifier
86
+ * @param swapObject
87
+ * @param req
88
+ * @param abortSignal
89
+ * @param signDataPrefetchPromise
90
+ */
91
+ protected async getToBtcSignatureData(
92
+ chainIdentifier: string,
93
+ swapObject: SwapData,
94
+ req: Request & {paramReader: IParamReader},
95
+ abortSignal: AbortSignal,
96
+ signDataPrefetchPromise?: Promise<any>
97
+ ): Promise<{
98
+ prefix: string,
99
+ timeout: string,
100
+ signature: string,
101
+ feeRate: string
102
+ }> {
103
+ const prefetchedSignData = signDataPrefetchPromise!=null ? await signDataPrefetchPromise : null;
104
+ if(prefetchedSignData!=null) this.logger.debug("getToBtcSignatureData(): pre-fetched signature data: ", prefetchedSignData);
105
+ abortSignal.throwIfAborted();
106
+
107
+ const feeRateObj = await req.paramReader.getParams({
108
+ feeRate: FieldTypeEnum.String
109
+ }).catch(() => null);
110
+ abortSignal.throwIfAborted();
111
+
112
+ const feeRate = feeRateObj?.feeRate!=null && typeof(feeRateObj.feeRate)==="string" ? feeRateObj.feeRate : null;
113
+ this.logger.debug("getToBtcSignatureData(): using fee rate from client: ", feeRate);
114
+ const {swapContract, signer} = this.getChain(chainIdentifier);
115
+ const sigData = await swapContract.getInitSignature(
116
+ signer,
117
+ swapObject,
118
+ this.getInitAuthorizationTimeout(chainIdentifier),
119
+ prefetchedSignData,
120
+ feeRate
121
+ );
122
+ abortSignal.throwIfAborted();
123
+
124
+ return {
125
+ ...sigData,
126
+ feeRate
127
+ };
128
+ }
129
+
130
+ }
@@ -1,7 +1,7 @@
1
1
  import {Express, Request, Response} from "express";
2
2
  import {FromBtcSwapAbs, FromBtcSwapState} from "./FromBtcSwapAbs";
3
- import {MultichainData, SwapHandlerType} from "../SwapHandler";
4
- import {ISwapPrice} from "../ISwapPrice";
3
+ import {MultichainData, SwapHandlerType} from "../../SwapHandler";
4
+ import {ISwapPrice} from "../../../prices/ISwapPrice";
5
5
  import {
6
6
  BigIntBufferUtils,
7
7
  ChainSwapType,
@@ -11,15 +11,15 @@ import {
11
11
  SwapData
12
12
  } from "@atomiqlabs/base";
13
13
  import {randomBytes} from "crypto";
14
- import {expressHandlerWrapper} from "../../utils/Utils";
15
- import {PluginManager} from "../../plugins/PluginManager";
16
- import {IIntermediaryStorage} from "../../storage/IIntermediaryStorage";
17
- import {FieldTypeEnum} from "../../utils/paramcoders/SchemaVerifier";
18
- import {serverParamDecoder} from "../../utils/paramcoders/server/ServerParamDecoder";
19
- import {IParamReader} from "../../utils/paramcoders/IParamReader";
20
- import {ServerParamEncoder} from "../../utils/paramcoders/server/ServerParamEncoder";
14
+ import {expressHandlerWrapper, getAbortController} from "../../../utils/Utils";
15
+ import {PluginManager} from "../../../plugins/PluginManager";
16
+ import {IIntermediaryStorage} from "../../../storage/IIntermediaryStorage";
17
+ import {FieldTypeEnum} from "../../../utils/paramcoders/SchemaVerifier";
18
+ import {serverParamDecoder} from "../../../utils/paramcoders/server/ServerParamDecoder";
19
+ import {IParamReader} from "../../../utils/paramcoders/IParamReader";
20
+ import {ServerParamEncoder} from "../../../utils/paramcoders/server/ServerParamEncoder";
21
21
  import {FromBtcBaseConfig, FromBtcBaseSwapHandler} from "../FromBtcBaseSwapHandler";
22
- import {IBitcoinWallet} from "../../wallets/IBitcoinWallet";
22
+ import {IBitcoinWallet} from "../../../wallets/IBitcoinWallet";
23
23
 
24
24
  export type FromBtcConfig = FromBtcBaseConfig & {
25
25
  confirmations: number,
@@ -53,7 +53,7 @@ export class FromBtcAbs extends FromBtcBaseSwapHandler<FromBtcSwapAbs, FromBtcSw
53
53
  swapPricing: ISwapPrice,
54
54
  config: FromBtcConfig
55
55
  ) {
56
- super(storageDirectory, path, chains, swapPricing);
56
+ super(storageDirectory, path, chains, swapPricing, config);
57
57
  this.bitcoin = bitcoin;
58
58
  this.config = {
59
59
  ...config,
@@ -97,8 +97,8 @@ export class FromBtcAbs extends FromBtcBaseSwapHandler<FromBtcSwapAbs, FromBtcSw
97
97
  }
98
98
 
99
99
  this.swapLogger.info(swap, "processPastSwap(state=CREATED): removing past swap due to authorization expiry, address: "+swap.address);
100
- await this.bitcoin.addUnusedAddress(swap.address);
101
100
  await this.removeSwapData(swap, FromBtcSwapState.CANCELED);
101
+ await this.bitcoin.addUnusedAddress(swap.address);
102
102
  return false;
103
103
  }
104
104
 
@@ -182,8 +182,8 @@ export class FromBtcAbs extends FromBtcBaseSwapHandler<FromBtcSwapAbs, FromBtcSw
182
182
  savedSwap.txIds.refund = (event as any).meta?.txId;
183
183
 
184
184
  this.swapLogger.info(event, "SC: RefundEvent: swap refunded, address: "+savedSwap.address);
185
- await this.bitcoin.addUnusedAddress(savedSwap.address);
186
185
  await this.removeSwapData(savedSwap, FromBtcSwapState.REFUNDED);
186
+ await this.bitcoin.addUnusedAddress(savedSwap.address);
187
187
  }
188
188
 
189
189
  /**
@@ -255,8 +255,8 @@ export class FromBtcAbs extends FromBtcBaseSwapHandler<FromBtcSwapAbs, FromBtcSw
255
255
  } = {request: {}, times: {}};
256
256
 
257
257
  const chainIdentifier = req.query.chain as string ?? this.chains.default;
258
- const {swapContract, signer} = this.getChain(chainIdentifier);
259
- const depositToken = req.query.depositToken as string ?? swapContract.getNativeCurrencyAddress();
258
+ const {swapContract, signer, chainInterface} = this.getChain(chainIdentifier);
259
+ const depositToken = req.query.depositToken as string ?? chainInterface.getNativeCurrencyAddress();
260
260
  this.checkAllowedDepositToken(chainIdentifier, depositToken);
261
261
 
262
262
  metadata.times.requestReceived = Date.now();
@@ -279,7 +279,7 @@ export class FromBtcAbs extends FromBtcBaseSwapHandler<FromBtcSwapAbs, FromBtcSw
279
279
  const parsedBody: FromBtcRequestType = await req.paramReader.getParams({
280
280
  address: (val: string) => val!=null &&
281
281
  typeof(val)==="string" &&
282
- swapContract.isValidAddress(val) ? val : null,
282
+ chainInterface.isValidAddress(val) ? val : null,
283
283
  amount: FieldTypeEnum.BigInt,
284
284
  token: (val: string) => val!=null &&
285
285
  typeof(val)==="string" &&
@@ -293,7 +293,7 @@ export class FromBtcAbs extends FromBtcBaseSwapHandler<FromBtcSwapAbs, FromBtcSw
293
293
  };
294
294
  metadata.request = parsedBody;
295
295
 
296
- const requestedAmount = {input: !parsedBody.exactOut, amount: parsedBody.amount};
296
+ const requestedAmount = {input: !parsedBody.exactOut, amount: parsedBody.amount, token: parsedBody.token};
297
297
  const request = {
298
298
  chainIdentifier,
299
299
  raw: req,
@@ -304,12 +304,12 @@ export class FromBtcAbs extends FromBtcBaseSwapHandler<FromBtcSwapAbs, FromBtcSw
304
304
 
305
305
  //Check request params
306
306
  this.checkSequence(parsedBody.sequence);
307
- const fees = await this.preCheckAmounts(request, requestedAmount, useToken);
307
+ const fees = await this.AmountAssertions.preCheckFromBtcAmounts(this.type, request, requestedAmount);
308
308
  metadata.times.requestChecked = Date.now();
309
309
 
310
310
  //Create abortController for parallel prefetches
311
311
  const responseStream = res.responseStream;
312
- const abortController = this.getAbortController(responseStream);
312
+ const abortController = getAbortController(responseStream);
313
313
 
314
314
  //Pre-fetch data
315
315
  const {
@@ -336,7 +336,7 @@ export class FromBtcAbs extends FromBtcBaseSwapHandler<FromBtcSwapAbs, FromBtcSw
336
336
  totalInToken,
337
337
  securityDepositApyPPM,
338
338
  securityDepositBaseMultiplierPPM
339
- } = await this.checkFromBtcAmount(request, requestedAmount, fees, useToken, abortController.signal, pricePrefetchPromise);
339
+ } = await this.AmountAssertions.checkFromBtcAmount(this.type, request, {...requestedAmount, pricePrefetch: pricePrefetchPromise}, fees, abortController.signal);
340
340
  metadata.times.priceCalculated = Date.now();
341
341
 
342
342
  if(securityDepositApyPPM!=null) fees.securityDepositApyPPM = securityDepositApyPPM;
@@ -1,5 +1,5 @@
1
1
  import {SwapData} from "@atomiqlabs/base";
2
- import {SwapHandlerType} from "../SwapHandler";
2
+ import {SwapHandlerType} from "../../SwapHandler";
3
3
  import {FromBtcBaseSwap} from "../FromBtcBaseSwap";
4
4
 
5
5
  export enum FromBtcSwapState {