@strkfarm/sdk 1.1.38 → 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.
package/dist/index.mjs CHANGED
@@ -315,6 +315,25 @@ var defaultTokens = [{
315
315
  priceProxySymbol: "WBTC",
316
316
  priceCheckAmount: 1e-4
317
317
  // 112000 * 0.0001 = $11.2
318
+ }, {
319
+ name: "mRe7BTC",
320
+ symbol: "mRe7BTC",
321
+ logo: "https://imagedelivery.net/0xPAQaDtnQhBs8IzYRIlNg/3a62ecee-1e58-45d3-9862-3ce90dff1900/logo",
322
+ address: ContractAddr.from("0x4e4fb1a9ca7e84bae609b9dc0078ad7719e49187ae7e425bb47d131710eddac"),
323
+ decimals: 18,
324
+ coingeckId: void 0,
325
+ displayDecimals: 6,
326
+ priceCheckAmount: 1e-4
327
+ // 112000 * 0.0001 = $11.2
328
+ }, {
329
+ name: "mRe7YIELD",
330
+ symbol: "mRe7YIELD",
331
+ logo: "https://midas.app/assets/mre7-BcOOHm7i.svg",
332
+ address: ContractAddr.from("0x4be8945e61dc3e19ebadd1579a6bd53b262f51ba89e6f8b0c4bc9a7e3c633fc"),
333
+ decimals: 18,
334
+ coingeckId: void 0,
335
+ displayDecimals: 2,
336
+ priceCheckAmount: 100
318
337
  }];
319
338
  var tokens = defaultTokens;
320
339
  var _Global = class _Global {
@@ -2208,16 +2227,16 @@ var AvnuWrapper = class _AvnuWrapper {
2208
2227
  };
2209
2228
  return swapInfo;
2210
2229
  }
2211
- static buildZeroSwap(tokenToSell, address) {
2230
+ static buildZeroSwap(tokenToSell, beneficiary, tokenToBuy = tokenToSell) {
2212
2231
  return {
2213
2232
  token_from_address: tokenToSell.address,
2214
2233
  token_from_amount: uint256.bnToUint256(0),
2215
- token_to_address: tokenToSell.address,
2234
+ token_to_address: tokenToBuy.address,
2216
2235
  token_to_amount: uint256.bnToUint256(0),
2217
2236
  token_to_min_amount: uint256.bnToUint256(0),
2218
- beneficiary: address,
2237
+ beneficiary,
2219
2238
  integrator_fee_amount_bps: 0,
2220
- integrator_fee_recipient: address,
2239
+ integrator_fee_recipient: beneficiary,
2221
2240
  routes: []
2222
2241
  };
2223
2242
  }
@@ -4018,21 +4037,20 @@ var Harvests = class _Harvests {
4018
4037
  const rewards = await this.getHarvests(addr);
4019
4038
  if (rewards.length == 0) return [];
4020
4039
  const unClaimed = [];
4021
- const cls = await this.config.provider.getClassAt(rewards[0].rewardsContract.address);
4022
- for (let reward of rewards) {
4023
- const contract = new Contract4({ abi: cls.abi, address: reward.rewardsContract.address, providerOrAccount: this.config.provider });
4024
- const isClaimed = await contract.call("is_claimed", [reward.claim.id]);
4025
- logger.verbose(`${_Harvests.name}: isClaimed: ${isClaimed}`);
4026
- if (isClaimed) {
4027
- return unClaimed;
4028
- }
4029
- const bal = await new ERC20(this.config).balanceOf(reward.token, reward.rewardsContract.address, 18);
4030
- if (bal.lessThan(reward.claim.amount)) {
4031
- logger.verbose(`${_Harvests.name}: balance: ${bal.toString()}, amount: ${reward.claim.amount.toString()}`);
4032
- continue;
4033
- }
4034
- unClaimed.unshift(reward);
4040
+ const reward = rewards.sort((a, b) => b.endDate.getTime() - a.endDate.getTime())[0];
4041
+ const cls = await this.config.provider.getClassAt(reward.rewardsContract.address);
4042
+ const contract = new Contract4({ abi: cls.abi, address: reward.rewardsContract.address, providerOrAccount: this.config.provider });
4043
+ const isClaimed = await contract.call("is_claimed", [reward.claim.id]);
4044
+ logger.verbose(`${_Harvests.name}: isClaimed: ${isClaimed}`);
4045
+ if (isClaimed) {
4046
+ return unClaimed;
4035
4047
  }
4048
+ const bal = await new ERC20(this.config).balanceOf(reward.token, reward.rewardsContract.address, 18);
4049
+ if (bal.lessThan(reward.claim.amount)) {
4050
+ logger.verbose(`${_Harvests.name}: balance: ${bal.toString()}, amount: ${reward.claim.amount.toString()}`);
4051
+ return unClaimed;
4052
+ }
4053
+ unClaimed.unshift(reward);
4036
4054
  return unClaimed;
4037
4055
  }
4038
4056
  };
@@ -15299,6 +15317,91 @@ var apolloClient = new ApolloClient({
15299
15317
  });
15300
15318
  var apollo_client_default = apolloClient;
15301
15319
 
15320
+ // src/utils/math-utils.ts
15321
+ async function binarySearch(lowWei, highWei, callback) {
15322
+ while (lowWei <= highWei) {
15323
+ const diff = highWei - lowWei;
15324
+ const mid = lowWei + diff / 2n;
15325
+ const result = await callback(mid);
15326
+ if (result === "found") {
15327
+ return mid;
15328
+ } else if (result == "retry") {
15329
+ } else if (result === "go_low") {
15330
+ highWei = mid - BigInt(1);
15331
+ } else {
15332
+ lowWei = mid + BigInt(1);
15333
+ }
15334
+ }
15335
+ return null;
15336
+ }
15337
+ async function findMaxInputWithSlippage(options) {
15338
+ const {
15339
+ apiGetOutput,
15340
+ maxInput,
15341
+ maxSlippagePercent,
15342
+ tolerance,
15343
+ minInput = 0,
15344
+ referenceAmountMultiplier = 1e-3,
15345
+ referenceRate = 0
15346
+ } = options;
15347
+ let apiCalls = 0;
15348
+ if (!referenceRate && !referenceAmountMultiplier) {
15349
+ throw new Error("One of referenceRate or referenceAmountMultiplier must be provided");
15350
+ }
15351
+ let _referenceRate = referenceRate;
15352
+ if (!_referenceRate) {
15353
+ const smallAmount = maxInput * referenceAmountMultiplier;
15354
+ const referenceOutput = await apiGetOutput(smallAmount);
15355
+ apiCalls++;
15356
+ _referenceRate = referenceOutput / smallAmount;
15357
+ }
15358
+ async function checkSlippage(inputAmount) {
15359
+ const actualOutput = await apiGetOutput(inputAmount);
15360
+ apiCalls++;
15361
+ const expectedOutput = inputAmount * referenceRate;
15362
+ const slippage = (expectedOutput - actualOutput) / expectedOutput;
15363
+ logger.verbose(`findMaxInputWithSlippage::checkSlippage inputAmount: ${inputAmount}, actualOutput: ${actualOutput}, slippage: ${slippage}, maxSlippagePercent: ${maxSlippagePercent}`);
15364
+ return {
15365
+ acceptable: slippage <= maxSlippagePercent,
15366
+ slippage,
15367
+ output: actualOutput
15368
+ };
15369
+ }
15370
+ const maxCheck = await checkSlippage(maxInput);
15371
+ if (maxCheck.acceptable) {
15372
+ return {
15373
+ optimalInput: maxInput,
15374
+ actualOutput: maxCheck.output,
15375
+ actualSlippage: maxCheck.slippage,
15376
+ apiCallsUsed: apiCalls
15377
+ };
15378
+ }
15379
+ let left = minInput;
15380
+ let right = maxInput;
15381
+ let bestInput = minInput;
15382
+ let bestOutput = 0;
15383
+ let bestSlippage = 0;
15384
+ const convergenceThreshold = tolerance * maxInput;
15385
+ while (right - left > convergenceThreshold) {
15386
+ const mid = (left + right) / 2;
15387
+ const midCheck = await checkSlippage(mid);
15388
+ if (midCheck.acceptable) {
15389
+ bestInput = mid;
15390
+ bestOutput = midCheck.output;
15391
+ bestSlippage = midCheck.slippage;
15392
+ left = mid;
15393
+ } else {
15394
+ right = mid;
15395
+ }
15396
+ }
15397
+ return {
15398
+ optimalInput: bestInput,
15399
+ actualOutput: bestOutput,
15400
+ actualSlippage: bestSlippage,
15401
+ apiCallsUsed: apiCalls
15402
+ };
15403
+ }
15404
+
15302
15405
  // src/strategies/ekubo-cl-vault.tsx
15303
15406
  import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
15304
15407
  var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
@@ -16421,62 +16524,193 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
16421
16524
  logger.verbose(
16422
16525
  `${_EkuboCLVault.name}: harvest => Processing claim, isToken1: ${isToken1} amount: ${postFeeAmount.toWei()}`
16423
16526
  );
16424
- const token0Amt = isToken1 ? new Web3Number(0, token0Info.decimals) : postFeeAmount;
16425
- const token1Amt = isToken1 ? postFeeAmount : new Web3Number(0, token0Info.decimals);
16527
+ const isRewardTokenMatch = claim.token.eq(poolKey.token0) || claim.token.eq(poolKey.token1);
16528
+ if (isRewardTokenMatch) {
16529
+ const _callsFinal = await this._handleRewardAndVaultTokenMatchHarvest({
16530
+ acc,
16531
+ claim,
16532
+ isToken1,
16533
+ token0Info,
16534
+ token1Info,
16535
+ postFeeAmount,
16536
+ poolKey,
16537
+ bounds,
16538
+ maxIterations,
16539
+ priceRatioPrecision
16540
+ });
16541
+ calls.push(..._callsFinal);
16542
+ } else {
16543
+ const _callsFinal = await this._handleRewardAndVaultTokenMismatchHarvest({
16544
+ claim,
16545
+ token0Info,
16546
+ token1Info,
16547
+ postFeeAmount,
16548
+ poolKey,
16549
+ bounds,
16550
+ maxIterations,
16551
+ priceRatioPrecision,
16552
+ acc
16553
+ });
16554
+ calls.push(..._callsFinal);
16555
+ }
16556
+ }
16557
+ return calls;
16558
+ }
16559
+ /**
16560
+ * @description This funciton requires atleast one of the pool tokens to be reward token
16561
+ * i.e. STRK.
16562
+ * @param params
16563
+ */
16564
+ async _handleRewardAndVaultTokenMatchHarvest(params) {
16565
+ const { acc, claim, isToken1, token0Info, token1Info, postFeeAmount, poolKey, bounds, maxIterations, priceRatioPrecision } = params;
16566
+ const token0Amt = isToken1 ? new Web3Number(0, token0Info.decimals) : postFeeAmount;
16567
+ const token1Amt = isToken1 ? postFeeAmount : new Web3Number(0, token0Info.decimals);
16568
+ logger.verbose(
16569
+ `${_EkuboCLVault.name}: harvest => token0Amt: ${token0Amt.toString()}, token1Amt: ${token1Amt.toString()}`
16570
+ );
16571
+ const swapInfo = await this.getSwapInfoGivenAmounts(
16572
+ poolKey,
16573
+ token0Amt,
16574
+ token1Amt,
16575
+ bounds,
16576
+ maxIterations,
16577
+ priceRatioPrecision
16578
+ );
16579
+ swapInfo.token_to_address = token0Info.address.address;
16580
+ logger.verbose(
16581
+ `${_EkuboCLVault.name}: harvest => swapInfo: ${JSON.stringify(swapInfo)}`
16582
+ );
16583
+ logger.verbose(
16584
+ `${_EkuboCLVault.name}: harvest => claim: ${JSON.stringify(claim)}`
16585
+ );
16586
+ const harvestEstimateCall = async (swapInfo1) => {
16587
+ const swap1Amount = Web3Number.fromWei(
16588
+ uint2564.uint256ToBN(swapInfo1.token_from_amount).toString(),
16589
+ 18
16590
+ // cause its always STRK?
16591
+ ).minimum(
16592
+ postFeeAmount.toFixed(18)
16593
+ // cause always strk
16594
+ );
16595
+ swapInfo.token_from_amount = uint2564.bnToUint256(swap1Amount.toWei());
16596
+ swapInfo.token_to_min_amount = uint2564.bnToUint256(
16597
+ swap1Amount.multipliedBy(0).toWei()
16598
+ // placeholder
16599
+ );
16426
16600
  logger.verbose(
16427
- `${_EkuboCLVault.name}: harvest => token0Amt: ${token0Amt.toString()}, token1Amt: ${token1Amt.toString()}`
16601
+ `${_EkuboCLVault.name}: harvest => swap1Amount: ${swap1Amount}`
16428
16602
  );
16429
- const swapInfo = await this.getSwapInfoGivenAmounts(
16430
- poolKey,
16431
- token0Amt,
16432
- token1Amt,
16433
- bounds,
16434
- maxIterations,
16435
- priceRatioPrecision
16603
+ const remainingAmount = postFeeAmount.minus(swap1Amount).maximum(0);
16604
+ logger.verbose(
16605
+ `${_EkuboCLVault.name}: harvest => remainingAmount: ${remainingAmount}`
16436
16606
  );
16437
- swapInfo.token_to_address = token0Info.address.address;
16607
+ const swapInfo2 = {
16608
+ ...swapInfo,
16609
+ token_from_amount: uint2564.bnToUint256(remainingAmount.toWei())
16610
+ };
16611
+ swapInfo2.token_to_address = token1Info.address.address;
16438
16612
  logger.verbose(
16439
- `${_EkuboCLVault.name}: harvest => swapInfo: ${JSON.stringify(swapInfo)}`
16613
+ `${_EkuboCLVault.name}: harvest => swapInfo: ${JSON.stringify(
16614
+ swapInfo
16615
+ )}`
16440
16616
  );
16441
16617
  logger.verbose(
16442
- `${_EkuboCLVault.name}: harvest => claim: ${JSON.stringify(claim)}`
16618
+ `${_EkuboCLVault.name}: harvest => swapInfo2: ${JSON.stringify(
16619
+ swapInfo2
16620
+ )}`
16443
16621
  );
16444
- const harvestEstimateCall = async (swapInfo1) => {
16445
- const swap1Amount = Web3Number.fromWei(
16446
- uint2564.uint256ToBN(swapInfo1.token_from_amount).toString(),
16447
- 18
16448
- // cause its always STRK?
16449
- ).minimum(
16450
- postFeeAmount.toFixed(18)
16451
- // cause always strk
16452
- );
16453
- swapInfo.token_from_amount = uint2564.bnToUint256(swap1Amount.toWei());
16454
- swapInfo.token_to_min_amount = uint2564.bnToUint256(
16455
- swap1Amount.multipliedBy(0).toWei()
16456
- // placeholder
16457
- );
16458
- logger.verbose(
16459
- `${_EkuboCLVault.name}: harvest => swap1Amount: ${swap1Amount}`
16460
- );
16461
- const remainingAmount = postFeeAmount.minus(swap1Amount).maximum(0);
16462
- logger.verbose(
16463
- `${_EkuboCLVault.name}: harvest => remainingAmount: ${remainingAmount}`
16464
- );
16465
- const swapInfo2 = {
16466
- ...swapInfo,
16467
- token_from_amount: uint2564.bnToUint256(remainingAmount.toWei())
16468
- };
16469
- swapInfo2.token_to_address = token1Info.address.address;
16470
- logger.verbose(
16471
- `${_EkuboCLVault.name}: harvest => swapInfo: ${JSON.stringify(
16472
- swapInfo
16473
- )}`
16474
- );
16475
- logger.verbose(
16476
- `${_EkuboCLVault.name}: harvest => swapInfo2: ${JSON.stringify(
16477
- swapInfo2
16478
- )}`
16479
- );
16622
+ const calldata = [
16623
+ claim.rewardsContract.address,
16624
+ {
16625
+ id: claim.claim.id,
16626
+ amount: claim.claim.amount.toWei(),
16627
+ claimee: claim.claim.claimee.address
16628
+ },
16629
+ claim.proof.map((p) => num5.getDecimalString(p)),
16630
+ swapInfo,
16631
+ swapInfo2
16632
+ ];
16633
+ logger.verbose(
16634
+ `${_EkuboCLVault.name}: harvest => calldata: ${JSON.stringify(
16635
+ calldata
16636
+ )}`
16637
+ );
16638
+ return [this.contract.populate("harvest", calldata)];
16639
+ };
16640
+ const _callsFinal = await this.rebalanceIter(
16641
+ swapInfo,
16642
+ acc,
16643
+ harvestEstimateCall,
16644
+ claim.token.eq(poolKey.token0),
16645
+ 0,
16646
+ 0n,
16647
+ BigInt(postFeeAmount.toWei())
16648
+ // upper limit is the post fee amount
16649
+ );
16650
+ logger.verbose(
16651
+ `${_EkuboCLVault.name}: harvest => _callsFinal: ${JSON.stringify(
16652
+ _callsFinal
16653
+ )}`
16654
+ );
16655
+ return _callsFinal;
16656
+ }
16657
+ /**
16658
+ * @description This function handles harvesting of reward token that is not the same as any of the vault token
16659
+ * i.e. STRK is not part of vault tokens like BTC/ETH
16660
+ * @param params
16661
+ * @returns
16662
+ */
16663
+ async _handleRewardAndVaultTokenMismatchHarvest(params) {
16664
+ const { acc, claim, token0Info, token1Info, postFeeAmount, poolKey, bounds, maxIterations, priceRatioPrecision } = params;
16665
+ let token0Amt = postFeeAmount;
16666
+ const beneficiary = this.address.address;
16667
+ let harvestCall = null;
16668
+ harvestCall = await this.harvestMismatchEstimateCallFn({
16669
+ postFeeAmount,
16670
+ claim,
16671
+ token0Info,
16672
+ token1Info,
16673
+ acc
16674
+ });
16675
+ if (!harvestCall) {
16676
+ throw new Error("Harvest call not found");
16677
+ }
16678
+ return [harvestCall];
16679
+ }
16680
+ // given an amount (i.e. portion of reward to use to swap to token0), returns info on increasing or decreasing
16681
+ // amount for binary search
16682
+ async harvestMismatchEstimateCallFn(params) {
16683
+ const { postFeeAmount, claim, token0Info, token1Info, acc } = params;
16684
+ let harvestCall = null;
16685
+ const binarySearchCallbackFn = async (mid) => {
16686
+ const rewardPart2 = BigInt(postFeeAmount.toWei()) - mid;
16687
+ const avnuWrapper = new AvnuWrapper();
16688
+ const beneficiary = this.address.address;
16689
+ const quote1 = await avnuWrapper.getQuotes(
16690
+ claim.token.address,
16691
+ token0Info.address.address,
16692
+ mid.toString(),
16693
+ beneficiary
16694
+ );
16695
+ const swapInfo1 = await avnuWrapper.getSwapInfo(
16696
+ quote1,
16697
+ beneficiary,
16698
+ 0,
16699
+ beneficiary
16700
+ );
16701
+ const quote2 = await avnuWrapper.getQuotes(
16702
+ claim.token.address,
16703
+ token1Info.address.address,
16704
+ rewardPart2.toString(),
16705
+ beneficiary
16706
+ );
16707
+ const swapInfo2 = await avnuWrapper.getSwapInfo(
16708
+ quote2,
16709
+ beneficiary,
16710
+ 0,
16711
+ beneficiary
16712
+ );
16713
+ try {
16480
16714
  const calldata = [
16481
16715
  claim.rewardsContract.address,
16482
16716
  {
@@ -16485,34 +16719,24 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
16485
16719
  claimee: claim.claim.claimee.address
16486
16720
  },
16487
16721
  claim.proof.map((p) => num5.getDecimalString(p)),
16488
- swapInfo,
16722
+ swapInfo1,
16489
16723
  swapInfo2
16490
16724
  ];
16491
- logger.verbose(
16492
- `${_EkuboCLVault.name}: harvest => calldata: ${JSON.stringify(
16493
- calldata
16494
- )}`
16495
- );
16496
- return [this.contract.populate("harvest", calldata)];
16497
- };
16498
- const _callsFinal = await this.rebalanceIter(
16499
- swapInfo,
16500
- acc,
16501
- harvestEstimateCall,
16502
- claim.token.eq(poolKey.token0),
16503
- 0,
16504
- 0n,
16505
- BigInt(postFeeAmount.toWei())
16506
- // upper limit is the post fee amount
16507
- );
16508
- logger.verbose(
16509
- `${_EkuboCLVault.name}: harvest => _callsFinal: ${JSON.stringify(
16510
- _callsFinal
16511
- )}`
16512
- );
16513
- calls.push(..._callsFinal);
16514
- }
16515
- return calls;
16725
+ harvestCall = this.contract.populate("harvest", calldata);
16726
+ const gas = await acc.estimateInvokeFee(harvestCall);
16727
+ return "found";
16728
+ } catch (err) {
16729
+ console.error(err);
16730
+ if (err.message.includes("invalid token0 amount")) {
16731
+ return "go_low";
16732
+ } else if (err.message.includes("invalid token1 amount")) {
16733
+ return "go_high";
16734
+ }
16735
+ return "retry";
16736
+ }
16737
+ };
16738
+ await binarySearch(0n, BigInt(postFeeAmount.toWei()), binarySearchCallbackFn);
16739
+ return harvestCall;
16516
16740
  }
16517
16741
  async getInvestmentFlows() {
16518
16742
  const netYield = await this.netAPY();
@@ -19044,7 +19268,58 @@ function toBigInt(value) {
19044
19268
  }
19045
19269
 
19046
19270
  // src/strategies/universal-adapters/baseAdapter.ts
19271
+ var APYType = /* @__PURE__ */ ((APYType2) => {
19272
+ APYType2["BASE"] = "base";
19273
+ APYType2["REWARD"] = "reward";
19274
+ APYType2["LST"] = "lst";
19275
+ return APYType2;
19276
+ })(APYType || {});
19047
19277
  var BaseAdapter = class extends CacheClass {
19278
+ // readonly config: BaseAdapterConfig;
19279
+ // constructor(config: BaseAdapterConfig) {
19280
+ // super();
19281
+ // this.config = config;
19282
+ // }
19283
+ constructor() {
19284
+ super();
19285
+ }
19286
+ // /**
19287
+ // * Loop through all supported positions and return amount, usd value, remarks and apy for each
19288
+ // */
19289
+ // async getPositions(): Promise<PositionInfo[]> {
19290
+ // const results: PositionInfo[] = [];
19291
+ // for (const supported of this.config.supportedPositions) {
19292
+ // const amount = await this.getPosition(supported);
19293
+ // const usdValue = await this.getUSDValue(supported.asset, amount);
19294
+ // const apy = await this.getAPY(supported);
19295
+ // results.push({ amount, usdValue, apy });
19296
+ // }
19297
+ // return results;
19298
+ // }
19299
+ // /**
19300
+ // * Implemented by child adapters to compute APY for a given supported position
19301
+ // */
19302
+ // protected abstract getAPY(supportedPosition: SupportedPosition): Promise<PositionAPY>;
19303
+ // /**
19304
+ // * Implemented by child adapters to fetch amount for a given supported position
19305
+ // */
19306
+ // protected abstract getPosition(supportedPosition: SupportedPosition): Promise<Web3Number>;
19307
+ // /**
19308
+ // * Implemented by child adapters to calculate maximum deposit positions
19309
+ // * @param amount Optional amount in baseToken to deposit
19310
+ // */
19311
+ // protected abstract maxDeposit(amount?: Web3Number): Promise<PositionInfo[]>;
19312
+ // /**
19313
+ // * Implemented by child adapters to calculate maximum withdraw positions
19314
+ // */
19315
+ // protected abstract maxWithdraw(): Promise<PositionInfo[]>;
19316
+ // /**
19317
+ // * Uses pricer to convert an amount of an asset to USD value
19318
+ // */
19319
+ // protected async getUSDValue(asset: TokenInfo, amount: Web3Number): Promise<number> {
19320
+ // const priceInfo = await this.config.pricer.getPrice(asset.symbol);
19321
+ // return amount.toNumber() * priceInfo.price;
19322
+ // }
19048
19323
  constructSimpleLeafData(params, sanitizer = SIMPLE_SANITIZER) {
19049
19324
  const { id, target, method, packedArguments } = params;
19050
19325
  return {
@@ -19062,6 +19337,94 @@ var BaseAdapter = class extends CacheClass {
19062
19337
  ]
19063
19338
  };
19064
19339
  }
19340
+ // /**
19341
+ // * Implementor must provide target/method/packedArguments/sanitizer for deposit leaf construction
19342
+ // */
19343
+ // protected abstract _getDepositLeaf(): {
19344
+ // target: ContractAddr,
19345
+ // method: string,
19346
+ // packedArguments: bigint[],
19347
+ // sanitizer: ContractAddr,
19348
+ // id: string
19349
+ // }[];
19350
+ // /**
19351
+ // * Implementor must provide target/method/packedArguments/sanitizer for withdraw leaf construction
19352
+ // */
19353
+ // protected abstract _getWithdrawLeaf(): {
19354
+ // target: ContractAddr,
19355
+ // method: string,
19356
+ // packedArguments: bigint[],
19357
+ // sanitizer: ContractAddr,
19358
+ // id: string
19359
+ // }[];
19360
+ // /**
19361
+ // * Returns deposit leaf adapter using configured proof id
19362
+ // */
19363
+ // getDepositLeaf(): AdapterLeafType<T1> {
19364
+ // const leafConfigs = this._getDepositLeaf();
19365
+ // const leaves = leafConfigs.map(config => {
19366
+ // const { target, method, packedArguments, sanitizer, id } = config;
19367
+ // const leaf = this.constructSimpleLeafData({
19368
+ // id: id,
19369
+ // target,
19370
+ // method,
19371
+ // packedArguments
19372
+ // }, sanitizer);
19373
+ // return leaf;
19374
+ // });
19375
+ // return { leaves, callConstructor: this.getDepositCall.bind(this) as unknown as GenerateCallFn<T1> };
19376
+ // }
19377
+ // /**
19378
+ // * Returns withdraw leaf adapter using configured proof id
19379
+ // */
19380
+ // getWithdrawLeaf(): AdapterLeafType<T2> {
19381
+ // const leafConfigs = this._getWithdrawLeaf();
19382
+ // const leaves = leafConfigs.map(config => {
19383
+ // const { target, method, packedArguments, sanitizer, id } = config;
19384
+ // const leaf = this.constructSimpleLeafData({
19385
+ // id: id,
19386
+ // target,
19387
+ // method,
19388
+ // packedArguments
19389
+ // }, sanitizer ?? SIMPLE_SANITIZER);
19390
+ // return leaf;
19391
+ // });
19392
+ // return { leaves, callConstructor: this.getWithdrawCall.bind(this) as unknown as GenerateCallFn<T2> };
19393
+ // }
19394
+ // /**
19395
+ // * Default deposit callConstructor: expects params as calldata (bigint[])
19396
+ // */
19397
+ // protected getDepositCall<T1 = bigint[]>(params: T1): ManageCall[] {
19398
+ // const leafConfigs = this._getDepositLeaf();
19399
+ // return leafConfigs.map(config => {
19400
+ // const { target, method, sanitizer } = config;
19401
+ // return {
19402
+ // sanitizer: sanitizer ?? SIMPLE_SANITIZER,
19403
+ // call: {
19404
+ // contractAddress: target,
19405
+ // selector: hash.getSelectorFromName(method),
19406
+ // calldata: params as unknown as bigint[]
19407
+ // }
19408
+ // };
19409
+ // });
19410
+ // }
19411
+ // /**
19412
+ // * Default withdraw callConstructor: expects params as calldata (bigint[])
19413
+ // */
19414
+ // protected getWithdrawCall<T2 = bigint[]>(params: T2): ManageCall[] {
19415
+ // const leafConfigs = this._getWithdrawLeaf();
19416
+ // return leafConfigs.map(config => {
19417
+ // const { target, method, sanitizer } = config;
19418
+ // return {
19419
+ // sanitizer: sanitizer ?? SIMPLE_SANITIZER,
19420
+ // call: {
19421
+ // contractAddress: target,
19422
+ // selector: hash.getSelectorFromName(method),
19423
+ // calldata: params as unknown as bigint[]
19424
+ // }
19425
+ // };
19426
+ // });
19427
+ // }
19065
19428
  };
19066
19429
 
19067
19430
  // src/strategies/universal-adapters/common-adapter.ts
@@ -26664,7 +27027,20 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
26664
27027
  }
26665
27028
  const output = await contract.call("pair_config", [this.config.collateral.address.address, this.config.debt.address.address]);
26666
27029
  logger.verbose(`${this.config.debt.symbol}::VesuAdapter::getDebtCap debt_cap: ${output.debt_cap.toString()}`);
26667
- return Web3Number.fromWei(output.debt_cap.toString(), this.config.debt.decimals);
27030
+ if (!isV2) {
27031
+ throw new Error("getDebtCap is not supported for v1");
27032
+ }
27033
+ const currentDebt = await this.getCurrentDebtUtilisationAmount(config);
27034
+ logger.verbose(`${this.config.debt.symbol}::VesuAdapter::getDebtCap currentDebt: ${currentDebt.toString()}`);
27035
+ return Web3Number.fromWei(output.debt_cap.toString(), this.config.debt.decimals).minus(currentDebt);
27036
+ }
27037
+ async getCurrentDebtUtilisationAmount(config) {
27038
+ const { contract, isV2 } = await this.getVesuSingletonContract(config, this.config.poolId);
27039
+ if (!isV2) {
27040
+ throw new Error("getCurrentDebtUtilisationAmount is not supported for v1");
27041
+ }
27042
+ const output = await contract.call("pairs", [this.config.collateral.address.address, this.config.debt.address.address]);
27043
+ return new Web3Number((Number(output.total_nominal_debt) / 1e18).toFixed(9), this.config.debt.decimals);
26668
27044
  }
26669
27045
  async getMaxBorrowableByInterestRate(config, asset, maxBorrowAPY) {
26670
27046
  const { contract, isV2 } = await this.getVesuSingletonContract(config, this.config.poolId);
@@ -26697,16 +27073,17 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
26697
27073
  const assetConfig = isV2 ? _assetConfig : _assetConfig["0"];
26698
27074
  const timeDelta = assetConfig.last_updated;
26699
27075
  const lastFullUtilizationRate = assetConfig.last_full_utilization_rate;
26700
- const totalSupply = new Web3Number((Number(assetConfig.total_nominal_debt) / 1e18).toFixed(9), asset.decimals).plus(Web3Number.fromWei(assetConfig.reserve, asset.decimals));
27076
+ const currentDebt = new Web3Number((Number(assetConfig.total_nominal_debt) / 1e18).toFixed(9), asset.decimals);
27077
+ const totalSupply = currentDebt.plus(Web3Number.fromWei(assetConfig.reserve, asset.decimals));
26701
27078
  const ratePerSecond = BigInt(Math.round(maxBorrowAPY / 365 / 24 / 60 / 60 * Number(SCALE)));
26702
27079
  const maxUtilisation = this.getMaxUtilizationGivenRatePerSecond(interestRateConfig, ratePerSecond, timeDelta, lastFullUtilizationRate);
26703
27080
  logger.verbose(`${asset.symbol}::VesuAdapter::getMaxBorrowableByInterestRate maxUtilisation: ${Number(maxUtilisation) / 1e18}, totalSupply: ${totalSupply.toString()}`);
26704
27081
  const maxDebtToHave = totalSupply.multipliedBy(Number(maxUtilisation) / 1e18);
26705
- const currentDebt = new Web3Number((Number(assetConfig.total_nominal_debt) / 1e18).toFixed(9), asset.decimals);
27082
+ logger.verbose(`${asset.symbol}::VesuAdapter::getMaxBorrowableByInterestRate currentDebt: ${currentDebt.toString()}, maxDebtToHave: ${maxDebtToHave.toString()}`);
26706
27083
  return maxDebtToHave.minus(currentDebt);
26707
27084
  }
26708
- async getLTVConfig(config) {
26709
- const CACHE_KEY = "ltv_config";
27085
+ async getLTVConfig(config, blockNumber = "latest") {
27086
+ const CACHE_KEY = `ltv_config_${blockNumber}`;
26710
27087
  const cacheData = this.getCache(CACHE_KEY);
26711
27088
  if (cacheData) {
26712
27089
  return cacheData;
@@ -26714,10 +27091,10 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
26714
27091
  const { contract, isV2 } = await this.getVesuSingletonContract(config, this.config.poolId);
26715
27092
  let ltv = 0;
26716
27093
  if (isV2) {
26717
- const output = await contract.call("pair_config", [this.config.collateral.address.address, this.config.debt.address.address]);
27094
+ const output = await contract.call("pair_config", [this.config.collateral.address.address, this.config.debt.address.address], { blockIdentifier: blockNumber });
26718
27095
  ltv = Number(output.max_ltv) / 1e18;
26719
27096
  } else {
26720
- const output = await contract.call("ltv_config", [this.config.poolId.address, this.config.collateral.address.address, this.config.debt.address.address]);
27097
+ const output = await contract.call("ltv_config", [this.config.poolId.address, this.config.collateral.address.address, this.config.debt.address.address], { blockIdentifier: blockNumber });
26721
27098
  ltv = Number(output.max_ltv) / 1e18;
26722
27099
  }
26723
27100
  if (ltv == 0) {
@@ -26726,11 +27103,11 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
26726
27103
  this.setCache(CACHE_KEY, ltv, 3e5);
26727
27104
  return this.getCache(CACHE_KEY);
26728
27105
  }
26729
- async getPositions(config) {
27106
+ async getPositions(config, blockNumber = "latest") {
26730
27107
  if (!this.pricer) {
26731
27108
  throw new Error("Pricer is not initialized");
26732
27109
  }
26733
- const CACHE_KEY = "positions";
27110
+ const CACHE_KEY = `positions_${blockNumber}`;
26734
27111
  const cacheData = this.getCache(CACHE_KEY);
26735
27112
  if (cacheData) {
26736
27113
  return cacheData;
@@ -26742,7 +27119,8 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
26742
27119
  this.config.collateral.address.address,
26743
27120
  this.config.debt.address.address,
26744
27121
  this.config.vaultAllocator.address
26745
- ]);
27122
+ ], { blockIdentifier: blockNumber });
27123
+ console.log(output);
26746
27124
  const token1Price = await this.pricer.getPrice(this.config.collateral.symbol);
26747
27125
  const token2Price = await this.pricer.getPrice(this.config.debt.symbol);
26748
27126
  logger.verbose(`VesuAdapter::getPositions token1Price: ${token1Price.price}, token2Price: ${token2Price.price}`);
@@ -26762,11 +27140,11 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
26762
27140
  this.setCache(CACHE_KEY, value, 6e4);
26763
27141
  return value;
26764
27142
  }
26765
- async getCollateralization(config) {
27143
+ async getCollateralization(config, blockNumber = "latest") {
26766
27144
  if (!this.pricer) {
26767
27145
  throw new Error("Pricer is not initialized");
26768
27146
  }
26769
- const CACHE_KEY = "collateralization";
27147
+ const CACHE_KEY = `collateralization_${blockNumber}`;
26770
27148
  const cacheData = this.getCache(CACHE_KEY);
26771
27149
  if (cacheData) {
26772
27150
  return cacheData;
@@ -26778,7 +27156,7 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
26778
27156
  this.config.collateral.address.address,
26779
27157
  this.config.debt.address.address,
26780
27158
  this.config.vaultAllocator.address
26781
- ]);
27159
+ ], { blockIdentifier: blockNumber });
26782
27160
  const collateralAmount = Web3Number.fromWei(output["1"].toString(), 18);
26783
27161
  const debtAmount = Web3Number.fromWei(output["2"].toString(), 18);
26784
27162
  const value = [{
@@ -26815,9 +27193,9 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
26815
27193
  ltv
26816
27194
  };
26817
27195
  }
26818
- async getHealthFactor() {
26819
- const ltv = await this.getLTVConfig(this.networkConfig);
26820
- const collateralisation = await this.getCollateralization(this.networkConfig);
27196
+ async getHealthFactor(blockNumber = "latest") {
27197
+ const ltv = await this.getLTVConfig(this.networkConfig, blockNumber);
27198
+ const collateralisation = await this.getCollateralization(this.networkConfig, blockNumber);
26821
27199
  return collateralisation[0].usdValue * ltv / collateralisation[1].usdValue;
26822
27200
  }
26823
27201
  static async getVesuPools(retry = 0) {
@@ -29479,11 +29857,11 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
29479
29857
  vesuAdapter2.networkConfig = this.config;
29480
29858
  return [vesuAdapter1, vesuAdapter2];
29481
29859
  }
29482
- async getVesuPositions() {
29860
+ async getVesuPositions(blockNumber = "latest") {
29483
29861
  const adapters = this.getVesuAdapters();
29484
29862
  const positions = [];
29485
29863
  for (const adapter of adapters) {
29486
- positions.push(...await adapter.getPositions(this.config));
29864
+ positions.push(...await adapter.getPositions(this.config, blockNumber));
29487
29865
  }
29488
29866
  return positions;
29489
29867
  }
@@ -29552,8 +29930,8 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
29552
29930
  async getLSTAPR(address) {
29553
29931
  return 0;
29554
29932
  }
29555
- async getVesuHealthFactors() {
29556
- return await Promise.all(this.getVesuAdapters().map((v) => v.getHealthFactor()));
29933
+ async getVesuHealthFactors(blockNumber = "latest") {
29934
+ return await Promise.all(this.getVesuAdapters().map((v) => v.getHealthFactor(blockNumber)));
29557
29935
  }
29558
29936
  async computeRebalanceConditionAndReturnCalls() {
29559
29937
  const vesuAdapters = this.getVesuAdapters();
@@ -30149,6 +30527,42 @@ var UniversalStrategies = [
30149
30527
 
30150
30528
  // src/strategies/universal-lst-muliplier-strategy.tsx
30151
30529
  import { Contract as Contract10, uint256 as uint2569 } from "starknet";
30530
+
30531
+ // src/utils/health-factor-math.ts
30532
+ var HealthFactorMath = class {
30533
+ static getCollateralRequired(debtAmount, debtPrice, targetHF, maxLTV, collateralPrice, collateralTokenInfo) {
30534
+ const numerator = debtAmount.multipliedBy(debtPrice).multipliedBy(targetHF);
30535
+ const denominator = collateralPrice * maxLTV;
30536
+ const collateralAmount = numerator.dividedBy(denominator);
30537
+ const netCollateral = new Web3Number(collateralAmount.toString(), collateralTokenInfo.decimals);
30538
+ return netCollateral;
30539
+ }
30540
+ static getMinCollateralRequiredOnLooping(debtAmount, debtPrice, targetHF, maxLTV, collateralPrice, collateralTokenInfo) {
30541
+ const netCollateral = this.getCollateralRequired(debtAmount, debtPrice, targetHF, maxLTV, collateralPrice, collateralTokenInfo);
30542
+ const collateralFromDebt = new Web3Number(debtAmount.multipliedBy(debtPrice).dividedBy(collateralPrice).toString(), collateralTokenInfo.decimals);
30543
+ return netCollateral.minus(collateralFromDebt);
30544
+ }
30545
+ static getHealthFactor(collateralAmount, collateralPrice, maxLTV, debtAmount, debtPrice) {
30546
+ const numerator = collateralAmount.multipliedBy(collateralPrice).multipliedBy(maxLTV);
30547
+ const denominator = debtAmount.multipliedBy(debtPrice);
30548
+ const healthFactor = numerator.dividedBy(denominator);
30549
+ return healthFactor.toNumber();
30550
+ }
30551
+ static getMaxDebtAmountOnLooping(collateralAmount, collateralPrice, maxLTV, targetHF, debtPrice, debtTokenInfo) {
30552
+ const numerator = collateralAmount.multipliedBy(collateralPrice).multipliedBy(maxLTV);
30553
+ const denominator = targetHF - maxLTV;
30554
+ const debtAmount = numerator.dividedBy(denominator);
30555
+ return new Web3Number(debtAmount.toString(), debtTokenInfo.decimals);
30556
+ }
30557
+ static getMaxDebtAmount(collateralAmount, collateralPrice, maxLTV, targetHF, debtPrice, debtTokenInfo) {
30558
+ const numerator = collateralAmount.multipliedBy(collateralPrice).multipliedBy(maxLTV);
30559
+ const denominator = targetHF * debtPrice;
30560
+ const debtAmount = numerator.dividedBy(denominator);
30561
+ return new Web3Number(debtAmount.toString(), debtTokenInfo.decimals);
30562
+ }
30563
+ };
30564
+
30565
+ // src/strategies/universal-lst-muliplier-strategy.tsx
30152
30566
  import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
30153
30567
  var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy extends UniversalStrategy {
30154
30568
  constructor(config, pricer, metadata) {
@@ -30163,15 +30577,14 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30163
30577
  }
30164
30578
  }
30165
30579
  asset() {
30166
- const vesuAdapter1 = this.getAdapter("vesu_leg1_adapter" /* VESU_LEG1 */);
30167
- return vesuAdapter1.config.collateral;
30580
+ return this.getVesuSameTokenAdapter().config.collateral;
30168
30581
  }
30169
30582
  getTag() {
30170
30583
  return `${_UniversalLstMultiplierStrategy.name}:${this.metadata.name}`;
30171
30584
  }
30172
30585
  // Vesu adapter with LST and base token match
30173
30586
  getVesuSameTokenAdapter() {
30174
- const baseAdapter = this.getAdapter("vesu_leg1_adapter" /* VESU_LEG1 */);
30587
+ const baseAdapter = this.getAdapter(getVesuLegId("vesu_leg1" /* VESU_LEG1 */, this.metadata.additionalInfo.underlyingToken.symbol));
30175
30588
  baseAdapter.networkConfig = this.config;
30176
30589
  baseAdapter.pricer = this.pricer;
30177
30590
  return baseAdapter;
@@ -30219,20 +30632,52 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30219
30632
  return price;
30220
30633
  }
30221
30634
  async getAvnuSwapMultiplyCall(params) {
30222
- return this._getAvnuDepositSwapLegCall({
30223
- ...params,
30224
- minHF: 1.1
30225
- // undo
30226
- });
30635
+ assert(params.isDeposit, "Only deposit is supported in getAvnuSwapMultiplyCall");
30636
+ const maxBorrowableAmounts = await this.getMaxBorrowableAmount({ isAPYComputation: false });
30637
+ const allVesuAdapters = this.getVesuAdapters();
30638
+ let remainingAmount = params.leg1DepositAmount;
30639
+ const lstExRate = await this.getLSTExchangeRate();
30640
+ const baseAssetPrice = await this.pricer.getPrice(this.getLSTUnderlyingTokenInfo().symbol);
30641
+ const lstPrice = baseAssetPrice.price * lstExRate;
30642
+ for (let i = 0; i < maxBorrowableAmounts.maxBorrowables.length; i++) {
30643
+ const maxBorrowable = maxBorrowableAmounts.maxBorrowables[i];
30644
+ const vesuAdapter = allVesuAdapters.find((adapter) => adapter.config.debt.address.eq(maxBorrowable.borrowableAsset.address));
30645
+ if (!vesuAdapter) {
30646
+ throw new Error(`${this.getTag()}::getAvnuSwapMultiplyCall: vesuAdapter not found for borrowable asset: ${maxBorrowable.borrowableAsset.symbol}`);
30647
+ }
30648
+ const maxLTV = await vesuAdapter.getLTVConfig(this.config);
30649
+ const debtPrice = await this.pricer.getPrice(maxBorrowable.borrowableAsset.symbol);
30650
+ const maxAmountToDeposit = HealthFactorMath.getMinCollateralRequiredOnLooping(
30651
+ maxBorrowable.amount,
30652
+ debtPrice.price,
30653
+ this.metadata.additionalInfo.targetHealthFactor,
30654
+ maxLTV,
30655
+ lstPrice,
30656
+ this.asset()
30657
+ );
30658
+ const amountToDeposit = remainingAmount.minimum(maxAmountToDeposit);
30659
+ logger.verbose(`${this.getTag()}::getAvnuSwapMultiplyCall::${vesuAdapter.config.debt.symbol}:: remainingAmount: ${remainingAmount}, amountToDeposit: ${amountToDeposit}, depositAmount: ${amountToDeposit}, maxBorrowable: ${maxBorrowable.amount}`);
30660
+ const call = await this._getAvnuDepositSwapLegCall({
30661
+ isDeposit: params.isDeposit,
30662
+ // adjust decimals of debt asset
30663
+ leg1DepositAmount: amountToDeposit,
30664
+ minHF: 1.1,
30665
+ // undo
30666
+ vesuAdapter
30667
+ });
30668
+ remainingAmount = remainingAmount.minus(amountToDeposit);
30669
+ return { call, vesuAdapter };
30670
+ }
30671
+ throw new Error(`${this.getTag()}::getAvnuSwapMultiplyCall: no calls found`);
30227
30672
  }
30228
30673
  async _getAvnuDepositSwapLegCall(params) {
30674
+ const { vesuAdapter } = params;
30229
30675
  logger.verbose(`${this.getTag()}::_getAvnuDepositSwapLegCall params: ${JSON.stringify(params)}`);
30230
30676
  assert(params.isDeposit, "Only deposit is supported in _getAvnuDepositSwapLegCall");
30231
- const [vesuAdapter1] = this.getVesuAdapters();
30232
- const legLTV = await vesuAdapter1.getLTVConfig(this.config);
30677
+ const legLTV = await vesuAdapter.getLTVConfig(this.config);
30233
30678
  logger.verbose(`${this.getTag()}::_getAvnuDepositSwapLegCall legLTV: ${legLTV}`);
30234
- const existingPositions = await vesuAdapter1.getPositions(this.config);
30235
- const collateralisation = await vesuAdapter1.getCollateralization(this.config);
30679
+ const existingPositions = await vesuAdapter.getPositions(this.config);
30680
+ const collateralisation = await vesuAdapter.getCollateralization(this.config);
30236
30681
  const existingCollateralInfo = existingPositions[0];
30237
30682
  const existingDebtInfo = existingPositions[1];
30238
30683
  logger.debug(`${this.getTag()}::_getAvnuDepositSwapLegCall existingCollateralInfo: ${JSON.stringify(existingCollateralInfo)},
@@ -30240,11 +30685,40 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30240
30685
  const collateralPrice = collateralisation[0].usdValue > 0 ? collateralisation[0].usdValue / existingCollateralInfo.amount.toNumber() : 1;
30241
30686
  const debtPrice = collateralisation[1].usdValue > 0 ? collateralisation[1].usdValue / existingDebtInfo.amount.toNumber() : 1;
30242
30687
  logger.debug(`${this.getTag()}::_getAvnuDepositSwapLegCall collateralPrice: ${collateralPrice}, debtPrice: ${debtPrice}`);
30688
+ const debtTokenInfo = vesuAdapter.config.debt;
30689
+ let newDepositAmount = params.leg1DepositAmount;
30243
30690
  const totalCollateral = existingCollateralInfo.amount.plus(params.leg1DepositAmount);
30244
30691
  logger.verbose(`${this.getTag()}::_getAvnuDepositSwapLegCall totalCollateral: ${totalCollateral}`);
30245
- const totalDebtAmount = totalCollateral.multipliedBy(collateralPrice).multipliedBy(legLTV).dividedBy(debtPrice).dividedBy(params.minHF);
30246
- logger.verbose(`${this.getTag()}::_getAvnuDepositSwapLegCall totalDebtAmount: ${totalDebtAmount}`);
30247
- const debtAmount = totalDebtAmount.minus(existingDebtInfo.amount);
30692
+ const totalDebtAmount = new Web3Number(
30693
+ totalCollateral.multipliedBy(collateralPrice).multipliedBy(legLTV).dividedBy(debtPrice).dividedBy(params.minHF).toString(),
30694
+ debtTokenInfo.decimals
30695
+ );
30696
+ let debtAmount = totalDebtAmount.minus(existingDebtInfo.amount);
30697
+ logger.verbose(`${this.getTag()}::_getAvnuDepositSwapLegCall totalDebtAmount: ${totalDebtAmount}, initial computed debt: ${debtAmount}`);
30698
+ const maxBorrowable = await this.getMaxBorrowableAmountByVesuAdapter(vesuAdapter, false);
30699
+ if (debtAmount.gt(0) && maxBorrowable.amount.eq(0)) {
30700
+ logger.verbose(`${this.getTag()}::_getAvnuDepositSwapLegCall maxBorrowable is 0, skipping`);
30701
+ return void 0;
30702
+ } else if (debtAmount.gt(0) && maxBorrowable.amount.gt(0)) {
30703
+ debtAmount = maxBorrowable.amount.minimum(debtAmount);
30704
+ const newDebtUSDValue = debtAmount.multipliedBy(debtPrice);
30705
+ const totalCollateralRequired = HealthFactorMath.getCollateralRequired(
30706
+ debtAmount.plus(existingDebtInfo.amount),
30707
+ debtPrice,
30708
+ params.minHF,
30709
+ legLTV,
30710
+ collateralPrice,
30711
+ this.asset()
30712
+ );
30713
+ newDepositAmount = totalCollateralRequired.minus(existingCollateralInfo.amount);
30714
+ if (newDepositAmount.lt(0)) {
30715
+ throw new Error(`${this.getTag()}::_getAvnuDepositSwapLegCall newDepositAmount is less than 0, newDepositAmount: ${newDepositAmount}, totalCollateralRequired: ${totalCollateralRequired}, existingCollateralInfo.amount: ${existingCollateralInfo.amount}`);
30716
+ }
30717
+ if (newDebtUSDValue.toNumber() < 100) {
30718
+ logger.verbose(`${this.getTag()}::_getAvnuDepositSwapLegCall newDebtUSDValue is less than 100, skipping`);
30719
+ return void 0;
30720
+ }
30721
+ }
30248
30722
  logger.verbose(`${this.getTag()}::_getAvnuDepositSwapLegCall debtAmount: ${debtAmount}`);
30249
30723
  if (debtAmount.lt(0)) {
30250
30724
  const lstDEXPrice = await this.getLSTDexPrice();
@@ -30256,32 +30730,34 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30256
30730
  assert(calls.length == 1, `Expected 1 call for unwind, got ${calls.length}`);
30257
30731
  return calls[0];
30258
30732
  }
30733
+ console.log(`debtAmount`, debtAmount.toWei(), params.leg1DepositAmount.toWei());
30259
30734
  const STEP0 = "approve_token1" /* APPROVE_TOKEN1 */;
30260
30735
  const manage0Info = this.getProofs(STEP0);
30261
30736
  const manageCall0 = manage0Info.callConstructor({
30262
- amount: params.leg1DepositAmount
30737
+ amount: newDepositAmount
30263
30738
  });
30264
- const STEP1 = "vesu_leg1" /* VESU_LEG1 */;
30739
+ const STEP1 = getVesuLegId("vesu_leg1" /* VESU_LEG1 */, vesuAdapter.config.debt.symbol);
30265
30740
  const manage1Info = this.getProofs(STEP1);
30266
30741
  const manageCall1 = manage1Info.callConstructor(VesuAdapter.getDefaultModifyPositionCallParams({
30267
- collateralAmount: params.leg1DepositAmount,
30742
+ collateralAmount: newDepositAmount,
30268
30743
  isAddCollateral: params.isDeposit,
30269
30744
  debtAmount,
30270
30745
  isBorrow: params.isDeposit
30271
30746
  }));
30747
+ console.log(`manageCall1`, manageCall1.call, debtAmount.toWei(), newDepositAmount.toWei());
30272
30748
  const proofIds = [STEP0, STEP1];
30273
30749
  const manageCalls = [manageCall0, manageCall1];
30274
30750
  if (debtAmount.gt(0)) {
30275
- const STEP2 = "avnu_multiply_approve_deposit" /* AVNU_MULTIPLY_APPROVE_DEPOSIT */;
30751
+ const STEP2 = getAvnuManageIDs("avnu_mul_approve_dep" /* AVNU_MULTIPLY_APPROVE_DEPOSIT */, vesuAdapter.config.debt.symbol);
30276
30752
  const manage2Info = this.getProofs(STEP2);
30277
30753
  const manageCall2 = manage2Info.callConstructor({
30278
30754
  amount: debtAmount
30279
30755
  });
30280
- const debtTokenInfo = vesuAdapter1.config.debt;
30756
+ const debtTokenInfo2 = vesuAdapter.config.debt;
30281
30757
  const lstTokenInfo = this.asset();
30282
30758
  const avnuModule = new AvnuWrapper();
30283
30759
  const quote = await avnuModule.getQuotes(
30284
- debtTokenInfo.address.address,
30760
+ debtTokenInfo2.address.address,
30285
30761
  lstTokenInfo.address.address,
30286
30762
  debtAmount.toWei(),
30287
30763
  this.metadata.additionalInfo.vaultAllocator.address
@@ -30297,7 +30773,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30297
30773
  minAmountWei
30298
30774
  );
30299
30775
  logger.verbose(`${this.getTag()}::_getAvnuDepositSwapLegCall swapInfo: ${JSON.stringify(swapInfo)}`);
30300
- const STEP3 = "avnu_multiply_swap_deposit" /* AVNU_MULTIPLY_SWAP_DEPOSIT */;
30776
+ const STEP3 = getAvnuManageIDs("avnu_mul_swap_dep" /* AVNU_MULTIPLY_SWAP_DEPOSIT */, vesuAdapter.config.debt.symbol);
30301
30777
  const manage3Info = this.getProofs(STEP3);
30302
30778
  const manageCall3 = manage3Info.callConstructor({
30303
30779
  props: swapInfo
@@ -30315,7 +30791,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30315
30791
  const manageCall4 = manage4Info.callConstructor({
30316
30792
  amount: minAmount
30317
30793
  });
30318
- const STEP5 = "vesu_leg1" /* VESU_LEG1 */;
30794
+ const STEP5 = getVesuLegId("vesu_leg1" /* VESU_LEG1 */, vesuAdapter.config.debt.symbol);
30319
30795
  const manage5Info = this.getProofs(STEP5);
30320
30796
  const manageCall5 = manage5Info.callConstructor(VesuAdapter.getDefaultModifyPositionCallParams({
30321
30797
  collateralAmount: minAmount,
@@ -30332,28 +30808,41 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30332
30808
  }
30333
30809
  // todo unwind or not deposit when the yield is bad.
30334
30810
  async getLSTMultiplierRebalanceCall() {
30335
- const positions = await this.getVaultPositions();
30336
- assert(positions.length == 3, "Rebalance call is only supported for 3 positions");
30811
+ let shouldRebalance = false;
30812
+ const calls = [];
30813
+ const allVesuAdapters = this.getVesuAdapters().filter((vesuAdapter) => vesuAdapter.config.debt.symbol === "LBTC");
30814
+ for (const vesuAdapter of allVesuAdapters) {
30815
+ const call = await this._getLSTMultiplierRebalanceCall(vesuAdapter);
30816
+ if (call.shouldRebalance && call.manageCall) {
30817
+ shouldRebalance = true;
30818
+ calls.push({ vesuAdapter, manageCall: call.manageCall });
30819
+ }
30820
+ }
30821
+ return { shouldRebalance, manageCalls: calls };
30822
+ }
30823
+ async _getLSTMultiplierRebalanceCall(vesuAdapter) {
30824
+ const positions = await vesuAdapter.getPositions(this.config);
30825
+ assert(positions.length == 2, "Rebalance call is only supported for 2 positions");
30337
30826
  const existingCollateralInfo = positions[0];
30338
30827
  const existingDebtInfo = positions[1];
30339
- const unusedBalance = positions[2];
30340
- const [healthFactor] = await this.getVesuHealthFactors();
30341
- const [vesuAdapter1] = this.getVesuAdapters();
30342
- const legLTV = await vesuAdapter1.getLTVConfig(this.config);
30343
- const collateralisation = await vesuAdapter1.getCollateralization(this.config);
30344
- logger.debug(`${this.getTag()}::getVesuMultiplyCall existingCollateralInfo: ${JSON.stringify(existingCollateralInfo)},
30828
+ const unusedBalance = await this.getUnusedBalance();
30829
+ const healthFactor = await vesuAdapter.getHealthFactor();
30830
+ const collateralisation = await vesuAdapter.getCollateralization(this.config);
30831
+ logger.debug(`${this.getTag()}::getVesuMultiplyCall::${vesuAdapter.config.debt.symbol} existingCollateralInfo: ${JSON.stringify(existingCollateralInfo)},
30345
30832
  existingDebtInfo: ${JSON.stringify(existingDebtInfo)}, collateralisation: ${JSON.stringify(collateralisation)}`);
30346
30833
  const collateralPrice = collateralisation[0].usdValue > 0 ? collateralisation[0].usdValue / existingCollateralInfo.amount.toNumber() : 1;
30347
30834
  const debtPrice = collateralisation[1].usdValue > 0 ? collateralisation[1].usdValue / existingDebtInfo.amount.toNumber() : 1;
30348
30835
  logger.debug(`${this.getTag()}::getVesuMultiplyCall collateralPrice: ${collateralPrice}, debtPrice: ${debtPrice}`);
30836
+ logger.debug(`${this.getTag()}::getVesuMultiplyCall healthFactor: ${healthFactor}`);
30349
30837
  const isHFTooLow = healthFactor < this.metadata.additionalInfo.minHealthFactor;
30350
30838
  const isHFTooHigh = healthFactor > this.metadata.additionalInfo.targetHealthFactor + 0.05;
30351
- if (isHFTooLow || isHFTooHigh) {
30839
+ if (isHFTooLow || isHFTooHigh || 1) {
30352
30840
  const manageCall = await this._getAvnuDepositSwapLegCall({
30353
30841
  isDeposit: true,
30354
30842
  leg1DepositAmount: unusedBalance.amount,
30355
- minHF: 1.02
30843
+ minHF: 1.02,
30356
30844
  // todo, shouldnt use this 1.02 HF, if there isn;t more looping left.
30845
+ vesuAdapter
30357
30846
  });
30358
30847
  return { shouldRebalance: true, manageCall };
30359
30848
  } else {
@@ -30386,7 +30875,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30386
30875
  async _getMinOutputAmountLSTBuy(amountInUnderlying) {
30387
30876
  const lstTruePrice = await this.getLSTExchangeRate();
30388
30877
  const minOutputAmount = amountInUnderlying.dividedBy(lstTruePrice).multipliedBy(0.99979);
30389
- return minOutputAmount;
30878
+ return new Web3Number(minOutputAmount.toString(), this.asset().decimals);
30390
30879
  }
30391
30880
  async _getMinOutputAmountLSTSell(amountInLST) {
30392
30881
  const lstTruePrice = await this.getLSTExchangeRate();
@@ -30443,21 +30932,52 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30443
30932
  const vesuAdapter1 = this.getVesuSameTokenAdapter();
30444
30933
  return vesuAdapter1.config.debt;
30445
30934
  }
30446
- async getMaxBorrowableAmount() {
30935
+ async getMaxBorrowableAmount(params = { isAPYComputation: false }) {
30447
30936
  const vesuAdapters = this.getVesuAdapters();
30448
30937
  let netMaxBorrowableAmount = Web3Number.fromWei("0", this.getLSTUnderlyingTokenInfo().decimals);
30449
30938
  const maxBorrowables = [];
30450
- const lstAPY = await this.getLSTAPR(this.getLSTUnderlyingTokenInfo().address);
30451
- const maxInterestRate = lstAPY * 0.8;
30452
30939
  for (const vesuAdapter of vesuAdapters) {
30453
- const maxBorrowableAmount = await vesuAdapter.getMaxBorrowableByInterestRate(this.config, vesuAdapter.config.debt, maxInterestRate);
30454
- const debtCap = await vesuAdapter.getDebtCap(this.config);
30455
- maxBorrowables.push({ amount: maxBorrowableAmount.minimum(debtCap), borrowableAsset: vesuAdapter.config.debt });
30940
+ maxBorrowables.push(await this.getMaxBorrowableAmountByVesuAdapter(vesuAdapter, params.isAPYComputation));
30456
30941
  }
30457
30942
  maxBorrowables.sort((a, b) => b.amount.toNumber() - a.amount.toNumber());
30458
30943
  netMaxBorrowableAmount = maxBorrowables.reduce((acc, curr) => acc.plus(curr.amount), Web3Number.fromWei("0", this.getLSTUnderlyingTokenInfo().decimals));
30459
30944
  return { netMaxBorrowableAmount, maxBorrowables };
30460
30945
  }
30946
+ // recursively, using binary search computes max swappable.
30947
+ // @dev assumes 1 token of from == 1 token of to
30948
+ async getMaxSwappableWithMaxSlippage(fromToken, toToken, maxSlippage, maxAmount) {
30949
+ const output = await findMaxInputWithSlippage({
30950
+ apiGetOutput: async (inputAmount) => {
30951
+ const ekuboQuoter = new EkuboQuoter(this.config);
30952
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
30953
+ const quote = await ekuboQuoter.getQuote(fromToken.address.address, toToken.address.address, new Web3Number(inputAmount.toFixed(9), fromToken.decimals));
30954
+ return Web3Number.fromWei(quote.total_calculated.toString(), toToken.decimals).toNumber();
30955
+ },
30956
+ maxInput: maxAmount.toNumber(),
30957
+ maxSlippagePercent: maxSlippage,
30958
+ tolerance: 1e-3,
30959
+ referenceRate: 1
30960
+ });
30961
+ return new Web3Number(output.optimalInput, fromToken.decimals);
30962
+ }
30963
+ async getMaxBorrowableAmountByVesuAdapter(vesuAdapter, isAPYComputation) {
30964
+ const lstAPY = await this.getLSTAPR(this.getLSTUnderlyingTokenInfo().address);
30965
+ const maxInterestRate = lstAPY * 0.8;
30966
+ const maxBorrowableAmount = await vesuAdapter.getMaxBorrowableByInterestRate(this.config, vesuAdapter.config.debt, maxInterestRate);
30967
+ const debtCap = await vesuAdapter.getDebtCap(this.config);
30968
+ const maxBorrowable = maxBorrowableAmount.minimum(debtCap).multipliedBy(0.999);
30969
+ if (vesuAdapter.config.debt.address.eq(this.getLSTUnderlyingTokenInfo().address) || isAPYComputation) {
30970
+ return { amount: maxBorrowable, dexSwappableAmount: maxBorrowable, maxBorrowableAmount: maxBorrowable, borrowableAsset: vesuAdapter.config.debt };
30971
+ }
30972
+ try {
30973
+ const maxSwappable = await this.getMaxSwappableWithMaxSlippage(vesuAdapter.config.debt, this.getLSTUnderlyingTokenInfo(), 2e-4, maxBorrowable);
30974
+ return { amount: maxBorrowable.minimum(maxSwappable), dexSwappableAmount: maxSwappable, maxBorrowableAmount: maxBorrowable, borrowableAsset: vesuAdapter.config.debt };
30975
+ } catch (error) {
30976
+ logger.warn(`${this.getTag()}: Failed to get max swappable: ${error}`);
30977
+ const maxSwappable = Web3Number.fromWei("0", vesuAdapter.config.debt.decimals);
30978
+ return { amount: maxBorrowable.minimum(maxSwappable), dexSwappableAmount: maxSwappable, maxBorrowableAmount: maxBorrowable, borrowableAsset: vesuAdapter.config.debt };
30979
+ }
30980
+ }
30461
30981
  // todo how much to unwind to get back healthy APY zone again
30462
30982
  // if net APY < LST APR + 0.5%, we need to unwind to get back to LST APR + 1% atleast or 0 vesu position
30463
30983
  // For xSTRK, simply deposit in Vesu if looping is not viable
@@ -30481,7 +31001,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30481
31001
  // todo undo this
30482
31002
  async netAPY() {
30483
31003
  const unusedBalance = await this.getUnusedBalance();
30484
- const maxNewDeposits = await this.maxNewDeposits();
31004
+ const maxNewDeposits = await this.maxNewDeposits({ isAPYComputation: true });
30485
31005
  const lstAPY = await this.getLSTAPR(this.getLSTUnderlyingTokenInfo().address);
30486
31006
  if (maxNewDeposits * 1.5 < unusedBalance.amount.toNumber()) {
30487
31007
  logger.verbose(`${this.getTag()}::netAPY: unused balance is > max servicable from loan, lstAPY: ${lstAPY}`);
@@ -30498,8 +31018,8 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30498
31018
  return output;
30499
31019
  }
30500
31020
  }
30501
- async maxNewDeposits() {
30502
- const maxBorrowableAmounts = await this.getMaxBorrowableAmount();
31021
+ async maxNewDeposits(params = { isAPYComputation: false }) {
31022
+ const maxBorrowableAmounts = await this.getMaxBorrowableAmount(params);
30503
31023
  let ltv = void 0;
30504
31024
  for (let adapter of this.getVesuAdapters()) {
30505
31025
  const maxBorrowableAmount = maxBorrowableAmounts.maxBorrowables.find((b) => b.borrowableAsset.address.eq(adapter.config.debt.address))?.amount;
@@ -30602,7 +31122,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30602
31122
  const manageCall2 = manage2Info.callConstructor({
30603
31123
  delegation: true
30604
31124
  });
30605
- const STEP3_ID = "multiply_vesu" /* MULTIPLY_VESU */;
31125
+ const STEP3_ID = getVesuLegId("multiply_vesu" /* MULTIPLY_VESU */, vesuAdapter1.config.debt.symbol);
30606
31126
  const manage3Info = this.getProofs(STEP3_ID);
30607
31127
  const multiplyParams = params.isIncrease ? {
30608
31128
  isIncrease: true,
@@ -30668,6 +31188,7 @@ function VaultDescription(lstSymbol, underlyingSymbol) {
30668
31188
  /* @__PURE__ */ jsxs4("p", { style: { fontSize: "14px", lineHeight: "1.5", marginBottom: "16px" }, children: [
30669
31189
  "This vault uses Vesu for lending and borrowing. The oracle used by this pool is a ",
30670
31190
  highlightTextWithLinks("conversion rate oracle", [{ highlight: "conversion rate oracle", link: "https://docs.pragma.build/starknet/development#conversion-rate" }]),
31191
+ " ",
30671
31192
  "which is resilient to liquidity issues and price volatility, hence reducing the risk of liquidation. However, overtime, if left un-monitored, debt can increase enough to trigger a liquidation. But no worries, our continuous monitoring systems look for situations with reduced health factor and balance collateral/debt to bring it back to safe levels. With Troves, you can have a peaceful sleep."
30672
31193
  ] }),
30673
31194
  /* @__PURE__ */ jsx5("div", { style: { backgroundColor: "#222", padding: "10px", borderRadius: "8px", marginBottom: "20px", border: "1px solid #444" }, children: /* @__PURE__ */ jsxs4("p", { style: { fontSize: "13px", color: "#ccc" }, children: [
@@ -30678,17 +31199,19 @@ function VaultDescription(lstSymbol, underlyingSymbol) {
30678
31199
  ] }) }),
30679
31200
  /* @__PURE__ */ jsx5("div", { style: { backgroundColor: "#222", padding: "10px", borderRadius: "8px", marginBottom: "20px", border: "1px solid #444" }, children: /* @__PURE__ */ jsxs4("p", { style: { fontSize: "13px", color: "#ccc" }, children: [
30680
31201
  /* @__PURE__ */ jsx5("strong", { children: "Debt limits:" }),
30681
- " Pools on Vesu have debt caps that are gradually increased over time. Until caps are raised, deposited LSTs remain in the vault, generating a shared net return for all depositors."
30682
- ] }) }),
30683
- /* @__PURE__ */ jsx5("div", { style: { backgroundColor: "#222", padding: "10px", borderRadius: "8px", marginBottom: "20px", border: "1px solid #444" }, children: /* @__PURE__ */ jsxs4("p", { style: { fontSize: "13px", color: "#ccc" }, children: [
30684
- /* @__PURE__ */ jsx5("strong", { children: "APY assumptions:" }),
30685
- " APY shown is the max possible value given current LST and borrowing rates. True APY will be subject to the actual leverage, based on above point. More insights on exact APY will be added soon."
31202
+ " Pools on Vesu have debt caps that are gradually increased over time. Until caps are raised, deposited LSTs remain in the vault, generating a shared net return for all depositors. There is no additional fee taken by Troves on LST APY, its only on added gain."
30686
31203
  ] }) })
30687
31204
  ] });
30688
31205
  }
30689
31206
  function getDescription2(tokenSymbol, underlyingSymbol) {
30690
31207
  return VaultDescription(tokenSymbol, underlyingSymbol);
30691
31208
  }
31209
+ function getAvnuManageIDs(baseID, debtTokenSymbol) {
31210
+ return `${baseID}_${debtTokenSymbol.toLowerCase()}`;
31211
+ }
31212
+ function getVesuLegId(baseID, debtTokenSymbol) {
31213
+ return `${baseID}_${debtTokenSymbol.toLowerCase()}`;
31214
+ }
30692
31215
  function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
30693
31216
  vaultSettings.leafAdapters = [];
30694
31217
  const lstToken = Global.getDefaultTokens().find((token) => token.symbol === lstSymbol);
@@ -30698,7 +31221,7 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
30698
31221
  collateral: lstToken,
30699
31222
  debt: underlyingToken,
30700
31223
  vaultAllocator: vaultSettings.vaultAllocator,
30701
- id: "vesu_leg1" /* VESU_LEG1 */
31224
+ id: getVesuLegId("vesu_leg1" /* VESU_LEG1 */, underlyingToken.symbol)
30702
31225
  });
30703
31226
  const commonAdapter = new CommonAdapter({
30704
31227
  manager: vaultSettings.manager,
@@ -30707,25 +31230,39 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
30707
31230
  vaultAddress: vaultSettings.vaultAddress,
30708
31231
  vaultAllocator: vaultSettings.vaultAllocator
30709
31232
  });
30710
- const { isV2, addr: poolAddr } = getVesuSingletonAddress(pool1);
30711
- const VESU_MULTIPLY = isV2 ? vesuAdapterLST.VESU_MULTIPLY : vesuAdapterLST.VESU_MULTIPLY_V1;
30712
- vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, VESU_MULTIPLY, "multiple_approve" /* MULTIPLE_APPROVE */).bind(commonAdapter));
30713
- vaultSettings.leafAdapters.push(vesuAdapterLST.getMultiplyAdapter("multiply_vesu" /* MULTIPLY_VESU */).bind(vesuAdapterLST));
30714
- vaultSettings.leafAdapters.push(vesuAdapterLST.getVesuModifyDelegationAdapter("switch_delegation_on" /* SWITCH_DELEGATION_ON */).bind(vesuAdapterLST));
30715
- vaultSettings.leafAdapters.push(vesuAdapterLST.getVesuModifyDelegationAdapter("switch_delegation_off" /* SWITCH_DELEGATION_OFF */).bind(vesuAdapterLST));
30716
31233
  vaultSettings.adapters.push(...[{
30717
- id: "vesu_leg1_adapter" /* VESU_LEG1 */,
31234
+ id: getVesuLegId("vesu_leg1" /* VESU_LEG1 */, underlyingToken.symbol),
30718
31235
  adapter: vesuAdapterLST
30719
31236
  }, {
30720
31237
  id: "common_adapter" /* COMMON */,
30721
31238
  adapter: commonAdapter
30722
31239
  }]);
30723
- vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(underlyingToken.address, AVNU_EXCHANGE, "avnu_multiply_approve_deposit" /* AVNU_MULTIPLY_APPROVE_DEPOSIT */).bind(commonAdapter));
30724
- vaultSettings.leafAdapters.push(commonAdapter.getAvnuAdapter(underlyingToken.address, lstToken.address, "avnu_multiply_swap_deposit" /* AVNU_MULTIPLY_SWAP_DEPOSIT */, false).bind(commonAdapter));
30725
- vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, AVNU_EXCHANGE, "avnu_multiply_approve_withdraw" /* AVNU_MULTIPLY_APPROVE_WITHDRAW */).bind(commonAdapter));
30726
- vaultSettings.leafAdapters.push(commonAdapter.getAvnuAdapter(lstToken.address, underlyingToken.address, "avnu_multiply_swap_withdraw" /* AVNU_MULTIPLY_SWAP_WITHDRAW */, false).bind(commonAdapter));
30727
- vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, poolAddr, "approve_token1" /* APPROVE_TOKEN1 */).bind(commonAdapter));
30728
- vaultSettings.leafAdapters.push(vesuAdapterLST.getModifyPosition.bind(vesuAdapterLST));
31240
+ const { isV2, addr: poolAddr } = getVesuSingletonAddress(pool1);
31241
+ const VESU_MULTIPLY = isV2 ? vesuAdapterLST.VESU_MULTIPLY : vesuAdapterLST.VESU_MULTIPLY_V1;
31242
+ vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, VESU_MULTIPLY, "multiple_approve" /* MULTIPLE_APPROVE */).bind(commonAdapter));
31243
+ vaultSettings.leafAdapters.push(vesuAdapterLST.getVesuModifyDelegationAdapter("switch_delegation_on" /* SWITCH_DELEGATION_ON */).bind(vesuAdapterLST));
31244
+ vaultSettings.leafAdapters.push(vesuAdapterLST.getVesuModifyDelegationAdapter("switch_delegation_off" /* SWITCH_DELEGATION_OFF */).bind(vesuAdapterLST));
31245
+ vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, AVNU_EXCHANGE, "avnu_mul_approve_withdr" /* AVNU_MULTIPLY_APPROVE_WITHDRAW */).bind(commonAdapter));
31246
+ for (let borrowableAsset of vaultSettings.borrowable_assets) {
31247
+ const debtAsset = borrowableAsset;
31248
+ const approve_debt_token_id = getAvnuManageIDs("avnu_mul_approve_dep" /* AVNU_MULTIPLY_APPROVE_DEPOSIT */, debtAsset.symbol);
31249
+ const swap_debt_token_id = getAvnuManageIDs("avnu_mul_swap_dep" /* AVNU_MULTIPLY_SWAP_DEPOSIT */, debtAsset.symbol);
31250
+ const swap_lst_token_id = getAvnuManageIDs("avnu_mul_swap_withdr" /* AVNU_MULTIPLY_SWAP_WITHDRAW */, debtAsset.symbol);
31251
+ vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(debtAsset.address, AVNU_EXCHANGE, approve_debt_token_id).bind(commonAdapter));
31252
+ vaultSettings.leafAdapters.push(commonAdapter.getAvnuAdapter(debtAsset.address, lstToken.address, swap_debt_token_id, false).bind(commonAdapter));
31253
+ vaultSettings.leafAdapters.push(commonAdapter.getAvnuAdapter(lstToken.address, debtAsset.address, swap_lst_token_id, false).bind(commonAdapter));
31254
+ const vesuAdapter = new VesuAdapter({
31255
+ poolId: pool1,
31256
+ collateral: lstToken,
31257
+ debt: debtAsset,
31258
+ vaultAllocator: vaultSettings.vaultAllocator,
31259
+ id: getVesuLegId("vesu_leg1" /* VESU_LEG1 */, debtAsset.symbol)
31260
+ });
31261
+ vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, poolAddr, "approve_token1" /* APPROVE_TOKEN1 */).bind(commonAdapter));
31262
+ vaultSettings.leafAdapters.push(vesuAdapter.getModifyPosition.bind(vesuAdapter));
31263
+ const multiplID = getVesuLegId("multiply_vesu" /* MULTIPLY_VESU */, debtAsset.symbol);
31264
+ vaultSettings.leafAdapters.push(vesuAdapter.getMultiplyAdapter(multiplID).bind(vesuAdapter));
31265
+ }
30729
31266
  vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, vaultSettings.vaultAddress, "approve_bring_liquidity" /* APPROVE_BRING_LIQUIDITY */).bind(commonAdapter));
30730
31267
  vaultSettings.leafAdapters.push(commonAdapter.getBringLiquidityAdapter("bring_liquidity" /* BRING_LIQUIDITY */).bind(commonAdapter));
30731
31268
  vaultSettings.leafAdapters.push(vesuAdapterLST.getDefispringRewardsAdapter("defispring_rewards" /* DEFISPRING_REWARDS */).bind(vesuAdapterLST));
@@ -30803,7 +31340,8 @@ var hyperxSTRK = {
30803
31340
  adapters: [],
30804
31341
  targetHealthFactor: 1.1,
30805
31342
  minHealthFactor: 1.05,
30806
- borrowable_assets: Global.getDefaultTokens().filter((token) => token.symbol === "STRK")
31343
+ borrowable_assets: Global.getDefaultTokens().filter((token) => token.symbol === "STRK"),
31344
+ underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "STRK")
30807
31345
  };
30808
31346
  var hyperxWBTC = {
30809
31347
  vaultAddress: ContractAddr.from("0x2da9d0f96a46b453f55604313785dc866424240b1c6811d13bef594343db818"),
@@ -30815,7 +31353,8 @@ var hyperxWBTC = {
30815
31353
  adapters: [],
30816
31354
  targetHealthFactor: 1.1,
30817
31355
  minHealthFactor: 1.05,
30818
- borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset))
31356
+ borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
31357
+ underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "WBTC")
30819
31358
  };
30820
31359
  var hyperxtBTC = {
30821
31360
  vaultAddress: ContractAddr.from("0x47d5f68477e5637ce0e56436c6b5eee5a354e6828995dae106b11a48679328"),
@@ -30827,7 +31366,8 @@ var hyperxtBTC = {
30827
31366
  adapters: [],
30828
31367
  targetHealthFactor: 1.1,
30829
31368
  minHealthFactor: 1.05,
30830
- borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset))
31369
+ borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
31370
+ underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "tBTC")
30831
31371
  };
30832
31372
  var hyperxsBTC = {
30833
31373
  vaultAddress: ContractAddr.from("0x437ef1e7d0f100b2e070b7a65cafec0b2be31b0290776da8b4112f5473d8d9"),
@@ -30839,7 +31379,8 @@ var hyperxsBTC = {
30839
31379
  adapters: [],
30840
31380
  targetHealthFactor: 1.1,
30841
31381
  minHealthFactor: 1.05,
30842
- borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset))
31382
+ borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
31383
+ underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "solvBTC")
30843
31384
  };
30844
31385
  var hyperxLBTC = {
30845
31386
  vaultAddress: ContractAddr.from("0x64cf24d4883fe569926419a0569ab34497c6956a1a308fa883257f7486d7030"),
@@ -30851,7 +31392,8 @@ var hyperxLBTC = {
30851
31392
  adapters: [],
30852
31393
  targetHealthFactor: 1.1,
30853
31394
  minHealthFactor: 1.05,
30854
- borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset))
31395
+ borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
31396
+ underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "LBTC")
30855
31397
  };
30856
31398
  function getInvestmentSteps(lstSymbol, underlyingSymbol) {
30857
31399
  return [
@@ -30883,7 +31425,7 @@ function getStrategySettings(lstSymbol, underlyingSymbol, addresses, isPreview =
30883
31425
  faqs: getFAQs2(lstSymbol, underlyingSymbol),
30884
31426
  investmentSteps: getInvestmentSteps(lstSymbol, underlyingSymbol),
30885
31427
  isPreview,
30886
- apyMethodology: "Current annualized APY in terms of base asset of the LST"
31428
+ apyMethodology: "Current annualized APY in terms of base asset of the LST. There is no additional fee taken by Troves on LST APY. We charge a 10% performance fee on the additional gain which is already accounted in the APY shown."
30887
31429
  };
30888
31430
  }
30889
31431
  var HyperLSTStrategies = [
@@ -31553,6 +32095,7 @@ var Deployer = {
31553
32095
  };
31554
32096
  var deployer_default = Deployer;
31555
32097
  export {
32098
+ APYType,
31556
32099
  AUMTypes,
31557
32100
  AVNU_EXCHANGE,
31558
32101
  AVNU_MIDDLEWARE,