@strkfarm/sdk 1.1.70 → 2.0.0-dev.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 (53) hide show
  1. package/dist/cli.js +2 -2
  2. package/dist/cli.mjs +2 -2
  3. package/dist/index.browser.global.js +66861 -59746
  4. package/dist/index.browser.mjs +24970 -18579
  5. package/dist/index.d.ts +1969 -776
  6. package/dist/index.js +25264 -18850
  7. package/dist/index.mjs +25463 -19089
  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 +8 -1
  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 +98 -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 +418 -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 +544 -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 +28 -0
  48. package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +77 -0
  49. package/src/strategies/vesu-extended-strategy/utils/constants.ts +48 -0
  50. package/src/strategies/vesu-extended-strategy/utils/helper.ts +374 -0
  51. package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +992 -0
  52. package/src/strategies/vesu-rebalance.tsx +16 -19
  53. package/src/utils/health-factor-math.ts +11 -5
@@ -0,0 +1,28 @@
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<Call[]>;
23
+ abstract handleDeposit(): Promise<{
24
+ extendedAmountInBTC: Web3Number;
25
+ calls: Call[];
26
+ }>;
27
+ abstract handleWithdraw(amount: Web3Number): Promise<Call[]>;
28
+ }
@@ -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,48 @@
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 WBTC_TOKEN_ADDRESS = "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac";
7
+ export const WBTC_TOKEN_DECIMALS = 8;
8
+ export const MAINTENANCE_MARGIN = 0.01;
9
+ export const MAX_PRICE_DROP_PERCENTAGE = Number(process.env.MAX_PRICE_DROP_PERCENTAGE ?? 0.25);
10
+ export const MAX_LTV_BTC_USDC = 0.8428;
11
+ export const MAX_LIQUIDATION_RATIO = 0.86;
12
+ export const VAULT_ID_EXTENDED= process.env.VAULT_ID_EXTENDED ?? 220774;
13
+ export const WALLET_ADDRESS =
14
+ process.env.WALLET_ADDRESS ?? "0x07b84bb6E87588BdAde0bfe6173A615b3C220F9C3803456aE183C50EA1d15Ba1";
15
+ export const TESTNET_WALLET_ADDRESS =
16
+ process.env.TESTNET_WALLET_ADDRESS ?? "0x07b84bb6E87588BdAde0bfe6173A615b3C220F9C3803456aE183C50EA1d15Ba1";
17
+ export const TEST_WALLET_2 =
18
+ process.env.TEST_WALLET_2 ?? "0x004C1bdC61DAc7947F3C93d0163d660012E2aB0521567f7155fcf502848791A7";
19
+ export const STRK_API_TEST_RPC = process.env.STRK_API_TEST_RPC ?? "https://sepolia.starknet.a5a.ch";
20
+ export const STRK_API_RPC = process.env.STRK_API_RPC ?? "https://mainnet.starknet.a5a.ch";
21
+ export const MAX_RETRIES = Number(process.env.MAX_RETRIES ?? 3);
22
+ export const MAX_DELAY = Number(process.env.MAX_DELAY ?? 100);
23
+ export const EXTEND_MARKET_NAME = "BTC-USD";
24
+ export const LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ?? 10);
25
+ export const REBALANCER_INTERVAL = Number(process.env.REBALANCER_INTERVAL ?? 180000); //3 mins
26
+ export const WITHDRAWAL_INTERVAL = Number(process.env.WITHDRAWAL_INTERVAL ?? 18000000); //5 hours
27
+ export const INVESTING_INTERVAL = Number(process.env.INVESTING_INTERVAL ?? 180000); //3 mins
28
+ export const MAXIMUM_DELTA = Number(process.env.MAXIMUM_DELTA ?? 5);
29
+ export const EXTENDED_BASE_URL = process.env.EXTENDED_BASE_URL ?? "https://api.starknet.extended.exchange";
30
+ export const VESU_POOL_ID = "0x02eef0c13b10b487ea5916b54c0a7f98ec43fb3048f60fdeedaf5b08f6f88aaf";
31
+ export const EKUBO_ENDPOINT = "https://quoter-mainnet-api.ekubo.org/{{AMOUNT}}/{{TOKEN_FROM_ADDRESS}}/{{TOKEN_TO_ADDRESS}}"; // e.g. ETH/USDC'
32
+ export const TARGET_HF = Number(process.env.TARGET_HF ?? 1.4);
33
+ export const MULTIPLY_CONTRACT_ADDRESS = "0x07964760e90baa28841ec94714151e03fbc13321797e68a874e88f27c9d58513";
34
+ export const EXTEND_CONTRACT_ADDRESS = "0x062da0780fae50d68cecaa5a051606dc21217ba290969b302db4dd99d2e9b470";
35
+ export const EXTENDED_QTY_PRECISION = 5;
36
+ export const EXTENDED_FEES= Number(process.env.EXTENDED_FEES ?? 0.006);
37
+ export const REBALANCE_PRICE_DROP_PERCENTAGE = Number(process.env.REBALANCE_PRICE_DROP_PERCENTAGE ?? 3);
38
+ export const PRICE_MAX_SLIPPAGE_EKUBO = Number(process.env.PRICE_MAX_SLIPPAGE_EKUBO ?? 0.005);
39
+ export const MINIMUM_DEBT_AMOUNT_VESU_FOR_REBALANCING = Number(process.env.MINIMUM_DEBT_AMOUNT_VESU_FOR_REBALANCING ?? 1);
40
+ export const MINIMUM_EXTENDED_POSITION_SIZE = 0.0001;
41
+ export const MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP = 0.00001;
42
+ export const MAX_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED = 700;
43
+ export const MIN_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED = -100;
44
+
45
+ //STATUS CODES
46
+ export const SUCCESS_STATUS_CODE = 200;
47
+ export const ERROR_STATUS_CODE = 500;
48
+ export const BAD_REQUEST_STATUS_CODE = 400;
@@ -0,0 +1,374 @@
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 extendedBTCExposure =
131
+ extendedPosition.length > 0
132
+ ? new Web3Number(extendedPosition[0].size, WBTC_TOKEN_DECIMALS)
133
+ : new Web3Number(0, WBTC_TOKEN_DECIMALS);
134
+ const extendedExposureUSD =
135
+ extendedBTCExposure.multipliedBy(collateralPrice);
136
+ // console.log("the extended exposure usd is", extendedExposureUSD.toNumber());
137
+ //console.log("the collateral units are", collateralUnits.toNumber());\
138
+ const vesuExposureUSD = collateralUnits.multipliedBy(collateralPrice);
139
+ if (vesuExposureUSD.lessThan(0)) {
140
+ return {
141
+ vesu_amount: new Web3Number(0, USDC_TOKEN_DECIMALS),
142
+ extended_amount: amountInUsdc,
143
+ extended_leverage,
144
+ vesu_leverage,
145
+ };
146
+ }
147
+ if (extendedExposureUSD.lessThan(0)) {
148
+ return {
149
+ vesu_amount: amountInUsdc,
150
+ extended_amount: new Web3Number(0, USDC_TOKEN_DECIMALS),
151
+ extended_leverage,
152
+ vesu_leverage,
153
+ };
154
+ }
155
+ //console.log("the vesu exposure usd is", vesuExposureUSD.toNumber());
156
+ const numerator1 = amountInUsdc.multipliedBy(extended_leverage);
157
+ const numerator2 = vesuExposureUSD.multipliedBy(vesu_leverage);
158
+ const numerator3 = extendedExposureUSD
159
+ .multipliedBy(extended_leverage)
160
+ .multipliedBy(-1);
161
+ const finalNumerator = numerator1.plus(numerator2).plus(numerator3);
162
+ const denominator = extended_leverage + vesu_leverage;
163
+ const vesuAmountInUSDC = finalNumerator.dividedBy(denominator);
164
+ console.log("the vesu amount in usdc is", vesuAmountInUSDC.toNumber());
165
+ const extendedAmountInUSDC = amountInUsdc.minus(vesuAmountInUSDC);
166
+ console.log(
167
+ "the extended amount in usdc is",
168
+ extendedAmountInUSDC.toNumber()
169
+ );
170
+ //console.log("the vesu amount in usdc is", vesuAmountInUSDC.toNumber());
171
+ //console.log("the extended amount in usdc is", extendedAmountInUSDC.toNumber());
172
+
173
+ return {
174
+ vesu_amount: vesuAmountInUSDC,
175
+ extended_amount: extendedAmountInUSDC,
176
+ extended_leverage,
177
+ vesu_leverage,
178
+ };
179
+ } catch (err) {
180
+ logger.error(`error calculating amount distribution for withdrawal: ${err}`);
181
+ return null;
182
+ }
183
+ };
184
+ /**
185
+ * calculate the leverage required for Avnu
186
+ * calculates the optimal leverage for Avnu based on LTV ratios and price drop protection
187
+ * @returns {number} The calculated leverage value
188
+ */
189
+ export const calculateVesuLeverage = () => {
190
+ const max_ltv_ratio = (1 - MAX_PRICE_DROP_PERCENTAGE) * MAX_LIQUIDATION_RATIO; //0.75
191
+ const our_ltv_ratio = Math.floor(max_ltv_ratio * 100) - 5; //buffer of 5% to prevent liquidation
192
+ const leverage = 1 / (1 - our_ltv_ratio / 100);
193
+ return Math.ceil(leverage * 10) / 10;
194
+ };
195
+
196
+ /**
197
+ * calculate leverage for extended
198
+ * calculates the maximum safe leverage for Extended based on maintenance margin and price drop protection
199
+ * @returns {number} The calculated leverage value
200
+ */
201
+ export const calculateExtendedLevergae = () => {
202
+ const extended_leverage_max =
203
+ 1 / (MAINTENANCE_MARGIN + MAX_PRICE_DROP_PERCENTAGE);
204
+ return Math.floor(extended_leverage_max);
205
+ };
206
+
207
+ /**
208
+ * calculates the debt amount for leverage operations
209
+ * Determines how much debt to add or remove based on collateral changes and target health factor
210
+ * @param {Web3Number} collateralAmount - Current collateral amount
211
+ * @param {Web3Number} debtAmount - Current debt amount
212
+ * @param {number} debtPrice - Current price of the debt token
213
+ * @param {number} maxLtv - Maximum loan-to-value ratio (default: MAX_LTV_BTC_USDC)
214
+ * @param {number} addedAmount - Amount being added to collateral
215
+ * @param {number} collateralPrice - Current price of the collateral token
216
+ * @param {boolean} isDeposit - Whether this is a deposit (true) or withdrawal (false)
217
+ * @returns {object} Object containing deltadebtAmountUnits and isIncrease flag
218
+ */
219
+ // 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
220
+ export const calculateDebtAmount = (
221
+ collateralAmount: Web3Number,
222
+ debtAmount: Web3Number,
223
+ debtPrice: number,
224
+ maxLtv: number = MAX_LTV_BTC_USDC,
225
+ addedAmount: Web3Number, // this is in btc
226
+ collateralPrice: number,
227
+ isDeposit: boolean
228
+ ) => {
229
+ try {
230
+ // => X = (((collateral + legDepositAmount) * collateralPrice * ltv) - (debt * debtPrice * target hf)) / (target hf - ltv)
231
+ const marginAmount = addedAmount.multipliedBy(isDeposit ? 1 : -1);
232
+ const numerator1 = collateralAmount
233
+ .plus(addedAmount)
234
+ .multipliedBy(collateralPrice)
235
+ .multipliedBy(maxLtv);
236
+ const numerator2 = debtAmount
237
+ .multipliedBy(debtPrice)
238
+ .multipliedBy(TARGET_HF);
239
+ const denominator = TARGET_HF - maxLtv;
240
+ const x_debt_usd = numerator1.minus(numerator2).dividedBy(denominator);
241
+ let deltadebtAmountUnits = new Web3Number(
242
+ x_debt_usd.dividedBy(debtPrice).toFixed(2),
243
+ 2
244
+ );
245
+ let isIncrease = x_debt_usd.greaterThan(0);
246
+ return { deltadebtAmountUnits, isIncrease };
247
+ } catch (err) {
248
+ return { deltadebtAmountUnits: null, isIncrease: null };
249
+ }
250
+ };
251
+
252
+ /**
253
+ * calculate the debt amount to be repaid for withdrawal
254
+ * @param debtAmount in debt units
255
+ * @param collateralAmount in collateral units
256
+ * @param maxLtv in percentage
257
+ * @param withdrawalAmount in collateral units
258
+ * @param collateralPrice in usd
259
+ * @param debtPrice in usd
260
+ * @returns deltadebtAmountUnits in debt units
261
+ * isIncrease: true if the debt amount is increasing, false if it is decreasing
262
+ */
263
+ export const calculateDebtReductionAmountForWithdrawal = (
264
+ debtAmount: Web3Number,
265
+ collateralAmount: Web3Number,
266
+ maxLtv: number = MAX_LTV_BTC_USDC,
267
+ withdrawalAmount: Web3Number,
268
+ collateralPrice: number,
269
+ debtPrice: number,
270
+ usdcDecimals: number
271
+ ) => {
272
+ try {
273
+ const vesuLeverage = calculateVesuLeverage();
274
+ const numerator1 = collateralAmount
275
+ .multipliedBy(collateralPrice)
276
+ .multipliedBy(maxLtv)
277
+ .multipliedBy(-1);
278
+ withdrawalAmount = withdrawalAmount.multipliedBy(vesuLeverage);
279
+ const numerator2 = debtAmount
280
+ .multipliedBy(debtPrice)
281
+ .multipliedBy(TARGET_HF);
282
+ const numerator3 = withdrawalAmount
283
+ .multipliedBy(collateralPrice)
284
+ .multipliedBy(maxLtv);
285
+ const numeratorTotal = numerator1.plus(numerator2).plus(numerator3);
286
+ const denominator = debtPrice * TARGET_HF;
287
+ const x_debt_usdc = numeratorTotal.dividedBy(denominator);
288
+ let deltadebtAmountUnits = x_debt_usdc
289
+ .multipliedBy(-1)
290
+ .toFixed(usdcDecimals); // means we are paying debt
291
+ return { deltadebtAmountUnits };
292
+ } catch (err) {
293
+ return { deltadebtAmountUnits: null };
294
+ }
295
+ };
296
+
297
+ /**
298
+ * calculate the amount to deposit on extended when incurring losses
299
+ * @param client - The client
300
+ * @returns The amount to deposit on extended when incurring losses
301
+ */
302
+ export const calculateAmountDepositOnExtendedWhenIncurringLosses = async (
303
+ client: ExtendedWrapper
304
+ ) => {
305
+ try {
306
+ const extendedHoldings = await client.getHoldings();
307
+ const extended_leverage = calculateExtendedLevergae();
308
+ const latestPosition = (await client.getPositions()).data.pop();
309
+ console.log("the latest position is", latestPosition, extendedHoldings);
310
+ if (!extendedHoldings || !latestPosition) {
311
+ logger.error(`error getting extended position: extendedHoldings=${extendedHoldings}, latestPosition=${latestPosition}`);
312
+ return null;
313
+ }
314
+ const positionValueInUSD = latestPosition.value;
315
+ const equity = extendedHoldings.data.equity;
316
+ const deposit =
317
+ Number(positionValueInUSD) / extended_leverage - Number(equity);
318
+ return new Web3Number(Math.floor(deposit / 0.2) * 0.2, USDC_TOKEN_DECIMALS);
319
+ } catch (err) {
320
+ return null;
321
+ }
322
+ };
323
+
324
+ export const calculateExposureDelta = (
325
+ exposure_extended: number,
326
+ exposure_vesu: number
327
+ ) => {
328
+ const exposure_delta = new Web3Number(exposure_extended - exposure_vesu, 2);
329
+ return exposure_delta.absoluteValue().toNumber();
330
+ };
331
+
332
+ /// In case BTC PRICE DROPS
333
+ // 1. calculate the ltv on vesu
334
+ // 2. Find the debt that needs to be paid to maintain the ltv
335
+
336
+ /**
337
+ * calculate the delta percentage between the current btc price and the last btc price
338
+ * @param {number} btcPrice - The current btc price
339
+ * @param {number} lastBtcPrice - The last btc price
340
+ * @returns {number} The delta percentage
341
+ */
342
+ export const calculateBTCPriceDelta = (
343
+ btcPrice: number,
344
+ lastBtcPrice: number
345
+ ) => {
346
+ return ((btcPrice - lastBtcPrice) / lastBtcPrice) * 100;
347
+ };
348
+
349
+ export const calculateVesUPositionSizeGivenExtended = (
350
+ extendedPositonValue: number,
351
+ extendedHoldingAmount: Web3Number,
352
+ collateralAmount: Web3Number,
353
+ collateralPrice: number
354
+ ) => {
355
+ const extendedLeverage = calculateExtendedLevergae();
356
+ const vesuLeverage = calculateVesuLeverage();
357
+ const extendedAmount = extendedHoldingAmount;
358
+ const extendedAmountInBTC = extendedAmount
359
+ .dividedBy(collateralPrice)
360
+ const numerator1 = extendedAmount.multipliedBy(extendedLeverage)
361
+ .plus(extendedPositonValue)
362
+ const numerator2 = collateralAmount
363
+ .multipliedBy(collateralPrice)
364
+ .multipliedBy(-1);
365
+ const vesuAmountInUsd = numerator1.plus(numerator2).dividedBy(vesuLeverage);
366
+ const vesuAmountInBTC = vesuAmountInUsd
367
+ .dividedBy(collateralPrice)
368
+ .toFixed(WBTC_TOKEN_DECIMALS);
369
+ return {
370
+ vesuAmountInUsd: vesuAmountInUsd.toFixed(2),
371
+ vesuAmountInBTC: new Web3Number(vesuAmountInBTC, WBTC_TOKEN_DECIMALS),
372
+ extendedAmountInBTC: extendedAmountInBTC,
373
+ };
374
+ };