@strkfarm/sdk 2.0.0-staging.1 → 2.0.0-staging.10

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.
@@ -0,0 +1,159 @@
1
+ import { IConfig, IStrategyMetadata } from "@/interfaces";
2
+ import { PricerBase } from "@/modules/pricerBase";
3
+ import {
4
+ UniversalStrategy,
5
+ UniversalStrategySettings
6
+ } from "./universal-strategy";
7
+ import { EkuboCLVault, CLVaultStrategySettings } from "./ekubo-cl-vault";
8
+ import {
9
+ UniversalLstMultiplierStrategy,
10
+ HyperLSTStrategySettings
11
+ } from "./universal-lst-muliplier-strategy";
12
+ import { VesuRebalance, VesuRebalanceSettings } from "./vesu-rebalance";
13
+ import { SenseiVault, SenseiVaultSettings } from "./sensei";
14
+
15
+ export enum FactoryStrategyType {
16
+ UNIVERSAL = "UNIVERSAL",
17
+ EKUBO_CL = "EKUBO_CL",
18
+ HYPER_LST = "HYPER_LST",
19
+ VESU_REBALANCE = "VESU_REBALANCE",
20
+ SENSEI = "SENSEI"
21
+ }
22
+
23
+ export function createUniversalStrategy(
24
+ config: IConfig,
25
+ pricer: PricerBase,
26
+ metadata: IStrategyMetadata<UniversalStrategySettings>
27
+ ): UniversalStrategy<UniversalStrategySettings> {
28
+ return new UniversalStrategy(config, pricer, metadata);
29
+ }
30
+
31
+ export function createEkuboCLStrategy(
32
+ config: IConfig,
33
+ pricer: PricerBase,
34
+ metadata: IStrategyMetadata<CLVaultStrategySettings>
35
+ ): EkuboCLVault {
36
+ return new EkuboCLVault(config, pricer, metadata);
37
+ }
38
+
39
+ export function createHyperLSTStrategy(
40
+ config: IConfig,
41
+ pricer: PricerBase,
42
+ metadata: IStrategyMetadata<HyperLSTStrategySettings>
43
+ ): UniversalLstMultiplierStrategy {
44
+ return new UniversalLstMultiplierStrategy(config, pricer, metadata);
45
+ }
46
+
47
+ export function createVesuRebalanceStrategy(
48
+ config: IConfig,
49
+ pricer: PricerBase,
50
+ metadata: IStrategyMetadata<VesuRebalanceSettings>
51
+ ): VesuRebalance {
52
+ return new VesuRebalance(config, pricer, metadata);
53
+ }
54
+
55
+ export function createSenseiStrategy(
56
+ config: IConfig,
57
+ pricer: PricerBase,
58
+ metadata: IStrategyMetadata<SenseiVaultSettings>
59
+ ): SenseiVault {
60
+ return new SenseiVault(config, pricer, metadata);
61
+ }
62
+
63
+ /**
64
+ * Determines the strategy type from metadata by inspecting the additionalInfo structure
65
+ */
66
+ export function getStrategyTypeFromMetadata(
67
+ metadata: IStrategyMetadata<any>
68
+ ): FactoryStrategyType {
69
+ const info = metadata.additionalInfo;
70
+
71
+ // Check for HyperLST (extends UniversalStrategySettings with borrowable_assets and underlyingToken)
72
+ if (info && "borrowable_assets" in info && "underlyingToken" in info) {
73
+ return FactoryStrategyType.HYPER_LST;
74
+ }
75
+
76
+ // Check for EkuboCL (has newBounds, rebalanceConditions, quoteAsset)
77
+ if (
78
+ info &&
79
+ ("newBounds" in info || typeof info.newBounds !== "undefined") &&
80
+ "rebalanceConditions" in info &&
81
+ "quoteAsset" in info
82
+ ) {
83
+ return FactoryStrategyType.EKUBO_CL;
84
+ }
85
+
86
+ // Check for Sensei (has mainToken, secondaryToken, targetHfBps)
87
+ if (
88
+ info &&
89
+ "mainToken" in info &&
90
+ "secondaryToken" in info &&
91
+ "targetHfBps" in info
92
+ ) {
93
+ return FactoryStrategyType.SENSEI;
94
+ }
95
+
96
+ // Check for VesuRebalance (has feeBps, but simpler structure)
97
+ if (info && "feeBps" in info && Object.keys(info).length <= 2) {
98
+ return FactoryStrategyType.VESU_REBALANCE;
99
+ }
100
+
101
+ // Check for Universal (has vaultAddress, manager, vaultAllocator, etc.)
102
+ if (
103
+ info &&
104
+ "vaultAddress" in info &&
105
+ "manager" in info &&
106
+ "vaultAllocator" in info
107
+ ) {
108
+ return FactoryStrategyType.UNIVERSAL;
109
+ }
110
+
111
+ throw new Error(
112
+ `Unable to determine strategy type from metadata: ${metadata.id}`
113
+ );
114
+ }
115
+
116
+ /**
117
+ * Generic factory function that creates SDK strategy instances based on type
118
+ */
119
+ export function createStrategy(
120
+ type: FactoryStrategyType,
121
+ config: IConfig,
122
+ pricer: PricerBase,
123
+ metadata: IStrategyMetadata<any>
124
+ ) {
125
+ switch (type) {
126
+ case FactoryStrategyType.UNIVERSAL:
127
+ return createUniversalStrategy(
128
+ config,
129
+ pricer,
130
+ metadata as IStrategyMetadata<UniversalStrategySettings>
131
+ );
132
+ case FactoryStrategyType.EKUBO_CL:
133
+ return createEkuboCLStrategy(
134
+ config,
135
+ pricer,
136
+ metadata as IStrategyMetadata<CLVaultStrategySettings>
137
+ );
138
+ case FactoryStrategyType.HYPER_LST:
139
+ return createHyperLSTStrategy(
140
+ config,
141
+ pricer,
142
+ metadata as IStrategyMetadata<HyperLSTStrategySettings>
143
+ );
144
+ case FactoryStrategyType.VESU_REBALANCE:
145
+ return createVesuRebalanceStrategy(
146
+ config,
147
+ pricer,
148
+ metadata as IStrategyMetadata<VesuRebalanceSettings>
149
+ );
150
+ case FactoryStrategyType.SENSEI:
151
+ return createSenseiStrategy(
152
+ config,
153
+ pricer,
154
+ metadata as IStrategyMetadata<SenseiVaultSettings>
155
+ );
156
+ default:
157
+ throw new Error(`Unknown strategy type: ${type}`);
158
+ }
159
+ }
@@ -7,3 +7,4 @@ export * from './universal-adapters';
7
7
  export * from './universal-strategy';
8
8
  export * from './universal-lst-muliplier-strategy';
9
9
  export * from "./registry";
10
+ export * from "./factory";
@@ -1,9 +1,4 @@
1
- /**
2
- * Strategy Registry - Centralized strategy metadata and filtering
3
- * Provides utilities for getting strategy lists, metadata, and filter options
4
- */
5
-
6
- import { IStrategyMetadata } from "@/interfaces";
1
+ import { getAllStrategyTags, IStrategyMetadata } from "@/interfaces";
7
2
  import {
8
3
  EkuboCLVaultStrategies,
9
4
  CLVaultStrategySettings,
@@ -31,7 +26,6 @@ export interface FilterOption {
31
26
  export interface StrategyFilterMetadata {
32
27
  assets: FilterOption[];
33
28
  protocols: FilterOption[];
34
- categories: FilterOption[];
35
29
  quickFilters: FilterOption[];
36
30
  }
37
31
 
@@ -55,7 +49,6 @@ export interface StrategyMetadata {
55
49
  type: StrategyType;
56
50
  assets: string[]; // Token symbols (e.g., ["STRK", "USDC"])
57
51
  protocols: string[]; // Protocol names (e.g., ["Ekubo"])
58
- category: string; // Category (e.g., "BTC", "Meta Vaults")
59
52
  tags: string[];
60
53
  curator?: { name: string; logo: string };
61
54
  isRetired: boolean;
@@ -166,7 +159,6 @@ export function getAllStrategyMetadata(): StrategyMetadata[] {
166
159
  type: entry.type,
167
160
  assets: extractAssets(entry.metadata),
168
161
  protocols: entry.metadata.protocols.map(p => p.name.toLowerCase()),
169
- category: entry.metadata.category,
170
162
  tags: entry.metadata.tags || [],
171
163
  curator: entry.metadata.curator,
172
164
  isRetired: isRetired(entry.metadata),
@@ -178,62 +170,55 @@ export function getAllStrategyMetadata(): StrategyMetadata[] {
178
170
  * Get filter metadata - defines available filters and their options
179
171
  */
180
172
  export function getFilterMetadata(): StrategyFilterMetadata {
181
- const allMetadata = getAllStrategyMetadata();
182
-
183
- // Extract unique assets
184
- const assetSet = new Set<string>();
185
- allMetadata.forEach((meta) => {
186
- meta.assets.forEach((asset) => assetSet.add(asset));
187
- });
188
- const assets: FilterOption[] = Array.from(assetSet)
189
- .sort()
190
- .map((id) => ({
191
- id,
192
- label: id.toUpperCase(),
193
- }));
194
-
195
- // Extract unique protocols
196
- const protocolSet = new Set<string>();
197
- allMetadata.forEach((meta) => {
198
- meta.protocols.forEach((protocol) => protocolSet.add(protocol));
199
- });
200
- const protocols: FilterOption[] = Array.from(protocolSet)
201
- .sort()
202
- .map((id) => ({
203
- id,
204
- label:
205
- id === "meta-vaults"
206
- ? "Meta Vaults"
207
- : id.charAt(0).toUpperCase() + id.slice(1),
208
- }));
209
-
210
- // Extract unique categories
211
- const categorySet = new Set<string>();
212
- allMetadata.forEach((meta) => {
213
- if (meta.category) categorySet.add(meta.category);
214
- });
215
- const categories: FilterOption[] = Array.from(categorySet)
216
- .sort()
217
- .map((id) => ({
218
- id,
219
- label:
220
- id === "btc" ? "BTC" : id === "meta-vaults" ? "Meta Vaults" : "All",
221
- }));
222
-
223
- // Quick filters
224
- const quickFilters: FilterOption[] = [
225
- { id: "all", label: "All Strategies" },
226
- { id: "btc", label: "BTC" },
227
- { id: "meta-vaults", label: "Meta Vaults" },
228
- ];
229
-
230
- return {
231
- assets,
232
- protocols,
233
- categories,
234
- quickFilters,
235
- };
236
- }
173
+ const allMetadata = getAllStrategyMetadata();
174
+
175
+ // Extract unique assets
176
+ const assetSet = new Set<string>();
177
+ allMetadata.forEach((meta) => {
178
+ meta.assets.forEach((asset) => assetSet.add(asset));
179
+ });
180
+
181
+ const allowedAssets = new Set(["eth", "btc", "strk", "usdt", "usdc"]);
182
+ const assets: FilterOption[] = Array.from(assetSet)
183
+ .filter((asset) => allowedAssets.has(asset.toLowerCase()))
184
+ .sort((a, b) => {
185
+ // Sort in specific order: ETH, BTC, STRK, USDT, USDC
186
+ const order = ["eth", "btc", "strk", "usdt", "usdc"];
187
+ const aIndex = order.indexOf(a.toLowerCase());
188
+ const bIndex = order.indexOf(b.toLowerCase());
189
+ if (aIndex === -1 && bIndex === -1) return 0;
190
+ if (aIndex === -1) return 1;
191
+ if (bIndex === -1) return -1;
192
+ return aIndex - bIndex;
193
+ })
194
+ .map((id) => ({
195
+ id,
196
+ label: id.toUpperCase()
197
+ }));
198
+
199
+ // Extract unique protocols
200
+ const protocolSet = new Set<string>();
201
+ allMetadata.forEach((meta) => {
202
+ meta.protocols.forEach((protocol) => protocolSet.add(protocol));
203
+ });
204
+ const protocols: FilterOption[] = Array.from(protocolSet)
205
+ .sort()
206
+ .map((id) => ({
207
+ id,
208
+ label: id.charAt(0).toUpperCase() + id.slice(1)
209
+ }));
210
+
211
+ const quickFilters: FilterOption[] = [
212
+ { id: "all", label: "All Strategies" },
213
+ ...getAllStrategyTags().map((tag) => ({ id: tag.toLowerCase().replaceAll(" ", "-"), label: tag })),
214
+ ];
215
+
216
+ return {
217
+ assets,
218
+ protocols,
219
+ quickFilters
220
+ };
221
+ }
237
222
 
238
223
  /**
239
224
  * Get live strategies (filter out retired)
@@ -252,51 +237,3 @@ export function getStrategiesByType(
252
237
  const registry = buildStrategyRegistry();
253
238
  return registry.filter((entry) => entry.type === type);
254
239
  }
255
-
256
- /**
257
- * Get strategies by filter criteria
258
- */
259
- export interface StrategyFilterCriteria {
260
- assets?: string[];
261
- protocols?: string[];
262
- categories?: string[];
263
- showRetired?: boolean;
264
- }
265
-
266
- export function getFilteredStrategies(
267
- criteria: StrategyFilterCriteria,
268
- ): StrategyMetadata[] {
269
- let allMetadata = getAllStrategyMetadata();
270
-
271
- // Filter out retired strategies if not explicitly shown
272
- if (!criteria.showRetired) {
273
- allMetadata = allMetadata.filter((meta) => !meta.isRetired);
274
- }
275
-
276
- // Filter by assets
277
- if (criteria.assets && criteria.assets.length > 0) {
278
- allMetadata = allMetadata.filter((meta) =>
279
- meta.assets.some((asset) =>
280
- criteria.assets!.includes(asset.toLowerCase()),
281
- ),
282
- );
283
- }
284
-
285
- // Filter by protocols
286
- if (criteria.protocols && criteria.protocols.length > 0) {
287
- allMetadata = allMetadata.filter((meta) =>
288
- meta.protocols.some((protocol) =>
289
- criteria.protocols!.includes(protocol.toLowerCase()),
290
- ),
291
- );
292
- }
293
-
294
- // Filter by categories
295
- if (criteria.categories && criteria.categories.length > 0) {
296
- allMetadata = allMetadata.filter((meta) =>
297
- criteria.categories!.includes(meta.category),
298
- );
299
- }
300
-
301
- return allMetadata;
302
- }
@@ -1,7 +1,7 @@
1
- import { getNoRiskTags, highlightTextWithLinks, IConfig, IProtocol, IStrategyMetadata, RiskFactor, RiskType, StrategyCategory, StrategyTag, TokenInfo, AuditStatus, SourceCodeType, AccessControlType, InstantWithdrawalVault } from "@/interfaces";
1
+ import { getNoRiskTags, highlightTextWithLinks, IConfig, IProtocol, IStrategyMetadata, RiskFactor, RiskType, StrategyTag, TokenInfo, AuditStatus, SourceCodeType, AccessControlType, InstantWithdrawalVault, StrategyLiveStatus, VaultType } from "@/interfaces";
2
2
  import { BaseStrategy, SingleActionAmount, SingleTokenInfo } from "./base-strategy";
3
3
  import { ContractAddr, Web3Number } from "@/dataTypes";
4
- import { Call, Contract, uint256, BlockIdentifier } from "starknet";
4
+ import { Call, Contract, num, uint256, BlockIdentifier } from "starknet";
5
5
  import SenseiABI from "@/data/sensei.abi.json";
6
6
  import { getTrovesEndpoint, logger } from "@/utils";
7
7
  import { Global } from "@/global";
@@ -11,6 +11,8 @@ import ERC20ABI from "@/data/erc20.abi.json";
11
11
  import { AvnuWrapper } from "@/modules";
12
12
  import { gql } from "@apollo/client";
13
13
  import apolloClient from "@/modules/apollo-client";
14
+ import { VesuAdapter, VesuPools } from "./universal-adapters/vesu-adapter";
15
+ import { LSTAPRService } from "@/modules/lst-apr";
14
16
 
15
17
  export interface SenseiVaultSettings {
16
18
  mainToken: TokenInfo;
@@ -236,12 +238,111 @@ export class SenseiVault extends BaseStrategy<
236
238
  return settings;
237
239
  };
238
240
 
241
+ async netAPY(): Promise<number> {
242
+ try {
243
+ // Fetch Vesu pools and select the Re7 xSTRK pool
244
+ const { pools } = await VesuAdapter.getVesuPools();
245
+ const re7PoolId = VesuPools.Re7xSTRK;
246
+ const pool = pools.find((p: any) =>
247
+ ContractAddr.from(num.getHexString(p.id)).eq(re7PoolId),
248
+ );
249
+
250
+ if (!pool) {
251
+ logger.warn(`${SenseiVault.name}::netAPY - Re7 xSTRK pool not found`);
252
+ return 0;
253
+ }
254
+
255
+ const mainSymbol = this.metadata.additionalInfo.mainToken.symbol.toLowerCase(); // STRK
256
+ const secondarySymbol =
257
+ this.metadata.additionalInfo.secondaryToken.symbol.toLowerCase(); // xSTRK
258
+
259
+ const collateralAssetStats = pool.assets.find(
260
+ (a: any) => String(a.symbol).toLowerCase() === secondarySymbol,
261
+ )?.stats;
262
+ const debtAssetStats = pool.assets.find(
263
+ (a: any) => String(a.symbol).toLowerCase() === mainSymbol,
264
+ )?.stats;
265
+
266
+ if (!collateralAssetStats || !debtAssetStats) {
267
+ logger.warn(
268
+ `${SenseiVault.name}::netAPY - Missing collateral/debt stats on Vesu pool`,
269
+ );
270
+ return 0;
271
+ }
272
+
273
+ // Base xSTRK lending APY from Vesu
274
+ const xstrkSupplyAPY =
275
+ Number(collateralAssetStats.supplyApy?.value || 0) / 1e18;
276
+
277
+ // STRK rewards APR on xSTRK collateral from Vesu
278
+ const strkRewardsAPR = collateralAssetStats.defiSpringSupplyApr
279
+ ? Number(collateralAssetStats.defiSpringSupplyApr.value || 0) / 1e18
280
+ : 0;
281
+
282
+ // STRK borrow APY from Vesu
283
+ const borrowAPY =
284
+ Number(debtAssetStats.borrowApr?.value || 0) / 1e18;
285
+
286
+ // LST APR for xSTRK from Endur (based on underlying STRK asset)
287
+ const lstAPY = await LSTAPRService.getLSTAPR(
288
+ this.metadata.additionalInfo.mainToken.address,
289
+ );
290
+
291
+ // Collateral APY = Vesu xSTRK supply + Endur xSTRK APR + STRK rewards
292
+ const collateralAPY = xstrkSupplyAPY + lstAPY + strkRewardsAPR;
293
+
294
+ const feeFactor = this.metadata.additionalInfo.feeBps / 10000; // convert bps to decimal
295
+ const feeAdjustedColAPY =
296
+ collateralAPY - strkRewardsAPR * feeFactor;
297
+
298
+ // Position info (collateral & debt in USD terms)
299
+ const { collateralUSDValue, debtUSDValue } =
300
+ await this.getPositionInfo();
301
+
302
+ const collateralUSD = Number(collateralUSDValue.toFixed(6));
303
+ const debtUSD = Number(debtUSDValue.toFixed(6));
304
+
305
+ // Compute expected leverage using the same math as app-side strategy
306
+ const targetHf = this.metadata.additionalInfo.targetHfBps / 10000;
307
+ const xSTRKPrice = await this.getSecondaryTokenPriceRelativeToMain();
308
+ const denominator = targetHf * xSTRKPrice - 0.87;
309
+ if (denominator <= 0) {
310
+ logger.warn(
311
+ `${SenseiVault.name}::netAPY - Invalid denominator in leverage calc`,
312
+ );
313
+ return 0;
314
+ }
315
+ const borrowedSTRK = (0.87 * xSTRKPrice) / denominator;
316
+ const expectedLeverage = 1 + borrowedSTRK;
317
+ if (!Number.isFinite(expectedLeverage) || expectedLeverage <= 0) {
318
+ logger.warn(
319
+ `${SenseiVault.name}::netAPY - Non-positive or invalid expectedLeverage`,
320
+ );
321
+ return 0;
322
+ }
323
+
324
+ const payoff =
325
+ collateralUSD * feeAdjustedColAPY - debtUSD * borrowAPY;
326
+ const investment = collateralUSD - debtUSD;
327
+
328
+ if (investment === 0) {
329
+ return 0;
330
+ }
331
+
332
+ const netAPY = payoff / investment;
333
+ return Number.isFinite(netAPY) ? netAPY : 0;
334
+ } catch (error) {
335
+ logger.error(`${SenseiVault.name}::netAPY - Error`, error);
336
+ return 0;
337
+ }
338
+ }
339
+
239
340
  /**
240
341
  * Calculates user realized APY based on position growth accounting for deposits and withdrawals.
241
342
  * Returns the APY as a number.
343
+ * Not implemented for Sensei Strategy yet.
242
344
  */
243
345
  async getUserRealizedAPY(
244
- userAddress: ContractAddr,
245
346
  blockIdentifier: BlockIdentifier = "latest",
246
347
  sinceBlocks = 600000
247
348
  ): Promise<number> {
@@ -453,9 +554,10 @@ const FAQS = [
453
554
  export const SenseiStrategies: IStrategyMetadata<SenseiVaultSettings>[] =
454
555
  [
455
556
  {
557
+ id: "xstrk_sensei",
456
558
  name: "xSTRK Sensei",
457
559
  description: highlightTextWithLinks(
458
- senseiDescription.replaceAll('{{token1}}', 'STRK').replaceAll('{{token2}}', 'xSTRK'),
560
+ senseiDescription.replace('{{token1}}', 'STRK').replace('{{token2}}', 'xSTRK'),
459
561
  [{
460
562
  highlight: "Endur",
461
563
  link: "https://endur.fi"
@@ -472,11 +574,37 @@ export const SenseiStrategies: IStrategyMetadata<SenseiVaultSettings>[] =
472
574
  ),
473
575
  launchBlock: 1053811,
474
576
  type: "Other",
577
+ curator: {
578
+ name: "Unwrap Labs",
579
+ logo: "https://assets.troves.fi/integrations/unwraplabs/white.png"
580
+ },
581
+ vaultType: {
582
+ type: VaultType.FARMING,
583
+ description: "this is a yield farming vault"
584
+ },
475
585
  depositTokens: [
476
586
  Global.getDefaultTokens().find((t) => t.symbol === "STRK")!
477
587
  ],
478
588
  protocols: [endurProtocol, vesuProtocol],
479
- maxTVL: new Web3Number("1500000", 18),
589
+ settings: {
590
+ maxTVL: new Web3Number("1500000", 18),
591
+ alerts: [
592
+ {
593
+ type: "info",
594
+ text: "Depeg-risk: If xSTRK price on DEXes deviates from expected price, you may lose money or may have to wait for the price to recover.",
595
+ tab: "all"
596
+ }
597
+ ],
598
+ liveStatus: StrategyLiveStatus.ACTIVE,
599
+ isPaused: false,
600
+ isInMaintenance: false,
601
+ isAudited: false,
602
+ isInstantWithdrawal: true,
603
+ isTransactionHistDisabled: true,
604
+ quoteToken: Global.getDefaultTokens().find(
605
+ (t) => t.symbol === "STRK"
606
+ )!
607
+ },
480
608
  risk: {
481
609
  riskFactor: _riskFactor,
482
610
  netRisk:
@@ -500,8 +628,7 @@ export const SenseiStrategies: IStrategyMetadata<SenseiVaultSettings>[] =
500
628
  "Repeat the process to loop your position",
501
629
  "Claim DeFi spring (STRK) rewards weekly and reinvest",
502
630
  ],
503
- category: StrategyCategory.ALL,
504
- tags: [StrategyTag.SENSEI],
631
+ tags: [StrategyTag.LEVERED],
505
632
  security: {
506
633
  auditStatus: AuditStatus.AUDITED,
507
634
  sourceCode: {
@@ -232,7 +232,8 @@ function getVesuMultiplyParams(isIncrease: boolean, params: IncreaseLeverParams
232
232
  export const VesuPools = {
233
233
  Genesis: ContractAddr.from('0x4dc4f0ca6ea4961e4c8373265bfd5317678f4fe374d76f3fd7135f57763bf28'),
234
234
  Re7xSTRK: ContractAddr.from('0x052fb52363939c3aa848f8f4ac28f0a51379f8d1b971d8444de25fbd77d8f161'),
235
- Re7xBTC: ContractAddr.from('0x3a8416bf20d036df5b1cf3447630a2e1cb04685f6b0c3a70ed7fb1473548ecf')
235
+ Re7xBTC: ContractAddr.from('0x3a8416bf20d036df5b1cf3447630a2e1cb04685f6b0c3a70ed7fb1473548ecf'),
236
+ Prime: ContractAddr.from('0x451fe483d5921a2919ddd81d0de6696669bccdacd859f72a4fba7656b97c3b5'),
236
237
  }
237
238
 
238
239
  export const extensionMap: {[key: string]: ContractAddr} = {};
@@ -587,7 +588,8 @@ export class VesuAdapter extends BaseAdapter {
587
588
  const assetConfig = isV2 ? _assetConfig : _assetConfig['0'];
588
589
  const timeDelta = assetConfig.last_updated;
589
590
  const lastFullUtilizationRate = assetConfig.last_full_utilization_rate;
590
- const currentDebt = new Web3Number((Number(assetConfig.total_nominal_debt) / 1e18).toFixed(9), asset.decimals);
591
+ const debtSharePrice = Web3Number.fromWei(assetConfig.last_rate_accumulator, 18);
592
+ const currentDebt = (new Web3Number((Number(assetConfig.total_nominal_debt) / 1e18).toFixed(9), asset.decimals)).multipliedBy(debtSharePrice);
591
593
  const totalSupply = currentDebt.plus(Web3Number.fromWei(assetConfig.reserve, asset.decimals));
592
594
 
593
595
  const ratePerSecond = BigInt(Math.round(maxBorrowAPY / 365 / 24 / 60 / 60 * Number(SCALE)));
@@ -596,7 +598,7 @@ export class VesuAdapter extends BaseAdapter {
596
598
 
597
599
  const maxDebtToHave = totalSupply.multipliedBy(Number(maxUtilisation) / 1e18);
598
600
  logger.verbose(`${asset.symbol}::VesuAdapter::getMaxBorrowableByInterestRate currentDebt: ${currentDebt.toString()}, maxDebtToHave: ${maxDebtToHave.toString()}`);
599
- return maxDebtToHave.minus(currentDebt);
601
+ return {maxDebtToHave: maxDebtToHave.minus(currentDebt), currentDebt: currentDebt, totalSupply: totalSupply};
600
602
  }
601
603
 
602
604
  async getLTVConfig(config: IConfig, blockNumber: BlockIdentifier = 'latest') {
@@ -745,7 +747,7 @@ export class VesuAdapter extends BaseAdapter {
745
747
  let pools: any[] = [];
746
748
  try {
747
749
  const data = await getAPIUsingHeadlessBrowser(
748
- `${ENDPOINTS.VESU_BASE_STAGING}/pools`
750
+ `${ENDPOINTS.VESU_BASE}/pools`
749
751
  );
750
752
  pools = data.data;
751
753
 
@@ -891,4 +893,4 @@ export class VesuAdapter extends BaseAdapter {
891
893
  }
892
894
  throw new Error('Max utilization not found');
893
895
  }
894
- }
896
+ }