@strkfarm/sdk 1.1.39 → 1.1.40

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.
@@ -274,6 +274,25 @@ var defaultTokens = [{
274
274
  priceProxySymbol: "WBTC",
275
275
  priceCheckAmount: 1e-4
276
276
  // 112000 * 0.0001 = $11.2
277
+ }, {
278
+ name: "mRe7BTC",
279
+ symbol: "mRe7BTC",
280
+ logo: "https://imagedelivery.net/0xPAQaDtnQhBs8IzYRIlNg/3a62ecee-1e58-45d3-9862-3ce90dff1900/logo",
281
+ address: ContractAddr.from("0x4e4fb1a9ca7e84bae609b9dc0078ad7719e49187ae7e425bb47d131710eddac"),
282
+ decimals: 18,
283
+ coingeckId: void 0,
284
+ displayDecimals: 6,
285
+ priceCheckAmount: 1e-4
286
+ // 112000 * 0.0001 = $11.2
287
+ }, {
288
+ name: "mRe7YIELD",
289
+ symbol: "mRe7YIELD",
290
+ logo: "https://midas.app/assets/mre7-BcOOHm7i.svg",
291
+ address: ContractAddr.from("0x4be8945e61dc3e19ebadd1579a6bd53b262f51ba89e6f8b0c4bc9a7e3c633fc"),
292
+ decimals: 18,
293
+ coingeckId: void 0,
294
+ displayDecimals: 2,
295
+ priceCheckAmount: 100
277
296
  }];
278
297
  var tokens = defaultTokens;
279
298
  var _Global = class _Global {
@@ -2159,16 +2178,16 @@ var AvnuWrapper = class _AvnuWrapper {
2159
2178
  };
2160
2179
  return swapInfo;
2161
2180
  }
2162
- static buildZeroSwap(tokenToSell, address) {
2181
+ static buildZeroSwap(tokenToSell, beneficiary, tokenToBuy = tokenToSell) {
2163
2182
  return {
2164
2183
  token_from_address: tokenToSell.address,
2165
2184
  token_from_amount: uint256.bnToUint256(0),
2166
- token_to_address: tokenToSell.address,
2185
+ token_to_address: tokenToBuy.address,
2167
2186
  token_to_amount: uint256.bnToUint256(0),
2168
2187
  token_to_min_amount: uint256.bnToUint256(0),
2169
- beneficiary: address,
2188
+ beneficiary,
2170
2189
  integrator_fee_amount_bps: 0,
2171
- integrator_fee_recipient: address,
2190
+ integrator_fee_recipient: beneficiary,
2172
2191
  routes: []
2173
2192
  };
2174
2193
  }
@@ -4120,21 +4139,20 @@ var Harvests = class _Harvests {
4120
4139
  const rewards = await this.getHarvests(addr);
4121
4140
  if (rewards.length == 0) return [];
4122
4141
  const unClaimed = [];
4123
- const cls = await this.config.provider.getClassAt(rewards[0].rewardsContract.address);
4124
- for (let reward of rewards) {
4125
- const contract = new Contract4({ abi: cls.abi, address: reward.rewardsContract.address, providerOrAccount: this.config.provider });
4126
- const isClaimed = await contract.call("is_claimed", [reward.claim.id]);
4127
- logger.verbose(`${_Harvests.name}: isClaimed: ${isClaimed}`);
4128
- if (isClaimed) {
4129
- return unClaimed;
4130
- }
4131
- const bal = await new ERC20(this.config).balanceOf(reward.token, reward.rewardsContract.address, 18);
4132
- if (bal.lessThan(reward.claim.amount)) {
4133
- logger.verbose(`${_Harvests.name}: balance: ${bal.toString()}, amount: ${reward.claim.amount.toString()}`);
4134
- continue;
4135
- }
4136
- unClaimed.unshift(reward);
4142
+ const reward = rewards.sort((a, b) => b.endDate.getTime() - a.endDate.getTime())[0];
4143
+ const cls = await this.config.provider.getClassAt(reward.rewardsContract.address);
4144
+ const contract = new Contract4({ abi: cls.abi, address: reward.rewardsContract.address, providerOrAccount: this.config.provider });
4145
+ const isClaimed = await contract.call("is_claimed", [reward.claim.id]);
4146
+ logger.verbose(`${_Harvests.name}: isClaimed: ${isClaimed}`);
4147
+ if (isClaimed) {
4148
+ return unClaimed;
4137
4149
  }
4150
+ const bal = await new ERC20(this.config).balanceOf(reward.token, reward.rewardsContract.address, 18);
4151
+ if (bal.lessThan(reward.claim.amount)) {
4152
+ logger.verbose(`${_Harvests.name}: balance: ${bal.toString()}, amount: ${reward.claim.amount.toString()}`);
4153
+ return unClaimed;
4154
+ }
4155
+ unClaimed.unshift(reward);
4138
4156
  return unClaimed;
4139
4157
  }
4140
4158
  };
@@ -15401,6 +15419,91 @@ var apolloClient = new ApolloClient({
15401
15419
  });
15402
15420
  var apollo_client_default = apolloClient;
15403
15421
 
15422
+ // src/utils/math-utils.ts
15423
+ async function binarySearch(lowWei, highWei, callback) {
15424
+ while (lowWei <= highWei) {
15425
+ const diff = highWei - lowWei;
15426
+ const mid = lowWei + diff / 2n;
15427
+ const result = await callback(mid);
15428
+ if (result === "found") {
15429
+ return mid;
15430
+ } else if (result == "retry") {
15431
+ } else if (result === "go_low") {
15432
+ highWei = mid - BigInt(1);
15433
+ } else {
15434
+ lowWei = mid + BigInt(1);
15435
+ }
15436
+ }
15437
+ return null;
15438
+ }
15439
+ async function findMaxInputWithSlippage(options) {
15440
+ const {
15441
+ apiGetOutput,
15442
+ maxInput,
15443
+ maxSlippagePercent,
15444
+ tolerance,
15445
+ minInput = 0,
15446
+ referenceAmountMultiplier = 1e-3,
15447
+ referenceRate = 0
15448
+ } = options;
15449
+ let apiCalls = 0;
15450
+ if (!referenceRate && !referenceAmountMultiplier) {
15451
+ throw new Error("One of referenceRate or referenceAmountMultiplier must be provided");
15452
+ }
15453
+ let _referenceRate = referenceRate;
15454
+ if (!_referenceRate) {
15455
+ const smallAmount = maxInput * referenceAmountMultiplier;
15456
+ const referenceOutput = await apiGetOutput(smallAmount);
15457
+ apiCalls++;
15458
+ _referenceRate = referenceOutput / smallAmount;
15459
+ }
15460
+ async function checkSlippage(inputAmount) {
15461
+ const actualOutput = await apiGetOutput(inputAmount);
15462
+ apiCalls++;
15463
+ const expectedOutput = inputAmount * referenceRate;
15464
+ const slippage = (expectedOutput - actualOutput) / expectedOutput;
15465
+ logger.verbose(`findMaxInputWithSlippage::checkSlippage inputAmount: ${inputAmount}, actualOutput: ${actualOutput}, slippage: ${slippage}, maxSlippagePercent: ${maxSlippagePercent}`);
15466
+ return {
15467
+ acceptable: slippage <= maxSlippagePercent,
15468
+ slippage,
15469
+ output: actualOutput
15470
+ };
15471
+ }
15472
+ const maxCheck = await checkSlippage(maxInput);
15473
+ if (maxCheck.acceptable) {
15474
+ return {
15475
+ optimalInput: maxInput,
15476
+ actualOutput: maxCheck.output,
15477
+ actualSlippage: maxCheck.slippage,
15478
+ apiCallsUsed: apiCalls
15479
+ };
15480
+ }
15481
+ let left = minInput;
15482
+ let right = maxInput;
15483
+ let bestInput = minInput;
15484
+ let bestOutput = 0;
15485
+ let bestSlippage = 0;
15486
+ const convergenceThreshold = tolerance * maxInput;
15487
+ while (right - left > convergenceThreshold) {
15488
+ const mid = (left + right) / 2;
15489
+ const midCheck = await checkSlippage(mid);
15490
+ if (midCheck.acceptable) {
15491
+ bestInput = mid;
15492
+ bestOutput = midCheck.output;
15493
+ bestSlippage = midCheck.slippage;
15494
+ left = mid;
15495
+ } else {
15496
+ right = mid;
15497
+ }
15498
+ }
15499
+ return {
15500
+ optimalInput: bestInput,
15501
+ actualOutput: bestOutput,
15502
+ actualSlippage: bestSlippage,
15503
+ apiCallsUsed: apiCalls
15504
+ };
15505
+ }
15506
+
15404
15507
  // src/strategies/ekubo-cl-vault.tsx
15405
15508
  import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
15406
15509
  var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
@@ -16523,62 +16626,193 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
16523
16626
  logger.verbose(
16524
16627
  `${_EkuboCLVault.name}: harvest => Processing claim, isToken1: ${isToken1} amount: ${postFeeAmount.toWei()}`
16525
16628
  );
16526
- const token0Amt = isToken1 ? new Web3Number(0, token0Info.decimals) : postFeeAmount;
16527
- const token1Amt = isToken1 ? postFeeAmount : new Web3Number(0, token0Info.decimals);
16629
+ const isRewardTokenMatch = claim.token.eq(poolKey.token0) || claim.token.eq(poolKey.token1);
16630
+ if (isRewardTokenMatch) {
16631
+ const _callsFinal = await this._handleRewardAndVaultTokenMatchHarvest({
16632
+ acc,
16633
+ claim,
16634
+ isToken1,
16635
+ token0Info,
16636
+ token1Info,
16637
+ postFeeAmount,
16638
+ poolKey,
16639
+ bounds,
16640
+ maxIterations,
16641
+ priceRatioPrecision
16642
+ });
16643
+ calls.push(..._callsFinal);
16644
+ } else {
16645
+ const _callsFinal = await this._handleRewardAndVaultTokenMismatchHarvest({
16646
+ claim,
16647
+ token0Info,
16648
+ token1Info,
16649
+ postFeeAmount,
16650
+ poolKey,
16651
+ bounds,
16652
+ maxIterations,
16653
+ priceRatioPrecision,
16654
+ acc
16655
+ });
16656
+ calls.push(..._callsFinal);
16657
+ }
16658
+ }
16659
+ return calls;
16660
+ }
16661
+ /**
16662
+ * @description This funciton requires atleast one of the pool tokens to be reward token
16663
+ * i.e. STRK.
16664
+ * @param params
16665
+ */
16666
+ async _handleRewardAndVaultTokenMatchHarvest(params) {
16667
+ const { acc, claim, isToken1, token0Info, token1Info, postFeeAmount, poolKey, bounds, maxIterations, priceRatioPrecision } = params;
16668
+ const token0Amt = isToken1 ? new Web3Number(0, token0Info.decimals) : postFeeAmount;
16669
+ const token1Amt = isToken1 ? postFeeAmount : new Web3Number(0, token0Info.decimals);
16670
+ logger.verbose(
16671
+ `${_EkuboCLVault.name}: harvest => token0Amt: ${token0Amt.toString()}, token1Amt: ${token1Amt.toString()}`
16672
+ );
16673
+ const swapInfo = await this.getSwapInfoGivenAmounts(
16674
+ poolKey,
16675
+ token0Amt,
16676
+ token1Amt,
16677
+ bounds,
16678
+ maxIterations,
16679
+ priceRatioPrecision
16680
+ );
16681
+ swapInfo.token_to_address = token0Info.address.address;
16682
+ logger.verbose(
16683
+ `${_EkuboCLVault.name}: harvest => swapInfo: ${JSON.stringify(swapInfo)}`
16684
+ );
16685
+ logger.verbose(
16686
+ `${_EkuboCLVault.name}: harvest => claim: ${JSON.stringify(claim)}`
16687
+ );
16688
+ const harvestEstimateCall = async (swapInfo1) => {
16689
+ const swap1Amount = Web3Number.fromWei(
16690
+ uint2564.uint256ToBN(swapInfo1.token_from_amount).toString(),
16691
+ 18
16692
+ // cause its always STRK?
16693
+ ).minimum(
16694
+ postFeeAmount.toFixed(18)
16695
+ // cause always strk
16696
+ );
16697
+ swapInfo.token_from_amount = uint2564.bnToUint256(swap1Amount.toWei());
16698
+ swapInfo.token_to_min_amount = uint2564.bnToUint256(
16699
+ swap1Amount.multipliedBy(0).toWei()
16700
+ // placeholder
16701
+ );
16528
16702
  logger.verbose(
16529
- `${_EkuboCLVault.name}: harvest => token0Amt: ${token0Amt.toString()}, token1Amt: ${token1Amt.toString()}`
16703
+ `${_EkuboCLVault.name}: harvest => swap1Amount: ${swap1Amount}`
16530
16704
  );
16531
- const swapInfo = await this.getSwapInfoGivenAmounts(
16532
- poolKey,
16533
- token0Amt,
16534
- token1Amt,
16535
- bounds,
16536
- maxIterations,
16537
- priceRatioPrecision
16705
+ const remainingAmount = postFeeAmount.minus(swap1Amount).maximum(0);
16706
+ logger.verbose(
16707
+ `${_EkuboCLVault.name}: harvest => remainingAmount: ${remainingAmount}`
16538
16708
  );
16539
- swapInfo.token_to_address = token0Info.address.address;
16709
+ const swapInfo2 = {
16710
+ ...swapInfo,
16711
+ token_from_amount: uint2564.bnToUint256(remainingAmount.toWei())
16712
+ };
16713
+ swapInfo2.token_to_address = token1Info.address.address;
16540
16714
  logger.verbose(
16541
- `${_EkuboCLVault.name}: harvest => swapInfo: ${JSON.stringify(swapInfo)}`
16715
+ `${_EkuboCLVault.name}: harvest => swapInfo: ${JSON.stringify(
16716
+ swapInfo
16717
+ )}`
16542
16718
  );
16543
16719
  logger.verbose(
16544
- `${_EkuboCLVault.name}: harvest => claim: ${JSON.stringify(claim)}`
16720
+ `${_EkuboCLVault.name}: harvest => swapInfo2: ${JSON.stringify(
16721
+ swapInfo2
16722
+ )}`
16545
16723
  );
16546
- const harvestEstimateCall = async (swapInfo1) => {
16547
- const swap1Amount = Web3Number.fromWei(
16548
- uint2564.uint256ToBN(swapInfo1.token_from_amount).toString(),
16549
- 18
16550
- // cause its always STRK?
16551
- ).minimum(
16552
- postFeeAmount.toFixed(18)
16553
- // cause always strk
16554
- );
16555
- swapInfo.token_from_amount = uint2564.bnToUint256(swap1Amount.toWei());
16556
- swapInfo.token_to_min_amount = uint2564.bnToUint256(
16557
- swap1Amount.multipliedBy(0).toWei()
16558
- // placeholder
16559
- );
16560
- logger.verbose(
16561
- `${_EkuboCLVault.name}: harvest => swap1Amount: ${swap1Amount}`
16562
- );
16563
- const remainingAmount = postFeeAmount.minus(swap1Amount).maximum(0);
16564
- logger.verbose(
16565
- `${_EkuboCLVault.name}: harvest => remainingAmount: ${remainingAmount}`
16566
- );
16567
- const swapInfo2 = {
16568
- ...swapInfo,
16569
- token_from_amount: uint2564.bnToUint256(remainingAmount.toWei())
16570
- };
16571
- swapInfo2.token_to_address = token1Info.address.address;
16572
- logger.verbose(
16573
- `${_EkuboCLVault.name}: harvest => swapInfo: ${JSON.stringify(
16574
- swapInfo
16575
- )}`
16576
- );
16577
- logger.verbose(
16578
- `${_EkuboCLVault.name}: harvest => swapInfo2: ${JSON.stringify(
16579
- swapInfo2
16580
- )}`
16581
- );
16724
+ const calldata = [
16725
+ claim.rewardsContract.address,
16726
+ {
16727
+ id: claim.claim.id,
16728
+ amount: claim.claim.amount.toWei(),
16729
+ claimee: claim.claim.claimee.address
16730
+ },
16731
+ claim.proof.map((p) => num5.getDecimalString(p)),
16732
+ swapInfo,
16733
+ swapInfo2
16734
+ ];
16735
+ logger.verbose(
16736
+ `${_EkuboCLVault.name}: harvest => calldata: ${JSON.stringify(
16737
+ calldata
16738
+ )}`
16739
+ );
16740
+ return [this.contract.populate("harvest", calldata)];
16741
+ };
16742
+ const _callsFinal = await this.rebalanceIter(
16743
+ swapInfo,
16744
+ acc,
16745
+ harvestEstimateCall,
16746
+ claim.token.eq(poolKey.token0),
16747
+ 0,
16748
+ 0n,
16749
+ BigInt(postFeeAmount.toWei())
16750
+ // upper limit is the post fee amount
16751
+ );
16752
+ logger.verbose(
16753
+ `${_EkuboCLVault.name}: harvest => _callsFinal: ${JSON.stringify(
16754
+ _callsFinal
16755
+ )}`
16756
+ );
16757
+ return _callsFinal;
16758
+ }
16759
+ /**
16760
+ * @description This function handles harvesting of reward token that is not the same as any of the vault token
16761
+ * i.e. STRK is not part of vault tokens like BTC/ETH
16762
+ * @param params
16763
+ * @returns
16764
+ */
16765
+ async _handleRewardAndVaultTokenMismatchHarvest(params) {
16766
+ const { acc, claim, token0Info, token1Info, postFeeAmount, poolKey, bounds, maxIterations, priceRatioPrecision } = params;
16767
+ let token0Amt = postFeeAmount;
16768
+ const beneficiary = this.address.address;
16769
+ let harvestCall = null;
16770
+ harvestCall = await this.harvestMismatchEstimateCallFn({
16771
+ postFeeAmount,
16772
+ claim,
16773
+ token0Info,
16774
+ token1Info,
16775
+ acc
16776
+ });
16777
+ if (!harvestCall) {
16778
+ throw new Error("Harvest call not found");
16779
+ }
16780
+ return [harvestCall];
16781
+ }
16782
+ // given an amount (i.e. portion of reward to use to swap to token0), returns info on increasing or decreasing
16783
+ // amount for binary search
16784
+ async harvestMismatchEstimateCallFn(params) {
16785
+ const { postFeeAmount, claim, token0Info, token1Info, acc } = params;
16786
+ let harvestCall = null;
16787
+ const binarySearchCallbackFn = async (mid) => {
16788
+ const rewardPart2 = BigInt(postFeeAmount.toWei()) - mid;
16789
+ const avnuWrapper = new AvnuWrapper();
16790
+ const beneficiary = this.address.address;
16791
+ const quote1 = await avnuWrapper.getQuotes(
16792
+ claim.token.address,
16793
+ token0Info.address.address,
16794
+ mid.toString(),
16795
+ beneficiary
16796
+ );
16797
+ const swapInfo1 = await avnuWrapper.getSwapInfo(
16798
+ quote1,
16799
+ beneficiary,
16800
+ 0,
16801
+ beneficiary
16802
+ );
16803
+ const quote2 = await avnuWrapper.getQuotes(
16804
+ claim.token.address,
16805
+ token1Info.address.address,
16806
+ rewardPart2.toString(),
16807
+ beneficiary
16808
+ );
16809
+ const swapInfo2 = await avnuWrapper.getSwapInfo(
16810
+ quote2,
16811
+ beneficiary,
16812
+ 0,
16813
+ beneficiary
16814
+ );
16815
+ try {
16582
16816
  const calldata = [
16583
16817
  claim.rewardsContract.address,
16584
16818
  {
@@ -16587,34 +16821,24 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
16587
16821
  claimee: claim.claim.claimee.address
16588
16822
  },
16589
16823
  claim.proof.map((p) => num5.getDecimalString(p)),
16590
- swapInfo,
16824
+ swapInfo1,
16591
16825
  swapInfo2
16592
16826
  ];
16593
- logger.verbose(
16594
- `${_EkuboCLVault.name}: harvest => calldata: ${JSON.stringify(
16595
- calldata
16596
- )}`
16597
- );
16598
- return [this.contract.populate("harvest", calldata)];
16599
- };
16600
- const _callsFinal = await this.rebalanceIter(
16601
- swapInfo,
16602
- acc,
16603
- harvestEstimateCall,
16604
- claim.token.eq(poolKey.token0),
16605
- 0,
16606
- 0n,
16607
- BigInt(postFeeAmount.toWei())
16608
- // upper limit is the post fee amount
16609
- );
16610
- logger.verbose(
16611
- `${_EkuboCLVault.name}: harvest => _callsFinal: ${JSON.stringify(
16612
- _callsFinal
16613
- )}`
16614
- );
16615
- calls.push(..._callsFinal);
16616
- }
16617
- return calls;
16827
+ harvestCall = this.contract.populate("harvest", calldata);
16828
+ const gas = await acc.estimateInvokeFee(harvestCall);
16829
+ return "found";
16830
+ } catch (err) {
16831
+ console.error(err);
16832
+ if (err.message.includes("invalid token0 amount")) {
16833
+ return "go_low";
16834
+ } else if (err.message.includes("invalid token1 amount")) {
16835
+ return "go_high";
16836
+ }
16837
+ return "retry";
16838
+ }
16839
+ };
16840
+ await binarySearch(0n, BigInt(postFeeAmount.toWei()), binarySearchCallbackFn);
16841
+ return harvestCall;
16618
16842
  }
16619
16843
  async getInvestmentFlows() {
16620
16844
  const netYield = await this.netAPY();
@@ -19146,7 +19370,58 @@ function toBigInt(value) {
19146
19370
  }
19147
19371
 
19148
19372
  // src/strategies/universal-adapters/baseAdapter.ts
19373
+ var APYType = /* @__PURE__ */ ((APYType2) => {
19374
+ APYType2["BASE"] = "base";
19375
+ APYType2["REWARD"] = "reward";
19376
+ APYType2["LST"] = "lst";
19377
+ return APYType2;
19378
+ })(APYType || {});
19149
19379
  var BaseAdapter = class extends CacheClass {
19380
+ // readonly config: BaseAdapterConfig;
19381
+ // constructor(config: BaseAdapterConfig) {
19382
+ // super();
19383
+ // this.config = config;
19384
+ // }
19385
+ constructor() {
19386
+ super();
19387
+ }
19388
+ // /**
19389
+ // * Loop through all supported positions and return amount, usd value, remarks and apy for each
19390
+ // */
19391
+ // async getPositions(): Promise<PositionInfo[]> {
19392
+ // const results: PositionInfo[] = [];
19393
+ // for (const supported of this.config.supportedPositions) {
19394
+ // const amount = await this.getPosition(supported);
19395
+ // const usdValue = await this.getUSDValue(supported.asset, amount);
19396
+ // const apy = await this.getAPY(supported);
19397
+ // results.push({ amount, usdValue, apy });
19398
+ // }
19399
+ // return results;
19400
+ // }
19401
+ // /**
19402
+ // * Implemented by child adapters to compute APY for a given supported position
19403
+ // */
19404
+ // protected abstract getAPY(supportedPosition: SupportedPosition): Promise<PositionAPY>;
19405
+ // /**
19406
+ // * Implemented by child adapters to fetch amount for a given supported position
19407
+ // */
19408
+ // protected abstract getPosition(supportedPosition: SupportedPosition): Promise<Web3Number>;
19409
+ // /**
19410
+ // * Implemented by child adapters to calculate maximum deposit positions
19411
+ // * @param amount Optional amount in baseToken to deposit
19412
+ // */
19413
+ // protected abstract maxDeposit(amount?: Web3Number): Promise<PositionInfo[]>;
19414
+ // /**
19415
+ // * Implemented by child adapters to calculate maximum withdraw positions
19416
+ // */
19417
+ // protected abstract maxWithdraw(): Promise<PositionInfo[]>;
19418
+ // /**
19419
+ // * Uses pricer to convert an amount of an asset to USD value
19420
+ // */
19421
+ // protected async getUSDValue(asset: TokenInfo, amount: Web3Number): Promise<number> {
19422
+ // const priceInfo = await this.config.pricer.getPrice(asset.symbol);
19423
+ // return amount.toNumber() * priceInfo.price;
19424
+ // }
19150
19425
  constructSimpleLeafData(params, sanitizer = SIMPLE_SANITIZER) {
19151
19426
  const { id, target, method, packedArguments } = params;
19152
19427
  return {
@@ -19164,6 +19439,94 @@ var BaseAdapter = class extends CacheClass {
19164
19439
  ]
19165
19440
  };
19166
19441
  }
19442
+ // /**
19443
+ // * Implementor must provide target/method/packedArguments/sanitizer for deposit leaf construction
19444
+ // */
19445
+ // protected abstract _getDepositLeaf(): {
19446
+ // target: ContractAddr,
19447
+ // method: string,
19448
+ // packedArguments: bigint[],
19449
+ // sanitizer: ContractAddr,
19450
+ // id: string
19451
+ // }[];
19452
+ // /**
19453
+ // * Implementor must provide target/method/packedArguments/sanitizer for withdraw leaf construction
19454
+ // */
19455
+ // protected abstract _getWithdrawLeaf(): {
19456
+ // target: ContractAddr,
19457
+ // method: string,
19458
+ // packedArguments: bigint[],
19459
+ // sanitizer: ContractAddr,
19460
+ // id: string
19461
+ // }[];
19462
+ // /**
19463
+ // * Returns deposit leaf adapter using configured proof id
19464
+ // */
19465
+ // getDepositLeaf(): AdapterLeafType<T1> {
19466
+ // const leafConfigs = this._getDepositLeaf();
19467
+ // const leaves = leafConfigs.map(config => {
19468
+ // const { target, method, packedArguments, sanitizer, id } = config;
19469
+ // const leaf = this.constructSimpleLeafData({
19470
+ // id: id,
19471
+ // target,
19472
+ // method,
19473
+ // packedArguments
19474
+ // }, sanitizer);
19475
+ // return leaf;
19476
+ // });
19477
+ // return { leaves, callConstructor: this.getDepositCall.bind(this) as unknown as GenerateCallFn<T1> };
19478
+ // }
19479
+ // /**
19480
+ // * Returns withdraw leaf adapter using configured proof id
19481
+ // */
19482
+ // getWithdrawLeaf(): AdapterLeafType<T2> {
19483
+ // const leafConfigs = this._getWithdrawLeaf();
19484
+ // const leaves = leafConfigs.map(config => {
19485
+ // const { target, method, packedArguments, sanitizer, id } = config;
19486
+ // const leaf = this.constructSimpleLeafData({
19487
+ // id: id,
19488
+ // target,
19489
+ // method,
19490
+ // packedArguments
19491
+ // }, sanitizer ?? SIMPLE_SANITIZER);
19492
+ // return leaf;
19493
+ // });
19494
+ // return { leaves, callConstructor: this.getWithdrawCall.bind(this) as unknown as GenerateCallFn<T2> };
19495
+ // }
19496
+ // /**
19497
+ // * Default deposit callConstructor: expects params as calldata (bigint[])
19498
+ // */
19499
+ // protected getDepositCall<T1 = bigint[]>(params: T1): ManageCall[] {
19500
+ // const leafConfigs = this._getDepositLeaf();
19501
+ // return leafConfigs.map(config => {
19502
+ // const { target, method, sanitizer } = config;
19503
+ // return {
19504
+ // sanitizer: sanitizer ?? SIMPLE_SANITIZER,
19505
+ // call: {
19506
+ // contractAddress: target,
19507
+ // selector: hash.getSelectorFromName(method),
19508
+ // calldata: params as unknown as bigint[]
19509
+ // }
19510
+ // };
19511
+ // });
19512
+ // }
19513
+ // /**
19514
+ // * Default withdraw callConstructor: expects params as calldata (bigint[])
19515
+ // */
19516
+ // protected getWithdrawCall<T2 = bigint[]>(params: T2): ManageCall[] {
19517
+ // const leafConfigs = this._getWithdrawLeaf();
19518
+ // return leafConfigs.map(config => {
19519
+ // const { target, method, sanitizer } = config;
19520
+ // return {
19521
+ // sanitizer: sanitizer ?? SIMPLE_SANITIZER,
19522
+ // call: {
19523
+ // contractAddress: target,
19524
+ // selector: hash.getSelectorFromName(method),
19525
+ // calldata: params as unknown as bigint[]
19526
+ // }
19527
+ // };
19528
+ // });
19529
+ // }
19167
19530
  };
19168
19531
 
19169
19532
  // src/strategies/universal-adapters/common-adapter.ts
@@ -26766,7 +27129,20 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
26766
27129
  }
26767
27130
  const output = await contract.call("pair_config", [this.config.collateral.address.address, this.config.debt.address.address]);
26768
27131
  logger.verbose(`${this.config.debt.symbol}::VesuAdapter::getDebtCap debt_cap: ${output.debt_cap.toString()}`);
26769
- return Web3Number.fromWei(output.debt_cap.toString(), this.config.debt.decimals);
27132
+ if (!isV2) {
27133
+ throw new Error("getDebtCap is not supported for v1");
27134
+ }
27135
+ const currentDebt = await this.getCurrentDebtUtilisationAmount(config);
27136
+ logger.verbose(`${this.config.debt.symbol}::VesuAdapter::getDebtCap currentDebt: ${currentDebt.toString()}`);
27137
+ return Web3Number.fromWei(output.debt_cap.toString(), this.config.debt.decimals).minus(currentDebt);
27138
+ }
27139
+ async getCurrentDebtUtilisationAmount(config) {
27140
+ const { contract, isV2 } = await this.getVesuSingletonContract(config, this.config.poolId);
27141
+ if (!isV2) {
27142
+ throw new Error("getCurrentDebtUtilisationAmount is not supported for v1");
27143
+ }
27144
+ const output = await contract.call("pairs", [this.config.collateral.address.address, this.config.debt.address.address]);
27145
+ return new Web3Number((Number(output.total_nominal_debt) / 1e18).toFixed(9), this.config.debt.decimals);
26770
27146
  }
26771
27147
  async getMaxBorrowableByInterestRate(config, asset, maxBorrowAPY) {
26772
27148
  const { contract, isV2 } = await this.getVesuSingletonContract(config, this.config.poolId);
@@ -26799,16 +27175,17 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
26799
27175
  const assetConfig = isV2 ? _assetConfig : _assetConfig["0"];
26800
27176
  const timeDelta = assetConfig.last_updated;
26801
27177
  const lastFullUtilizationRate = assetConfig.last_full_utilization_rate;
26802
- const totalSupply = new Web3Number((Number(assetConfig.total_nominal_debt) / 1e18).toFixed(9), asset.decimals).plus(Web3Number.fromWei(assetConfig.reserve, asset.decimals));
27178
+ const currentDebt = new Web3Number((Number(assetConfig.total_nominal_debt) / 1e18).toFixed(9), asset.decimals);
27179
+ const totalSupply = currentDebt.plus(Web3Number.fromWei(assetConfig.reserve, asset.decimals));
26803
27180
  const ratePerSecond = BigInt(Math.round(maxBorrowAPY / 365 / 24 / 60 / 60 * Number(SCALE)));
26804
27181
  const maxUtilisation = this.getMaxUtilizationGivenRatePerSecond(interestRateConfig, ratePerSecond, timeDelta, lastFullUtilizationRate);
26805
27182
  logger.verbose(`${asset.symbol}::VesuAdapter::getMaxBorrowableByInterestRate maxUtilisation: ${Number(maxUtilisation) / 1e18}, totalSupply: ${totalSupply.toString()}`);
26806
27183
  const maxDebtToHave = totalSupply.multipliedBy(Number(maxUtilisation) / 1e18);
26807
- const currentDebt = new Web3Number((Number(assetConfig.total_nominal_debt) / 1e18).toFixed(9), asset.decimals);
27184
+ logger.verbose(`${asset.symbol}::VesuAdapter::getMaxBorrowableByInterestRate currentDebt: ${currentDebt.toString()}, maxDebtToHave: ${maxDebtToHave.toString()}`);
26808
27185
  return maxDebtToHave.minus(currentDebt);
26809
27186
  }
26810
- async getLTVConfig(config) {
26811
- const CACHE_KEY = "ltv_config";
27187
+ async getLTVConfig(config, blockNumber = "latest") {
27188
+ const CACHE_KEY = `ltv_config_${blockNumber}`;
26812
27189
  const cacheData = this.getCache(CACHE_KEY);
26813
27190
  if (cacheData) {
26814
27191
  return cacheData;
@@ -26816,10 +27193,10 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
26816
27193
  const { contract, isV2 } = await this.getVesuSingletonContract(config, this.config.poolId);
26817
27194
  let ltv = 0;
26818
27195
  if (isV2) {
26819
- const output = await contract.call("pair_config", [this.config.collateral.address.address, this.config.debt.address.address]);
27196
+ const output = await contract.call("pair_config", [this.config.collateral.address.address, this.config.debt.address.address], { blockIdentifier: blockNumber });
26820
27197
  ltv = Number(output.max_ltv) / 1e18;
26821
27198
  } else {
26822
- const output = await contract.call("ltv_config", [this.config.poolId.address, this.config.collateral.address.address, this.config.debt.address.address]);
27199
+ const output = await contract.call("ltv_config", [this.config.poolId.address, this.config.collateral.address.address, this.config.debt.address.address], { blockIdentifier: blockNumber });
26823
27200
  ltv = Number(output.max_ltv) / 1e18;
26824
27201
  }
26825
27202
  if (ltv == 0) {
@@ -26828,11 +27205,11 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
26828
27205
  this.setCache(CACHE_KEY, ltv, 3e5);
26829
27206
  return this.getCache(CACHE_KEY);
26830
27207
  }
26831
- async getPositions(config) {
27208
+ async getPositions(config, blockNumber = "latest") {
26832
27209
  if (!this.pricer) {
26833
27210
  throw new Error("Pricer is not initialized");
26834
27211
  }
26835
- const CACHE_KEY = "positions";
27212
+ const CACHE_KEY = `positions_${blockNumber}`;
26836
27213
  const cacheData = this.getCache(CACHE_KEY);
26837
27214
  if (cacheData) {
26838
27215
  return cacheData;
@@ -26844,7 +27221,8 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
26844
27221
  this.config.collateral.address.address,
26845
27222
  this.config.debt.address.address,
26846
27223
  this.config.vaultAllocator.address
26847
- ]);
27224
+ ], { blockIdentifier: blockNumber });
27225
+ console.log(output);
26848
27226
  const token1Price = await this.pricer.getPrice(this.config.collateral.symbol);
26849
27227
  const token2Price = await this.pricer.getPrice(this.config.debt.symbol);
26850
27228
  logger.verbose(`VesuAdapter::getPositions token1Price: ${token1Price.price}, token2Price: ${token2Price.price}`);
@@ -26864,11 +27242,11 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
26864
27242
  this.setCache(CACHE_KEY, value, 6e4);
26865
27243
  return value;
26866
27244
  }
26867
- async getCollateralization(config) {
27245
+ async getCollateralization(config, blockNumber = "latest") {
26868
27246
  if (!this.pricer) {
26869
27247
  throw new Error("Pricer is not initialized");
26870
27248
  }
26871
- const CACHE_KEY = "collateralization";
27249
+ const CACHE_KEY = `collateralization_${blockNumber}`;
26872
27250
  const cacheData = this.getCache(CACHE_KEY);
26873
27251
  if (cacheData) {
26874
27252
  return cacheData;
@@ -26880,7 +27258,7 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
26880
27258
  this.config.collateral.address.address,
26881
27259
  this.config.debt.address.address,
26882
27260
  this.config.vaultAllocator.address
26883
- ]);
27261
+ ], { blockIdentifier: blockNumber });
26884
27262
  const collateralAmount = Web3Number.fromWei(output["1"].toString(), 18);
26885
27263
  const debtAmount = Web3Number.fromWei(output["2"].toString(), 18);
26886
27264
  const value = [{
@@ -26917,9 +27295,9 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
26917
27295
  ltv
26918
27296
  };
26919
27297
  }
26920
- async getHealthFactor() {
26921
- const ltv = await this.getLTVConfig(this.networkConfig);
26922
- const collateralisation = await this.getCollateralization(this.networkConfig);
27298
+ async getHealthFactor(blockNumber = "latest") {
27299
+ const ltv = await this.getLTVConfig(this.networkConfig, blockNumber);
27300
+ const collateralisation = await this.getCollateralization(this.networkConfig, blockNumber);
26923
27301
  return collateralisation[0].usdValue * ltv / collateralisation[1].usdValue;
26924
27302
  }
26925
27303
  static async getVesuPools(retry = 0) {
@@ -29581,11 +29959,11 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
29581
29959
  vesuAdapter2.networkConfig = this.config;
29582
29960
  return [vesuAdapter1, vesuAdapter2];
29583
29961
  }
29584
- async getVesuPositions() {
29962
+ async getVesuPositions(blockNumber = "latest") {
29585
29963
  const adapters = this.getVesuAdapters();
29586
29964
  const positions = [];
29587
29965
  for (const adapter of adapters) {
29588
- positions.push(...await adapter.getPositions(this.config));
29966
+ positions.push(...await adapter.getPositions(this.config, blockNumber));
29589
29967
  }
29590
29968
  return positions;
29591
29969
  }
@@ -29654,8 +30032,8 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
29654
30032
  async getLSTAPR(address) {
29655
30033
  return 0;
29656
30034
  }
29657
- async getVesuHealthFactors() {
29658
- return await Promise.all(this.getVesuAdapters().map((v) => v.getHealthFactor()));
30035
+ async getVesuHealthFactors(blockNumber = "latest") {
30036
+ return await Promise.all(this.getVesuAdapters().map((v) => v.getHealthFactor(blockNumber)));
29659
30037
  }
29660
30038
  async computeRebalanceConditionAndReturnCalls() {
29661
30039
  const vesuAdapters = this.getVesuAdapters();
@@ -30251,6 +30629,42 @@ var UniversalStrategies = [
30251
30629
 
30252
30630
  // src/strategies/universal-lst-muliplier-strategy.tsx
30253
30631
  import { Contract as Contract10, uint256 as uint2569 } from "starknet";
30632
+
30633
+ // src/utils/health-factor-math.ts
30634
+ var HealthFactorMath = class {
30635
+ static getCollateralRequired(debtAmount, debtPrice, targetHF, maxLTV, collateralPrice, collateralTokenInfo) {
30636
+ const numerator = debtAmount.multipliedBy(debtPrice).multipliedBy(targetHF);
30637
+ const denominator = collateralPrice * maxLTV;
30638
+ const collateralAmount = numerator.dividedBy(denominator);
30639
+ const netCollateral = new Web3Number(collateralAmount.toString(), collateralTokenInfo.decimals);
30640
+ return netCollateral;
30641
+ }
30642
+ static getMinCollateralRequiredOnLooping(debtAmount, debtPrice, targetHF, maxLTV, collateralPrice, collateralTokenInfo) {
30643
+ const netCollateral = this.getCollateralRequired(debtAmount, debtPrice, targetHF, maxLTV, collateralPrice, collateralTokenInfo);
30644
+ const collateralFromDebt = new Web3Number(debtAmount.multipliedBy(debtPrice).dividedBy(collateralPrice).toString(), collateralTokenInfo.decimals);
30645
+ return netCollateral.minus(collateralFromDebt);
30646
+ }
30647
+ static getHealthFactor(collateralAmount, collateralPrice, maxLTV, debtAmount, debtPrice) {
30648
+ const numerator = collateralAmount.multipliedBy(collateralPrice).multipliedBy(maxLTV);
30649
+ const denominator = debtAmount.multipliedBy(debtPrice);
30650
+ const healthFactor = numerator.dividedBy(denominator);
30651
+ return healthFactor.toNumber();
30652
+ }
30653
+ static getMaxDebtAmountOnLooping(collateralAmount, collateralPrice, maxLTV, targetHF, debtPrice, debtTokenInfo) {
30654
+ const numerator = collateralAmount.multipliedBy(collateralPrice).multipliedBy(maxLTV);
30655
+ const denominator = targetHF - maxLTV;
30656
+ const debtAmount = numerator.dividedBy(denominator);
30657
+ return new Web3Number(debtAmount.toString(), debtTokenInfo.decimals);
30658
+ }
30659
+ static getMaxDebtAmount(collateralAmount, collateralPrice, maxLTV, targetHF, debtPrice, debtTokenInfo) {
30660
+ const numerator = collateralAmount.multipliedBy(collateralPrice).multipliedBy(maxLTV);
30661
+ const denominator = targetHF * debtPrice;
30662
+ const debtAmount = numerator.dividedBy(denominator);
30663
+ return new Web3Number(debtAmount.toString(), debtTokenInfo.decimals);
30664
+ }
30665
+ };
30666
+
30667
+ // src/strategies/universal-lst-muliplier-strategy.tsx
30254
30668
  import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
30255
30669
  var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy extends UniversalStrategy {
30256
30670
  constructor(config, pricer, metadata) {
@@ -30265,15 +30679,14 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30265
30679
  }
30266
30680
  }
30267
30681
  asset() {
30268
- const vesuAdapter1 = this.getAdapter("vesu_leg1_adapter" /* VESU_LEG1 */);
30269
- return vesuAdapter1.config.collateral;
30682
+ return this.getVesuSameTokenAdapter().config.collateral;
30270
30683
  }
30271
30684
  getTag() {
30272
30685
  return `${_UniversalLstMultiplierStrategy.name}:${this.metadata.name}`;
30273
30686
  }
30274
30687
  // Vesu adapter with LST and base token match
30275
30688
  getVesuSameTokenAdapter() {
30276
- const baseAdapter = this.getAdapter("vesu_leg1_adapter" /* VESU_LEG1 */);
30689
+ const baseAdapter = this.getAdapter(getVesuLegId("vesu_leg1" /* VESU_LEG1 */, this.metadata.additionalInfo.underlyingToken.symbol));
30277
30690
  baseAdapter.networkConfig = this.config;
30278
30691
  baseAdapter.pricer = this.pricer;
30279
30692
  return baseAdapter;
@@ -30321,20 +30734,52 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30321
30734
  return price;
30322
30735
  }
30323
30736
  async getAvnuSwapMultiplyCall(params) {
30324
- return this._getAvnuDepositSwapLegCall({
30325
- ...params,
30326
- minHF: 1.1
30327
- // undo
30328
- });
30737
+ assert(params.isDeposit, "Only deposit is supported in getAvnuSwapMultiplyCall");
30738
+ const maxBorrowableAmounts = await this.getMaxBorrowableAmount({ isAPYComputation: false });
30739
+ const allVesuAdapters = this.getVesuAdapters();
30740
+ let remainingAmount = params.leg1DepositAmount;
30741
+ const lstExRate = await this.getLSTExchangeRate();
30742
+ const baseAssetPrice = await this.pricer.getPrice(this.getLSTUnderlyingTokenInfo().symbol);
30743
+ const lstPrice = baseAssetPrice.price * lstExRate;
30744
+ for (let i = 0; i < maxBorrowableAmounts.maxBorrowables.length; i++) {
30745
+ const maxBorrowable = maxBorrowableAmounts.maxBorrowables[i];
30746
+ const vesuAdapter = allVesuAdapters.find((adapter) => adapter.config.debt.address.eq(maxBorrowable.borrowableAsset.address));
30747
+ if (!vesuAdapter) {
30748
+ throw new Error(`${this.getTag()}::getAvnuSwapMultiplyCall: vesuAdapter not found for borrowable asset: ${maxBorrowable.borrowableAsset.symbol}`);
30749
+ }
30750
+ const maxLTV = await vesuAdapter.getLTVConfig(this.config);
30751
+ const debtPrice = await this.pricer.getPrice(maxBorrowable.borrowableAsset.symbol);
30752
+ const maxAmountToDeposit = HealthFactorMath.getMinCollateralRequiredOnLooping(
30753
+ maxBorrowable.amount,
30754
+ debtPrice.price,
30755
+ this.metadata.additionalInfo.targetHealthFactor,
30756
+ maxLTV,
30757
+ lstPrice,
30758
+ this.asset()
30759
+ );
30760
+ const amountToDeposit = remainingAmount.minimum(maxAmountToDeposit);
30761
+ logger.verbose(`${this.getTag()}::getAvnuSwapMultiplyCall::${vesuAdapter.config.debt.symbol}:: remainingAmount: ${remainingAmount}, amountToDeposit: ${amountToDeposit}, depositAmount: ${amountToDeposit}, maxBorrowable: ${maxBorrowable.amount}`);
30762
+ const call = await this._getAvnuDepositSwapLegCall({
30763
+ isDeposit: params.isDeposit,
30764
+ // adjust decimals of debt asset
30765
+ leg1DepositAmount: amountToDeposit,
30766
+ minHF: 1.1,
30767
+ // undo
30768
+ vesuAdapter
30769
+ });
30770
+ remainingAmount = remainingAmount.minus(amountToDeposit);
30771
+ return { call, vesuAdapter };
30772
+ }
30773
+ throw new Error(`${this.getTag()}::getAvnuSwapMultiplyCall: no calls found`);
30329
30774
  }
30330
30775
  async _getAvnuDepositSwapLegCall(params) {
30776
+ const { vesuAdapter } = params;
30331
30777
  logger.verbose(`${this.getTag()}::_getAvnuDepositSwapLegCall params: ${JSON.stringify(params)}`);
30332
30778
  assert(params.isDeposit, "Only deposit is supported in _getAvnuDepositSwapLegCall");
30333
- const [vesuAdapter1] = this.getVesuAdapters();
30334
- const legLTV = await vesuAdapter1.getLTVConfig(this.config);
30779
+ const legLTV = await vesuAdapter.getLTVConfig(this.config);
30335
30780
  logger.verbose(`${this.getTag()}::_getAvnuDepositSwapLegCall legLTV: ${legLTV}`);
30336
- const existingPositions = await vesuAdapter1.getPositions(this.config);
30337
- const collateralisation = await vesuAdapter1.getCollateralization(this.config);
30781
+ const existingPositions = await vesuAdapter.getPositions(this.config);
30782
+ const collateralisation = await vesuAdapter.getCollateralization(this.config);
30338
30783
  const existingCollateralInfo = existingPositions[0];
30339
30784
  const existingDebtInfo = existingPositions[1];
30340
30785
  logger.debug(`${this.getTag()}::_getAvnuDepositSwapLegCall existingCollateralInfo: ${JSON.stringify(existingCollateralInfo)},
@@ -30342,11 +30787,40 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30342
30787
  const collateralPrice = collateralisation[0].usdValue > 0 ? collateralisation[0].usdValue / existingCollateralInfo.amount.toNumber() : 1;
30343
30788
  const debtPrice = collateralisation[1].usdValue > 0 ? collateralisation[1].usdValue / existingDebtInfo.amount.toNumber() : 1;
30344
30789
  logger.debug(`${this.getTag()}::_getAvnuDepositSwapLegCall collateralPrice: ${collateralPrice}, debtPrice: ${debtPrice}`);
30790
+ const debtTokenInfo = vesuAdapter.config.debt;
30791
+ let newDepositAmount = params.leg1DepositAmount;
30345
30792
  const totalCollateral = existingCollateralInfo.amount.plus(params.leg1DepositAmount);
30346
30793
  logger.verbose(`${this.getTag()}::_getAvnuDepositSwapLegCall totalCollateral: ${totalCollateral}`);
30347
- const totalDebtAmount = totalCollateral.multipliedBy(collateralPrice).multipliedBy(legLTV).dividedBy(debtPrice).dividedBy(params.minHF);
30348
- logger.verbose(`${this.getTag()}::_getAvnuDepositSwapLegCall totalDebtAmount: ${totalDebtAmount}`);
30349
- const debtAmount = totalDebtAmount.minus(existingDebtInfo.amount);
30794
+ const totalDebtAmount = new Web3Number(
30795
+ totalCollateral.multipliedBy(collateralPrice).multipliedBy(legLTV).dividedBy(debtPrice).dividedBy(params.minHF).toString(),
30796
+ debtTokenInfo.decimals
30797
+ );
30798
+ let debtAmount = totalDebtAmount.minus(existingDebtInfo.amount);
30799
+ logger.verbose(`${this.getTag()}::_getAvnuDepositSwapLegCall totalDebtAmount: ${totalDebtAmount}, initial computed debt: ${debtAmount}`);
30800
+ const maxBorrowable = await this.getMaxBorrowableAmountByVesuAdapter(vesuAdapter, false);
30801
+ if (debtAmount.gt(0) && maxBorrowable.amount.eq(0)) {
30802
+ logger.verbose(`${this.getTag()}::_getAvnuDepositSwapLegCall maxBorrowable is 0, skipping`);
30803
+ return void 0;
30804
+ } else if (debtAmount.gt(0) && maxBorrowable.amount.gt(0)) {
30805
+ debtAmount = maxBorrowable.amount.minimum(debtAmount);
30806
+ const newDebtUSDValue = debtAmount.multipliedBy(debtPrice);
30807
+ const totalCollateralRequired = HealthFactorMath.getCollateralRequired(
30808
+ debtAmount.plus(existingDebtInfo.amount),
30809
+ debtPrice,
30810
+ params.minHF,
30811
+ legLTV,
30812
+ collateralPrice,
30813
+ this.asset()
30814
+ );
30815
+ newDepositAmount = totalCollateralRequired.minus(existingCollateralInfo.amount);
30816
+ if (newDepositAmount.lt(0)) {
30817
+ throw new Error(`${this.getTag()}::_getAvnuDepositSwapLegCall newDepositAmount is less than 0, newDepositAmount: ${newDepositAmount}, totalCollateralRequired: ${totalCollateralRequired}, existingCollateralInfo.amount: ${existingCollateralInfo.amount}`);
30818
+ }
30819
+ if (newDebtUSDValue.toNumber() < 100) {
30820
+ logger.verbose(`${this.getTag()}::_getAvnuDepositSwapLegCall newDebtUSDValue is less than 100, skipping`);
30821
+ return void 0;
30822
+ }
30823
+ }
30350
30824
  logger.verbose(`${this.getTag()}::_getAvnuDepositSwapLegCall debtAmount: ${debtAmount}`);
30351
30825
  if (debtAmount.lt(0)) {
30352
30826
  const lstDEXPrice = await this.getLSTDexPrice();
@@ -30358,32 +30832,34 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30358
30832
  assert(calls.length == 1, `Expected 1 call for unwind, got ${calls.length}`);
30359
30833
  return calls[0];
30360
30834
  }
30835
+ console.log(`debtAmount`, debtAmount.toWei(), params.leg1DepositAmount.toWei());
30361
30836
  const STEP0 = "approve_token1" /* APPROVE_TOKEN1 */;
30362
30837
  const manage0Info = this.getProofs(STEP0);
30363
30838
  const manageCall0 = manage0Info.callConstructor({
30364
- amount: params.leg1DepositAmount
30839
+ amount: newDepositAmount
30365
30840
  });
30366
- const STEP1 = "vesu_leg1" /* VESU_LEG1 */;
30841
+ const STEP1 = getVesuLegId("vesu_leg1" /* VESU_LEG1 */, vesuAdapter.config.debt.symbol);
30367
30842
  const manage1Info = this.getProofs(STEP1);
30368
30843
  const manageCall1 = manage1Info.callConstructor(VesuAdapter.getDefaultModifyPositionCallParams({
30369
- collateralAmount: params.leg1DepositAmount,
30844
+ collateralAmount: newDepositAmount,
30370
30845
  isAddCollateral: params.isDeposit,
30371
30846
  debtAmount,
30372
30847
  isBorrow: params.isDeposit
30373
30848
  }));
30849
+ console.log(`manageCall1`, manageCall1.call, debtAmount.toWei(), newDepositAmount.toWei());
30374
30850
  const proofIds = [STEP0, STEP1];
30375
30851
  const manageCalls = [manageCall0, manageCall1];
30376
30852
  if (debtAmount.gt(0)) {
30377
- const STEP2 = "avnu_multiply_approve_deposit" /* AVNU_MULTIPLY_APPROVE_DEPOSIT */;
30853
+ const STEP2 = getAvnuManageIDs("avnu_mul_approve_dep" /* AVNU_MULTIPLY_APPROVE_DEPOSIT */, vesuAdapter.config.debt.symbol);
30378
30854
  const manage2Info = this.getProofs(STEP2);
30379
30855
  const manageCall2 = manage2Info.callConstructor({
30380
30856
  amount: debtAmount
30381
30857
  });
30382
- const debtTokenInfo = vesuAdapter1.config.debt;
30858
+ const debtTokenInfo2 = vesuAdapter.config.debt;
30383
30859
  const lstTokenInfo = this.asset();
30384
30860
  const avnuModule = new AvnuWrapper();
30385
30861
  const quote = await avnuModule.getQuotes(
30386
- debtTokenInfo.address.address,
30862
+ debtTokenInfo2.address.address,
30387
30863
  lstTokenInfo.address.address,
30388
30864
  debtAmount.toWei(),
30389
30865
  this.metadata.additionalInfo.vaultAllocator.address
@@ -30399,7 +30875,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30399
30875
  minAmountWei
30400
30876
  );
30401
30877
  logger.verbose(`${this.getTag()}::_getAvnuDepositSwapLegCall swapInfo: ${JSON.stringify(swapInfo)}`);
30402
- const STEP3 = "avnu_multiply_swap_deposit" /* AVNU_MULTIPLY_SWAP_DEPOSIT */;
30878
+ const STEP3 = getAvnuManageIDs("avnu_mul_swap_dep" /* AVNU_MULTIPLY_SWAP_DEPOSIT */, vesuAdapter.config.debt.symbol);
30403
30879
  const manage3Info = this.getProofs(STEP3);
30404
30880
  const manageCall3 = manage3Info.callConstructor({
30405
30881
  props: swapInfo
@@ -30417,7 +30893,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30417
30893
  const manageCall4 = manage4Info.callConstructor({
30418
30894
  amount: minAmount
30419
30895
  });
30420
- const STEP5 = "vesu_leg1" /* VESU_LEG1 */;
30896
+ const STEP5 = getVesuLegId("vesu_leg1" /* VESU_LEG1 */, vesuAdapter.config.debt.symbol);
30421
30897
  const manage5Info = this.getProofs(STEP5);
30422
30898
  const manageCall5 = manage5Info.callConstructor(VesuAdapter.getDefaultModifyPositionCallParams({
30423
30899
  collateralAmount: minAmount,
@@ -30434,28 +30910,41 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30434
30910
  }
30435
30911
  // todo unwind or not deposit when the yield is bad.
30436
30912
  async getLSTMultiplierRebalanceCall() {
30437
- const positions = await this.getVaultPositions();
30438
- assert(positions.length == 3, "Rebalance call is only supported for 3 positions");
30913
+ let shouldRebalance = false;
30914
+ const calls = [];
30915
+ const allVesuAdapters = this.getVesuAdapters().filter((vesuAdapter) => vesuAdapter.config.debt.symbol === "LBTC");
30916
+ for (const vesuAdapter of allVesuAdapters) {
30917
+ const call = await this._getLSTMultiplierRebalanceCall(vesuAdapter);
30918
+ if (call.shouldRebalance && call.manageCall) {
30919
+ shouldRebalance = true;
30920
+ calls.push({ vesuAdapter, manageCall: call.manageCall });
30921
+ }
30922
+ }
30923
+ return { shouldRebalance, manageCalls: calls };
30924
+ }
30925
+ async _getLSTMultiplierRebalanceCall(vesuAdapter) {
30926
+ const positions = await vesuAdapter.getPositions(this.config);
30927
+ assert(positions.length == 2, "Rebalance call is only supported for 2 positions");
30439
30928
  const existingCollateralInfo = positions[0];
30440
30929
  const existingDebtInfo = positions[1];
30441
- const unusedBalance = positions[2];
30442
- const [healthFactor] = await this.getVesuHealthFactors();
30443
- const [vesuAdapter1] = this.getVesuAdapters();
30444
- const legLTV = await vesuAdapter1.getLTVConfig(this.config);
30445
- const collateralisation = await vesuAdapter1.getCollateralization(this.config);
30446
- logger.debug(`${this.getTag()}::getVesuMultiplyCall existingCollateralInfo: ${JSON.stringify(existingCollateralInfo)},
30930
+ const unusedBalance = await this.getUnusedBalance();
30931
+ const healthFactor = await vesuAdapter.getHealthFactor();
30932
+ const collateralisation = await vesuAdapter.getCollateralization(this.config);
30933
+ logger.debug(`${this.getTag()}::getVesuMultiplyCall::${vesuAdapter.config.debt.symbol} existingCollateralInfo: ${JSON.stringify(existingCollateralInfo)},
30447
30934
  existingDebtInfo: ${JSON.stringify(existingDebtInfo)}, collateralisation: ${JSON.stringify(collateralisation)}`);
30448
30935
  const collateralPrice = collateralisation[0].usdValue > 0 ? collateralisation[0].usdValue / existingCollateralInfo.amount.toNumber() : 1;
30449
30936
  const debtPrice = collateralisation[1].usdValue > 0 ? collateralisation[1].usdValue / existingDebtInfo.amount.toNumber() : 1;
30450
30937
  logger.debug(`${this.getTag()}::getVesuMultiplyCall collateralPrice: ${collateralPrice}, debtPrice: ${debtPrice}`);
30938
+ logger.debug(`${this.getTag()}::getVesuMultiplyCall healthFactor: ${healthFactor}`);
30451
30939
  const isHFTooLow = healthFactor < this.metadata.additionalInfo.minHealthFactor;
30452
30940
  const isHFTooHigh = healthFactor > this.metadata.additionalInfo.targetHealthFactor + 0.05;
30453
- if (isHFTooLow || isHFTooHigh) {
30941
+ if (isHFTooLow || isHFTooHigh || 1) {
30454
30942
  const manageCall = await this._getAvnuDepositSwapLegCall({
30455
30943
  isDeposit: true,
30456
30944
  leg1DepositAmount: unusedBalance.amount,
30457
- minHF: 1.02
30945
+ minHF: 1.02,
30458
30946
  // todo, shouldnt use this 1.02 HF, if there isn;t more looping left.
30947
+ vesuAdapter
30459
30948
  });
30460
30949
  return { shouldRebalance: true, manageCall };
30461
30950
  } else {
@@ -30488,7 +30977,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30488
30977
  async _getMinOutputAmountLSTBuy(amountInUnderlying) {
30489
30978
  const lstTruePrice = await this.getLSTExchangeRate();
30490
30979
  const minOutputAmount = amountInUnderlying.dividedBy(lstTruePrice).multipliedBy(0.99979);
30491
- return minOutputAmount;
30980
+ return new Web3Number(minOutputAmount.toString(), this.asset().decimals);
30492
30981
  }
30493
30982
  async _getMinOutputAmountLSTSell(amountInLST) {
30494
30983
  const lstTruePrice = await this.getLSTExchangeRate();
@@ -30545,21 +31034,52 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30545
31034
  const vesuAdapter1 = this.getVesuSameTokenAdapter();
30546
31035
  return vesuAdapter1.config.debt;
30547
31036
  }
30548
- async getMaxBorrowableAmount() {
31037
+ async getMaxBorrowableAmount(params = { isAPYComputation: false }) {
30549
31038
  const vesuAdapters = this.getVesuAdapters();
30550
31039
  let netMaxBorrowableAmount = Web3Number.fromWei("0", this.getLSTUnderlyingTokenInfo().decimals);
30551
31040
  const maxBorrowables = [];
30552
- const lstAPY = await this.getLSTAPR(this.getLSTUnderlyingTokenInfo().address);
30553
- const maxInterestRate = lstAPY * 0.8;
30554
31041
  for (const vesuAdapter of vesuAdapters) {
30555
- const maxBorrowableAmount = await vesuAdapter.getMaxBorrowableByInterestRate(this.config, vesuAdapter.config.debt, maxInterestRate);
30556
- const debtCap = await vesuAdapter.getDebtCap(this.config);
30557
- maxBorrowables.push({ amount: maxBorrowableAmount.minimum(debtCap), borrowableAsset: vesuAdapter.config.debt });
31042
+ maxBorrowables.push(await this.getMaxBorrowableAmountByVesuAdapter(vesuAdapter, params.isAPYComputation));
30558
31043
  }
30559
31044
  maxBorrowables.sort((a, b) => b.amount.toNumber() - a.amount.toNumber());
30560
31045
  netMaxBorrowableAmount = maxBorrowables.reduce((acc, curr) => acc.plus(curr.amount), Web3Number.fromWei("0", this.getLSTUnderlyingTokenInfo().decimals));
30561
31046
  return { netMaxBorrowableAmount, maxBorrowables };
30562
31047
  }
31048
+ // recursively, using binary search computes max swappable.
31049
+ // @dev assumes 1 token of from == 1 token of to
31050
+ async getMaxSwappableWithMaxSlippage(fromToken, toToken, maxSlippage, maxAmount) {
31051
+ const output = await findMaxInputWithSlippage({
31052
+ apiGetOutput: async (inputAmount) => {
31053
+ const ekuboQuoter = new EkuboQuoter(this.config);
31054
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
31055
+ const quote = await ekuboQuoter.getQuote(fromToken.address.address, toToken.address.address, new Web3Number(inputAmount.toFixed(9), fromToken.decimals));
31056
+ return Web3Number.fromWei(quote.total_calculated.toString(), toToken.decimals).toNumber();
31057
+ },
31058
+ maxInput: maxAmount.toNumber(),
31059
+ maxSlippagePercent: maxSlippage,
31060
+ tolerance: 1e-3,
31061
+ referenceRate: 1
31062
+ });
31063
+ return new Web3Number(output.optimalInput, fromToken.decimals);
31064
+ }
31065
+ async getMaxBorrowableAmountByVesuAdapter(vesuAdapter, isAPYComputation) {
31066
+ const lstAPY = await this.getLSTAPR(this.getLSTUnderlyingTokenInfo().address);
31067
+ const maxInterestRate = lstAPY * 0.8;
31068
+ const maxBorrowableAmount = await vesuAdapter.getMaxBorrowableByInterestRate(this.config, vesuAdapter.config.debt, maxInterestRate);
31069
+ const debtCap = await vesuAdapter.getDebtCap(this.config);
31070
+ const maxBorrowable = maxBorrowableAmount.minimum(debtCap).multipliedBy(0.999);
31071
+ if (vesuAdapter.config.debt.address.eq(this.getLSTUnderlyingTokenInfo().address) || isAPYComputation) {
31072
+ return { amount: maxBorrowable, dexSwappableAmount: maxBorrowable, maxBorrowableAmount: maxBorrowable, borrowableAsset: vesuAdapter.config.debt };
31073
+ }
31074
+ try {
31075
+ const maxSwappable = await this.getMaxSwappableWithMaxSlippage(vesuAdapter.config.debt, this.getLSTUnderlyingTokenInfo(), 2e-4, maxBorrowable);
31076
+ return { amount: maxBorrowable.minimum(maxSwappable), dexSwappableAmount: maxSwappable, maxBorrowableAmount: maxBorrowable, borrowableAsset: vesuAdapter.config.debt };
31077
+ } catch (error) {
31078
+ logger.warn(`${this.getTag()}: Failed to get max swappable: ${error}`);
31079
+ const maxSwappable = Web3Number.fromWei("0", vesuAdapter.config.debt.decimals);
31080
+ return { amount: maxBorrowable.minimum(maxSwappable), dexSwappableAmount: maxSwappable, maxBorrowableAmount: maxBorrowable, borrowableAsset: vesuAdapter.config.debt };
31081
+ }
31082
+ }
30563
31083
  // todo how much to unwind to get back healthy APY zone again
30564
31084
  // if net APY < LST APR + 0.5%, we need to unwind to get back to LST APR + 1% atleast or 0 vesu position
30565
31085
  // For xSTRK, simply deposit in Vesu if looping is not viable
@@ -30583,7 +31103,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30583
31103
  // todo undo this
30584
31104
  async netAPY() {
30585
31105
  const unusedBalance = await this.getUnusedBalance();
30586
- const maxNewDeposits = await this.maxNewDeposits();
31106
+ const maxNewDeposits = await this.maxNewDeposits({ isAPYComputation: true });
30587
31107
  const lstAPY = await this.getLSTAPR(this.getLSTUnderlyingTokenInfo().address);
30588
31108
  if (maxNewDeposits * 1.5 < unusedBalance.amount.toNumber()) {
30589
31109
  logger.verbose(`${this.getTag()}::netAPY: unused balance is > max servicable from loan, lstAPY: ${lstAPY}`);
@@ -30600,8 +31120,8 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30600
31120
  return output;
30601
31121
  }
30602
31122
  }
30603
- async maxNewDeposits() {
30604
- const maxBorrowableAmounts = await this.getMaxBorrowableAmount();
31123
+ async maxNewDeposits(params = { isAPYComputation: false }) {
31124
+ const maxBorrowableAmounts = await this.getMaxBorrowableAmount(params);
30605
31125
  let ltv = void 0;
30606
31126
  for (let adapter of this.getVesuAdapters()) {
30607
31127
  const maxBorrowableAmount = maxBorrowableAmounts.maxBorrowables.find((b) => b.borrowableAsset.address.eq(adapter.config.debt.address))?.amount;
@@ -30704,7 +31224,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30704
31224
  const manageCall2 = manage2Info.callConstructor({
30705
31225
  delegation: true
30706
31226
  });
30707
- const STEP3_ID = "multiply_vesu" /* MULTIPLY_VESU */;
31227
+ const STEP3_ID = getVesuLegId("multiply_vesu" /* MULTIPLY_VESU */, vesuAdapter1.config.debt.symbol);
30708
31228
  const manage3Info = this.getProofs(STEP3_ID);
30709
31229
  const multiplyParams = params.isIncrease ? {
30710
31230
  isIncrease: true,
@@ -30788,6 +31308,12 @@ function VaultDescription(lstSymbol, underlyingSymbol) {
30788
31308
  function getDescription2(tokenSymbol, underlyingSymbol) {
30789
31309
  return VaultDescription(tokenSymbol, underlyingSymbol);
30790
31310
  }
31311
+ function getAvnuManageIDs(baseID, debtTokenSymbol) {
31312
+ return `${baseID}_${debtTokenSymbol.toLowerCase()}`;
31313
+ }
31314
+ function getVesuLegId(baseID, debtTokenSymbol) {
31315
+ return `${baseID}_${debtTokenSymbol.toLowerCase()}`;
31316
+ }
30791
31317
  function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
30792
31318
  vaultSettings.leafAdapters = [];
30793
31319
  const lstToken = Global.getDefaultTokens().find((token) => token.symbol === lstSymbol);
@@ -30797,7 +31323,7 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
30797
31323
  collateral: lstToken,
30798
31324
  debt: underlyingToken,
30799
31325
  vaultAllocator: vaultSettings.vaultAllocator,
30800
- id: "vesu_leg1" /* VESU_LEG1 */
31326
+ id: getVesuLegId("vesu_leg1" /* VESU_LEG1 */, underlyingToken.symbol)
30801
31327
  });
30802
31328
  const commonAdapter = new CommonAdapter({
30803
31329
  manager: vaultSettings.manager,
@@ -30806,25 +31332,39 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
30806
31332
  vaultAddress: vaultSettings.vaultAddress,
30807
31333
  vaultAllocator: vaultSettings.vaultAllocator
30808
31334
  });
30809
- const { isV2, addr: poolAddr } = getVesuSingletonAddress(pool1);
30810
- const VESU_MULTIPLY = isV2 ? vesuAdapterLST.VESU_MULTIPLY : vesuAdapterLST.VESU_MULTIPLY_V1;
30811
- vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, VESU_MULTIPLY, "multiple_approve" /* MULTIPLE_APPROVE */).bind(commonAdapter));
30812
- vaultSettings.leafAdapters.push(vesuAdapterLST.getMultiplyAdapter("multiply_vesu" /* MULTIPLY_VESU */).bind(vesuAdapterLST));
30813
- vaultSettings.leafAdapters.push(vesuAdapterLST.getVesuModifyDelegationAdapter("switch_delegation_on" /* SWITCH_DELEGATION_ON */).bind(vesuAdapterLST));
30814
- vaultSettings.leafAdapters.push(vesuAdapterLST.getVesuModifyDelegationAdapter("switch_delegation_off" /* SWITCH_DELEGATION_OFF */).bind(vesuAdapterLST));
30815
31335
  vaultSettings.adapters.push(...[{
30816
- id: "vesu_leg1_adapter" /* VESU_LEG1 */,
31336
+ id: getVesuLegId("vesu_leg1" /* VESU_LEG1 */, underlyingToken.symbol),
30817
31337
  adapter: vesuAdapterLST
30818
31338
  }, {
30819
31339
  id: "common_adapter" /* COMMON */,
30820
31340
  adapter: commonAdapter
30821
31341
  }]);
30822
- vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(underlyingToken.address, AVNU_EXCHANGE, "avnu_multiply_approve_deposit" /* AVNU_MULTIPLY_APPROVE_DEPOSIT */).bind(commonAdapter));
30823
- vaultSettings.leafAdapters.push(commonAdapter.getAvnuAdapter(underlyingToken.address, lstToken.address, "avnu_multiply_swap_deposit" /* AVNU_MULTIPLY_SWAP_DEPOSIT */, false).bind(commonAdapter));
30824
- vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, AVNU_EXCHANGE, "avnu_multiply_approve_withdraw" /* AVNU_MULTIPLY_APPROVE_WITHDRAW */).bind(commonAdapter));
30825
- vaultSettings.leafAdapters.push(commonAdapter.getAvnuAdapter(lstToken.address, underlyingToken.address, "avnu_multiply_swap_withdraw" /* AVNU_MULTIPLY_SWAP_WITHDRAW */, false).bind(commonAdapter));
30826
- vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, poolAddr, "approve_token1" /* APPROVE_TOKEN1 */).bind(commonAdapter));
30827
- vaultSettings.leafAdapters.push(vesuAdapterLST.getModifyPosition.bind(vesuAdapterLST));
31342
+ const { isV2, addr: poolAddr } = getVesuSingletonAddress(pool1);
31343
+ const VESU_MULTIPLY = isV2 ? vesuAdapterLST.VESU_MULTIPLY : vesuAdapterLST.VESU_MULTIPLY_V1;
31344
+ vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, VESU_MULTIPLY, "multiple_approve" /* MULTIPLE_APPROVE */).bind(commonAdapter));
31345
+ vaultSettings.leafAdapters.push(vesuAdapterLST.getVesuModifyDelegationAdapter("switch_delegation_on" /* SWITCH_DELEGATION_ON */).bind(vesuAdapterLST));
31346
+ vaultSettings.leafAdapters.push(vesuAdapterLST.getVesuModifyDelegationAdapter("switch_delegation_off" /* SWITCH_DELEGATION_OFF */).bind(vesuAdapterLST));
31347
+ vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, AVNU_EXCHANGE, "avnu_mul_approve_withdr" /* AVNU_MULTIPLY_APPROVE_WITHDRAW */).bind(commonAdapter));
31348
+ for (let borrowableAsset of vaultSettings.borrowable_assets) {
31349
+ const debtAsset = borrowableAsset;
31350
+ const approve_debt_token_id = getAvnuManageIDs("avnu_mul_approve_dep" /* AVNU_MULTIPLY_APPROVE_DEPOSIT */, debtAsset.symbol);
31351
+ const swap_debt_token_id = getAvnuManageIDs("avnu_mul_swap_dep" /* AVNU_MULTIPLY_SWAP_DEPOSIT */, debtAsset.symbol);
31352
+ const swap_lst_token_id = getAvnuManageIDs("avnu_mul_swap_withdr" /* AVNU_MULTIPLY_SWAP_WITHDRAW */, debtAsset.symbol);
31353
+ vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(debtAsset.address, AVNU_EXCHANGE, approve_debt_token_id).bind(commonAdapter));
31354
+ vaultSettings.leafAdapters.push(commonAdapter.getAvnuAdapter(debtAsset.address, lstToken.address, swap_debt_token_id, false).bind(commonAdapter));
31355
+ vaultSettings.leafAdapters.push(commonAdapter.getAvnuAdapter(lstToken.address, debtAsset.address, swap_lst_token_id, false).bind(commonAdapter));
31356
+ const vesuAdapter = new VesuAdapter({
31357
+ poolId: pool1,
31358
+ collateral: lstToken,
31359
+ debt: debtAsset,
31360
+ vaultAllocator: vaultSettings.vaultAllocator,
31361
+ id: getVesuLegId("vesu_leg1" /* VESU_LEG1 */, debtAsset.symbol)
31362
+ });
31363
+ vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, poolAddr, "approve_token1" /* APPROVE_TOKEN1 */).bind(commonAdapter));
31364
+ vaultSettings.leafAdapters.push(vesuAdapter.getModifyPosition.bind(vesuAdapter));
31365
+ const multiplID = getVesuLegId("multiply_vesu" /* MULTIPLY_VESU */, debtAsset.symbol);
31366
+ vaultSettings.leafAdapters.push(vesuAdapter.getMultiplyAdapter(multiplID).bind(vesuAdapter));
31367
+ }
30828
31368
  vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, vaultSettings.vaultAddress, "approve_bring_liquidity" /* APPROVE_BRING_LIQUIDITY */).bind(commonAdapter));
30829
31369
  vaultSettings.leafAdapters.push(commonAdapter.getBringLiquidityAdapter("bring_liquidity" /* BRING_LIQUIDITY */).bind(commonAdapter));
30830
31370
  vaultSettings.leafAdapters.push(vesuAdapterLST.getDefispringRewardsAdapter("defispring_rewards" /* DEFISPRING_REWARDS */).bind(vesuAdapterLST));
@@ -30902,7 +31442,8 @@ var hyperxSTRK = {
30902
31442
  adapters: [],
30903
31443
  targetHealthFactor: 1.1,
30904
31444
  minHealthFactor: 1.05,
30905
- borrowable_assets: Global.getDefaultTokens().filter((token) => token.symbol === "STRK")
31445
+ borrowable_assets: Global.getDefaultTokens().filter((token) => token.symbol === "STRK"),
31446
+ underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "STRK")
30906
31447
  };
30907
31448
  var hyperxWBTC = {
30908
31449
  vaultAddress: ContractAddr.from("0x2da9d0f96a46b453f55604313785dc866424240b1c6811d13bef594343db818"),
@@ -30914,7 +31455,8 @@ var hyperxWBTC = {
30914
31455
  adapters: [],
30915
31456
  targetHealthFactor: 1.1,
30916
31457
  minHealthFactor: 1.05,
30917
- borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset))
31458
+ borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
31459
+ underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "WBTC")
30918
31460
  };
30919
31461
  var hyperxtBTC = {
30920
31462
  vaultAddress: ContractAddr.from("0x47d5f68477e5637ce0e56436c6b5eee5a354e6828995dae106b11a48679328"),
@@ -30926,7 +31468,8 @@ var hyperxtBTC = {
30926
31468
  adapters: [],
30927
31469
  targetHealthFactor: 1.1,
30928
31470
  minHealthFactor: 1.05,
30929
- borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset))
31471
+ borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
31472
+ underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "tBTC")
30930
31473
  };
30931
31474
  var hyperxsBTC = {
30932
31475
  vaultAddress: ContractAddr.from("0x437ef1e7d0f100b2e070b7a65cafec0b2be31b0290776da8b4112f5473d8d9"),
@@ -30938,7 +31481,8 @@ var hyperxsBTC = {
30938
31481
  adapters: [],
30939
31482
  targetHealthFactor: 1.1,
30940
31483
  minHealthFactor: 1.05,
30941
- borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset))
31484
+ borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
31485
+ underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "solvBTC")
30942
31486
  };
30943
31487
  var hyperxLBTC = {
30944
31488
  vaultAddress: ContractAddr.from("0x64cf24d4883fe569926419a0569ab34497c6956a1a308fa883257f7486d7030"),
@@ -30950,7 +31494,8 @@ var hyperxLBTC = {
30950
31494
  adapters: [],
30951
31495
  targetHealthFactor: 1.1,
30952
31496
  minHealthFactor: 1.05,
30953
- borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset))
31497
+ borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
31498
+ underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "LBTC")
30954
31499
  };
30955
31500
  function getInvestmentSteps(lstSymbol, underlyingSymbol) {
30956
31501
  return [
@@ -30993,6 +31538,7 @@ var HyperLSTStrategies = [
30993
31538
  getStrategySettings("xLBTC", "LBTC", hyperxLBTC, false)
30994
31539
  ];
30995
31540
  export {
31541
+ APYType,
30996
31542
  AUMTypes,
30997
31543
  AVNU_EXCHANGE,
30998
31544
  AVNU_MIDDLEWARE,