@strkfarm/sdk 2.0.0-dev.5 → 2.0.0-dev.50

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.
Files changed (79) hide show
  1. package/dist/cli.js +190 -36
  2. package/dist/cli.mjs +188 -34
  3. package/dist/index.browser.global.js +119400 -92821
  4. package/dist/index.browser.mjs +13293 -11146
  5. package/dist/index.d.ts +2281 -1938
  6. package/dist/index.js +13532 -11179
  7. package/dist/index.mjs +14165 -11836
  8. package/package.json +59 -60
  9. package/src/data/avnu.abi.json +840 -0
  10. package/src/data/ekubo-price-fethcer.abi.json +265 -0
  11. package/src/data/redeem-request-nft.abi.json +752 -0
  12. package/src/data/universal-vault.abi.json +8 -7
  13. package/src/dataTypes/_bignumber.ts +13 -4
  14. package/src/dataTypes/bignumber.browser.ts +10 -1
  15. package/src/dataTypes/bignumber.node.ts +10 -1
  16. package/src/dataTypes/index.ts +3 -2
  17. package/src/dataTypes/mynumber.ts +141 -0
  18. package/src/global.ts +279 -233
  19. package/src/index.browser.ts +2 -1
  20. package/src/interfaces/common.tsx +228 -6
  21. package/src/modules/apollo-client-config.ts +28 -0
  22. package/src/modules/avnu.ts +21 -12
  23. package/src/modules/ekubo-pricer.ts +80 -0
  24. package/src/modules/ekubo-quoter.ts +48 -30
  25. package/src/modules/erc20.ts +17 -0
  26. package/src/modules/harvests.ts +43 -29
  27. package/src/modules/index.ts +2 -1
  28. package/src/modules/pragma.ts +23 -8
  29. package/src/modules/pricer-avnu-api.ts +114 -0
  30. package/src/modules/pricer-from-api.ts +156 -15
  31. package/src/modules/pricer-lst.ts +1 -1
  32. package/src/modules/pricer.ts +107 -41
  33. package/src/modules/pricerBase.ts +2 -1
  34. package/src/modules/zkLend.ts +3 -2
  35. package/src/node/deployer.ts +36 -1
  36. package/src/node/pricer-redis.ts +3 -1
  37. package/src/strategies/base-strategy.ts +168 -16
  38. package/src/strategies/constants.ts +8 -3
  39. package/src/strategies/ekubo-cl-vault.tsx +1048 -355
  40. package/src/strategies/factory.ts +199 -0
  41. package/src/strategies/index.ts +5 -3
  42. package/src/strategies/registry.ts +262 -0
  43. package/src/strategies/sensei.ts +354 -10
  44. package/src/strategies/svk-strategy.ts +292 -31
  45. package/src/strategies/token-boosted-xstrk-carry-strategy.tsx +1261 -0
  46. package/src/strategies/types.ts +4 -0
  47. package/src/strategies/universal-adapters/adapter-utils.ts +4 -1
  48. package/src/strategies/universal-adapters/avnu-adapter.ts +196 -272
  49. package/src/strategies/universal-adapters/baseAdapter.ts +263 -251
  50. package/src/strategies/universal-adapters/common-adapter.ts +206 -203
  51. package/src/strategies/universal-adapters/index.ts +10 -8
  52. package/src/strategies/universal-adapters/svk-troves-adapter.ts +511 -0
  53. package/src/strategies/universal-adapters/token-transfer-adapter.ts +200 -0
  54. package/src/strategies/universal-adapters/vesu-adapter.ts +120 -82
  55. package/src/strategies/universal-adapters/vesu-modify-position-adapter.ts +525 -0
  56. package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +866 -860
  57. package/src/strategies/universal-adapters/vesu-position-common.ts +258 -0
  58. package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +18 -3
  59. package/src/strategies/universal-lst-muliplier-strategy.tsx +895 -416
  60. package/src/strategies/universal-strategy.tsx +1332 -1173
  61. package/src/strategies/vesu-rebalance.tsx +254 -153
  62. package/src/strategies/yoloVault.ts +1096 -0
  63. package/src/utils/cacheClass.ts +11 -2
  64. package/src/utils/health-factor-math.ts +33 -1
  65. package/src/utils/index.ts +3 -1
  66. package/src/utils/logger.browser.ts +22 -4
  67. package/src/utils/logger.node.ts +259 -24
  68. package/src/utils/starknet-call-parser.ts +1036 -0
  69. package/src/utils/strategy-utils.ts +61 -0
  70. package/src/modules/ExtendedWrapperSDk/index.ts +0 -62
  71. package/src/modules/ExtendedWrapperSDk/types.ts +0 -311
  72. package/src/modules/ExtendedWrapperSDk/wrapper.ts +0 -395
  73. package/src/strategies/universal-adapters/extended-adapter.ts +0 -662
  74. package/src/strategies/universal-adapters/unused-balance-adapter.ts +0 -109
  75. package/src/strategies/vesu-extended-strategy/services/operationService.ts +0 -34
  76. package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +0 -77
  77. package/src/strategies/vesu-extended-strategy/utils/constants.ts +0 -49
  78. package/src/strategies/vesu-extended-strategy/utils/helper.ts +0 -372
  79. package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +0 -1140
@@ -1,7 +1,13 @@
1
- import { getNoRiskTags, highlightTextWithLinks, IConfig, IProtocol, IStrategyMetadata, RiskFactor, RiskType, TokenInfo } from "@/interfaces";
2
- import { BaseStrategy, SingleActionAmount, SingleTokenInfo } from "./base-strategy";
1
+ import { getNoRiskTags, highlightTextWithLinks, IConfig, IProtocol, IStrategyMetadata, RiskFactor, RiskType, StrategyTag, TokenInfo, AuditStatus, SourceCodeType, AccessControlType, InstantWithdrawalVault, StrategyLiveStatus, VaultType, UnwrapLabsCurator } from "@/interfaces";
2
+ import {
3
+ BaseStrategy,
4
+ SingleActionAmount,
5
+ SingleTokenInfo,
6
+ UserPositionCard,
7
+ UserPositionCardsInput,
8
+ } from "./base-strategy";
3
9
  import { ContractAddr, Web3Number } from "@/dataTypes";
4
- import { Call, Contract, uint256 } from "starknet";
10
+ import { Call, Contract, num, uint256, BlockIdentifier } from "starknet";
5
11
  import SenseiABI from "@/data/sensei.abi.json";
6
12
  import { getTrovesEndpoint, logger } from "@/utils";
7
13
  import { Global } from "@/global";
@@ -9,6 +15,10 @@ import { QuoteRequest } from "@avnu/avnu-sdk";
9
15
  import { PricerBase } from "@/modules/pricerBase";
10
16
  import ERC20ABI from "@/data/erc20.abi.json";
11
17
  import { AvnuWrapper } from "@/modules";
18
+ import { gql } from "@apollo/client";
19
+ import apolloClient from "@/modules/apollo-client";
20
+ import { VesuAdapter, VesuPools } from "./universal-adapters/vesu-adapter";
21
+ import { LSTAPRService } from "@/modules/lst-apr";
12
22
 
13
23
  export interface SenseiVaultSettings {
14
24
  mainToken: TokenInfo;
@@ -37,17 +47,27 @@ export class SenseiVault extends BaseStrategy<
37
47
  }
38
48
  }
39
49
 
40
- async getUserTVL(user: ContractAddr): Promise<SingleTokenInfo> {
50
+ async getUserTVL(user: ContractAddr, blockIdentifier: BlockIdentifier = "latest"): Promise<SingleTokenInfo> {
41
51
  const result: any = await this.contract.call(
42
52
  "describe_position",
43
53
  [user.address],
54
+ {
55
+ blockIdentifier,
56
+ }
44
57
  );
45
58
  const amount = Web3Number.fromWei(
46
59
  uint256.uint256ToBN(result[1].estimated_size).toString(),
47
60
  this.metadata.depositTokens[0].decimals,
48
61
  )
62
+
63
+ // Convert blockIdentifier to block number for pricer if it's a number
64
+ const blockNumber = typeof blockIdentifier === 'number' || typeof blockIdentifier === 'bigint'
65
+ ? Number(blockIdentifier)
66
+ : undefined;
67
+
49
68
  const price = await this.pricer.getPrice(
50
69
  this.metadata.depositTokens[0].symbol,
70
+ blockNumber
51
71
  );
52
72
  return {
53
73
  usdValue: Number(amount.toFixed(6)) * price.price,
@@ -80,7 +100,7 @@ export class SenseiVault extends BaseStrategy<
80
100
  tokenInfo: this.metadata.depositTokens[0],
81
101
  };
82
102
  } catch (error) {
83
- console.error('Error fetching TVL:', error);
103
+ console.error(`[SDK] Error fetching TVL for ${this.metadata.id}:`, error);
84
104
  return {
85
105
  usdValue: 0,
86
106
  amount: new Web3Number('0', this.metadata.depositTokens[0].decimals),
@@ -108,7 +128,7 @@ export class SenseiVault extends BaseStrategy<
108
128
  return calls;
109
129
  }
110
130
 
111
- async withdrawCall(amountInfo: SingleActionAmount, receiver: ContractAddr, owner: ContractAddr): Promise<Call[]> {
131
+ async withdrawCall(amountInfo: SingleActionAmount, receiver: ContractAddr, owner: ContractAddr, _isMaxWithdraw: boolean = false): Promise<Call[]> {
112
132
  const call = this.contract.populate('withdraw', [
113
133
  uint256.bnToUint256(amountInfo.amount.toWei()),
114
134
  receiver.address,
@@ -223,7 +243,272 @@ export class SenseiVault extends BaseStrategy<
223
243
  logger.verbose('getSettings', settings);
224
244
  return settings;
225
245
  };
246
+
247
+ /**
248
+ * Calculate lifetime earnings for a user
249
+ * Not yet implemented for Sensei Vault strategy
250
+ */
251
+ getLifetimeEarnings(
252
+ userTVL: SingleTokenInfo,
253
+ investmentFlows: Array<{ amount: string; type: string; timestamp: number; tx_hash: string }>
254
+ ): any {
255
+ throw new Error("getLifetimeEarnings is not implemented yet for this strategy");
256
+ }
257
+
258
+ async netAPY(): Promise<number> {
259
+ try {
260
+ // Fetch Vesu pools and select the Re7 xSTRK pool
261
+ const { pools } = await VesuAdapter.getVesuPools();
262
+ const re7PoolId = VesuPools.Re7xSTRK;
263
+ const pool = pools.find((p: any) =>
264
+ ContractAddr.from(num.getHexString(p.id)).eq(re7PoolId),
265
+ );
266
+
267
+ if (!pool) {
268
+ logger.warn(`${SenseiVault.name}::netAPY - Re7 xSTRK pool not found`);
269
+ return 0;
270
+ }
271
+
272
+ const mainSymbol = this.metadata.additionalInfo.mainToken.symbol.toLowerCase(); // STRK
273
+ const secondarySymbol =
274
+ this.metadata.additionalInfo.secondaryToken.symbol.toLowerCase(); // xSTRK
275
+
276
+ const collateralAssetStats = pool.assets.find(
277
+ (a: any) => String(a.symbol).toLowerCase() === secondarySymbol,
278
+ )?.stats;
279
+ const debtAssetStats = pool.assets.find(
280
+ (a: any) => String(a.symbol).toLowerCase() === mainSymbol,
281
+ )?.stats;
282
+
283
+ if (!collateralAssetStats || !debtAssetStats) {
284
+ logger.warn(
285
+ `${SenseiVault.name}::netAPY - Missing collateral/debt stats on Vesu pool`,
286
+ );
287
+ return 0;
288
+ }
289
+
290
+ // Base xSTRK lending APY from Vesu
291
+ const xstrkSupplyAPY =
292
+ Number(collateralAssetStats.supplyApy?.value || 0) / 1e18;
293
+
294
+ // STRK rewards APR on xSTRK collateral from Vesu
295
+ const strkRewardsAPR = collateralAssetStats.defiSpringSupplyApr
296
+ ? Number(collateralAssetStats.defiSpringSupplyApr.value || 0) / 1e18
297
+ : 0;
298
+
299
+ // STRK borrow APY from Vesu
300
+ const borrowAPY =
301
+ Number(debtAssetStats.borrowApr?.value || 0) / 1e18;
302
+
303
+ // LST APR for xSTRK from Endur (based on underlying STRK asset)
304
+ const lstAPY = await LSTAPRService.getLSTAPR(
305
+ this.metadata.additionalInfo.mainToken.address,
306
+ );
307
+
308
+ // Collateral APY = Vesu xSTRK supply + Endur xSTRK APR + STRK rewards
309
+ const collateralAPY = xstrkSupplyAPY + lstAPY + strkRewardsAPR;
310
+
311
+ const feeFactor = this.metadata.additionalInfo.feeBps / 10000; // convert bps to decimal
312
+ const feeAdjustedColAPY =
313
+ collateralAPY - strkRewardsAPR * feeFactor;
314
+
315
+ // Position info (collateral & debt in USD terms)
316
+ const { collateralUSDValue, debtUSDValue } =
317
+ await this.getPositionInfo();
318
+
319
+ const collateralUSD = Number(collateralUSDValue.toFixed(6));
320
+ const debtUSD = Number(debtUSDValue.toFixed(6));
321
+
322
+ // Compute expected leverage using the same math as app-side strategy
323
+ const targetHf = this.metadata.additionalInfo.targetHfBps / 10000;
324
+ const xSTRKPrice = await this.getSecondaryTokenPriceRelativeToMain();
325
+ const denominator = targetHf * xSTRKPrice - 0.87;
326
+ if (denominator <= 0) {
327
+ logger.warn(
328
+ `${SenseiVault.name}::netAPY - Invalid denominator in leverage calc`,
329
+ );
330
+ return 0;
331
+ }
332
+ const borrowedSTRK = (0.87 * xSTRKPrice) / denominator;
333
+ const expectedLeverage = 1 + borrowedSTRK;
334
+ if (!Number.isFinite(expectedLeverage) || expectedLeverage <= 0) {
335
+ logger.warn(
336
+ `${SenseiVault.name}::netAPY - Non-positive or invalid expectedLeverage`,
337
+ );
338
+ return 0;
339
+ }
340
+
341
+ const payoff =
342
+ collateralUSD * feeAdjustedColAPY - debtUSD * borrowAPY;
343
+ const investment = collateralUSD - debtUSD;
344
+
345
+ if (investment === 0) {
346
+ return 0;
347
+ }
348
+
349
+ const netAPY = payoff / investment;
350
+ return Number.isFinite(netAPY) ? netAPY : 0;
351
+ } catch (error) {
352
+ logger.error(`${SenseiVault.name}::netAPY - Error`, error);
353
+ return 0;
354
+ }
355
+ }
356
+
357
+ /**
358
+ * Calculates user realized APY based on position growth accounting for deposits and withdrawals.
359
+ * Returns the APY as a number.
360
+ * Not implemented for Sensei Strategy yet.
361
+ */
362
+ async getUserRealizedAPY(
363
+ blockIdentifier: BlockIdentifier = "latest",
364
+ sinceBlocks = 600000
365
+ ): Promise<number> {
366
+ throw new Error("getUserRealizedAPY not implemented yet for Sensei strategy");
226
367
 
368
+ /*
369
+ logger.verbose(
370
+ `${SenseiVault.name}: getUserRealizedAPY => starting with userAddress=${userAddress.address}, blockIdentifier=${blockIdentifier}, sinceBlocks=${sinceBlocks}`
371
+ );
372
+
373
+ // Determine current block number
374
+ let blockNow =
375
+ typeof blockIdentifier === "number" || typeof blockIdentifier === "bigint"
376
+ ? Number(blockIdentifier)
377
+ : (await this.config.provider.getBlockLatestAccepted()).block_number;
378
+
379
+ // Look back window, but never before launch block
380
+ const blockBefore = Math.max(
381
+ blockNow - sinceBlocks,
382
+ this.metadata.launchBlock
383
+ );
384
+
385
+ logger.verbose(
386
+ `${SenseiVault.name}: getUserRealizedAPY => blockNow=${blockNow}, blockBefore=${blockBefore}`
387
+ );
388
+
389
+ // Get current estimated size
390
+ const currentResult: any = await this.contract.call(
391
+ "describe_position",
392
+ [userAddress.address],
393
+ {
394
+ blockIdentifier,
395
+ }
396
+ );
397
+ const currentEstimatedSize = Web3Number.fromWei(
398
+ uint256.uint256ToBN(currentResult[1].estimated_size).toString(),
399
+ this.metadata.depositTokens[0].decimals,
400
+ );
401
+
402
+ // Get previous estimated size
403
+ const previousResult: any = await this.contract.call(
404
+ "describe_position",
405
+ [userAddress.address],
406
+ {
407
+ blockIdentifier: blockBefore,
408
+ }
409
+ );
410
+ const previousEstimatedSize = Web3Number.fromWei(
411
+ uint256.uint256ToBN(previousResult[1].estimated_size).toString(),
412
+ this.metadata.depositTokens[0].decimals,
413
+ );
414
+
415
+ logger.verbose(
416
+ `${SenseiVault.name}: getUserRealizedAPY => currentEstimatedSize=${currentEstimatedSize.toString()}, previousEstimatedSize=${previousEstimatedSize.toString()}`
417
+ );
418
+
419
+ // Query GraphQL for deposits and withdrawals between blockBefore and blockNow
420
+ let newDeposits = Web3Number.fromWei("0", this.metadata.depositTokens[0].decimals);
421
+ let newWithdrawals = Web3Number.fromWei("0", this.metadata.depositTokens[0].decimals);
422
+
423
+ try {
424
+ const { data } = await apolloClient.query({
425
+ query: gql`
426
+ query Query($where: Investment_flowsWhereInput) {
427
+ findManyInvestment_flows(where: $where) {
428
+ block_number
429
+ amount
430
+ type
431
+ }
432
+ }
433
+ `,
434
+ variables: {
435
+ where: {
436
+ contract: {
437
+ equals: this.address.address.toLowerCase(),
438
+ },
439
+ owner: {
440
+ equals: userAddress.address.toLowerCase(),
441
+ },
442
+ block_number: {
443
+ gte: blockBefore,
444
+ lte: blockNow,
445
+ },
446
+ },
447
+ },
448
+ fetchPolicy: 'no-cache',
449
+ });
450
+
451
+ // Sum deposits and withdrawals
452
+ for (const flow of data.findManyInvestment_flows) {
453
+ const amount = Web3Number.fromWei(
454
+ flow.amount,
455
+ this.metadata.depositTokens[0].decimals
456
+ );
457
+ if (flow.type === 'deposit') {
458
+ newDeposits = newDeposits.plus(amount);
459
+ } else if (flow.type === 'withdraw') {
460
+ newWithdrawals = newWithdrawals.plus(amount);
461
+ }
462
+ }
463
+
464
+ logger.verbose(
465
+ `${SenseiVault.name}: getUserRealizedAPY => newDeposits=${newDeposits.toString()}, newWithdrawals=${newWithdrawals.toString()}`
466
+ );
467
+ } catch (error) {
468
+ logger.verbose(
469
+ `${SenseiVault.name}: getUserRealizedAPY => Error querying GraphQL, continuing with zero deposits/withdrawals:`,
470
+ error
471
+ );
472
+ // Continue with zero deposits/withdrawals if GraphQL query fails
473
+ }
474
+
475
+ // Calculate growth: Current estimated size - new deposits + new withdrawals - previous estimated size
476
+ const growth = currentEstimatedSize
477
+ .minus(newDeposits)
478
+ .plus(newWithdrawals)
479
+ .minus(previousEstimatedSize);
480
+
481
+ logger.verbose(
482
+ `${SenseiVault.name}: getUserRealizedAPY => growth=${growth.toString()}`
483
+ );
484
+
485
+ // Handle edge case where previous position is zero
486
+ if (previousEstimatedSize.isZero() || previousEstimatedSize.lte(0)) {
487
+ logger.verbose(
488
+ `${SenseiVault.name}: getUserRealizedAPY => Previous position is zero, returning 0`
489
+ );
490
+ return 0;
491
+ }
492
+
493
+ // Calculate actual block difference (in case limited by launch block)
494
+ const actualBlockDiff = blockNow - blockBefore;
495
+
496
+ // Calculate APY: 100 * 365/n * growth / previousEstimatedSize
497
+ // where n is the number of blocks (sinceBlocks or actual block difference)
498
+ const growthRatio = growth.dividedBy(previousEstimatedSize);
499
+ const apy = Number(growthRatio) * 100 * 365 / actualBlockDiff;
500
+
501
+ logger.verbose(
502
+ `${SenseiVault.name}: getUserRealizedAPY => actualBlockDiff=${actualBlockDiff}, growthRatio=${Number(growthRatio)}, apy=${apy}`
503
+ );
504
+
505
+ return apy;
506
+ */
507
+ }
508
+
509
+ async getUserPositionCards(_input: UserPositionCardsInput): Promise<UserPositionCard[]> {
510
+ return [];
511
+ }
227
512
  }
228
513
 
229
514
  const senseiDescription = `Deposit your {{token1}} to automatically loop your funds via Endur ({{token2}}) and Vesu to create a delta neutral position. This strategy is designed to maximize your yield on {{token1}}. Your position is automatically adjusted periodically to maintain a healthy health factor. You receive a NFT as representation for your stake on Troves. You can withdraw anytime by redeeming your NFT for {{token1}}.`;
@@ -289,9 +574,10 @@ const FAQS = [
289
574
  export const SenseiStrategies: IStrategyMetadata<SenseiVaultSettings>[] =
290
575
  [
291
576
  {
577
+ id: "xstrk_sensei",
292
578
  name: "xSTRK Sensei",
293
579
  description: highlightTextWithLinks(
294
- senseiDescription.replaceAll('{{token1}}', 'STRK').replaceAll('{{token2}}', 'xSTRK'),
580
+ senseiDescription.replace('{{token1}}', 'STRK').replace('{{token2}}', 'xSTRK'),
295
581
  [{
296
582
  highlight: "Endur",
297
583
  link: "https://endur.fi"
@@ -308,11 +594,33 @@ export const SenseiStrategies: IStrategyMetadata<SenseiVaultSettings>[] =
308
594
  ),
309
595
  launchBlock: 1053811,
310
596
  type: "Other",
597
+ curator: UnwrapLabsCurator,
598
+ vaultType: {
599
+ type: VaultType.LOOPING,
600
+ description: "Creates leveraged looping position on xSTRK by borrowing STRK to increase yield"
601
+ },
311
602
  depositTokens: [
312
603
  Global.getDefaultTokens().find((t) => t.symbol === "STRK")!
313
604
  ],
314
605
  protocols: [endurProtocol, vesuProtocol],
315
- maxTVL: new Web3Number("1500000", 18),
606
+ settings: {
607
+ alerts: [
608
+ {
609
+ type: "info",
610
+ 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.",
611
+ tab: "all"
612
+ }
613
+ ],
614
+ liveStatus: StrategyLiveStatus.RETIRED,
615
+ isPaused: false,
616
+ isInMaintenance: false,
617
+ isAudited: false,
618
+ isInstantWithdrawal: true,
619
+ isTransactionHistDisabled: true,
620
+ quoteToken: Global.getDefaultTokens().find(
621
+ (t) => t.symbol === "STRK"
622
+ )!
623
+ },
316
624
  risk: {
317
625
  riskFactor: _riskFactor,
318
626
  netRisk:
@@ -335,6 +643,42 @@ export const SenseiStrategies: IStrategyMetadata<SenseiVaultSettings>[] =
335
643
  "Buy more xSTRK with borrowed STRK",
336
644
  "Repeat the process to loop your position",
337
645
  "Claim DeFi spring (STRK) rewards weekly and reinvest",
338
- ]
646
+ ],
647
+ tags: [StrategyTag.LEVERED],
648
+ security: {
649
+ auditStatus: AuditStatus.AUDITED,
650
+ sourceCode: {
651
+ type: SourceCodeType.CLOSED_SOURCE,
652
+ contractLink: "https://github.com/trovesfi/troves-contracts",
653
+ },
654
+ accessControl: {
655
+ type: AccessControlType.ROLE_BASED_ACCESS,
656
+ addresses: [ContractAddr.from("0x0")],
657
+ timeLock: "2 Days",
658
+ },
659
+ },
660
+ redemptionInfo: {
661
+ instantWithdrawalVault: InstantWithdrawalVault.YES,
662
+ redemptionsInfo: [],
663
+ alerts: [],
664
+ },
665
+ usualTimeToEarnings: "2 weeks",
666
+ usualTimeToEarningsDescription: "Strategy returns depend on LST price on DEXes. Even though the true price of LST on Endur increases continuously, the DEX price may lag sometimes, and historically is seen to rebase at least once every 2 weeks. This is when you realise your earnings.",
667
+ points: [{
668
+ multiplier: 4,
669
+ logo: 'https://endur.fi/favicon.ico',
670
+ toolTip: "This strategy holds xSTRK. Earn 3-4x Endur points on your xSTRK due to the leverage. Points can be found on endur.fi.",
671
+ }],
672
+ discontinuationInfo: {
673
+ info: highlightTextWithLinks(
674
+ "This strategy is retired. All funds have been moved to Hyper xSTRK.",
675
+ [
676
+ {
677
+ highlight: "Hyper xSTRK",
678
+ link: "/strategy/hyper_xstrk",
679
+ },
680
+ ]
681
+ ),
682
+ },
339
683
  },
340
- ];
684
+ ];