@strkfarm/sdk 1.1.25 → 1.1.27
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 +231 -112
- package/dist/index.browser.mjs +125 -1
- package/dist/index.d.ts +50 -1
- package/dist/index.js +126 -1
- package/dist/index.mjs +125 -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
|
@@ -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 underlyingAddresses = vesuAdapters.map(adapter => adapter.config.debt.address);
|
|
233
|
+
let lstAPRs: Map<string, number>;
|
|
234
|
+
try {
|
|
235
|
+
lstAPRs = await LSTAPRService.getLSTAPRs(underlyingAddresses);
|
|
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.debt.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
|
}
|