@strkfarm/sdk 1.1.24 → 1.1.26
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 +129 -6
- package/dist/index.browser.mjs +127 -4
- package/dist/index.d.ts +50 -1
- package/dist/index.js +128 -4
- package/dist/index.mjs +127 -4
- package/package.json +1 -1
- package/src/modules/index.ts +2 -1
- package/src/modules/lst-apr.ts +140 -0
- package/src/strategies/ekubo-cl-vault.tsx +3 -3
- package/src/strategies/universal-strategy.tsx +31 -2
|
@@ -20191,7 +20191,7 @@ ${r2}}` : "}", l2;
|
|
|
20191
20191
|
toHexString: () => toHexString2,
|
|
20192
20192
|
toStorageKey: () => toStorageKey2
|
|
20193
20193
|
});
|
|
20194
|
-
var
|
|
20194
|
+
var import_utils63 = require_utils2();
|
|
20195
20195
|
function isHex3(hex) {
|
|
20196
20196
|
return /^0x[0-9a-f]*$/i.test(hex);
|
|
20197
20197
|
}
|
|
@@ -20264,7 +20264,7 @@ ${r2}}` : "}", l2;
|
|
|
20264
20264
|
if (adaptedValue.length % 2 !== 0) {
|
|
20265
20265
|
adaptedValue = `0${adaptedValue}`;
|
|
20266
20266
|
}
|
|
20267
|
-
return (0,
|
|
20267
|
+
return (0, import_utils63.hexToBytes)(adaptedValue);
|
|
20268
20268
|
}
|
|
20269
20269
|
function addPercent2(number2, percent) {
|
|
20270
20270
|
const bigIntNum = BigInt(number2);
|
|
@@ -28658,6 +28658,7 @@ ${r2}}` : "}", l2;
|
|
|
28658
28658
|
HyperLSTStrategies: () => HyperLSTStrategies,
|
|
28659
28659
|
ILending: () => ILending,
|
|
28660
28660
|
Initializable: () => Initializable,
|
|
28661
|
+
LSTAPRService: () => LSTAPRService,
|
|
28661
28662
|
MarginType: () => MarginType,
|
|
28662
28663
|
Network: () => Network,
|
|
28663
28664
|
PRICE_ROUTER: () => PRICE_ROUTER,
|
|
@@ -53881,6 +53882,107 @@ ${JSON.stringify(data, null, 2)}`;
|
|
|
53881
53882
|
}
|
|
53882
53883
|
};
|
|
53883
53884
|
|
|
53885
|
+
// src/modules/lst-apr.ts
|
|
53886
|
+
var LSTAPRService = class {
|
|
53887
|
+
// 5 minutes
|
|
53888
|
+
/**
|
|
53889
|
+
* Fetches LST stats from Endur API with caching
|
|
53890
|
+
* @returns Promise<LSTStats[]> Array of LST statistics
|
|
53891
|
+
*/
|
|
53892
|
+
static async getLSTStats() {
|
|
53893
|
+
const now = Date.now();
|
|
53894
|
+
if (this.cache && now - this.cacheTimestamp < this.CACHE_DURATION) {
|
|
53895
|
+
logger2.verbose(`LSTAPRService: Returning cached LST stats`);
|
|
53896
|
+
return this.cache;
|
|
53897
|
+
}
|
|
53898
|
+
try {
|
|
53899
|
+
logger2.verbose(`LSTAPRService: Fetching LST stats from Endur API`);
|
|
53900
|
+
const response = await fetch(this.ENDUR_API_URL);
|
|
53901
|
+
if (!response.ok) {
|
|
53902
|
+
throw new Error(`Failed to fetch LST stats: ${response.status} ${response.statusText}`);
|
|
53903
|
+
}
|
|
53904
|
+
const data = await response.json();
|
|
53905
|
+
if (!Array.isArray(data)) {
|
|
53906
|
+
throw new Error("Invalid response format: expected array");
|
|
53907
|
+
}
|
|
53908
|
+
this.cache = data;
|
|
53909
|
+
this.cacheTimestamp = now;
|
|
53910
|
+
logger2.verbose(`LSTAPRService: Successfully fetched ${data.length} LST stats`);
|
|
53911
|
+
return data;
|
|
53912
|
+
} catch (error2) {
|
|
53913
|
+
logger2.error(`LSTAPRService: Error fetching LST stats: ${error2}`);
|
|
53914
|
+
if (this.cache) {
|
|
53915
|
+
logger2.warn(`LSTAPRService: Returning stale cached data due to API error`);
|
|
53916
|
+
return this.cache;
|
|
53917
|
+
}
|
|
53918
|
+
throw error2;
|
|
53919
|
+
}
|
|
53920
|
+
}
|
|
53921
|
+
/**
|
|
53922
|
+
* Gets LST APR for a specific asset address
|
|
53923
|
+
* @param assetAddress - The contract address of the underlying asset
|
|
53924
|
+
* @returns Promise<number> The LST APR (not divided by 1e18)
|
|
53925
|
+
*/
|
|
53926
|
+
static async getLSTAPR(assetAddress) {
|
|
53927
|
+
const stats = await this.getLSTStats();
|
|
53928
|
+
const lstStat = stats.find(
|
|
53929
|
+
(stat) => ContractAddr.eqString(stat.assetAddress, assetAddress.address)
|
|
53930
|
+
);
|
|
53931
|
+
if (!lstStat) {
|
|
53932
|
+
logger2.warn(`LSTAPRService: No LST stats found for asset address ${assetAddress.address}`);
|
|
53933
|
+
return 0;
|
|
53934
|
+
}
|
|
53935
|
+
logger2.verbose(`LSTAPRService: Found LST APR for ${lstStat.asset}: ${lstStat.apy} (${lstStat.apyInPercentage})`);
|
|
53936
|
+
return lstStat.apy;
|
|
53937
|
+
}
|
|
53938
|
+
/**
|
|
53939
|
+
* Gets LST APR for multiple asset addresses
|
|
53940
|
+
* @param assetAddresses - Array of contract addresses
|
|
53941
|
+
* @returns Promise<Map<string, number>> Map of asset address to LST APR
|
|
53942
|
+
*/
|
|
53943
|
+
static async getLSTAPRs(assetAddresses) {
|
|
53944
|
+
const stats = await this.getLSTStats();
|
|
53945
|
+
const result2 = /* @__PURE__ */ new Map();
|
|
53946
|
+
for (const assetAddress of assetAddresses) {
|
|
53947
|
+
const lstStat = stats.find(
|
|
53948
|
+
(stat) => ContractAddr.eqString(stat.assetAddress, assetAddress.address)
|
|
53949
|
+
);
|
|
53950
|
+
if (lstStat) {
|
|
53951
|
+
result2.set(assetAddress.address, lstStat.apy);
|
|
53952
|
+
logger2.verbose(`LSTAPRService: Found LST APR for ${lstStat.asset}: ${lstStat.apy}`);
|
|
53953
|
+
} else {
|
|
53954
|
+
result2.set(assetAddress.address, 0);
|
|
53955
|
+
logger2.warn(`LSTAPRService: No LST stats found for asset address ${assetAddress.address}`);
|
|
53956
|
+
}
|
|
53957
|
+
}
|
|
53958
|
+
return result2;
|
|
53959
|
+
}
|
|
53960
|
+
/**
|
|
53961
|
+
* Gets all available LST assets and their APRs
|
|
53962
|
+
* @returns Promise<Map<string, LSTStats>> Map of asset address to LST stats
|
|
53963
|
+
*/
|
|
53964
|
+
static async getAllLSTStats() {
|
|
53965
|
+
const stats = await this.getLSTStats();
|
|
53966
|
+
const result2 = /* @__PURE__ */ new Map();
|
|
53967
|
+
for (const stat of stats) {
|
|
53968
|
+
result2.set(stat.assetAddress, stat);
|
|
53969
|
+
}
|
|
53970
|
+
return result2;
|
|
53971
|
+
}
|
|
53972
|
+
/**
|
|
53973
|
+
* Clears the cache (useful for testing or forcing refresh)
|
|
53974
|
+
*/
|
|
53975
|
+
static clearCache() {
|
|
53976
|
+
this.cache = null;
|
|
53977
|
+
this.cacheTimestamp = 0;
|
|
53978
|
+
logger2.verbose(`LSTAPRService: Cache cleared`);
|
|
53979
|
+
}
|
|
53980
|
+
};
|
|
53981
|
+
LSTAPRService.ENDUR_API_URL = "https://app.endur.fi/api/lst/stats";
|
|
53982
|
+
LSTAPRService.cache = null;
|
|
53983
|
+
LSTAPRService.cacheTimestamp = 0;
|
|
53984
|
+
LSTAPRService.CACHE_DURATION = 5 * 60 * 1e3;
|
|
53985
|
+
|
|
53884
53986
|
// src/interfaces/common.tsx
|
|
53885
53987
|
var import_jsx_runtime = __toESM(require_jsx_runtime());
|
|
53886
53988
|
var RiskType = /* @__PURE__ */ ((RiskType2) => {
|
|
@@ -80478,7 +80580,7 @@ spurious results.`);
|
|
|
80478
80580
|
return [baseFlow, rebalanceFlow];
|
|
80479
80581
|
}
|
|
80480
80582
|
};
|
|
80481
|
-
var _description2 = "Deploys your {{POOL_NAME}} into an Ekubo liquidity pool, automatically rebalancing positions around the current price to optimize yield and reduce the need for manual adjustments. Trading fees and
|
|
80583
|
+
var _description2 = "Deploys your {{POOL_NAME}} into an Ekubo liquidity pool, automatically rebalancing positions around the current price to optimize yield and reduce the need for manual adjustments. Trading fees and any rewards are automatically compounded back into the strategy. In return, you receive an ERC-20 token representing your share of the strategy";
|
|
80482
80584
|
var _protocol2 = {
|
|
80483
80585
|
name: "Ekubo",
|
|
80484
80586
|
logo: "https://app.ekubo.org/favicon.ico"
|
|
@@ -80523,7 +80625,7 @@ spurious results.`);
|
|
|
80523
80625
|
},
|
|
80524
80626
|
{
|
|
80525
80627
|
question: "How are trading fees and rewards handled?",
|
|
80526
|
-
answer: "Trading fees and
|
|
80628
|
+
answer: "Trading fees and any rewards are automatically compounded back into the strategy, increasing your overall returns."
|
|
80527
80629
|
},
|
|
80528
80630
|
{
|
|
80529
80631
|
question: "What happens during withdrawal?",
|
|
@@ -80900,7 +81002,7 @@ spurious results.`);
|
|
|
80900
81002
|
s.investmentSteps = [
|
|
80901
81003
|
"Supply tokens to Ekubo's pool",
|
|
80902
81004
|
"Monitor and Rebalance position to optimize yield",
|
|
80903
|
-
"Harvest and
|
|
81005
|
+
"Harvest and re-invest any rewards every week (Auto-compound)"
|
|
80904
81006
|
];
|
|
80905
81007
|
});
|
|
80906
81008
|
|
|
@@ -90613,12 +90715,21 @@ spurious results.`);
|
|
|
90613
90715
|
logger2.verbose(`${this.metadata.name}::netAPY: positions: ${JSON.stringify(positions)}`);
|
|
90614
90716
|
const baseAPYs = [];
|
|
90615
90717
|
const rewardAPYs = [];
|
|
90718
|
+
const collateralAddresses = vesuAdapters.map((adapter) => adapter.config.collateral.address);
|
|
90719
|
+
let lstAPRs;
|
|
90720
|
+
try {
|
|
90721
|
+
lstAPRs = await LSTAPRService.getLSTAPRs(collateralAddresses);
|
|
90722
|
+
} catch (error2) {
|
|
90723
|
+
logger2.warn(`${this.metadata.name}::netAPY: Failed to fetch LST APRs from Endur API, using fallback: ${error2}`);
|
|
90724
|
+
lstAPRs = /* @__PURE__ */ new Map();
|
|
90725
|
+
}
|
|
90616
90726
|
for (const [index, pool] of pools.entries()) {
|
|
90617
90727
|
const vesuAdapter = vesuAdapters[index];
|
|
90618
90728
|
const collateralAsset = pool.assets.find((a) => a.symbol.toLowerCase() === vesuAdapter.config.collateral.symbol.toLowerCase())?.stats;
|
|
90619
90729
|
const debtAsset = pool.assets.find((a) => a.symbol.toLowerCase() === vesuAdapter.config.debt.symbol.toLowerCase())?.stats;
|
|
90620
90730
|
const supplyApy = Number(collateralAsset.supplyApy.value || 0) / 1e18;
|
|
90621
|
-
const lstAPY =
|
|
90731
|
+
const lstAPY = lstAPRs.get(vesuAdapter.config.collateral.address.address) || 0;
|
|
90732
|
+
logger2.verbose(`${this.metadata.name}::netAPY: ${vesuAdapter.config.collateral.symbol} LST APR from Endur: ${lstAPY}`);
|
|
90622
90733
|
baseAPYs.push(...[supplyApy + lstAPY, Number(debtAsset.borrowApr.value) / 1e18]);
|
|
90623
90734
|
rewardAPYs.push(...[Number(collateralAsset.defiSpringSupplyApr?.value || "0") / 1e18, 0]);
|
|
90624
90735
|
}
|
|
@@ -90842,6 +90953,18 @@ spurious results.`);
|
|
|
90842
90953
|
getTag() {
|
|
90843
90954
|
return `${_UniversalStrategy.name}:${this.metadata.name}`;
|
|
90844
90955
|
}
|
|
90956
|
+
/**
|
|
90957
|
+
* Gets LST APR for the strategy's underlying asset from Endur API
|
|
90958
|
+
* @returns Promise<number> The LST APR (not divided by 1e18)
|
|
90959
|
+
*/
|
|
90960
|
+
async getLSTAPR() {
|
|
90961
|
+
try {
|
|
90962
|
+
return await LSTAPRService.getLSTAPR(this.asset().address);
|
|
90963
|
+
} catch (error2) {
|
|
90964
|
+
logger2.warn(`${this.getTag()}: Failed to get LST APR: ${error2}`);
|
|
90965
|
+
return 0;
|
|
90966
|
+
}
|
|
90967
|
+
}
|
|
90845
90968
|
async getVesuHealthFactors() {
|
|
90846
90969
|
return await Promise.all(this.getVesuAdapters().map((v) => v.getHealthFactor()));
|
|
90847
90970
|
}
|
package/dist/index.browser.mjs
CHANGED
|
@@ -2279,6 +2279,107 @@ var PricerLST = class extends Pricer {
|
|
|
2279
2279
|
}
|
|
2280
2280
|
};
|
|
2281
2281
|
|
|
2282
|
+
// src/modules/lst-apr.ts
|
|
2283
|
+
var LSTAPRService = class {
|
|
2284
|
+
// 5 minutes
|
|
2285
|
+
/**
|
|
2286
|
+
* Fetches LST stats from Endur API with caching
|
|
2287
|
+
* @returns Promise<LSTStats[]> Array of LST statistics
|
|
2288
|
+
*/
|
|
2289
|
+
static async getLSTStats() {
|
|
2290
|
+
const now = Date.now();
|
|
2291
|
+
if (this.cache && now - this.cacheTimestamp < this.CACHE_DURATION) {
|
|
2292
|
+
logger.verbose(`LSTAPRService: Returning cached LST stats`);
|
|
2293
|
+
return this.cache;
|
|
2294
|
+
}
|
|
2295
|
+
try {
|
|
2296
|
+
logger.verbose(`LSTAPRService: Fetching LST stats from Endur API`);
|
|
2297
|
+
const response = await fetch(this.ENDUR_API_URL);
|
|
2298
|
+
if (!response.ok) {
|
|
2299
|
+
throw new Error(`Failed to fetch LST stats: ${response.status} ${response.statusText}`);
|
|
2300
|
+
}
|
|
2301
|
+
const data = await response.json();
|
|
2302
|
+
if (!Array.isArray(data)) {
|
|
2303
|
+
throw new Error("Invalid response format: expected array");
|
|
2304
|
+
}
|
|
2305
|
+
this.cache = data;
|
|
2306
|
+
this.cacheTimestamp = now;
|
|
2307
|
+
logger.verbose(`LSTAPRService: Successfully fetched ${data.length} LST stats`);
|
|
2308
|
+
return data;
|
|
2309
|
+
} catch (error) {
|
|
2310
|
+
logger.error(`LSTAPRService: Error fetching LST stats: ${error}`);
|
|
2311
|
+
if (this.cache) {
|
|
2312
|
+
logger.warn(`LSTAPRService: Returning stale cached data due to API error`);
|
|
2313
|
+
return this.cache;
|
|
2314
|
+
}
|
|
2315
|
+
throw error;
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
/**
|
|
2319
|
+
* Gets LST APR for a specific asset address
|
|
2320
|
+
* @param assetAddress - The contract address of the underlying asset
|
|
2321
|
+
* @returns Promise<number> The LST APR (not divided by 1e18)
|
|
2322
|
+
*/
|
|
2323
|
+
static async getLSTAPR(assetAddress) {
|
|
2324
|
+
const stats = await this.getLSTStats();
|
|
2325
|
+
const lstStat = stats.find(
|
|
2326
|
+
(stat) => ContractAddr.eqString(stat.assetAddress, assetAddress.address)
|
|
2327
|
+
);
|
|
2328
|
+
if (!lstStat) {
|
|
2329
|
+
logger.warn(`LSTAPRService: No LST stats found for asset address ${assetAddress.address}`);
|
|
2330
|
+
return 0;
|
|
2331
|
+
}
|
|
2332
|
+
logger.verbose(`LSTAPRService: Found LST APR for ${lstStat.asset}: ${lstStat.apy} (${lstStat.apyInPercentage})`);
|
|
2333
|
+
return lstStat.apy;
|
|
2334
|
+
}
|
|
2335
|
+
/**
|
|
2336
|
+
* Gets LST APR for multiple asset addresses
|
|
2337
|
+
* @param assetAddresses - Array of contract addresses
|
|
2338
|
+
* @returns Promise<Map<string, number>> Map of asset address to LST APR
|
|
2339
|
+
*/
|
|
2340
|
+
static async getLSTAPRs(assetAddresses) {
|
|
2341
|
+
const stats = await this.getLSTStats();
|
|
2342
|
+
const result = /* @__PURE__ */ new Map();
|
|
2343
|
+
for (const assetAddress of assetAddresses) {
|
|
2344
|
+
const lstStat = stats.find(
|
|
2345
|
+
(stat) => ContractAddr.eqString(stat.assetAddress, assetAddress.address)
|
|
2346
|
+
);
|
|
2347
|
+
if (lstStat) {
|
|
2348
|
+
result.set(assetAddress.address, lstStat.apy);
|
|
2349
|
+
logger.verbose(`LSTAPRService: Found LST APR for ${lstStat.asset}: ${lstStat.apy}`);
|
|
2350
|
+
} else {
|
|
2351
|
+
result.set(assetAddress.address, 0);
|
|
2352
|
+
logger.warn(`LSTAPRService: No LST stats found for asset address ${assetAddress.address}`);
|
|
2353
|
+
}
|
|
2354
|
+
}
|
|
2355
|
+
return result;
|
|
2356
|
+
}
|
|
2357
|
+
/**
|
|
2358
|
+
* Gets all available LST assets and their APRs
|
|
2359
|
+
* @returns Promise<Map<string, LSTStats>> Map of asset address to LST stats
|
|
2360
|
+
*/
|
|
2361
|
+
static async getAllLSTStats() {
|
|
2362
|
+
const stats = await this.getLSTStats();
|
|
2363
|
+
const result = /* @__PURE__ */ new Map();
|
|
2364
|
+
for (const stat of stats) {
|
|
2365
|
+
result.set(stat.assetAddress, stat);
|
|
2366
|
+
}
|
|
2367
|
+
return result;
|
|
2368
|
+
}
|
|
2369
|
+
/**
|
|
2370
|
+
* Clears the cache (useful for testing or forcing refresh)
|
|
2371
|
+
*/
|
|
2372
|
+
static clearCache() {
|
|
2373
|
+
this.cache = null;
|
|
2374
|
+
this.cacheTimestamp = 0;
|
|
2375
|
+
logger.verbose(`LSTAPRService: Cache cleared`);
|
|
2376
|
+
}
|
|
2377
|
+
};
|
|
2378
|
+
LSTAPRService.ENDUR_API_URL = "https://app.endur.fi/api/lst/stats";
|
|
2379
|
+
LSTAPRService.cache = null;
|
|
2380
|
+
LSTAPRService.cacheTimestamp = 0;
|
|
2381
|
+
LSTAPRService.CACHE_DURATION = 5 * 60 * 1e3;
|
|
2382
|
+
|
|
2282
2383
|
// src/interfaces/common.tsx
|
|
2283
2384
|
import { BlockTag, RpcProvider as RpcProvider2 } from "starknet";
|
|
2284
2385
|
import { Fragment, jsx } from "react/jsx-runtime";
|
|
@@ -16557,7 +16658,7 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
|
16557
16658
|
return [baseFlow, rebalanceFlow];
|
|
16558
16659
|
}
|
|
16559
16660
|
};
|
|
16560
|
-
var _description2 = "Deploys your {{POOL_NAME}} into an Ekubo liquidity pool, automatically rebalancing positions around the current price to optimize yield and reduce the need for manual adjustments. Trading fees and
|
|
16661
|
+
var _description2 = "Deploys your {{POOL_NAME}} into an Ekubo liquidity pool, automatically rebalancing positions around the current price to optimize yield and reduce the need for manual adjustments. Trading fees and any rewards are automatically compounded back into the strategy. In return, you receive an ERC-20 token representing your share of the strategy";
|
|
16561
16662
|
var _protocol2 = {
|
|
16562
16663
|
name: "Ekubo",
|
|
16563
16664
|
logo: "https://app.ekubo.org/favicon.ico"
|
|
@@ -16602,7 +16703,7 @@ var faqs2 = [
|
|
|
16602
16703
|
},
|
|
16603
16704
|
{
|
|
16604
16705
|
question: "How are trading fees and rewards handled?",
|
|
16605
|
-
answer: "Trading fees and
|
|
16706
|
+
answer: "Trading fees and any rewards are automatically compounded back into the strategy, increasing your overall returns."
|
|
16606
16707
|
},
|
|
16607
16708
|
{
|
|
16608
16709
|
question: "What happens during withdrawal?",
|
|
@@ -16979,7 +17080,7 @@ EkuboCLVaultStrategies.forEach((s) => {
|
|
|
16979
17080
|
s.investmentSteps = [
|
|
16980
17081
|
"Supply tokens to Ekubo's pool",
|
|
16981
17082
|
"Monitor and Rebalance position to optimize yield",
|
|
16982
|
-
"Harvest and
|
|
17083
|
+
"Harvest and re-invest any rewards every week (Auto-compound)"
|
|
16983
17084
|
];
|
|
16984
17085
|
});
|
|
16985
17086
|
|
|
@@ -26705,12 +26806,21 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
26705
26806
|
logger.verbose(`${this.metadata.name}::netAPY: positions: ${JSON.stringify(positions)}`);
|
|
26706
26807
|
const baseAPYs = [];
|
|
26707
26808
|
const rewardAPYs = [];
|
|
26809
|
+
const collateralAddresses = vesuAdapters.map((adapter) => adapter.config.collateral.address);
|
|
26810
|
+
let lstAPRs;
|
|
26811
|
+
try {
|
|
26812
|
+
lstAPRs = await LSTAPRService.getLSTAPRs(collateralAddresses);
|
|
26813
|
+
} catch (error) {
|
|
26814
|
+
logger.warn(`${this.metadata.name}::netAPY: Failed to fetch LST APRs from Endur API, using fallback: ${error}`);
|
|
26815
|
+
lstAPRs = /* @__PURE__ */ new Map();
|
|
26816
|
+
}
|
|
26708
26817
|
for (const [index, pool] of pools.entries()) {
|
|
26709
26818
|
const vesuAdapter = vesuAdapters[index];
|
|
26710
26819
|
const collateralAsset = pool.assets.find((a) => a.symbol.toLowerCase() === vesuAdapter.config.collateral.symbol.toLowerCase())?.stats;
|
|
26711
26820
|
const debtAsset = pool.assets.find((a) => a.symbol.toLowerCase() === vesuAdapter.config.debt.symbol.toLowerCase())?.stats;
|
|
26712
26821
|
const supplyApy = Number(collateralAsset.supplyApy.value || 0) / 1e18;
|
|
26713
|
-
const lstAPY =
|
|
26822
|
+
const lstAPY = lstAPRs.get(vesuAdapter.config.collateral.address.address) || 0;
|
|
26823
|
+
logger.verbose(`${this.metadata.name}::netAPY: ${vesuAdapter.config.collateral.symbol} LST APR from Endur: ${lstAPY}`);
|
|
26714
26824
|
baseAPYs.push(...[supplyApy + lstAPY, Number(debtAsset.borrowApr.value) / 1e18]);
|
|
26715
26825
|
rewardAPYs.push(...[Number(collateralAsset.defiSpringSupplyApr?.value || "0") / 1e18, 0]);
|
|
26716
26826
|
}
|
|
@@ -26934,6 +27044,18 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
26934
27044
|
getTag() {
|
|
26935
27045
|
return `${_UniversalStrategy.name}:${this.metadata.name}`;
|
|
26936
27046
|
}
|
|
27047
|
+
/**
|
|
27048
|
+
* Gets LST APR for the strategy's underlying asset from Endur API
|
|
27049
|
+
* @returns Promise<number> The LST APR (not divided by 1e18)
|
|
27050
|
+
*/
|
|
27051
|
+
async getLSTAPR() {
|
|
27052
|
+
try {
|
|
27053
|
+
return await LSTAPRService.getLSTAPR(this.asset().address);
|
|
27054
|
+
} catch (error) {
|
|
27055
|
+
logger.warn(`${this.getTag()}: Failed to get LST APR: ${error}`);
|
|
27056
|
+
return 0;
|
|
27057
|
+
}
|
|
27058
|
+
}
|
|
26937
27059
|
async getVesuHealthFactors() {
|
|
26938
27060
|
return await Promise.all(this.getVesuAdapters().map((v) => v.getHealthFactor()));
|
|
26939
27061
|
}
|
|
@@ -27982,6 +28104,7 @@ export {
|
|
|
27982
28104
|
HyperLSTStrategies,
|
|
27983
28105
|
ILending,
|
|
27984
28106
|
Initializable,
|
|
28107
|
+
LSTAPRService,
|
|
27985
28108
|
MarginType,
|
|
27986
28109
|
Network,
|
|
27987
28110
|
PRICE_ROUTER,
|
package/dist/index.d.ts
CHANGED
|
@@ -1225,6 +1225,11 @@ declare class UniversalStrategy<S extends UniversalStrategySettings> extends Bas
|
|
|
1225
1225
|
debtAmount: Web3Number;
|
|
1226
1226
|
}): UniversalManageCall[];
|
|
1227
1227
|
getTag(): string;
|
|
1228
|
+
/**
|
|
1229
|
+
* Gets LST APR for the strategy's underlying asset from Endur API
|
|
1230
|
+
* @returns Promise<number> The LST APR (not divided by 1e18)
|
|
1231
|
+
*/
|
|
1232
|
+
getLSTAPR(): Promise<number>;
|
|
1228
1233
|
getVesuHealthFactors(): Promise<number[]>;
|
|
1229
1234
|
computeRebalanceConditionAndReturnCalls(): Promise<Call[]>;
|
|
1230
1235
|
private getNewHealthFactor;
|
|
@@ -1385,6 +1390,50 @@ declare class PricerLST extends Pricer {
|
|
|
1385
1390
|
_getPriceEkubo(token: TokenInfo, amountIn?: Web3Number, retry?: number): Promise<number>;
|
|
1386
1391
|
}
|
|
1387
1392
|
|
|
1393
|
+
interface LSTStats {
|
|
1394
|
+
asset: string;
|
|
1395
|
+
assetAddress: string;
|
|
1396
|
+
lstAddress: string;
|
|
1397
|
+
tvlUsd: number;
|
|
1398
|
+
tvlAsset: number;
|
|
1399
|
+
apy: number;
|
|
1400
|
+
apyInPercentage: string;
|
|
1401
|
+
exchangeRate: number;
|
|
1402
|
+
preciseExchangeRate: string;
|
|
1403
|
+
}
|
|
1404
|
+
declare class LSTAPRService {
|
|
1405
|
+
private static readonly ENDUR_API_URL;
|
|
1406
|
+
private static cache;
|
|
1407
|
+
private static cacheTimestamp;
|
|
1408
|
+
private static readonly CACHE_DURATION;
|
|
1409
|
+
/**
|
|
1410
|
+
* Fetches LST stats from Endur API with caching
|
|
1411
|
+
* @returns Promise<LSTStats[]> Array of LST statistics
|
|
1412
|
+
*/
|
|
1413
|
+
static getLSTStats(): Promise<LSTStats[]>;
|
|
1414
|
+
/**
|
|
1415
|
+
* Gets LST APR for a specific asset address
|
|
1416
|
+
* @param assetAddress - The contract address of the underlying asset
|
|
1417
|
+
* @returns Promise<number> The LST APR (not divided by 1e18)
|
|
1418
|
+
*/
|
|
1419
|
+
static getLSTAPR(assetAddress: ContractAddr): Promise<number>;
|
|
1420
|
+
/**
|
|
1421
|
+
* Gets LST APR for multiple asset addresses
|
|
1422
|
+
* @param assetAddresses - Array of contract addresses
|
|
1423
|
+
* @returns Promise<Map<string, number>> Map of asset address to LST APR
|
|
1424
|
+
*/
|
|
1425
|
+
static getLSTAPRs(assetAddresses: ContractAddr[]): Promise<Map<string, number>>;
|
|
1426
|
+
/**
|
|
1427
|
+
* Gets all available LST assets and their APRs
|
|
1428
|
+
* @returns Promise<Map<string, LSTStats>> Map of asset address to LST stats
|
|
1429
|
+
*/
|
|
1430
|
+
static getAllLSTStats(): Promise<Map<string, LSTStats>>;
|
|
1431
|
+
/**
|
|
1432
|
+
* Clears the cache (useful for testing or forcing refresh)
|
|
1433
|
+
*/
|
|
1434
|
+
static clearCache(): void;
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1388
1437
|
declare class TelegramNotif {
|
|
1389
1438
|
private subscribers;
|
|
1390
1439
|
readonly bot: TelegramBot;
|
|
@@ -1535,4 +1584,4 @@ declare class PasswordJsonCryptoUtil {
|
|
|
1535
1584
|
decrypt(encryptedData: string, password: string): any;
|
|
1536
1585
|
}
|
|
1537
1586
|
|
|
1538
|
-
export { AUMTypes, AVNU_MIDDLEWARE, type AccountInfo, type AdapterLeafType, type AllAccountsStore, type ApproveCallParams, AutoCompounderSTRK, type AvnuSwapCallParams, AvnuWrapper, BaseAdapter, BaseStrategy, type CLVaultStrategySettings, CommonAdapter, type CommonAdapterConfig, ContractAddr, type DecreaseLeverParams, Deployer, type DualActionAmount, type DualTokenInfo, ERC20, type EkuboBounds, EkuboCLVault, EkuboCLVaultStrategies, type EkuboPoolKey, type EkuboQuote, EkuboQuoter, type EkuboRouteNode, type EkuboSplit, type FAQ, FatalError, type FlashloanCallParams, FlowChartColors, type GenerateCallFn, Global, HyperLSTStrategies, type IConfig, type IInvestmentFlow, ILending, type ILendingMetadata, type ILendingPosition, type IProtocol, type IStrategyMetadata, type IncreaseLeverParams, Initializable, type LeafAdapterFn, type LeafData, type LendingToken, type ManageCall, MarginType, Network, PRICE_ROUTER, PasswordJsonCryptoUtil, Pragma, type PriceInfo, Pricer, PricerFromApi, PricerLST, PricerRedis, Protocols, type RequiredFields, type RequiredKeys, type RequiredStoreConfig, type RiskFactor, RiskType, type Route, type RouteNode, SIMPLE_SANITIZER, SIMPLE_SANITIZER_V2, SIMPLE_SANITIZER_VESU_V1_DELEGATIONS, SenseiStrategies, SenseiVault, type SenseiVaultSettings, type SingleActionAmount, type SingleTokenInfo, StandardMerkleTree, type StandardMerkleTreeData, Store, type StoreConfig, type Swap, type SwapInfo, TelegramGroupNotif, TelegramNotif, type TokenAmount, type TokenInfo, UNIVERSAL_ADAPTERS, UNIVERSAL_MANAGE_IDS, UniversalLstMultiplierStrategy, type UniversalManageCall, UniversalStrategies, UniversalStrategy, type UniversalStrategySettings, VESU_SINGLETON, type VaultPosition, VesuAdapter, type VesuAdapterConfig, type VesuAmount, VesuAmountDenomination, VesuAmountType, type VesuDefiSpringRewardsCallParams, type VesuModifyDelegationCallParams, type VesuModifyPositionCallParams, type VesuMultiplyCallParams, VesuPools, VesuRebalance, type VesuRebalanceSettings, VesuRebalanceStrategies, Web3Number, ZkLend, assert, getAPIUsingHeadlessBrowser, getContractDetails, getDefaultStoreConfig, getMainnetConfig, getNoRiskTags, getRiskColor, getRiskExplaination, getTrovesEndpoint, getVesuSingletonAddress, highlightTextWithLinks, type i257, logger, toBigInt };
|
|
1587
|
+
export { AUMTypes, AVNU_MIDDLEWARE, type AccountInfo, type AdapterLeafType, type AllAccountsStore, type ApproveCallParams, AutoCompounderSTRK, type AvnuSwapCallParams, AvnuWrapper, BaseAdapter, BaseStrategy, type CLVaultStrategySettings, CommonAdapter, type CommonAdapterConfig, ContractAddr, type DecreaseLeverParams, Deployer, type DualActionAmount, type DualTokenInfo, ERC20, type EkuboBounds, EkuboCLVault, EkuboCLVaultStrategies, type EkuboPoolKey, type EkuboQuote, EkuboQuoter, type EkuboRouteNode, type EkuboSplit, type FAQ, FatalError, type FlashloanCallParams, FlowChartColors, type GenerateCallFn, Global, HyperLSTStrategies, type IConfig, type IInvestmentFlow, ILending, type ILendingMetadata, type ILendingPosition, type IProtocol, type IStrategyMetadata, type IncreaseLeverParams, Initializable, LSTAPRService, type LSTStats, type LeafAdapterFn, type LeafData, type LendingToken, type ManageCall, MarginType, Network, PRICE_ROUTER, PasswordJsonCryptoUtil, Pragma, type PriceInfo, Pricer, PricerFromApi, PricerLST, PricerRedis, Protocols, type RequiredFields, type RequiredKeys, type RequiredStoreConfig, type RiskFactor, RiskType, type Route, type RouteNode, SIMPLE_SANITIZER, SIMPLE_SANITIZER_V2, SIMPLE_SANITIZER_VESU_V1_DELEGATIONS, SenseiStrategies, SenseiVault, type SenseiVaultSettings, type SingleActionAmount, type SingleTokenInfo, StandardMerkleTree, type StandardMerkleTreeData, Store, type StoreConfig, type Swap, type SwapInfo, TelegramGroupNotif, TelegramNotif, type TokenAmount, type TokenInfo, UNIVERSAL_ADAPTERS, UNIVERSAL_MANAGE_IDS, UniversalLstMultiplierStrategy, type UniversalManageCall, UniversalStrategies, UniversalStrategy, type UniversalStrategySettings, VESU_SINGLETON, type VaultPosition, VesuAdapter, type VesuAdapterConfig, type VesuAmount, VesuAmountDenomination, VesuAmountType, type VesuDefiSpringRewardsCallParams, type VesuModifyDelegationCallParams, type VesuModifyPositionCallParams, type VesuMultiplyCallParams, VesuPools, VesuRebalance, type VesuRebalanceSettings, VesuRebalanceStrategies, Web3Number, ZkLend, assert, getAPIUsingHeadlessBrowser, getContractDetails, getDefaultStoreConfig, getMainnetConfig, getNoRiskTags, getRiskColor, getRiskExplaination, getTrovesEndpoint, getVesuSingletonAddress, highlightTextWithLinks, type i257, logger, toBigInt };
|
package/dist/index.js
CHANGED
|
@@ -49,6 +49,7 @@ __export(index_exports, {
|
|
|
49
49
|
HyperLSTStrategies: () => HyperLSTStrategies,
|
|
50
50
|
ILending: () => ILending,
|
|
51
51
|
Initializable: () => Initializable,
|
|
52
|
+
LSTAPRService: () => LSTAPRService,
|
|
52
53
|
MarginType: () => MarginType,
|
|
53
54
|
Network: () => Network,
|
|
54
55
|
PRICE_ROUTER: () => PRICE_ROUTER,
|
|
@@ -16653,7 +16654,7 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
|
16653
16654
|
return [baseFlow, rebalanceFlow];
|
|
16654
16655
|
}
|
|
16655
16656
|
};
|
|
16656
|
-
var _description2 = "Deploys your {{POOL_NAME}} into an Ekubo liquidity pool, automatically rebalancing positions around the current price to optimize yield and reduce the need for manual adjustments. Trading fees and
|
|
16657
|
+
var _description2 = "Deploys your {{POOL_NAME}} into an Ekubo liquidity pool, automatically rebalancing positions around the current price to optimize yield and reduce the need for manual adjustments. Trading fees and any rewards are automatically compounded back into the strategy. In return, you receive an ERC-20 token representing your share of the strategy";
|
|
16657
16658
|
var _protocol2 = {
|
|
16658
16659
|
name: "Ekubo",
|
|
16659
16660
|
logo: "https://app.ekubo.org/favicon.ico"
|
|
@@ -16698,7 +16699,7 @@ var faqs2 = [
|
|
|
16698
16699
|
},
|
|
16699
16700
|
{
|
|
16700
16701
|
question: "How are trading fees and rewards handled?",
|
|
16701
|
-
answer: "Trading fees and
|
|
16702
|
+
answer: "Trading fees and any rewards are automatically compounded back into the strategy, increasing your overall returns."
|
|
16702
16703
|
},
|
|
16703
16704
|
{
|
|
16704
16705
|
question: "What happens during withdrawal?",
|
|
@@ -17075,7 +17076,7 @@ EkuboCLVaultStrategies.forEach((s) => {
|
|
|
17075
17076
|
s.investmentSteps = [
|
|
17076
17077
|
"Supply tokens to Ekubo's pool",
|
|
17077
17078
|
"Monitor and Rebalance position to optimize yield",
|
|
17078
|
-
"Harvest and
|
|
17079
|
+
"Harvest and re-invest any rewards every week (Auto-compound)"
|
|
17079
17080
|
];
|
|
17080
17081
|
});
|
|
17081
17082
|
|
|
@@ -26801,12 +26802,21 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
26801
26802
|
logger.verbose(`${this.metadata.name}::netAPY: positions: ${JSON.stringify(positions)}`);
|
|
26802
26803
|
const baseAPYs = [];
|
|
26803
26804
|
const rewardAPYs = [];
|
|
26805
|
+
const collateralAddresses = vesuAdapters.map((adapter) => adapter.config.collateral.address);
|
|
26806
|
+
let lstAPRs;
|
|
26807
|
+
try {
|
|
26808
|
+
lstAPRs = await LSTAPRService.getLSTAPRs(collateralAddresses);
|
|
26809
|
+
} catch (error) {
|
|
26810
|
+
logger.warn(`${this.metadata.name}::netAPY: Failed to fetch LST APRs from Endur API, using fallback: ${error}`);
|
|
26811
|
+
lstAPRs = /* @__PURE__ */ new Map();
|
|
26812
|
+
}
|
|
26804
26813
|
for (const [index, pool] of pools.entries()) {
|
|
26805
26814
|
const vesuAdapter = vesuAdapters[index];
|
|
26806
26815
|
const collateralAsset = pool.assets.find((a) => a.symbol.toLowerCase() === vesuAdapter.config.collateral.symbol.toLowerCase())?.stats;
|
|
26807
26816
|
const debtAsset = pool.assets.find((a) => a.symbol.toLowerCase() === vesuAdapter.config.debt.symbol.toLowerCase())?.stats;
|
|
26808
26817
|
const supplyApy = Number(collateralAsset.supplyApy.value || 0) / 1e18;
|
|
26809
|
-
const lstAPY =
|
|
26818
|
+
const lstAPY = lstAPRs.get(vesuAdapter.config.collateral.address.address) || 0;
|
|
26819
|
+
logger.verbose(`${this.metadata.name}::netAPY: ${vesuAdapter.config.collateral.symbol} LST APR from Endur: ${lstAPY}`);
|
|
26810
26820
|
baseAPYs.push(...[supplyApy + lstAPY, Number(debtAsset.borrowApr.value) / 1e18]);
|
|
26811
26821
|
rewardAPYs.push(...[Number(collateralAsset.defiSpringSupplyApr?.value || "0") / 1e18, 0]);
|
|
26812
26822
|
}
|
|
@@ -27030,6 +27040,18 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
27030
27040
|
getTag() {
|
|
27031
27041
|
return `${_UniversalStrategy.name}:${this.metadata.name}`;
|
|
27032
27042
|
}
|
|
27043
|
+
/**
|
|
27044
|
+
* Gets LST APR for the strategy's underlying asset from Endur API
|
|
27045
|
+
* @returns Promise<number> The LST APR (not divided by 1e18)
|
|
27046
|
+
*/
|
|
27047
|
+
async getLSTAPR() {
|
|
27048
|
+
try {
|
|
27049
|
+
return await LSTAPRService.getLSTAPR(this.asset().address);
|
|
27050
|
+
} catch (error) {
|
|
27051
|
+
logger.warn(`${this.getTag()}: Failed to get LST APR: ${error}`);
|
|
27052
|
+
return 0;
|
|
27053
|
+
}
|
|
27054
|
+
}
|
|
27033
27055
|
async getVesuHealthFactors() {
|
|
27034
27056
|
return await Promise.all(this.getVesuAdapters().map((v) => v.getHealthFactor()));
|
|
27035
27057
|
}
|
|
@@ -28110,6 +28132,107 @@ var PricerLST2 = class extends Pricer {
|
|
|
28110
28132
|
}
|
|
28111
28133
|
};
|
|
28112
28134
|
|
|
28135
|
+
// src/modules/lst-apr.ts
|
|
28136
|
+
var LSTAPRService = class {
|
|
28137
|
+
// 5 minutes
|
|
28138
|
+
/**
|
|
28139
|
+
* Fetches LST stats from Endur API with caching
|
|
28140
|
+
* @returns Promise<LSTStats[]> Array of LST statistics
|
|
28141
|
+
*/
|
|
28142
|
+
static async getLSTStats() {
|
|
28143
|
+
const now = Date.now();
|
|
28144
|
+
if (this.cache && now - this.cacheTimestamp < this.CACHE_DURATION) {
|
|
28145
|
+
logger.verbose(`LSTAPRService: Returning cached LST stats`);
|
|
28146
|
+
return this.cache;
|
|
28147
|
+
}
|
|
28148
|
+
try {
|
|
28149
|
+
logger.verbose(`LSTAPRService: Fetching LST stats from Endur API`);
|
|
28150
|
+
const response = await fetch(this.ENDUR_API_URL);
|
|
28151
|
+
if (!response.ok) {
|
|
28152
|
+
throw new Error(`Failed to fetch LST stats: ${response.status} ${response.statusText}`);
|
|
28153
|
+
}
|
|
28154
|
+
const data = await response.json();
|
|
28155
|
+
if (!Array.isArray(data)) {
|
|
28156
|
+
throw new Error("Invalid response format: expected array");
|
|
28157
|
+
}
|
|
28158
|
+
this.cache = data;
|
|
28159
|
+
this.cacheTimestamp = now;
|
|
28160
|
+
logger.verbose(`LSTAPRService: Successfully fetched ${data.length} LST stats`);
|
|
28161
|
+
return data;
|
|
28162
|
+
} catch (error) {
|
|
28163
|
+
logger.error(`LSTAPRService: Error fetching LST stats: ${error}`);
|
|
28164
|
+
if (this.cache) {
|
|
28165
|
+
logger.warn(`LSTAPRService: Returning stale cached data due to API error`);
|
|
28166
|
+
return this.cache;
|
|
28167
|
+
}
|
|
28168
|
+
throw error;
|
|
28169
|
+
}
|
|
28170
|
+
}
|
|
28171
|
+
/**
|
|
28172
|
+
* Gets LST APR for a specific asset address
|
|
28173
|
+
* @param assetAddress - The contract address of the underlying asset
|
|
28174
|
+
* @returns Promise<number> The LST APR (not divided by 1e18)
|
|
28175
|
+
*/
|
|
28176
|
+
static async getLSTAPR(assetAddress) {
|
|
28177
|
+
const stats = await this.getLSTStats();
|
|
28178
|
+
const lstStat = stats.find(
|
|
28179
|
+
(stat) => ContractAddr.eqString(stat.assetAddress, assetAddress.address)
|
|
28180
|
+
);
|
|
28181
|
+
if (!lstStat) {
|
|
28182
|
+
logger.warn(`LSTAPRService: No LST stats found for asset address ${assetAddress.address}`);
|
|
28183
|
+
return 0;
|
|
28184
|
+
}
|
|
28185
|
+
logger.verbose(`LSTAPRService: Found LST APR for ${lstStat.asset}: ${lstStat.apy} (${lstStat.apyInPercentage})`);
|
|
28186
|
+
return lstStat.apy;
|
|
28187
|
+
}
|
|
28188
|
+
/**
|
|
28189
|
+
* Gets LST APR for multiple asset addresses
|
|
28190
|
+
* @param assetAddresses - Array of contract addresses
|
|
28191
|
+
* @returns Promise<Map<string, number>> Map of asset address to LST APR
|
|
28192
|
+
*/
|
|
28193
|
+
static async getLSTAPRs(assetAddresses) {
|
|
28194
|
+
const stats = await this.getLSTStats();
|
|
28195
|
+
const result = /* @__PURE__ */ new Map();
|
|
28196
|
+
for (const assetAddress of assetAddresses) {
|
|
28197
|
+
const lstStat = stats.find(
|
|
28198
|
+
(stat) => ContractAddr.eqString(stat.assetAddress, assetAddress.address)
|
|
28199
|
+
);
|
|
28200
|
+
if (lstStat) {
|
|
28201
|
+
result.set(assetAddress.address, lstStat.apy);
|
|
28202
|
+
logger.verbose(`LSTAPRService: Found LST APR for ${lstStat.asset}: ${lstStat.apy}`);
|
|
28203
|
+
} else {
|
|
28204
|
+
result.set(assetAddress.address, 0);
|
|
28205
|
+
logger.warn(`LSTAPRService: No LST stats found for asset address ${assetAddress.address}`);
|
|
28206
|
+
}
|
|
28207
|
+
}
|
|
28208
|
+
return result;
|
|
28209
|
+
}
|
|
28210
|
+
/**
|
|
28211
|
+
* Gets all available LST assets and their APRs
|
|
28212
|
+
* @returns Promise<Map<string, LSTStats>> Map of asset address to LST stats
|
|
28213
|
+
*/
|
|
28214
|
+
static async getAllLSTStats() {
|
|
28215
|
+
const stats = await this.getLSTStats();
|
|
28216
|
+
const result = /* @__PURE__ */ new Map();
|
|
28217
|
+
for (const stat of stats) {
|
|
28218
|
+
result.set(stat.assetAddress, stat);
|
|
28219
|
+
}
|
|
28220
|
+
return result;
|
|
28221
|
+
}
|
|
28222
|
+
/**
|
|
28223
|
+
* Clears the cache (useful for testing or forcing refresh)
|
|
28224
|
+
*/
|
|
28225
|
+
static clearCache() {
|
|
28226
|
+
this.cache = null;
|
|
28227
|
+
this.cacheTimestamp = 0;
|
|
28228
|
+
logger.verbose(`LSTAPRService: Cache cleared`);
|
|
28229
|
+
}
|
|
28230
|
+
};
|
|
28231
|
+
LSTAPRService.ENDUR_API_URL = "https://app.endur.fi/api/lst/stats";
|
|
28232
|
+
LSTAPRService.cache = null;
|
|
28233
|
+
LSTAPRService.cacheTimestamp = 0;
|
|
28234
|
+
LSTAPRService.CACHE_DURATION = 5 * 60 * 1e3;
|
|
28235
|
+
|
|
28113
28236
|
// src/notifs/telegram.ts
|
|
28114
28237
|
var import_node_telegram_bot_api = __toESM(require("node-telegram-bot-api"));
|
|
28115
28238
|
var TelegramNotif = class {
|
|
@@ -28638,6 +28761,7 @@ var deployer_default = Deployer;
|
|
|
28638
28761
|
HyperLSTStrategies,
|
|
28639
28762
|
ILending,
|
|
28640
28763
|
Initializable,
|
|
28764
|
+
LSTAPRService,
|
|
28641
28765
|
MarginType,
|
|
28642
28766
|
Network,
|
|
28643
28767
|
PRICE_ROUTER,
|
package/dist/index.mjs
CHANGED
|
@@ -16556,7 +16556,7 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
|
16556
16556
|
return [baseFlow, rebalanceFlow];
|
|
16557
16557
|
}
|
|
16558
16558
|
};
|
|
16559
|
-
var _description2 = "Deploys your {{POOL_NAME}} into an Ekubo liquidity pool, automatically rebalancing positions around the current price to optimize yield and reduce the need for manual adjustments. Trading fees and
|
|
16559
|
+
var _description2 = "Deploys your {{POOL_NAME}} into an Ekubo liquidity pool, automatically rebalancing positions around the current price to optimize yield and reduce the need for manual adjustments. Trading fees and any rewards are automatically compounded back into the strategy. In return, you receive an ERC-20 token representing your share of the strategy";
|
|
16560
16560
|
var _protocol2 = {
|
|
16561
16561
|
name: "Ekubo",
|
|
16562
16562
|
logo: "https://app.ekubo.org/favicon.ico"
|
|
@@ -16601,7 +16601,7 @@ var faqs2 = [
|
|
|
16601
16601
|
},
|
|
16602
16602
|
{
|
|
16603
16603
|
question: "How are trading fees and rewards handled?",
|
|
16604
|
-
answer: "Trading fees and
|
|
16604
|
+
answer: "Trading fees and any rewards are automatically compounded back into the strategy, increasing your overall returns."
|
|
16605
16605
|
},
|
|
16606
16606
|
{
|
|
16607
16607
|
question: "What happens during withdrawal?",
|
|
@@ -16978,7 +16978,7 @@ EkuboCLVaultStrategies.forEach((s) => {
|
|
|
16978
16978
|
s.investmentSteps = [
|
|
16979
16979
|
"Supply tokens to Ekubo's pool",
|
|
16980
16980
|
"Monitor and Rebalance position to optimize yield",
|
|
16981
|
-
"Harvest and
|
|
16981
|
+
"Harvest and re-invest any rewards every week (Auto-compound)"
|
|
16982
16982
|
];
|
|
16983
16983
|
});
|
|
16984
16984
|
|
|
@@ -26704,12 +26704,21 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
26704
26704
|
logger.verbose(`${this.metadata.name}::netAPY: positions: ${JSON.stringify(positions)}`);
|
|
26705
26705
|
const baseAPYs = [];
|
|
26706
26706
|
const rewardAPYs = [];
|
|
26707
|
+
const collateralAddresses = vesuAdapters.map((adapter) => adapter.config.collateral.address);
|
|
26708
|
+
let lstAPRs;
|
|
26709
|
+
try {
|
|
26710
|
+
lstAPRs = await LSTAPRService.getLSTAPRs(collateralAddresses);
|
|
26711
|
+
} catch (error) {
|
|
26712
|
+
logger.warn(`${this.metadata.name}::netAPY: Failed to fetch LST APRs from Endur API, using fallback: ${error}`);
|
|
26713
|
+
lstAPRs = /* @__PURE__ */ new Map();
|
|
26714
|
+
}
|
|
26707
26715
|
for (const [index, pool] of pools.entries()) {
|
|
26708
26716
|
const vesuAdapter = vesuAdapters[index];
|
|
26709
26717
|
const collateralAsset = pool.assets.find((a) => a.symbol.toLowerCase() === vesuAdapter.config.collateral.symbol.toLowerCase())?.stats;
|
|
26710
26718
|
const debtAsset = pool.assets.find((a) => a.symbol.toLowerCase() === vesuAdapter.config.debt.symbol.toLowerCase())?.stats;
|
|
26711
26719
|
const supplyApy = Number(collateralAsset.supplyApy.value || 0) / 1e18;
|
|
26712
|
-
const lstAPY =
|
|
26720
|
+
const lstAPY = lstAPRs.get(vesuAdapter.config.collateral.address.address) || 0;
|
|
26721
|
+
logger.verbose(`${this.metadata.name}::netAPY: ${vesuAdapter.config.collateral.symbol} LST APR from Endur: ${lstAPY}`);
|
|
26713
26722
|
baseAPYs.push(...[supplyApy + lstAPY, Number(debtAsset.borrowApr.value) / 1e18]);
|
|
26714
26723
|
rewardAPYs.push(...[Number(collateralAsset.defiSpringSupplyApr?.value || "0") / 1e18, 0]);
|
|
26715
26724
|
}
|
|
@@ -26933,6 +26942,18 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
26933
26942
|
getTag() {
|
|
26934
26943
|
return `${_UniversalStrategy.name}:${this.metadata.name}`;
|
|
26935
26944
|
}
|
|
26945
|
+
/**
|
|
26946
|
+
* Gets LST APR for the strategy's underlying asset from Endur API
|
|
26947
|
+
* @returns Promise<number> The LST APR (not divided by 1e18)
|
|
26948
|
+
*/
|
|
26949
|
+
async getLSTAPR() {
|
|
26950
|
+
try {
|
|
26951
|
+
return await LSTAPRService.getLSTAPR(this.asset().address);
|
|
26952
|
+
} catch (error) {
|
|
26953
|
+
logger.warn(`${this.getTag()}: Failed to get LST APR: ${error}`);
|
|
26954
|
+
return 0;
|
|
26955
|
+
}
|
|
26956
|
+
}
|
|
26936
26957
|
async getVesuHealthFactors() {
|
|
26937
26958
|
return await Promise.all(this.getVesuAdapters().map((v) => v.getHealthFactor()));
|
|
26938
26959
|
}
|
|
@@ -28013,6 +28034,107 @@ var PricerLST2 = class extends Pricer {
|
|
|
28013
28034
|
}
|
|
28014
28035
|
};
|
|
28015
28036
|
|
|
28037
|
+
// src/modules/lst-apr.ts
|
|
28038
|
+
var LSTAPRService = class {
|
|
28039
|
+
// 5 minutes
|
|
28040
|
+
/**
|
|
28041
|
+
* Fetches LST stats from Endur API with caching
|
|
28042
|
+
* @returns Promise<LSTStats[]> Array of LST statistics
|
|
28043
|
+
*/
|
|
28044
|
+
static async getLSTStats() {
|
|
28045
|
+
const now = Date.now();
|
|
28046
|
+
if (this.cache && now - this.cacheTimestamp < this.CACHE_DURATION) {
|
|
28047
|
+
logger.verbose(`LSTAPRService: Returning cached LST stats`);
|
|
28048
|
+
return this.cache;
|
|
28049
|
+
}
|
|
28050
|
+
try {
|
|
28051
|
+
logger.verbose(`LSTAPRService: Fetching LST stats from Endur API`);
|
|
28052
|
+
const response = await fetch(this.ENDUR_API_URL);
|
|
28053
|
+
if (!response.ok) {
|
|
28054
|
+
throw new Error(`Failed to fetch LST stats: ${response.status} ${response.statusText}`);
|
|
28055
|
+
}
|
|
28056
|
+
const data = await response.json();
|
|
28057
|
+
if (!Array.isArray(data)) {
|
|
28058
|
+
throw new Error("Invalid response format: expected array");
|
|
28059
|
+
}
|
|
28060
|
+
this.cache = data;
|
|
28061
|
+
this.cacheTimestamp = now;
|
|
28062
|
+
logger.verbose(`LSTAPRService: Successfully fetched ${data.length} LST stats`);
|
|
28063
|
+
return data;
|
|
28064
|
+
} catch (error) {
|
|
28065
|
+
logger.error(`LSTAPRService: Error fetching LST stats: ${error}`);
|
|
28066
|
+
if (this.cache) {
|
|
28067
|
+
logger.warn(`LSTAPRService: Returning stale cached data due to API error`);
|
|
28068
|
+
return this.cache;
|
|
28069
|
+
}
|
|
28070
|
+
throw error;
|
|
28071
|
+
}
|
|
28072
|
+
}
|
|
28073
|
+
/**
|
|
28074
|
+
* Gets LST APR for a specific asset address
|
|
28075
|
+
* @param assetAddress - The contract address of the underlying asset
|
|
28076
|
+
* @returns Promise<number> The LST APR (not divided by 1e18)
|
|
28077
|
+
*/
|
|
28078
|
+
static async getLSTAPR(assetAddress) {
|
|
28079
|
+
const stats = await this.getLSTStats();
|
|
28080
|
+
const lstStat = stats.find(
|
|
28081
|
+
(stat) => ContractAddr.eqString(stat.assetAddress, assetAddress.address)
|
|
28082
|
+
);
|
|
28083
|
+
if (!lstStat) {
|
|
28084
|
+
logger.warn(`LSTAPRService: No LST stats found for asset address ${assetAddress.address}`);
|
|
28085
|
+
return 0;
|
|
28086
|
+
}
|
|
28087
|
+
logger.verbose(`LSTAPRService: Found LST APR for ${lstStat.asset}: ${lstStat.apy} (${lstStat.apyInPercentage})`);
|
|
28088
|
+
return lstStat.apy;
|
|
28089
|
+
}
|
|
28090
|
+
/**
|
|
28091
|
+
* Gets LST APR for multiple asset addresses
|
|
28092
|
+
* @param assetAddresses - Array of contract addresses
|
|
28093
|
+
* @returns Promise<Map<string, number>> Map of asset address to LST APR
|
|
28094
|
+
*/
|
|
28095
|
+
static async getLSTAPRs(assetAddresses) {
|
|
28096
|
+
const stats = await this.getLSTStats();
|
|
28097
|
+
const result = /* @__PURE__ */ new Map();
|
|
28098
|
+
for (const assetAddress of assetAddresses) {
|
|
28099
|
+
const lstStat = stats.find(
|
|
28100
|
+
(stat) => ContractAddr.eqString(stat.assetAddress, assetAddress.address)
|
|
28101
|
+
);
|
|
28102
|
+
if (lstStat) {
|
|
28103
|
+
result.set(assetAddress.address, lstStat.apy);
|
|
28104
|
+
logger.verbose(`LSTAPRService: Found LST APR for ${lstStat.asset}: ${lstStat.apy}`);
|
|
28105
|
+
} else {
|
|
28106
|
+
result.set(assetAddress.address, 0);
|
|
28107
|
+
logger.warn(`LSTAPRService: No LST stats found for asset address ${assetAddress.address}`);
|
|
28108
|
+
}
|
|
28109
|
+
}
|
|
28110
|
+
return result;
|
|
28111
|
+
}
|
|
28112
|
+
/**
|
|
28113
|
+
* Gets all available LST assets and their APRs
|
|
28114
|
+
* @returns Promise<Map<string, LSTStats>> Map of asset address to LST stats
|
|
28115
|
+
*/
|
|
28116
|
+
static async getAllLSTStats() {
|
|
28117
|
+
const stats = await this.getLSTStats();
|
|
28118
|
+
const result = /* @__PURE__ */ new Map();
|
|
28119
|
+
for (const stat of stats) {
|
|
28120
|
+
result.set(stat.assetAddress, stat);
|
|
28121
|
+
}
|
|
28122
|
+
return result;
|
|
28123
|
+
}
|
|
28124
|
+
/**
|
|
28125
|
+
* Clears the cache (useful for testing or forcing refresh)
|
|
28126
|
+
*/
|
|
28127
|
+
static clearCache() {
|
|
28128
|
+
this.cache = null;
|
|
28129
|
+
this.cacheTimestamp = 0;
|
|
28130
|
+
logger.verbose(`LSTAPRService: Cache cleared`);
|
|
28131
|
+
}
|
|
28132
|
+
};
|
|
28133
|
+
LSTAPRService.ENDUR_API_URL = "https://app.endur.fi/api/lst/stats";
|
|
28134
|
+
LSTAPRService.cache = null;
|
|
28135
|
+
LSTAPRService.cacheTimestamp = 0;
|
|
28136
|
+
LSTAPRService.CACHE_DURATION = 5 * 60 * 1e3;
|
|
28137
|
+
|
|
28016
28138
|
// src/notifs/telegram.ts
|
|
28017
28139
|
import TelegramBot from "node-telegram-bot-api";
|
|
28018
28140
|
var TelegramNotif = class {
|
|
@@ -28540,6 +28662,7 @@ export {
|
|
|
28540
28662
|
HyperLSTStrategies,
|
|
28541
28663
|
ILending,
|
|
28542
28664
|
Initializable,
|
|
28665
|
+
LSTAPRService,
|
|
28543
28666
|
MarginType,
|
|
28544
28667
|
Network,
|
|
28545
28668
|
PRICE_ROUTER,
|
package/package.json
CHANGED
package/src/modules/index.ts
CHANGED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { ContractAddr } from "@/dataTypes";
|
|
2
|
+
import { logger } from "@/utils";
|
|
3
|
+
|
|
4
|
+
export interface LSTStats {
|
|
5
|
+
asset: string;
|
|
6
|
+
assetAddress: string;
|
|
7
|
+
lstAddress: string;
|
|
8
|
+
tvlUsd: number;
|
|
9
|
+
tvlAsset: number;
|
|
10
|
+
apy: number;
|
|
11
|
+
apyInPercentage: string;
|
|
12
|
+
exchangeRate: number;
|
|
13
|
+
preciseExchangeRate: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class LSTAPRService {
|
|
17
|
+
private static readonly ENDUR_API_URL = 'https://app.endur.fi/api/lst/stats';
|
|
18
|
+
private static cache: LSTStats[] | null = null;
|
|
19
|
+
private static cacheTimestamp: number = 0;
|
|
20
|
+
private static readonly CACHE_DURATION = 5 * 60 * 1000; // 5 minutes
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Fetches LST stats from Endur API with caching
|
|
24
|
+
* @returns Promise<LSTStats[]> Array of LST statistics
|
|
25
|
+
*/
|
|
26
|
+
static async getLSTStats(): Promise<LSTStats[]> {
|
|
27
|
+
const now = Date.now();
|
|
28
|
+
|
|
29
|
+
// Return cached data if still valid
|
|
30
|
+
if (this.cache && (now - this.cacheTimestamp) < this.CACHE_DURATION) {
|
|
31
|
+
logger.verbose(`LSTAPRService: Returning cached LST stats`);
|
|
32
|
+
return this.cache;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
logger.verbose(`LSTAPRService: Fetching LST stats from Endur API`);
|
|
37
|
+
const response = await fetch(this.ENDUR_API_URL);
|
|
38
|
+
|
|
39
|
+
if (!response.ok) {
|
|
40
|
+
throw new Error(`Failed to fetch LST stats: ${response.status} ${response.statusText}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const data: LSTStats[] = await response.json();
|
|
44
|
+
|
|
45
|
+
// Validate the response structure
|
|
46
|
+
if (!Array.isArray(data)) {
|
|
47
|
+
throw new Error('Invalid response format: expected array');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Cache the data
|
|
51
|
+
this.cache = data;
|
|
52
|
+
this.cacheTimestamp = now;
|
|
53
|
+
|
|
54
|
+
logger.verbose(`LSTAPRService: Successfully fetched ${data.length} LST stats`);
|
|
55
|
+
return data;
|
|
56
|
+
|
|
57
|
+
} catch (error) {
|
|
58
|
+
logger.error(`LSTAPRService: Error fetching LST stats: ${error}`);
|
|
59
|
+
|
|
60
|
+
// Return cached data if available, even if expired
|
|
61
|
+
if (this.cache) {
|
|
62
|
+
logger.warn(`LSTAPRService: Returning stale cached data due to API error`);
|
|
63
|
+
return this.cache;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Gets LST APR for a specific asset address
|
|
72
|
+
* @param assetAddress - The contract address of the underlying asset
|
|
73
|
+
* @returns Promise<number> The LST APR (not divided by 1e18)
|
|
74
|
+
*/
|
|
75
|
+
static async getLSTAPR(assetAddress: ContractAddr): Promise<number> {
|
|
76
|
+
const stats = await this.getLSTStats();
|
|
77
|
+
|
|
78
|
+
const lstStat = stats.find(stat =>
|
|
79
|
+
ContractAddr.eqString(stat.assetAddress, assetAddress.address)
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
if (!lstStat) {
|
|
83
|
+
logger.warn(`LSTAPRService: No LST stats found for asset address ${assetAddress.address}`);
|
|
84
|
+
return 0;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
logger.verbose(`LSTAPRService: Found LST APR for ${lstStat.asset}: ${lstStat.apy} (${lstStat.apyInPercentage})`);
|
|
88
|
+
return lstStat.apy;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Gets LST APR for multiple asset addresses
|
|
93
|
+
* @param assetAddresses - Array of contract addresses
|
|
94
|
+
* @returns Promise<Map<string, number>> Map of asset address to LST APR
|
|
95
|
+
*/
|
|
96
|
+
static async getLSTAPRs(assetAddresses: ContractAddr[]): Promise<Map<string, number>> {
|
|
97
|
+
const stats = await this.getLSTStats();
|
|
98
|
+
const result = new Map<string, number>();
|
|
99
|
+
|
|
100
|
+
for (const assetAddress of assetAddresses) {
|
|
101
|
+
const lstStat = stats.find(stat =>
|
|
102
|
+
ContractAddr.eqString(stat.assetAddress, assetAddress.address)
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
if (lstStat) {
|
|
106
|
+
result.set(assetAddress.address, lstStat.apy);
|
|
107
|
+
logger.verbose(`LSTAPRService: Found LST APR for ${lstStat.asset}: ${lstStat.apy}`);
|
|
108
|
+
} else {
|
|
109
|
+
result.set(assetAddress.address, 0);
|
|
110
|
+
logger.warn(`LSTAPRService: No LST stats found for asset address ${assetAddress.address}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Gets all available LST assets and their APRs
|
|
119
|
+
* @returns Promise<Map<string, LSTStats>> Map of asset address to LST stats
|
|
120
|
+
*/
|
|
121
|
+
static async getAllLSTStats(): Promise<Map<string, LSTStats>> {
|
|
122
|
+
const stats = await this.getLSTStats();
|
|
123
|
+
const result = new Map<string, LSTStats>();
|
|
124
|
+
|
|
125
|
+
for (const stat of stats) {
|
|
126
|
+
result.set(stat.assetAddress, stat);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Clears the cache (useful for testing or forcing refresh)
|
|
134
|
+
*/
|
|
135
|
+
static clearCache(): void {
|
|
136
|
+
this.cache = null;
|
|
137
|
+
this.cacheTimestamp = 0;
|
|
138
|
+
logger.verbose(`LSTAPRService: Cache cleared`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -1751,7 +1751,7 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
1751
1751
|
}
|
|
1752
1752
|
|
|
1753
1753
|
const _description =
|
|
1754
|
-
"Deploys your {{POOL_NAME}} into an Ekubo liquidity pool, automatically rebalancing positions around the current price to optimize yield and reduce the need for manual adjustments. Trading fees and
|
|
1754
|
+
"Deploys your {{POOL_NAME}} into an Ekubo liquidity pool, automatically rebalancing positions around the current price to optimize yield and reduce the need for manual adjustments. Trading fees and any rewards are automatically compounded back into the strategy. In return, you receive an ERC-20 token representing your share of the strategy";
|
|
1755
1755
|
const _protocol: IProtocol = {
|
|
1756
1756
|
name: "Ekubo",
|
|
1757
1757
|
logo: "https://app.ekubo.org/favicon.ico",
|
|
@@ -1812,7 +1812,7 @@ const faqs: FAQ[] = [
|
|
|
1812
1812
|
{
|
|
1813
1813
|
question: "How are trading fees and rewards handled?",
|
|
1814
1814
|
answer:
|
|
1815
|
-
"Trading fees and
|
|
1815
|
+
"Trading fees and any rewards are automatically compounded back into the strategy, increasing your overall returns.",
|
|
1816
1816
|
},
|
|
1817
1817
|
{
|
|
1818
1818
|
question: "What happens during withdrawal?",
|
|
@@ -2217,6 +2217,6 @@ EkuboCLVaultStrategies.forEach((s) => {
|
|
|
2217
2217
|
s.investmentSteps = [
|
|
2218
2218
|
"Supply tokens to Ekubo's pool",
|
|
2219
2219
|
"Monitor and Rebalance position to optimize yield",
|
|
2220
|
-
"Harvest and
|
|
2220
|
+
"Harvest and re-invest any rewards every week (Auto-compound)",
|
|
2221
2221
|
]
|
|
2222
2222
|
});
|
|
@@ -9,7 +9,7 @@ import UniversalVaultAbi from '../data/universal-vault.abi.json';
|
|
|
9
9
|
import ManagerAbi from '../data/vault-manager.abi.json';
|
|
10
10
|
import { ApproveCallParams, AvnuSwapCallParams, BaseAdapter, CommonAdapter, FlashloanCallParams, GenerateCallFn, LeafAdapterFn, ManageCall, VesuAdapter, VesuDefiSpringRewardsCallParams, VesuModifyPositionCallParams, VesuPools } from "./universal-adapters";
|
|
11
11
|
import { Global } from "@/global";
|
|
12
|
-
import { AvnuWrapper, ERC20 } from "@/modules";
|
|
12
|
+
import { AvnuWrapper, ERC20, LSTAPRService } from "@/modules";
|
|
13
13
|
import { AVNU_MIDDLEWARE, VESU_SINGLETON } from "./universal-adapters/adapter-utils";
|
|
14
14
|
import { VesuHarvests } from "@/modules/harvests";
|
|
15
15
|
|
|
@@ -227,12 +227,28 @@ export class UniversalStrategy<
|
|
|
227
227
|
logger.verbose(`${this.metadata.name}::netAPY: positions: ${JSON.stringify(positions)}`);
|
|
228
228
|
const baseAPYs: number[] = [];
|
|
229
229
|
const rewardAPYs: number[] = [];
|
|
230
|
+
|
|
231
|
+
// Get LST APRs for all collateral assets with fallback
|
|
232
|
+
const collateralAddresses = vesuAdapters.map(adapter => adapter.config.collateral.address);
|
|
233
|
+
let lstAPRs: Map<string, number>;
|
|
234
|
+
try {
|
|
235
|
+
lstAPRs = await LSTAPRService.getLSTAPRs(collateralAddresses);
|
|
236
|
+
} catch (error) {
|
|
237
|
+
logger.warn(`${this.metadata.name}::netAPY: Failed to fetch LST APRs from Endur API, using fallback: ${error}`);
|
|
238
|
+
// Fallback: create empty map (will result in 0 LST APR)
|
|
239
|
+
lstAPRs = new Map();
|
|
240
|
+
}
|
|
241
|
+
|
|
230
242
|
for (const [index, pool] of pools.entries()) {
|
|
231
243
|
const vesuAdapter = vesuAdapters[index];
|
|
232
244
|
const collateralAsset = pool.assets.find((a: any) => a.symbol.toLowerCase() === vesuAdapter.config.collateral.symbol.toLowerCase())?.stats!;
|
|
233
245
|
const debtAsset = pool.assets.find((a: any) => a.symbol.toLowerCase() === vesuAdapter.config.debt.symbol.toLowerCase())?.stats!;
|
|
234
246
|
const supplyApy = Number(collateralAsset.supplyApy.value || 0) / 1e18;
|
|
235
|
-
|
|
247
|
+
|
|
248
|
+
// Use LST APR from Endur API instead of Vesu's lstApr
|
|
249
|
+
const lstAPY = lstAPRs.get(vesuAdapter.config.collateral.address.address) || 0;
|
|
250
|
+
logger.verbose(`${this.metadata.name}::netAPY: ${vesuAdapter.config.collateral.symbol} LST APR from Endur: ${lstAPY}`);
|
|
251
|
+
|
|
236
252
|
baseAPYs.push(...[supplyApy + lstAPY, Number(debtAsset.borrowApr.value) / 1e18]);
|
|
237
253
|
rewardAPYs.push(...[Number(collateralAsset.defiSpringSupplyApr?.value || "0") / 1e18, 0]);
|
|
238
254
|
}
|
|
@@ -501,6 +517,19 @@ export class UniversalStrategy<
|
|
|
501
517
|
return `${UniversalStrategy.name}:${this.metadata.name}`;
|
|
502
518
|
}
|
|
503
519
|
|
|
520
|
+
/**
|
|
521
|
+
* Gets LST APR for the strategy's underlying asset from Endur API
|
|
522
|
+
* @returns Promise<number> The LST APR (not divided by 1e18)
|
|
523
|
+
*/
|
|
524
|
+
async getLSTAPR(): Promise<number> {
|
|
525
|
+
try {
|
|
526
|
+
return await LSTAPRService.getLSTAPR(this.asset().address);
|
|
527
|
+
} catch (error) {
|
|
528
|
+
logger.warn(`${this.getTag()}: Failed to get LST APR: ${error}`);
|
|
529
|
+
return 0;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
504
533
|
async getVesuHealthFactors() {
|
|
505
534
|
return await Promise.all(this.getVesuAdapters().map(v => v.getHealthFactor()));
|
|
506
535
|
}
|