@atomiqlabs/lp-lib 16.2.0 → 17.0.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.
- package/LICENSE +201 -201
- package/dist/fees/IBtcFeeEstimator.d.ts +3 -3
- package/dist/fees/IBtcFeeEstimator.js +2 -2
- package/dist/index.d.ts +42 -42
- package/dist/index.js +58 -58
- package/dist/info/InfoHandler.d.ts +17 -17
- package/dist/info/InfoHandler.js +60 -60
- package/dist/plugins/IPlugin.d.ts +144 -144
- package/dist/plugins/IPlugin.js +34 -34
- package/dist/plugins/PluginManager.d.ts +113 -113
- package/dist/plugins/PluginManager.js +274 -274
- package/dist/prices/BinanceSwapPrice.d.ts +29 -29
- package/dist/prices/BinanceSwapPrice.js +79 -79
- package/dist/prices/CoinGeckoSwapPrice.d.ts +33 -33
- package/dist/prices/CoinGeckoSwapPrice.js +51 -51
- package/dist/prices/ISwapPrice.d.ts +43 -43
- package/dist/prices/ISwapPrice.js +55 -55
- package/dist/prices/OKXSwapPrice.d.ts +29 -29
- package/dist/prices/OKXSwapPrice.js +79 -79
- package/dist/storage/IIntermediaryStorage.d.ts +18 -18
- package/dist/storage/IIntermediaryStorage.js +2 -2
- package/dist/storagemanager/IntermediaryStorageManager.d.ts +19 -19
- package/dist/storagemanager/IntermediaryStorageManager.js +111 -111
- package/dist/storagemanager/StorageManager.d.ts +13 -13
- package/dist/storagemanager/StorageManager.js +64 -64
- package/dist/swaps/SwapHandler.d.ts +171 -171
- package/dist/swaps/SwapHandler.js +217 -217
- package/dist/swaps/SwapHandlerSwap.d.ts +79 -79
- package/dist/swaps/SwapHandlerSwap.js +78 -78
- package/dist/swaps/assertions/AmountAssertions.d.ts +28 -28
- package/dist/swaps/assertions/AmountAssertions.js +74 -74
- package/dist/swaps/assertions/FromBtcAmountAssertions.d.ts +76 -76
- package/dist/swaps/assertions/FromBtcAmountAssertions.js +185 -185
- package/dist/swaps/assertions/LightningAssertions.d.ts +44 -44
- package/dist/swaps/assertions/LightningAssertions.js +86 -86
- package/dist/swaps/assertions/ToBtcAmountAssertions.d.ts +53 -53
- package/dist/swaps/assertions/ToBtcAmountAssertions.js +150 -150
- package/dist/swaps/escrow/EscrowHandler.d.ts +50 -50
- package/dist/swaps/escrow/EscrowHandler.js +151 -151
- package/dist/swaps/escrow/EscrowHandlerSwap.d.ts +35 -35
- package/dist/swaps/escrow/EscrowHandlerSwap.js +69 -69
- package/dist/swaps/escrow/FromBtcBaseSwap.d.ts +14 -14
- package/dist/swaps/escrow/FromBtcBaseSwap.js +32 -32
- package/dist/swaps/escrow/FromBtcBaseSwapHandler.d.ts +102 -102
- package/dist/swaps/escrow/FromBtcBaseSwapHandler.js +210 -210
- package/dist/swaps/escrow/ToBtcBaseSwap.d.ts +36 -36
- package/dist/swaps/escrow/ToBtcBaseSwap.js +67 -67
- package/dist/swaps/escrow/ToBtcBaseSwapHandler.d.ts +53 -53
- package/dist/swaps/escrow/ToBtcBaseSwapHandler.js +81 -81
- package/dist/swaps/escrow/frombtc_abstract/FromBtcAbs.d.ts +84 -84
- package/dist/swaps/escrow/frombtc_abstract/FromBtcAbs.js +322 -322
- package/dist/swaps/escrow/frombtc_abstract/FromBtcSwapAbs.d.ts +21 -21
- package/dist/swaps/escrow/frombtc_abstract/FromBtcSwapAbs.js +50 -50
- package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnAbs.d.ts +108 -108
- package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnAbs.js +695 -695
- package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnSwapAbs.d.ts +33 -33
- package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnSwapAbs.js +91 -91
- package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAuto.d.ts +112 -112
- package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAuto.js +708 -708
- package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAutoSwap.d.ts +55 -55
- package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAutoSwap.js +120 -120
- package/dist/swaps/escrow/tobtc_abstract/ToBtcAbs.d.ts +170 -170
- package/dist/swaps/escrow/tobtc_abstract/ToBtcAbs.js +746 -745
- package/dist/swaps/escrow/tobtc_abstract/ToBtcSwapAbs.d.ts +28 -28
- package/dist/swaps/escrow/tobtc_abstract/ToBtcSwapAbs.js +64 -64
- package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnAbs.d.ts +178 -178
- package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnAbs.js +900 -899
- package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnSwapAbs.d.ts +24 -24
- package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnSwapAbs.js +58 -58
- package/dist/swaps/spv_vault_swap/SpvVault.d.ts +44 -44
- package/dist/swaps/spv_vault_swap/SpvVault.js +145 -145
- package/dist/swaps/spv_vault_swap/SpvVaultSwap.d.ts +68 -68
- package/dist/swaps/spv_vault_swap/SpvVaultSwap.js +158 -158
- package/dist/swaps/spv_vault_swap/SpvVaultSwapHandler.d.ts +68 -68
- package/dist/swaps/spv_vault_swap/SpvVaultSwapHandler.js +561 -561
- package/dist/swaps/spv_vault_swap/SpvVaults.d.ts +63 -63
- package/dist/swaps/spv_vault_swap/SpvVaults.js +491 -491
- package/dist/swaps/trusted/frombtc_trusted/FromBtcTrusted.d.ts +52 -52
- package/dist/swaps/trusted/frombtc_trusted/FromBtcTrusted.js +662 -662
- package/dist/swaps/trusted/frombtc_trusted/FromBtcTrustedSwap.d.ts +52 -52
- package/dist/swaps/trusted/frombtc_trusted/FromBtcTrustedSwap.js +118 -118
- package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrusted.d.ts +77 -77
- package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrusted.js +504 -504
- package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrustedSwap.d.ts +34 -34
- package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrustedSwap.js +81 -81
- package/dist/utils/BitcoinUtils.d.ts +4 -4
- package/dist/utils/BitcoinUtils.js +61 -61
- package/dist/utils/Utils.d.ts +32 -32
- package/dist/utils/Utils.js +129 -129
- package/dist/utils/paramcoders/IParamReader.d.ts +5 -5
- package/dist/utils/paramcoders/IParamReader.js +2 -2
- package/dist/utils/paramcoders/IParamWriter.d.ts +4 -4
- package/dist/utils/paramcoders/IParamWriter.js +2 -2
- package/dist/utils/paramcoders/LegacyParamEncoder.d.ts +10 -10
- package/dist/utils/paramcoders/LegacyParamEncoder.js +22 -22
- package/dist/utils/paramcoders/ParamDecoder.d.ts +25 -25
- package/dist/utils/paramcoders/ParamDecoder.js +222 -222
- package/dist/utils/paramcoders/ParamEncoder.d.ts +9 -9
- package/dist/utils/paramcoders/ParamEncoder.js +22 -22
- package/dist/utils/paramcoders/SchemaVerifier.d.ts +21 -21
- package/dist/utils/paramcoders/SchemaVerifier.js +84 -84
- package/dist/utils/paramcoders/server/ServerParamDecoder.d.ts +8 -8
- package/dist/utils/paramcoders/server/ServerParamDecoder.js +107 -107
- package/dist/utils/paramcoders/server/ServerParamEncoder.d.ts +11 -11
- package/dist/utils/paramcoders/server/ServerParamEncoder.js +65 -65
- package/dist/wallets/IBitcoinWallet.d.ts +149 -149
- package/dist/wallets/IBitcoinWallet.js +97 -97
- package/dist/wallets/ILightningWallet.d.ts +136 -136
- package/dist/wallets/ILightningWallet.js +37 -37
- package/dist/wallets/ISpvVaultSigner.d.ts +7 -7
- package/dist/wallets/ISpvVaultSigner.js +2 -2
- package/package.json +36 -36
- package/src/fees/IBtcFeeEstimator.ts +6 -6
- package/src/index.ts +53 -53
- package/src/info/InfoHandler.ts +103 -103
- package/src/plugins/IPlugin.ts +174 -174
- package/src/plugins/PluginManager.ts +354 -354
- package/src/prices/BinanceSwapPrice.ts +101 -101
- package/src/prices/CoinGeckoSwapPrice.ts +75 -75
- package/src/prices/ISwapPrice.ts +88 -88
- package/src/prices/OKXSwapPrice.ts +101 -101
- package/src/storage/IIntermediaryStorage.ts +19 -19
- package/src/storagemanager/IntermediaryStorageManager.ts +118 -118
- package/src/storagemanager/StorageManager.ts +78 -78
- package/src/swaps/SwapHandler.ts +323 -323
- package/src/swaps/SwapHandlerSwap.ts +141 -141
- package/src/swaps/assertions/AmountAssertions.ts +77 -77
- package/src/swaps/assertions/FromBtcAmountAssertions.ts +251 -251
- package/src/swaps/assertions/LightningAssertions.ts +103 -103
- package/src/swaps/assertions/ToBtcAmountAssertions.ts +203 -203
- package/src/swaps/escrow/EscrowHandler.ts +172 -172
- package/src/swaps/escrow/EscrowHandlerSwap.ts +86 -86
- package/src/swaps/escrow/FromBtcBaseSwap.ts +38 -38
- package/src/swaps/escrow/FromBtcBaseSwapHandler.ts +286 -286
- package/src/swaps/escrow/ToBtcBaseSwap.ts +85 -85
- package/src/swaps/escrow/ToBtcBaseSwapHandler.ts +129 -129
- package/src/swaps/escrow/frombtc_abstract/FromBtcAbs.ts +457 -457
- package/src/swaps/escrow/frombtc_abstract/FromBtcSwapAbs.ts +61 -61
- package/src/swaps/escrow/frombtcln_abstract/FromBtcLnAbs.ts +873 -873
- package/src/swaps/escrow/frombtcln_abstract/FromBtcLnSwapAbs.ts +141 -141
- package/src/swaps/escrow/frombtcln_autoinit/FromBtcLnAuto.ts +866 -866
- package/src/swaps/escrow/frombtcln_autoinit/FromBtcLnAutoSwap.ts +196 -196
- package/src/swaps/escrow/tobtc_abstract/ToBtcAbs.ts +921 -920
- package/src/swaps/escrow/tobtc_abstract/ToBtcSwapAbs.ts +108 -108
- package/src/swaps/escrow/tobtcln_abstract/ToBtcLnAbs.ts +1150 -1149
- package/src/swaps/escrow/tobtcln_abstract/ToBtcLnSwapAbs.ts +80 -80
- package/src/swaps/spv_vault_swap/SpvVault.ts +178 -178
- package/src/swaps/spv_vault_swap/SpvVaultSwap.ts +228 -228
- package/src/swaps/spv_vault_swap/SpvVaultSwapHandler.ts +718 -718
- package/src/swaps/spv_vault_swap/SpvVaults.ts +567 -567
- package/src/swaps/trusted/frombtc_trusted/FromBtcTrusted.ts +762 -762
- package/src/swaps/trusted/frombtc_trusted/FromBtcTrustedSwap.ts +185 -185
- package/src/swaps/trusted/frombtcln_trusted/FromBtcLnTrusted.ts +603 -603
- package/src/swaps/trusted/frombtcln_trusted/FromBtcLnTrustedSwap.ts +121 -121
- package/src/utils/BitcoinUtils.ts +59 -59
- package/src/utils/Utils.ts +150 -150
- package/src/utils/paramcoders/IParamReader.ts +7 -7
- package/src/utils/paramcoders/IParamWriter.ts +8 -8
- package/src/utils/paramcoders/LegacyParamEncoder.ts +27 -27
- package/src/utils/paramcoders/ParamDecoder.ts +218 -218
- package/src/utils/paramcoders/ParamEncoder.ts +29 -29
- package/src/utils/paramcoders/SchemaVerifier.ts +96 -96
- package/src/utils/paramcoders/server/ServerParamDecoder.ts +118 -118
- package/src/utils/paramcoders/server/ServerParamEncoder.ts +75 -75
- package/src/wallets/IBitcoinWallet.ts +237 -237
- package/src/wallets/ILightningWallet.ts +200 -200
- package/src/wallets/ISpvVaultSigner.ts +10 -10
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
import { AmountAssertions } from "./AmountAssertions";
|
|
2
|
-
import { ToBtcLnRequestType } from "../escrow/tobtcln_abstract/ToBtcLnAbs";
|
|
3
|
-
import { ToBtcRequestType } from "../escrow/tobtc_abstract/ToBtcAbs";
|
|
4
|
-
import { RequestData, SwapHandlerType } from "../SwapHandler";
|
|
5
|
-
export declare class ToBtcAmountAssertions extends AmountAssertions {
|
|
6
|
-
/**
|
|
7
|
-
* Checks minimums/maximums, calculates the fee & total amount
|
|
8
|
-
*
|
|
9
|
-
* @param swapType
|
|
10
|
-
* @param request
|
|
11
|
-
* @param requestedAmount
|
|
12
|
-
* @throws {DefinedRuntimeError} will throw an error if the amount is outside minimum/maximum bounds
|
|
13
|
-
*/
|
|
14
|
-
preCheckToBtcAmounts(swapType: SwapHandlerType.TO_BTCLN | SwapHandlerType.TO_BTC, request: RequestData<ToBtcLnRequestType | ToBtcRequestType>, requestedAmount: {
|
|
15
|
-
input: boolean;
|
|
16
|
-
amount: bigint;
|
|
17
|
-
token: string;
|
|
18
|
-
}): Promise<{
|
|
19
|
-
baseFee: bigint;
|
|
20
|
-
feePPM: bigint;
|
|
21
|
-
}>;
|
|
22
|
-
/**
|
|
23
|
-
* Checks minimums/maximums, calculates network fee (based on the callback passed), swap fee & total amount
|
|
24
|
-
*
|
|
25
|
-
* @param swapType
|
|
26
|
-
* @param request
|
|
27
|
-
* @param requestedAmount
|
|
28
|
-
* @param fees
|
|
29
|
-
* @param getNetworkFee
|
|
30
|
-
* @param signal
|
|
31
|
-
* @throws {DefinedRuntimeError} will throw an error if the amount is outside minimum/maximum bounds,
|
|
32
|
-
* or if we don't have enough funds (getNetworkFee callback throws)
|
|
33
|
-
*/
|
|
34
|
-
checkToBtcAmount<T extends {
|
|
35
|
-
networkFee: bigint;
|
|
36
|
-
}>(swapType: SwapHandlerType.TO_BTCLN | SwapHandlerType.TO_BTC, request: RequestData<ToBtcLnRequestType | ToBtcRequestType>, requestedAmount: {
|
|
37
|
-
input: boolean;
|
|
38
|
-
amount: bigint;
|
|
39
|
-
token: string;
|
|
40
|
-
pricePrefetch?: Promise<bigint>;
|
|
41
|
-
}, fees: {
|
|
42
|
-
baseFee: bigint;
|
|
43
|
-
feePPM: bigint;
|
|
44
|
-
}, getNetworkFee: (amount: bigint) => Promise<T>, signal: AbortSignal): Promise<{
|
|
45
|
-
amountBD: bigint;
|
|
46
|
-
networkFeeData: T;
|
|
47
|
-
swapFee: bigint;
|
|
48
|
-
swapFeeInToken: bigint;
|
|
49
|
-
networkFee: bigint;
|
|
50
|
-
networkFeeInToken: bigint;
|
|
51
|
-
totalInToken: bigint;
|
|
52
|
-
}>;
|
|
53
|
-
}
|
|
1
|
+
import { AmountAssertions } from "./AmountAssertions";
|
|
2
|
+
import { ToBtcLnRequestType } from "../escrow/tobtcln_abstract/ToBtcLnAbs";
|
|
3
|
+
import { ToBtcRequestType } from "../escrow/tobtc_abstract/ToBtcAbs";
|
|
4
|
+
import { RequestData, SwapHandlerType } from "../SwapHandler";
|
|
5
|
+
export declare class ToBtcAmountAssertions extends AmountAssertions {
|
|
6
|
+
/**
|
|
7
|
+
* Checks minimums/maximums, calculates the fee & total amount
|
|
8
|
+
*
|
|
9
|
+
* @param swapType
|
|
10
|
+
* @param request
|
|
11
|
+
* @param requestedAmount
|
|
12
|
+
* @throws {DefinedRuntimeError} will throw an error if the amount is outside minimum/maximum bounds
|
|
13
|
+
*/
|
|
14
|
+
preCheckToBtcAmounts(swapType: SwapHandlerType.TO_BTCLN | SwapHandlerType.TO_BTC, request: RequestData<ToBtcLnRequestType | ToBtcRequestType>, requestedAmount: {
|
|
15
|
+
input: boolean;
|
|
16
|
+
amount: bigint;
|
|
17
|
+
token: string;
|
|
18
|
+
}): Promise<{
|
|
19
|
+
baseFee: bigint;
|
|
20
|
+
feePPM: bigint;
|
|
21
|
+
}>;
|
|
22
|
+
/**
|
|
23
|
+
* Checks minimums/maximums, calculates network fee (based on the callback passed), swap fee & total amount
|
|
24
|
+
*
|
|
25
|
+
* @param swapType
|
|
26
|
+
* @param request
|
|
27
|
+
* @param requestedAmount
|
|
28
|
+
* @param fees
|
|
29
|
+
* @param getNetworkFee
|
|
30
|
+
* @param signal
|
|
31
|
+
* @throws {DefinedRuntimeError} will throw an error if the amount is outside minimum/maximum bounds,
|
|
32
|
+
* or if we don't have enough funds (getNetworkFee callback throws)
|
|
33
|
+
*/
|
|
34
|
+
checkToBtcAmount<T extends {
|
|
35
|
+
networkFee: bigint;
|
|
36
|
+
}>(swapType: SwapHandlerType.TO_BTCLN | SwapHandlerType.TO_BTC, request: RequestData<ToBtcLnRequestType | ToBtcRequestType>, requestedAmount: {
|
|
37
|
+
input: boolean;
|
|
38
|
+
amount: bigint;
|
|
39
|
+
token: string;
|
|
40
|
+
pricePrefetch?: Promise<bigint>;
|
|
41
|
+
}, fees: {
|
|
42
|
+
baseFee: bigint;
|
|
43
|
+
feePPM: bigint;
|
|
44
|
+
}, getNetworkFee: (amount: bigint) => Promise<T>, signal: AbortSignal): Promise<{
|
|
45
|
+
amountBD: bigint;
|
|
46
|
+
networkFeeData: T;
|
|
47
|
+
swapFee: bigint;
|
|
48
|
+
swapFeeInToken: bigint;
|
|
49
|
+
networkFee: bigint;
|
|
50
|
+
networkFeeInToken: bigint;
|
|
51
|
+
totalInToken: bigint;
|
|
52
|
+
}>;
|
|
53
|
+
}
|
|
@@ -1,150 +1,150 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ToBtcAmountAssertions = void 0;
|
|
4
|
-
const AmountAssertions_1 = require("./AmountAssertions");
|
|
5
|
-
const PluginManager_1 = require("../../plugins/PluginManager");
|
|
6
|
-
const IPlugin_1 = require("../../plugins/IPlugin");
|
|
7
|
-
class ToBtcAmountAssertions extends AmountAssertions_1.AmountAssertions {
|
|
8
|
-
/**
|
|
9
|
-
* Checks minimums/maximums, calculates the fee & total amount
|
|
10
|
-
*
|
|
11
|
-
* @param swapType
|
|
12
|
-
* @param request
|
|
13
|
-
* @param requestedAmount
|
|
14
|
-
* @throws {DefinedRuntimeError} will throw an error if the amount is outside minimum/maximum bounds
|
|
15
|
-
*/
|
|
16
|
-
async preCheckToBtcAmounts(swapType, request, requestedAmount) {
|
|
17
|
-
const res = await PluginManager_1.PluginManager.onHandlePreToBtcQuote(swapType, request, requestedAmount, request.chainIdentifier, { minInBtc: this.config.min, maxInBtc: this.config.max }, { baseFeeInBtc: this.config.baseFee, feePPM: this.config.feePPM });
|
|
18
|
-
if (res != null) {
|
|
19
|
-
AmountAssertions_1.AmountAssertions.handlePluginErrorResponses(res);
|
|
20
|
-
if ((0, IPlugin_1.isQuoteSetFees)(res)) {
|
|
21
|
-
return {
|
|
22
|
-
baseFee: res.baseFee || this.config.baseFee,
|
|
23
|
-
feePPM: res.feePPM || this.config.feePPM
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
if (!requestedAmount.input) {
|
|
28
|
-
this.checkBtcAmountInBounds(requestedAmount.amount);
|
|
29
|
-
}
|
|
30
|
-
return {
|
|
31
|
-
baseFee: this.config.baseFee,
|
|
32
|
-
feePPM: this.config.feePPM
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Checks minimums/maximums, calculates network fee (based on the callback passed), swap fee & total amount
|
|
37
|
-
*
|
|
38
|
-
* @param swapType
|
|
39
|
-
* @param request
|
|
40
|
-
* @param requestedAmount
|
|
41
|
-
* @param fees
|
|
42
|
-
* @param getNetworkFee
|
|
43
|
-
* @param signal
|
|
44
|
-
* @throws {DefinedRuntimeError} will throw an error if the amount is outside minimum/maximum bounds,
|
|
45
|
-
* or if we don't have enough funds (getNetworkFee callback throws)
|
|
46
|
-
*/
|
|
47
|
-
async checkToBtcAmount(swapType, request, requestedAmount, fees, getNetworkFee, signal) {
|
|
48
|
-
const chainIdentifier = request.chainIdentifier;
|
|
49
|
-
const res = await PluginManager_1.PluginManager.onHandlePostToBtcQuote(swapType, request, requestedAmount, request.chainIdentifier, { minInBtc: this.config.min, maxInBtc: this.config.max }, { baseFeeInBtc: fees.baseFee, feePPM: fees.feePPM, networkFeeGetter: getNetworkFee });
|
|
50
|
-
signal.throwIfAborted();
|
|
51
|
-
if (res != null) {
|
|
52
|
-
AmountAssertions_1.AmountAssertions.handlePluginErrorResponses(res);
|
|
53
|
-
if ((0, IPlugin_1.isQuoteSetFees)(res)) {
|
|
54
|
-
if (res.baseFee != null)
|
|
55
|
-
fees.baseFee = res.baseFee;
|
|
56
|
-
if (res.feePPM != null)
|
|
57
|
-
fees.feePPM = res.feePPM;
|
|
58
|
-
}
|
|
59
|
-
if ((0, IPlugin_1.isToBtcPluginQuote)(res)) {
|
|
60
|
-
if (requestedAmount.input) {
|
|
61
|
-
return {
|
|
62
|
-
amountBD: res.amount.amount,
|
|
63
|
-
swapFee: res.swapFee.inOutputTokens,
|
|
64
|
-
swapFeeInToken: res.swapFee.inInputTokens,
|
|
65
|
-
networkFee: res.networkFee.inOutputTokens,
|
|
66
|
-
networkFeeInToken: res.networkFee.inInputTokens,
|
|
67
|
-
networkFeeData: res.networkFeeData,
|
|
68
|
-
totalInToken: requestedAmount.amount
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
return {
|
|
73
|
-
amountBD: requestedAmount.amount,
|
|
74
|
-
swapFee: res.swapFee.inOutputTokens,
|
|
75
|
-
swapFeeInToken: res.swapFee.inInputTokens,
|
|
76
|
-
networkFee: res.networkFee.inOutputTokens,
|
|
77
|
-
networkFeeInToken: res.networkFee.inInputTokens,
|
|
78
|
-
networkFeeData: res.networkFeeData,
|
|
79
|
-
totalInToken: res.amount.amount + res.swapFee.inInputTokens + res.networkFee.inInputTokens
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
let amountBD;
|
|
85
|
-
let tooHigh = false;
|
|
86
|
-
let tooLow = false;
|
|
87
|
-
if (requestedAmount.input) {
|
|
88
|
-
amountBD = await this.swapPricing.getToBtcSwapAmount(requestedAmount.amount, requestedAmount.token, chainIdentifier, null, requestedAmount.pricePrefetch);
|
|
89
|
-
signal.throwIfAborted();
|
|
90
|
-
//Decrease by base fee
|
|
91
|
-
amountBD = amountBD - fees.baseFee;
|
|
92
|
-
//If it's already smaller than minimum, set it to minimum so we can calculate the network fee
|
|
93
|
-
if (amountBD < (this.config.min * 95n / 100n)) {
|
|
94
|
-
amountBD = this.config.min;
|
|
95
|
-
tooLow = true;
|
|
96
|
-
}
|
|
97
|
-
//If it's already larger than maximum, set it to maximum so we can calculate the network fee
|
|
98
|
-
if (amountBD > (this.config.max * 105n / 100n)) {
|
|
99
|
-
amountBD = this.config.max;
|
|
100
|
-
tooHigh = true;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
amountBD = requestedAmount.amount;
|
|
105
|
-
this.checkBtcAmountInBounds(amountBD);
|
|
106
|
-
}
|
|
107
|
-
const resp = await getNetworkFee(amountBD);
|
|
108
|
-
signal.throwIfAborted();
|
|
109
|
-
if (requestedAmount.input) {
|
|
110
|
-
//Decrease by network fee
|
|
111
|
-
amountBD = amountBD - resp.networkFee;
|
|
112
|
-
//Decrease by percentage fee
|
|
113
|
-
amountBD = amountBD * 1000000n / (fees.feePPM + 1000000n);
|
|
114
|
-
tooHigh || (tooHigh = amountBD > (this.config.max * 105n / 100n));
|
|
115
|
-
tooLow || (tooLow = amountBD < (this.config.min * 95n / 100n));
|
|
116
|
-
if (tooLow || tooHigh) {
|
|
117
|
-
//Compute min/max
|
|
118
|
-
let adjustedMin = this.config.min * (fees.feePPM + 1000000n) / 1000000n;
|
|
119
|
-
let adjustedMax = this.config.max * (fees.feePPM + 1000000n) / 1000000n;
|
|
120
|
-
adjustedMin = adjustedMin + fees.baseFee + resp.networkFee;
|
|
121
|
-
adjustedMax = adjustedMax + fees.baseFee + resp.networkFee;
|
|
122
|
-
const minIn = await this.swapPricing.getFromBtcSwapAmount(adjustedMin, requestedAmount.token, chainIdentifier, null, requestedAmount.pricePrefetch);
|
|
123
|
-
const maxIn = await this.swapPricing.getFromBtcSwapAmount(adjustedMax, requestedAmount.token, chainIdentifier, null, requestedAmount.pricePrefetch);
|
|
124
|
-
throw {
|
|
125
|
-
code: tooLow ? 20003 : 20004,
|
|
126
|
-
msg: tooLow ? "Amount too low!" : "Amount too high!",
|
|
127
|
-
data: {
|
|
128
|
-
min: minIn.toString(10),
|
|
129
|
-
max: maxIn.toString(10)
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
const swapFee = fees.baseFee + (amountBD * fees.feePPM / 1000000n);
|
|
135
|
-
const networkFeeInToken = await this.swapPricing.getFromBtcSwapAmount(resp.networkFee, requestedAmount.token, chainIdentifier, true, requestedAmount.pricePrefetch);
|
|
136
|
-
const swapFeeInToken = await this.swapPricing.getFromBtcSwapAmount(swapFee, requestedAmount.token, chainIdentifier, true, requestedAmount.pricePrefetch);
|
|
137
|
-
signal.throwIfAborted();
|
|
138
|
-
let total;
|
|
139
|
-
if (requestedAmount.input) {
|
|
140
|
-
total = requestedAmount.amount;
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
const amountInToken = await this.swapPricing.getFromBtcSwapAmount(requestedAmount.amount, requestedAmount.token, chainIdentifier, true, requestedAmount.pricePrefetch);
|
|
144
|
-
signal.throwIfAborted();
|
|
145
|
-
total = amountInToken + swapFeeInToken + networkFeeInToken;
|
|
146
|
-
}
|
|
147
|
-
return { amountBD, networkFeeData: resp, swapFee, swapFeeInToken, networkFee: resp.networkFee, networkFeeInToken, totalInToken: total };
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
exports.ToBtcAmountAssertions = ToBtcAmountAssertions;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ToBtcAmountAssertions = void 0;
|
|
4
|
+
const AmountAssertions_1 = require("./AmountAssertions");
|
|
5
|
+
const PluginManager_1 = require("../../plugins/PluginManager");
|
|
6
|
+
const IPlugin_1 = require("../../plugins/IPlugin");
|
|
7
|
+
class ToBtcAmountAssertions extends AmountAssertions_1.AmountAssertions {
|
|
8
|
+
/**
|
|
9
|
+
* Checks minimums/maximums, calculates the fee & total amount
|
|
10
|
+
*
|
|
11
|
+
* @param swapType
|
|
12
|
+
* @param request
|
|
13
|
+
* @param requestedAmount
|
|
14
|
+
* @throws {DefinedRuntimeError} will throw an error if the amount is outside minimum/maximum bounds
|
|
15
|
+
*/
|
|
16
|
+
async preCheckToBtcAmounts(swapType, request, requestedAmount) {
|
|
17
|
+
const res = await PluginManager_1.PluginManager.onHandlePreToBtcQuote(swapType, request, requestedAmount, request.chainIdentifier, { minInBtc: this.config.min, maxInBtc: this.config.max }, { baseFeeInBtc: this.config.baseFee, feePPM: this.config.feePPM });
|
|
18
|
+
if (res != null) {
|
|
19
|
+
AmountAssertions_1.AmountAssertions.handlePluginErrorResponses(res);
|
|
20
|
+
if ((0, IPlugin_1.isQuoteSetFees)(res)) {
|
|
21
|
+
return {
|
|
22
|
+
baseFee: res.baseFee || this.config.baseFee,
|
|
23
|
+
feePPM: res.feePPM || this.config.feePPM
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (!requestedAmount.input) {
|
|
28
|
+
this.checkBtcAmountInBounds(requestedAmount.amount);
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
baseFee: this.config.baseFee,
|
|
32
|
+
feePPM: this.config.feePPM
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Checks minimums/maximums, calculates network fee (based on the callback passed), swap fee & total amount
|
|
37
|
+
*
|
|
38
|
+
* @param swapType
|
|
39
|
+
* @param request
|
|
40
|
+
* @param requestedAmount
|
|
41
|
+
* @param fees
|
|
42
|
+
* @param getNetworkFee
|
|
43
|
+
* @param signal
|
|
44
|
+
* @throws {DefinedRuntimeError} will throw an error if the amount is outside minimum/maximum bounds,
|
|
45
|
+
* or if we don't have enough funds (getNetworkFee callback throws)
|
|
46
|
+
*/
|
|
47
|
+
async checkToBtcAmount(swapType, request, requestedAmount, fees, getNetworkFee, signal) {
|
|
48
|
+
const chainIdentifier = request.chainIdentifier;
|
|
49
|
+
const res = await PluginManager_1.PluginManager.onHandlePostToBtcQuote(swapType, request, requestedAmount, request.chainIdentifier, { minInBtc: this.config.min, maxInBtc: this.config.max }, { baseFeeInBtc: fees.baseFee, feePPM: fees.feePPM, networkFeeGetter: getNetworkFee });
|
|
50
|
+
signal.throwIfAborted();
|
|
51
|
+
if (res != null) {
|
|
52
|
+
AmountAssertions_1.AmountAssertions.handlePluginErrorResponses(res);
|
|
53
|
+
if ((0, IPlugin_1.isQuoteSetFees)(res)) {
|
|
54
|
+
if (res.baseFee != null)
|
|
55
|
+
fees.baseFee = res.baseFee;
|
|
56
|
+
if (res.feePPM != null)
|
|
57
|
+
fees.feePPM = res.feePPM;
|
|
58
|
+
}
|
|
59
|
+
if ((0, IPlugin_1.isToBtcPluginQuote)(res)) {
|
|
60
|
+
if (requestedAmount.input) {
|
|
61
|
+
return {
|
|
62
|
+
amountBD: res.amount.amount,
|
|
63
|
+
swapFee: res.swapFee.inOutputTokens,
|
|
64
|
+
swapFeeInToken: res.swapFee.inInputTokens,
|
|
65
|
+
networkFee: res.networkFee.inOutputTokens,
|
|
66
|
+
networkFeeInToken: res.networkFee.inInputTokens,
|
|
67
|
+
networkFeeData: res.networkFeeData,
|
|
68
|
+
totalInToken: requestedAmount.amount
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
return {
|
|
73
|
+
amountBD: requestedAmount.amount,
|
|
74
|
+
swapFee: res.swapFee.inOutputTokens,
|
|
75
|
+
swapFeeInToken: res.swapFee.inInputTokens,
|
|
76
|
+
networkFee: res.networkFee.inOutputTokens,
|
|
77
|
+
networkFeeInToken: res.networkFee.inInputTokens,
|
|
78
|
+
networkFeeData: res.networkFeeData,
|
|
79
|
+
totalInToken: res.amount.amount + res.swapFee.inInputTokens + res.networkFee.inInputTokens
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
let amountBD;
|
|
85
|
+
let tooHigh = false;
|
|
86
|
+
let tooLow = false;
|
|
87
|
+
if (requestedAmount.input) {
|
|
88
|
+
amountBD = await this.swapPricing.getToBtcSwapAmount(requestedAmount.amount, requestedAmount.token, chainIdentifier, null, requestedAmount.pricePrefetch);
|
|
89
|
+
signal.throwIfAborted();
|
|
90
|
+
//Decrease by base fee
|
|
91
|
+
amountBD = amountBD - fees.baseFee;
|
|
92
|
+
//If it's already smaller than minimum, set it to minimum so we can calculate the network fee
|
|
93
|
+
if (amountBD < (this.config.min * 95n / 100n)) {
|
|
94
|
+
amountBD = this.config.min;
|
|
95
|
+
tooLow = true;
|
|
96
|
+
}
|
|
97
|
+
//If it's already larger than maximum, set it to maximum so we can calculate the network fee
|
|
98
|
+
if (amountBD > (this.config.max * 105n / 100n)) {
|
|
99
|
+
amountBD = this.config.max;
|
|
100
|
+
tooHigh = true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
amountBD = requestedAmount.amount;
|
|
105
|
+
this.checkBtcAmountInBounds(amountBD);
|
|
106
|
+
}
|
|
107
|
+
const resp = await getNetworkFee(amountBD);
|
|
108
|
+
signal.throwIfAborted();
|
|
109
|
+
if (requestedAmount.input) {
|
|
110
|
+
//Decrease by network fee
|
|
111
|
+
amountBD = amountBD - resp.networkFee;
|
|
112
|
+
//Decrease by percentage fee
|
|
113
|
+
amountBD = amountBD * 1000000n / (fees.feePPM + 1000000n);
|
|
114
|
+
tooHigh || (tooHigh = amountBD > (this.config.max * 105n / 100n));
|
|
115
|
+
tooLow || (tooLow = amountBD < (this.config.min * 95n / 100n));
|
|
116
|
+
if (tooLow || tooHigh) {
|
|
117
|
+
//Compute min/max
|
|
118
|
+
let adjustedMin = this.config.min * (fees.feePPM + 1000000n) / 1000000n;
|
|
119
|
+
let adjustedMax = this.config.max * (fees.feePPM + 1000000n) / 1000000n;
|
|
120
|
+
adjustedMin = adjustedMin + fees.baseFee + resp.networkFee;
|
|
121
|
+
adjustedMax = adjustedMax + fees.baseFee + resp.networkFee;
|
|
122
|
+
const minIn = await this.swapPricing.getFromBtcSwapAmount(adjustedMin, requestedAmount.token, chainIdentifier, null, requestedAmount.pricePrefetch);
|
|
123
|
+
const maxIn = await this.swapPricing.getFromBtcSwapAmount(adjustedMax, requestedAmount.token, chainIdentifier, null, requestedAmount.pricePrefetch);
|
|
124
|
+
throw {
|
|
125
|
+
code: tooLow ? 20003 : 20004,
|
|
126
|
+
msg: tooLow ? "Amount too low!" : "Amount too high!",
|
|
127
|
+
data: {
|
|
128
|
+
min: minIn.toString(10),
|
|
129
|
+
max: maxIn.toString(10)
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const swapFee = fees.baseFee + (amountBD * fees.feePPM / 1000000n);
|
|
135
|
+
const networkFeeInToken = await this.swapPricing.getFromBtcSwapAmount(resp.networkFee, requestedAmount.token, chainIdentifier, true, requestedAmount.pricePrefetch);
|
|
136
|
+
const swapFeeInToken = await this.swapPricing.getFromBtcSwapAmount(swapFee, requestedAmount.token, chainIdentifier, true, requestedAmount.pricePrefetch);
|
|
137
|
+
signal.throwIfAborted();
|
|
138
|
+
let total;
|
|
139
|
+
if (requestedAmount.input) {
|
|
140
|
+
total = requestedAmount.amount;
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
const amountInToken = await this.swapPricing.getFromBtcSwapAmount(requestedAmount.amount, requestedAmount.token, chainIdentifier, true, requestedAmount.pricePrefetch);
|
|
144
|
+
signal.throwIfAborted();
|
|
145
|
+
total = amountInToken + swapFeeInToken + networkFeeInToken;
|
|
146
|
+
}
|
|
147
|
+
return { amountBD, networkFeeData: resp, swapFee, swapFeeInToken, networkFee: resp.networkFee, networkFeeInToken, totalInToken: total };
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
exports.ToBtcAmountAssertions = ToBtcAmountAssertions;
|
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
import { SwapBaseConfig, SwapHandler } from "../SwapHandler";
|
|
2
|
-
import { ChainEvent, ChainSwapType, ClaimEvent, InitializeEvent, RefundEvent, SwapData, SwapEvent } from "@atomiqlabs/base";
|
|
3
|
-
import { EscrowHandlerSwap } from "./EscrowHandlerSwap";
|
|
4
|
-
import { ServerParamEncoder } from "../../utils/paramcoders/server/ServerParamEncoder";
|
|
5
|
-
import { SwapHandlerSwap } from "../SwapHandlerSwap";
|
|
6
|
-
export type ToBtcBaseConfig = SwapBaseConfig & {
|
|
7
|
-
gracePeriod: bigint;
|
|
8
|
-
refundAuthorizationTimeout: number;
|
|
9
|
-
};
|
|
10
|
-
export declare abstract class EscrowHandler<V extends EscrowHandlerSwap<SwapData, S>, S> extends SwapHandler<V, S> {
|
|
11
|
-
abstract readonly swapType: ChainSwapType;
|
|
12
|
-
readonly escrowHashMap: Map<string, V>;
|
|
13
|
-
protected swapLogger: {
|
|
14
|
-
debug: (swap: SwapHandlerSwap | SwapEvent<SwapData> | SwapData, msg: string, ...args: any) => void;
|
|
15
|
-
info: (swap: SwapHandlerSwap | SwapEvent<SwapData> | SwapData, msg: string, ...args: any) => void;
|
|
16
|
-
warn: (swap: SwapHandlerSwap | SwapEvent<SwapData> | SwapData, msg: string, ...args: any) => void;
|
|
17
|
-
error: (swap: SwapHandlerSwap | SwapEvent<SwapData> | SwapData, msg: string, ...args: any) => void;
|
|
18
|
-
};
|
|
19
|
-
protected abstract processInitializeEvent(chainIdentifier: string, swap: V, event: InitializeEvent<SwapData>): Promise<void>;
|
|
20
|
-
protected abstract processClaimEvent(chainIdentifier: string, swap: V, event: ClaimEvent<SwapData>): Promise<void>;
|
|
21
|
-
protected abstract processRefundEvent(chainIdentifier: string, swap: V, event: RefundEvent<SwapData>): Promise<void>;
|
|
22
|
-
/**
|
|
23
|
-
* Chain event processor
|
|
24
|
-
*
|
|
25
|
-
* @param chainIdentifier
|
|
26
|
-
* @param eventData
|
|
27
|
-
*/
|
|
28
|
-
protected processEvent(chainIdentifier: string, eventData: ChainEvent<SwapData>[]): Promise<boolean>;
|
|
29
|
-
/**
|
|
30
|
-
* Initializes chain events subscription
|
|
31
|
-
*/
|
|
32
|
-
protected subscribeToEvents(): void;
|
|
33
|
-
protected loadData(ctor: new (data: any) => V): Promise<void>;
|
|
34
|
-
protected removeSwapData(swap: V, ultimateState?: S): Promise<void>;
|
|
35
|
-
protected saveSwapData(swap: V): Promise<void>;
|
|
36
|
-
protected saveSwapToEscrowHashMap(swap: V): void;
|
|
37
|
-
protected removeSwapFromEscrowHashMap(swap: V): void;
|
|
38
|
-
protected getSwapByEscrowHash(chainIdentifier: string, escrowHash: string): V;
|
|
39
|
-
protected getIdentifierFromEvent(event: SwapEvent<SwapData>): string;
|
|
40
|
-
protected getIdentifierFromSwapData(swapData: SwapData): string;
|
|
41
|
-
protected getIdentifier(swap: SwapHandlerSwap | SwapEvent<SwapData> | SwapData): string;
|
|
42
|
-
/**
|
|
43
|
-
* Starts a pre-fetch for signature data
|
|
44
|
-
*
|
|
45
|
-
* @param chainIdentifier
|
|
46
|
-
* @param abortController
|
|
47
|
-
* @param responseStream
|
|
48
|
-
*/
|
|
49
|
-
protected getSignDataPrefetch(chainIdentifier: string, abortController: AbortController, responseStream?: ServerParamEncoder): Promise<any>;
|
|
50
|
-
}
|
|
1
|
+
import { SwapBaseConfig, SwapHandler } from "../SwapHandler";
|
|
2
|
+
import { ChainEvent, ChainSwapType, ClaimEvent, InitializeEvent, RefundEvent, SwapData, SwapEvent } from "@atomiqlabs/base";
|
|
3
|
+
import { EscrowHandlerSwap } from "./EscrowHandlerSwap";
|
|
4
|
+
import { ServerParamEncoder } from "../../utils/paramcoders/server/ServerParamEncoder";
|
|
5
|
+
import { SwapHandlerSwap } from "../SwapHandlerSwap";
|
|
6
|
+
export type ToBtcBaseConfig = SwapBaseConfig & {
|
|
7
|
+
gracePeriod: bigint;
|
|
8
|
+
refundAuthorizationTimeout: number;
|
|
9
|
+
};
|
|
10
|
+
export declare abstract class EscrowHandler<V extends EscrowHandlerSwap<SwapData, S>, S> extends SwapHandler<V, S> {
|
|
11
|
+
abstract readonly swapType: ChainSwapType;
|
|
12
|
+
readonly escrowHashMap: Map<string, V>;
|
|
13
|
+
protected swapLogger: {
|
|
14
|
+
debug: (swap: SwapHandlerSwap | SwapEvent<SwapData> | SwapData, msg: string, ...args: any) => void;
|
|
15
|
+
info: (swap: SwapHandlerSwap | SwapEvent<SwapData> | SwapData, msg: string, ...args: any) => void;
|
|
16
|
+
warn: (swap: SwapHandlerSwap | SwapEvent<SwapData> | SwapData, msg: string, ...args: any) => void;
|
|
17
|
+
error: (swap: SwapHandlerSwap | SwapEvent<SwapData> | SwapData, msg: string, ...args: any) => void;
|
|
18
|
+
};
|
|
19
|
+
protected abstract processInitializeEvent(chainIdentifier: string, swap: V, event: InitializeEvent<SwapData>): Promise<void>;
|
|
20
|
+
protected abstract processClaimEvent(chainIdentifier: string, swap: V, event: ClaimEvent<SwapData>): Promise<void>;
|
|
21
|
+
protected abstract processRefundEvent(chainIdentifier: string, swap: V, event: RefundEvent<SwapData>): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Chain event processor
|
|
24
|
+
*
|
|
25
|
+
* @param chainIdentifier
|
|
26
|
+
* @param eventData
|
|
27
|
+
*/
|
|
28
|
+
protected processEvent(chainIdentifier: string, eventData: ChainEvent<SwapData>[]): Promise<boolean>;
|
|
29
|
+
/**
|
|
30
|
+
* Initializes chain events subscription
|
|
31
|
+
*/
|
|
32
|
+
protected subscribeToEvents(): void;
|
|
33
|
+
protected loadData(ctor: new (data: any) => V): Promise<void>;
|
|
34
|
+
protected removeSwapData(swap: V, ultimateState?: S): Promise<void>;
|
|
35
|
+
protected saveSwapData(swap: V): Promise<void>;
|
|
36
|
+
protected saveSwapToEscrowHashMap(swap: V): void;
|
|
37
|
+
protected removeSwapFromEscrowHashMap(swap: V): void;
|
|
38
|
+
protected getSwapByEscrowHash(chainIdentifier: string, escrowHash: string): V;
|
|
39
|
+
protected getIdentifierFromEvent(event: SwapEvent<SwapData>): string;
|
|
40
|
+
protected getIdentifierFromSwapData(swapData: SwapData): string;
|
|
41
|
+
protected getIdentifier(swap: SwapHandlerSwap | SwapEvent<SwapData> | SwapData): string;
|
|
42
|
+
/**
|
|
43
|
+
* Starts a pre-fetch for signature data
|
|
44
|
+
*
|
|
45
|
+
* @param chainIdentifier
|
|
46
|
+
* @param abortController
|
|
47
|
+
* @param responseStream
|
|
48
|
+
*/
|
|
49
|
+
protected getSignDataPrefetch(chainIdentifier: string, abortController: AbortController, responseStream?: ServerParamEncoder): Promise<any>;
|
|
50
|
+
}
|