@strkfarm/sdk 2.0.0-dev.40 → 2.0.0-dev.41

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.
@@ -2,8 +2,8 @@ import { ContractAddr, Web3Number } from "@/dataTypes";
2
2
  import { IConfig, IStrategyMetadata, Protocols, TokenInfo, VaultPosition } from "@/interfaces";
3
3
  import { PricerBase } from "@/modules/pricerBase";
4
4
  import { ERC20 } from "@/modules";
5
- import { BaseStrategy, SingleActionAmount, SingleTokenInfo } from "./base-strategy";
6
- import { Call, Contract, num, uint256 } from "starknet";
5
+ import { BaseStrategy, SingleActionAmount, SingleTokenInfo, UserPositionCard, UserPositionCardsInput } from "./base-strategy";
6
+ import { BlockIdentifier, Call, Contract, num, uint256 } from "starknet";
7
7
  import { assert, LeafData, logger, StandardMerkleTree } from "@/utils";
8
8
  import { UniversalStrategySettings } from "./universal-strategy";
9
9
  import { UNIVERSAL_MANAGE_IDS } from "./universal-strategy";
@@ -94,6 +94,34 @@ export abstract class SVKStrategy<S extends UniversalStrategySettings>
94
94
  return [call];
95
95
  }
96
96
 
97
+ async getUserTVL(user: ContractAddr, blockIdentifier: BlockIdentifier = "latest"): Promise<SingleTokenInfo> {
98
+ const shares: any = await this.contract.call("balanceOf", [user.address], { blockIdentifier });
99
+ const assets: any = await this.contract.call(
100
+ "convert_to_assets",
101
+ [uint256.bnToUint256(shares)],
102
+ { blockIdentifier }
103
+ );
104
+ const amount = Web3Number.fromWei(
105
+ assets.toString(),
106
+ this.metadata.depositTokens[0].decimals
107
+ );
108
+
109
+ const blockNumber = typeof blockIdentifier === "number" || typeof blockIdentifier === "bigint"
110
+ ? Number(blockIdentifier)
111
+ : undefined;
112
+
113
+ const price = await this.pricer.getPrice(
114
+ this.metadata.depositTokens[0].symbol,
115
+ blockNumber
116
+ );
117
+ const usdValue = Number(amount.toFixed(6)) * price.price;
118
+ return {
119
+ tokenInfo: this.asset(),
120
+ amount,
121
+ usdValue
122
+ };
123
+ }
124
+
97
125
  /**
98
126
  * Returns the unused balance in the vault allocator.
99
127
  * Note: This function is common for any SVK strategy.
@@ -322,6 +350,135 @@ export abstract class SVKStrategy<S extends UniversalStrategySettings>
322
350
  };
323
351
  }
324
352
 
353
+ async getUserRealizedAPY(
354
+ blockIdentifier: BlockIdentifier = "latest",
355
+ sinceBlocks = 600000
356
+ ): Promise<number> {
357
+ logger.verbose(
358
+ `${this.getTag()}: getUserRealizedAPY => starting with blockIdentifier=${blockIdentifier}, sinceBlocks=${sinceBlocks}`
359
+ );
360
+
361
+ const blockNow =
362
+ typeof blockIdentifier === "number" || typeof blockIdentifier === "bigint"
363
+ ? Number(blockIdentifier)
364
+ : (await this.config.provider.getBlockLatestAccepted()).block_number;
365
+ const blockNowTime =
366
+ typeof blockIdentifier === "number" || typeof blockIdentifier === "bigint"
367
+ ? (await this.config.provider.getBlockWithTxs(blockIdentifier)).timestamp
368
+ : new Date().getTime() / 1000;
369
+
370
+ const blockBefore = Math.max(
371
+ blockNow - sinceBlocks,
372
+ this.metadata.launchBlock
373
+ );
374
+
375
+ const assetsNowRaw: bigint = await this.contract.call("total_assets", [], {
376
+ blockIdentifier,
377
+ }) as bigint;
378
+ const amountNow = Web3Number.fromWei(
379
+ assetsNowRaw.toString(),
380
+ this.metadata.depositTokens[0].decimals
381
+ );
382
+
383
+ const supplyNowRaw: bigint = await this.contract.call("total_supply", [], {
384
+ blockIdentifier,
385
+ }) as bigint;
386
+ const supplyNow = Web3Number.fromWei(supplyNowRaw.toString(), 18);
387
+
388
+ const assetsBeforeRaw: bigint = await this.contract.call(
389
+ "total_assets",
390
+ [],
391
+ { blockIdentifier: blockBefore }
392
+ ) as bigint;
393
+ const amountBefore = Web3Number.fromWei(
394
+ assetsBeforeRaw.toString(),
395
+ this.metadata.depositTokens[0].decimals
396
+ );
397
+
398
+ const supplyBeforeRaw: bigint = await this.contract.call(
399
+ "total_supply",
400
+ [],
401
+ { blockIdentifier: blockBefore }
402
+ ) as bigint;
403
+ const supplyBefore = Web3Number.fromWei(supplyBeforeRaw.toString(), 18);
404
+
405
+ const blockBeforeInfo = await this.config.provider.getBlockWithTxs(
406
+ blockBefore
407
+ );
408
+
409
+ const assetsPerShareNow = amountNow
410
+ .multipliedBy(1e18)
411
+ .dividedBy(supplyNow.toString());
412
+
413
+ const assetsPerShareBf = amountBefore
414
+ .multipliedBy(1e18)
415
+ .dividedBy(supplyBefore.toString());
416
+
417
+ const timeDiffSeconds = blockNowTime - blockBeforeInfo.timestamp;
418
+
419
+ logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsNow: ${amountNow.toString()}`);
420
+ logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsBefore: ${amountBefore.toString()}`);
421
+ logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsPerShareNow: ${assetsPerShareNow.toString()}`);
422
+ logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsPerShareBf: ${assetsPerShareBf.toString()}`);
423
+ logger.verbose(`${this.getTag()} [getUserRealizedAPY] Supply before: ${supplyBefore.toString()}`);
424
+ logger.verbose(`${this.getTag()} [getUserRealizedAPY] Supply now: ${supplyNow.toString()}`);
425
+ logger.verbose(`${this.getTag()} [getUserRealizedAPY] Time diff in seconds: ${timeDiffSeconds}`);
426
+
427
+ const apyForGivenBlocks =
428
+ Number(
429
+ assetsPerShareNow
430
+ .minus(assetsPerShareBf)
431
+ .multipliedBy(10000)
432
+ .dividedBy(assetsPerShareBf)
433
+ ) / 10000;
434
+
435
+ return (apyForGivenBlocks * (365 * 24 * 3600)) / timeDiffSeconds;
436
+ }
437
+
438
+ async getUserPositionCards(input: UserPositionCardsInput): Promise<UserPositionCard[]> {
439
+ const { user, investmentFlows = [] } = input;
440
+ const [userTVL] = await Promise.all([
441
+ this.getUserTVL(user),
442
+ ]);
443
+ const cards: UserPositionCard[] = [
444
+ {
445
+ title: "Your Holdings",
446
+ tooltip: "Your Holdings",
447
+ value: this.formatTokenAmountForCard(userTVL.amount, userTVL.tokenInfo),
448
+ subValue: `≈ ${this.formatUSDForCard(userTVL.usdValue)}`,
449
+ subValueColor: "positive",
450
+ },
451
+ ];
452
+
453
+ let lifetimeAmount = userTVL.amount.multipliedBy(0);
454
+ let lifetimeTokenInfo = userTVL.tokenInfo;
455
+ let lifetimeUsdValue = 0;
456
+ if (investmentFlows.length > 0) {
457
+ try {
458
+ const earningsResult = this.getLifetimeEarnings(userTVL, investmentFlows);
459
+ lifetimeAmount = earningsResult.lifetimeEarnings;
460
+ lifetimeTokenInfo = earningsResult.tokenInfo.tokenInfo;
461
+ const userAmount = userTVL.amount.toNumber();
462
+ if (Number.isFinite(userAmount) && userAmount > 0) {
463
+ const pricePerToken = userTVL.usdValue / userAmount;
464
+ lifetimeUsdValue = lifetimeAmount.toNumber() * pricePerToken;
465
+ }
466
+ } catch (error) {
467
+ logger.warn(`${this.getTag()}::getUserPositionCards lifetime earnings fallback`, error);
468
+ }
469
+ }
470
+
471
+ cards.push({
472
+ title: "Lifetime Earnings",
473
+ tooltip: "Lifetime Earnings",
474
+ value: this.formatTokenAmountForCard(lifetimeAmount, lifetimeTokenInfo),
475
+ subValue: `≈ ${this.formatUSDForCard(lifetimeUsdValue)}`,
476
+ subValueColor: this.getSubValueColorFromSignedNumber(lifetimeUsdValue),
477
+ });
478
+
479
+ return cards;
480
+ }
481
+
325
482
  async getPrevAUM() {
326
483
  const currentAUM: bigint = await this.contract.call('aum', []) as bigint;
327
484
  const prevAum = Web3Number.fromWei(currentAUM.toString(), this.asset().decimals);
@@ -33,7 +33,11 @@ import { ERC20, PricerFromApi, TokenMarketData } from "@/modules";
33
33
  import { PricerBase } from "@/modules/pricerBase";
34
34
  import { logger, assert } from "@/utils";
35
35
  import { BlockIdentifier, Call, uint256, num } from "starknet";
36
- import { SingleTokenInfo } from "./base-strategy";
36
+ import {
37
+ SingleTokenInfo,
38
+ UserPositionCard,
39
+ UserPositionCardsInput,
40
+ } from "./base-strategy";
37
41
  import { SVKStrategy } from "./svk-strategy";
38
42
  import {
39
43
  APYType,
@@ -320,6 +324,34 @@ export class BoostedxSTRKCarryStrategy<
320
324
  };
321
325
  }
322
326
 
327
+ async getUserPositionCards(
328
+ input: UserPositionCardsInput,
329
+ ): Promise<UserPositionCard[]> {
330
+ const cards = await super.getUserPositionCards(input);
331
+ const realizedApyRaw = await this.getUserRealizedAPY().catch((error) => {
332
+ logger.warn(
333
+ `${this.getTag()}::getUserPositionCards realized APY fallback`,
334
+ error,
335
+ );
336
+ return null;
337
+ });
338
+
339
+ const realizedApy =
340
+ typeof realizedApyRaw === "number"
341
+ ? this.formatPercentForCard(realizedApyRaw)
342
+ : "N/A";
343
+
344
+ cards.push({
345
+ title: "Realized APY",
346
+ tooltip:
347
+ this.metadata.realizedApyMethodology ||
348
+ "Realized APY is based on past 14 days performance",
349
+ value: realizedApy,
350
+ });
351
+
352
+ return cards;
353
+ }
354
+
323
355
  async getAUM(): Promise<{
324
356
  net: SingleTokenInfo;
325
357
  prevAum: Web3Number;
@@ -952,7 +984,7 @@ const wbtcBoostedSettings: BoostedxSTRKCarryStrategySettings = {
952
984
  depositToken: Global.getDefaultTokens().find((t) => t.symbol === "WBTC")!,
953
985
  debtToken: Global.getDefaultTokens().find((t) => t.symbol === "STRK")!,
954
986
  lstHyperToken: Global.getDefaultTokens().find((t) => t.symbol === "xSTRK")!,
955
- maxLTV: 0.70,
987
+ maxLTV: 0.7,
956
988
  targetLTV: 0.5,
957
989
  hasBtcFiRewards: true,
958
990
  hyperLstVaultAddress: ContractAddr.from(
@@ -1013,8 +1045,7 @@ const boostedCarryRiskFactors: RiskFactor[] = [
1013
1045
  value: OracleRiskLevel.SINGLE_RELIABLE,
1014
1046
  // 10% — Vesu HF depends on feeds; Starknet oracles are established but not redundant here.
1015
1047
  weight: 10,
1016
- reason:
1017
- "Vesu collateral and debt valuations rely on Starknet price feeds.",
1048
+ reason: "Vesu collateral and debt valuations rely on Starknet price feeds.",
1018
1049
  },
1019
1050
  {
1020
1051
  type: RiskType.COUNTERPARTY_RISK,
@@ -1065,9 +1096,10 @@ function getBoostedCarryFAQs(
1065
1096
  question: "Which protocols are used?",
1066
1097
  answer: (
1067
1098
  <span>
1068
- <strong>Vesu</strong> for collateral and borrowing, <strong>Avnu</strong>{" "}
1069
- for swaps, <strong>Endur</strong> for {lstSymbol}, and the Troves{" "}
1070
- <strong>Hyper-{lstSymbol}</strong> vault for the boosted leg.
1099
+ <strong>Vesu</strong> for collateral and borrowing,{" "}
1100
+ <strong>Avnu</strong> for swaps, <strong>Endur</strong> for{" "}
1101
+ {lstSymbol}, and the Troves <strong>Hyper-{lstSymbol}</strong> vault
1102
+ for the boosted leg.
1071
1103
  </span>
1072
1104
  ),
1073
1105
  },
@@ -1160,6 +1192,9 @@ function getStrategySettings(
1160
1192
  ],
1161
1193
  },
1162
1194
  contractDetails: getContractDetails(settings),
1195
+ feeBps: {
1196
+ performanceFeeBps: 1500,
1197
+ },
1163
1198
  faqs: getBoostedCarryFAQs(
1164
1199
  depositToken.symbol,
1165
1200
  debtToken.symbol,
@@ -1180,7 +1215,8 @@ function getStrategySettings(
1180
1215
  auditStatus: AuditStatus.AUDITED,
1181
1216
  sourceCode: {
1182
1217
  type: SourceCodeType.OPEN_SOURCE,
1183
- contractLink: "https://github.com/trovesfi/starknet_vault_kit/tree/sherlock-audited",
1218
+ contractLink:
1219
+ "https://github.com/trovesfi/starknet_vault_kit/tree/sherlock-audited",
1184
1220
  },
1185
1221
  // TODO
1186
1222
  accessControl: {
@@ -1206,7 +1242,8 @@ function getStrategySettings(
1206
1242
  ],
1207
1243
  },
1208
1244
  usualTimeToEarnings: "2 weeks",
1209
- usualTimeToEarningsDescription: "This strategy depends on Hyper xSTRK's yield, which depends on the price of xSTRK on DEX appreciating. It may be possible the increase is not continuous and generally rebases atleast once every 2 weeks.",
1245
+ usualTimeToEarningsDescription:
1246
+ "This strategy depends on Hyper xSTRK's yield, which depends on the price of xSTRK on DEX appreciating. It may be possible the increase is not continuous and generally rebases atleast once every 2 weeks.",
1210
1247
  };
1211
1248
  }
1212
1249
 
@@ -8,7 +8,7 @@ import { AVNU_EXCHANGE } from "./universal-adapters/adapter-utils";
8
8
  import { DepegRiskLevel, LiquidationRiskLevel, SmartContractRiskLevel, TechnicalRiskLevel } from "@/interfaces/risks";
9
9
  import { AvnuWrapper, EkuboQuoter, ERC20, LSTAPRService, PricerFromApi, PricerLST } from "@/modules";
10
10
  import { assert, logger } from "@/utils";
11
- import { SingleActionAmount, SingleTokenInfo } from "./base-strategy";
11
+ import { SingleActionAmount, SingleTokenInfo, UserPositionCard, UserPositionCardsInput } from "./base-strategy";
12
12
  import { SVKStrategy } from "./svk-strategy";
13
13
  import { Call, Contract, uint256 } from "starknet";
14
14
  import ERC4626Abi from "@/data/erc4626.abi.json";
@@ -119,8 +119,8 @@ export class UniversalLstMultiplierStrategy<S extends HyperLSTStrategySettings>
119
119
  // todo support lending assets of underlying as well (like if xSTRK looping is not viable, simply supply STRK)
120
120
  getVesuMultiplyAdapters() {
121
121
  const vesuMultipleAdapters = this.metadata.additionalInfo.adapters
122
- .filter(adapter => adapter.adapter.name === VesuMultiplyAdapter.name)
123
- .map(adapter => adapter.adapter) as VesuMultiplyAdapter[]
122
+ .filter(adapter => adapter.adapter.name === VesuMultiplyAdapter.name)
123
+ .map(adapter => adapter.adapter) as VesuMultiplyAdapter[]
124
124
 
125
125
  for (const vesuAdapter of vesuMultipleAdapters) {
126
126
  vesuAdapter.config.pricer = this.pricer;
@@ -586,7 +586,7 @@ export class UniversalLstMultiplierStrategy<S extends HyperLSTStrategySettings>
586
586
  };
587
587
  }
588
588
 
589
- async getAUM(unrealizedAUM: boolean = false): Promise<{net: SingleTokenInfo, prevAum: Web3Number, splits: PositionInfo[]}> {
589
+ async getAUM(unrealizedAUM: boolean = false): Promise<{ net: SingleTokenInfo, prevAum: Web3Number, splits: PositionInfo[] }> {
590
590
  const underlying = this.asset();
591
591
  assert(underlying.symbol.startsWith('x'), 'Underlying is not an LST of Endur');
592
592
 
@@ -642,7 +642,7 @@ export class UniversalLstMultiplierStrategy<S extends HyperLSTStrategySettings>
642
642
  tokenInfo: underlying,
643
643
  amount: netAUM,
644
644
  usdValue: netAUM.toNumber() * assetPrice.price,
645
- apy: {apy: 0, type: APYType.BASE}, // VT: Dont remember why this field exists here. FOr now, set it to 0.
645
+ apy: { apy: 0, type: APYType.BASE }, // VT: Dont remember why this field exists here. FOr now, set it to 0.
646
646
  remarks: AUMTypes.FINALISED,
647
647
  protocol: Protocols.NONE
648
648
  };
@@ -651,16 +651,18 @@ export class UniversalLstMultiplierStrategy<S extends HyperLSTStrategySettings>
651
651
  tokenInfo: underlying,
652
652
  amount: Web3Number.fromWei('0', underlying.decimals),
653
653
  usdValue: 0,
654
- apy: {apy: 0, type: APYType.BASE},
654
+ apy: { apy: 0, type: APYType.BASE },
655
655
  remarks: AUMTypes.DEFISPRING,
656
656
  protocol: Protocols.NONE
657
657
  };
658
658
 
659
- return {net: {
660
- tokenInfo: underlying,
661
- amount: netAUM,
662
- usdValue: netAUM.toNumber() * assetPrice.price
663
- }, prevAum: prevAum, splits: [realAUM, estimatedAUMDelta]};
659
+ return {
660
+ net: {
661
+ tokenInfo: underlying,
662
+ amount: netAUM,
663
+ usdValue: netAUM.toNumber() * assetPrice.price
664
+ }, prevAum: prevAum, splits: [realAUM, estimatedAUMDelta]
665
+ };
664
666
  }
665
667
 
666
668
  async getTVLUnrealized() {
@@ -682,6 +684,70 @@ export class UniversalLstMultiplierStrategy<S extends HyperLSTStrategySettings>
682
684
  };
683
685
  }
684
686
 
687
+ async getUserPositionCards(input: UserPositionCardsInput): Promise<UserPositionCard[]> {
688
+ const cards = await super.getUserPositionCards(input);
689
+
690
+ try {
691
+ const [unrealizedResult, userTVL, realizedApyRaw] = await Promise.all([
692
+ this.getUserUnrealizedGains(input.user),
693
+ this.getUserTVL(input.user),
694
+ this.getUserRealizedAPY().catch(() => null),
695
+ ]);
696
+ const amount = unrealizedResult.unrealizedGains;
697
+ let usdValue = 0;
698
+ const userAmount = userTVL.amount.toNumber();
699
+ if (Number.isFinite(userAmount) && userAmount > 0) {
700
+ usdValue = (userTVL.usdValue / userAmount) * amount.toNumber();
701
+ }
702
+
703
+ cards.push({
704
+ title: "Unrealized Gains",
705
+ tooltip: "Unrealized gains based on current market prices vs Endur prices. If you withdraw now, you will forgo these gains.",
706
+ value: this.formatTokenAmountForCard(amount, unrealizedResult.tokenInfo),
707
+ subValue: `≈ ${this.formatUSDForCard(usdValue)}`,
708
+ subValueColor: this.getSubValueColorFromSignedNumber(usdValue),
709
+ });
710
+
711
+ const realizedApy = typeof realizedApyRaw === "number"
712
+ ? this.formatPercentForCard(realizedApyRaw)
713
+ : "N/A";
714
+ cards.push({
715
+ title: "Realized APY",
716
+ tooltip: this.metadata.realizedApyMethodology || "Realized APY is based on past 14 days performance",
717
+ value: realizedApy,
718
+ });
719
+ } catch (error) {
720
+ logger.warn(`${this.getTag()}::getUserPositionCards unrealized gains fallback`, error);
721
+ cards.push({
722
+ title: "Unrealized Gains",
723
+ tooltip: "Unrealized gains based on current market prices vs Endur prices. If you withdraw now, you will forgo these gains.",
724
+ value: this.formatTokenAmountForCard(
725
+ Web3Number.fromWei("0", this.asset().decimals),
726
+ this.asset()
727
+ ),
728
+ subValue: `≈ ${this.formatUSDForCard(0)}`,
729
+ subValueColor: "default",
730
+ });
731
+ cards.push({
732
+ title: "Realized APY",
733
+ tooltip: this.metadata.realizedApyMethodology || "Realized APY is based on past 14 days performance",
734
+ value: "N/A",
735
+ });
736
+ }
737
+
738
+ if (this.asset().symbol === "xSTRK") {
739
+ const index = cards.findIndex((card) => card.title === "Lifetime Earnings");
740
+ if (index >= 0) {
741
+ cards[index] = {
742
+ ...cards[index],
743
+ tooltip: "Lifetime earnings of the vault. Due to migration of xSTRK Sensei to this vault, any migrated funds are also seen as lifetime earnings. Team is working to fix this soon.",
744
+ };
745
+ }
746
+ }
747
+
748
+ return cards;
749
+ }
750
+
685
751
  }
686
752
 
687
753
  export default function VaultDescription(
@@ -706,7 +772,7 @@ export default function VaultDescription(
706
772
  </p>
707
773
 
708
774
  <p style={{ fontSize: "14px", lineHeight: "1.5", marginBottom: "16px" }}>
709
- This vault uses Vesu for lending and borrowing. The oracle used by this pool is a {highlightTextWithLinks("conversion rate oracle", [{highlight: "conversion rate oracle", link: "https://docs.pragma.build/starknet/development#conversion-rate"}])}
775
+ This vault uses Vesu for lending and borrowing. The oracle used by this pool is a {highlightTextWithLinks("conversion rate oracle", [{ highlight: "conversion rate oracle", link: "https://docs.pragma.build/starknet/development#conversion-rate" }])}
710
776
  {" "}which is resilient to liquidity issues and price volatility, hence reducing the risk of liquidation. However, overtime, if left un-monitored, debt can increase enough to trigger a liquidation. But no worries, our continuous monitoring systems look for situations with reduced health factor and balance collateral/debt to bring it back to safe levels. With Troves, you can have a peaceful sleep.
711
777
  </p>
712
778
 
@@ -747,7 +813,7 @@ function getLooperSettings(
747
813
 
748
814
  const baseAdapterConfig: BaseAdapterConfig = {
749
815
  baseToken: lstToken,
750
- supportedPositions: [{asset: lstToken, isDebt: false}, {asset: underlyingToken, isDebt: true}],
816
+ supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: underlyingToken, isDebt: true }],
751
817
  networkConfig: getMainnetConfig(),
752
818
  pricer: new PricerFromApi(getMainnetConfig(), Global.getDefaultTokens()),
753
819
  vaultAllocator: vaultSettings.vaultAllocator,
@@ -899,7 +965,7 @@ export const _riskFactor: RiskFactor[] = [
899
965
  { type: RiskType.SMART_CONTRACT_RISK, value: SmartContractRiskLevel.WELL_AUDITED, weight: 25, reason: "Audited by Zellic" },
900
966
  { type: RiskType.LIQUIDATION_RISK, value: LiquidationRiskLevel.VERY_LOW_PROBABILITY, weight: 25, reason: "The collateral and debt are highly correlated" },
901
967
  { type: RiskType.TECHNICAL_RISK, value: TechnicalRiskLevel.STABLE_INFRASTRUCTURE, weight: 25, reason: "Liquidation can only happen if vault is left un-monitored for weeks, which is highly unlikely. We actively monitor all services on a daily basis." },
902
- {type: RiskType.DEPEG_RISK, value: DepegRiskLevel.GENERALLY_STABLE, weight: 25, reason: "Generally stable pegged assets" },
968
+ { type: RiskType.DEPEG_RISK, value: DepegRiskLevel.GENERALLY_STABLE, weight: 25, reason: "Generally stable pegged assets" },
903
969
  ];
904
970
 
905
971
  const hyperxSTRK: HyperLSTStrategySettings = {
@@ -1088,8 +1154,8 @@ function createHyperLSTSettings(
1088
1154
  tab: "deposit" as const,
1089
1155
  text: (
1090
1156
  <>
1091
- To acquire the LST, please visit{" "}
1092
- <a href="https://app.endur.fi" target="_blank" rel="noopener noreferrer">endur.fi</a>
1157
+ To acquire the LST, please visit{" "}
1158
+ <a href="https://app.endur.fi" target="_blank" rel="noopener noreferrer">endur.fi</a>
1093
1159
  </>
1094
1160
  ),
1095
1161
  type: "info" as const,
@@ -1171,9 +1237,14 @@ function getStrategySettings(
1171
1237
  faqs: getFAQs(lstSymbol, underlyingSymbol, isLST),
1172
1238
  investmentSteps: getInvestmentSteps(lstSymbol, underlyingSymbol),
1173
1239
  isPreview: isPreview,
1174
- apyMethodology: 'Current annualized APY in terms of base asset of the LST. There is no additional fee taken by Troves on LST APY. We charge a 10% performance fee on the additional gain which is already accounted in the APY shown.',
1175
- realizedApyMethodology: 'The realizedAPY is based on past 14 days performance by the vault',
1176
- tags: lstSymbol.includes('BTC')
1240
+ apyMethodology:
1241
+ "Current annualized APY in terms of base asset of the LST. There is no additional fee taken by Troves on LST APY. We charge a 10% performance fee on the additional gain which is already accounted in the APY shown.",
1242
+ realizedApyMethodology:
1243
+ "The realizedAPY is based on past 14 days performance by the vault",
1244
+ feeBps: {
1245
+ performanceFeeBps: 1000,
1246
+ },
1247
+ tags: lstSymbol.includes("BTC")
1177
1248
  ? [StrategyTag.BTC, StrategyTag.LEVERED]
1178
1249
  : [StrategyTag.LEVERED],
1179
1250
  security: HYPER_LST_SECURITY,