@strkfarm/sdk 1.1.9 → 1.1.11
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/index.browser.global.js +166 -24
- package/dist/index.browser.mjs +161 -18
- package/dist/index.d.ts +20 -4
- package/dist/index.js +160 -16
- package/dist/index.mjs +159 -16
- package/package.json +1 -1
- package/src/global.ts +10 -0
- package/src/interfaces/common.tsx +2 -1
- package/src/modules/index.ts +2 -1
- package/src/modules/pricer-from-api.ts +1 -1
- package/src/modules/pricer-lst.ts +66 -0
- package/src/modules/pricer.ts +1 -1
- package/src/strategies/ekubo-cl-vault.tsx +23 -0
- package/src/strategies/universal-lst-muliplier-strategy.tsx +70 -13
- package/src/strategies/universal-strategy.tsx +12 -4
package/src/global.ts
CHANGED
|
@@ -122,6 +122,16 @@ const defaultTokens: TokenInfo[] = [{
|
|
|
122
122
|
symbol: 'xtBTC',
|
|
123
123
|
logo: 'https://assets.strkfarm.com/integrations/tokens/xtbtc.svg',
|
|
124
124
|
address: ContractAddr.from('0x43a35c1425a0125ef8c171f1a75c6f31ef8648edcc8324b55ce1917db3f9b91'),
|
|
125
|
+
decimals: 18,
|
|
126
|
+
coingeckId: undefined,
|
|
127
|
+
displayDecimals: 6,
|
|
128
|
+
priceProxySymbol: 'WBTC',
|
|
129
|
+
priceCheckAmount: 0.0001, // 112000 * 0.0001 = $11.2
|
|
130
|
+
}, {
|
|
131
|
+
name: 'xLBTC',
|
|
132
|
+
symbol: 'xLBTC',
|
|
133
|
+
logo: 'https://assets.strkfarm.com/integrations/tokens/xlbtc.svg',
|
|
134
|
+
address: ContractAddr.from('0x036834a40984312f7f7de8d31e3f6305b325389eaeea5b1c0664b2fb936461a4'),
|
|
125
135
|
decimals: 8,
|
|
126
136
|
coingeckId: undefined,
|
|
127
137
|
displayDecimals: 6,
|
|
@@ -96,7 +96,8 @@ export interface IStrategyMetadata<T> {
|
|
|
96
96
|
points?: {multiplier: number, logo: string, toolTip?: string}[];
|
|
97
97
|
docs?: string;
|
|
98
98
|
investmentSteps: string[];
|
|
99
|
-
curator?: { name: string, logo: string }
|
|
99
|
+
curator?: { name: string, logo: string },
|
|
100
|
+
isPreview?: boolean
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
export interface IInvestmentFlow {
|
package/src/modules/index.ts
CHANGED
|
@@ -42,7 +42,7 @@ export class PricerFromApi extends PricerBase {
|
|
|
42
42
|
|
|
43
43
|
async getPriceFromMyAPI(tokenSymbol: string) {
|
|
44
44
|
logger.verbose(`getPrice from redis: ${tokenSymbol}`);
|
|
45
|
-
const endpoint = 'https://
|
|
45
|
+
const endpoint = 'https://cache-server-t2me.onrender.com'
|
|
46
46
|
const url = `${endpoint}/api/price/${tokenSymbol}`;
|
|
47
47
|
const priceInfoRes = await fetch(url);
|
|
48
48
|
const priceInfo = await priceInfoRes.json();
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { FatalError, PriceInfo, Pricer, Web3Number } from "@/index.browser";
|
|
2
|
+
import { PricerBase } from "./pricerBase";
|
|
3
|
+
import { IConfig, TokenInfo } from "@/interfaces";
|
|
4
|
+
import { logger } from "@/utils";
|
|
5
|
+
import axios from "axios";
|
|
6
|
+
|
|
7
|
+
export class PricerLST extends Pricer {
|
|
8
|
+
private tokenMaps: {lst: TokenInfo, underlying: TokenInfo}[];
|
|
9
|
+
protected EKUBO_API = 'https://quoter-mainnet-api.ekubo.org/{{AMOUNT}}/{{TOKEN_ADDRESS}}/{{UNDERLYING_ADDRESS}}'; // e.g. xSTRK/STRK
|
|
10
|
+
|
|
11
|
+
constructor(config: IConfig, tokenMaps: {lst: TokenInfo, underlying: TokenInfo}[]) {
|
|
12
|
+
const refreshInterval = 5000;
|
|
13
|
+
const staleTime = 60000;
|
|
14
|
+
const allTokens = tokenMaps.map(map => [map.lst, map.underlying]).flat();
|
|
15
|
+
super(config, allTokens, refreshInterval, staleTime);
|
|
16
|
+
this.tokenMaps = tokenMaps;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
isUnderlying(token: TokenInfo): boolean {
|
|
20
|
+
return this.tokenMaps.some(map => map.underlying.address.eq(token.address));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
getUnderlying(token: TokenInfo): TokenInfo {
|
|
24
|
+
return this.tokenMaps.find(map => map.lst.address.eq(token.address))!.underlying;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async _getPrice(token: TokenInfo, defaultMethod = 'all'): Promise<number> {
|
|
28
|
+
if (this.isUnderlying(token)) {
|
|
29
|
+
return 1; // underlying is always 1 relative to LST
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const methodToUse: string = this.methodToUse[token.symbol] || defaultMethod; // default start with coinbase
|
|
33
|
+
logger.verbose(`Fetching price of ${token.symbol} using ${methodToUse}`);
|
|
34
|
+
try {
|
|
35
|
+
const result = await this._getPriceEkubo(token, new Web3Number(token.priceCheckAmount ? token.priceCheckAmount : 1, token.decimals));
|
|
36
|
+
this.methodToUse[token.symbol] = 'Ekubo';
|
|
37
|
+
return result;
|
|
38
|
+
} catch (error: any) {
|
|
39
|
+
console.warn(`Ekubo: price err [${token.symbol}]: `, error.message);
|
|
40
|
+
console.warn(`Ekubo: price err [${token.symbol}]: `, Object.keys(error));
|
|
41
|
+
// do nothing, try next
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
throw new FatalError(`Price not found for ${token.symbol}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async _getPriceEkubo(token: TokenInfo, amountIn = new Web3Number(1, token.decimals), retry = 0): Promise<number> {
|
|
48
|
+
const underlying = this.getUnderlying(token);
|
|
49
|
+
const url = this.EKUBO_API
|
|
50
|
+
.replace("{{TOKEN_ADDRESS}}", token.address.toString())
|
|
51
|
+
.replace("{{AMOUNT}}", amountIn.toWei())
|
|
52
|
+
.replace("{{UNDERLYING_ADDRESS}}", underlying.address.toString());
|
|
53
|
+
const result = await axios.get(url);
|
|
54
|
+
const data: any = result.data;
|
|
55
|
+
const multiplier = 1 / amountIn.toNumber();
|
|
56
|
+
const outputUnderlying = Number(Web3Number.fromWei(data.total_calculated, underlying.decimals).toFixed(6)) * multiplier;
|
|
57
|
+
logger.verbose(`Ekubo: ${token.symbol} -> ${underlying.symbol}: ${outputUnderlying}, retry: ${retry}`);
|
|
58
|
+
if (outputUnderlying === 0 && retry < 3) {
|
|
59
|
+
// try again with a higher amount
|
|
60
|
+
const amountIn = new Web3Number(100, token.decimals); // 100 unit of token
|
|
61
|
+
return await this._getPriceEkubo(token, amountIn, retry + 1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return outputUnderlying;
|
|
65
|
+
}
|
|
66
|
+
}
|
package/src/modules/pricer.ts
CHANGED
|
@@ -21,7 +21,7 @@ export class Pricer extends PricerBase {
|
|
|
21
21
|
|
|
22
22
|
// code populates this map during runtime to determine which method to use for a given token
|
|
23
23
|
// The method set will be the first one to try after first attempt
|
|
24
|
-
|
|
24
|
+
protected methodToUse: {[tokenSymbol: string]: 'Ekubo' | 'Coinbase' | 'Coinmarketcap'} = {};
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* TOKENA and TOKENB are the two token names to get price of TokenA in terms of TokenB
|
|
@@ -1809,6 +1809,29 @@ const lstStrategies: IStrategyMetadata<CLVaultStrategySettings>[] = [
|
|
|
1809
1809
|
contractDetails: [],
|
|
1810
1810
|
investmentSteps: []
|
|
1811
1811
|
},
|
|
1812
|
+
{
|
|
1813
|
+
...xSTRKSTRK,
|
|
1814
|
+
name: "Ekubo xLBTC/LBTC",
|
|
1815
|
+
description: <></>,
|
|
1816
|
+
address: ContractAddr.from(
|
|
1817
|
+
"0x315a614603b1f702e466aedcbcb1ad97a77eb1192b8bd077e5154d4f2ee4fab"
|
|
1818
|
+
),
|
|
1819
|
+
launchBlock: 2344809,
|
|
1820
|
+
// must be same order as poolKey token0 and token1
|
|
1821
|
+
depositTokens: [
|
|
1822
|
+
Global.getDefaultTokens().find((t) => t.symbol === "LBTC")!,
|
|
1823
|
+
Global.getDefaultTokens().find((t) => t.symbol === "xLBTC")!,
|
|
1824
|
+
],
|
|
1825
|
+
additionalInfo: {
|
|
1826
|
+
...xSTRKSTRK.additionalInfo,
|
|
1827
|
+
quoteAsset: Global.getDefaultTokens().find((t) => t.symbol === "LBTC")!,
|
|
1828
|
+
lstContract: Global.getDefaultTokens().find((t) => t.symbol === "xLBTC")!.address,
|
|
1829
|
+
},
|
|
1830
|
+
faqs: getLSTFAQs("xLBTC"),
|
|
1831
|
+
points: [],
|
|
1832
|
+
contractDetails: [],
|
|
1833
|
+
investmentSteps: []
|
|
1834
|
+
}
|
|
1812
1835
|
];
|
|
1813
1836
|
|
|
1814
1837
|
const ETHUSDCRe7Strategy: IStrategyMetadata<CLVaultStrategySettings> = {
|
|
@@ -6,7 +6,7 @@ import { Global } from "@/global";
|
|
|
6
6
|
import { ApproveCallParams, CommonAdapter, ManageCall, Swap, VesuAdapter, VesuModifyDelegationCallParams, VesuMultiplyCallParams, VesuPools } from "./universal-adapters";
|
|
7
7
|
import { AVNU_MIDDLEWARE } from "./universal-adapters/adapter-utils";
|
|
8
8
|
import { LiquidationRiskLevel, SmartContractRiskLevel, TechnicalRiskLevel } from "@/interfaces/risks";
|
|
9
|
-
import { EkuboQuoter, ERC20 } from "@/modules";
|
|
9
|
+
import { EkuboQuoter, ERC20, PricerLST } from "@/modules";
|
|
10
10
|
import { assert, logger } from "@/utils";
|
|
11
11
|
import { SingleTokenInfo } from "./base-strategy";
|
|
12
12
|
import { Call, Contract, uint256 } from "starknet";
|
|
@@ -17,7 +17,7 @@ export class UniversalLstMultiplierStrategy extends UniversalStrategy<UniversalS
|
|
|
17
17
|
|
|
18
18
|
private quoteAmountToFetchPrice = new Web3Number(1, 18);
|
|
19
19
|
|
|
20
|
-
constructor(config: IConfig, pricer:
|
|
20
|
+
constructor(config: IConfig, pricer: PricerLST, metadata: IStrategyMetadata<UniversalStrategySettings>) {
|
|
21
21
|
super(config, pricer, metadata);
|
|
22
22
|
|
|
23
23
|
const STRKToken = Global.getDefaultTokens().find(token => token.symbol === 'STRK')!;
|
|
@@ -42,9 +42,9 @@ export class UniversalLstMultiplierStrategy extends UniversalStrategy<UniversalS
|
|
|
42
42
|
|
|
43
43
|
// not applicable for this strategy
|
|
44
44
|
// No rewards on collateral or borrowing of LST assets
|
|
45
|
-
protected async getRewardsAUM(prevAum: Web3Number): Promise<Web3Number> {
|
|
46
|
-
|
|
47
|
-
}
|
|
45
|
+
// protected async getRewardsAUM(prevAum: Web3Number): Promise<Web3Number> {
|
|
46
|
+
// return Web3Number.fromWei("0", this.asset().decimals);
|
|
47
|
+
// }
|
|
48
48
|
|
|
49
49
|
async getLSTDexPrice() {
|
|
50
50
|
const ekuboQuoter = new EkuboQuoter(this.config);
|
|
@@ -82,12 +82,16 @@ export class UniversalLstMultiplierStrategy extends UniversalStrategy<UniversalS
|
|
|
82
82
|
logger.debug(`${this.getTag()}::getVesuMultiplyCall existingCollateralInfo: ${JSON.stringify(existingCollateralInfo)},
|
|
83
83
|
existingDebtInfo: ${JSON.stringify(existingDebtInfo)}, collateralisation: ${JSON.stringify(collateralisation)}`);
|
|
84
84
|
|
|
85
|
+
// - Prices as seen by Vesu contracts, ideal for HF math
|
|
85
86
|
// Price 1 is ok as fallback bcz that would relatively price the
|
|
86
87
|
// collateral and debt as equal.
|
|
87
88
|
const collateralPrice = collateralisation[0].usdValue > 0 ? collateralisation[0].usdValue / existingCollateralInfo.amount.toNumber() : 1;
|
|
88
89
|
const debtPrice = collateralisation[1].usdValue > 0 ? collateralisation[1].usdValue / existingDebtInfo.amount.toNumber() : 1;
|
|
89
90
|
logger.debug(`${this.getTag()}::getVesuMultiplyCall collateralPrice: ${collateralPrice}, debtPrice: ${debtPrice}`);
|
|
90
91
|
|
|
92
|
+
// - Prices as seen by actual swap price
|
|
93
|
+
const dexPrice = await this.getLSTDexPrice();
|
|
94
|
+
|
|
91
95
|
// compute optimal amount of collateral and debt post addition/removal
|
|
92
96
|
// target hf = collateral * collateralPrice * ltv / debt * debtPrice
|
|
93
97
|
// assuming X to be the usd amount of debt borrowed or repaied (negative).
|
|
@@ -97,11 +101,10 @@ export class UniversalLstMultiplierStrategy extends UniversalStrategy<UniversalS
|
|
|
97
101
|
// => X = (((collateral + legDepositAmount) * collateralPrice * ltv) - (debt * debtPrice * target hf)) / (target hf - ltv)
|
|
98
102
|
const addedCollateral = params.leg1DepositAmount
|
|
99
103
|
.multipliedBy(params.isDeposit ? 1 : -1)
|
|
100
|
-
const DEXPrice = await this.getLSTDexPrice();
|
|
101
104
|
logger.verbose(`${this.getTag()}::getVesuMultiplyCall addedCollateral: ${addedCollateral}`);
|
|
102
105
|
const numeratorPart1 = (existingCollateralInfo.amount.plus((addedCollateral))).multipliedBy(collateralPrice).multipliedBy(legLTV);
|
|
103
106
|
const numeratorPart2 = existingDebtInfo.amount.multipliedBy(debtPrice).multipliedBy(this.metadata.additionalInfo.targetHealthFactor);
|
|
104
|
-
const denominatorPart = this.metadata.additionalInfo.targetHealthFactor - (legLTV /
|
|
107
|
+
const denominatorPart = this.metadata.additionalInfo.targetHealthFactor - (legLTV / dexPrice);
|
|
105
108
|
const x_debt_usd = numeratorPart1.minus(numeratorPart2).dividedBy(denominatorPart);
|
|
106
109
|
logger.verbose(`${this.getTag()}::getVesuMultiplyCall x_debt_usd: ${x_debt_usd}`);
|
|
107
110
|
logger.debug(`${this.getTag()}::getVesuMultiplyCall numeratorPart1: ${numeratorPart1}, numeratorPart2: ${numeratorPart2}, denominatorPart: ${denominatorPart}`);
|
|
@@ -121,6 +124,7 @@ export class UniversalLstMultiplierStrategy extends UniversalStrategy<UniversalS
|
|
|
121
124
|
return this.getModifyLeverCall({
|
|
122
125
|
marginAmount,
|
|
123
126
|
debtAmount,
|
|
127
|
+
lstDexPriceInUnderlying: dexPrice,
|
|
124
128
|
isIncrease: debtAmount.greaterThan(0)
|
|
125
129
|
});
|
|
126
130
|
}
|
|
@@ -152,6 +156,7 @@ export class UniversalLstMultiplierStrategy extends UniversalStrategy<UniversalS
|
|
|
152
156
|
async getModifyLeverCall(params: {
|
|
153
157
|
marginAmount: Web3Number, // >0 during deposit
|
|
154
158
|
debtAmount: Web3Number,
|
|
159
|
+
lstDexPriceInUnderlying: number,
|
|
155
160
|
isIncrease: boolean
|
|
156
161
|
}): Promise<Call[]> {
|
|
157
162
|
assert(!params.marginAmount.isZero() || !params.debtAmount.isZero(), 'Deposit/debt must be non-0');
|
|
@@ -175,13 +180,12 @@ export class UniversalLstMultiplierStrategy extends UniversalStrategy<UniversalS
|
|
|
175
180
|
manageCalls.push(manageCall1);
|
|
176
181
|
}
|
|
177
182
|
|
|
183
|
+
const lstDexPriceInUnderlying = params.lstDexPriceInUnderlying;
|
|
178
184
|
const ekuboQuoter = new EkuboQuoter(this.config);
|
|
179
185
|
|
|
180
186
|
// compute quotes for margin swap
|
|
181
|
-
const lstPrice = await this.getLSTExchangeRate();
|
|
182
187
|
const marginSwap: Swap[] = [];
|
|
183
188
|
|
|
184
|
-
|
|
185
189
|
// compute quotes for lever swap
|
|
186
190
|
const MAX_SLIPPAGE = 0.01;
|
|
187
191
|
// when increasing, debt is swapped to collateral (LST)
|
|
@@ -196,8 +200,8 @@ export class UniversalLstMultiplierStrategy extends UniversalStrategy<UniversalS
|
|
|
196
200
|
);
|
|
197
201
|
assert(leverSwapQuote.price_impact < MAX_SLIPPAGE, 'getIncreaseLeverCall: Price impact is too high [Debt swap]');
|
|
198
202
|
const leverSwap = ekuboQuoter.getVesuMultiplyQuote(leverSwapQuote, fromToken, toToken);
|
|
199
|
-
const minExpectedDebt = params.debtAmount.dividedBy(
|
|
200
|
-
const maxUsedCollateral = params.debtAmount.abs().dividedBy(
|
|
203
|
+
const minExpectedDebt = params.debtAmount.dividedBy(lstDexPriceInUnderlying).multipliedBy(1 - MAX_SLIPPAGE); // used for increase
|
|
204
|
+
const maxUsedCollateral = params.debtAmount.abs().dividedBy(lstDexPriceInUnderlying).multipliedBy(1 + MAX_SLIPPAGE); // +ve for exact amount out, used for decrease
|
|
201
205
|
|
|
202
206
|
const STEP2_ID = LST_MULTIPLIER_MANAGE_IDS.SWITCH_DELEGATION_ON;
|
|
203
207
|
const manage2Info = this.getProofs<VesuModifyDelegationCallParams>(STEP2_ID);
|
|
@@ -416,6 +420,54 @@ const hyperxSTRK: UniversalStrategySettings = {
|
|
|
416
420
|
minHealthFactor: 1.05
|
|
417
421
|
}
|
|
418
422
|
|
|
423
|
+
const hyperxWBTC: UniversalStrategySettings = {
|
|
424
|
+
vaultAddress: ContractAddr.from('0x2da9d0f96a46b453f55604313785dc866424240b1c6811d13bef594343db818'),
|
|
425
|
+
manager: ContractAddr.from('0x75866db44c81e6986f06035206ee9c7d15833ddb22d6a22c016cfb5c866a491'),
|
|
426
|
+
vaultAllocator: ContractAddr.from('0x57b5c1bb457b5e840a2714ae53ada87d77be2f3fd33a59b4fe709ef20c020c1'),
|
|
427
|
+
redeemRequestNFT: ContractAddr.from('0x7a5dc288325456f05e70e9616e16bc02ffbe448f4b89f80b47c0970b989c7c'),
|
|
428
|
+
aumOracle: ContractAddr.from(''),
|
|
429
|
+
leafAdapters: [],
|
|
430
|
+
adapters: [],
|
|
431
|
+
targetHealthFactor: 1.1,
|
|
432
|
+
minHealthFactor: 1.05
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const hyperxtBTC: UniversalStrategySettings = {
|
|
436
|
+
vaultAddress: ContractAddr.from('0x47d5f68477e5637ce0e56436c6b5eee5a354e6828995dae106b11a48679328'),
|
|
437
|
+
manager: ContractAddr.from('0xc4cc3e08029a0ae076f5fdfca70575abb78d23c5cd1c49a957f7e697885401'),
|
|
438
|
+
vaultAllocator: ContractAddr.from('0x50bbd4fe69f841ecb13b2619fe50ebfa4e8944671b5d0ebf7868fd80c61b31e'),
|
|
439
|
+
redeemRequestNFT: ContractAddr.from('0xeac9032f02057779816e38a6cb9185d12d86b3aacc9949b96b36de359c1e3'),
|
|
440
|
+
aumOracle: ContractAddr.from(''),
|
|
441
|
+
leafAdapters: [],
|
|
442
|
+
adapters: [],
|
|
443
|
+
targetHealthFactor: 1.1,
|
|
444
|
+
minHealthFactor: 1.05
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const hyperxsBTC: UniversalStrategySettings = {
|
|
448
|
+
vaultAddress: ContractAddr.from('0x437ef1e7d0f100b2e070b7a65cafec0b2be31b0290776da8b4112f5473d8d9'),
|
|
449
|
+
manager: ContractAddr.from('0xc9ac023090625b0be3f6532ca353f086746f9c09f939dbc1b2613f09e5f821'),
|
|
450
|
+
vaultAllocator: ContractAddr.from('0x60c2d856936b975459a5b4eb28b8672d91f757bd76cebb6241f8d670185dc01'),
|
|
451
|
+
redeemRequestNFT: ContractAddr.from('0x429e8ee8bc7ecd1ade72630d350a2e0f10f9a2507c45f188ba17fe8f2ab4cf3'),
|
|
452
|
+
aumOracle: ContractAddr.from(''),
|
|
453
|
+
leafAdapters: [],
|
|
454
|
+
adapters: [],
|
|
455
|
+
targetHealthFactor: 1.1,
|
|
456
|
+
minHealthFactor: 1.05
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
const hyperxLBTC: UniversalStrategySettings = {
|
|
460
|
+
vaultAddress: ContractAddr.from('0x38e96a301428d204ab4553799aa386a0f14a5ef9b30a5830be1814e4fb8da1c'),
|
|
461
|
+
manager: ContractAddr.from('0x18d376446d9df1f783e17aff1f21bac3d97aa3ba378e367742cdd744468ad35'),
|
|
462
|
+
vaultAllocator: ContractAddr.from('0x3e98774ca0508505ba6d7f17d95ec391648f44f947b0d211241464a4f5b9b20'),
|
|
463
|
+
redeemRequestNFT: ContractAddr.from('0x268017b4c8b2117ca0136d9a77e3666db44b143447566f0746ca0b1c9ab1e72'),
|
|
464
|
+
aumOracle: ContractAddr.from('0x521a3f339c65e918e0d8a065b14baef1ea25676bb7fca1e0238ac47e20d7755'),
|
|
465
|
+
leafAdapters: [],
|
|
466
|
+
adapters: [],
|
|
467
|
+
targetHealthFactor: 1.1,
|
|
468
|
+
minHealthFactor: 1.05
|
|
469
|
+
}
|
|
470
|
+
|
|
419
471
|
function getInvestmentSteps(lstSymbol: string, underlyingSymbol: string) {
|
|
420
472
|
return [
|
|
421
473
|
`Deposit ${underlyingSymbol} into the vault`,
|
|
@@ -427,7 +479,7 @@ function getInvestmentSteps(lstSymbol: string, underlyingSymbol: string) {
|
|
|
427
479
|
]
|
|
428
480
|
}
|
|
429
481
|
|
|
430
|
-
function getStrategySettings(lstSymbol: string, underlyingSymbol: string, addresses: UniversalStrategySettings): IStrategyMetadata<UniversalStrategySettings> {
|
|
482
|
+
function getStrategySettings(lstSymbol: string, underlyingSymbol: string, addresses: UniversalStrategySettings, isPreview: boolean = false): IStrategyMetadata<UniversalStrategySettings> {
|
|
431
483
|
return {
|
|
432
484
|
name: `Hyper ${lstSymbol}`,
|
|
433
485
|
description: getDescription(lstSymbol),
|
|
@@ -448,10 +500,15 @@ function getStrategySettings(lstSymbol: string, underlyingSymbol: string, addres
|
|
|
448
500
|
contractDetails: getContractDetails(addresses),
|
|
449
501
|
faqs: getFAQs(lstSymbol, underlyingSymbol),
|
|
450
502
|
investmentSteps: getInvestmentSteps(lstSymbol, underlyingSymbol),
|
|
503
|
+
isPreview: isPreview
|
|
451
504
|
}
|
|
452
505
|
}
|
|
453
506
|
|
|
454
507
|
export const HyperLSTStrategies: IStrategyMetadata<UniversalStrategySettings>[] =
|
|
455
508
|
[
|
|
456
|
-
getStrategySettings('xSTRK', 'STRK', hyperxSTRK),
|
|
509
|
+
getStrategySettings('xSTRK', 'STRK', hyperxSTRK, false),
|
|
510
|
+
getStrategySettings('xWBTC', 'WBTC', hyperxWBTC, true),
|
|
511
|
+
getStrategySettings('xtBTC', 'tBTC', hyperxtBTC, true),
|
|
512
|
+
getStrategySettings('xsBTC', 'solvBTC', hyperxsBTC, true),
|
|
513
|
+
getStrategySettings('xLBTC', 'LBTC', hyperxLBTC, true),
|
|
457
514
|
]
|
|
@@ -203,6 +203,14 @@ export class UniversalStrategy<
|
|
|
203
203
|
* @returns {Promise<number>} The weighted average APY across all pools
|
|
204
204
|
*/
|
|
205
205
|
async netAPY(): Promise<{ net: number, splits: { apy: number, id: string }[] }> {
|
|
206
|
+
if (this.metadata.isPreview) {
|
|
207
|
+
return { net: 0, splits: [{
|
|
208
|
+
apy: 0, id: 'base'
|
|
209
|
+
}, {
|
|
210
|
+
apy: 0, id: 'defispring'
|
|
211
|
+
}] };
|
|
212
|
+
}
|
|
213
|
+
|
|
206
214
|
const prevAUM = await this.getPrevAUM();
|
|
207
215
|
|
|
208
216
|
// get Vesu pools, positions and APYs
|
|
@@ -302,20 +310,20 @@ export class UniversalStrategy<
|
|
|
302
310
|
const underlying = this.asset();
|
|
303
311
|
let vesuAum = Web3Number.fromWei("0", underlying.decimals);
|
|
304
312
|
|
|
313
|
+
let tokenUnderlyingPrice = await this.pricer.getPrice(this.asset().symbol);
|
|
314
|
+
|
|
305
315
|
// handle collateral
|
|
306
316
|
if (legAUM[0].token.address.eq(underlying.address)) {
|
|
307
317
|
vesuAum = vesuAum.plus(legAUM[0].amount);
|
|
308
318
|
} else {
|
|
309
|
-
|
|
310
|
-
vesuAum = vesuAum.plus(legAUM[1].usdValue / tokenPrice.price);
|
|
319
|
+
vesuAum = vesuAum.plus(legAUM[1].usdValue / tokenUnderlyingPrice.price);
|
|
311
320
|
}
|
|
312
321
|
|
|
313
322
|
// handle debt
|
|
314
323
|
if (legAUM[1].token.address.eq(underlying.address)) {
|
|
315
324
|
vesuAum = vesuAum.minus(legAUM[1].amount);
|
|
316
325
|
} else {
|
|
317
|
-
|
|
318
|
-
vesuAum = vesuAum.minus(legAUM[1].usdValue / tokenPrice.price);
|
|
326
|
+
vesuAum = vesuAum.minus(legAUM[1].usdValue / tokenUnderlyingPrice.price);
|
|
319
327
|
};
|
|
320
328
|
|
|
321
329
|
logger.verbose(`${this.getTag()} Vesu AUM: ${vesuAum}, legCollateral: ${legAUM[0].amount.toNumber()}, legDebt: ${legAUM[1].amount.toNumber()}`);
|