@strkfarm/sdk 1.0.56 → 1.0.58

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.
package/dist/index.mjs CHANGED
@@ -1986,7 +1986,6 @@ import { toHex } from "@ericnordelo/strk-merkle-tree/dist/bytes";
1986
1986
  import { processMultiProof, processProof } from "@ericnordelo/strk-merkle-tree/dist/core";
1987
1987
  import { standardLeafHash } from "@ericnordelo/strk-merkle-tree/dist/hashes";
1988
1988
  import { MerkleTreeImpl } from "@ericnordelo/strk-merkle-tree/dist/merkletree";
1989
- import { validateArgument } from "@ericnordelo/strk-merkle-tree/src/utils/errors";
1990
1989
  import { num as num2 } from "starknet";
1991
1990
 
1992
1991
  // ../node_modules/@noble/hashes/esm/_assert.js
@@ -4044,13 +4043,6 @@ var StandardMerkleTree = class _StandardMerkleTree extends MerkleTreeImpl {
4044
4043
  });
4045
4044
  return new _StandardMerkleTree(tree, indexedValues, leafEncoding);
4046
4045
  }
4047
- static load(data) {
4048
- validateArgument(data.format === "standard-v1", `Unknown format '${data.format}'`);
4049
- validateArgument(data.leafEncoding !== void 0, "Expected leaf encoding");
4050
- const tree = new _StandardMerkleTree(data.tree, data.values, data.leafEncoding);
4051
- tree.validate();
4052
- return tree;
4053
- }
4054
4046
  static verify(root, leafEncoding, leaf, proof) {
4055
4047
  return toHex(root) === processProof(standardLeafHash(leafEncoding, leaf), proof);
4056
4048
  }
@@ -5808,23 +5800,10 @@ var vesu_rebalance_abi_default = [
5808
5800
  }
5809
5801
  ];
5810
5802
 
5811
- // src/strategies/base-strategy.ts
5812
- var BaseStrategy = class {
5813
- constructor(config) {
5803
+ // src/utils/cacheClass.ts
5804
+ var CacheClass = class {
5805
+ constructor() {
5814
5806
  this.cache = /* @__PURE__ */ new Map();
5815
- this.config = config;
5816
- }
5817
- async getUserTVL(user) {
5818
- throw new Error("Not implemented");
5819
- }
5820
- async getTVL() {
5821
- throw new Error("Not implemented");
5822
- }
5823
- async depositCall(amountInfo, receiver) {
5824
- throw new Error("Not implemented");
5825
- }
5826
- async withdrawCall(amountInfo, receiver, owner) {
5827
- throw new Error("Not implemented");
5828
5807
  }
5829
5808
  setCache(key, data, ttl = 6e4) {
5830
5809
  const timestamp = Date.now();
@@ -5845,6 +5824,27 @@ var BaseStrategy = class {
5845
5824
  }
5846
5825
  };
5847
5826
 
5827
+ // src/strategies/base-strategy.ts
5828
+ var BaseStrategy = class extends CacheClass {
5829
+ constructor(config) {
5830
+ super();
5831
+ this.cache = /* @__PURE__ */ new Map();
5832
+ this.config = config;
5833
+ }
5834
+ async getUserTVL(user) {
5835
+ throw new Error("Not implemented");
5836
+ }
5837
+ async getTVL() {
5838
+ throw new Error("Not implemented");
5839
+ }
5840
+ async depositCall(amountInfo, receiver) {
5841
+ throw new Error("Not implemented");
5842
+ }
5843
+ async withdrawCall(amountInfo, receiver, owner) {
5844
+ throw new Error("Not implemented");
5845
+ }
5846
+ };
5847
+
5848
5848
  // src/node/headless.browser.ts
5849
5849
  import axios5 from "axios";
5850
5850
  async function getAPIUsingHeadlessBrowser(url) {
@@ -20318,9 +20318,8 @@ var SenseiVault = class extends BaseStrategy {
20318
20318
  }
20319
20319
  async getPositionInfo() {
20320
20320
  const CACHE_KEY = "positionInfo";
20321
- if (this.isCacheValid(CACHE_KEY)) {
20322
- return this.getCache(CACHE_KEY);
20323
- }
20321
+ const existingCacheData = this.getCache(CACHE_KEY);
20322
+ if (existingCacheData) return existingCacheData;
20324
20323
  const resp = await fetch(
20325
20324
  `${getTrovesEndpoint()}/vesu/positions?walletAddress=${this.address.address}`
20326
20325
  );
@@ -20364,9 +20363,8 @@ var SenseiVault = class extends BaseStrategy {
20364
20363
  }
20365
20364
  async getSecondaryTokenPriceRelativeToMain(retry = 0) {
20366
20365
  const CACHE_KEY = "xSTRKPrice";
20367
- if (this.isCacheValid(CACHE_KEY)) {
20368
- return this.getCache(CACHE_KEY);
20369
- }
20366
+ const existingCacheData = this.getCache(CACHE_KEY);
20367
+ if (existingCacheData) return existingCacheData;
20370
20368
  const params = {
20371
20369
  sellTokenAddress: this.metadata.additionalInfo.secondaryToken.address.address,
20372
20370
  buyTokenAddress: this.metadata.additionalInfo.mainToken.address.address,
@@ -20520,7 +20518,7 @@ function toBigInt(value) {
20520
20518
  }
20521
20519
 
20522
20520
  // src/strategies/universal-adapters/baseAdapter.ts
20523
- var BaseAdapter = class {
20521
+ var BaseAdapter = class extends CacheClass {
20524
20522
  constructSimpleLeafData(params) {
20525
20523
  const { id, target, method, packedArguments } = params;
20526
20524
  return {
@@ -22895,7 +22893,6 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
22895
22893
  constructor(config) {
22896
22894
  super();
22897
22895
  this.VESU_SINGLETON = ContractAddr.from("0x000d8d6dfec4d33bfb6895de9f3852143a17c6f92fd2a21da3d6924d34870160");
22898
- this.cache = {};
22899
22896
  this.getModifyPosition = () => {
22900
22897
  const positionData = [0n];
22901
22898
  const packedArguments = [
@@ -22924,17 +22921,19 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
22924
22921
  denomination: this.formatAmountDenominationEnum(params.collateralAmount.denomination),
22925
22922
  value: {
22926
22923
  abs: uint2567.bnToUint256(params.collateralAmount.value.abs.toWei()),
22927
- is_negative: params.collateralAmount.value.is_negative
22924
+ is_negative: params.collateralAmount.value.abs.isZero() ? false : params.collateralAmount.value.is_negative
22928
22925
  }
22929
22926
  };
22927
+ logger.verbose(`VesuAdapter::ConstructingModify::Collateral::${JSON.stringify(_collateral)}`);
22930
22928
  const _debt = {
22931
22929
  amount_type: this.formatAmountTypeEnum(params.debtAmount.amount_type),
22932
22930
  denomination: this.formatAmountDenominationEnum(params.debtAmount.denomination),
22933
22931
  value: {
22934
22932
  abs: uint2567.bnToUint256(params.debtAmount.value.abs.toWei()),
22935
- is_negative: params.debtAmount.value.is_negative
22933
+ is_negative: params.debtAmount.value.abs.isZero() ? false : params.debtAmount.value.is_negative
22936
22934
  }
22937
22935
  };
22936
+ logger.verbose(`VesuAdapter::ConstructingModify::Debt::${JSON.stringify(_debt)}`);
22938
22937
  const singletonContract = new Contract8(vesu_singleton_abi_default, this.VESU_SINGLETON.toString(), new RpcProvider4({ nodeUrl: "" }));
22939
22938
  const call = singletonContract.populate("modify_position", {
22940
22939
  params: {
@@ -23003,20 +23002,22 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
23003
23002
  }
23004
23003
  async getLTVConfig(config) {
23005
23004
  const CACHE_KEY = "ltv_config";
23006
- if (this.cache[CACHE_KEY]) {
23007
- return this.cache[CACHE_KEY];
23005
+ const cacheData = this.getCache(CACHE_KEY);
23006
+ if (cacheData) {
23007
+ return cacheData;
23008
23008
  }
23009
23009
  const output2 = await this.getVesuSingletonContract(config).call("ltv_config", [this.config.poolId.address, this.config.collateral.address.address, this.config.debt.address.address]);
23010
- this.cache[CACHE_KEY] = Number(output2.max_ltv) / 1e18;
23011
- return this.cache[CACHE_KEY];
23010
+ this.setCache(CACHE_KEY, Number(output2.max_ltv) / 1e18, 3e5);
23011
+ return this.getCache(CACHE_KEY);
23012
23012
  }
23013
23013
  async getPositions(config) {
23014
23014
  if (!this.pricer) {
23015
23015
  throw new Error("Pricer is not initialized");
23016
23016
  }
23017
23017
  const CACHE_KEY = "positions";
23018
- if (this.cache[CACHE_KEY]) {
23019
- return this.cache[CACHE_KEY];
23018
+ const cacheData = this.getCache(CACHE_KEY);
23019
+ if (cacheData) {
23020
+ return cacheData;
23020
23021
  }
23021
23022
  const output2 = await this.getVesuSingletonContract(config).call("position_unsafe", [
23022
23023
  this.config.poolId.address,
@@ -23039,9 +23040,65 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
23039
23040
  usdValue: debtAmount.multipliedBy(token2Price.price).toNumber(),
23040
23041
  remarks: "Debt"
23041
23042
  }];
23042
- this.cache[CACHE_KEY] = value;
23043
+ this.setCache(CACHE_KEY, value, 6e4);
23044
+ return value;
23045
+ }
23046
+ async getCollateralization(config) {
23047
+ if (!this.pricer) {
23048
+ throw new Error("Pricer is not initialized");
23049
+ }
23050
+ const CACHE_KEY = "collateralization";
23051
+ const cacheData = this.getCache(CACHE_KEY);
23052
+ if (cacheData) {
23053
+ return cacheData;
23054
+ }
23055
+ const output2 = await this.getVesuSingletonContract(config).call("check_collateralization_unsafe", [
23056
+ this.config.poolId.address,
23057
+ this.config.collateral.address.address,
23058
+ this.config.debt.address.address,
23059
+ this.config.vaultAllocator.address
23060
+ ]);
23061
+ const collateralAmount = Web3Number.fromWei(output2["1"].toString(), 18);
23062
+ const debtAmount = Web3Number.fromWei(output2["2"].toString(), 18);
23063
+ const value = [{
23064
+ token: this.config.collateral,
23065
+ usdValue: collateralAmount.toNumber(),
23066
+ remarks: "Collateral"
23067
+ }, {
23068
+ token: this.config.debt,
23069
+ usdValue: debtAmount.toNumber(),
23070
+ remarks: "Debt"
23071
+ }];
23072
+ this.setCache(CACHE_KEY, value, 6e4);
23043
23073
  return value;
23044
23074
  }
23075
+ async getAssetPrices() {
23076
+ const collateralizationProm = this.getCollateralization(this.networkConfig);
23077
+ const positionsProm = this.getPositions(this.networkConfig);
23078
+ const ltvProm = this.getLTVConfig(this.networkConfig);
23079
+ const output2 = await Promise.all([collateralizationProm, positionsProm, ltvProm]);
23080
+ const [collateralization, positions, ltv] = output2;
23081
+ const collateralTokenAmount = positions[0].amount;
23082
+ const collateralUSDAmount = collateralization[0].usdValue;
23083
+ const collateralPrice = collateralUSDAmount / collateralTokenAmount.toNumber();
23084
+ const debtTokenAmount = positions[1].amount;
23085
+ const debtUSDAmount = collateralization[1].usdValue;
23086
+ const debtPrice = debtUSDAmount / debtTokenAmount.toNumber();
23087
+ return {
23088
+ collateralTokenAmount,
23089
+ collateralUSDAmount,
23090
+ collateralPrice,
23091
+ debtTokenAmount,
23092
+ debtUSDAmount,
23093
+ debtPrice,
23094
+ ltv
23095
+ };
23096
+ }
23097
+ async getHealthFactor() {
23098
+ const ltv = await this.getLTVConfig(this.networkConfig);
23099
+ const collateralisation = await this.getCollateralization(this.networkConfig);
23100
+ return collateralisation[0].usdValue * ltv / collateralisation[1].usdValue;
23101
+ }
23045
23102
  static async getVesuPools(retry = 0) {
23046
23103
  const CACHE_KEY = "VESU_POOLS";
23047
23104
  const cacheValue = Global.getGlobalCache(CACHE_KEY);
@@ -25413,19 +25470,32 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
25413
25470
  const debtAsset1 = pool1.assets.find((a) => a.symbol === vesuAdapter1.config.debt.symbol)?.stats;
25414
25471
  const collateralAsset2 = pool2.assets.find((a) => a.symbol === vesuAdapter2.config.collateral.symbol)?.stats;
25415
25472
  const debtAsset2 = pool2.assets.find((a) => a.symbol === vesuAdapter2.config.debt.symbol)?.stats;
25416
- const collateral1APY = Number(collateralAsset1.supplyApy.value) / 1e18 + Number(collateralAsset1.defiSpringSupplyApr.value) / 1e18;
25473
+ const collateral1APY = Number(collateralAsset1.supplyApy.value) / 1e18;
25417
25474
  const debt1APY = Number(debtAsset1.borrowApr.value) / 1e18;
25418
- const collateral2APY = Number(collateralAsset2.supplyApy.value) / 1e18 + Number(collateralAsset2.defiSpringSupplyApr.value) / 1e18;
25475
+ const collateral2APY = Number(collateralAsset2.supplyApy.value) / 1e18;
25419
25476
  const debt2APY = Number(debtAsset2.borrowApr.value) / 1e18;
25420
- const apys = [collateral1APY, debt1APY, collateral2APY, debt2APY];
25421
25477
  const positions = await this.getVaultPositions();
25422
- assert(positions.length == apys.length, "Positions and APYs length mismatch");
25423
- const weightedAPYs = positions.map((pos, i) => {
25424
- return pos.usdValue * apys[i] * (i % 2 == 0 ? 1 : -1);
25425
- });
25426
- const netPosition = positions.reduce((acc, val, index) => acc + val.usdValue * (index % 2 == 0 ? 1 : -1), 0);
25427
- const apy = weightedAPYs.reduce((acc, val) => acc + val, 0) / netPosition;
25428
- return apy;
25478
+ const weights = positions.map((p, index) => p.usdValue * (index % 2 == 0 ? 1 : -1));
25479
+ const baseAPYs = [collateral1APY, debt1APY, collateral2APY, debt2APY];
25480
+ assert(positions.length == baseAPYs.length, "Positions and APYs length mismatch");
25481
+ const rewardAPYs = [Number(collateralAsset1.defiSpringSupplyApr.value) / 1e18, 0, Number(collateralAsset2.defiSpringSupplyApr.value) / 1e18, 0];
25482
+ const baseAPY = this.computeAPY(baseAPYs, weights);
25483
+ const rewardAPY = this.computeAPY(rewardAPYs, weights);
25484
+ const apys = [...baseAPYs, ...rewardAPYs];
25485
+ const netAPY = baseAPY + rewardAPY;
25486
+ return { net: netAPY, splits: [{
25487
+ apy: baseAPY,
25488
+ id: "base"
25489
+ }, {
25490
+ apy: rewardAPY,
25491
+ id: "defispring"
25492
+ }] };
25493
+ }
25494
+ computeAPY(apys, weights) {
25495
+ assert(apys.length === weights.length, "APYs and weights length mismatch");
25496
+ const weightedSum = apys.reduce((acc, apy, i) => acc + apy * weights[i], 0);
25497
+ const totalWeight = weights.reduce((acc, weight) => acc + weight, 0);
25498
+ return weightedSum / totalWeight;
25429
25499
  }
25430
25500
  /**
25431
25501
  * Calculates the total TVL of the strategy.
@@ -25448,22 +25518,50 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
25448
25518
  };
25449
25519
  }
25450
25520
  async getAUM() {
25521
+ const currentAUM = await this.contract.call("aum", []);
25522
+ const lastReportTime = await this.contract.call("last_report_timestamp", []);
25523
+ const token1Price = await this.pricer.getPrice(this.metadata.depositTokens[0].symbol);
25451
25524
  const [vesuAdapter1, vesuAdapter2] = this.getVesuAdapters();
25452
25525
  const leg1AUM = await vesuAdapter1.getPositions(this.config);
25453
25526
  const leg2AUM = await vesuAdapter2.getPositions(this.config);
25454
- const token1Price = await this.pricer.getPrice(vesuAdapter1.config.collateral.symbol);
25455
- const aumToken = leg1AUM[0].amount.plus(leg2AUM[0].usdValue / token1Price.price).minus(leg1AUM[1].usdValue / token1Price.price).minus(leg2AUM[1].amount);
25456
- return {
25527
+ const balance = await new ERC20(this.config).balanceOf(this.asset().address, this.metadata.additionalInfo.vaultAllocator, this.asset().decimals);
25528
+ logger.verbose(`${this.getTag()} unused balance: ${balance}`);
25529
+ const aumToken = leg1AUM[0].amount.plus(leg2AUM[0].usdValue / token1Price.price).minus(leg1AUM[1].usdValue / token1Price.price).minus(leg2AUM[1].amount).plus(balance);
25530
+ logger.verbose(`${this.getTag()} Actual AUM: ${aumToken}`);
25531
+ const netAPY = await this.netAPY();
25532
+ const defispringAPY = netAPY.splits.find((s) => s.id === "defispring")?.apy || 0;
25533
+ if (!defispringAPY) throw new Error("DefiSpring APY not found");
25534
+ const timeDiff = Math.round(Date.now() / 1e3) - Number(lastReportTime);
25535
+ const growthRate = timeDiff * defispringAPY / (365 * 24 * 60 * 60);
25536
+ const prevAum = Web3Number.fromWei(currentAUM.toString(), this.asset().decimals);
25537
+ const rewardAssets = prevAum.multipliedBy(growthRate);
25538
+ logger.verbose(`${this.getTag()} DefiSpring AUM time difference: ${timeDiff}`);
25539
+ logger.verbose(`${this.getTag()} Current AUM: ${currentAUM}`);
25540
+ logger.verbose(`${this.getTag()} Net APY: ${JSON.stringify(netAPY)}`);
25541
+ logger.verbose(`${this.getTag()} rewards AUM: ${rewardAssets}`);
25542
+ const newAUM = aumToken.plus(rewardAssets);
25543
+ logger.verbose(`${this.getTag()} New AUM: ${newAUM}`);
25544
+ const net = {
25457
25545
  tokenInfo: this.asset(),
25458
- amount: aumToken,
25459
- usdValue: aumToken.multipliedBy(token1Price.price).toNumber()
25546
+ amount: newAUM,
25547
+ usdValue: newAUM.multipliedBy(token1Price.price).toNumber()
25460
25548
  };
25549
+ const splits = [{
25550
+ id: "finalised",
25551
+ aum: aumToken
25552
+ }, {
25553
+ id: "defispring",
25554
+ aum: rewardAssets
25555
+ }];
25556
+ return { net, splits, prevAum };
25461
25557
  }
25462
25558
  getVesuAdapters() {
25463
25559
  const vesuAdapter1 = this.getAdapter("vesu_leg1_adapter" /* VESU_LEG1 */);
25464
25560
  const vesuAdapter2 = this.getAdapter("vesu_leg2_adapter" /* VESU_LEG2 */);
25465
25561
  vesuAdapter1.pricer = this.pricer;
25466
25562
  vesuAdapter2.pricer = this.pricer;
25563
+ vesuAdapter1.networkConfig = this.config;
25564
+ vesuAdapter2.networkConfig = this.config;
25467
25565
  return [vesuAdapter1, vesuAdapter2];
25468
25566
  }
25469
25567
  async getVaultPositions() {
@@ -25505,12 +25603,14 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
25505
25603
  }));
25506
25604
  const output2 = [{
25507
25605
  proofs: manage5Info.proofs,
25508
- manageCall: manageCall5
25606
+ manageCall: manageCall5,
25607
+ step: STEP2_ID
25509
25608
  }];
25510
25609
  if (approveAmount.gt(0)) {
25511
25610
  output2.unshift({
25512
25611
  proofs: manage4Info.proofs,
25513
- manageCall: manageCall4
25612
+ manageCall: manageCall4,
25613
+ step: STEP1_ID
25514
25614
  });
25515
25615
  }
25516
25616
  return output2;
@@ -25518,9 +25618,96 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
25518
25618
  getTag() {
25519
25619
  return `${_UniversalStrategy.name}:${this.metadata.name}`;
25520
25620
  }
25621
+ async getVesuHealthFactors() {
25622
+ return await Promise.all(this.getVesuAdapters().map((v) => v.getHealthFactor()));
25623
+ }
25624
+ async computeRebalanceConditionAndReturnCalls() {
25625
+ const vesuAdapters = this.getVesuAdapters();
25626
+ const healthFactors = await this.getVesuHealthFactors();
25627
+ const leg1HealthFactor = healthFactors[0];
25628
+ const leg2HealthFactor = healthFactors[1];
25629
+ logger.verbose(`${this.getTag()}: HealthFactorLeg1: ${leg1HealthFactor}`);
25630
+ logger.verbose(`${this.getTag()}: HealthFactorLeg2: ${leg2HealthFactor}`);
25631
+ const minHf = this.metadata.additionalInfo.minHealthFactor;
25632
+ const isRebalanceNeeded1 = leg1HealthFactor < minHf;
25633
+ const isRebalanceNeeded2 = leg2HealthFactor < minHf;
25634
+ if (!isRebalanceNeeded1 && !isRebalanceNeeded2) {
25635
+ return [];
25636
+ }
25637
+ if (isRebalanceNeeded1) {
25638
+ const amount = await this.getLegRebalanceAmount(vesuAdapters[0], leg1HealthFactor, false);
25639
+ const leg2HF = await this.getNewHealthFactor(vesuAdapters[1], amount, true);
25640
+ assert(leg2HF > minHf, `Rebalance Leg1 failed: Leg2 HF after rebalance would be too low: ${leg2HF}`);
25641
+ return [await this.getRebalanceCall({
25642
+ isLeg1toLeg2: false,
25643
+ amount
25644
+ })];
25645
+ } else {
25646
+ const amount = await this.getLegRebalanceAmount(vesuAdapters[1], leg2HealthFactor, true);
25647
+ const leg1HF = await this.getNewHealthFactor(vesuAdapters[0], amount, false);
25648
+ assert(leg1HF > minHf, `Rebalance Leg2 failed: Leg1 HF after rebalance would be too low: ${leg1HF}`);
25649
+ return [await this.getRebalanceCall({
25650
+ isLeg1toLeg2: true,
25651
+ amount
25652
+ })];
25653
+ }
25654
+ }
25655
+ async getNewHealthFactor(vesuAdapter, newAmount, isWithdraw) {
25656
+ const {
25657
+ collateralTokenAmount,
25658
+ collateralUSDAmount,
25659
+ collateralPrice,
25660
+ debtTokenAmount,
25661
+ debtUSDAmount,
25662
+ debtPrice,
25663
+ ltv
25664
+ } = await vesuAdapter.getAssetPrices();
25665
+ if (isWithdraw) {
25666
+ const newHF = (collateralTokenAmount.toNumber() - newAmount.toNumber()) * collateralPrice * ltv / debtUSDAmount;
25667
+ logger.verbose(`getNewHealthFactor:: HF: ${newHF}, amoutn: ${newAmount.toNumber()}, isDeposit`);
25668
+ return newHF;
25669
+ } else {
25670
+ const newHF = collateralUSDAmount * ltv / ((debtTokenAmount.toNumber() + newAmount.toNumber()) * debtPrice);
25671
+ logger.verbose(`getNewHealthFactor:: HF: ${newHF}, amoutn: ${newAmount.toNumber()}, isRepay`);
25672
+ return newHF;
25673
+ }
25674
+ }
25675
+ /**
25676
+ *
25677
+ * @param vesuAdapter
25678
+ * @param currentHf
25679
+ * @param isDeposit if true, attempt by adding collateral, else by repaying
25680
+ * @returns
25681
+ */
25682
+ async getLegRebalanceAmount(vesuAdapter, currentHf, isDeposit) {
25683
+ const {
25684
+ collateralTokenAmount,
25685
+ collateralUSDAmount,
25686
+ collateralPrice,
25687
+ debtTokenAmount,
25688
+ debtUSDAmount,
25689
+ debtPrice,
25690
+ ltv
25691
+ } = await vesuAdapter.getAssetPrices();
25692
+ if (debtTokenAmount.isZero()) {
25693
+ return Web3Number.fromWei(0, 0);
25694
+ }
25695
+ assert(collateralPrice > 0 && debtPrice > 0, "getRebalanceAmount: Invalid price");
25696
+ const targetHF = this.metadata.additionalInfo.targetHealthFactor;
25697
+ if (currentHf > targetHF - 0.01)
25698
+ throw new Error("getLegRebalanceAmount: Current health factor is healthy");
25699
+ if (isDeposit) {
25700
+ const newAmount = targetHF * debtUSDAmount / (collateralPrice * ltv) - collateralTokenAmount.toNumber();
25701
+ logger.verbose(`${this.getTag()}:: getLegRebalanceAmount: addCollateral, currentHf: ${currentHf}, targetHF: ${targetHF}, collAmount: ${collateralTokenAmount.toString()}, collUSD: ${collateralUSDAmount}, collPrice: ${collateralPrice}, debtAmount: ${debtTokenAmount.toString()}, debtUSD: ${debtUSDAmount}, debtPrice: ${debtPrice}, ltv: ${ltv}, newAmount: ${newAmount}`);
25702
+ return new Web3Number(newAmount.toFixed(8), collateralTokenAmount.decimals);
25703
+ } else {
25704
+ const newAmount = debtTokenAmount.toNumber() - collateralUSDAmount * ltv / (targetHF * debtPrice);
25705
+ 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}`);
25706
+ return new Web3Number(newAmount.toFixed(8), debtTokenAmount.decimals);
25707
+ }
25708
+ }
25521
25709
  async getVesuMultiplyCall(params) {
25522
- const vesuAdapter1 = this.getAdapter("vesu_leg1_adapter" /* VESU_LEG1 */);
25523
- const vesuAdapter2 = this.getAdapter("vesu_leg2_adapter" /* VESU_LEG2 */);
25710
+ const [vesuAdapter1, vesuAdapter2] = this.getVesuAdapters();
25524
25711
  const leg1LTV = await vesuAdapter1.getLTVConfig(this.config);
25525
25712
  const leg2LTV = await vesuAdapter2.getLTVConfig(this.config);
25526
25713
  logger.verbose(`${this.getTag()}: LTVLeg1: ${leg1LTV}`);
@@ -25529,7 +25716,7 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
25529
25716
  const token2Price = await this.pricer.getPrice(vesuAdapter2.config.collateral.symbol);
25530
25717
  logger.verbose(`${this.getTag()}: Price${vesuAdapter1.config.collateral.symbol}: ${token1Price.price}`);
25531
25718
  logger.verbose(`${this.getTag()}: Price${vesuAdapter2.config.collateral.symbol}: ${token2Price.price}`);
25532
- const TARGET_HF = 1.3;
25719
+ const TARGET_HF = this.metadata.additionalInfo.targetHealthFactor;
25533
25720
  const k1 = token1Price.price * leg1LTV / token2Price.price / TARGET_HF;
25534
25721
  const k2 = token1Price.price * TARGET_HF / token2Price.price / leg2LTV;
25535
25722
  const borrow2Amount = new Web3Number(
@@ -25587,14 +25774,14 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
25587
25774
  });
25588
25775
  if (params.isLeg1toLeg2) {
25589
25776
  const manageCall = this.getManageCall([
25590
- "vesu_leg1" /* VESU_LEG1 */,
25591
- "vesu_leg2" /* VESU_LEG2 */
25777
+ ...callSet1.map((i) => i.step),
25778
+ ...callSet2.map((i) => i.step)
25592
25779
  ], [...callSet1.map((i) => i.manageCall), ...callSet2.map((i) => i.manageCall)]);
25593
25780
  return manageCall;
25594
25781
  } else {
25595
25782
  const manageCall = this.getManageCall([
25596
- "vesu_leg2" /* VESU_LEG2 */,
25597
- "vesu_leg1" /* VESU_LEG1 */
25783
+ ...callSet2.map((i) => i.step),
25784
+ ...callSet1.map((i) => i.step)
25598
25785
  ], [...callSet2.map((i) => i.manageCall), ...callSet1.map((i) => i.manageCall)]);
25599
25786
  return manageCall;
25600
25787
  }
@@ -25661,15 +25848,21 @@ var usdcVaultSettings = {
25661
25848
  manager: ContractAddr.from("0xf41a2b1f498a7f9629db0b8519259e66e964260a23d20003f3e42bb1997a07"),
25662
25849
  vaultAllocator: ContractAddr.from("0x228cca1005d3f2b55cbaba27cb291dacf1b9a92d1d6b1638195fbd3d0c1e3ba"),
25663
25850
  redeemRequestNFT: ContractAddr.from("0x906d03590010868cbf7590ad47043959d7af8e782089a605d9b22567b64fda"),
25851
+ aumOracle: ContractAddr.from("0x6faf45ed185dec13ef723c9ead4266cab98d06f2cb237e331b1fa5c2aa79afe"),
25664
25852
  leafAdapters: [],
25665
- adapters: []
25853
+ adapters: [],
25854
+ targetHealthFactor: 1.3,
25855
+ minHealthFactor: 1.25
25666
25856
  };
25667
25857
  var wbtcVaultSettings = {
25668
25858
  manager: ContractAddr.from("0xef8a664ffcfe46a6af550766d27c28937bf1b77fb4ab54d8553e92bca5ba34"),
25669
25859
  vaultAllocator: ContractAddr.from("0x1e01c25f0d9494570226ad28a7fa856c0640505e809c366a9fab4903320e735"),
25670
25860
  redeemRequestNFT: ContractAddr.from("0x4fec59a12f8424281c1e65a80b5de51b4e754625c60cddfcd00d46941ec37b2"),
25861
+ aumOracle: ContractAddr.from("0x2edf4edbed3f839e7f07dcd913e92299898ff4cf0ba532f8c572c66c5b331b2"),
25671
25862
  leafAdapters: [],
25672
- adapters: []
25863
+ adapters: [],
25864
+ targetHealthFactor: 1.3,
25865
+ minHealthFactor: 1.25
25673
25866
  };
25674
25867
  var UniversalStrategies = [
25675
25868
  {
@@ -25719,13 +25912,10 @@ var TelegramNotif = class {
25719
25912
  this.subscribers = [
25720
25913
  // '6820228303',
25721
25914
  "1505578076",
25722
- // '5434736198', // maaza
25723
25915
  "1356705582",
25724
25916
  // langs
25725
25917
  "1388729514",
25726
25918
  // hwashere
25727
- "6020162572",
25728
- //minato
25729
25919
  "985902592"
25730
25920
  ];
25731
25921
  this.bot = new TelegramBot(token, { polling: shouldPoll });
@@ -26002,7 +26192,7 @@ function getAccount(accountKey, config, password = process.env.ACCOUNT_SECURE_PA
26002
26192
  ...storeConfig,
26003
26193
  PASSWORD: password
26004
26194
  });
26005
- return store.getAccount(accountKey);
26195
+ return store.getAccount(accountKey, "0x3");
26006
26196
  }
26007
26197
  async function myDeclare(contract_name, package_name = "strkfarm", config, acc) {
26008
26198
  const provider2 = config.provider;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strkfarm/sdk",
3
- "version": "1.0.56",
3
+ "version": "1.0.58",
4
4
  "description": "STRKFarm TS SDK (Meant for our internal use, but feel free to use it)",
5
5
  "typings": "dist/index.d.ts",
6
6
  "types": "dist/index.d.ts",
@@ -36,7 +36,7 @@ function getAccount(
36
36
  PASSWORD: password
37
37
  });
38
38
 
39
- return store.getAccount(accountKey);
39
+ return store.getAccount(accountKey, '0x3');
40
40
  }
41
41
 
42
42
  async function myDeclare(contract_name: string, package_name: string = 'strkfarm', config: IConfig, acc: Account) {
@@ -5,10 +5,8 @@ export class TelegramNotif {
5
5
  private subscribers: string[] = [
6
6
  // '6820228303',
7
7
  '1505578076',
8
- // '5434736198', // maaza
9
8
  '1356705582', // langs
10
9
  '1388729514', // hwashere
11
- '6020162572', //minato
12
10
  '985902592'
13
11
  ];
14
12
  readonly bot: TelegramBot;
@@ -1,5 +1,6 @@
1
1
  import { ContractAddr, Web3Number } from "@/dataTypes";
2
2
  import { IConfig, TokenInfo } from "@/interfaces";
3
+ import { CacheClass } from "@/utils/cacheClass";
3
4
  import { Call } from "starknet";
4
5
 
5
6
  export interface SingleActionAmount {
@@ -26,11 +27,12 @@ interface CacheData {
26
27
  ttl: number;
27
28
  data: any;
28
29
  }
29
- export class BaseStrategy<TVLInfo, ActionInfo> {
30
+ export class BaseStrategy<TVLInfo, ActionInfo> extends CacheClass {
30
31
  readonly config: IConfig;
31
32
  readonly cache: Map<string, CacheData> = new Map();
32
33
 
33
34
  constructor(config: IConfig) {
35
+ super();
34
36
  this.config = config;
35
37
  }
36
38
 
@@ -49,26 +51,4 @@ export class BaseStrategy<TVLInfo, ActionInfo> {
49
51
  async withdrawCall(amountInfo: ActionInfo, receiver: ContractAddr, owner: ContractAddr): Promise<Call[]> {
50
52
  throw new Error("Not implemented");
51
53
  }
52
-
53
- setCache(key: string, data: any, ttl: number = 60000): void {
54
- const timestamp = Date.now();
55
- this.cache.set(key, { timestamp, ttl, data });
56
- }
57
-
58
- getCache(key: string): any | null {
59
- const cachedData = this.cache.get(key);
60
- if (!cachedData || !this.isCacheValid(key)) {
61
- return null;
62
- }
63
- return cachedData.data;
64
- }
65
-
66
- isCacheValid(key: string): boolean {
67
- const cachedData = this.cache.get(key);
68
- if (!cachedData) return false;
69
-
70
- const { timestamp, ttl } = cachedData;
71
- return Date.now() - timestamp <= ttl;
72
- }
73
-
74
54
  }
@@ -126,9 +126,16 @@ export class SenseiVault extends BaseStrategy<
126
126
  collateralInSTRK: number;
127
127
  }> {
128
128
  const CACHE_KEY = 'positionInfo';
129
- if (this.isCacheValid(CACHE_KEY)) {
130
- return this.getCache(CACHE_KEY);
131
- }
129
+ const existingCacheData = this.getCache<{
130
+ collateralXSTRK: Web3Number;
131
+ collateralUSDValue: Web3Number;
132
+ debtSTRK: Web3Number;
133
+ debtUSDValue: Web3Number;
134
+ xSTRKPrice: number;
135
+ collateralInSTRK: number;
136
+ }>(CACHE_KEY);
137
+ if (existingCacheData) return existingCacheData;
138
+
132
139
  const resp = await fetch(
133
140
  `${getTrovesEndpoint()}/vesu/positions?walletAddress=${this.address.address}`,
134
141
  );
@@ -179,9 +186,9 @@ export class SenseiVault extends BaseStrategy<
179
186
 
180
187
  async getSecondaryTokenPriceRelativeToMain(retry = 0): Promise<number> {
181
188
  const CACHE_KEY = 'xSTRKPrice';
182
- if (this.isCacheValid(CACHE_KEY)) {
183
- return this.getCache(CACHE_KEY);
184
- }
189
+ const existingCacheData = this.getCache<number>(CACHE_KEY);
190
+ if (existingCacheData) return existingCacheData;
191
+
185
192
  const params: QuoteRequest = {
186
193
  sellTokenAddress: this.metadata.additionalInfo.secondaryToken.address.address,
187
194
  buyTokenAddress: this.metadata.additionalInfo.mainToken.address.address,
@@ -2,6 +2,7 @@ import { Call, hash, num, shortString } from "starknet";
2
2
  import { SIMPLE_SANITIZER, toBigInt } from "./adapter-utils";
3
3
  import { ContractAddr } from "@/dataTypes";
4
4
  import { LeafData } from "@/utils";
5
+ import { CacheClass } from "@/utils/cacheClass";
5
6
 
6
7
  export interface ManageCall {
7
8
  sanitizer: ContractAddr,
@@ -16,7 +17,7 @@ export type GenerateCallFn<T> = (params: T) => ManageCall;
16
17
  export type AdapterLeafType<T> = {leaf: LeafData, callConstructor: GenerateCallFn<T>}
17
18
  export type LeafAdapterFn<T> = () => AdapterLeafType<T>;
18
19
 
19
- export class BaseAdapter {
20
+ export class BaseAdapter extends CacheClass {
20
21
 
21
22
  protected constructSimpleLeafData(params: {
22
23
  id: string,