@strkfarm/sdk 2.0.0-dev.27 → 2.0.0-dev.28
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/dist/cli.js +190 -36
- package/dist/cli.mjs +188 -34
- package/dist/index.browser.global.js +79130 -49357
- package/dist/index.browser.mjs +18039 -11434
- package/dist/index.d.ts +2869 -898
- package/dist/index.js +19036 -12210
- package/dist/index.mjs +18942 -12161
- package/package.json +1 -1
- package/src/data/avnu.abi.json +840 -0
- package/src/data/ekubo-price-fethcer.abi.json +265 -0
- package/src/dataTypes/_bignumber.ts +13 -4
- package/src/dataTypes/index.ts +3 -2
- package/src/dataTypes/mynumber.ts +141 -0
- package/src/global.ts +76 -41
- package/src/index.browser.ts +2 -1
- package/src/interfaces/common.tsx +167 -2
- package/src/modules/ExtendedWrapperSDk/types.ts +26 -4
- package/src/modules/ExtendedWrapperSDk/wrapper.ts +110 -67
- package/src/modules/apollo-client-config.ts +28 -0
- package/src/modules/avnu.ts +4 -4
- package/src/modules/ekubo-pricer.ts +79 -0
- package/src/modules/ekubo-quoter.ts +46 -30
- package/src/modules/erc20.ts +17 -0
- package/src/modules/harvests.ts +43 -29
- package/src/modules/pragma.ts +23 -8
- package/src/modules/pricer-from-api.ts +156 -15
- package/src/modules/pricer-lst.ts +1 -1
- package/src/modules/pricer.ts +40 -4
- package/src/modules/pricerBase.ts +2 -1
- package/src/node/deployer.ts +36 -1
- package/src/node/pricer-redis.ts +2 -1
- package/src/strategies/base-strategy.ts +78 -10
- package/src/strategies/ekubo-cl-vault.tsx +906 -347
- package/src/strategies/factory.ts +159 -0
- package/src/strategies/index.ts +6 -1
- package/src/strategies/registry.ts +239 -0
- package/src/strategies/sensei.ts +335 -7
- package/src/strategies/svk-strategy.ts +97 -27
- package/src/strategies/types.ts +4 -0
- package/src/strategies/universal-adapters/adapter-utils.ts +2 -1
- package/src/strategies/universal-adapters/avnu-adapter.ts +177 -268
- package/src/strategies/universal-adapters/baseAdapter.ts +263 -251
- package/src/strategies/universal-adapters/common-adapter.ts +206 -203
- package/src/strategies/universal-adapters/extended-adapter.ts +155 -336
- package/src/strategies/universal-adapters/index.ts +9 -8
- package/src/strategies/universal-adapters/token-transfer-adapter.ts +200 -0
- package/src/strategies/universal-adapters/usdc<>usdce-adapter.ts +200 -0
- package/src/strategies/universal-adapters/vesu-adapter.ts +110 -75
- package/src/strategies/universal-adapters/vesu-modify-position-adapter.ts +476 -0
- package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +762 -844
- package/src/strategies/universal-adapters/vesu-position-common.ts +251 -0
- package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +18 -3
- package/src/strategies/universal-lst-muliplier-strategy.tsx +396 -204
- package/src/strategies/universal-strategy.tsx +1426 -1178
- package/src/strategies/vesu-extended-strategy/services/executionService.ts +2251 -0
- package/src/strategies/vesu-extended-strategy/services/extended-vesu-state-manager.ts +2941 -0
- package/src/strategies/vesu-extended-strategy/services/operationService.ts +12 -1
- package/src/strategies/vesu-extended-strategy/types/transaction-metadata.ts +52 -0
- package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +1 -0
- package/src/strategies/vesu-extended-strategy/utils/constants.ts +2 -0
- package/src/strategies/vesu-extended-strategy/utils/helper.ts +158 -124
- package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +377 -1788
- package/src/strategies/vesu-rebalance.tsx +255 -152
- package/src/utils/health-factor-math.ts +4 -1
- package/src/utils/index.ts +2 -1
- package/src/utils/logger.browser.ts +22 -4
- package/src/utils/logger.node.ts +259 -24
- package/src/utils/starknet-call-parser.ts +1036 -0
- package/src/utils/strategy-utils.ts +61 -0
- package/src/strategies/universal-adapters/unused-balance-adapter.ts +0 -109
|
@@ -2,9 +2,19 @@ import { Web3Number } from "@/dataTypes";
|
|
|
2
2
|
import { ExtendedAdapter } from "@/strategies/universal-adapters/extended-adapter";
|
|
3
3
|
import { VesuMultiplyAdapter } from "../../universal-adapters/vesu-multiply-adapter";
|
|
4
4
|
import { CycleType, TransactionResult } from "../types/transaction-metadata";
|
|
5
|
-
|
|
5
|
+
import { UsdcToUsdceAdapter } from "@/strategies/universal-adapters/usdc<>usdce-adapter";
|
|
6
|
+
import { AssetMovementPlan } from "../vesu-extended-strategy";
|
|
6
7
|
export abstract class Operations {
|
|
7
8
|
|
|
9
|
+
abstract computeAssetMovements(
|
|
10
|
+
extendedAmount: Web3Number,
|
|
11
|
+
vesuAmount: Web3Number
|
|
12
|
+
): Promise<AssetMovementPlan | null>;
|
|
13
|
+
|
|
14
|
+
abstract executeAssetMovements(
|
|
15
|
+
plan: AssetMovementPlan
|
|
16
|
+
): Promise<TransactionResult[]>;
|
|
17
|
+
|
|
8
18
|
abstract shouldMoveAssets(
|
|
9
19
|
extendedAmount: Web3Number,
|
|
10
20
|
vesuAmount: Web3Number
|
|
@@ -28,6 +38,7 @@ export abstract class Operations {
|
|
|
28
38
|
params: { from: string; to: string; amount: Web3Number, cycleType: CycleType },
|
|
29
39
|
extendedAdapter: ExtendedAdapter,
|
|
30
40
|
vesuAdapter: VesuMultiplyAdapter,
|
|
41
|
+
usdcToUsdceAdapter: UsdcToUsdceAdapter,
|
|
31
42
|
): Promise<TransactionResult>;
|
|
32
43
|
/**
|
|
33
44
|
* Handle deposit operation.
|
|
@@ -32,5 +32,57 @@ export interface TransactionResult<T = any> {
|
|
|
32
32
|
transactionMetadata: TransactionMetadata;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
// ─── Execution Lifecycle Events ─────────────────────────────────────────────
|
|
35
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Key lifecycle event types emitted during execution.
|
|
39
|
+
* Used by callers (e.g. risk engine) to hook into the execution pipeline
|
|
40
|
+
* and persist state to DB, send alerts, etc.
|
|
41
|
+
*/
|
|
42
|
+
export enum ExecutionEventType {
|
|
43
|
+
/** Execution started — tx sent on-chain or order placed on exchange */
|
|
44
|
+
INITIATED = 'INITIATED',
|
|
45
|
+
/** Execution completed successfully — tx confirmed / order filled */
|
|
46
|
+
SUCCESS = 'SUCCESS',
|
|
47
|
+
/** Execution failed — tx reverted / order rejected / timeout */
|
|
48
|
+
FAILURE = 'FAILURE',
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Metadata payload accompanying each execution lifecycle event.
|
|
53
|
+
* Contains relevant identifiers, prices, and contextual information.
|
|
54
|
+
*/
|
|
55
|
+
export interface ExecutionEventMetadata {
|
|
56
|
+
/** Route type string (e.g. RouteType value) */
|
|
57
|
+
routeType?: string;
|
|
58
|
+
/** Human-readable route summary */
|
|
59
|
+
routeSummary?: string;
|
|
60
|
+
/** On-chain transaction hash (when available) */
|
|
61
|
+
txHash?: string;
|
|
62
|
+
/** Exchange order ID (for off-chain orders) */
|
|
63
|
+
orderId?: string;
|
|
64
|
+
/** Amount involved in the operation */
|
|
65
|
+
amount?: string;
|
|
66
|
+
/** Protocol name */
|
|
67
|
+
protocol?: string;
|
|
68
|
+
/** Actual execution price (for exchange orders) */
|
|
69
|
+
executionPrice?: number;
|
|
70
|
+
/** Limit price that was set */
|
|
71
|
+
limitPrice?: number;
|
|
72
|
+
/** Error message on failure */
|
|
73
|
+
error?: string;
|
|
74
|
+
/** On-chain calls that were built */
|
|
75
|
+
calls?: Call[];
|
|
76
|
+
/** Extensible: any extra metadata */
|
|
77
|
+
[key: string]: any;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Callback invoked on key execution lifecycle events.
|
|
82
|
+
* Callers can use this to save to DB, send notifications, log, etc.
|
|
83
|
+
*/
|
|
84
|
+
export type ExecutionCallback = (
|
|
85
|
+
eventType: ExecutionEventType,
|
|
86
|
+
metadata: ExecutionEventMetadata,
|
|
87
|
+
) => void | Promise<void>;
|
|
36
88
|
|
|
@@ -18,6 +18,8 @@ export const STRK_API_RPC = process.env.STRK_API_RPC ?? "https://mainnet.starkne
|
|
|
18
18
|
export const MAX_RETRIES = Number(process.env.MAX_RETRIES ?? 3);
|
|
19
19
|
export const MAX_DELAY = Number(process.env.MAX_DELAY ?? 100);
|
|
20
20
|
export const EXTEND_MARKET_NAME = "BTC-USD";
|
|
21
|
+
|
|
22
|
+
// factor of balance to keep as buffer (0.05 = 5%)
|
|
21
23
|
export const LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ?? 0.05);
|
|
22
24
|
export const LIMIT_BALANCE_VALUE=20;
|
|
23
25
|
export const REBALANCER_INTERVAL = Number(process.env.REBALANCER_INTERVAL ?? 180000); //3 mins
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
USDC_TOKEN_DECIMALS,
|
|
10
10
|
MAX_LIQUIDATION_RATIO,
|
|
11
11
|
} from "./constants";
|
|
12
|
+
import { VesuConfig } from "./config.runtime";
|
|
12
13
|
import { ExtendedAdapter } from "../../universal-adapters/extended-adapter";
|
|
13
14
|
import { Balance } from "@/modules/ExtendedWrapperSDk";
|
|
14
15
|
import { Web3Number } from "@/dataTypes";
|
|
@@ -16,6 +17,7 @@ import { Position } from "@/modules/ExtendedWrapperSDk";
|
|
|
16
17
|
// import { getAllOpenPositionsExtended } from "../services/extendedService";
|
|
17
18
|
import ExtendedWrapper from "@/modules/ExtendedWrapperSDk";
|
|
18
19
|
import { logger } from "@/utils";
|
|
20
|
+
import { HealthFactorMath } from "@/utils/health-factor-math";
|
|
19
21
|
// import {
|
|
20
22
|
// calculatePositionOnVesu,
|
|
21
23
|
// getAssetPrice,
|
|
@@ -29,7 +31,7 @@ import { logger } from "@/utils";
|
|
|
29
31
|
*/
|
|
30
32
|
export const returnFormattedAmount = (
|
|
31
33
|
amount: number,
|
|
32
|
-
toTokenDecimals: number
|
|
34
|
+
toTokenDecimals: number,
|
|
33
35
|
) => {
|
|
34
36
|
const formattedAmount =
|
|
35
37
|
"0x" + BigInt(Math.floor(amount * 10 ** toTokenDecimals)).toString(16);
|
|
@@ -37,67 +39,63 @@ export const returnFormattedAmount = (
|
|
|
37
39
|
};
|
|
38
40
|
|
|
39
41
|
/**
|
|
40
|
-
* calculates the amount to distribute to
|
|
42
|
+
* calculates the amount to distribute to Extended and Vesu
|
|
41
43
|
* Determines how much to allocate to each platform based on leverage calculations
|
|
42
44
|
* @param {number} amount - The total amount to distribute
|
|
43
45
|
* @returns {object} Object containing avnu_amount, extended_amount, and extended_leverage
|
|
44
46
|
*/
|
|
45
|
-
export const calculateAmountDistribution =
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
extended_leverage: number;
|
|
57
|
-
vesu_leverage: number;
|
|
58
|
-
}> => {
|
|
47
|
+
export const calculateAmountDistribution = (
|
|
48
|
+
amountToInvest: number,
|
|
49
|
+
collateralPrice: number, // in usd
|
|
50
|
+
collateralUnits: Web3Number, // existing collateral in vesu (e.g. BTC)
|
|
51
|
+
extendedExposureUsd: Web3Number,
|
|
52
|
+
): {
|
|
53
|
+
vesuAmount: Web3Number;
|
|
54
|
+
extendedAmount: Web3Number;
|
|
55
|
+
extendedLeverage: number;
|
|
56
|
+
vesuLeverage: number;
|
|
57
|
+
} => {
|
|
59
58
|
try {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
: new Web3Number(0, WBTC_TOKEN_DECIMALS);
|
|
59
|
+
/**
|
|
60
|
+
* Logic: Match the newly created total exposure in USD on both sides
|
|
61
|
+
* New Vesu exposure = VesuAmount * vesuLeverage
|
|
62
|
+
* New Extended exposure = ExtendedAmount * extendedLeverage
|
|
63
|
+
* VesuAmount + ExtendedAmount = amountToInvest
|
|
64
|
+
* ExtendedAmount * extendedleverage = (amountToInvest - ExtendedAmount) * vesuLeverage
|
|
65
|
+
* ExtendedAmount * (extendedleverage + vesuLeverage) = amountToInvest * vesuLeverage
|
|
66
|
+
* ExtendedAmount = amountToInvest * vesuLeverage / (extendedleverage + vesuLeverage)
|
|
67
|
+
* VesuAmount = amountToInvest - ExtendedAmount
|
|
68
|
+
* @dev note: below cal includes existing exposures too
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
const extendedLeverage = calculateExtendedLevergae();
|
|
72
|
+
const vesuLeverage = calculateVesuLeverage();
|
|
75
73
|
const vesuBTCExposureUSD = collateralUnits.multipliedBy(collateralPrice);
|
|
76
|
-
const numerator1 =
|
|
77
|
-
const numerator2 =
|
|
78
|
-
const denominator =
|
|
74
|
+
const numerator1 = vesuLeverage * amountToInvest + vesuBTCExposureUSD.toNumber();
|
|
75
|
+
const numerator2 = extendedExposureUsd.toNumber();
|
|
76
|
+
const denominator = vesuLeverage + extendedLeverage;
|
|
79
77
|
const ExtendedAmount = new Web3Number(
|
|
80
78
|
((numerator1 - numerator2) / denominator).toFixed(2),
|
|
81
|
-
USDC_TOKEN_DECIMALS
|
|
79
|
+
USDC_TOKEN_DECIMALS,
|
|
82
80
|
);
|
|
83
81
|
|
|
84
82
|
const VesuAmount = new Web3Number(
|
|
85
|
-
|
|
86
|
-
USDC_TOKEN_DECIMALS
|
|
83
|
+
amountToInvest.toFixed(2),
|
|
84
|
+
USDC_TOKEN_DECIMALS,
|
|
87
85
|
).minus(ExtendedAmount);
|
|
88
86
|
|
|
89
87
|
return {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
88
|
+
vesuAmount: VesuAmount,
|
|
89
|
+
extendedAmount: ExtendedAmount,
|
|
90
|
+
extendedLeverage,
|
|
91
|
+
vesuLeverage,
|
|
94
92
|
};
|
|
95
93
|
} catch (err) {
|
|
96
94
|
return {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
95
|
+
vesuAmount: new Web3Number(0, 0),
|
|
96
|
+
extendedAmount: new Web3Number(0, 0),
|
|
97
|
+
extendedLeverage: 0,
|
|
98
|
+
vesuLeverage: 0,
|
|
101
99
|
};
|
|
102
100
|
}
|
|
103
101
|
};
|
|
@@ -113,7 +111,7 @@ export const calculateAmountDistributionForWithdrawal = async (
|
|
|
113
111
|
amountInUsdc: Web3Number,
|
|
114
112
|
collateralPrice: number,
|
|
115
113
|
collateralUnits: Web3Number,
|
|
116
|
-
extendedPosition: Position[] | null
|
|
114
|
+
extendedPosition: Position[] | null,
|
|
117
115
|
): Promise<{
|
|
118
116
|
vesu_amount: Web3Number;
|
|
119
117
|
extended_amount: Web3Number;
|
|
@@ -148,23 +146,20 @@ export const calculateAmountDistributionForWithdrawal = async (
|
|
|
148
146
|
vesu_leverage,
|
|
149
147
|
};
|
|
150
148
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
149
|
+
logger.debug(`calculateAmountDistributionForWithdrawal vesuExposureUsd=${vesuExposureUSD.toNumber()}`);
|
|
150
|
+
logger.debug(`calculateAmountDistributionForWithdrawal extendedExposureUsd=${extendedExposureUSD.toNumber()}`);
|
|
151
|
+
logger.debug(`calculateAmountDistributionForWithdrawal amountInUsdc=${amountInUsdc.toNumber()}`);
|
|
152
|
+
logger.debug(`calculateAmountDistributionForWithdrawal extendedLeverage=${extended_leverage}`);
|
|
153
|
+
logger.debug(`calculateAmountDistributionForWithdrawal vesuLeverage=${vesu_leverage}`);
|
|
156
154
|
const numerator1 = amountInUsdc.multipliedBy(extended_leverage);
|
|
157
155
|
const numerator2 = vesuExposureUSD;
|
|
158
156
|
const numerator3 = extendedExposureUSD.multipliedBy(-1);
|
|
159
157
|
const finalNumerator = numerator1.plus(numerator2).plus(numerator3);
|
|
160
158
|
const denominator = extended_leverage + vesu_leverage;
|
|
161
159
|
const vesuAmountInUSDC = finalNumerator.dividedBy(denominator);
|
|
162
|
-
|
|
160
|
+
logger.debug(`calculateAmountDistributionForWithdrawal vesuAmountInUsdc=${vesuAmountInUSDC.toNumber()}`);
|
|
163
161
|
const extendedAmountInUSDC = amountInUsdc.minus(vesuAmountInUSDC);
|
|
164
|
-
|
|
165
|
-
"the extended amount in usdc is",
|
|
166
|
-
extendedAmountInUSDC.toNumber()
|
|
167
|
-
);
|
|
162
|
+
logger.debug(`calculateAmountDistributionForWithdrawal extendedAmountInUsdc=${extendedAmountInUSDC.toNumber()}`);
|
|
168
163
|
//console.log("the vesu amount in usdc is", vesuAmountInUSDC.toNumber());
|
|
169
164
|
//console.log("the extended amount in usdc is", extendedAmountInUSDC.toNumber());\
|
|
170
165
|
await new Promise((resolve) => setTimeout(resolve, 10000));
|
|
@@ -176,7 +171,7 @@ export const calculateAmountDistributionForWithdrawal = async (
|
|
|
176
171
|
};
|
|
177
172
|
} catch (err) {
|
|
178
173
|
logger.error(
|
|
179
|
-
`error calculating amount distribution for withdrawal: ${err}
|
|
174
|
+
`error calculating amount distribution for withdrawal: ${err}`,
|
|
180
175
|
);
|
|
181
176
|
return null;
|
|
182
177
|
}
|
|
@@ -187,10 +182,10 @@ export const calculateAmountDistributionForWithdrawal = async (
|
|
|
187
182
|
* @returns {number} The calculated leverage value
|
|
188
183
|
*/
|
|
189
184
|
export const calculateVesuLeverage = () => {
|
|
190
|
-
const
|
|
191
|
-
const
|
|
192
|
-
const leverage =
|
|
193
|
-
return
|
|
185
|
+
const targetLtv = VesuConfig.targetLtv;
|
|
186
|
+
const debtBorrowed = targetLtv / (1 - targetLtv);
|
|
187
|
+
const leverage = (1 + debtBorrowed);
|
|
188
|
+
return leverage;
|
|
194
189
|
};
|
|
195
190
|
|
|
196
191
|
/**
|
|
@@ -217,32 +212,44 @@ export const calculateExtendedLevergae = () => {
|
|
|
217
212
|
* @returns {object} Object containing deltadebtAmountUnits and isIncrease flag
|
|
218
213
|
*/
|
|
219
214
|
// 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
|
|
215
|
+
|
|
220
216
|
export const calculateDebtAmount = (
|
|
221
217
|
collateralAmount: Web3Number,
|
|
222
218
|
debtAmount: Web3Number,
|
|
223
219
|
debtPrice: number,
|
|
224
|
-
maxLtv: number =
|
|
220
|
+
maxLtv: number = VesuConfig.maxLtv,
|
|
225
221
|
addedAmount: Web3Number, // this is in btc
|
|
226
222
|
collateralPrice: number,
|
|
227
|
-
isDeposit: boolean
|
|
223
|
+
isDeposit: boolean,
|
|
224
|
+
targetLtv: number = VesuConfig.targetLtv,
|
|
228
225
|
) => {
|
|
229
226
|
try {
|
|
230
227
|
// => X = (((collateral + legDepositAmount) * collateralPrice * ltv) - (debt * debtPrice * target hf)) / (target hf - ltv)
|
|
228
|
+
logger.debug(`calculateDebtAmount maxLtv=${maxLtv}, collateralAmount=${collateralAmount.toNumber()}`);
|
|
229
|
+
logger.debug(`calculateDebtAmount targetLtv=${targetLtv}, debtAmount=${debtAmount.toNumber()}`);
|
|
230
|
+
|
|
231
|
+
const targetHf = VesuConfig.maxLtv / targetLtv;
|
|
232
|
+
logger.debug(`calculateDebtAmount targetHf=${targetHf}`);
|
|
231
233
|
const addedCollateral = addedAmount.multipliedBy(isDeposit ? 1 : -1);
|
|
234
|
+
logger.debug(`calculateDebtAmount addedCollateral=${addedCollateral.toNumber()}, collateralPrice=${collateralPrice}`);
|
|
232
235
|
const numerator1 = collateralAmount
|
|
233
236
|
.plus(addedCollateral)
|
|
234
237
|
.multipliedBy(collateralPrice)
|
|
235
238
|
.multipliedBy(maxLtv);
|
|
239
|
+
logger.debug(`calculateDebtAmount numerator1=${numerator1.toNumber()}`);
|
|
236
240
|
const numerator2 = debtAmount
|
|
237
241
|
.multipliedBy(debtPrice)
|
|
238
|
-
.multipliedBy(
|
|
239
|
-
|
|
242
|
+
.multipliedBy(targetHf);
|
|
243
|
+
logger.debug(`calculateDebtAmount numerator2=${numerator2.toNumber()}`);
|
|
244
|
+
const denominator = targetHf - maxLtv;
|
|
245
|
+
logger.debug(`calculateDebtAmount denominator=${denominator}`);
|
|
240
246
|
const x_debt_usd = numerator1.minus(numerator2).dividedBy(denominator);
|
|
241
|
-
|
|
247
|
+
logger.debug(`calculateDebtAmount xDebtUsd=${x_debt_usd.toNumber()}`);
|
|
248
|
+
const deltadebtAmountUnits = new Web3Number(
|
|
242
249
|
x_debt_usd.dividedBy(debtPrice).toFixed(2),
|
|
243
|
-
2
|
|
250
|
+
2,
|
|
244
251
|
);
|
|
245
|
-
|
|
252
|
+
const isIncrease = x_debt_usd.greaterThan(0);
|
|
246
253
|
return { deltadebtAmountUnits, isIncrease };
|
|
247
254
|
} catch (err) {
|
|
248
255
|
return { deltadebtAmountUnits: null, isIncrease: null };
|
|
@@ -267,7 +274,7 @@ export const calculateDebtReductionAmountForWithdrawal = (
|
|
|
267
274
|
withdrawalAmount: Web3Number,
|
|
268
275
|
collateralPrice: number,
|
|
269
276
|
debtPrice: number,
|
|
270
|
-
usdcDecimals: number
|
|
277
|
+
usdcDecimals: number,
|
|
271
278
|
) => {
|
|
272
279
|
try {
|
|
273
280
|
const vesuLeverage = calculateVesuLeverage();
|
|
@@ -294,13 +301,15 @@ export const calculateDebtReductionAmountForWithdrawal = (
|
|
|
294
301
|
}
|
|
295
302
|
};
|
|
296
303
|
|
|
304
|
+
|
|
305
|
+
// ! required?
|
|
297
306
|
/**
|
|
298
307
|
* calculate the amount to deposit on extended when incurring losses
|
|
299
308
|
* @param client - The client
|
|
300
309
|
* @returns The amount to deposit on extended when incurring losses
|
|
301
310
|
*/
|
|
302
311
|
export const calculateAmountDepositOnExtendedWhenIncurringLosses = async (
|
|
303
|
-
client: ExtendedWrapper
|
|
312
|
+
client: ExtendedWrapper,
|
|
304
313
|
) => {
|
|
305
314
|
try {
|
|
306
315
|
const extendedHoldings = await client.getHoldings();
|
|
@@ -308,13 +317,13 @@ export const calculateAmountDepositOnExtendedWhenIncurringLosses = async (
|
|
|
308
317
|
const latestPosition = (await client.getPositions()).data.pop();
|
|
309
318
|
if (!extendedHoldings || !latestPosition) {
|
|
310
319
|
logger.error(
|
|
311
|
-
`error getting extended position: extendedHoldings=${extendedHoldings}, latestPosition=${latestPosition}
|
|
320
|
+
`error getting extended position: extendedHoldings=${extendedHoldings}, latestPosition=${latestPosition}`,
|
|
312
321
|
);
|
|
313
322
|
return null;
|
|
314
323
|
}
|
|
315
324
|
const positionValueInUSD = new Web3Number(
|
|
316
325
|
latestPosition.value,
|
|
317
|
-
USDC_TOKEN_DECIMALS
|
|
326
|
+
USDC_TOKEN_DECIMALS,
|
|
318
327
|
);
|
|
319
328
|
const equity = extendedHoldings.data.equity;
|
|
320
329
|
const deposit = positionValueInUSD
|
|
@@ -324,7 +333,7 @@ export const calculateAmountDepositOnExtendedWhenIncurringLosses = async (
|
|
|
324
333
|
return new Web3Number(deposit, USDC_TOKEN_DECIMALS);
|
|
325
334
|
} catch (err) {
|
|
326
335
|
logger.error(
|
|
327
|
-
`error calculating amount deposit on extended when incurring losses: ${err}
|
|
336
|
+
`error calculating amount deposit on extended when incurring losses: ${err}`,
|
|
328
337
|
);
|
|
329
338
|
return null;
|
|
330
339
|
}
|
|
@@ -349,15 +358,15 @@ export const calculateWBTCAmountToMaintainLTV = (
|
|
|
349
358
|
debtPrice: number,
|
|
350
359
|
maxLtv: number = MAX_LIQUIDATION_RATIO,
|
|
351
360
|
collateralPrice: number,
|
|
352
|
-
targetHF: number = TARGET_HF
|
|
353
361
|
) => {
|
|
354
362
|
try {
|
|
363
|
+
const targetHf = VesuConfig.maxLtv / VesuConfig.targetLtv;
|
|
355
364
|
const numerator1 = collateralAmount
|
|
356
365
|
.multipliedBy(collateralPrice)
|
|
357
366
|
.multipliedBy(maxLtv);
|
|
358
367
|
const numerator2 = debtAmount
|
|
359
368
|
.multipliedBy(debtPrice)
|
|
360
|
-
.multipliedBy(
|
|
369
|
+
.multipliedBy(targetHf);
|
|
361
370
|
const denominator = maxLtv;
|
|
362
371
|
const collateralAmountToMaintainLTV = numerator2
|
|
363
372
|
.minus(numerator1)
|
|
@@ -366,7 +375,7 @@ export const calculateWBTCAmountToMaintainLTV = (
|
|
|
366
375
|
collateralAmountToMaintainLTV
|
|
367
376
|
.dividedBy(collateralPrice)
|
|
368
377
|
.toFixed(WBTC_TOKEN_DECIMALS),
|
|
369
|
-
WBTC_TOKEN_DECIMALS
|
|
378
|
+
WBTC_TOKEN_DECIMALS,
|
|
370
379
|
);
|
|
371
380
|
return { deltaCollateralAmountUnits };
|
|
372
381
|
} catch (err) {
|
|
@@ -374,18 +383,17 @@ export const calculateWBTCAmountToMaintainLTV = (
|
|
|
374
383
|
}
|
|
375
384
|
};
|
|
376
385
|
|
|
386
|
+
// ! required?
|
|
377
387
|
export const calculateExposureDelta = (
|
|
378
388
|
exposure_extended: number,
|
|
379
|
-
exposure_vesu: number
|
|
389
|
+
exposure_vesu: number,
|
|
380
390
|
) => {
|
|
381
391
|
const exposure_delta = new Web3Number(exposure_extended - exposure_vesu, 2);
|
|
382
392
|
return exposure_delta.absoluteValue().toNumber();
|
|
383
393
|
};
|
|
384
394
|
|
|
385
|
-
/// In case BTC PRICE DROPS
|
|
386
|
-
// 1. calculate the ltv on vesu
|
|
387
|
-
// 2. Find the debt that needs to be paid to maintain the ltv
|
|
388
395
|
|
|
396
|
+
// ! required?
|
|
389
397
|
/**
|
|
390
398
|
* calculate the delta percentage between the current btc price and the last btc price
|
|
391
399
|
* @param {number} btcPrice - The current btc price
|
|
@@ -394,36 +402,34 @@ export const calculateExposureDelta = (
|
|
|
394
402
|
*/
|
|
395
403
|
export const calculateBTCPriceDelta = (
|
|
396
404
|
btcPrice: number,
|
|
397
|
-
lastBtcPrice: number
|
|
405
|
+
lastBtcPrice: number,
|
|
398
406
|
) => {
|
|
399
407
|
return ((btcPrice - lastBtcPrice) / lastBtcPrice) * 100;
|
|
400
408
|
};
|
|
401
409
|
|
|
402
410
|
export const calculateVesUPositionSizeGivenExtended = (
|
|
403
|
-
|
|
411
|
+
extendedPositonSize: number,
|
|
404
412
|
extendedHoldingAmount: Web3Number,
|
|
405
413
|
collateralAmount: Web3Number,
|
|
406
|
-
|
|
414
|
+
extendedBtcPrice: number,
|
|
407
415
|
) => {
|
|
408
416
|
const extendedLeverage = calculateExtendedLevergae();
|
|
409
417
|
const vesuLeverage = calculateVesuLeverage();
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
const
|
|
418
|
+
logger.debug(`calculateVesUPositionSizeGivenExtended extendedLeverage=${extendedLeverage}`);
|
|
419
|
+
logger.debug(`calculateVesUPositionSizeGivenExtended vesuLeverage=${vesuLeverage}`);
|
|
420
|
+
const extendedAmountInBTC = new Web3Number(extendedHoldingAmount.dividedBy(extendedBtcPrice).toFixed(WBTC_TOKEN_DECIMALS), WBTC_TOKEN_DECIMALS);
|
|
421
|
+
logger.debug(`calculateVesUPositionSizeGivenExtended extendedAmountInBTC=${extendedAmountInBTC.toNumber()}`);
|
|
422
|
+
const numerator1 = extendedAmountInBTC
|
|
413
423
|
.multipliedBy(extendedLeverage)
|
|
414
|
-
.plus(
|
|
424
|
+
.plus(extendedPositonSize);
|
|
425
|
+
logger.debug(`calculateVesUPositionSizeGivenExtended numerator1=${numerator1.toNumber()}`);
|
|
415
426
|
const numerator2 = collateralAmount
|
|
416
|
-
.multipliedBy(collateralPrice)
|
|
417
427
|
.multipliedBy(-1);
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
const vesuAmountInBTC = vesuAmountInUsd
|
|
422
|
-
.dividedBy(collateralPrice)
|
|
423
|
-
.toFixed(WBTC_TOKEN_DECIMALS);
|
|
428
|
+
logger.debug(`calculateVesUPositionSizeGivenExtended numerator2=${numerator2.toNumber()}`);
|
|
429
|
+
const vesuAmountInBTC = new Web3Number(numerator1.plus(numerator2).dividedBy(vesuLeverage).toFixed(WBTC_TOKEN_DECIMALS), WBTC_TOKEN_DECIMALS);
|
|
430
|
+
logger.debug(`calculateVesUPositionSizeGivenExtended vesuAmountInBTC=${vesuAmountInBTC.toNumber()}`);
|
|
424
431
|
return {
|
|
425
|
-
|
|
426
|
-
vesuAmountInBTC: new Web3Number(vesuAmountInBTC, WBTC_TOKEN_DECIMALS),
|
|
432
|
+
vesuAmountInBTC: vesuAmountInBTC,
|
|
427
433
|
extendedAmountInBTC: extendedAmountInBTC,
|
|
428
434
|
};
|
|
429
435
|
};
|
|
@@ -436,58 +442,86 @@ export const calculateVesUPositionSizeGivenExtended = (
|
|
|
436
442
|
* @param collateralPrice - The collateral price
|
|
437
443
|
* @param debtPrice - The debt price
|
|
438
444
|
* @param targetHf - The target hf
|
|
445
|
+
* @@dev returns negative to represent debt to be repaid
|
|
439
446
|
* @returns The debt amount to be repaid
|
|
440
447
|
*/
|
|
441
448
|
export const calculateDeltaDebtAmount = (
|
|
442
|
-
maxLtv: number = MAX_LTV_BTC_USDC,
|
|
443
449
|
existingVesuCollateral: Web3Number,
|
|
444
450
|
existingVesuDebt: Web3Number,
|
|
445
|
-
collateralPrice: number,
|
|
446
451
|
debtPrice: number,
|
|
447
|
-
|
|
452
|
+
collateralPrice: number,
|
|
448
453
|
) => {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
454
|
+
const currentHf = HealthFactorMath.getHealthFactor(
|
|
455
|
+
existingVesuCollateral,
|
|
456
|
+
collateralPrice,
|
|
457
|
+
VesuConfig.maxLtv,
|
|
458
|
+
existingVesuDebt,
|
|
459
|
+
debtPrice
|
|
460
|
+
);
|
|
461
|
+
const targetHf = VesuConfig.maxLtv / VesuConfig.targetLtv;
|
|
462
|
+
logger.debug(`calculateDeltaDebtAmount currentHf=${currentHf} targetHf=${targetHf}`);
|
|
453
463
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
464
|
+
const term1 = existingVesuCollateral
|
|
465
|
+
.multipliedBy(collateralPrice)
|
|
466
|
+
.multipliedBy(VesuConfig.maxLtv);
|
|
467
|
+
|
|
468
|
+
const term2 = existingVesuDebt
|
|
469
|
+
.multipliedBy(debtPrice)
|
|
470
|
+
.multipliedBy(targetHf)
|
|
471
|
+
.multipliedBy(-1);
|
|
472
|
+
const debtAmountToBeRepaid = term1.plus(term2).dividedBy(targetHf);
|
|
473
|
+
return {
|
|
474
|
+
deltaDebt: new Web3Number(
|
|
475
|
+
debtAmountToBeRepaid.toFixed(USDC_TOKEN_DECIMALS),
|
|
476
|
+
USDC_TOKEN_DECIMALS,
|
|
477
|
+
),
|
|
478
|
+
shouldRebalance: currentHf < (targetHf - 0.05),
|
|
466
479
|
}
|
|
467
480
|
};
|
|
468
481
|
|
|
469
482
|
export const calculatePositionToCloseToWithdrawAmount = async (
|
|
470
483
|
extendedBalance: Balance,
|
|
471
484
|
extendedPositions: Position,
|
|
472
|
-
amountToWithdraw: Web3Number
|
|
485
|
+
amountToWithdraw: Web3Number,
|
|
473
486
|
) => {
|
|
474
487
|
try {
|
|
475
488
|
const extendedLeverage = calculateExtendedLevergae();
|
|
476
489
|
const extendedPosition = extendedPositions.value;
|
|
477
|
-
const marginRequired = new Web3Number(
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
490
|
+
const marginRequired = new Web3Number(
|
|
491
|
+
extendedBalance.initialMargin,
|
|
492
|
+
USDC_TOKEN_DECIMALS,
|
|
493
|
+
);
|
|
494
|
+
const unrealisedPnl = new Web3Number(
|
|
495
|
+
extendedBalance.unrealisedPnl,
|
|
496
|
+
USDC_TOKEN_DECIMALS,
|
|
497
|
+
);
|
|
498
|
+
const availableForWithdrawal = new Web3Number(
|
|
499
|
+
extendedBalance.availableForWithdrawal,
|
|
500
|
+
USDC_TOKEN_DECIMALS,
|
|
501
|
+
);
|
|
502
|
+
const upnlPercent = unrealisedPnl.dividedBy(extendedPosition);
|
|
481
503
|
/**
|
|
482
504
|
* New Formula
|
|
483
505
|
*/
|
|
484
|
-
const walletBalance = new Web3Number(
|
|
485
|
-
|
|
506
|
+
const walletBalance = new Web3Number(
|
|
507
|
+
extendedBalance.balance,
|
|
508
|
+
USDC_TOKEN_DECIMALS,
|
|
509
|
+
);
|
|
510
|
+
const term1 = marginRequired
|
|
511
|
+
.minus(walletBalance)
|
|
512
|
+
.minus(availableForWithdrawal)
|
|
513
|
+
.plus(amountToWithdraw)
|
|
514
|
+
.multipliedBy(extendedLeverage);
|
|
486
515
|
const denominator = upnlPercent.multipliedBy(extendedLeverage).plus(1);
|
|
487
|
-
return new Web3Number(
|
|
516
|
+
return new Web3Number(
|
|
517
|
+
Math.ceil(
|
|
518
|
+
term1.dividedBy(denominator).dividedBy(extendedLeverage).toNumber(),
|
|
519
|
+
),
|
|
520
|
+
USDC_TOKEN_DECIMALS,
|
|
521
|
+
);
|
|
488
522
|
} catch (err) {
|
|
489
523
|
logger.error(
|
|
490
|
-
`error calculating position to close to withdraw amount: ${err}
|
|
524
|
+
`error calculating position to close to withdraw amount: ${err}`,
|
|
491
525
|
);
|
|
492
526
|
return new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
493
527
|
}
|