@strkfarm/sdk 1.1.21 → 1.1.23

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.
@@ -9691,15 +9691,15 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
9691
9691
  }
9692
9692
  async getPoolInfo(p, pools, vesuPositions, totalAssets, isErrorPositionsAPI, isErrorPoolsAPI) {
9693
9693
  const vesuPosition = vesuPositions.find(
9694
- (d) => d.pool.id.toString() === num4.getDecimalString(p.pool_id.address.toString())
9694
+ (d) => ContractAddr.from(d.id).eq(p.pool_id)
9695
9695
  );
9696
9696
  const _pool = pools.find((d) => {
9697
9697
  logger.verbose(
9698
- `pool check: ${d.id == num4.getDecimalString(p.pool_id.address.toString())}, id: ${d.id}, pool_id: ${num4.getDecimalString(
9698
+ `pool check: ${ContractAddr.from(d.id).eq(p.pool_id)}, id: ${d.id}, pool_id: ${num4.getDecimalString(
9699
9699
  p.pool_id.address.toString()
9700
9700
  )}`
9701
9701
  );
9702
- return d.id == num4.getDecimalString(p.pool_id.address.toString());
9702
+ return ContractAddr.from(d.id).eq(p.pool_id);
9703
9703
  });
9704
9704
  logger.verbose(`pool: ${JSON.stringify(_pool)}`);
9705
9705
  logger.verbose(typeof _pool);
@@ -15289,6 +15289,17 @@ var erc4626_abi_default = [
15289
15289
  }
15290
15290
  ];
15291
15291
 
15292
+ // src/strategies/ekubo-cl-vault.tsx
15293
+ import { gql } from "@apollo/client";
15294
+
15295
+ // src/modules/apollo-client.ts
15296
+ import { ApolloClient, InMemoryCache } from "@apollo/client";
15297
+ var apolloClient = new ApolloClient({
15298
+ uri: "https://api.troves.fi/",
15299
+ cache: new InMemoryCache()
15300
+ });
15301
+ var apollo_client_default = apolloClient;
15302
+
15292
15303
  // src/strategies/ekubo-cl-vault.tsx
15293
15304
  import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
15294
15305
  var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
@@ -15446,11 +15457,75 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
15446
15457
  handleFeesCall() {
15447
15458
  return [this.contract.populate("handle_fees", [])];
15448
15459
  }
15449
- /**
15450
- * Calculates assets before and now in a given token of TVL per share to observe growth
15451
- * @returns {Promise<number>} The weighted average APY across all pools
15452
- */
15453
- async netAPY(blockIdentifier = "latest", sinceBlocks = 6e5) {
15460
+ async getFeeHistory(timePeriod = "24h") {
15461
+ const { data } = await apollo_client_default.query({
15462
+ query: gql`
15463
+ query ContractFeeEarnings(
15464
+ $timeframe: String!
15465
+ $contract: String!
15466
+ ) {
15467
+ contractFeeEarnings(timeframe: $timeframe, contract: $contract) {
15468
+ contract
15469
+ dailyEarnings {
15470
+ date
15471
+ tokenAddress
15472
+ amount
15473
+ }
15474
+ totalCollections
15475
+ }
15476
+ }
15477
+ `,
15478
+ variables: {
15479
+ timeframe: timePeriod,
15480
+ contract: this.address.address
15481
+ },
15482
+ fetchPolicy: "no-cache"
15483
+ });
15484
+ const poolKey = await this.getPoolKey();
15485
+ const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
15486
+ const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
15487
+ const price0 = await this.pricer.getPrice(token0Info.symbol);
15488
+ const price1 = await this.pricer.getPrice(token1Info.symbol);
15489
+ let totalToken0Amount = Web3Number.fromWei(0, token0Info.decimals);
15490
+ let totalToken1Amount = Web3Number.fromWei(0, token1Info.decimals);
15491
+ let totalToken0Usd = 0;
15492
+ let totalToken1Usd = 0;
15493
+ const parsedFeeInfo = [];
15494
+ const feeInfo = data.contractFeeEarnings.dailyEarnings;
15495
+ for (const d of feeInfo) {
15496
+ const tokenInfo = await Global.getTokenInfoFromAddr(ContractAddr.from(d.tokenAddress));
15497
+ const amount = Web3Number.fromWei(d.amount, tokenInfo.decimals);
15498
+ if (tokenInfo.address.eq(poolKey.token0)) {
15499
+ totalToken0Amount = totalToken0Amount.plus(amount);
15500
+ totalToken0Usd = totalToken0Usd + amount.multipliedBy(price0.price).toNumber();
15501
+ } else {
15502
+ totalToken1Amount = totalToken1Amount.plus(amount);
15503
+ totalToken1Usd = totalToken1Usd + amount.multipliedBy(price1.price).toNumber();
15504
+ }
15505
+ parsedFeeInfo.push({
15506
+ date: d.date,
15507
+ tokenInfo,
15508
+ amount: Web3Number.fromWei(d.amount, tokenInfo.decimals)
15509
+ });
15510
+ }
15511
+ return {
15512
+ summary: {
15513
+ usdValue: totalToken0Usd + totalToken1Usd,
15514
+ token0: {
15515
+ tokenInfo: token0Info,
15516
+ amount: totalToken0Amount,
15517
+ usdValue: totalToken0Usd
15518
+ },
15519
+ token1: {
15520
+ tokenInfo: token1Info,
15521
+ amount: totalToken1Amount,
15522
+ usdValue: totalToken1Usd
15523
+ }
15524
+ },
15525
+ history: parsedFeeInfo
15526
+ };
15527
+ }
15528
+ async netSharesBasedTrueAPY(blockIdentifier = "latest", sinceBlocks = 6e5) {
15454
15529
  const tvlNow = await this._getTVL(blockIdentifier);
15455
15530
  const supplyNow = await this.totalSupply(blockIdentifier);
15456
15531
  const priceNow = await this.getCurrentPrice(blockIdentifier);
@@ -15488,6 +15563,23 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
15488
15563
  ) / 1e4;
15489
15564
  return apyForGivenBlocks * (365 * 24 * 3600) / timeDiffSeconds;
15490
15565
  }
15566
+ async feeBasedAPY(blockIdentifier = "latest", sinceBlocks = 6e5) {
15567
+ const feeInfo = await this.getFeeHistory("24h");
15568
+ const tvlNow = await this.getTVL("latest");
15569
+ return feeInfo.summary.usdValue * 365 / tvlNow.usdValue;
15570
+ }
15571
+ /**
15572
+ * Calculates assets before and now in a given token of TVL per share to observe growth
15573
+ * @returns {Promise<number>} The weighted average APY across all pools
15574
+ */
15575
+ async netAPY(blockIdentifier = "latest", sinceBlocks = 6e5) {
15576
+ const isUSDCQouteToken = this.metadata.additionalInfo.quoteAsset.symbol === "USDC";
15577
+ if (!isUSDCQouteToken) {
15578
+ return this.netSharesBasedTrueAPY(blockIdentifier, sinceBlocks);
15579
+ } else {
15580
+ return this.feeBasedAPY(blockIdentifier, sinceBlocks);
15581
+ }
15582
+ }
15491
15583
  async getHarvestRewardShares(fromBlock, toBlock) {
15492
15584
  const len = Number(await this.contract.call("get_total_rewards"));
15493
15585
  let shares = Web3Number.fromWei(0, 18);
@@ -16701,7 +16793,7 @@ var ETHUSDCRe7Strategy = {
16701
16793
  Global.getDefaultTokens().find((t) => t.symbol === "ETH"),
16702
16794
  Global.getDefaultTokens().find((t) => t.symbol === "USDC")
16703
16795
  ],
16704
- apyMethodology: "APY based on 7-day historical performance, including fees and rewards.",
16796
+ apyMethodology: "Annualized fee APY, calculated as fees earned in the last 24h divided by TVL",
16705
16797
  additionalInfo: {
16706
16798
  newBounds: "Managed by Re7",
16707
16799
  truePrice: 1,
@@ -16722,6 +16814,10 @@ var ETHUSDCRe7Strategy = {
16722
16814
  /* @__PURE__ */ jsx3("a", { href: "https://www.re7labs.xyz", style: { textDecoration: "underline", marginLeft: "2px" }, target: "_blank", children: "here" }),
16723
16815
  "."
16724
16816
  ] })
16817
+ },
16818
+ {
16819
+ question: "How is the APY calculated?",
16820
+ answer: /* @__PURE__ */ jsx3("div", { children: "It's an annualized fee APY, calculated as fees earned in the last 24h divided by TVL. Factors like impermanent loss are not considered." })
16725
16821
  }
16726
16822
  ],
16727
16823
  risk: highRisk,
@@ -26690,7 +26786,7 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
26690
26786
  if (legAUM[0].token.address.eq(underlying.address)) {
26691
26787
  vesuAum = vesuAum.plus(legAUM[0].amount);
26692
26788
  } else {
26693
- vesuAum = vesuAum.plus(legAUM[1].usdValue / tokenUnderlyingPrice.price);
26789
+ vesuAum = vesuAum.plus(legAUM[0].usdValue / tokenUnderlyingPrice.price);
26694
26790
  }
26695
26791
  if (legAUM[1].token.address.eq(underlying.address)) {
26696
26792
  vesuAum = vesuAum.minus(legAUM[1].amount);
@@ -26723,7 +26819,8 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
26723
26819
  amount: zeroAmt,
26724
26820
  usdValue: 0
26725
26821
  };
26726
- if (vesuAum.isZero()) {
26822
+ const aumToken = vesuAum.plus(balance.amount);
26823
+ if (aumToken.isZero()) {
26727
26824
  return { net, splits: [{
26728
26825
  aum: zeroAmt,
26729
26826
  id: "finalised" /* FINALISED */
@@ -26732,7 +26829,6 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
26732
26829
  id: "defispring" /* DEFISPRING */
26733
26830
  }], prevAum };
26734
26831
  }
26735
- const aumToken = vesuAum.plus(balance.amount);
26736
26832
  logger.verbose(`${this.getTag()} Actual AUM: ${aumToken}`);
26737
26833
  const rewardAssets = await this.getRewardsAUM(prevAum);
26738
26834
  const newAUM = aumToken.plus(rewardAssets);
package/dist/index.d.ts CHANGED
@@ -642,6 +642,11 @@ interface EkuboBounds {
642
642
  lowerTick: bigint;
643
643
  upperTick: bigint;
644
644
  }
645
+ interface FeeHistory {
646
+ date: string;
647
+ tokenInfo: TokenInfo;
648
+ amount: Web3Number;
649
+ }
645
650
  /**
646
651
  * Settings for the CLVaultStrategy
647
652
  *
@@ -696,6 +701,12 @@ declare class EkuboCLVault extends BaseStrategy<DualTokenInfo, DualActionAmount>
696
701
  rebalanceCall(newBounds: EkuboBounds, swapParams: SwapInfo): Call[];
697
702
  handleUnusedCall(swapParams: SwapInfo): Call[];
698
703
  handleFeesCall(): Call[];
704
+ getFeeHistory(timePeriod?: '24h' | '30d' | '3m'): Promise<{
705
+ summary: DualTokenInfo;
706
+ history: FeeHistory[];
707
+ }>;
708
+ netSharesBasedTrueAPY(blockIdentifier?: BlockIdentifier, sinceBlocks?: number): Promise<number>;
709
+ feeBasedAPY(blockIdentifier?: BlockIdentifier, sinceBlocks?: number): Promise<number>;
699
710
  /**
700
711
  * Calculates assets before and now in a given token of TVL per share to observe growth
701
712
  * @returns {Promise<number>} The weighted average APY across all pools
@@ -1382,6 +1393,24 @@ declare class TelegramNotif {
1382
1393
  sendMessage(msg: string): void;
1383
1394
  }
1384
1395
 
1396
+ declare class TelegramGroupNotif {
1397
+ readonly bot: TelegramBot;
1398
+ private groupId;
1399
+ private topicId?;
1400
+ constructor(token: string, groupId: string, topicId?: number);
1401
+ activateChatBot(): void;
1402
+ sendMessage(msg: string): void;
1403
+ sendFormattedMessage(msg: string, parseMode?: 'HTML' | 'Markdown' | 'MarkdownV2'): void;
1404
+ sendPhoto(photo: string | Buffer, caption?: string): void;
1405
+ getGroupInfo(): {
1406
+ groupId: string;
1407
+ topicId: number | undefined;
1408
+ hasTopic: boolean;
1409
+ };
1410
+ updateGroupId(newGroupId: string): void;
1411
+ updateTopicId(newTopicId?: number): void;
1412
+ }
1413
+
1385
1414
  declare class PricerRedis extends Pricer {
1386
1415
  private redisClient;
1387
1416
  constructor(config: IConfig, tokens: TokenInfo[]);
@@ -1506,4 +1535,4 @@ declare class PasswordJsonCryptoUtil {
1506
1535
  decrypt(encryptedData: string, password: string): any;
1507
1536
  }
1508
1537
 
1509
- export { AUMTypes, AVNU_MIDDLEWARE, type AccountInfo, type AdapterLeafType, type AllAccountsStore, type ApproveCallParams, AutoCompounderSTRK, type AvnuSwapCallParams, AvnuWrapper, BaseAdapter, BaseStrategy, type CLVaultStrategySettings, CommonAdapter, type CommonAdapterConfig, ContractAddr, type DecreaseLeverParams, Deployer, type DualActionAmount, type DualTokenInfo, ERC20, type EkuboBounds, EkuboCLVault, EkuboCLVaultStrategies, type EkuboPoolKey, type EkuboQuote, EkuboQuoter, type EkuboRouteNode, type EkuboSplit, type FAQ, FatalError, type FlashloanCallParams, FlowChartColors, type GenerateCallFn, Global, HyperLSTStrategies, type IConfig, type IInvestmentFlow, ILending, type ILendingMetadata, type ILendingPosition, type IProtocol, type IStrategyMetadata, type IncreaseLeverParams, Initializable, type LeafAdapterFn, type LeafData, type LendingToken, type ManageCall, MarginType, Network, PRICE_ROUTER, PasswordJsonCryptoUtil, Pragma, type PriceInfo, Pricer, PricerFromApi, PricerLST, PricerRedis, Protocols, type RequiredFields, type RequiredKeys, type RequiredStoreConfig, type RiskFactor, RiskType, type Route, type RouteNode, SIMPLE_SANITIZER, SIMPLE_SANITIZER_V2, SIMPLE_SANITIZER_VESU_V1_DELEGATIONS, SenseiStrategies, SenseiVault, type SenseiVaultSettings, type SingleActionAmount, type SingleTokenInfo, StandardMerkleTree, type StandardMerkleTreeData, Store, type StoreConfig, type Swap, type SwapInfo, TelegramNotif, type TokenAmount, type TokenInfo, UNIVERSAL_ADAPTERS, UNIVERSAL_MANAGE_IDS, UniversalLstMultiplierStrategy, type UniversalManageCall, UniversalStrategies, UniversalStrategy, type UniversalStrategySettings, VESU_SINGLETON, type VaultPosition, VesuAdapter, type VesuAdapterConfig, type VesuAmount, VesuAmountDenomination, VesuAmountType, type VesuDefiSpringRewardsCallParams, type VesuModifyDelegationCallParams, type VesuModifyPositionCallParams, type VesuMultiplyCallParams, VesuPools, VesuRebalance, type VesuRebalanceSettings, VesuRebalanceStrategies, Web3Number, ZkLend, assert, getAPIUsingHeadlessBrowser, getContractDetails, getDefaultStoreConfig, getMainnetConfig, getNoRiskTags, getRiskColor, getRiskExplaination, getTrovesEndpoint, getVesuSingletonAddress, highlightTextWithLinks, type i257, logger, toBigInt };
1538
+ export { AUMTypes, AVNU_MIDDLEWARE, type AccountInfo, type AdapterLeafType, type AllAccountsStore, type ApproveCallParams, AutoCompounderSTRK, type AvnuSwapCallParams, AvnuWrapper, BaseAdapter, BaseStrategy, type CLVaultStrategySettings, CommonAdapter, type CommonAdapterConfig, ContractAddr, type DecreaseLeverParams, Deployer, type DualActionAmount, type DualTokenInfo, ERC20, type EkuboBounds, EkuboCLVault, EkuboCLVaultStrategies, type EkuboPoolKey, type EkuboQuote, EkuboQuoter, type EkuboRouteNode, type EkuboSplit, type FAQ, FatalError, type FlashloanCallParams, FlowChartColors, type GenerateCallFn, Global, HyperLSTStrategies, type IConfig, type IInvestmentFlow, ILending, type ILendingMetadata, type ILendingPosition, type IProtocol, type IStrategyMetadata, type IncreaseLeverParams, Initializable, type LeafAdapterFn, type LeafData, type LendingToken, type ManageCall, MarginType, Network, PRICE_ROUTER, PasswordJsonCryptoUtil, Pragma, type PriceInfo, Pricer, PricerFromApi, PricerLST, PricerRedis, Protocols, type RequiredFields, type RequiredKeys, type RequiredStoreConfig, type RiskFactor, RiskType, type Route, type RouteNode, SIMPLE_SANITIZER, SIMPLE_SANITIZER_V2, SIMPLE_SANITIZER_VESU_V1_DELEGATIONS, SenseiStrategies, SenseiVault, type SenseiVaultSettings, type SingleActionAmount, type SingleTokenInfo, StandardMerkleTree, type StandardMerkleTreeData, Store, type StoreConfig, type Swap, type SwapInfo, TelegramGroupNotif, TelegramNotif, type TokenAmount, type TokenInfo, UNIVERSAL_ADAPTERS, UNIVERSAL_MANAGE_IDS, UniversalLstMultiplierStrategy, type UniversalManageCall, UniversalStrategies, UniversalStrategy, type UniversalStrategySettings, VESU_SINGLETON, type VaultPosition, VesuAdapter, type VesuAdapterConfig, type VesuAmount, VesuAmountDenomination, VesuAmountType, type VesuDefiSpringRewardsCallParams, type VesuModifyDelegationCallParams, type VesuModifyPositionCallParams, type VesuMultiplyCallParams, VesuPools, VesuRebalance, type VesuRebalanceSettings, VesuRebalanceStrategies, Web3Number, ZkLend, assert, getAPIUsingHeadlessBrowser, getContractDetails, getDefaultStoreConfig, getMainnetConfig, getNoRiskTags, getRiskColor, getRiskExplaination, getTrovesEndpoint, getVesuSingletonAddress, highlightTextWithLinks, type i257, logger, toBigInt };
package/dist/index.js CHANGED
@@ -67,6 +67,7 @@ __export(index_exports, {
67
67
  SenseiVault: () => SenseiVault,
68
68
  StandardMerkleTree: () => StandardMerkleTree,
69
69
  Store: () => Store,
70
+ TelegramGroupNotif: () => TelegramGroupNotif,
70
71
  TelegramNotif: () => TelegramNotif,
71
72
  UNIVERSAL_ADAPTERS: () => UNIVERSAL_ADAPTERS,
72
73
  UNIVERSAL_MANAGE_IDS: () => UNIVERSAL_MANAGE_IDS,
@@ -9790,15 +9791,15 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
9790
9791
  }
9791
9792
  async getPoolInfo(p, pools, vesuPositions, totalAssets, isErrorPositionsAPI, isErrorPoolsAPI) {
9792
9793
  const vesuPosition = vesuPositions.find(
9793
- (d) => d.pool.id.toString() === import_starknet10.num.getDecimalString(p.pool_id.address.toString())
9794
+ (d) => ContractAddr.from(d.id).eq(p.pool_id)
9794
9795
  );
9795
9796
  const _pool = pools.find((d) => {
9796
9797
  logger.verbose(
9797
- `pool check: ${d.id == import_starknet10.num.getDecimalString(p.pool_id.address.toString())}, id: ${d.id}, pool_id: ${import_starknet10.num.getDecimalString(
9798
+ `pool check: ${ContractAddr.from(d.id).eq(p.pool_id)}, id: ${d.id}, pool_id: ${import_starknet10.num.getDecimalString(
9798
9799
  p.pool_id.address.toString()
9799
9800
  )}`
9800
9801
  );
9801
- return d.id == import_starknet10.num.getDecimalString(p.pool_id.address.toString());
9802
+ return ContractAddr.from(d.id).eq(p.pool_id);
9802
9803
  });
9803
9804
  logger.verbose(`pool: ${JSON.stringify(_pool)}`);
9804
9805
  logger.verbose(typeof _pool);
@@ -15384,6 +15385,17 @@ var erc4626_abi_default = [
15384
15385
  }
15385
15386
  ];
15386
15387
 
15388
+ // src/strategies/ekubo-cl-vault.tsx
15389
+ var import_client2 = require("@apollo/client");
15390
+
15391
+ // src/modules/apollo-client.ts
15392
+ var import_client = require("@apollo/client");
15393
+ var apolloClient = new import_client.ApolloClient({
15394
+ uri: "https://api.troves.fi/",
15395
+ cache: new import_client.InMemoryCache()
15396
+ });
15397
+ var apollo_client_default = apolloClient;
15398
+
15387
15399
  // src/strategies/ekubo-cl-vault.tsx
15388
15400
  var import_jsx_runtime3 = require("react/jsx-runtime");
15389
15401
  var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
@@ -15541,11 +15553,75 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
15541
15553
  handleFeesCall() {
15542
15554
  return [this.contract.populate("handle_fees", [])];
15543
15555
  }
15544
- /**
15545
- * Calculates assets before and now in a given token of TVL per share to observe growth
15546
- * @returns {Promise<number>} The weighted average APY across all pools
15547
- */
15548
- async netAPY(blockIdentifier = "latest", sinceBlocks = 6e5) {
15556
+ async getFeeHistory(timePeriod = "24h") {
15557
+ const { data } = await apollo_client_default.query({
15558
+ query: import_client2.gql`
15559
+ query ContractFeeEarnings(
15560
+ $timeframe: String!
15561
+ $contract: String!
15562
+ ) {
15563
+ contractFeeEarnings(timeframe: $timeframe, contract: $contract) {
15564
+ contract
15565
+ dailyEarnings {
15566
+ date
15567
+ tokenAddress
15568
+ amount
15569
+ }
15570
+ totalCollections
15571
+ }
15572
+ }
15573
+ `,
15574
+ variables: {
15575
+ timeframe: timePeriod,
15576
+ contract: this.address.address
15577
+ },
15578
+ fetchPolicy: "no-cache"
15579
+ });
15580
+ const poolKey = await this.getPoolKey();
15581
+ const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
15582
+ const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
15583
+ const price0 = await this.pricer.getPrice(token0Info.symbol);
15584
+ const price1 = await this.pricer.getPrice(token1Info.symbol);
15585
+ let totalToken0Amount = Web3Number.fromWei(0, token0Info.decimals);
15586
+ let totalToken1Amount = Web3Number.fromWei(0, token1Info.decimals);
15587
+ let totalToken0Usd = 0;
15588
+ let totalToken1Usd = 0;
15589
+ const parsedFeeInfo = [];
15590
+ const feeInfo = data.contractFeeEarnings.dailyEarnings;
15591
+ for (const d of feeInfo) {
15592
+ const tokenInfo = await Global.getTokenInfoFromAddr(ContractAddr.from(d.tokenAddress));
15593
+ const amount = Web3Number.fromWei(d.amount, tokenInfo.decimals);
15594
+ if (tokenInfo.address.eq(poolKey.token0)) {
15595
+ totalToken0Amount = totalToken0Amount.plus(amount);
15596
+ totalToken0Usd = totalToken0Usd + amount.multipliedBy(price0.price).toNumber();
15597
+ } else {
15598
+ totalToken1Amount = totalToken1Amount.plus(amount);
15599
+ totalToken1Usd = totalToken1Usd + amount.multipliedBy(price1.price).toNumber();
15600
+ }
15601
+ parsedFeeInfo.push({
15602
+ date: d.date,
15603
+ tokenInfo,
15604
+ amount: Web3Number.fromWei(d.amount, tokenInfo.decimals)
15605
+ });
15606
+ }
15607
+ return {
15608
+ summary: {
15609
+ usdValue: totalToken0Usd + totalToken1Usd,
15610
+ token0: {
15611
+ tokenInfo: token0Info,
15612
+ amount: totalToken0Amount,
15613
+ usdValue: totalToken0Usd
15614
+ },
15615
+ token1: {
15616
+ tokenInfo: token1Info,
15617
+ amount: totalToken1Amount,
15618
+ usdValue: totalToken1Usd
15619
+ }
15620
+ },
15621
+ history: parsedFeeInfo
15622
+ };
15623
+ }
15624
+ async netSharesBasedTrueAPY(blockIdentifier = "latest", sinceBlocks = 6e5) {
15549
15625
  const tvlNow = await this._getTVL(blockIdentifier);
15550
15626
  const supplyNow = await this.totalSupply(blockIdentifier);
15551
15627
  const priceNow = await this.getCurrentPrice(blockIdentifier);
@@ -15583,6 +15659,23 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
15583
15659
  ) / 1e4;
15584
15660
  return apyForGivenBlocks * (365 * 24 * 3600) / timeDiffSeconds;
15585
15661
  }
15662
+ async feeBasedAPY(blockIdentifier = "latest", sinceBlocks = 6e5) {
15663
+ const feeInfo = await this.getFeeHistory("24h");
15664
+ const tvlNow = await this.getTVL("latest");
15665
+ return feeInfo.summary.usdValue * 365 / tvlNow.usdValue;
15666
+ }
15667
+ /**
15668
+ * Calculates assets before and now in a given token of TVL per share to observe growth
15669
+ * @returns {Promise<number>} The weighted average APY across all pools
15670
+ */
15671
+ async netAPY(blockIdentifier = "latest", sinceBlocks = 6e5) {
15672
+ const isUSDCQouteToken = this.metadata.additionalInfo.quoteAsset.symbol === "USDC";
15673
+ if (!isUSDCQouteToken) {
15674
+ return this.netSharesBasedTrueAPY(blockIdentifier, sinceBlocks);
15675
+ } else {
15676
+ return this.feeBasedAPY(blockIdentifier, sinceBlocks);
15677
+ }
15678
+ }
15586
15679
  async getHarvestRewardShares(fromBlock, toBlock) {
15587
15680
  const len = Number(await this.contract.call("get_total_rewards"));
15588
15681
  let shares = Web3Number.fromWei(0, 18);
@@ -16796,7 +16889,7 @@ var ETHUSDCRe7Strategy = {
16796
16889
  Global.getDefaultTokens().find((t) => t.symbol === "ETH"),
16797
16890
  Global.getDefaultTokens().find((t) => t.symbol === "USDC")
16798
16891
  ],
16799
- apyMethodology: "APY based on 7-day historical performance, including fees and rewards.",
16892
+ apyMethodology: "Annualized fee APY, calculated as fees earned in the last 24h divided by TVL",
16800
16893
  additionalInfo: {
16801
16894
  newBounds: "Managed by Re7",
16802
16895
  truePrice: 1,
@@ -16817,6 +16910,10 @@ var ETHUSDCRe7Strategy = {
16817
16910
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("a", { href: "https://www.re7labs.xyz", style: { textDecoration: "underline", marginLeft: "2px" }, target: "_blank", children: "here" }),
16818
16911
  "."
16819
16912
  ] })
16913
+ },
16914
+ {
16915
+ question: "How is the APY calculated?",
16916
+ answer: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: "It's an annualized fee APY, calculated as fees earned in the last 24h divided by TVL. Factors like impermanent loss are not considered." })
16820
16917
  }
16821
16918
  ],
16822
16919
  risk: highRisk,
@@ -26785,7 +26882,7 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
26785
26882
  if (legAUM[0].token.address.eq(underlying.address)) {
26786
26883
  vesuAum = vesuAum.plus(legAUM[0].amount);
26787
26884
  } else {
26788
- vesuAum = vesuAum.plus(legAUM[1].usdValue / tokenUnderlyingPrice.price);
26885
+ vesuAum = vesuAum.plus(legAUM[0].usdValue / tokenUnderlyingPrice.price);
26789
26886
  }
26790
26887
  if (legAUM[1].token.address.eq(underlying.address)) {
26791
26888
  vesuAum = vesuAum.minus(legAUM[1].amount);
@@ -26818,7 +26915,8 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
26818
26915
  amount: zeroAmt,
26819
26916
  usdValue: 0
26820
26917
  };
26821
- if (vesuAum.isZero()) {
26918
+ const aumToken = vesuAum.plus(balance.amount);
26919
+ if (aumToken.isZero()) {
26822
26920
  return { net, splits: [{
26823
26921
  aum: zeroAmt,
26824
26922
  id: "finalised" /* FINALISED */
@@ -26827,7 +26925,6 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
26827
26925
  id: "defispring" /* DEFISPRING */
26828
26926
  }], prevAum };
26829
26927
  }
26830
- const aumToken = vesuAum.plus(balance.amount);
26831
26928
  logger.verbose(`${this.getTag()} Actual AUM: ${aumToken}`);
26832
26929
  const rewardAssets = await this.getRewardsAUM(prevAum);
26833
26930
  const newAUM = aumToken.plus(rewardAssets);
@@ -28028,6 +28125,92 @@ var TelegramNotif = class {
28028
28125
  }
28029
28126
  };
28030
28127
 
28128
+ // src/notifs/telegram-group.ts
28129
+ var import_node_telegram_bot_api2 = __toESM(require("node-telegram-bot-api"));
28130
+ var TelegramGroupNotif = class {
28131
+ constructor(token, groupId, topicId) {
28132
+ this.bot = new import_node_telegram_bot_api2.default(token, { polling: false });
28133
+ this.groupId = groupId;
28134
+ this.topicId = topicId;
28135
+ }
28136
+ // listen to start msgs, register chatId and send registered msg
28137
+ activateChatBot() {
28138
+ this.bot.on("message", (msg) => {
28139
+ console.log(`Tg: Message received: `, msg);
28140
+ const chatId = msg.chat.id;
28141
+ let text = msg.text.toLowerCase().trim();
28142
+ console.log(`Tg: IncomingMsg: ID: ${chatId}, msg: ${text}`, msg);
28143
+ logger.verbose(`Tg: IncomingMsg: ID: ${chatId}, msg: ${text}`);
28144
+ });
28145
+ }
28146
+ // send a message to the group
28147
+ sendMessage(msg) {
28148
+ logger.verbose(`Tg Group: Sending message to group ${this.groupId}: ${msg}`);
28149
+ const messageOptions = {};
28150
+ if (this.topicId !== void 0) {
28151
+ messageOptions.message_thread_id = this.topicId;
28152
+ }
28153
+ this.bot.sendMessage(this.groupId, msg, messageOptions).catch((err) => {
28154
+ logger.error(`Tg Group: Error sending message to group ${this.groupId}`);
28155
+ logger.error(`Tg Group: Error details: ${err.message}`);
28156
+ }).then(() => {
28157
+ logger.verbose(`Tg Group: Message sent to group ${this.groupId}${this.topicId ? ` (topic: ${this.topicId})` : ""}`);
28158
+ });
28159
+ }
28160
+ // send a message with specific formatting options
28161
+ sendFormattedMessage(msg, parseMode) {
28162
+ logger.verbose(`Tg Group: Sending formatted message to group ${this.groupId}: ${msg}`);
28163
+ const messageOptions = {};
28164
+ if (this.topicId !== void 0) {
28165
+ messageOptions.message_thread_id = this.topicId;
28166
+ }
28167
+ if (parseMode) {
28168
+ messageOptions.parse_mode = parseMode;
28169
+ }
28170
+ this.bot.sendMessage(this.groupId, msg, messageOptions).catch((err) => {
28171
+ logger.error(`Tg Group: Error sending formatted message to group ${this.groupId}`);
28172
+ logger.error(`Tg Group: Error details: ${err.message}`);
28173
+ }).then(() => {
28174
+ logger.verbose(`Tg Group: Formatted message sent to group ${this.groupId}${this.topicId ? ` (topic: ${this.topicId})` : ""}`);
28175
+ });
28176
+ }
28177
+ // send a photo to the group
28178
+ sendPhoto(photo, caption) {
28179
+ logger.verbose(`Tg Group: Sending photo to group ${this.groupId}`);
28180
+ const messageOptions = {};
28181
+ if (this.topicId !== void 0) {
28182
+ messageOptions.message_thread_id = this.topicId;
28183
+ }
28184
+ if (caption) {
28185
+ messageOptions.caption = caption;
28186
+ }
28187
+ this.bot.sendPhoto(this.groupId, photo, messageOptions).catch((err) => {
28188
+ logger.error(`Tg Group: Error sending photo to group ${this.groupId}`);
28189
+ logger.error(`Tg Group: Error details: ${err.message}`);
28190
+ }).then(() => {
28191
+ logger.verbose(`Tg Group: Photo sent to group ${this.groupId}${this.topicId ? ` (topic: ${this.topicId})` : ""}`);
28192
+ });
28193
+ }
28194
+ // get group information
28195
+ getGroupInfo() {
28196
+ return {
28197
+ groupId: this.groupId,
28198
+ topicId: this.topicId,
28199
+ hasTopic: this.topicId !== void 0
28200
+ };
28201
+ }
28202
+ // update group ID (useful if group ID changes)
28203
+ updateGroupId(newGroupId) {
28204
+ this.groupId = newGroupId;
28205
+ logger.verbose(`Tg Group: Updated group ID to ${newGroupId}`);
28206
+ }
28207
+ // update topic ID (useful for switching topics)
28208
+ updateTopicId(newTopicId) {
28209
+ this.topicId = newTopicId;
28210
+ logger.verbose(`Tg Group: Updated topic ID to ${newTopicId || "none"}`);
28211
+ }
28212
+ };
28213
+
28031
28214
  // src/node/pricer-redis.ts
28032
28215
  var import_redis = require("redis");
28033
28216
  var PricerRedis = class extends Pricer {
@@ -28446,6 +28629,7 @@ var deployer_default = Deployer;
28446
28629
  SenseiVault,
28447
28630
  StandardMerkleTree,
28448
28631
  Store,
28632
+ TelegramGroupNotif,
28449
28633
  TelegramNotif,
28450
28634
  UNIVERSAL_ADAPTERS,
28451
28635
  UNIVERSAL_MANAGE_IDS,