@strkfarm/sdk 2.0.0-staging.7 → 2.0.0-staging.71

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.
@@ -9,6 +9,7 @@ import {
9
9
  UniversalLstMultiplierStrategy,
10
10
  HyperLSTStrategySettings
11
11
  } from "./universal-lst-muliplier-strategy";
12
+ import { YoLoVault, YoloVaultSettings } from "./yoloVault";
12
13
  import { VesuRebalance, VesuRebalanceSettings } from "./vesu-rebalance";
13
14
  import { SenseiVault, SenseiVaultSettings } from "./sensei";
14
15
 
@@ -17,7 +18,8 @@ export enum FactoryStrategyType {
17
18
  EKUBO_CL = "EKUBO_CL",
18
19
  HYPER_LST = "HYPER_LST",
19
20
  VESU_REBALANCE = "VESU_REBALANCE",
20
- SENSEI = "SENSEI"
21
+ SENSEI = "SENSEI",
22
+ YOLO_VAULT = "YOLO_VAULT"
21
23
  }
22
24
 
23
25
  export function createUniversalStrategy(
@@ -36,6 +38,14 @@ export function createEkuboCLStrategy(
36
38
  return new EkuboCLVault(config, pricer, metadata);
37
39
  }
38
40
 
41
+ export function createYoloVaultStrategy(
42
+ config: IConfig,
43
+ pricer: PricerBase,
44
+ metadata: IStrategyMetadata<YoloVaultSettings>
45
+ ): YoLoVault {
46
+ return new YoLoVault(config, pricer, metadata);
47
+ }
48
+
39
49
  export function createHyperLSTStrategy(
40
50
  config: IConfig,
41
51
  pricer: PricerBase,
@@ -67,6 +77,10 @@ export function getStrategyTypeFromMetadata(
67
77
  metadata: IStrategyMetadata<any>
68
78
  ): FactoryStrategyType {
69
79
  const info = metadata.additionalInfo;
80
+
81
+ if (info && "mainToken" in info && "secondaryToken" in info && "minEpochDurationSeconds" in info && "feeBps" in info) {
82
+ return FactoryStrategyType.YOLO_VAULT;
83
+ }
70
84
 
71
85
  // Check for HyperLST (extends UniversalStrategySettings with borrowable_assets and underlyingToken)
72
86
  if (info && "borrowable_assets" in info && "underlyingToken" in info) {
@@ -153,6 +167,12 @@ export function createStrategy(
153
167
  pricer,
154
168
  metadata as IStrategyMetadata<SenseiVaultSettings>
155
169
  );
170
+ case FactoryStrategyType.YOLO_VAULT:
171
+ return createYoloVaultStrategy(
172
+ config,
173
+ pricer,
174
+ metadata as IStrategyMetadata<YoloVaultSettings>
175
+ );
156
176
  default:
157
177
  throw new Error(`Unknown strategy type: ${type}`);
158
178
  }
@@ -3,8 +3,10 @@ export * from './vesu-rebalance';
3
3
  export * from './ekubo-cl-vault';
4
4
  export * from './base-strategy';
5
5
  export * from './sensei';
6
+ export * from './yoloVault';
6
7
  export * from './universal-adapters';
7
8
  export * from './universal-strategy';
8
9
  export * from './universal-lst-muliplier-strategy';
9
10
  export * from "./registry";
10
11
  export * from "./factory";
12
+ export * from "./types";
@@ -1,4 +1,4 @@
1
- import { IStrategyMetadata } from "@/interfaces";
1
+ import { getAllStrategyTags, IStrategyMetadata } from "@/interfaces";
2
2
  import {
3
3
  EkuboCLVaultStrategies,
4
4
  CLVaultStrategySettings,
@@ -10,6 +10,7 @@ import {
10
10
  import { UniversalStrategies } from "./universal-strategy";
11
11
  import { VesuRebalanceStrategies } from "./vesu-rebalance";
12
12
  import { SenseiStrategies } from "./sensei";
13
+ import { YoloVaultStrategies } from "./yoloVault";
13
14
 
14
15
  /**
15
16
  * Filter option definition
@@ -26,7 +27,6 @@ export interface FilterOption {
26
27
  export interface StrategyFilterMetadata {
27
28
  assets: FilterOption[];
28
29
  protocols: FilterOption[];
29
- categories: FilterOption[];
30
30
  quickFilters: FilterOption[];
31
31
  }
32
32
 
@@ -39,6 +39,7 @@ export enum StrategyType {
39
39
  HYPER_LST = "hyper-lst",
40
40
  VESU_REBALANCE = "vesu-rebalance",
41
41
  SENSEI = "sensei",
42
+ YOLO_VAULT = "yolo-vault",
42
43
  }
43
44
 
44
45
  /**
@@ -50,7 +51,6 @@ export interface StrategyMetadata {
50
51
  type: StrategyType;
51
52
  assets: string[]; // Token symbols (e.g., ["STRK", "USDC"])
52
53
  protocols: string[]; // Protocol names (e.g., ["Ekubo"])
53
- category: string; // Category (e.g., "BTC", "Meta Vaults")
54
54
  tags: string[];
55
55
  curator?: { name: string; logo: string };
56
56
  isRetired: boolean;
@@ -145,6 +145,16 @@ export function buildStrategyRegistry(): StrategyRegistryEntry[] {
145
145
  });
146
146
  }
147
147
 
148
+ // Register Yolo Vault strategies
149
+ if (YoloVaultStrategies && Array.isArray(YoloVaultStrategies)) {
150
+ YoloVaultStrategies.forEach((metadata) => {
151
+ registry.push({
152
+ metadata: metadata as any,
153
+ type: StrategyType.YOLO_VAULT,
154
+ });
155
+ });
156
+ }
157
+
148
158
  return registry;
149
159
  }
150
160
 
@@ -161,7 +171,6 @@ export function getAllStrategyMetadata(): StrategyMetadata[] {
161
171
  type: entry.type,
162
172
  assets: extractAssets(entry.metadata),
163
173
  protocols: entry.metadata.protocols.map(p => p.name.toLowerCase()),
164
- category: entry.metadata.category,
165
174
  tags: entry.metadata.tags || [],
166
175
  curator: entry.metadata.curator,
167
176
  isRetired: isRetired(entry.metadata),
@@ -208,41 +217,17 @@ export function getFilterMetadata(): StrategyFilterMetadata {
208
217
  .sort()
209
218
  .map((id) => ({
210
219
  id,
211
- label:
212
- id === "meta-vaults"
213
- ? "Meta Vaults"
214
- : id.charAt(0).toUpperCase() + id.slice(1)
215
- }));
216
-
217
- // Extract unique categories
218
- const categorySet = new Set<string>();
219
- allMetadata.forEach((meta) => {
220
- if (meta.category) categorySet.add(meta.category);
221
- });
222
- const categories: FilterOption[] = Array.from(categorySet)
223
- .sort()
224
- .map((id) => ({
225
- id,
226
- label:
227
- id === "btc"
228
- ? "BTC"
229
- : id === "meta-vaults"
230
- ? "Meta Vaults"
231
- : "All"
220
+ label: id.charAt(0).toUpperCase() + id.slice(1)
232
221
  }));
233
222
 
234
223
  const quickFilters: FilterOption[] = [
235
224
  { id: "all", label: "All Strategies" },
236
- { id: "btc", label: "BTC" },
237
- { id: "ekubo", label: "Ekubo" },
238
- { id: "endur", label: "Endur" },
239
- { id: "meta-vaults", label: "Meta Vaults" }
225
+ ...getAllStrategyTags().map((tag) => ({ id: tag.toLowerCase().replaceAll(" ", "-"), label: tag })),
240
226
  ];
241
227
 
242
228
  return {
243
229
  assets,
244
230
  protocols,
245
- categories,
246
231
  quickFilters
247
232
  };
248
233
  }
@@ -1,5 +1,11 @@
1
- import { getNoRiskTags, highlightTextWithLinks, IConfig, IProtocol, IStrategyMetadata, RiskFactor, RiskType, StrategyCategory, StrategyTag, TokenInfo, AuditStatus, SourceCodeType, AccessControlType, InstantWithdrawalVault, StrategyLiveStatus, VaultType } 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
10
  import { Call, Contract, num, uint256, BlockIdentifier } from "starknet";
5
11
  import SenseiABI from "@/data/sensei.abi.json";
@@ -94,7 +100,7 @@ export class SenseiVault extends BaseStrategy<
94
100
  tokenInfo: this.metadata.depositTokens[0],
95
101
  };
96
102
  } catch (error) {
97
- console.error('Error fetching TVL:', error);
103
+ console.error(`[SDK] Error fetching TVL for ${this.metadata.id}:`, error);
98
104
  return {
99
105
  usdValue: 0,
100
106
  amount: new Web3Number('0', this.metadata.depositTokens[0].decimals),
@@ -238,6 +244,17 @@ export class SenseiVault extends BaseStrategy<
238
244
  return settings;
239
245
  };
240
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
+
241
258
  async netAPY(): Promise<number> {
242
259
  try {
243
260
  // Fetch Vesu pools and select the Re7 xSTRK pool
@@ -340,9 +357,9 @@ export class SenseiVault extends BaseStrategy<
340
357
  /**
341
358
  * Calculates user realized APY based on position growth accounting for deposits and withdrawals.
342
359
  * Returns the APY as a number.
360
+ * Not implemented for Sensei Strategy yet.
343
361
  */
344
362
  async getUserRealizedAPY(
345
- userAddress: ContractAddr,
346
363
  blockIdentifier: BlockIdentifier = "latest",
347
364
  sinceBlocks = 600000
348
365
  ): Promise<number> {
@@ -488,7 +505,10 @@ export class SenseiVault extends BaseStrategy<
488
505
  return apy;
489
506
  */
490
507
  }
491
-
508
+
509
+ async getUserPositionCards(_input: UserPositionCardsInput): Promise<UserPositionCard[]> {
510
+ return [];
511
+ }
492
512
  }
493
513
 
494
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}}.`;
@@ -574,16 +594,16 @@ export const SenseiStrategies: IStrategyMetadata<SenseiVaultSettings>[] =
574
594
  ),
575
595
  launchBlock: 1053811,
576
596
  type: "Other",
597
+ curator: UnwrapLabsCurator,
577
598
  vaultType: {
578
- type: VaultType.FARMING,
579
- description: "this is a yield farming vault"
599
+ type: VaultType.LOOPING,
600
+ description: "Creates leveraged looping position on xSTRK by borrowing STRK to increase yield"
580
601
  },
581
602
  depositTokens: [
582
603
  Global.getDefaultTokens().find((t) => t.symbol === "STRK")!
583
604
  ],
584
605
  protocols: [endurProtocol, vesuProtocol],
585
606
  settings: {
586
- maxTVL: new Web3Number("1500000", 18),
587
607
  alerts: [
588
608
  {
589
609
  type: "info",
@@ -591,7 +611,7 @@ export const SenseiStrategies: IStrategyMetadata<SenseiVaultSettings>[] =
591
611
  tab: "all"
592
612
  }
593
613
  ],
594
- liveStatus: StrategyLiveStatus.ACTIVE,
614
+ liveStatus: StrategyLiveStatus.RETIRED,
595
615
  isPaused: false,
596
616
  isInMaintenance: false,
597
617
  isAudited: false,
@@ -624,8 +644,7 @@ export const SenseiStrategies: IStrategyMetadata<SenseiVaultSettings>[] =
624
644
  "Repeat the process to loop your position",
625
645
  "Claim DeFi spring (STRK) rewards weekly and reinvest",
626
646
  ],
627
- category: StrategyCategory.ALL,
628
- tags: [StrategyTag.SENSEI],
647
+ tags: [StrategyTag.LEVERED],
629
648
  security: {
630
649
  auditStatus: AuditStatus.AUDITED,
631
650
  sourceCode: {
@@ -633,13 +652,33 @@ export const SenseiStrategies: IStrategyMetadata<SenseiVaultSettings>[] =
633
652
  contractLink: "https://github.com/trovesfi/troves-contracts",
634
653
  },
635
654
  accessControl: {
636
- type: AccessControlType.STANDARD_ACCOUNT,
655
+ type: AccessControlType.ROLE_BASED_ACCESS,
637
656
  addresses: [ContractAddr.from("0x0")],
638
657
  timeLock: "2 Days",
639
658
  },
640
659
  },
641
660
  redemptionInfo: {
642
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
+ ),
643
682
  },
644
683
  },
645
- ];
684
+ ];
@@ -0,0 +1,4 @@
1
+ export enum LSTPriceType {
2
+ ENDUR_PRICE = 'ENDUR_PRICE',
3
+ AVNU_PRICE = 'AVNU_PRICE'
4
+ }
@@ -234,6 +234,25 @@ export const VesuPools = {
234
234
  Re7xSTRK: ContractAddr.from('0x052fb52363939c3aa848f8f4ac28f0a51379f8d1b971d8444de25fbd77d8f161'),
235
235
  Re7xBTC: ContractAddr.from('0x3a8416bf20d036df5b1cf3447630a2e1cb04685f6b0c3a70ed7fb1473548ecf'),
236
236
  Prime: ContractAddr.from('0x451fe483d5921a2919ddd81d0de6696669bccdacd859f72a4fba7656b97c3b5'),
237
+ Re7STRK: ContractAddr.from('0x01fcdacc1d8184eca7b472b5acbaf1500cec9d5683ca95fede8128b46c8f9cc2'),
238
+ }
239
+
240
+ export const VesuPoolMetadata = {
241
+ [VesuPools.Genesis.address]: {
242
+ name: 'Genesis',
243
+ },
244
+ [VesuPools.Re7xSTRK.address]: {
245
+ name: 'Re7 xSTRK',
246
+ },
247
+ [VesuPools.Re7xBTC.address]: {
248
+ name: 'Re7 xBTC',
249
+ },
250
+ [VesuPools.Prime.address]: {
251
+ name: 'Prime',
252
+ },
253
+ [VesuPools.Re7STRK.address]: {
254
+ name: 'Re7 STRK',
255
+ },
237
256
  }
238
257
 
239
258
  export const extensionMap: {[key: string]: ContractAddr} = {};
@@ -418,14 +437,14 @@ export class VesuAdapter extends BaseAdapter {
418
437
  }
419
438
  }
420
439
 
421
- getVesuModifyDelegationAdapter = (id: string): LeafAdapterFn<VesuModifyDelegationCallParams> => {
440
+ getVesuModifyDelegationAdapter = (id: string, delegatee: ContractAddr): LeafAdapterFn<VesuModifyDelegationCallParams> => {
422
441
  return () => {
423
442
  const { addr: VESU_SINGLETON, isV2 } = getVesuSingletonAddress(this.config.poolId);
424
443
  const packedArguments: bigint[] = isV2 ? [
425
- toBigInt(this.VESU_MULTIPLY.toString()), // v2
444
+ toBigInt(delegatee.toString()), // v2
426
445
  ] : [
427
446
  this.config.poolId.toBigInt(),
428
- toBigInt(this.VESU_MULTIPLY_V1.toString()), // v1
447
+ toBigInt(delegatee.toString()), // v1
429
448
  ];
430
449
  const output = this.constructSimpleLeafData({
431
450
  id: id,
@@ -434,29 +453,31 @@ export class VesuAdapter extends BaseAdapter {
434
453
  packedArguments
435
454
  }, isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER_VESU_V1_DELEGATIONS);
436
455
 
437
- return { leaf: output, callConstructor: this.getVesuModifyDelegationCall.bind(this) };
456
+ return { leaf: output, callConstructor: this.getVesuModifyDelegationCall(delegatee).bind(this) };
438
457
  }
439
458
  }
440
459
 
441
- getVesuModifyDelegationCall = (params: VesuModifyDelegationCallParams): ManageCall => {
442
- const VESU_SINGLETON = getVesuSingletonAddress(this.config.poolId).addr;
443
- const { contract, isV2 } = this.getVesuSingletonContract(getMainnetConfig(), this.config.poolId);
444
- const call = contract.populate('modify_delegation', isV2 ? {
445
- delegatee: this.VESU_MULTIPLY.toBigInt(),
446
- delegation: params.delegation,
447
- } : {
448
- pool_id: this.config.poolId.toBigInt(),
449
- delegatee: this.VESU_MULTIPLY_V1.toBigInt(),
450
- delegation: params.delegation,
451
- });
452
- return {
453
- sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER_VESU_V1_DELEGATIONS,
454
- call: {
455
- contractAddress: VESU_SINGLETON,
456
- selector: hash.getSelectorFromName('modify_delegation'),
457
- calldata: [
458
- ...call.calldata as bigint[]
459
- ]
460
+ getVesuModifyDelegationCall = (delegatee: ContractAddr) => {
461
+ return (params: VesuModifyDelegationCallParams) => {
462
+ const VESU_SINGLETON = getVesuSingletonAddress(this.config.poolId).addr;
463
+ const { contract, isV2 } = this.getVesuSingletonContract(getMainnetConfig(), this.config.poolId);
464
+ const call = contract.populate('modify_delegation', isV2 ? {
465
+ delegatee: delegatee.toBigInt(),
466
+ delegation: params.delegation,
467
+ } : {
468
+ pool_id: this.config.poolId.toBigInt(),
469
+ delegatee: delegatee.toBigInt(),
470
+ delegation: params.delegation,
471
+ });
472
+ return {
473
+ sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER_VESU_V1_DELEGATIONS,
474
+ call: {
475
+ contractAddress: VESU_SINGLETON,
476
+ selector: hash.getSelectorFromName('modify_delegation'),
477
+ calldata: [
478
+ ...call.calldata as bigint[]
479
+ ]
480
+ }
460
481
  }
461
482
  }
462
483
  }
@@ -654,12 +675,12 @@ export class VesuAdapter extends BaseAdapter {
654
675
  amount: collateralAmount,
655
676
  token: this.config.collateral,
656
677
  usdValue: collateralAmount.multipliedBy(token1Price.price).toNumber(),
657
- remarks: "Collateral"
678
+ remarks: `Collateral - ${VesuPoolMetadata[this.config.poolId.address].name} pool`
658
679
  }, {
659
680
  amount: debtAmount,
660
681
  token: this.config.debt,
661
682
  usdValue: debtAmount.multipliedBy(token2Price.price).toNumber(),
662
- remarks: "Debt"
683
+ remarks: `Debt - ${VesuPoolMetadata[this.config.poolId.address].name} pool`
663
684
  }];
664
685
  this.setCache(CACHE_KEY, value, 60000); // ttl: 1min
665
686
  return value;