@strkfarm/sdk 1.1.25 → 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 +126 -3
- package/dist/index.browser.mjs +124 -1
- package/dist/index.d.ts +50 -1
- package/dist/index.js +125 -1
- package/dist/index.mjs +124 -1
- package/package.json +1 -1
- package/src/modules/index.ts +2 -1
- package/src/modules/lst-apr.ts +140 -0
- 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) => {
|
|
@@ -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";
|
|
@@ -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,
|
|
@@ -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
|
@@ -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
|
+
}
|
|
@@ -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
|
}
|