@strkfarm/sdk 1.1.70 → 2.0.0-dev.2

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 (53) hide show
  1. package/dist/cli.js +2 -2
  2. package/dist/cli.mjs +2 -2
  3. package/dist/index.browser.global.js +67016 -59681
  4. package/dist/index.browser.mjs +29832 -23221
  5. package/dist/index.d.ts +2006 -787
  6. package/dist/index.js +25403 -18769
  7. package/dist/index.mjs +25333 -18739
  8. package/package.json +80 -76
  9. package/src/data/extended-deposit.abi.json +3613 -0
  10. package/src/data/universal-vault.abi.json +135 -20
  11. package/src/dataTypes/address.ts +7 -0
  12. package/src/global.ts +240 -193
  13. package/src/interfaces/common.tsx +26 -2
  14. package/src/modules/ExtendedWrapperSDk/index.ts +62 -0
  15. package/src/modules/ExtendedWrapperSDk/types.ts +311 -0
  16. package/src/modules/ExtendedWrapperSDk/wrapper.ts +395 -0
  17. package/src/modules/avnu.ts +17 -4
  18. package/src/modules/ekubo-quoter.ts +99 -10
  19. package/src/modules/erc20.ts +67 -21
  20. package/src/modules/harvests.ts +16 -29
  21. package/src/modules/index.ts +5 -1
  22. package/src/modules/lst-apr.ts +36 -0
  23. package/src/modules/midas.ts +159 -0
  24. package/src/modules/pricer-from-api.ts +2 -2
  25. package/src/modules/pricer-lst.ts +1 -1
  26. package/src/modules/pricer.ts +3 -38
  27. package/src/modules/token-market-data.ts +202 -0
  28. package/src/node/deployer.ts +1 -36
  29. package/src/strategies/autoCompounderStrk.ts +1 -1
  30. package/src/strategies/base-strategy.ts +20 -3
  31. package/src/strategies/ekubo-cl-vault.tsx +123 -306
  32. package/src/strategies/index.ts +4 -1
  33. package/src/strategies/svk-strategy.ts +247 -0
  34. package/src/strategies/universal-adapters/adapter-optimizer.ts +65 -0
  35. package/src/strategies/universal-adapters/adapter-utils.ts +5 -1
  36. package/src/strategies/universal-adapters/avnu-adapter.ts +411 -0
  37. package/src/strategies/universal-adapters/baseAdapter.ts +181 -153
  38. package/src/strategies/universal-adapters/common-adapter.ts +98 -77
  39. package/src/strategies/universal-adapters/extended-adapter.ts +661 -0
  40. package/src/strategies/universal-adapters/index.ts +5 -1
  41. package/src/strategies/universal-adapters/unused-balance-adapter.ts +109 -0
  42. package/src/strategies/universal-adapters/vesu-adapter.ts +220 -218
  43. package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +924 -0
  44. package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +58 -51
  45. package/src/strategies/universal-lst-muliplier-strategy.tsx +707 -774
  46. package/src/strategies/universal-strategy.tsx +1098 -1180
  47. package/src/strategies/vesu-extended-strategy/services/operationService.ts +34 -0
  48. package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +77 -0
  49. package/src/strategies/vesu-extended-strategy/utils/constants.ts +49 -0
  50. package/src/strategies/vesu-extended-strategy/utils/helper.ts +376 -0
  51. package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +1134 -0
  52. package/src/strategies/vesu-rebalance.tsx +16 -19
  53. package/src/utils/health-factor-math.ts +11 -5
@@ -0,0 +1,34 @@
1
+ import { Web3Number } from "@/dataTypes";
2
+ import { TokenInfo } from "@/interfaces";
3
+ import { ExtendedAdapter } from "@/strategies/universal-adapters/extended-adapter";
4
+ import { VesuMultiplyAdapter } from "../../universal-adapters/vesu-multiply-adapter";
5
+ import { Call } from "starknet";
6
+ export abstract class Operations {
7
+ abstract shouldMoveAssets(
8
+ extendedAmount: Web3Number,
9
+ vesuAmount: Web3Number
10
+ ): Promise<Call[]>;
11
+ abstract shouldInvest(): Promise<{
12
+ shouldInvest: boolean;
13
+ vesuAmount: Web3Number;
14
+ extendedAmount: Web3Number;
15
+ extendedLeverage: number;
16
+ vesuLeverage: number;
17
+ }>;
18
+ abstract moveAssets(
19
+ params: { from: string; to: string; amount: Web3Number },
20
+ extendedAdapter: ExtendedAdapter,
21
+ vesuAdapter: VesuMultiplyAdapter
22
+ ): Promise<{
23
+ calls: Call[];
24
+ status: boolean;
25
+ }>;
26
+ abstract handleDeposit(): Promise<{
27
+ extendedAmountInBTC: Web3Number;
28
+ calls: Call[];
29
+ }>;
30
+ abstract handleWithdraw(amount: Web3Number): Promise<{
31
+ calls: Call[];
32
+ status: boolean;
33
+ }> ;
34
+ }
@@ -0,0 +1,77 @@
1
+ import {
2
+ AVNU_API,
3
+ USDC_TOKEN_ADDRESS,
4
+ USDC_TOKEN_DECIMALS,
5
+ WBTC_TOKEN_ADDRESS,
6
+ WBTC_TOKEN_DECIMALS,
7
+ WALLET_ADDRESS,
8
+ EXTEND_CONTRACT_ADDRESS,
9
+ MULTIPLY_CONTRACT_ADDRESS,
10
+ EXTENDED_BASE_URL,
11
+ EXTEND_MARKET_NAME,
12
+ EXTENDED_QTY_PRECISION,
13
+ EXTENDED_FEES,
14
+ MAINTENANCE_MARGIN,
15
+ VESU_POOL_ID,
16
+ MAX_LTV_BTC_USDC,
17
+ MAX_LIQUIDATION_RATIO,
18
+ TARGET_HF,
19
+ EKUBO_ENDPOINT,
20
+ PRICE_MAX_SLIPPAGE_EKUBO,
21
+ MINIMUM_DEBT_AMOUNT_VESU_FOR_REBALANCING,
22
+ MINIMUM_EXTENDED_POSITION_SIZE
23
+ } from "./constants"
24
+ import VesuPoolV2Abi from '@/data/vesu-pool-v2.abi.json';
25
+ import ExtendedDepositAbi from '@/data/extended-deposit.abi.json';
26
+ import VesuMultiplyAbi from '@/data/vesu-multiple.abi.json';
27
+
28
+ // Grouped, readable configuration (no behavior change). Consumers can migrate gradually.
29
+
30
+ export const AddressesConfig = {
31
+ tokens: {
32
+ USDC: { address: USDC_TOKEN_ADDRESS, decimals: USDC_TOKEN_DECIMALS },
33
+ WBTC: { address: WBTC_TOKEN_ADDRESS, decimals: WBTC_TOKEN_DECIMALS },
34
+ },
35
+ contracts: {
36
+ EXTENDED: EXTEND_CONTRACT_ADDRESS,
37
+ MULTIPLY: MULTIPLY_CONTRACT_ADDRESS,
38
+ },
39
+ wallet: {
40
+ address: WALLET_ADDRESS,
41
+ },
42
+ } as const;
43
+
44
+ export const ExtendedConfig = {
45
+ baseUrl: EXTENDED_BASE_URL,
46
+ marketName: EXTEND_MARKET_NAME,
47
+ maintenanceMargin: MAINTENANCE_MARGIN,
48
+ precision: EXTENDED_QTY_PRECISION,
49
+ fees: EXTENDED_FEES,
50
+ minPositionSize: MINIMUM_EXTENDED_POSITION_SIZE,
51
+ } as const;
52
+
53
+ export const VesuConfig = {
54
+ poolId: VESU_POOL_ID,
55
+ maxLtv: MAX_LTV_BTC_USDC,
56
+ maxLiquidationRatio: MAX_LIQUIDATION_RATIO,
57
+ targetHealthFactor: TARGET_HF,
58
+ ekubo: {
59
+ endpoint: EKUBO_ENDPOINT,
60
+ priceMaxSlippage: PRICE_MAX_SLIPPAGE_EKUBO,
61
+ },
62
+ avnu: {
63
+ api: AVNU_API,
64
+ },
65
+ minDebtForVesuRebalacing:MINIMUM_DEBT_AMOUNT_VESU_FOR_REBALANCING
66
+ } as const;
67
+
68
+ export const AbisConfig = {
69
+ vesu: {
70
+ multiply: VesuMultiplyAbi,
71
+ pool: VesuPoolV2Abi,
72
+ },
73
+ extended: {
74
+ contract: ExtendedDepositAbi,
75
+ },
76
+ } as const;
77
+
@@ -0,0 +1,49 @@
1
+ export const AVNU_API = "https://starknet.api.avnu.fi/swap/v2/quotes";
2
+ export const SLIPPAGE = 0.01;
3
+ export const USDC_TOKEN_DECIMALS = 6;
4
+ export const USDC_TOKEN_ADDRESS =
5
+ "0x053C91253BC9682c04929cA02ED00b3E423f6710D2ee7e0D5EBB06F3eCF368A8";
6
+ export const BUFFER_USDC_IN_WITHDRAWAL=5;
7
+ export const WBTC_TOKEN_ADDRESS = "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac";
8
+ export const WBTC_TOKEN_DECIMALS = 8;
9
+ export const MAINTENANCE_MARGIN = 0.01;
10
+ export const MAX_PRICE_DROP_PERCENTAGE = Number(process.env.MAX_PRICE_DROP_PERCENTAGE ?? 0.25);
11
+ export const MAX_LTV_BTC_USDC = 0.8428;
12
+ export const MAX_LIQUIDATION_RATIO = 0.86;
13
+ export const VAULT_ID_EXTENDED= process.env.VAULT_ID_EXTENDED ?? 220774;
14
+ export const WALLET_ADDRESS =
15
+ process.env.WALLET_ADDRESS ?? "0x07b84bb6E87588BdAde0bfe6173A615b3C220F9C3803456aE183C50EA1d15Ba1";
16
+ export const TESTNET_WALLET_ADDRESS =
17
+ process.env.TESTNET_WALLET_ADDRESS ?? "0x07b84bb6E87588BdAde0bfe6173A615b3C220F9C3803456aE183C50EA1d15Ba1";
18
+ export const TEST_WALLET_2 =
19
+ process.env.TEST_WALLET_2 ?? "0x004C1bdC61DAc7947F3C93d0163d660012E2aB0521567f7155fcf502848791A7";
20
+ export const STRK_API_TEST_RPC = process.env.STRK_API_TEST_RPC ?? "https://sepolia.starknet.a5a.ch";
21
+ export const STRK_API_RPC = process.env.STRK_API_RPC ?? "https://mainnet.starknet.a5a.ch";
22
+ export const MAX_RETRIES = Number(process.env.MAX_RETRIES ?? 3);
23
+ export const MAX_DELAY = Number(process.env.MAX_DELAY ?? 100);
24
+ export const EXTEND_MARKET_NAME = "BTC-USD";
25
+ export const LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ?? 10);
26
+ export const REBALANCER_INTERVAL = Number(process.env.REBALANCER_INTERVAL ?? 180000); //3 mins
27
+ export const WITHDRAWAL_INTERVAL = Number(process.env.WITHDRAWAL_INTERVAL ?? 18000000); //5 hours
28
+ export const INVESTING_INTERVAL = Number(process.env.INVESTING_INTERVAL ?? 180000); //3 mins
29
+ export const MAXIMUM_DELTA = Number(process.env.MAXIMUM_DELTA ?? 5);
30
+ export const EXTENDED_BASE_URL = process.env.EXTENDED_BASE_URL ?? "https://api.starknet.extended.exchange";
31
+ export const VESU_POOL_ID = "0x02eef0c13b10b487ea5916b54c0a7f98ec43fb3048f60fdeedaf5b08f6f88aaf";
32
+ export const EKUBO_ENDPOINT = "https://quoter-mainnet-api.ekubo.org/{{AMOUNT}}/{{TOKEN_FROM_ADDRESS}}/{{TOKEN_TO_ADDRESS}}"; // e.g. ETH/USDC'
33
+ export const TARGET_HF = Number(process.env.TARGET_HF ?? 1.4);
34
+ export const MULTIPLY_CONTRACT_ADDRESS = "0x07964760e90baa28841ec94714151e03fbc13321797e68a874e88f27c9d58513";
35
+ export const EXTEND_CONTRACT_ADDRESS = "0x062da0780fae50d68cecaa5a051606dc21217ba290969b302db4dd99d2e9b470";
36
+ export const EXTENDED_QTY_PRECISION = 5;
37
+ export const EXTENDED_FEES= Number(process.env.EXTENDED_FEES ?? 0.006);
38
+ export const REBALANCE_PRICE_DROP_PERCENTAGE = Number(process.env.REBALANCE_PRICE_DROP_PERCENTAGE ?? 3);
39
+ export const PRICE_MAX_SLIPPAGE_EKUBO = Number(process.env.PRICE_MAX_SLIPPAGE_EKUBO ?? 0.005);
40
+ export const MINIMUM_DEBT_AMOUNT_VESU_FOR_REBALANCING = Number(process.env.MINIMUM_DEBT_AMOUNT_VESU_FOR_REBALANCING ?? 1);
41
+ export const MINIMUM_EXTENDED_POSITION_SIZE = 0.0001;
42
+ export const MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP = 0.00001;
43
+ export const MAX_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED = 700;
44
+ export const MIN_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED = -100;
45
+
46
+ //STATUS CODES
47
+ export const SUCCESS_STATUS_CODE = 200;
48
+ export const ERROR_STATUS_CODE = 500;
49
+ export const BAD_REQUEST_STATUS_CODE = 400;
@@ -0,0 +1,376 @@
1
+ import {
2
+ MAINTENANCE_MARGIN,
3
+ MAX_LTV_BTC_USDC,
4
+ MAX_PRICE_DROP_PERCENTAGE,
5
+ TARGET_HF,
6
+ WBTC_TOKEN_ADDRESS,
7
+ USDC_TOKEN_ADDRESS,
8
+ WBTC_TOKEN_DECIMALS,
9
+ USDC_TOKEN_DECIMALS,
10
+ MAX_LIQUIDATION_RATIO,
11
+ } from "./constants";
12
+ import { Web3Number } from "@/dataTypes";
13
+ import { Position } from "@/modules/ExtendedWrapperSDk";
14
+ // import { getAllOpenPositionsExtended } from "../services/extendedService";
15
+ import ExtendedWrapper from "@/modules/ExtendedWrapperSDk";
16
+ import { logger } from "@/utils";
17
+ // import {
18
+ // calculatePositionOnVesu,
19
+ // getAssetPrice,
20
+ // } from "../services/vesuService";
21
+ /**
22
+ * Function to return formatted amount to BigInt
23
+ * Converts a decimal amount to the proper format for blockchain transactions
24
+ * @param {number} amount - The decimal amount to convert
25
+ * @param {number} fromTokenDecimals - The decimal precision of the token
26
+ * @returns {string} The formatted amount as a hexadecimal string
27
+ */
28
+ export const returnFormattedAmount = (
29
+ amount: number,
30
+ toTokenDecimals: number
31
+ ) => {
32
+ const formattedAmount =
33
+ "0x" + BigInt(Math.floor(amount * 10 ** toTokenDecimals)).toString(16);
34
+ return formattedAmount;
35
+ };
36
+
37
+ /**
38
+ * calculates the amount to distribute to Extend and Vesu
39
+ * Determines how much to allocate to each platform based on leverage calculations
40
+ * @param {number} amount - The total amount to distribute
41
+ * @returns {object} Object containing avnu_amount, extended_amount, and extended_leverage
42
+ */
43
+ export const calculateAmountDistribution = async (
44
+ amount: number,
45
+ client: ExtendedWrapper,
46
+ marketName: string,
47
+ collateralPrice: number,
48
+ debtPrice: number,
49
+ collateralUnits: Web3Number,
50
+ extendedPosition: Position[] | null
51
+ ): Promise<{
52
+ vesu_amount: Web3Number;
53
+ extended_amount: Web3Number;
54
+ extended_leverage: number;
55
+ vesu_leverage: number;
56
+ }> => {
57
+ try {
58
+ const extended_leverage = calculateExtendedLevergae();
59
+ const vesu_leverage = calculateVesuLeverage();
60
+ if (extendedPosition === null) {
61
+ logger.error("error getting extended positions");
62
+ return {
63
+ vesu_amount: new Web3Number(0, 0),
64
+ extended_amount: new Web3Number(0, 0),
65
+ extended_leverage: 0,
66
+ vesu_leverage: 0,
67
+ };
68
+ }
69
+ const extendedBTCExposure =
70
+ extendedPosition.length > 0
71
+ ? new Web3Number(extendedPosition[0].size, WBTC_TOKEN_DECIMALS)
72
+ : new Web3Number(0, WBTC_TOKEN_DECIMALS);
73
+ const extendedExposureUSD =
74
+ extendedBTCExposure.multipliedBy(collateralPrice);
75
+ const vesuBTCExposureUSD = collateralUnits.multipliedBy(collateralPrice);
76
+ const numerator1 = vesu_leverage * amount + vesuBTCExposureUSD.toNumber();
77
+ const numerator2 = extendedExposureUSD.toNumber();
78
+ const denominator = vesu_leverage + extended_leverage;
79
+ const ExtendedAmount = new Web3Number(
80
+ ((numerator1 - numerator2) / denominator).toFixed(2),
81
+ USDC_TOKEN_DECIMALS
82
+ );
83
+
84
+ const VesuAmount = new Web3Number(
85
+ amount.toFixed(2),
86
+ USDC_TOKEN_DECIMALS
87
+ ).minus(ExtendedAmount);
88
+
89
+ return {
90
+ vesu_amount: VesuAmount,
91
+ extended_amount: ExtendedAmount,
92
+ extended_leverage,
93
+ vesu_leverage,
94
+ };
95
+ } catch (err) {
96
+ return {
97
+ vesu_amount: new Web3Number(0, 0),
98
+ extended_amount: new Web3Number(0, 0),
99
+ extended_leverage: 0,
100
+ vesu_leverage: 0,
101
+ };
102
+ }
103
+ };
104
+
105
+ /**
106
+ * calculate the amount distribution for withdrawal
107
+ * @param amount - The amount to withdraw
108
+ * @param client - The client
109
+ * @param marketName - The market name
110
+ * @returns {object} Object containing avnu_amount and extended_amount
111
+ */
112
+ export const calculateAmountDistributionForWithdrawal = async (
113
+ amountInUsdc: Web3Number,
114
+ collateralPrice: number,
115
+ collateralUnits: Web3Number,
116
+ extendedPosition: Position[] | null
117
+ ): Promise<{
118
+ vesu_amount: Web3Number;
119
+ extended_amount: Web3Number;
120
+ extended_leverage: number;
121
+ vesu_leverage: number;
122
+ } | null> => {
123
+ try {
124
+ const extended_leverage = calculateExtendedLevergae();
125
+ const vesu_leverage = calculateVesuLeverage();
126
+ if (extendedPosition === null) {
127
+ logger.error("error getting extended positions");
128
+ return null;
129
+ }
130
+ const extendedExposureUSD =
131
+ extendedPosition.length > 0
132
+ ? new Web3Number(extendedPosition[0].value, USDC_TOKEN_DECIMALS)
133
+ : new Web3Number(0, USDC_TOKEN_DECIMALS);
134
+ console.log("THe collateral is", collateralPrice, collateralUnits);
135
+ // console.log("the extended exposure usd is", extendedExposureUSD.toNumber());
136
+ //console.log("the collateral units are", collateralUnits.toNumber());\
137
+ const vesuExposureUSD = collateralUnits.multipliedBy(collateralPrice);
138
+ if (vesuExposureUSD.lessThan(0)) {
139
+ return {
140
+ vesu_amount: new Web3Number(0, USDC_TOKEN_DECIMALS),
141
+ extended_amount: amountInUsdc,
142
+ extended_leverage,
143
+ vesu_leverage,
144
+ };
145
+ }
146
+ if (extendedExposureUSD.lessThan(0)) {
147
+ return {
148
+ vesu_amount: amountInUsdc,
149
+ extended_amount: new Web3Number(0, USDC_TOKEN_DECIMALS),
150
+ extended_leverage,
151
+ vesu_leverage,
152
+ };
153
+ }
154
+ console.log("the vesu exposure usd is", vesuExposureUSD.toNumber());
155
+ console.log("the extended exposure usd is", extendedExposureUSD.toNumber());
156
+ console.log("the amount in usdc is", amountInUsdc.toNumber());
157
+ console.log("the extended leverage is", extended_leverage);
158
+ console.log("the vesu leverage is", vesu_leverage);
159
+ const numerator1 = amountInUsdc.multipliedBy(extended_leverage);
160
+ const numerator2 = vesuExposureUSD;
161
+ const numerator3 = extendedExposureUSD
162
+ .multipliedBy(-1);
163
+ const finalNumerator = numerator1.plus(numerator2).plus(numerator3);
164
+ const denominator = extended_leverage + vesu_leverage;
165
+ const vesuAmountInUSDC = finalNumerator.dividedBy(denominator);
166
+ console.log("the vesu amount in usdc is", vesuAmountInUSDC.toNumber());
167
+ const extendedAmountInUSDC = amountInUsdc.minus(vesuAmountInUSDC);
168
+ console.log(
169
+ "the extended amount in usdc is",
170
+ extendedAmountInUSDC.toNumber()
171
+ );
172
+ //console.log("the vesu amount in usdc is", vesuAmountInUSDC.toNumber());
173
+ //console.log("the extended amount in usdc is", extendedAmountInUSDC.toNumber());\
174
+ await new Promise((resolve) => setTimeout(resolve, 10000));
175
+ return {
176
+ vesu_amount: vesuAmountInUSDC,
177
+ extended_amount: extendedAmountInUSDC,
178
+ extended_leverage,
179
+ vesu_leverage,
180
+ };
181
+ } catch (err) {
182
+ logger.error(`error calculating amount distribution for withdrawal: ${err}`);
183
+ return null;
184
+ }
185
+ };
186
+ /**
187
+ * calculate the leverage required for Avnu
188
+ * calculates the optimal leverage for Avnu based on LTV ratios and price drop protection
189
+ * @returns {number} The calculated leverage value
190
+ */
191
+ export const calculateVesuLeverage = () => {
192
+ const max_ltv_ratio = (1 - MAX_PRICE_DROP_PERCENTAGE) * MAX_LIQUIDATION_RATIO; //0.75
193
+ const our_ltv_ratio = Math.floor(max_ltv_ratio * 100) - 5; //buffer of 5% to prevent liquidation
194
+ const leverage = 1 / (1 - our_ltv_ratio / 100);
195
+ return Math.ceil(leverage * 10) / 10;
196
+ };
197
+
198
+ /**
199
+ * calculate leverage for extended
200
+ * calculates the maximum safe leverage for Extended based on maintenance margin and price drop protection
201
+ * @returns {number} The calculated leverage value
202
+ */
203
+ export const calculateExtendedLevergae = () => {
204
+ const extended_leverage_max =
205
+ 1 / (MAINTENANCE_MARGIN + MAX_PRICE_DROP_PERCENTAGE);
206
+ return Math.floor(extended_leverage_max);
207
+ };
208
+
209
+ /**
210
+ * calculates the debt amount for leverage operations
211
+ * Determines how much debt to add or remove based on collateral changes and target health factor
212
+ * @param {Web3Number} collateralAmount - Current collateral amount
213
+ * @param {Web3Number} debtAmount - Current debt amount
214
+ * @param {number} debtPrice - Current price of the debt token
215
+ * @param {number} maxLtv - Maximum loan-to-value ratio (default: MAX_LTV_BTC_USDC)
216
+ * @param {number} addedAmount - Amount being added to collateral
217
+ * @param {number} collateralPrice - Current price of the collateral token
218
+ * @param {boolean} isDeposit - Whether this is a deposit (true) or withdrawal (false)
219
+ * @returns {object} Object containing deltadebtAmountUnits and isIncrease flag
220
+ */
221
+ // In case BTC_PRICE DROPS the added amount will be zero, and use this formula to calculated the debt that needs to be paid to maintain the ltv
222
+ export const calculateDebtAmount = (
223
+ collateralAmount: Web3Number,
224
+ debtAmount: Web3Number,
225
+ debtPrice: number,
226
+ maxLtv: number = MAX_LTV_BTC_USDC,
227
+ addedAmount: Web3Number, // this is in btc
228
+ collateralPrice: number,
229
+ isDeposit: boolean
230
+ ) => {
231
+ try {
232
+ // => X = (((collateral + legDepositAmount) * collateralPrice * ltv) - (debt * debtPrice * target hf)) / (target hf - ltv)
233
+ const marginAmount = addedAmount.multipliedBy(isDeposit ? 1 : -1);
234
+ const numerator1 = collateralAmount
235
+ .plus(addedAmount)
236
+ .multipliedBy(collateralPrice)
237
+ .multipliedBy(maxLtv);
238
+ const numerator2 = debtAmount
239
+ .multipliedBy(debtPrice)
240
+ .multipliedBy(TARGET_HF);
241
+ const denominator = TARGET_HF - maxLtv;
242
+ const x_debt_usd = numerator1.minus(numerator2).dividedBy(denominator);
243
+ let deltadebtAmountUnits = new Web3Number(
244
+ x_debt_usd.dividedBy(debtPrice).toFixed(2),
245
+ 2
246
+ );
247
+ let isIncrease = x_debt_usd.greaterThan(0);
248
+ return { deltadebtAmountUnits, isIncrease };
249
+ } catch (err) {
250
+ return { deltadebtAmountUnits: null, isIncrease: null };
251
+ }
252
+ };
253
+
254
+ /**
255
+ * calculate the debt amount to be repaid for withdrawal
256
+ * @param debtAmount in debt units
257
+ * @param collateralAmount in collateral units
258
+ * @param maxLtv in percentage
259
+ * @param withdrawalAmount in collateral units
260
+ * @param collateralPrice in usd
261
+ * @param debtPrice in usd
262
+ * @returns deltadebtAmountUnits in debt units
263
+ * isIncrease: true if the debt amount is increasing, false if it is decreasing
264
+ */
265
+ export const calculateDebtReductionAmountForWithdrawal = (
266
+ debtAmount: Web3Number,
267
+ collateralAmount: Web3Number,
268
+ maxLtv: number = MAX_LTV_BTC_USDC,
269
+ withdrawalAmount: Web3Number,
270
+ collateralPrice: number,
271
+ debtPrice: number,
272
+ usdcDecimals: number
273
+ ) => {
274
+ try {
275
+ const vesuLeverage = calculateVesuLeverage();
276
+ const numerator1 = collateralAmount
277
+ .multipliedBy(collateralPrice)
278
+ .multipliedBy(maxLtv)
279
+ .multipliedBy(-1);
280
+ withdrawalAmount = withdrawalAmount.multipliedBy(vesuLeverage);
281
+ const numerator2 = debtAmount
282
+ .multipliedBy(debtPrice)
283
+ .multipliedBy(TARGET_HF);
284
+ const numerator3 = withdrawalAmount
285
+ .multipliedBy(collateralPrice)
286
+ .multipliedBy(maxLtv);
287
+ const numeratorTotal = numerator1.plus(numerator2).plus(numerator3);
288
+ const denominator = debtPrice * TARGET_HF;
289
+ const x_debt_usdc = numeratorTotal.dividedBy(denominator);
290
+ let deltadebtAmountUnits = x_debt_usdc
291
+ .multipliedBy(-1)
292
+ .toFixed(usdcDecimals); // means we are paying debt
293
+ return { deltadebtAmountUnits };
294
+ } catch (err) {
295
+ return { deltadebtAmountUnits: null };
296
+ }
297
+ };
298
+
299
+ /**
300
+ * calculate the amount to deposit on extended when incurring losses
301
+ * @param client - The client
302
+ * @returns The amount to deposit on extended when incurring losses
303
+ */
304
+ export const calculateAmountDepositOnExtendedWhenIncurringLosses = async (
305
+ client: ExtendedWrapper
306
+ ) => {
307
+ try {
308
+ const extendedHoldings = await client.getHoldings();
309
+ const extended_leverage = calculateExtendedLevergae();
310
+ const latestPosition = (await client.getPositions()).data.pop();
311
+ console.log("the latest position is", latestPosition, extendedHoldings);
312
+ if (!extendedHoldings || !latestPosition) {
313
+ logger.error(`error getting extended position: extendedHoldings=${extendedHoldings}, latestPosition=${latestPosition}`);
314
+ return null;
315
+ }
316
+ const positionValueInUSD = latestPosition.value;
317
+ const equity = extendedHoldings.data.equity;
318
+ const deposit =
319
+ Number(positionValueInUSD) / extended_leverage - Number(equity);
320
+ return new Web3Number(Math.floor(deposit / 0.2) * 0.2, USDC_TOKEN_DECIMALS);
321
+ } catch (err) {
322
+ return null;
323
+ }
324
+ };
325
+
326
+ export const calculateExposureDelta = (
327
+ exposure_extended: number,
328
+ exposure_vesu: number
329
+ ) => {
330
+ const exposure_delta = new Web3Number(exposure_extended - exposure_vesu, 2);
331
+ return exposure_delta.absoluteValue().toNumber();
332
+ };
333
+
334
+ /// In case BTC PRICE DROPS
335
+ // 1. calculate the ltv on vesu
336
+ // 2. Find the debt that needs to be paid to maintain the ltv
337
+
338
+ /**
339
+ * calculate the delta percentage between the current btc price and the last btc price
340
+ * @param {number} btcPrice - The current btc price
341
+ * @param {number} lastBtcPrice - The last btc price
342
+ * @returns {number} The delta percentage
343
+ */
344
+ export const calculateBTCPriceDelta = (
345
+ btcPrice: number,
346
+ lastBtcPrice: number
347
+ ) => {
348
+ return ((btcPrice - lastBtcPrice) / lastBtcPrice) * 100;
349
+ };
350
+
351
+ export const calculateVesUPositionSizeGivenExtended = (
352
+ extendedPositonValue: number,
353
+ extendedHoldingAmount: Web3Number,
354
+ collateralAmount: Web3Number,
355
+ collateralPrice: number
356
+ ) => {
357
+ const extendedLeverage = calculateExtendedLevergae();
358
+ const vesuLeverage = calculateVesuLeverage();
359
+ const extendedAmount = extendedHoldingAmount;
360
+ const extendedAmountInBTC = extendedAmount
361
+ .dividedBy(collateralPrice)
362
+ const numerator1 = extendedAmount.multipliedBy(extendedLeverage)
363
+ .plus(extendedPositonValue)
364
+ const numerator2 = collateralAmount
365
+ .multipliedBy(collateralPrice)
366
+ .multipliedBy(-1);
367
+ const vesuAmountInUsd = numerator1.plus(numerator2).dividedBy(vesuLeverage);
368
+ const vesuAmountInBTC = vesuAmountInUsd
369
+ .dividedBy(collateralPrice)
370
+ .toFixed(WBTC_TOKEN_DECIMALS);
371
+ return {
372
+ vesuAmountInUsd: vesuAmountInUsd.toFixed(2),
373
+ vesuAmountInBTC: new Web3Number(vesuAmountInBTC, WBTC_TOKEN_DECIMALS),
374
+ extendedAmountInBTC: extendedAmountInBTC,
375
+ };
376
+ };