@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.
@@ -1,5 +1,5 @@
1
1
  import { ContractAddr, Web3Number } from "@/dataTypes";
2
- import { SingleActionAmount, SingleTokenInfo, UserPositionCard, UserPositionCardsInput } from "./base-strategy";
2
+ import { SingleActionAmount, SingleTokenInfo } from "./base-strategy";
3
3
  import { PricerBase } from "@/modules/pricerBase";
4
4
  import { FAQ, getNoRiskTags, IConfig, IStrategyMetadata, Protocols, RiskFactor, RiskType, StrategyTag, VaultPosition, AuditStatus, SourceCodeType, AccessControlType, InstantWithdrawalVault, StrategyLiveStatus, StrategySettings, VaultType, RedemptionInfo, UnwrapLabsCurator, getMainnetConfig } from "@/interfaces";
5
5
  import { BlockIdentifier, Call, CallData, Contract, num, uint256 } from "starknet";
@@ -35,7 +35,7 @@ export interface UniversalStrategySettings {
35
35
 
36
36
  // Useful for returning adapter class objects that can compute
37
37
  // certain things for us (e.g. positions, hfs)
38
- adapters: {id: string, adapter: BaseAdapter<DepositParams, WithdrawParams>}[]
38
+ adapters: { id: string, adapter: BaseAdapter<DepositParams, WithdrawParams> }[]
39
39
 
40
40
  targetHealthFactor: number,
41
41
  minHealthFactor: number
@@ -57,15 +57,15 @@ export class UniversalStrategy<
57
57
  > extends SVKStrategy<S> {
58
58
 
59
59
  constructor(
60
- config: IConfig,
61
- pricer: PricerBase,
62
- metadata: IStrategyMetadata<S>
63
- ) {
64
- super(config, pricer, metadata);
65
- assert(
66
- metadata.depositTokens.length === 1,
67
- "VesuRebalance only supports 1 deposit token",
68
- );
60
+ config: IConfig,
61
+ pricer: PricerBase,
62
+ metadata: IStrategyMetadata<S>
63
+ ) {
64
+ super(config, pricer, metadata);
65
+ assert(
66
+ metadata.depositTokens.length === 1,
67
+ "VesuRebalance only supports 1 deposit token",
68
+ );
69
69
  }
70
70
 
71
71
  getMerkleTree() {
@@ -155,35 +155,6 @@ export class UniversalStrategy<
155
155
  return [call];
156
156
  }
157
157
 
158
- async getUserTVL(user: ContractAddr, blockIdentifier: BlockIdentifier = "latest") {
159
- const shares: any = await this.contract.call("balanceOf", [user.address], { blockIdentifier });
160
- const assets: any = await this.contract.call(
161
- "convert_to_assets",
162
- [uint256.bnToUint256(shares)],
163
- { blockIdentifier }
164
- );
165
- const amount = Web3Number.fromWei(
166
- assets.toString(),
167
- this.metadata.depositTokens[0].decimals
168
- );
169
-
170
- // Convert blockIdentifier to block number for pricer if it's a number
171
- const blockNumber = typeof blockIdentifier === 'number' || typeof blockIdentifier === 'bigint'
172
- ? Number(blockIdentifier)
173
- : undefined;
174
-
175
- let price = await this.pricer.getPrice(
176
- this.metadata.depositTokens[0].symbol,
177
- blockNumber
178
- );
179
- const usdValue = Number(amount.toFixed(6)) * price.price;
180
- return {
181
- tokenInfo: this.asset(),
182
- amount,
183
- usdValue
184
- };
185
- }
186
-
187
158
  async getVesuAPYs() {
188
159
  // get Vesu pools, positions and APYs
189
160
  const vesuAdapters = this.getVesuAdapters();
@@ -233,11 +204,13 @@ export class UniversalStrategy<
233
204
  */
234
205
  async netAPY(): Promise<{ net: number, splits: { apy: number, id: string }[] }> {
235
206
  if (this.metadata.isPreview) {
236
- return { net: 0, splits: [{
237
- apy: 0, id: 'base'
238
- }, {
239
- apy: 0, id: 'defispring'
240
- }] };
207
+ return {
208
+ net: 0, splits: [{
209
+ apy: 0, id: 'base'
210
+ }, {
211
+ apy: 0, id: 'defispring'
212
+ }]
213
+ };
241
214
  }
242
215
 
243
216
  const { positions, baseAPYs, rewardAPYs } = await this.getVesuAPYs();
@@ -259,22 +232,26 @@ export class UniversalStrategy<
259
232
  protected async returnNetAPY(baseAPYs: number[], rewardAPYs: number[], weights: number[], prevAUMUSD: Web3Number) {
260
233
  // If no positions, return 0
261
234
  if (weights.every(p => p == 0)) {
262
- return { net: 0, splits: [{
263
- apy: 0, id: 'base'
264
- }, {
265
- apy: 0, id: 'defispring'
266
- }]};
235
+ return {
236
+ net: 0, splits: [{
237
+ apy: 0, id: 'base'
238
+ }, {
239
+ apy: 0, id: 'defispring'
240
+ }]
241
+ };
267
242
  }
268
243
 
269
244
  const baseAPY = this.computeAPY(baseAPYs, weights, prevAUMUSD);
270
245
  const rewardAPY = this.computeAPY(rewardAPYs, weights, prevAUMUSD);
271
246
  const netAPY = baseAPY + rewardAPY;
272
247
  logger.verbose(`${this.metadata.name}::netAPY: net: ${netAPY}, baseAPY: ${baseAPY}, rewardAPY: ${rewardAPY}`);
273
- return { net: netAPY, splits: [{
274
- apy: baseAPY, id: 'base'
275
- }, {
276
- apy: rewardAPY, id: 'defispring'
277
- }] };
248
+ return {
249
+ net: netAPY, splits: [{
250
+ apy: baseAPY, id: 'base'
251
+ }, {
252
+ apy: rewardAPY, id: 'defispring'
253
+ }]
254
+ };
278
255
  }
279
256
 
280
257
  protected async getUnusedBalanceAPY() {
@@ -290,144 +267,6 @@ export class UniversalStrategy<
290
267
  return weightedSum / currentAUM.toNumber();
291
268
  }
292
269
 
293
- /**
294
- * Calculates user realized APY based on trueSharesBasedAPY method.
295
- * Returns the APY as a number.
296
- */
297
- async getUserRealizedAPY(
298
- blockIdentifier: BlockIdentifier = "latest",
299
- sinceBlocks = 600000
300
- ): Promise<number> {
301
- logger.verbose(
302
- `${this.getTag()}: getUserRealizedAPY => starting with blockIdentifier=${blockIdentifier}, sinceBlocks=${sinceBlocks}`
303
- );
304
-
305
- // Determine current block number and timestamp
306
- let blockNow =
307
- typeof blockIdentifier === "number" || typeof blockIdentifier === "bigint"
308
- ? Number(blockIdentifier)
309
- : (await this.config.provider.getBlockLatestAccepted()).block_number;
310
- const blockNowTime =
311
- typeof blockIdentifier === "number" || typeof blockIdentifier === "bigint"
312
- ? (await this.config.provider.getBlockWithTxs(blockIdentifier)).timestamp
313
- : new Date().getTime() / 1000;
314
-
315
- // Look back window, but never before launch block
316
- const blockBefore = Math.max(
317
- blockNow - sinceBlocks,
318
- this.metadata.launchBlock
319
- );
320
-
321
- // TVL amounts (in underlying token units) and supply at current reference block
322
- const assetsNowRaw: bigint = await this.contract.call("total_assets", [], {
323
- blockIdentifier,
324
- }) as bigint;
325
- const amountNow = Web3Number.fromWei(
326
- assetsNowRaw.toString(),
327
- this.metadata.depositTokens[0].decimals
328
- );
329
-
330
- const supplyNowRaw: bigint = await this.contract.call("total_supply", [], {
331
- blockIdentifier,
332
- }) as bigint;
333
- const supplyNow = Web3Number.fromWei(supplyNowRaw.toString(), 18);
334
-
335
- // Historical TVL and supply
336
- const assetsBeforeRaw: bigint = await this.contract.call(
337
- "total_assets",
338
- [],
339
- { blockIdentifier: blockBefore }
340
- ) as bigint;
341
- const amountBefore = Web3Number.fromWei(
342
- assetsBeforeRaw.toString(),
343
- this.metadata.depositTokens[0].decimals
344
- );
345
-
346
- const supplyBeforeRaw: bigint = await this.contract.call(
347
- "total_supply",
348
- [],
349
- { blockIdentifier: blockBefore }
350
- ) as bigint;
351
- const supplyBefore = Web3Number.fromWei(supplyBeforeRaw.toString(), 18);
352
-
353
- const blockBeforeInfo = await this.config.provider.getBlockWithTxs(
354
- blockBefore
355
- );
356
-
357
- // Calculate assets per share
358
- const assetsPerShareNow = amountNow
359
- .multipliedBy(1e18)
360
- .dividedBy(supplyNow.toString());
361
-
362
- const assetsPerShareBf = amountBefore
363
- .multipliedBy(1e18)
364
- .dividedBy(supplyBefore.toString());
365
-
366
- const timeDiffSeconds = blockNowTime - blockBeforeInfo.timestamp;
367
-
368
- logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsNow: ${amountNow.toString()}`);
369
- logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsBefore: ${amountBefore.toString()}`);
370
- logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsPerShareNow: ${assetsPerShareNow.toString()}`);
371
- logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsPerShareBf: ${assetsPerShareBf.toString()}`);
372
- logger.verbose(`${this.getTag()} [getUserRealizedAPY] Supply before: ${supplyBefore.toString()}`);
373
- logger.verbose(`${this.getTag()} [getUserRealizedAPY] Supply now: ${supplyNow.toString()}`);
374
- logger.verbose(`${this.getTag()} [getUserRealizedAPY] Time diff in seconds: ${timeDiffSeconds}`);
375
-
376
- const apyForGivenBlocks =
377
- Number(
378
- assetsPerShareNow
379
- .minus(assetsPerShareBf)
380
- .multipliedBy(10000)
381
- .dividedBy(assetsPerShareBf)
382
- ) / 10000;
383
-
384
- return (apyForGivenBlocks * (365 * 24 * 3600)) / timeDiffSeconds;
385
- }
386
-
387
- async getUserPositionCards(input: UserPositionCardsInput): Promise<UserPositionCard[]> {
388
- const { user, investmentFlows = [] } = input;
389
- const [userTVL] = await Promise.all([
390
- this.getUserTVL(user),
391
- ]);
392
- const cards: UserPositionCard[] = [
393
- {
394
- title: "Your Holdings",
395
- tooltip: "Your Holdings",
396
- value: this.formatTokenAmountForCard(userTVL.amount, userTVL.tokenInfo),
397
- subValue: `≈ ${this.formatUSDForCard(userTVL.usdValue)}`,
398
- subValueColor: "positive",
399
- },
400
- ];
401
-
402
- let lifetimeAmount = userTVL.amount.multipliedBy(0);
403
- let lifetimeTokenInfo = userTVL.tokenInfo;
404
- let lifetimeUsdValue = 0;
405
- if (investmentFlows.length > 0) {
406
- try {
407
- const earningsResult = this.getLifetimeEarnings(userTVL, investmentFlows);
408
- lifetimeAmount = earningsResult.lifetimeEarnings;
409
- lifetimeTokenInfo = earningsResult.tokenInfo.tokenInfo;
410
- const userAmount = userTVL.amount.toNumber();
411
- if (Number.isFinite(userAmount) && userAmount > 0) {
412
- const pricePerToken = userTVL.usdValue / userAmount;
413
- lifetimeUsdValue = lifetimeAmount.toNumber() * pricePerToken;
414
- }
415
- } catch (error) {
416
- logger.warn(`${this.getTag()}::getUserPositionCards lifetime earnings fallback`, error);
417
- }
418
- }
419
-
420
- cards.push({
421
- title: "Lifetime Earnings",
422
- tooltip: "Lifetime Earnings",
423
- value: this.formatTokenAmountForCard(lifetimeAmount, lifetimeTokenInfo),
424
- subValue: `≈ ${this.formatUSDForCard(lifetimeUsdValue)}`,
425
- subValueColor: this.getSubValueColorFromSignedNumber(lifetimeUsdValue),
426
- });
427
-
428
- return cards;
429
- }
430
-
431
270
  /**
432
271
  * Calculates the total TVL of the strategy.
433
272
  * @returns Object containing the total amount in token units and USD value
@@ -493,7 +332,7 @@ export class UniversalStrategy<
493
332
  return prevAum;
494
333
  }
495
334
 
496
- async getAUM(unrealizedAUM?: boolean): Promise<{net: SingleTokenInfo, prevAum: Web3Number, splits: {id: string, aum: Web3Number}[]}> {
335
+ async getAUM(unrealizedAUM?: boolean): Promise<{ net: SingleTokenInfo, prevAum: Web3Number, splits: { id: string, aum: Web3Number }[] }> {
497
336
  const prevAum = await this.getPrevAUM();
498
337
  const token1Price = await this.pricer.getPrice(this.metadata.depositTokens[0].symbol);
499
338
 
@@ -519,11 +358,13 @@ export class UniversalStrategy<
519
358
  };
520
359
  const aumToken = vesuAum.plus(balance.amount);
521
360
  if (aumToken.isZero()) {
522
- return { net, splits: [{
523
- aum: zeroAmt, id: AUMTypes.FINALISED
524
- }, {
525
- aum: zeroAmt, id: AUMTypes.DEFISPRING
526
- }], prevAum};
361
+ return {
362
+ net, splits: [{
363
+ aum: zeroAmt, id: AUMTypes.FINALISED
364
+ }, {
365
+ aum: zeroAmt, id: AUMTypes.DEFISPRING
366
+ }], prevAum
367
+ };
527
368
  }
528
369
  logger.verbose(`${this.getTag()} Actual AUM: ${aumToken}`);
529
370
 
@@ -638,39 +479,39 @@ export class UniversalStrategy<
638
479
  depositAmount: Web3Number,
639
480
  debtAmount: Web3Number
640
481
  }): UniversalManageCall[] {
641
- assert(params.depositAmount.gt(0) || params.debtAmount.gt(0), 'Either deposit or debt amount must be greater than 0');
642
- // approve token
643
- const isToken1 = params.isLeg1 == params.isDeposit; // XOR
644
- const STEP1_ID = isToken1 ? UNIVERSAL_MANAGE_IDS.APPROVE_TOKEN1 :UNIVERSAL_MANAGE_IDS.APPROVE_TOKEN2;
645
- const manage4Info = this.getProofs<ApproveCallParams>(STEP1_ID);
646
- const approveAmount = params.isDeposit ? params.depositAmount : params.debtAmount;
647
- const manageCall4 = manage4Info.callConstructor({
648
- amount: approveAmount
649
- })
482
+ assert(params.depositAmount.gt(0) || params.debtAmount.gt(0), 'Either deposit or debt amount must be greater than 0');
483
+ // approve token
484
+ const isToken1 = params.isLeg1 == params.isDeposit; // XOR
485
+ const STEP1_ID = isToken1 ? UNIVERSAL_MANAGE_IDS.APPROVE_TOKEN1 : UNIVERSAL_MANAGE_IDS.APPROVE_TOKEN2;
486
+ const manage4Info = this.getProofs<ApproveCallParams>(STEP1_ID);
487
+ const approveAmount = params.isDeposit ? params.depositAmount : params.debtAmount;
488
+ const manageCall4 = manage4Info.callConstructor({
489
+ amount: approveAmount
490
+ })
650
491
 
651
- // deposit and borrow or repay and withdraw
652
- const STEP2_ID = params.isLeg1 ? UNIVERSAL_MANAGE_IDS.VESU_LEG1 : UNIVERSAL_MANAGE_IDS.VESU_LEG2;
653
- const manage5Info = this.getProofs<VesuModifyPositionCallParams>(STEP2_ID);
654
- const manageCall5 = manage5Info.callConstructor(VesuAdapter.getDefaultModifyPositionCallParams({
655
- collateralAmount: params.depositAmount,
656
- isAddCollateral: params.isDeposit,
657
- debtAmount: params.debtAmount,
658
- isBorrow: params.isDeposit
659
- }))
660
-
661
- const output: UniversalManageCall[] = [{
662
- proofs: manage5Info.proofs,
663
- manageCall: manageCall5 as unknown as ManageCall,
664
- step: STEP2_ID
665
- }];
666
- if (approveAmount.gt(0)) {
667
- output.unshift({
668
- proofs: manage4Info.proofs,
669
- manageCall: manageCall4 as unknown as ManageCall,
670
- step: STEP1_ID
671
- })
672
- }
673
- return output;
492
+ // deposit and borrow or repay and withdraw
493
+ const STEP2_ID = params.isLeg1 ? UNIVERSAL_MANAGE_IDS.VESU_LEG1 : UNIVERSAL_MANAGE_IDS.VESU_LEG2;
494
+ const manage5Info = this.getProofs<VesuModifyPositionCallParams>(STEP2_ID);
495
+ const manageCall5 = manage5Info.callConstructor(VesuAdapter.getDefaultModifyPositionCallParams({
496
+ collateralAmount: params.depositAmount,
497
+ isAddCollateral: params.isDeposit,
498
+ debtAmount: params.debtAmount,
499
+ isBorrow: params.isDeposit
500
+ }))
501
+
502
+ const output: UniversalManageCall[] = [{
503
+ proofs: manage5Info.proofs,
504
+ manageCall: manageCall5 as unknown as ManageCall,
505
+ step: STEP2_ID
506
+ }];
507
+ if (approveAmount.gt(0)) {
508
+ output.unshift({
509
+ proofs: manage4Info.proofs,
510
+ manageCall: manageCall4 as unknown as ManageCall,
511
+ step: STEP1_ID
512
+ })
513
+ }
514
+ return output;
674
515
  }
675
516
 
676
517
  getTag() {
@@ -764,7 +605,7 @@ export class UniversalStrategy<
764
605
  } = await vesuAdapter.getAssetPrices();
765
606
 
766
607
  // debt is zero, nothing to rebalance
767
- if(debtTokenAmount.isZero()) {
608
+ if (debtTokenAmount.isZero()) {
768
609
  return Web3Number.fromWei(0, 0);
769
610
  }
770
611
 
@@ -782,7 +623,7 @@ export class UniversalStrategy<
782
623
  return new Web3Number(newAmount.toFixed(8), collateralTokenAmount.decimals);
783
624
  } else {
784
625
  // TargetHF = collUSD * ltv / (debtAmount - newAmount) * debtPrice
785
- const newAmount = debtTokenAmount.toNumber() - collateralUSDAmount * ltv / (targetHF * debtPrice);
626
+ const newAmount = debtTokenAmount.toNumber() - collateralUSDAmount * ltv / (targetHF * debtPrice);
786
627
  logger.verbose(`${this.getTag()}:: getLegRebalanceAmount: repayDebt, currentHf: ${currentHf}, targetHF: ${targetHF}, collAmount: ${collateralTokenAmount.toString()}, collUSD: ${collateralUSDAmount}, collPrice: ${collateralPrice}, debtAmount: ${debtTokenAmount.toString()}, debtUSD: ${debtUSDAmount}, debtPrice: ${debtPrice}, ltv: ${ltv}, newAmount: ${newAmount}`);
787
628
  return new Web3Number(newAmount.toFixed(8), debtTokenAmount.decimals);
788
629
  }
@@ -805,7 +646,7 @@ export class UniversalStrategy<
805
646
 
806
647
  const TARGET_HF = this.metadata.additionalInfo.targetHealthFactor;
807
648
 
808
- const k1 = token1Price.price * leg1LTV / token2Price.price / TARGET_HF;
649
+ const k1 = token1Price.price * leg1LTV / token2Price.price / TARGET_HF;
809
650
  const k2 = token1Price.price * TARGET_HF / token2Price.price / leg2LTV;
810
651
 
811
652
  const borrow2Amount = new Web3Number(
@@ -841,19 +682,19 @@ export class UniversalStrategy<
841
682
  }
842
683
  const allActions = [...callSet1.map(i => i.manageCall), ...callSet2.map(i => i.manageCall)];
843
684
  const flashloanCalldata = CallData.compile([
844
- [...callSet1.map(i => i.proofs), ...callSet2.map(i => i.proofs)],
845
- allActions.map(i => i.sanitizer.address),
846
- allActions.map(i => i.call.contractAddress.address),
847
- allActions.map(i => i.call.selector),
848
- allActions.map(i => i.call.calldata)
685
+ [...callSet1.map(i => i.proofs), ...callSet2.map(i => i.proofs)],
686
+ allActions.map(i => i.sanitizer.address),
687
+ allActions.map(i => i.call.contractAddress.address),
688
+ allActions.map(i => i.call.selector),
689
+ allActions.map(i => i.call.calldata)
849
690
  ])
850
691
 
851
692
  // flash loan
852
693
  const STEP1_ID = UNIVERSAL_MANAGE_IDS.FLASH_LOAN;
853
694
  const manage1Info = this.getProofs<FlashloanCallParams>(STEP1_ID);
854
695
  const manageCall1 = manage1Info.callConstructor({
855
- amount: borrow2Amount,
856
- data: flashloanCalldata.map(i => BigInt(i))
696
+ amount: borrow2Amount,
697
+ data: flashloanCalldata.map(i => BigInt(i))
857
698
  })
858
699
  const manageCall = this.getManageCallFromManageCalls([
859
700
  manageCall1 as unknown as ManageCall,
@@ -884,8 +725,8 @@ export class UniversalStrategy<
884
725
 
885
726
  const manage1Info = this.getProofs<VesuDefiSpringRewardsCallParams>(UNIVERSAL_MANAGE_IDS.DEFISPRING_REWARDS);
886
727
  const manageCall1 = manage1Info.callConstructor({
887
- amount,
888
- proofs
728
+ amount,
729
+ proofs
889
730
  });
890
731
  const manageCalls: ManageCall[] = [manageCall1 as unknown as ManageCall];
891
732
 
@@ -895,21 +736,21 @@ export class UniversalStrategy<
895
736
  // approve
896
737
  const manage2Info = this.getProofs<ApproveCallParams>(UNIVERSAL_MANAGE_IDS.APPROVE_SWAP_TOKEN1);
897
738
  const manageCall2 = manage2Info.callConstructor({
898
- amount: actualReward
739
+ amount: actualReward
899
740
  });
900
741
 
901
742
  // swap
902
743
  const avnuModule = new AvnuWrapper();
903
744
  const quote = await avnuModule.getQuotes(
904
- STRK.address.address,
905
- this.asset().address.address,
906
- actualReward.toWei(),
907
- this.address.address
745
+ STRK.address.address,
746
+ this.asset().address.address,
747
+ actualReward.toWei(),
748
+ this.address.address
908
749
  );
909
750
  const swapInfo = await avnuModule.getSwapInfo(quote, this.address.address, 0, this.address.address);
910
751
  const manage3Info = this.getProofs<AvnuSwapCallParams>(UNIVERSAL_MANAGE_IDS.AVNU_SWAP_REWARDS);
911
752
  const manageCall3 = manage3Info.callConstructor({
912
- props: swapInfo
753
+ props: swapInfo
913
754
  });
914
755
  manageCalls.push(manageCall2 as unknown as ManageCall);
915
756
  manageCalls.push(manageCall3 as unknown as ManageCall);
@@ -1016,7 +857,7 @@ function getLooperSettings(
1016
857
  quoteAmountToFetchPrice: new Web3Number(0.1, 18),
1017
858
  minimumVesuMovementAmount: 5,
1018
859
  ...baseAdapterConfig,
1019
- supportedPositions: [{asset: ETHToken, isDebt: false}, {asset: USDCToken, isDebt: true}],
860
+ supportedPositions: [{ asset: ETHToken, isDebt: false }, { asset: USDCToken, isDebt: true }],
1020
861
  })
1021
862
  const vesuModifyPositionAdapter = new VesuModifyPositionAdapter({
1022
863
  poolId: pool1,
@@ -1025,7 +866,7 @@ function getLooperSettings(
1025
866
  targetLtv: 0.75,
1026
867
  maxLtv: 0.9,
1027
868
  ...baseAdapterConfig,
1028
- supportedPositions: [{asset: ETHToken, isDebt: false}, {asset: USDCToken, isDebt: true}],
869
+ supportedPositions: [{ asset: ETHToken, isDebt: false }, { asset: USDCToken, isDebt: true }],
1029
870
  })
1030
871
 
1031
872
  const avnuAdapter = new AvnuAdapter({
@@ -1035,7 +876,7 @@ function getLooperSettings(
1035
876
  minimumExtendedPriceDifferenceForSwapOpen: 0,
1036
877
  maximumExtendedPriceDifferenceForSwapClosing: 0,
1037
878
  ...baseAdapterConfig,
1038
- supportedPositions: [{asset: ETHToken, isDebt: false}, {asset: USDCToken, isDebt: false}],
879
+ supportedPositions: [{ asset: ETHToken, isDebt: false }, { asset: USDCToken, isDebt: false }],
1039
880
  })
1040
881
  // vaultSettings.adapters.push(...[{
1041
882
  // id: UNIVERSAL_ADAPTERS.COMMON,
@@ -1295,7 +1136,7 @@ function getFAQs(): FAQ[] {
1295
1136
  ];
1296
1137
  }
1297
1138
 
1298
- export function getContractDetails(settings: UniversalStrategySettings & { aumOracle?: ContractAddr }): {address: ContractAddr, name: string}[] {
1139
+ export function getContractDetails(settings: UniversalStrategySettings & { aumOracle?: ContractAddr }): { address: ContractAddr, name: string }[] {
1299
1140
  const contracts = [
1300
1141
  { address: settings.vaultAddress, name: "Vault" },
1301
1142
  { address: settings.manager, name: "Vault Manager" },
@@ -1319,38 +1160,38 @@ const AUDIT_URL = 'https://docs.troves.fi/p/security#starknet-vault-kit'
1319
1160
 
1320
1161
  // Helper to create common risk object
1321
1162
  const getUniversalRisk = () => ({
1322
- riskFactor: _riskFactor,
1323
- netRisk:
1324
- _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) /
1325
- _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
1326
- notARisks: getNoRiskTags(_riskFactor)
1163
+ riskFactor: _riskFactor,
1164
+ netRisk:
1165
+ _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) /
1166
+ _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
1167
+ notARisks: getNoRiskTags(_riskFactor)
1327
1168
  });
1328
1169
 
1329
1170
  // Helper to create Universal strategy settings
1330
1171
  const createUniversalSettings = (
1331
- tokenSymbol: string,
1332
- maxTVLDecimals: number
1172
+ tokenSymbol: string,
1173
+ maxTVLDecimals: number
1333
1174
  ): StrategySettings => {
1334
- const isUSDT = tokenSymbol === "USDT";
1335
- return {
1336
- maxTVL: Web3Number.fromWei(0, maxTVLDecimals),
1337
- isAudited: true,
1338
- liveStatus: isUSDT ? StrategyLiveStatus.RETIRED : StrategyLiveStatus.ACTIVE,
1339
- isPaused: isUSDT,
1340
- isInstantWithdrawal: false,
1341
- hideHarvestInfo: true,
1342
- quoteToken: Global.getDefaultTokens().find(
1343
- (token) => token.symbol === tokenSymbol
1344
- )!,
1345
- alerts: [
1346
- {
1347
- tab: "withdraw" as const,
1348
- text: "On withdrawal, you will receive an NFT representing your withdrawal request. The funds will be automatically sent to your wallet (NFT owner) in 1-2 hours. You can monitor the status in transactions tab.",
1349
- type: "info" as const
1350
- }
1351
- ],
1352
- showWithdrawalWarningModal: true
1353
- };
1175
+ const isUSDT = tokenSymbol === "USDT";
1176
+ return {
1177
+ maxTVL: Web3Number.fromWei(0, maxTVLDecimals),
1178
+ isAudited: true,
1179
+ liveStatus: isUSDT ? StrategyLiveStatus.RETIRED : StrategyLiveStatus.ACTIVE,
1180
+ isPaused: isUSDT,
1181
+ isInstantWithdrawal: false,
1182
+ hideHarvestInfo: true,
1183
+ quoteToken: Global.getDefaultTokens().find(
1184
+ (token) => token.symbol === tokenSymbol
1185
+ )!,
1186
+ alerts: [
1187
+ {
1188
+ tab: "withdraw" as const,
1189
+ text: "On withdrawal, you will receive an NFT representing your withdrawal request. The funds will be automatically sent to your wallet (NFT owner) in 1-2 hours. You can monitor the status in transactions tab.",
1190
+ type: "info" as const
1191
+ }
1192
+ ],
1193
+ showWithdrawalWarningModal: true
1194
+ };
1354
1195
  };
1355
1196
 
1356
1197
  const EVERGREEN_SECURITY = {
@@ -1369,8 +1210,8 @@ const EVERGREEN_SECURITY = {
1369
1210
  const EVERGREEN_REDEMPTION_INFO: RedemptionInfo = {
1370
1211
  instantWithdrawalVault: InstantWithdrawalVault.NO,
1371
1212
  redemptionsInfo: [{
1372
- title: "Typical Duration",
1373
- description: "1-2 hours"
1213
+ title: "Typical Duration",
1214
+ description: "1-2 hours"
1374
1215
  }],
1375
1216
  alerts: [{
1376
1217
  type: 'info',
@@ -1381,107 +1222,110 @@ const EVERGREEN_REDEMPTION_INFO: RedemptionInfo = {
1381
1222
 
1382
1223
  // Helper to create a Universal strategy
1383
1224
  const createUniversalStrategy = (params: {
1384
- tokenSymbol: string;
1385
- address: string;
1386
- vaultSettings: UniversalStrategySettings;
1387
- token1Symbol: string;
1388
- token2Symbol: string;
1389
- maxTVLDecimals: number;
1390
- allowedSources: AllowedSources[];
1391
- tags: StrategyTag[];
1225
+ tokenSymbol: string;
1226
+ address: string;
1227
+ vaultSettings: UniversalStrategySettings;
1228
+ token1Symbol: string;
1229
+ token2Symbol: string;
1230
+ maxTVLDecimals: number;
1231
+ allowedSources: AllowedSources[];
1232
+ tags: StrategyTag[];
1392
1233
  }): IStrategyMetadata<UniversalStrategySettings> => {
1393
- const isUSDT = params.tokenSymbol === "USDT";
1394
- return {
1395
- id: `evergreen_${params.tokenSymbol.toLowerCase()}`,
1396
- name: `${params.tokenSymbol} Evergreen`,
1397
- description: getDescription(params.tokenSymbol, params.allowedSources),
1398
- address: ContractAddr.from(params.address),
1399
- launchBlock: 0,
1400
- type: "ERC4626" as const,
1401
- vaultType: {
1402
- type: VaultType.META_VAULT,
1403
- description: "Automatically allocates funds to the best available yield source in the ecosystem"
1404
- },
1405
- depositTokens: [
1406
- Global.getDefaultTokens().find((token) => token.symbol === params.tokenSymbol)!
1407
- ],
1408
- additionalInfo: getLooperSettings(
1409
- params.token1Symbol,
1410
- params.token2Symbol,
1411
- params.vaultSettings,
1412
- VesuPools.Genesis,
1413
- VesuPools.Genesis
1414
- ),
1415
- risk: getUniversalRisk(),
1416
- auditUrl: AUDIT_URL,
1417
- protocols: [Protocols.VESU],
1418
- realizedApyMethodology: "The realizedAPY is based on past 14 days performance by the vault",
1419
- curator: UnwrapLabsCurator,
1420
- settings: createUniversalSettings(params.tokenSymbol, params.maxTVLDecimals),
1421
- contractDetails: getContractDetails(params.vaultSettings),
1422
- faqs: getFAQs(),
1423
- investmentSteps: investmentSteps,
1424
- tags: params.tags,
1425
- security: EVERGREEN_SECURITY,
1426
- redemptionInfo: EVERGREEN_REDEMPTION_INFO,
1427
- discontinuationInfo: isUSDT ? {
1428
- info: "This strategy has been retired and is no longer accepting new deposits."
1429
- } : undefined,
1430
- usualTimeToEarnings: null,
1431
- usualTimeToEarningsDescription: null,
1432
- };
1234
+ const isUSDT = params.tokenSymbol === "USDT";
1235
+ return {
1236
+ id: `evergreen_${params.tokenSymbol.toLowerCase()}`,
1237
+ name: `${params.tokenSymbol} Evergreen`,
1238
+ description: getDescription(params.tokenSymbol, params.allowedSources),
1239
+ address: ContractAddr.from(params.address),
1240
+ launchBlock: 0,
1241
+ type: "ERC4626" as const,
1242
+ vaultType: {
1243
+ type: VaultType.META_VAULT,
1244
+ description: "Automatically allocates funds to the best available yield source in the ecosystem"
1245
+ },
1246
+ depositTokens: [
1247
+ Global.getDefaultTokens().find((token) => token.symbol === params.tokenSymbol)!
1248
+ ],
1249
+ additionalInfo: getLooperSettings(
1250
+ params.token1Symbol,
1251
+ params.token2Symbol,
1252
+ params.vaultSettings,
1253
+ VesuPools.Genesis,
1254
+ VesuPools.Genesis
1255
+ ),
1256
+ risk: getUniversalRisk(),
1257
+ auditUrl: AUDIT_URL,
1258
+ protocols: [Protocols.VESU],
1259
+ realizedApyMethodology: "The realizedAPY is based on past 14 days performance by the vault",
1260
+ feeBps: {
1261
+ performanceFeeBps: 1000,
1262
+ },
1263
+ curator: UnwrapLabsCurator,
1264
+ settings: createUniversalSettings(params.tokenSymbol, params.maxTVLDecimals),
1265
+ contractDetails: getContractDetails(params.vaultSettings),
1266
+ faqs: getFAQs(),
1267
+ investmentSteps: investmentSteps,
1268
+ tags: params.tags,
1269
+ security: EVERGREEN_SECURITY,
1270
+ redemptionInfo: EVERGREEN_REDEMPTION_INFO,
1271
+ discontinuationInfo: isUSDT ? {
1272
+ info: "This strategy has been retired and is no longer accepting new deposits."
1273
+ } : undefined,
1274
+ usualTimeToEarnings: null,
1275
+ usualTimeToEarningsDescription: null,
1276
+ };
1433
1277
  };
1434
1278
 
1435
1279
  export const UniversalStrategies: IStrategyMetadata<UniversalStrategySettings>[] =
1436
- [
1280
+ [
1437
1281
  createUniversalStrategy({
1438
- tokenSymbol: "USDC.e",
1439
- address: "0x7e6498cf6a1bfc7e6fc89f1831865e2dacb9756def4ec4b031a9138788a3b5e",
1440
- vaultSettings: usdcVaultSettings,
1441
- token1Symbol: "USDC.e",
1442
- token2Symbol: "ETH",
1443
- maxTVLDecimals: 6,
1444
- allowedSources: ["vesu", "extended"],
1445
- tags: [StrategyTag.META_VAULT]
1282
+ tokenSymbol: "USDC.e",
1283
+ address: "0x7e6498cf6a1bfc7e6fc89f1831865e2dacb9756def4ec4b031a9138788a3b5e",
1284
+ vaultSettings: usdcVaultSettings,
1285
+ token1Symbol: "USDC.e",
1286
+ token2Symbol: "ETH",
1287
+ maxTVLDecimals: 6,
1288
+ allowedSources: ["vesu", "extended"],
1289
+ tags: [StrategyTag.META_VAULT]
1446
1290
  }),
1447
1291
  createUniversalStrategy({
1448
- tokenSymbol: "WBTC",
1449
- address: "0x5a4c1651b913aa2ea7afd9024911603152a19058624c3e425405370d62bf80c",
1450
- vaultSettings: wbtcVaultSettings,
1451
- token1Symbol: "WBTC",
1452
- token2Symbol: "ETH",
1453
- maxTVLDecimals: 8,
1454
- allowedSources: ["vesu", "endur", "extended"],
1455
- tags: [StrategyTag.BTC, StrategyTag.META_VAULT]
1292
+ tokenSymbol: "WBTC",
1293
+ address: "0x5a4c1651b913aa2ea7afd9024911603152a19058624c3e425405370d62bf80c",
1294
+ vaultSettings: wbtcVaultSettings,
1295
+ token1Symbol: "WBTC",
1296
+ token2Symbol: "ETH",
1297
+ maxTVLDecimals: 8,
1298
+ allowedSources: ["vesu", "endur", "extended"],
1299
+ tags: [StrategyTag.BTC, StrategyTag.META_VAULT]
1456
1300
  }),
1457
1301
  createUniversalStrategy({
1458
- tokenSymbol: "ETH",
1459
- address: "0x446c22d4d3f5cb52b4950ba832ba1df99464c6673a37c092b1d9622650dbd8",
1460
- vaultSettings: ethVaultSettings,
1461
- token1Symbol: "ETH",
1462
- token2Symbol: "WBTC",
1463
- maxTVLDecimals: 18,
1464
- allowedSources: ["vesu", "extended"],
1465
- tags: [StrategyTag.META_VAULT]
1302
+ tokenSymbol: "ETH",
1303
+ address: "0x446c22d4d3f5cb52b4950ba832ba1df99464c6673a37c092b1d9622650dbd8",
1304
+ vaultSettings: ethVaultSettings,
1305
+ token1Symbol: "ETH",
1306
+ token2Symbol: "WBTC",
1307
+ maxTVLDecimals: 18,
1308
+ allowedSources: ["vesu", "extended"],
1309
+ tags: [StrategyTag.META_VAULT]
1466
1310
  }),
1467
1311
  createUniversalStrategy({
1468
- tokenSymbol: "STRK",
1469
- address: "0x55d012f57e58c96e0a5c7ebbe55853989d01e6538b15a95e7178aca4af05c21",
1470
- vaultSettings: strkVaultSettings,
1471
- token1Symbol: "STRK",
1472
- token2Symbol: "ETH",
1473
- maxTVLDecimals: 18,
1474
- allowedSources: ["vesu", "endur", "extended"],
1475
- tags: [StrategyTag.META_VAULT]
1312
+ tokenSymbol: "STRK",
1313
+ address: "0x55d012f57e58c96e0a5c7ebbe55853989d01e6538b15a95e7178aca4af05c21",
1314
+ vaultSettings: strkVaultSettings,
1315
+ token1Symbol: "STRK",
1316
+ token2Symbol: "ETH",
1317
+ maxTVLDecimals: 18,
1318
+ allowedSources: ["vesu", "endur", "extended"],
1319
+ tags: [StrategyTag.META_VAULT]
1476
1320
  }),
1477
1321
  createUniversalStrategy({
1478
- tokenSymbol: "USDT",
1479
- address: "0x1c4933d1880c6778585e597154eaca7b428579d72f3aae425ad2e4d26c6bb3",
1480
- vaultSettings: usdtVaultSettings,
1481
- token1Symbol: "USDT",
1482
- token2Symbol: "ETH",
1483
- maxTVLDecimals: 6,
1484
- allowedSources: ["vesu"],
1485
- tags: [StrategyTag.META_VAULT]
1322
+ tokenSymbol: "USDT",
1323
+ address: "0x1c4933d1880c6778585e597154eaca7b428579d72f3aae425ad2e4d26c6bb3",
1324
+ vaultSettings: usdtVaultSettings,
1325
+ token1Symbol: "USDT",
1326
+ token2Symbol: "ETH",
1327
+ maxTVLDecimals: 6,
1328
+ allowedSources: ["vesu"],
1329
+ tags: [StrategyTag.META_VAULT]
1486
1330
  })
1487
- ];
1331
+ ];