@strkfarm/sdk 2.0.0-dev.13 → 2.0.0-dev.15

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.
@@ -28550,6 +28550,21 @@ var calculateAmountDepositOnExtendedWhenIncurringLosses = async (client) => {
28550
28550
  return null;
28551
28551
  }
28552
28552
  };
28553
+ var calculateWBTCAmountToMaintainLTV = (collateralAmount, debtAmount, debtPrice, maxLtv = MAX_LIQUIDATION_RATIO, collateralPrice, targetHF = TARGET_HF) => {
28554
+ try {
28555
+ const numerator1 = collateralAmount.multipliedBy(collateralPrice).multipliedBy(maxLtv);
28556
+ const numerator2 = debtAmount.multipliedBy(debtPrice).multipliedBy(targetHF);
28557
+ const denominator = maxLtv;
28558
+ const collateralAmountToMaintainLTV = numerator2.minus(numerator1).dividedBy(denominator);
28559
+ let deltaCollateralAmountUnits = new Web3Number(
28560
+ collateralAmountToMaintainLTV.dividedBy(collateralPrice).toFixed(WBTC_TOKEN_DECIMALS),
28561
+ WBTC_TOKEN_DECIMALS
28562
+ );
28563
+ return { deltaCollateralAmountUnits };
28564
+ } catch (err) {
28565
+ return { deltaCollateralAmountUnits: null };
28566
+ }
28567
+ };
28553
28568
  var calculateExposureDelta = (exposure_extended, exposure_vesu) => {
28554
28569
  const exposure_delta = new Web3Number(exposure_extended - exposure_vesu, 2);
28555
28570
  return exposure_delta.absoluteValue().toNumber();
@@ -29936,26 +29951,38 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29936
29951
  try {
29937
29952
  if (!this.client) {
29938
29953
  logger.error("Client not initialized");
29939
- return false;
29954
+ return {
29955
+ status: false,
29956
+ receivedTxnHash: false
29957
+ };
29940
29958
  }
29941
29959
  if (amount.lessThanOrEqualTo(0)) {
29942
29960
  logger.error(
29943
29961
  `Invalid withdrawal amount: ${amount.toNumber()}. Amount must be positive.`
29944
29962
  );
29945
- return false;
29963
+ return {
29964
+ status: false,
29965
+ receivedTxnHash: false
29966
+ };
29946
29967
  }
29947
29968
  if (amount.lessThanOrEqualTo(this.minimumExtendedMovementAmount)) {
29948
29969
  logger.warn(
29949
29970
  `Withdrawal amount ${amount.toNumber()} is below minimum Extended movement amount ${this.minimumExtendedMovementAmount}. Skipping withdrawal.`
29950
29971
  );
29951
- return false;
29972
+ return {
29973
+ status: false,
29974
+ receivedTxnHash: false
29975
+ };
29952
29976
  }
29953
29977
  const holdings = await this.getExtendedDepositAmount();
29954
29978
  if (!holdings) {
29955
29979
  logger.error(
29956
29980
  "Cannot get holdings - unable to validate withdrawal amount"
29957
29981
  );
29958
- return false;
29982
+ return {
29983
+ status: false,
29984
+ receivedTxnHash: false
29985
+ };
29959
29986
  }
29960
29987
  const availableForWithdrawal = parseFloat(
29961
29988
  holdings.availableForWithdrawal
@@ -29964,14 +29991,20 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29964
29991
  logger.error(
29965
29992
  `Invalid availableForWithdrawal: ${holdings.availableForWithdrawal}. Expected a finite, non-negative number.`
29966
29993
  );
29967
- return false;
29994
+ return {
29995
+ status: false,
29996
+ receivedTxnHash: false
29997
+ };
29968
29998
  }
29969
29999
  const withdrawalAmount = amount.toNumber();
29970
30000
  if (withdrawalAmount > availableForWithdrawal) {
29971
30001
  logger.error(
29972
30002
  `Withdrawal amount ${withdrawalAmount} exceeds available balance ${availableForWithdrawal}`
29973
30003
  );
29974
- return false;
30004
+ return {
30005
+ status: false,
30006
+ receivedTxnHash: false
30007
+ };
29975
30008
  }
29976
30009
  logger.info(
29977
30010
  `Withdrawing ${withdrawalAmount} from Extended. Available balance: ${availableForWithdrawal}`
@@ -29984,15 +30017,24 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29984
30017
  withdrawalRequest.data,
29985
30018
  "WITHDRAWAL" /* WITHDRAWAL */
29986
30019
  );
29987
- return withdrawalStatus;
30020
+ return {
30021
+ status: true,
30022
+ receivedTxnHash: withdrawalStatus
30023
+ };
29988
30024
  }
29989
30025
  logger.error(
29990
30026
  `Withdrawal request failed with status: ${withdrawalRequest.status}`
29991
30027
  );
29992
- return false;
30028
+ return {
30029
+ status: false,
30030
+ receivedTxnHash: false
30031
+ };
29993
30032
  } catch (error) {
29994
30033
  logger.error(`Error creating Withdraw Call: ${error}`);
29995
- return false;
30034
+ return {
30035
+ status: false,
30036
+ receivedTxnHash: false
30037
+ };
29996
30038
  }
29997
30039
  }
29998
30040
  async getHealthFactor() {
@@ -30478,360 +30520,690 @@ var UnusedBalanceAdapter = class _UnusedBalanceAdapter extends BaseAdapter {
30478
30520
  }
30479
30521
  };
30480
30522
 
30481
- // src/strategies/universal-strategy.tsx
30482
- var AUMTypes = /* @__PURE__ */ ((AUMTypes2) => {
30483
- AUMTypes2["FINALISED"] = "finalised";
30484
- AUMTypes2["DEFISPRING"] = "defispring";
30485
- return AUMTypes2;
30486
- })(AUMTypes || {});
30487
- var PositionTypeAvnuExtended = /* @__PURE__ */ ((PositionTypeAvnuExtended2) => {
30488
- PositionTypeAvnuExtended2["OPEN"] = "open";
30489
- PositionTypeAvnuExtended2["CLOSE"] = "close";
30490
- return PositionTypeAvnuExtended2;
30491
- })(PositionTypeAvnuExtended || {});
30492
- var UNIVERSAL_MANAGE_IDS = /* @__PURE__ */ ((UNIVERSAL_MANAGE_IDS2) => {
30493
- UNIVERSAL_MANAGE_IDS2["FLASH_LOAN"] = "flash_loan_init";
30494
- UNIVERSAL_MANAGE_IDS2["VESU_LEG1"] = "vesu_leg1";
30495
- UNIVERSAL_MANAGE_IDS2["VESU_LEG2"] = "vesu_leg2";
30496
- UNIVERSAL_MANAGE_IDS2["APPROVE_TOKEN1"] = "approve_token1";
30497
- UNIVERSAL_MANAGE_IDS2["APPROVE_TOKEN2"] = "approve_token2";
30498
- UNIVERSAL_MANAGE_IDS2["APPROVE_BRING_LIQUIDITY"] = "approve_bring_liquidity";
30499
- UNIVERSAL_MANAGE_IDS2["BRING_LIQUIDITY"] = "bring_liquidity";
30500
- UNIVERSAL_MANAGE_IDS2["DEFISPRING_REWARDS"] = "defispring_rewards";
30501
- UNIVERSAL_MANAGE_IDS2["APPROVE_SWAP_TOKEN1"] = "approve_swap_token1";
30502
- UNIVERSAL_MANAGE_IDS2["AVNU_SWAP_REWARDS"] = "avnu_swap_rewards";
30503
- return UNIVERSAL_MANAGE_IDS2;
30504
- })(UNIVERSAL_MANAGE_IDS || {});
30505
- function getContractDetails(settings) {
30506
- const contracts = [
30507
- { address: settings.vaultAddress, name: "Vault" },
30508
- { address: settings.manager, name: "Vault Manager" },
30509
- { address: settings.vaultAllocator, name: "Vault Allocator" },
30510
- { address: settings.redeemRequestNFT, name: "Redeem Request NFT" }
30511
- ];
30512
- if (settings.aumOracle) {
30513
- contracts.push({ address: settings.aumOracle, name: "AUM Oracle" });
30523
+ // src/strategies/universal-adapters/avnu-adapter.ts
30524
+ import { hash as hash7, uint256 as uint25614 } from "starknet";
30525
+ import axios10 from "axios";
30526
+ var AvnuAdapter = class _AvnuAdapter extends BaseAdapter {
30527
+ constructor(config) {
30528
+ super(config, _AvnuAdapter.name, Protocols.AVNU);
30529
+ this.config = config;
30530
+ this.avnuWrapper = new AvnuWrapper();
30514
30531
  }
30515
- return contracts;
30516
- }
30517
-
30518
- // src/strategies/svk-strategy.ts
30519
- import { Contract as Contract13, num as num10 } from "starknet";
30520
-
30521
- // src/data/universal-vault.abi.json
30522
- var universal_vault_abi_default = [
30523
- {
30524
- type: "impl",
30525
- name: "UpgradeableImpl",
30526
- interface_name: "openzeppelin_interfaces::upgrades::IUpgradeable"
30527
- },
30528
- {
30529
- type: "interface",
30530
- name: "openzeppelin_interfaces::upgrades::IUpgradeable",
30531
- items: [
30532
+ //abstract means the method has no implementation in this class; instead, child classes must implement it.
30533
+ async getAPY(supportedPosition) {
30534
+ return Promise.resolve({ apy: 0, type: "base" /* BASE */ });
30535
+ }
30536
+ async getPosition(supportedPosition) {
30537
+ return Promise.resolve({ amount: new Web3Number(0, 0), remarks: "" });
30538
+ }
30539
+ async maxDeposit(amount) {
30540
+ return Promise.resolve({
30541
+ tokenInfo: this.config.baseToken,
30542
+ amount: new Web3Number(0, 0),
30543
+ usdValue: 0,
30544
+ apy: { apy: 0, type: "base" /* BASE */ },
30545
+ protocol: Protocols.AVNU,
30546
+ remarks: ""
30547
+ });
30548
+ }
30549
+ async maxWithdraw() {
30550
+ return Promise.resolve({
30551
+ tokenInfo: this.config.baseToken,
30552
+ amount: new Web3Number(0, 0),
30553
+ usdValue: 0,
30554
+ apy: { apy: 0, type: "base" /* BASE */ },
30555
+ protocol: Protocols.AVNU,
30556
+ remarks: ""
30557
+ });
30558
+ }
30559
+ _getDepositLeaf() {
30560
+ const vaultAllocator = ContractAddr.from(
30561
+ this.config.vaultAllocator.address
30562
+ );
30563
+ return [
30532
30564
  {
30533
- type: "function",
30534
- name: "upgrade",
30535
- inputs: [
30536
- {
30537
- name: "new_class_hash",
30538
- type: "core::starknet::class_hash::ClassHash"
30539
- }
30565
+ target: this.config.supportedPositions[0].asset.address,
30566
+ method: "approve",
30567
+ packedArguments: [
30568
+ AVNU_EXCHANGE.toBigInt()
30540
30569
  ],
30541
- outputs: [],
30542
- state_mutability: "external"
30543
- }
30544
- ]
30545
- },
30546
- {
30547
- type: "impl",
30548
- name: "VaultMetadataImpl",
30549
- interface_name: "openzeppelin_interfaces::token::erc20::IERC20Metadata"
30550
- },
30551
- {
30552
- type: "struct",
30553
- name: "core::byte_array::ByteArray",
30554
- members: [
30555
- {
30556
- name: "data",
30557
- type: "core::array::Array::<core::bytes_31::bytes31>"
30558
- },
30559
- {
30560
- name: "pending_word",
30561
- type: "core::felt252"
30570
+ sanitizer: SIMPLE_SANITIZER,
30571
+ id: `approve_${this.config.supportedPositions[0].asset.symbol}`
30562
30572
  },
30563
30573
  {
30564
- name: "pending_word_len",
30565
- type: "core::integer::u32"
30566
- }
30567
- ]
30568
- },
30569
- {
30570
- type: "interface",
30571
- name: "openzeppelin_interfaces::token::erc20::IERC20Metadata",
30572
- items: [
30573
- {
30574
- type: "function",
30575
- name: "name",
30576
- inputs: [],
30577
- outputs: [
30578
- {
30579
- type: "core::byte_array::ByteArray"
30580
- }
30574
+ target: AVNU_EXCHANGE,
30575
+ method: "multi_route_swap",
30576
+ packedArguments: [
30577
+ this.config.supportedPositions[0].asset.address.toBigInt(),
30578
+ //usdc
30579
+ this.config.supportedPositions[1].asset.address.toBigInt(),
30580
+ //wbtc
30581
+ vaultAllocator.toBigInt()
30581
30582
  ],
30582
- state_mutability: "view"
30583
- },
30583
+ sanitizer: SIMPLE_SANITIZER,
30584
+ id: `asutb_${this.config.supportedPositions[0].asset.symbol}_${this.config.supportedPositions[1].asset.symbol}`
30585
+ }
30586
+ ];
30587
+ }
30588
+ _getWithdrawLeaf() {
30589
+ const vaultAllocator = ContractAddr.from(
30590
+ this.config.vaultAllocator.address
30591
+ );
30592
+ const toToken = this.config.supportedPositions[0].asset;
30593
+ const fromToken = this.config.supportedPositions[1].asset;
30594
+ return [
30584
30595
  {
30585
- type: "function",
30586
- name: "symbol",
30587
- inputs: [],
30588
- outputs: [
30589
- {
30590
- type: "core::byte_array::ByteArray"
30591
- }
30596
+ target: fromToken.address,
30597
+ method: "approve",
30598
+ packedArguments: [
30599
+ AVNU_EXCHANGE.toBigInt()
30592
30600
  ],
30593
- state_mutability: "view"
30601
+ sanitizer: SIMPLE_SANITIZER,
30602
+ id: `approve_${fromToken.symbol}`
30594
30603
  },
30595
30604
  {
30596
- type: "function",
30597
- name: "decimals",
30598
- inputs: [],
30599
- outputs: [
30600
- {
30601
- type: "core::integer::u8"
30602
- }
30605
+ target: AVNU_EXCHANGE,
30606
+ method: "multi_route_swap",
30607
+ packedArguments: [
30608
+ fromToken.address.toBigInt(),
30609
+ //wbtc
30610
+ toToken.address.toBigInt(),
30611
+ //usdc
30612
+ vaultAllocator.toBigInt()
30603
30613
  ],
30604
- state_mutability: "view"
30605
- }
30606
- ]
30607
- },
30608
- {
30609
- type: "impl",
30610
- name: "VaultImpl",
30611
- interface_name: "vault::vault::interface::IVault"
30612
- },
30613
- {
30614
- type: "struct",
30615
- name: "core::integer::u256",
30616
- members: [
30617
- {
30618
- name: "low",
30619
- type: "core::integer::u128"
30620
- },
30621
- {
30622
- name: "high",
30623
- type: "core::integer::u128"
30614
+ sanitizer: SIMPLE_SANITIZER,
30615
+ id: `asbtu_${fromToken.symbol}_${fromToken.symbol}`
30624
30616
  }
30625
- ]
30626
- },
30627
- {
30628
- type: "interface",
30629
- name: "vault::vault::interface::IVault",
30630
- items: [
30631
- {
30632
- type: "function",
30633
- name: "register_redeem_request",
30634
- inputs: [
30635
- {
30636
- name: "redeem_request",
30637
- type: "core::starknet::contract_address::ContractAddress"
30638
- }
30639
- ],
30640
- outputs: [],
30641
- state_mutability: "external"
30642
- },
30643
- {
30644
- type: "function",
30645
- name: "register_vault_allocator",
30646
- inputs: [
30647
- {
30648
- name: "vault_allocator",
30649
- type: "core::starknet::contract_address::ContractAddress"
30650
- }
30651
- ],
30652
- outputs: [],
30653
- state_mutability: "external"
30654
- },
30655
- {
30656
- type: "function",
30657
- name: "request_redeem",
30658
- inputs: [
30659
- {
30660
- name: "shares",
30661
- type: "core::integer::u256"
30662
- },
30663
- {
30664
- name: "receiver",
30665
- type: "core::starknet::contract_address::ContractAddress"
30666
- },
30667
- {
30668
- name: "owner",
30669
- type: "core::starknet::contract_address::ContractAddress"
30670
- }
30671
- ],
30672
- outputs: [
30673
- {
30674
- type: "core::integer::u256"
30675
- }
30676
- ],
30677
- state_mutability: "external"
30678
- },
30679
- {
30680
- type: "function",
30681
- name: "claim_redeem",
30682
- inputs: [
30683
- {
30684
- name: "id",
30685
- type: "core::integer::u256"
30686
- }
30687
- ],
30688
- outputs: [
30689
- {
30690
- type: "core::integer::u256"
30691
- }
30692
- ],
30693
- state_mutability: "external"
30694
- },
30695
- {
30696
- type: "function",
30697
- name: "set_fees_config",
30698
- inputs: [
30699
- {
30700
- name: "fees_recipient",
30701
- type: "core::starknet::contract_address::ContractAddress"
30702
- },
30703
- {
30704
- name: "redeem_fees",
30705
- type: "core::integer::u256"
30706
- },
30707
- {
30708
- name: "management_fees",
30709
- type: "core::integer::u256"
30710
- },
30711
- {
30712
- name: "performance_fees",
30713
- type: "core::integer::u256"
30714
- }
30715
- ],
30716
- outputs: [],
30717
- state_mutability: "external"
30718
- },
30719
- {
30720
- type: "function",
30721
- name: "set_report_delay",
30722
- inputs: [
30723
- {
30724
- name: "report_delay",
30725
- type: "core::integer::u64"
30617
+ ];
30618
+ }
30619
+ _getLegacySwapLeaf() {
30620
+ return [];
30621
+ }
30622
+ async getDepositCall(params) {
30623
+ try {
30624
+ const fromToken = this.config.supportedPositions[0].asset;
30625
+ const toToken = this.config.supportedPositions[1].asset;
30626
+ const vaultAllocator = ContractAddr.from(
30627
+ this.config.vaultAllocator.address
30628
+ );
30629
+ const quote = await this.getQuotesAvnu(
30630
+ fromToken.address.toString(),
30631
+ toToken.address.toString(),
30632
+ params.amount.toNumber(),
30633
+ vaultAllocator.address.toString(),
30634
+ toToken.decimals,
30635
+ true
30636
+ );
30637
+ if (!quote) {
30638
+ logger.error("error getting quote from avnu");
30639
+ return [];
30640
+ }
30641
+ const getCalldata = await this.avnuWrapper.getSwapCallData(
30642
+ quote,
30643
+ vaultAllocator.address
30644
+ );
30645
+ const swapCallData = getCalldata[0];
30646
+ const amount = uint25614.bnToUint256(quote.sellAmountInUsd * 10 ** 7);
30647
+ return [
30648
+ {
30649
+ sanitizer: SIMPLE_SANITIZER,
30650
+ call: {
30651
+ contractAddress: fromToken.address,
30652
+ selector: hash7.getSelectorFromName("approve"),
30653
+ calldata: [
30654
+ AVNU_EXCHANGE.toBigInt(),
30655
+ toBigInt(amount.low.toString()),
30656
+ // amount low
30657
+ toBigInt(amount.high.toString())
30658
+ // amount high
30659
+ ]
30726
30660
  }
30727
- ],
30728
- outputs: [],
30729
- state_mutability: "external"
30730
- },
30731
- {
30732
- type: "function",
30733
- name: "set_max_delta",
30734
- inputs: [
30735
- {
30736
- name: "max_delta",
30737
- type: "core::integer::u256"
30661
+ },
30662
+ {
30663
+ sanitizer: SIMPLE_SANITIZER,
30664
+ call: {
30665
+ contractAddress: AVNU_EXCHANGE,
30666
+ selector: hash7.getSelectorFromName("multi_route_swap"),
30667
+ calldata: swapCallData
30738
30668
  }
30739
- ],
30740
- outputs: [],
30741
- state_mutability: "external"
30742
- },
30743
- {
30744
- type: "function",
30745
- name: "report",
30746
- inputs: [
30747
- {
30748
- name: "new_aum",
30749
- type: "core::integer::u256"
30669
+ }
30670
+ ];
30671
+ } catch (error) {
30672
+ logger.error(`Error getting Avnu quote: ${error}`);
30673
+ return [];
30674
+ }
30675
+ }
30676
+ //Swap wbtc to usdc
30677
+ async getWithdrawCall(params) {
30678
+ try {
30679
+ const toToken = this.config.supportedPositions[0].asset;
30680
+ const fromToken = this.config.supportedPositions[1].asset;
30681
+ const vaultAllocator = ContractAddr.from(
30682
+ this.config.vaultAllocator.address
30683
+ );
30684
+ const quote = await this.getQuotesAvnu(
30685
+ fromToken.address.toString(),
30686
+ toToken.address.toString(),
30687
+ params.amount.toNumber(),
30688
+ vaultAllocator.address.toString(),
30689
+ fromToken.decimals,
30690
+ false
30691
+ );
30692
+ if (!quote) {
30693
+ logger.error("No quotes available for this swap, error in quotes avnu");
30694
+ return [];
30695
+ }
30696
+ const getCalldata = await this.avnuWrapper.getSwapCallData(
30697
+ quote,
30698
+ vaultAllocator.address
30699
+ );
30700
+ const swapCallData = getCalldata[0];
30701
+ const amount = uint25614.bnToUint256(params.amount.toWei());
30702
+ return [
30703
+ {
30704
+ sanitizer: SIMPLE_SANITIZER,
30705
+ call: {
30706
+ contractAddress: fromToken.address,
30707
+ selector: hash7.getSelectorFromName("approve"),
30708
+ calldata: [
30709
+ AVNU_EXCHANGE.toBigInt(),
30710
+ toBigInt(amount.low.toString()),
30711
+ // amount low
30712
+ toBigInt(amount.high.toString())
30713
+ // amount high
30714
+ ]
30750
30715
  }
30751
- ],
30752
- outputs: [],
30753
- state_mutability: "external"
30754
- },
30755
- {
30756
- type: "function",
30757
- name: "bring_liquidity",
30758
- inputs: [
30759
- {
30760
- name: "amount",
30761
- type: "core::integer::u256"
30716
+ },
30717
+ {
30718
+ sanitizer: SIMPLE_SANITIZER,
30719
+ call: {
30720
+ contractAddress: AVNU_EXCHANGE,
30721
+ selector: hash7.getSelectorFromName("multi_route_swap"),
30722
+ calldata: swapCallData
30762
30723
  }
30763
- ],
30764
- outputs: [],
30765
- state_mutability: "external"
30766
- },
30767
- {
30768
- type: "function",
30769
- name: "pause",
30770
- inputs: [],
30771
- outputs: [],
30772
- state_mutability: "external"
30773
- },
30774
- {
30775
- type: "function",
30776
- name: "unpause",
30777
- inputs: [],
30778
- outputs: [],
30779
- state_mutability: "external"
30780
- },
30781
- {
30782
- type: "function",
30783
- name: "epoch",
30784
- inputs: [],
30785
- outputs: [
30724
+ }
30725
+ ];
30726
+ } catch (error) {
30727
+ logger.error(`Error getting Avnu quote: ${error}`);
30728
+ return [];
30729
+ }
30730
+ }
30731
+ async getSwapCallData(quote) {
30732
+ return await this.avnuWrapper.getSwapCallData(quote, this.config.vaultAllocator.address);
30733
+ }
30734
+ async getHealthFactor() {
30735
+ return Promise.resolve(1);
30736
+ }
30737
+ async fetchQuoteWithRetry(params, retries = 5) {
30738
+ for (let attempt = 0; attempt < retries; attempt++) {
30739
+ try {
30740
+ const response = await axios10.get(this.config.baseUrl, { params });
30741
+ if (response.data && response.data.length > 0) {
30742
+ return response;
30743
+ }
30744
+ throw new Error("Empty response data");
30745
+ } catch (err) {
30746
+ logger.error(`Error fetching quote with retry: ${err}`);
30747
+ if (attempt === retries - 1) {
30748
+ throw err;
30749
+ }
30750
+ await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
30751
+ }
30752
+ }
30753
+ throw new Error("Failed to fetch quote after retries");
30754
+ }
30755
+ async getQuotesAvnu(from_token_address, to_token_address, amount, takerAddress, toTokenDecimals, usdcToBtc, maxIterations = 5, tolerance = 5e3) {
30756
+ try {
30757
+ const fromToken = this.config.supportedPositions[0].asset;
30758
+ const toToken = this.config.supportedPositions[1].asset;
30759
+ if (!usdcToBtc) {
30760
+ const sellAmount2 = returnFormattedAmount(amount, toTokenDecimals);
30761
+ const params2 = {
30762
+ sellTokenAddress: from_token_address,
30763
+ buyTokenAddress: to_token_address,
30764
+ takerAddress,
30765
+ sellAmount: sellAmount2
30766
+ };
30767
+ const finalQuote2 = await this.fetchQuoteWithRetry(params2);
30768
+ if (!finalQuote2.data.length) {
30769
+ logger.error("No quotes available for this swap, error in quotes avnu");
30770
+ return null;
30771
+ }
30772
+ const dataObject2 = finalQuote2.data[0];
30773
+ return dataObject2;
30774
+ }
30775
+ const btcPrice = await this.getPriceOfToken(toToken.address.toString());
30776
+ if (!btcPrice) {
30777
+ logger.error(`error getting btc price: ${btcPrice}`);
30778
+ return null;
30779
+ }
30780
+ const estimatedUsdcAmount = Math.floor(amount * btcPrice);
30781
+ const targetBtcBig = BigInt(returnFormattedAmount(amount, toTokenDecimals));
30782
+ let low = BigInt(
30783
+ Math.floor(
30784
+ estimatedUsdcAmount * 10 ** fromToken.decimals * 0.9
30785
+ )
30786
+ );
30787
+ let high = BigInt(
30788
+ Math.floor(
30789
+ estimatedUsdcAmount * 10 ** fromToken.decimals * 1.1
30790
+ )
30791
+ );
30792
+ let mid = 0n;
30793
+ for (let i = 0; i < maxIterations; i++) {
30794
+ mid = (low + high) / 2n;
30795
+ const sellAmount2 = returnFormattedAmount(Number(mid), 0);
30796
+ const quote = await this.fetchQuoteWithRetry({
30797
+ sellTokenAddress: from_token_address,
30798
+ buyTokenAddress: to_token_address,
30799
+ takerAddress,
30800
+ sellAmount: sellAmount2
30801
+ });
30802
+ const gotBtc = BigInt(quote.data[0].buyAmount);
30803
+ if (gotBtc === targetBtcBig) return quote.data[0];
30804
+ if (gotBtc > targetBtcBig) {
30805
+ high = mid;
30806
+ } else {
30807
+ low = mid;
30808
+ }
30809
+ if (gotBtc >= targetBtcBig && gotBtc <= targetBtcBig + BigInt(tolerance)) {
30810
+ return quote.data[0];
30811
+ }
30812
+ }
30813
+ let sellAmount = returnFormattedAmount(
30814
+ Number(mid),
30815
+ 0
30816
+ );
30817
+ const params = {
30818
+ sellTokenAddress: from_token_address,
30819
+ buyTokenAddress: to_token_address,
30820
+ takerAddress,
30821
+ sellAmount
30822
+ };
30823
+ const finalQuote = await this.fetchQuoteWithRetry(params);
30824
+ if (!finalQuote.data.length) {
30825
+ logger.error("No quotes available for this swap, error in quotes avnu");
30826
+ return null;
30827
+ }
30828
+ const dataObject = finalQuote.data[0];
30829
+ return dataObject;
30830
+ } catch (err) {
30831
+ logger.error(`No quotes available for this swap: ${err}`);
30832
+ return null;
30833
+ }
30834
+ }
30835
+ async getPriceOfToken(tokenAddress, retries = MAX_RETRIES) {
30836
+ try {
30837
+ const url = `https://starknet.impulse.avnu.fi/v1/tokens/${tokenAddress}/prices/line`;
30838
+ const response = await axios10.get(url);
30839
+ const length = response.data.length;
30840
+ return response.data[length - 1].value;
30841
+ } catch (err) {
30842
+ if (retries > 0) {
30843
+ await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
30844
+ return this.getPriceOfToken(tokenAddress, retries - 1);
30845
+ } else {
30846
+ logger.error(`Failed to fetch price for ${tokenAddress} after ${MAX_RETRIES} attempts`);
30847
+ return null;
30848
+ }
30849
+ }
30850
+ }
30851
+ };
30852
+
30853
+ // src/strategies/universal-strategy.tsx
30854
+ var AUMTypes = /* @__PURE__ */ ((AUMTypes2) => {
30855
+ AUMTypes2["FINALISED"] = "finalised";
30856
+ AUMTypes2["DEFISPRING"] = "defispring";
30857
+ return AUMTypes2;
30858
+ })(AUMTypes || {});
30859
+ var PositionTypeAvnuExtended = /* @__PURE__ */ ((PositionTypeAvnuExtended2) => {
30860
+ PositionTypeAvnuExtended2["OPEN"] = "open";
30861
+ PositionTypeAvnuExtended2["CLOSE"] = "close";
30862
+ return PositionTypeAvnuExtended2;
30863
+ })(PositionTypeAvnuExtended || {});
30864
+ var UNIVERSAL_MANAGE_IDS = /* @__PURE__ */ ((UNIVERSAL_MANAGE_IDS2) => {
30865
+ UNIVERSAL_MANAGE_IDS2["FLASH_LOAN"] = "flash_loan_init";
30866
+ UNIVERSAL_MANAGE_IDS2["VESU_LEG1"] = "vesu_leg1";
30867
+ UNIVERSAL_MANAGE_IDS2["VESU_LEG2"] = "vesu_leg2";
30868
+ UNIVERSAL_MANAGE_IDS2["APPROVE_TOKEN1"] = "approve_token1";
30869
+ UNIVERSAL_MANAGE_IDS2["APPROVE_TOKEN2"] = "approve_token2";
30870
+ UNIVERSAL_MANAGE_IDS2["APPROVE_BRING_LIQUIDITY"] = "approve_bring_liquidity";
30871
+ UNIVERSAL_MANAGE_IDS2["BRING_LIQUIDITY"] = "bring_liquidity";
30872
+ UNIVERSAL_MANAGE_IDS2["DEFISPRING_REWARDS"] = "defispring_rewards";
30873
+ UNIVERSAL_MANAGE_IDS2["APPROVE_SWAP_TOKEN1"] = "approve_swap_token1";
30874
+ UNIVERSAL_MANAGE_IDS2["AVNU_SWAP_REWARDS"] = "avnu_swap_rewards";
30875
+ return UNIVERSAL_MANAGE_IDS2;
30876
+ })(UNIVERSAL_MANAGE_IDS || {});
30877
+ function getContractDetails(settings) {
30878
+ const contracts = [
30879
+ { address: settings.vaultAddress, name: "Vault" },
30880
+ { address: settings.manager, name: "Vault Manager" },
30881
+ { address: settings.vaultAllocator, name: "Vault Allocator" },
30882
+ { address: settings.redeemRequestNFT, name: "Redeem Request NFT" }
30883
+ ];
30884
+ if (settings.aumOracle) {
30885
+ contracts.push({ address: settings.aumOracle, name: "AUM Oracle" });
30886
+ }
30887
+ return contracts;
30888
+ }
30889
+
30890
+ // src/strategies/svk-strategy.ts
30891
+ import { Contract as Contract13, num as num10 } from "starknet";
30892
+
30893
+ // src/data/universal-vault.abi.json
30894
+ var universal_vault_abi_default = [
30895
+ {
30896
+ type: "impl",
30897
+ name: "UpgradeableImpl",
30898
+ interface_name: "openzeppelin_interfaces::upgrades::IUpgradeable"
30899
+ },
30900
+ {
30901
+ type: "interface",
30902
+ name: "openzeppelin_interfaces::upgrades::IUpgradeable",
30903
+ items: [
30904
+ {
30905
+ type: "function",
30906
+ name: "upgrade",
30907
+ inputs: [
30786
30908
  {
30787
- type: "core::integer::u256"
30909
+ name: "new_class_hash",
30910
+ type: "core::starknet::class_hash::ClassHash"
30788
30911
  }
30789
30912
  ],
30790
- state_mutability: "view"
30913
+ outputs: [],
30914
+ state_mutability: "external"
30915
+ }
30916
+ ]
30917
+ },
30918
+ {
30919
+ type: "impl",
30920
+ name: "VaultMetadataImpl",
30921
+ interface_name: "openzeppelin_interfaces::token::erc20::IERC20Metadata"
30922
+ },
30923
+ {
30924
+ type: "struct",
30925
+ name: "core::byte_array::ByteArray",
30926
+ members: [
30927
+ {
30928
+ name: "data",
30929
+ type: "core::array::Array::<core::bytes_31::bytes31>"
30930
+ },
30931
+ {
30932
+ name: "pending_word",
30933
+ type: "core::felt252"
30791
30934
  },
30935
+ {
30936
+ name: "pending_word_len",
30937
+ type: "core::integer::u32"
30938
+ }
30939
+ ]
30940
+ },
30941
+ {
30942
+ type: "interface",
30943
+ name: "openzeppelin_interfaces::token::erc20::IERC20Metadata",
30944
+ items: [
30792
30945
  {
30793
30946
  type: "function",
30794
- name: "handled_epoch_len",
30947
+ name: "name",
30795
30948
  inputs: [],
30796
30949
  outputs: [
30797
30950
  {
30798
- type: "core::integer::u256"
30951
+ type: "core::byte_array::ByteArray"
30799
30952
  }
30800
30953
  ],
30801
30954
  state_mutability: "view"
30802
30955
  },
30803
30956
  {
30804
30957
  type: "function",
30805
- name: "buffer",
30958
+ name: "symbol",
30806
30959
  inputs: [],
30807
30960
  outputs: [
30808
30961
  {
30809
- type: "core::integer::u256"
30962
+ type: "core::byte_array::ByteArray"
30810
30963
  }
30811
30964
  ],
30812
30965
  state_mutability: "view"
30813
30966
  },
30814
30967
  {
30815
30968
  type: "function",
30816
- name: "aum",
30969
+ name: "decimals",
30817
30970
  inputs: [],
30818
30971
  outputs: [
30819
30972
  {
30820
- type: "core::integer::u256"
30973
+ type: "core::integer::u8"
30821
30974
  }
30822
30975
  ],
30823
30976
  state_mutability: "view"
30977
+ }
30978
+ ]
30979
+ },
30980
+ {
30981
+ type: "impl",
30982
+ name: "VaultImpl",
30983
+ interface_name: "vault::vault::interface::IVault"
30984
+ },
30985
+ {
30986
+ type: "struct",
30987
+ name: "core::integer::u256",
30988
+ members: [
30989
+ {
30990
+ name: "low",
30991
+ type: "core::integer::u128"
30824
30992
  },
30825
30993
  {
30826
- type: "function",
30827
- name: "redeem_assets",
30828
- inputs: [
30829
- {
30830
- name: "epoch",
30831
- type: "core::integer::u256"
30832
- }
30833
- ],
30834
- outputs: [
30994
+ name: "high",
30995
+ type: "core::integer::u128"
30996
+ }
30997
+ ]
30998
+ },
30999
+ {
31000
+ type: "interface",
31001
+ name: "vault::vault::interface::IVault",
31002
+ items: [
31003
+ {
31004
+ type: "function",
31005
+ name: "register_redeem_request",
31006
+ inputs: [
31007
+ {
31008
+ name: "redeem_request",
31009
+ type: "core::starknet::contract_address::ContractAddress"
31010
+ }
31011
+ ],
31012
+ outputs: [],
31013
+ state_mutability: "external"
31014
+ },
31015
+ {
31016
+ type: "function",
31017
+ name: "register_vault_allocator",
31018
+ inputs: [
31019
+ {
31020
+ name: "vault_allocator",
31021
+ type: "core::starknet::contract_address::ContractAddress"
31022
+ }
31023
+ ],
31024
+ outputs: [],
31025
+ state_mutability: "external"
31026
+ },
31027
+ {
31028
+ type: "function",
31029
+ name: "request_redeem",
31030
+ inputs: [
31031
+ {
31032
+ name: "shares",
31033
+ type: "core::integer::u256"
31034
+ },
31035
+ {
31036
+ name: "receiver",
31037
+ type: "core::starknet::contract_address::ContractAddress"
31038
+ },
31039
+ {
31040
+ name: "owner",
31041
+ type: "core::starknet::contract_address::ContractAddress"
31042
+ }
31043
+ ],
31044
+ outputs: [
31045
+ {
31046
+ type: "core::integer::u256"
31047
+ }
31048
+ ],
31049
+ state_mutability: "external"
31050
+ },
31051
+ {
31052
+ type: "function",
31053
+ name: "claim_redeem",
31054
+ inputs: [
31055
+ {
31056
+ name: "id",
31057
+ type: "core::integer::u256"
31058
+ }
31059
+ ],
31060
+ outputs: [
31061
+ {
31062
+ type: "core::integer::u256"
31063
+ }
31064
+ ],
31065
+ state_mutability: "external"
31066
+ },
31067
+ {
31068
+ type: "function",
31069
+ name: "set_fees_config",
31070
+ inputs: [
31071
+ {
31072
+ name: "fees_recipient",
31073
+ type: "core::starknet::contract_address::ContractAddress"
31074
+ },
31075
+ {
31076
+ name: "redeem_fees",
31077
+ type: "core::integer::u256"
31078
+ },
31079
+ {
31080
+ name: "management_fees",
31081
+ type: "core::integer::u256"
31082
+ },
31083
+ {
31084
+ name: "performance_fees",
31085
+ type: "core::integer::u256"
31086
+ }
31087
+ ],
31088
+ outputs: [],
31089
+ state_mutability: "external"
31090
+ },
31091
+ {
31092
+ type: "function",
31093
+ name: "set_report_delay",
31094
+ inputs: [
31095
+ {
31096
+ name: "report_delay",
31097
+ type: "core::integer::u64"
31098
+ }
31099
+ ],
31100
+ outputs: [],
31101
+ state_mutability: "external"
31102
+ },
31103
+ {
31104
+ type: "function",
31105
+ name: "set_max_delta",
31106
+ inputs: [
31107
+ {
31108
+ name: "max_delta",
31109
+ type: "core::integer::u256"
31110
+ }
31111
+ ],
31112
+ outputs: [],
31113
+ state_mutability: "external"
31114
+ },
31115
+ {
31116
+ type: "function",
31117
+ name: "report",
31118
+ inputs: [
31119
+ {
31120
+ name: "new_aum",
31121
+ type: "core::integer::u256"
31122
+ }
31123
+ ],
31124
+ outputs: [],
31125
+ state_mutability: "external"
31126
+ },
31127
+ {
31128
+ type: "function",
31129
+ name: "bring_liquidity",
31130
+ inputs: [
31131
+ {
31132
+ name: "amount",
31133
+ type: "core::integer::u256"
31134
+ }
31135
+ ],
31136
+ outputs: [],
31137
+ state_mutability: "external"
31138
+ },
31139
+ {
31140
+ type: "function",
31141
+ name: "pause",
31142
+ inputs: [],
31143
+ outputs: [],
31144
+ state_mutability: "external"
31145
+ },
31146
+ {
31147
+ type: "function",
31148
+ name: "unpause",
31149
+ inputs: [],
31150
+ outputs: [],
31151
+ state_mutability: "external"
31152
+ },
31153
+ {
31154
+ type: "function",
31155
+ name: "epoch",
31156
+ inputs: [],
31157
+ outputs: [
31158
+ {
31159
+ type: "core::integer::u256"
31160
+ }
31161
+ ],
31162
+ state_mutability: "view"
31163
+ },
31164
+ {
31165
+ type: "function",
31166
+ name: "handled_epoch_len",
31167
+ inputs: [],
31168
+ outputs: [
31169
+ {
31170
+ type: "core::integer::u256"
31171
+ }
31172
+ ],
31173
+ state_mutability: "view"
31174
+ },
31175
+ {
31176
+ type: "function",
31177
+ name: "buffer",
31178
+ inputs: [],
31179
+ outputs: [
31180
+ {
31181
+ type: "core::integer::u256"
31182
+ }
31183
+ ],
31184
+ state_mutability: "view"
31185
+ },
31186
+ {
31187
+ type: "function",
31188
+ name: "aum",
31189
+ inputs: [],
31190
+ outputs: [
31191
+ {
31192
+ type: "core::integer::u256"
31193
+ }
31194
+ ],
31195
+ state_mutability: "view"
31196
+ },
31197
+ {
31198
+ type: "function",
31199
+ name: "redeem_assets",
31200
+ inputs: [
31201
+ {
31202
+ name: "epoch",
31203
+ type: "core::integer::u256"
31204
+ }
31205
+ ],
31206
+ outputs: [
30835
31207
  {
30836
31208
  type: "core::integer::u256"
30837
31209
  }
@@ -33417,817 +33789,487 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
33417
33789
  } else {
33418
33790
  const adapters2 = await AdapterOptimizer.getAdapterToUse(allAdapters, false, params.leg1DepositAmount);
33419
33791
  if (adapters2.length > 0) {
33420
- const proofsInfo = adapters2.map((adapter) => adapter.getProofs(false, this.getMerkleTree()));
33421
- const calls = [];
33422
- for (const info of proofsInfo) {
33423
- const proofGroups = info.proofs;
33424
- const call = this.getManageCall(proofGroups, await info.callConstructor({ amount: params.leg1DepositAmount }));
33425
- calls.push(call);
33426
- }
33427
- return calls;
33428
- } else {
33429
- throw new Error(`${this.getTag()}::getVesuMultiplyCall: no adapters to use for unused balance: ${unusedBalance.amount.toString()}`);
33430
- }
33431
- }
33432
- }
33433
- const adapters = await AdapterOptimizer.getAdapterToUse(allAdapters, true, params.leg1DepositAmount);
33434
- if (adapters.length > 0) {
33435
- const proofsInfo = adapters.map((adapter) => adapter.getProofs(true, this.getMerkleTree()));
33436
- const calls = [];
33437
- for (const info of proofsInfo) {
33438
- const proofGroups = info.proofs;
33439
- const call = this.getManageCall(proofGroups, await info.callConstructor({ amount: params.leg1DepositAmount }));
33440
- calls.push(call);
33441
- }
33442
- return calls;
33443
- } else {
33444
- throw new Error(`${this.getTag()}::getVesuMultiplyCall: no adapters to use for deposit: ${params.leg1DepositAmount.toString()}`);
33445
- }
33446
- }
33447
- getLSTUnderlyingTokenInfo() {
33448
- return this.metadata.additionalInfo.underlyingToken;
33449
- }
33450
- // async getMaxBorrowableAmount(params: { isAPYComputation: boolean } = { isAPYComputation: false }) {
33451
- // const vesuAdapters = this.getVesuAdapters();
33452
- // let netMaxBorrowableAmount = Web3Number.fromWei("0", this.getLSTUnderlyingTokenInfo().decimals);
33453
- // const maxBorrowables: {amount: Web3Number, dexSwappableAmount: Web3Number, maxBorrowableAmount: Web3Number, borrowableAsset: TokenInfo}[] = [];
33454
- // for (const vesuAdapter of vesuAdapters) {
33455
- // maxBorrowables.push(await this.getMaxBorrowableAmountByVesuAdapter(vesuAdapter, params.isAPYComputation));
33456
- // }
33457
- // maxBorrowables.sort((a, b) => b.amount.toNumber() - a.amount.toNumber());
33458
- // netMaxBorrowableAmount = maxBorrowables.reduce((acc, curr) => acc.plus(curr.amount), Web3Number.fromWei("0", this.getLSTUnderlyingTokenInfo().decimals));
33459
- // return {netMaxBorrowableAmount, maxBorrowables};
33460
- // }
33461
- // recursively, using binary search computes max swappable.
33462
- // @dev assumes 1 token of from == 1 token of to
33463
- // async getMaxSwappableWithMaxSlippage(fromToken: TokenInfo, toToken: TokenInfo, maxSlippage: number, maxAmount: Web3Number) {
33464
- // const output = await findMaxInputWithSlippage({
33465
- // apiGetOutput: async (inputAmount: number): Promise<number> => {
33466
- // const ekuboQuoter = new EkuboQuoter(this.config);
33467
- // await new Promise(resolve => setTimeout(resolve, 1000)); // artificial delay, to avoid rate limit
33468
- // const quote = await ekuboQuoter.getQuote(fromToken.address.address, toToken.address.address, new Web3Number(inputAmount.toFixed(9), fromToken.decimals));
33469
- // return Web3Number.fromWei(quote.total_calculated.toString(), toToken.decimals).toNumber();
33470
- // },
33471
- // maxInput: maxAmount.toNumber(),
33472
- // maxSlippagePercent: maxSlippage,
33473
- // tolerance: 0.001,
33474
- // referenceRate: 1,
33475
- // });
33476
- // return new Web3Number(output.optimalInput, fromToken.decimals);
33477
- // }
33478
- // async getMaxBorrowableAmountByVesuAdapter(vesuAdapter: VesuAdapter, isAPYComputation: boolean) {
33479
- // const lstAPY = await this.getLSTAPR(this.getLSTUnderlyingTokenInfo().address);
33480
- // const maxInterestRate = lstAPY * 0.8;
33481
- // const maxBorrowableAmount = await vesuAdapter.getMaxBorrowableByInterestRate(this.config, vesuAdapter.config.debt, maxInterestRate);
33482
- // const debtCap = await vesuAdapter.getDebtCap(this.config);
33483
- // const maxBorrowable = maxBorrowableAmount.minimum(debtCap).multipliedBy(0.999);
33484
- // // Dont compute precise max swappable for APY computation
33485
- // if (vesuAdapter.config.debt.address.eq(this.getLSTUnderlyingTokenInfo().address) || isAPYComputation) {
33486
- // return {amount: maxBorrowable, dexSwappableAmount: maxBorrowable, maxBorrowableAmount: maxBorrowable, borrowableAsset: vesuAdapter.config.debt};
33487
- // }
33488
- // // Want < 0.02% slippage
33489
- // try {
33490
- // const maxSwappable = await this.getMaxSwappableWithMaxSlippage(vesuAdapter.config.debt, this.getLSTUnderlyingTokenInfo(), 0.0002, maxBorrowable);
33491
- // return {amount: maxBorrowable.minimum(maxSwappable), dexSwappableAmount: maxSwappable, maxBorrowableAmount: maxBorrowable, borrowableAsset: vesuAdapter.config.debt};
33492
- // } catch (error) {
33493
- // logger.warn(`${this.getTag()}: Failed to get max swappable: ${error}`);
33494
- // const maxSwappable = Web3Number.fromWei("0", vesuAdapter.config.debt.decimals);
33495
- // return {amount: maxBorrowable.minimum(maxSwappable), dexSwappableAmount: maxSwappable, maxBorrowableAmount: maxBorrowable, borrowableAsset: vesuAdapter.config.debt};
33496
- // }
33497
- // }
33498
- // todo how much to unwind to get back healthy APY zone again
33499
- // if net APY < LST APR + 0.5%, we need to unwind to get back to LST APR + 1% atleast or 0 vesu position
33500
- // For xSTRK, simply deposit in Vesu if looping is not viable
33501
- // /**
33502
- // * Gets LST APR for the strategy's underlying asset from Endur API
33503
- // * @returns Promise<number> The LST APR (not divided by 1e18)
33504
- // */
33505
- // async getLSTAPR(_address: ContractAddr): Promise<number> {
33506
- // try {
33507
- // const vesuAdapter1 = this.getVesuSameTokenAdapter();
33508
- // const apr = await LSTAPRService.getLSTAPR(vesuAdapter1.config.debt.address);
33509
- // if (!apr) {
33510
- // throw new Error('Failed to get LST APR');
33511
- // }
33512
- // return apr;
33513
- // } catch (error) {
33514
- // logger.warn(`${this.getTag()}: Failed to get LST APR: ${error}`);
33515
- // return 0;
33516
- // }
33517
- // }
33518
- // async maxNewDeposits(params: { isAPYComputation: boolean } = { isAPYComputation: false }) {
33519
- // const maxBorrowableAmounts = await this.getMaxBorrowableAmount(params);
33520
- // let ltv: number | undefined = undefined;
33521
- // for (let adapter of this.getVesuAdapters()) {
33522
- // const maxBorrowableAmount = maxBorrowableAmounts.maxBorrowables.find(b => b.borrowableAsset.address.eq(adapter.config.debt.address))?.amount;
33523
- // if (!maxBorrowableAmount) {
33524
- // throw new Error(`Max borrowable amount not found for adapter: ${adapter.config.debt.symbol}`);
33525
- // }
33526
- // const maxLTV = await adapter.getLTVConfig(this.config);
33527
- // if (!ltv) {
33528
- // ltv = maxLTV;
33529
- // } else if (ltv != maxLTV) {
33530
- // throw new Error(`LTV mismatch for adapter: ${adapter.config.debt.symbol}`);
33531
- // }
33532
- // }
33533
- // if (!ltv) {
33534
- // throw new Error('LTV not found');
33535
- // }
33536
- // // for simplicity, we assume 1 underlying = 1 LST
33537
- // const numerator = this.metadata.additionalInfo.targetHealthFactor * maxBorrowableAmounts.netMaxBorrowableAmount.toNumber() / (ltv)
33538
- // return numerator - maxBorrowableAmounts.netMaxBorrowableAmount.toNumber();
33539
- // }
33540
- async getAUM() {
33541
- const allPositions = [];
33542
- for (let adapter of this.metadata.additionalInfo.adapters) {
33543
- const positions = await adapter.adapter.getPositions();
33544
- allPositions.push(...positions);
33545
- }
33546
- const assetPrice = await this.pricer.getPrice(this.asset().symbol);
33547
- let netAUM = new Web3Number(0, this.asset().decimals);
33548
- for (let position of allPositions) {
33549
- if (position.tokenInfo.address.eq(this.asset().address)) {
33550
- netAUM = netAUM.plus(position.amount);
33551
- } else {
33552
- netAUM = netAUM.plus(position.usdValue / assetPrice.price);
33553
- }
33554
- }
33555
- const prevAum = await this.getPrevAUM();
33556
- const realAUM = {
33557
- tokenInfo: this.asset(),
33558
- amount: netAUM,
33559
- usdValue: netAUM.toNumber() * assetPrice.price,
33560
- apy: { apy: netAUM.toNumber() * assetPrice.price, type: "base" /* BASE */ },
33561
- remarks: "finalised" /* FINALISED */,
33562
- protocol: Protocols.NONE
33563
- // just placeholder
33564
- };
33565
- const estimatedAUMDelta = {
33566
- tokenInfo: this.asset(),
33567
- amount: Web3Number.fromWei("0", this.asset().decimals),
33568
- usdValue: 0,
33569
- apy: { apy: 0, type: "base" /* BASE */ },
33570
- remarks: "defispring" /* DEFISPRING */,
33571
- protocol: Protocols.NONE
33572
- // just placeholder
33573
- };
33574
- return { net: {
33575
- tokenInfo: this.asset(),
33576
- amount: netAUM,
33577
- usdValue: netAUM.toNumber() * assetPrice.price
33578
- }, prevAum, splits: [realAUM, estimatedAUMDelta] };
33579
- }
33580
- /**
33581
- *
33582
- * @param params marginAmount is in LST, debtAmount is in underlying
33583
- */
33584
- // async getModifyLeverCall(params: {
33585
- // marginAmount: Web3Number, // >0 during deposit
33586
- // debtAmount: Web3Number,
33587
- // lstDexPriceInUnderlying: number,
33588
- // isIncrease: boolean
33589
- // }): Promise<Call[]> {
33590
- // logger.verbose(`${this.getTag()}::getModifyLeverCall marginAmount: ${params.marginAmount}, debtAmount: ${params.debtAmount}, lstDexPriceInUnderlying: ${params.lstDexPriceInUnderlying}, isIncrease: ${params.isIncrease}`);
33591
- // const vesuAdapter = this.getVesuSameTokenAdapter();
33592
- // const manage0Info = vesuAdapter.
33593
- // const manageCall0 = manage0Info.callConstructor({
33594
- // amount: newDepositAmount
33595
- // });
33596
- // const manageCalls = await vesu
33597
- // return [this.getManageCall(proofsIDs, manageCalls)];
33598
- // }
33599
- };
33600
- function VaultDescription(lstSymbol, underlyingSymbol) {
33601
- const containerStyle = {
33602
- maxWidth: "800px",
33603
- margin: "0 auto",
33604
- backgroundColor: "#111",
33605
- color: "#eee",
33606
- fontFamily: "Arial, sans-serif",
33607
- borderRadius: "12px"
33608
- };
33609
- return /* @__PURE__ */ jsxs3("div", { style: containerStyle, children: [
33610
- /* @__PURE__ */ jsxs3("h1", { style: { fontSize: "18px", marginBottom: "10px" }, children: [
33611
- "Liquidation risk managed leverged ",
33612
- lstSymbol,
33613
- " Vault"
33614
- ] }),
33615
- /* @__PURE__ */ jsxs3("p", { style: { fontSize: "14px", lineHeight: "1.5", marginBottom: "16px" }, children: [
33616
- "This Levered Endur ",
33617
- lstSymbol,
33618
- " vault is a tokenized leveraged Vault, auto-compounding strategy that takes upto 5x leverage on ",
33619
- lstSymbol,
33620
- " by borrow ",
33621
- underlyingSymbol,
33622
- ". Borrowed amount is swapped to ",
33623
- lstSymbol,
33624
- " to create leverage. Depositors receive vault shares that represent a proportional claim on the underlying assets and accrued yield."
33625
- ] }),
33626
- /* @__PURE__ */ jsxs3("p", { style: { fontSize: "14px", lineHeight: "1.5", marginBottom: "16px" }, children: [
33627
- "This vault uses Vesu for lending and borrowing. The oracle used by this pool is a ",
33628
- highlightTextWithLinks("conversion rate oracle", [{ highlight: "conversion rate oracle", link: "https://docs.pragma.build/starknet/development#conversion-rate" }]),
33629
- " ",
33630
- "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."
33631
- ] }),
33632
- /* @__PURE__ */ jsx4("div", { style: { backgroundColor: "#222", padding: "10px", borderRadius: "8px", marginBottom: "20px", border: "1px solid #444" }, children: /* @__PURE__ */ jsxs3("p", { style: { fontSize: "13px", color: "#ccc" }, children: [
33633
- /* @__PURE__ */ jsx4("strong", { children: "Withdrawals:" }),
33634
- " Requests can take up to ",
33635
- /* @__PURE__ */ jsx4("strong", { children: "1-2 hours" }),
33636
- " to process as the vault unwinds and settles routing."
33637
- ] }) }),
33638
- /* @__PURE__ */ jsx4("div", { style: { backgroundColor: "#222", padding: "10px", borderRadius: "8px", marginBottom: "20px", border: "1px solid #444" }, children: /* @__PURE__ */ jsxs3("p", { style: { fontSize: "13px", color: "#ccc" }, children: [
33639
- /* @__PURE__ */ jsx4("strong", { children: "Debt limits:" }),
33640
- " Pools on Vesu have debt caps that are gradually increased over time. Until caps are raised, deposited Tokens remain in the vault, generating a shared net return for all depositors. There is no additional fee taken by Troves on Yield token's APY, its only on added gain."
33641
- ] }) })
33642
- ] });
33643
- }
33644
- function getDescription(tokenSymbol, underlyingSymbol) {
33645
- return VaultDescription(tokenSymbol, underlyingSymbol);
33646
- }
33647
- function getLooperSettings(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
33648
- vaultSettings.leafAdapters = [];
33649
- const lstToken = Global.getDefaultTokens().find((token) => token.symbol === lstSymbol);
33650
- const underlyingToken = Global.getDefaultTokens().find((token) => token.symbol === underlyingSymbol);
33651
- const baseAdapterConfig = {
33652
- baseToken: lstToken,
33653
- supportedPositions: [{ asset: lstToken, isDebt: false }],
33654
- networkConfig: getMainnetConfig(),
33655
- pricer: new PricerFromApi(getMainnetConfig(), Global.getDefaultTokens()),
33656
- vaultAllocator: vaultSettings.vaultAllocator,
33657
- vaultAddress: vaultSettings.vaultAddress
33658
- };
33659
- const vesuAdapterLST = new VesuSupplyOnlyAdapter({
33660
- // xWBTC vToken on re7 xBTC pool
33661
- vTokenContract: ContractAddr.from("0x062a162d0827db6f43ebb850cbef3c99fc7969e3070b83a2236c9f3713c89fd8"),
33662
- ...baseAdapterConfig
33663
- });
33664
- const vesuMultiplyAdapters = borrowableAssets.map((position) => new VesuMultiplyAdapter({
33665
- poolId: pool1,
33666
- collateral: lstToken,
33667
- debt: Global.getDefaultTokens().find((token) => token.symbol === position),
33668
- targetHealthFactor: vaultSettings.targetHealthFactor,
33669
- minHealthFactor: vaultSettings.minHealthFactor,
33670
- quoteAmountToFetchPrice: vaultSettings.quoteAmountToFetchPrice,
33671
- ...baseAdapterConfig,
33672
- supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }],
33673
- minimumVesuMovementAmount: 0
33674
- }));
33675
- const unusedBalanceAdapter = new UnusedBalanceAdapter({
33676
- ...baseAdapterConfig
33677
- });
33678
- vaultSettings.adapters.push({ id: `${vesuAdapterLST.name}_${lstToken.symbol}_${underlyingToken.symbol}`, adapter: vesuAdapterLST });
33679
- vesuMultiplyAdapters.map((adapter) => vaultSettings.adapters.push({ id: `${adapter.name}_${lstToken.symbol}_${underlyingToken.symbol}`, adapter }));
33680
- vaultSettings.adapters.push({ id: `${unusedBalanceAdapter.name}_${lstToken.symbol}`, adapter: unusedBalanceAdapter });
33681
- const commonAdapter = new CommonAdapter({
33682
- id: "flash_loan_init" /* FLASH_LOAN */,
33683
- vaultAddress: vaultSettings.vaultAddress,
33684
- vaultAllocator: vaultSettings.vaultAllocator,
33685
- manager: vaultSettings.manager,
33686
- asset: lstToken.address
33687
- });
33688
- vaultSettings.leafAdapters.push(() => vesuAdapterLST.getDepositLeaf());
33689
- vaultSettings.leafAdapters.push(() => vesuAdapterLST.getWithdrawLeaf());
33690
- vesuMultiplyAdapters.map((adapter) => vaultSettings.leafAdapters.push(() => adapter.getDepositLeaf()));
33691
- vesuMultiplyAdapters.map((adapter) => vaultSettings.leafAdapters.push(() => adapter.getWithdrawLeaf()));
33692
- vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, vaultSettings.vaultAddress, "approve_bring_liquidity" /* APPROVE_BRING_LIQUIDITY */).bind(commonAdapter));
33693
- vaultSettings.leafAdapters.push(commonAdapter.getBringLiquidityAdapter("bring_liquidity" /* BRING_LIQUIDITY */).bind(commonAdapter));
33694
- return vaultSettings;
33695
- }
33696
- var AUDIT_URL3 = "https://docs.troves.fi/p/security#starknet-vault-kit";
33697
- function getFAQs(lstSymbol, underlyingSymbol, isLST) {
33698
- return [
33699
- {
33700
- question: `What is the Hyper ${lstSymbol} Vault?`,
33701
- answer: `The Hyper ${lstSymbol} Vault is a tokenized strategy that automatically loops your ${lstSymbol} to create up to 5x leverage to hence yield in a very low risk manner.`
33702
- },
33703
- {
33704
- question: "How does yield allocation work?",
33705
- answer: `The strategy uses deposited ${lstSymbol} to collateralize it on Vesu, borrow more ${underlyingSymbol} to loop further. Instead of manually doing this, using flash loan, this leverage is created in a single gas efficient step. Our continuous monitoring systems gauge current yield and available liquidity in real time to make sure yield is optimal. For instance, if the looping becomes in-efficient in future, the strategy will rebalance to reduce leverage or simply hold ${lstSymbol} to continue earning yield.`
33706
- },
33707
- {
33708
- question: "Which protocols/dApp are used??",
33709
- answer: isLST ? /* @__PURE__ */ jsxs3("span", { children: [
33710
- "Currently, the LST is from ",
33711
- /* @__PURE__ */ jsx4("strong", { children: "Endur" }),
33712
- " while ",
33713
- /* @__PURE__ */ jsx4("strong", { children: "Vesu" }),
33714
- " is used to collateralize the looped position."
33715
- ] }) : /* @__PURE__ */ jsxs3("span", { children: [
33716
- "Currently, the Yield Token is from ",
33717
- /* @__PURE__ */ jsx4("strong", { children: "Re7 Labs (Midas)" }),
33718
- " while ",
33719
- /* @__PURE__ */ jsx4("strong", { children: "Vesu" }),
33720
- " is used to collateralize the looped position."
33721
- ] })
33722
- },
33723
- {
33724
- question: "Can I get liquidated?",
33725
- answer: "The strategy uses highly correlated assets which drastically reduces 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."
33726
- },
33727
- {
33728
- question: "What do I receive when I deposit?",
33729
- answer: "Depositors receive vault tokens representing their proportional share of the vault. These tokens entitle holders to both the principal and accrued yield."
33730
- },
33731
- {
33732
- question: "How long do withdrawals take?",
33733
- answer: "Withdrawals may take up to 1-2 hours to process, as the vault unwinds and settles liquidity routing across integrated protocols. In case of large withdrawals, to avoid slippage, we may slowly unwind the position, which could make the withdrawals longer."
33734
- },
33735
- {
33736
- question: `Is the Hyper ${lstSymbol} Vault non-custodial?`,
33737
- answer: `Yes. The Hyper ${lstSymbol} Vault operates entirely on-chain. Users always maintain control of their vault tokens, and the strategy is fully transparent.`
33738
- },
33739
- {
33740
- question: "Is the Vault audited?",
33741
- answer: `Yes. The Hyper ${lstSymbol} Vault is audited by Zellic. Look for safety icon beside the strategy name for more details.`
33742
- },
33743
- {
33744
- question: "Are there any fees?",
33745
- answer: "Troves charges a performance of 10% on the yield generated. The APY shown is net of this fee. This fee is only applied to the profits earned, ensuring that users retain their initial capital."
33746
- }
33747
- ];
33748
- }
33749
- var _riskFactor3 = [
33750
- { type: "Smart Contract Risk" /* SMART_CONTRACT_RISK */, value: 2 /* WELL_AUDITED */, weight: 25, reason: "Audited by Zellic" },
33751
- { type: "Liquidation Risk" /* LIQUIDATION_RISK */, value: 1 /* VERY_LOW_PROBABILITY */, weight: 25, reason: "The collateral and debt are highly correlated" },
33752
- { type: "Technical Risk" /* TECHNICAL_RISK */, value: 1 /* STABLE_INFRASTRUCTURE */, weight: 25, reason: "Liquidation can only happen if vault is left un-monitored for weeks, which is highly unlikely. We actively monitor all services on a daily basis." },
33753
- { type: "Depeg Risk" /* DEPEG_RISK */, value: 2 /* GENERALLY_STABLE */, weight: 25, reason: "Generally stable pegged assets" }
33754
- ];
33755
- var borrowableAssets = [
33756
- "WBTC",
33757
- "tBTC",
33758
- "LBTC",
33759
- "solvBTC"
33760
- ];
33761
- var hyperxSTRK = {
33762
- vaultAddress: ContractAddr.from("0x46c7a54c82b1fe374353859f554a40b8bd31d3e30f742901579e7b57b1b5960"),
33763
- manager: ContractAddr.from("0x5d499cd333757f461a0bedaca3dfc4d77320c773037e0aa299f22a6dbfdc03a"),
33764
- vaultAllocator: ContractAddr.from("0x511d07953a09bc7c505970891507c5a2486d2ea22752601a14db092186d7caa"),
33765
- redeemRequestNFT: ContractAddr.from("0x51e40b839dc0c2feca923f863072673b94abfa2483345be3b30b457a90d095"),
33766
- aumOracle: ContractAddr.from("0x48cf709870a1a0d453d37de108e0c41b8b89819ef54f95abc0e2e1f98bbe937"),
33767
- leafAdapters: [],
33768
- adapters: [],
33769
- targetHealthFactor: 1.1,
33770
- minHealthFactor: 1.05,
33771
- borrowable_assets: Global.getDefaultTokens().filter((token) => token.symbol === "STRK"),
33772
- underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "STRK"),
33773
- quoteAmountToFetchPrice: new Web3Number("100", Global.getDefaultTokens().find((token) => token.symbol === "STRK").decimals)
33774
- };
33775
- var hyperxWBTC = {
33776
- vaultAddress: ContractAddr.from("0x2da9d0f96a46b453f55604313785dc866424240b1c6811d13bef594343db818"),
33777
- manager: ContractAddr.from("0x75866db44c81e6986f06035206ee9c7d15833ddb22d6a22c016cfb5c866a491"),
33778
- vaultAllocator: ContractAddr.from("0x57b5c1bb457b5e840a2714ae53ada87d77be2f3fd33a59b4fe709ef20c020c1"),
33779
- redeemRequestNFT: ContractAddr.from("0x7a5dc288325456f05e70e9616e16bc02ffbe448f4b89f80b47c0970b989c7c"),
33780
- aumOracle: ContractAddr.from("0x258f8a0ca0d21f542e48ad89d00e92dc4d9db4999084f50ef9c22dfb1e83023"),
33781
- leafAdapters: [],
33782
- adapters: [],
33783
- targetHealthFactor: 1.1,
33784
- minHealthFactor: 1.05,
33785
- borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
33786
- underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "WBTC"),
33787
- quoteAmountToFetchPrice: new Web3Number("0.001", Global.getDefaultTokens().find((token) => token.symbol === "WBTC").decimals)
33788
- };
33789
- var hyperxtBTC = {
33790
- vaultAddress: ContractAddr.from("0x47d5f68477e5637ce0e56436c6b5eee5a354e6828995dae106b11a48679328"),
33791
- manager: ContractAddr.from("0xc4cc3e08029a0ae076f5fdfca70575abb78d23c5cd1c49a957f7e697885401"),
33792
- vaultAllocator: ContractAddr.from("0x50bbd4fe69f841ecb13b2619fe50ebfa4e8944671b5d0ebf7868fd80c61b31e"),
33793
- redeemRequestNFT: ContractAddr.from("0xeac9032f02057779816e38a6cb9185d12d86b3aacc9949b96b36de359c1e3"),
33794
- aumOracle: ContractAddr.from("0x7e0d05cb7ba3f7db77a36c21c21583b5a524c2e685c08c24b3554911fb4a039"),
33795
- leafAdapters: [],
33796
- adapters: [],
33797
- targetHealthFactor: 1.1,
33798
- minHealthFactor: 1.05,
33799
- borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
33800
- underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "tBTC"),
33801
- quoteAmountToFetchPrice: new Web3Number("0.001", Global.getDefaultTokens().find((token) => token.symbol === "tBTC").decimals)
33802
- };
33803
- var hyperxsBTC = {
33804
- vaultAddress: ContractAddr.from("0x437ef1e7d0f100b2e070b7a65cafec0b2be31b0290776da8b4112f5473d8d9"),
33805
- manager: ContractAddr.from("0xc9ac023090625b0be3f6532ca353f086746f9c09f939dbc1b2613f09e5f821"),
33806
- vaultAllocator: ContractAddr.from("0x60c2d856936b975459a5b4eb28b8672d91f757bd76cebb6241f8d670185dc01"),
33807
- redeemRequestNFT: ContractAddr.from("0x429e8ee8bc7ecd1ade72630d350a2e0f10f9a2507c45f188ba17fe8f2ab4cf3"),
33808
- aumOracle: ContractAddr.from("0x149298ade3e79ec6cbdac6cfad289c57504eaf54e590939136ed1ceca60c345"),
33809
- leafAdapters: [],
33810
- adapters: [],
33811
- targetHealthFactor: 1.1,
33812
- minHealthFactor: 1.05,
33813
- borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
33814
- underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "solvBTC"),
33815
- quoteAmountToFetchPrice: new Web3Number("0.001", Global.getDefaultTokens().find((token) => token.symbol === "solvBTC").decimals)
33816
- };
33817
- var hyperxLBTC = {
33818
- vaultAddress: ContractAddr.from("0x64cf24d4883fe569926419a0569ab34497c6956a1a308fa883257f7486d7030"),
33819
- manager: ContractAddr.from("0x203530a4022a99b8f4b406aaf33b0849d43ad7422c1d5cc14ff8c667abec6c0"),
33820
- vaultAllocator: ContractAddr.from("0x7dbc8ccd4eabce6ea6c19e0e5c9ccca3a93bd510303b9e071cbe25fc508546e"),
33821
- redeemRequestNFT: ContractAddr.from("0x5ee66a39af9aef3d0d48982b4a63e8bd2a5bad021916bd87fb0eae3a26800b8"),
33822
- aumOracle: ContractAddr.from("0x23d69e4391fa72d10e625e7575d8bddbb4aff96f04503f83fdde23123bf41d0"),
33823
- leafAdapters: [],
33824
- adapters: [],
33825
- targetHealthFactor: 1.1,
33826
- minHealthFactor: 1.05,
33827
- borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
33828
- underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "LBTC"),
33829
- quoteAmountToFetchPrice: new Web3Number("0.001", Global.getDefaultTokens().find((token) => token.symbol === "LBTC").decimals)
33830
- };
33831
- var hypermRe7BTC = {
33832
- vaultAddress: ContractAddr.from("0x6c89b75d09de82477edb86b2c2918cfc1a5dc0177cfbdea46278386b6499645"),
33833
- manager: ContractAddr.from("0x7bc2d0535e13352d3ab78ea047616a3162068294297304943d2302122a150a1"),
33834
- vaultAllocator: ContractAddr.from("0x760f9cebca9d2ee624f4224591da6da8b3ea5fd2410590735709551bd4e7570"),
33835
- redeemRequestNFT: ContractAddr.from("0x5e045ae0160f7650f8a4dd7c826f25630a89fe62434db4441e7e0075608180f"),
33836
- aumOracle: ContractAddr.from("0x3958df341b838813c24efb9183c23bddd1c57d44b1b86c0dd57f67887b89fba"),
33837
- leafAdapters: [],
33838
- adapters: [],
33839
- targetHealthFactor: 1.1,
33840
- minHealthFactor: 1.05,
33841
- borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
33842
- underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "WBTC"),
33843
- quoteAmountToFetchPrice: new Web3Number("0.001", Global.getDefaultTokens().find((token) => token.symbol === "mRe7BTC").decimals)
33844
- };
33845
- var hypermRe7YIELD = {
33846
- vaultAddress: ContractAddr.from("0x42797ab4eb1f72787442e91a73d63a39e3a141c1106470a946ecc328db6896c"),
33847
- manager: ContractAddr.from("0x435b45d40fbb406cf69ac84bb471e7b7a4ea2295d0893c05dd2db565295e77f"),
33848
- vaultAllocator: ContractAddr.from("0x456c4c6afca90512aeb5c735d84405fea6e51ab06d1851ac8cdb0a235e14f15"),
33849
- redeemRequestNFT: ContractAddr.from("0x4bbb25c2568af07967342833f7db1aece1be1be2330798dab4ee585aa6c2c72"),
33850
- aumOracle: ContractAddr.from("0x3e1f2825158cafccc9b42a8165d17ceb6b8e966474d9c63587d338746888382"),
33851
- leafAdapters: [],
33852
- adapters: [],
33853
- targetHealthFactor: 1.1,
33854
- minHealthFactor: 1.05,
33855
- borrowable_assets: [Global.getDefaultTokens().find((token) => token.symbol === "USDC")],
33856
- underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "USDC"),
33857
- quoteAmountToFetchPrice: new Web3Number("0.001", Global.getDefaultTokens().find((token) => token.symbol === "mRe7BTC").decimals)
33858
- };
33859
- function getInvestmentSteps(lstSymbol, underlyingSymbol) {
33860
- return [
33861
- `Deposit ${lstSymbol} into the vault`,
33862
- `The vault manager loops the ${underlyingSymbol} to buy ${lstSymbol}`,
33863
- `The vault manager collateralizes the ${lstSymbol} on Vesu`,
33864
- `The vault manager borrows more ${underlyingSymbol} to loop further`,
33865
- `If required, adjust leverage or re-allocate assets within pool on Vesu to optimize yield`
33866
- ];
33867
- }
33868
- function getStrategySettings(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST) {
33869
- return {
33870
- name: `Hyper ${lstSymbol}`,
33871
- description: getDescription(lstSymbol, underlyingSymbol),
33872
- address: addresses.vaultAddress,
33873
- launchBlock: 0,
33874
- type: "Other",
33875
- depositTokens: [Global.getDefaultTokens().find((token) => token.symbol === lstSymbol)],
33876
- additionalInfo: getLooperSettings(lstSymbol, underlyingSymbol, addresses, lstSymbol === "xSTRK" ? VesuPools.Re7xSTRK : VesuPools.Re7xBTC),
33877
- risk: {
33878
- riskFactor: _riskFactor3,
33879
- netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),
33880
- notARisks: getNoRiskTags(_riskFactor3)
33881
- },
33882
- auditUrl: AUDIT_URL3,
33883
- protocols: [Protocols.ENDUR, Protocols.VESU],
33884
- maxTVL: Web3Number.fromWei(0, 18),
33885
- contractDetails: getContractDetails(addresses),
33886
- faqs: getFAQs(lstSymbol, underlyingSymbol, isLST),
33887
- investmentSteps: getInvestmentSteps(lstSymbol, underlyingSymbol),
33888
- isPreview,
33889
- apyMethodology: isLST ? "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." : "Current annualized APY in terms of base asset of the Yield Token. There is no additional fee taken by Troves on yield token APY. We charge a 10% performance fee on the additional gain which is already accounted in the APY shown."
33890
- };
33891
- }
33892
- var HyperLSTStrategies = [
33893
- getStrategySettings("xSTRK", "STRK", hyperxSTRK, false, true),
33894
- getStrategySettings("xWBTC", "WBTC", hyperxWBTC, false, false),
33895
- getStrategySettings("xtBTC", "tBTC", hyperxtBTC, false, false),
33896
- getStrategySettings("xsBTC", "solvBTC", hyperxsBTC, false, false),
33897
- getStrategySettings("xLBTC", "LBTC", hyperxLBTC, false, false),
33898
- getStrategySettings("mRe7BTC", "mRe7BTC", hypermRe7BTC, false, false),
33899
- getStrategySettings("mRe7YIELD", "mRe7YIELD", hypermRe7YIELD, false, false)
33900
- ];
33901
-
33902
- // src/strategies/universal-adapters/avnu-adapter.ts
33903
- import { hash as hash7, uint256 as uint25614 } from "starknet";
33904
- import axios10 from "axios";
33905
- var AvnuAdapter = class _AvnuAdapter extends BaseAdapter {
33906
- constructor(config) {
33907
- super(config, _AvnuAdapter.name, Protocols.AVNU);
33908
- this.config = config;
33909
- this.avnuWrapper = new AvnuWrapper();
33910
- }
33911
- //abstract means the method has no implementation in this class; instead, child classes must implement it.
33912
- async getAPY(supportedPosition) {
33913
- return Promise.resolve({ apy: 0, type: "base" /* BASE */ });
33914
- }
33915
- async getPosition(supportedPosition) {
33916
- return Promise.resolve({ amount: new Web3Number(0, 0), remarks: "" });
33917
- }
33918
- async maxDeposit(amount) {
33919
- return Promise.resolve({
33920
- tokenInfo: this.config.baseToken,
33921
- amount: new Web3Number(0, 0),
33922
- usdValue: 0,
33923
- apy: { apy: 0, type: "base" /* BASE */ },
33924
- protocol: Protocols.AVNU,
33925
- remarks: ""
33926
- });
33927
- }
33928
- async maxWithdraw() {
33929
- return Promise.resolve({
33930
- tokenInfo: this.config.baseToken,
33931
- amount: new Web3Number(0, 0),
33932
- usdValue: 0,
33933
- apy: { apy: 0, type: "base" /* BASE */ },
33934
- protocol: Protocols.AVNU,
33935
- remarks: ""
33936
- });
33937
- }
33938
- _getDepositLeaf() {
33939
- const vaultAllocator = ContractAddr.from(
33940
- this.config.vaultAllocator.address
33941
- );
33942
- return [
33943
- {
33944
- target: this.config.supportedPositions[0].asset.address,
33945
- method: "approve",
33946
- packedArguments: [
33947
- AVNU_EXCHANGE.toBigInt()
33948
- ],
33949
- sanitizer: SIMPLE_SANITIZER,
33950
- id: `approve_${this.config.supportedPositions[0].asset.symbol}`
33951
- },
33952
- {
33953
- target: AVNU_EXCHANGE,
33954
- method: "multi_route_swap",
33955
- packedArguments: [
33956
- this.config.supportedPositions[0].asset.address.toBigInt(),
33957
- //usdc
33958
- this.config.supportedPositions[1].asset.address.toBigInt(),
33959
- //wbtc
33960
- vaultAllocator.toBigInt()
33961
- ],
33962
- sanitizer: SIMPLE_SANITIZER,
33963
- id: `asutb_${this.config.supportedPositions[0].asset.symbol}_${this.config.supportedPositions[1].asset.symbol}`
33964
- }
33965
- ];
33966
- }
33967
- _getWithdrawLeaf() {
33968
- const vaultAllocator = ContractAddr.from(
33969
- this.config.vaultAllocator.address
33970
- );
33971
- const toToken = this.config.supportedPositions[0].asset;
33972
- const fromToken = this.config.supportedPositions[1].asset;
33973
- return [
33974
- {
33975
- target: fromToken.address,
33976
- method: "approve",
33977
- packedArguments: [
33978
- AVNU_EXCHANGE.toBigInt()
33979
- ],
33980
- sanitizer: SIMPLE_SANITIZER,
33981
- id: `approve_${fromToken.symbol}`
33982
- },
33983
- {
33984
- target: AVNU_EXCHANGE,
33985
- method: "multi_route_swap",
33986
- packedArguments: [
33987
- fromToken.address.toBigInt(),
33988
- //wbtc
33989
- toToken.address.toBigInt(),
33990
- //usdc
33991
- vaultAllocator.toBigInt()
33992
- ],
33993
- sanitizer: SIMPLE_SANITIZER,
33994
- id: `asbtu_${fromToken.symbol}_${fromToken.symbol}`
33995
- }
33996
- ];
33997
- }
33998
- _getLegacySwapLeaf() {
33999
- return [];
34000
- }
34001
- async getDepositCall(params) {
34002
- try {
34003
- const fromToken = this.config.supportedPositions[0].asset;
34004
- const toToken = this.config.supportedPositions[1].asset;
34005
- const vaultAllocator = ContractAddr.from(
34006
- this.config.vaultAllocator.address
34007
- );
34008
- const quote = await this.getQuotesAvnu(
34009
- fromToken.address.toString(),
34010
- toToken.address.toString(),
34011
- params.amount.toNumber(),
34012
- vaultAllocator.address.toString(),
34013
- toToken.decimals,
34014
- true
34015
- );
34016
- if (!quote) {
34017
- logger.error("error getting quote from avnu");
34018
- return [];
34019
- }
34020
- const getCalldata = await this.avnuWrapper.getSwapCallData(
34021
- quote,
34022
- vaultAllocator.address
34023
- );
34024
- const swapCallData = getCalldata[0];
34025
- const amount = uint25614.bnToUint256(quote.sellAmountInUsd * 10 ** 7);
34026
- return [
34027
- {
34028
- sanitizer: SIMPLE_SANITIZER,
34029
- call: {
34030
- contractAddress: fromToken.address,
34031
- selector: hash7.getSelectorFromName("approve"),
34032
- calldata: [
34033
- AVNU_EXCHANGE.toBigInt(),
34034
- toBigInt(amount.low.toString()),
34035
- // amount low
34036
- toBigInt(amount.high.toString())
34037
- // amount high
34038
- ]
34039
- }
34040
- },
34041
- {
34042
- sanitizer: SIMPLE_SANITIZER,
34043
- call: {
34044
- contractAddress: AVNU_EXCHANGE,
34045
- selector: hash7.getSelectorFromName("multi_route_swap"),
34046
- calldata: swapCallData
33792
+ const proofsInfo = adapters2.map((adapter) => adapter.getProofs(false, this.getMerkleTree()));
33793
+ const calls = [];
33794
+ for (const info of proofsInfo) {
33795
+ const proofGroups = info.proofs;
33796
+ const call = this.getManageCall(proofGroups, await info.callConstructor({ amount: params.leg1DepositAmount }));
33797
+ calls.push(call);
34047
33798
  }
33799
+ return calls;
33800
+ } else {
33801
+ throw new Error(`${this.getTag()}::getVesuMultiplyCall: no adapters to use for unused balance: ${unusedBalance.amount.toString()}`);
34048
33802
  }
34049
- ];
34050
- } catch (error) {
34051
- logger.error(`Error getting Avnu quote: ${error}`);
34052
- return [];
34053
- }
34054
- }
34055
- //Swap wbtc to usdc
34056
- async getWithdrawCall(params) {
34057
- try {
34058
- const toToken = this.config.supportedPositions[0].asset;
34059
- const fromToken = this.config.supportedPositions[1].asset;
34060
- const vaultAllocator = ContractAddr.from(
34061
- this.config.vaultAllocator.address
34062
- );
34063
- const quote = await this.getQuotesAvnu(
34064
- fromToken.address.toString(),
34065
- toToken.address.toString(),
34066
- params.amount.toNumber(),
34067
- vaultAllocator.address.toString(),
34068
- fromToken.decimals,
34069
- false
34070
- );
34071
- if (!quote) {
34072
- logger.error("No quotes available for this swap, error in quotes avnu");
34073
- return [];
34074
33803
  }
34075
- const getCalldata = await this.avnuWrapper.getSwapCallData(
34076
- quote,
34077
- vaultAllocator.address
34078
- );
34079
- const swapCallData = getCalldata[0];
34080
- const amount = uint25614.bnToUint256(params.amount.toWei());
34081
- return [
34082
- {
34083
- sanitizer: SIMPLE_SANITIZER,
34084
- call: {
34085
- contractAddress: fromToken.address,
34086
- selector: hash7.getSelectorFromName("approve"),
34087
- calldata: [
34088
- AVNU_EXCHANGE.toBigInt(),
34089
- toBigInt(amount.low.toString()),
34090
- // amount low
34091
- toBigInt(amount.high.toString())
34092
- // amount high
34093
- ]
34094
- }
34095
- },
34096
- {
34097
- sanitizer: SIMPLE_SANITIZER,
34098
- call: {
34099
- contractAddress: AVNU_EXCHANGE,
34100
- selector: hash7.getSelectorFromName("multi_route_swap"),
34101
- calldata: swapCallData
34102
- }
34103
- }
34104
- ];
34105
- } catch (error) {
34106
- logger.error(`Error getting Avnu quote: ${error}`);
34107
- return [];
34108
33804
  }
34109
- }
34110
- async getSwapCallData(quote) {
34111
- return await this.avnuWrapper.getSwapCallData(quote, this.config.vaultAllocator.address);
34112
- }
34113
- async getHealthFactor() {
34114
- return Promise.resolve(1);
34115
- }
34116
- async fetchQuoteWithRetry(params, retries = 5) {
34117
- for (let attempt = 0; attempt < retries; attempt++) {
34118
- try {
34119
- const response = await axios10.get(this.config.baseUrl, { params });
34120
- if (response.data && response.data.length > 0) {
34121
- return response;
34122
- }
34123
- throw new Error("Empty response data");
34124
- } catch (err) {
34125
- logger.error(`Error fetching quote with retry: ${err}`);
34126
- if (attempt === retries - 1) {
34127
- throw err;
34128
- }
34129
- await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
33805
+ const adapters = await AdapterOptimizer.getAdapterToUse(allAdapters, true, params.leg1DepositAmount);
33806
+ if (adapters.length > 0) {
33807
+ const proofsInfo = adapters.map((adapter) => adapter.getProofs(true, this.getMerkleTree()));
33808
+ const calls = [];
33809
+ for (const info of proofsInfo) {
33810
+ const proofGroups = info.proofs;
33811
+ const call = this.getManageCall(proofGroups, await info.callConstructor({ amount: params.leg1DepositAmount }));
33812
+ calls.push(call);
34130
33813
  }
33814
+ return calls;
33815
+ } else {
33816
+ throw new Error(`${this.getTag()}::getVesuMultiplyCall: no adapters to use for deposit: ${params.leg1DepositAmount.toString()}`);
34131
33817
  }
34132
- throw new Error("Failed to fetch quote after retries");
34133
33818
  }
34134
- async getQuotesAvnu(from_token_address, to_token_address, amount, takerAddress, toTokenDecimals, usdcToBtc, maxIterations = 5, tolerance = 5e3) {
34135
- try {
34136
- const fromToken = this.config.supportedPositions[0].asset;
34137
- const toToken = this.config.supportedPositions[1].asset;
34138
- if (!usdcToBtc) {
34139
- const sellAmount2 = returnFormattedAmount(amount, toTokenDecimals);
34140
- const params2 = {
34141
- sellTokenAddress: from_token_address,
34142
- buyTokenAddress: to_token_address,
34143
- takerAddress,
34144
- sellAmount: sellAmount2
34145
- };
34146
- const finalQuote2 = await this.fetchQuoteWithRetry(params2);
34147
- if (!finalQuote2.data.length) {
34148
- logger.error("No quotes available for this swap, error in quotes avnu");
34149
- return null;
34150
- }
34151
- const dataObject2 = finalQuote2.data[0];
34152
- return dataObject2;
34153
- }
34154
- const btcPrice = await this.getPriceOfToken(toToken.address.toString());
34155
- if (!btcPrice) {
34156
- logger.error(`error getting btc price: ${btcPrice}`);
34157
- return null;
34158
- }
34159
- const estimatedUsdcAmount = Math.floor(amount * btcPrice);
34160
- const targetBtcBig = BigInt(returnFormattedAmount(amount, toTokenDecimals));
34161
- let low = BigInt(
34162
- Math.floor(
34163
- estimatedUsdcAmount * 10 ** fromToken.decimals * 0.9
34164
- )
34165
- );
34166
- let high = BigInt(
34167
- Math.floor(
34168
- estimatedUsdcAmount * 10 ** fromToken.decimals * 1.1
34169
- )
34170
- );
34171
- let mid = 0n;
34172
- for (let i = 0; i < maxIterations; i++) {
34173
- mid = (low + high) / 2n;
34174
- const sellAmount2 = returnFormattedAmount(Number(mid), 0);
34175
- const quote = await this.fetchQuoteWithRetry({
34176
- sellTokenAddress: from_token_address,
34177
- buyTokenAddress: to_token_address,
34178
- takerAddress,
34179
- sellAmount: sellAmount2
34180
- });
34181
- const gotBtc = BigInt(quote.data[0].buyAmount);
34182
- if (gotBtc === targetBtcBig) return quote.data[0];
34183
- if (gotBtc > targetBtcBig) {
34184
- high = mid;
34185
- } else {
34186
- low = mid;
34187
- }
34188
- if (gotBtc >= targetBtcBig && gotBtc <= targetBtcBig + BigInt(tolerance)) {
34189
- return quote.data[0];
34190
- }
34191
- }
34192
- let sellAmount = returnFormattedAmount(
34193
- Number(mid),
34194
- 0
34195
- );
34196
- const params = {
34197
- sellTokenAddress: from_token_address,
34198
- buyTokenAddress: to_token_address,
34199
- takerAddress,
34200
- sellAmount
34201
- };
34202
- const finalQuote = await this.fetchQuoteWithRetry(params);
34203
- if (!finalQuote.data.length) {
34204
- logger.error("No quotes available for this swap, error in quotes avnu");
34205
- return null;
34206
- }
34207
- const dataObject = finalQuote.data[0];
34208
- return dataObject;
34209
- } catch (err) {
34210
- logger.error(`No quotes available for this swap: ${err}`);
34211
- return null;
33819
+ getLSTUnderlyingTokenInfo() {
33820
+ return this.metadata.additionalInfo.underlyingToken;
33821
+ }
33822
+ // async getMaxBorrowableAmount(params: { isAPYComputation: boolean } = { isAPYComputation: false }) {
33823
+ // const vesuAdapters = this.getVesuAdapters();
33824
+ // let netMaxBorrowableAmount = Web3Number.fromWei("0", this.getLSTUnderlyingTokenInfo().decimals);
33825
+ // const maxBorrowables: {amount: Web3Number, dexSwappableAmount: Web3Number, maxBorrowableAmount: Web3Number, borrowableAsset: TokenInfo}[] = [];
33826
+ // for (const vesuAdapter of vesuAdapters) {
33827
+ // maxBorrowables.push(await this.getMaxBorrowableAmountByVesuAdapter(vesuAdapter, params.isAPYComputation));
33828
+ // }
33829
+ // maxBorrowables.sort((a, b) => b.amount.toNumber() - a.amount.toNumber());
33830
+ // netMaxBorrowableAmount = maxBorrowables.reduce((acc, curr) => acc.plus(curr.amount), Web3Number.fromWei("0", this.getLSTUnderlyingTokenInfo().decimals));
33831
+ // return {netMaxBorrowableAmount, maxBorrowables};
33832
+ // }
33833
+ // recursively, using binary search computes max swappable.
33834
+ // @dev assumes 1 token of from == 1 token of to
33835
+ // async getMaxSwappableWithMaxSlippage(fromToken: TokenInfo, toToken: TokenInfo, maxSlippage: number, maxAmount: Web3Number) {
33836
+ // const output = await findMaxInputWithSlippage({
33837
+ // apiGetOutput: async (inputAmount: number): Promise<number> => {
33838
+ // const ekuboQuoter = new EkuboQuoter(this.config);
33839
+ // await new Promise(resolve => setTimeout(resolve, 1000)); // artificial delay, to avoid rate limit
33840
+ // const quote = await ekuboQuoter.getQuote(fromToken.address.address, toToken.address.address, new Web3Number(inputAmount.toFixed(9), fromToken.decimals));
33841
+ // return Web3Number.fromWei(quote.total_calculated.toString(), toToken.decimals).toNumber();
33842
+ // },
33843
+ // maxInput: maxAmount.toNumber(),
33844
+ // maxSlippagePercent: maxSlippage,
33845
+ // tolerance: 0.001,
33846
+ // referenceRate: 1,
33847
+ // });
33848
+ // return new Web3Number(output.optimalInput, fromToken.decimals);
33849
+ // }
33850
+ // async getMaxBorrowableAmountByVesuAdapter(vesuAdapter: VesuAdapter, isAPYComputation: boolean) {
33851
+ // const lstAPY = await this.getLSTAPR(this.getLSTUnderlyingTokenInfo().address);
33852
+ // const maxInterestRate = lstAPY * 0.8;
33853
+ // const maxBorrowableAmount = await vesuAdapter.getMaxBorrowableByInterestRate(this.config, vesuAdapter.config.debt, maxInterestRate);
33854
+ // const debtCap = await vesuAdapter.getDebtCap(this.config);
33855
+ // const maxBorrowable = maxBorrowableAmount.minimum(debtCap).multipliedBy(0.999);
33856
+ // // Dont compute precise max swappable for APY computation
33857
+ // if (vesuAdapter.config.debt.address.eq(this.getLSTUnderlyingTokenInfo().address) || isAPYComputation) {
33858
+ // return {amount: maxBorrowable, dexSwappableAmount: maxBorrowable, maxBorrowableAmount: maxBorrowable, borrowableAsset: vesuAdapter.config.debt};
33859
+ // }
33860
+ // // Want < 0.02% slippage
33861
+ // try {
33862
+ // const maxSwappable = await this.getMaxSwappableWithMaxSlippage(vesuAdapter.config.debt, this.getLSTUnderlyingTokenInfo(), 0.0002, maxBorrowable);
33863
+ // return {amount: maxBorrowable.minimum(maxSwappable), dexSwappableAmount: maxSwappable, maxBorrowableAmount: maxBorrowable, borrowableAsset: vesuAdapter.config.debt};
33864
+ // } catch (error) {
33865
+ // logger.warn(`${this.getTag()}: Failed to get max swappable: ${error}`);
33866
+ // const maxSwappable = Web3Number.fromWei("0", vesuAdapter.config.debt.decimals);
33867
+ // return {amount: maxBorrowable.minimum(maxSwappable), dexSwappableAmount: maxSwappable, maxBorrowableAmount: maxBorrowable, borrowableAsset: vesuAdapter.config.debt};
33868
+ // }
33869
+ // }
33870
+ // todo how much to unwind to get back healthy APY zone again
33871
+ // if net APY < LST APR + 0.5%, we need to unwind to get back to LST APR + 1% atleast or 0 vesu position
33872
+ // For xSTRK, simply deposit in Vesu if looping is not viable
33873
+ // /**
33874
+ // * Gets LST APR for the strategy's underlying asset from Endur API
33875
+ // * @returns Promise<number> The LST APR (not divided by 1e18)
33876
+ // */
33877
+ // async getLSTAPR(_address: ContractAddr): Promise<number> {
33878
+ // try {
33879
+ // const vesuAdapter1 = this.getVesuSameTokenAdapter();
33880
+ // const apr = await LSTAPRService.getLSTAPR(vesuAdapter1.config.debt.address);
33881
+ // if (!apr) {
33882
+ // throw new Error('Failed to get LST APR');
33883
+ // }
33884
+ // return apr;
33885
+ // } catch (error) {
33886
+ // logger.warn(`${this.getTag()}: Failed to get LST APR: ${error}`);
33887
+ // return 0;
33888
+ // }
33889
+ // }
33890
+ // async maxNewDeposits(params: { isAPYComputation: boolean } = { isAPYComputation: false }) {
33891
+ // const maxBorrowableAmounts = await this.getMaxBorrowableAmount(params);
33892
+ // let ltv: number | undefined = undefined;
33893
+ // for (let adapter of this.getVesuAdapters()) {
33894
+ // const maxBorrowableAmount = maxBorrowableAmounts.maxBorrowables.find(b => b.borrowableAsset.address.eq(adapter.config.debt.address))?.amount;
33895
+ // if (!maxBorrowableAmount) {
33896
+ // throw new Error(`Max borrowable amount not found for adapter: ${adapter.config.debt.symbol}`);
33897
+ // }
33898
+ // const maxLTV = await adapter.getLTVConfig(this.config);
33899
+ // if (!ltv) {
33900
+ // ltv = maxLTV;
33901
+ // } else if (ltv != maxLTV) {
33902
+ // throw new Error(`LTV mismatch for adapter: ${adapter.config.debt.symbol}`);
33903
+ // }
33904
+ // }
33905
+ // if (!ltv) {
33906
+ // throw new Error('LTV not found');
33907
+ // }
33908
+ // // for simplicity, we assume 1 underlying = 1 LST
33909
+ // const numerator = this.metadata.additionalInfo.targetHealthFactor * maxBorrowableAmounts.netMaxBorrowableAmount.toNumber() / (ltv)
33910
+ // return numerator - maxBorrowableAmounts.netMaxBorrowableAmount.toNumber();
33911
+ // }
33912
+ async getAUM() {
33913
+ const allPositions = [];
33914
+ for (let adapter of this.metadata.additionalInfo.adapters) {
33915
+ const positions = await adapter.adapter.getPositions();
33916
+ allPositions.push(...positions);
34212
33917
  }
34213
- }
34214
- async getPriceOfToken(tokenAddress, retries = MAX_RETRIES) {
34215
- try {
34216
- const url = `https://starknet.impulse.avnu.fi/v1/tokens/${tokenAddress}/prices/line`;
34217
- const response = await axios10.get(url);
34218
- const length = response.data.length;
34219
- return response.data[length - 1].value;
34220
- } catch (err) {
34221
- if (retries > 0) {
34222
- await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
34223
- return this.getPriceOfToken(tokenAddress, retries - 1);
33918
+ const assetPrice = await this.pricer.getPrice(this.asset().symbol);
33919
+ let netAUM = new Web3Number(0, this.asset().decimals);
33920
+ for (let position of allPositions) {
33921
+ if (position.tokenInfo.address.eq(this.asset().address)) {
33922
+ netAUM = netAUM.plus(position.amount);
34224
33923
  } else {
34225
- logger.error(`Failed to fetch price for ${tokenAddress} after ${MAX_RETRIES} attempts`);
34226
- return null;
33924
+ netAUM = netAUM.plus(position.usdValue / assetPrice.price);
34227
33925
  }
34228
33926
  }
33927
+ const prevAum = await this.getPrevAUM();
33928
+ const realAUM = {
33929
+ tokenInfo: this.asset(),
33930
+ amount: netAUM,
33931
+ usdValue: netAUM.toNumber() * assetPrice.price,
33932
+ apy: { apy: netAUM.toNumber() * assetPrice.price, type: "base" /* BASE */ },
33933
+ remarks: "finalised" /* FINALISED */,
33934
+ protocol: Protocols.NONE
33935
+ // just placeholder
33936
+ };
33937
+ const estimatedAUMDelta = {
33938
+ tokenInfo: this.asset(),
33939
+ amount: Web3Number.fromWei("0", this.asset().decimals),
33940
+ usdValue: 0,
33941
+ apy: { apy: 0, type: "base" /* BASE */ },
33942
+ remarks: "defispring" /* DEFISPRING */,
33943
+ protocol: Protocols.NONE
33944
+ // just placeholder
33945
+ };
33946
+ return { net: {
33947
+ tokenInfo: this.asset(),
33948
+ amount: netAUM,
33949
+ usdValue: netAUM.toNumber() * assetPrice.price
33950
+ }, prevAum, splits: [realAUM, estimatedAUMDelta] };
34229
33951
  }
33952
+ /**
33953
+ *
33954
+ * @param params marginAmount is in LST, debtAmount is in underlying
33955
+ */
33956
+ // async getModifyLeverCall(params: {
33957
+ // marginAmount: Web3Number, // >0 during deposit
33958
+ // debtAmount: Web3Number,
33959
+ // lstDexPriceInUnderlying: number,
33960
+ // isIncrease: boolean
33961
+ // }): Promise<Call[]> {
33962
+ // logger.verbose(`${this.getTag()}::getModifyLeverCall marginAmount: ${params.marginAmount}, debtAmount: ${params.debtAmount}, lstDexPriceInUnderlying: ${params.lstDexPriceInUnderlying}, isIncrease: ${params.isIncrease}`);
33963
+ // const vesuAdapter = this.getVesuSameTokenAdapter();
33964
+ // const manage0Info = vesuAdapter.
33965
+ // const manageCall0 = manage0Info.callConstructor({
33966
+ // amount: newDepositAmount
33967
+ // });
33968
+ // const manageCalls = await vesu
33969
+ // return [this.getManageCall(proofsIDs, manageCalls)];
33970
+ // }
33971
+ };
33972
+ function VaultDescription(lstSymbol, underlyingSymbol) {
33973
+ const containerStyle = {
33974
+ maxWidth: "800px",
33975
+ margin: "0 auto",
33976
+ backgroundColor: "#111",
33977
+ color: "#eee",
33978
+ fontFamily: "Arial, sans-serif",
33979
+ borderRadius: "12px"
33980
+ };
33981
+ return /* @__PURE__ */ jsxs3("div", { style: containerStyle, children: [
33982
+ /* @__PURE__ */ jsxs3("h1", { style: { fontSize: "18px", marginBottom: "10px" }, children: [
33983
+ "Liquidation risk managed leverged ",
33984
+ lstSymbol,
33985
+ " Vault"
33986
+ ] }),
33987
+ /* @__PURE__ */ jsxs3("p", { style: { fontSize: "14px", lineHeight: "1.5", marginBottom: "16px" }, children: [
33988
+ "This Levered Endur ",
33989
+ lstSymbol,
33990
+ " vault is a tokenized leveraged Vault, auto-compounding strategy that takes upto 5x leverage on ",
33991
+ lstSymbol,
33992
+ " by borrow ",
33993
+ underlyingSymbol,
33994
+ ". Borrowed amount is swapped to ",
33995
+ lstSymbol,
33996
+ " to create leverage. Depositors receive vault shares that represent a proportional claim on the underlying assets and accrued yield."
33997
+ ] }),
33998
+ /* @__PURE__ */ jsxs3("p", { style: { fontSize: "14px", lineHeight: "1.5", marginBottom: "16px" }, children: [
33999
+ "This vault uses Vesu for lending and borrowing. The oracle used by this pool is a ",
34000
+ highlightTextWithLinks("conversion rate oracle", [{ highlight: "conversion rate oracle", link: "https://docs.pragma.build/starknet/development#conversion-rate" }]),
34001
+ " ",
34002
+ "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."
34003
+ ] }),
34004
+ /* @__PURE__ */ jsx4("div", { style: { backgroundColor: "#222", padding: "10px", borderRadius: "8px", marginBottom: "20px", border: "1px solid #444" }, children: /* @__PURE__ */ jsxs3("p", { style: { fontSize: "13px", color: "#ccc" }, children: [
34005
+ /* @__PURE__ */ jsx4("strong", { children: "Withdrawals:" }),
34006
+ " Requests can take up to ",
34007
+ /* @__PURE__ */ jsx4("strong", { children: "1-2 hours" }),
34008
+ " to process as the vault unwinds and settles routing."
34009
+ ] }) }),
34010
+ /* @__PURE__ */ jsx4("div", { style: { backgroundColor: "#222", padding: "10px", borderRadius: "8px", marginBottom: "20px", border: "1px solid #444" }, children: /* @__PURE__ */ jsxs3("p", { style: { fontSize: "13px", color: "#ccc" }, children: [
34011
+ /* @__PURE__ */ jsx4("strong", { children: "Debt limits:" }),
34012
+ " Pools on Vesu have debt caps that are gradually increased over time. Until caps are raised, deposited Tokens remain in the vault, generating a shared net return for all depositors. There is no additional fee taken by Troves on Yield token's APY, its only on added gain."
34013
+ ] }) })
34014
+ ] });
34015
+ }
34016
+ function getDescription(tokenSymbol, underlyingSymbol) {
34017
+ return VaultDescription(tokenSymbol, underlyingSymbol);
34018
+ }
34019
+ function getLooperSettings(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
34020
+ vaultSettings.leafAdapters = [];
34021
+ const lstToken = Global.getDefaultTokens().find((token) => token.symbol === lstSymbol);
34022
+ const underlyingToken = Global.getDefaultTokens().find((token) => token.symbol === underlyingSymbol);
34023
+ const baseAdapterConfig = {
34024
+ baseToken: lstToken,
34025
+ supportedPositions: [{ asset: lstToken, isDebt: false }],
34026
+ networkConfig: getMainnetConfig(),
34027
+ pricer: new PricerFromApi(getMainnetConfig(), Global.getDefaultTokens()),
34028
+ vaultAllocator: vaultSettings.vaultAllocator,
34029
+ vaultAddress: vaultSettings.vaultAddress
34030
+ };
34031
+ const vesuAdapterLST = new VesuSupplyOnlyAdapter({
34032
+ // xWBTC vToken on re7 xBTC pool
34033
+ vTokenContract: ContractAddr.from("0x062a162d0827db6f43ebb850cbef3c99fc7969e3070b83a2236c9f3713c89fd8"),
34034
+ ...baseAdapterConfig
34035
+ });
34036
+ const vesuMultiplyAdapters = borrowableAssets.map((position) => new VesuMultiplyAdapter({
34037
+ poolId: pool1,
34038
+ collateral: lstToken,
34039
+ debt: Global.getDefaultTokens().find((token) => token.symbol === position),
34040
+ targetHealthFactor: vaultSettings.targetHealthFactor,
34041
+ minHealthFactor: vaultSettings.minHealthFactor,
34042
+ quoteAmountToFetchPrice: vaultSettings.quoteAmountToFetchPrice,
34043
+ ...baseAdapterConfig,
34044
+ supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }],
34045
+ minimumVesuMovementAmount: 0
34046
+ }));
34047
+ const unusedBalanceAdapter = new UnusedBalanceAdapter({
34048
+ ...baseAdapterConfig
34049
+ });
34050
+ vaultSettings.adapters.push({ id: `${vesuAdapterLST.name}_${lstToken.symbol}_${underlyingToken.symbol}`, adapter: vesuAdapterLST });
34051
+ vesuMultiplyAdapters.map((adapter) => vaultSettings.adapters.push({ id: `${adapter.name}_${lstToken.symbol}_${underlyingToken.symbol}`, adapter }));
34052
+ vaultSettings.adapters.push({ id: `${unusedBalanceAdapter.name}_${lstToken.symbol}`, adapter: unusedBalanceAdapter });
34053
+ const commonAdapter = new CommonAdapter({
34054
+ id: "flash_loan_init" /* FLASH_LOAN */,
34055
+ vaultAddress: vaultSettings.vaultAddress,
34056
+ vaultAllocator: vaultSettings.vaultAllocator,
34057
+ manager: vaultSettings.manager,
34058
+ asset: lstToken.address
34059
+ });
34060
+ vaultSettings.leafAdapters.push(() => vesuAdapterLST.getDepositLeaf());
34061
+ vaultSettings.leafAdapters.push(() => vesuAdapterLST.getWithdrawLeaf());
34062
+ vesuMultiplyAdapters.map((adapter) => vaultSettings.leafAdapters.push(() => adapter.getDepositLeaf()));
34063
+ vesuMultiplyAdapters.map((adapter) => vaultSettings.leafAdapters.push(() => adapter.getWithdrawLeaf()));
34064
+ vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, vaultSettings.vaultAddress, "approve_bring_liquidity" /* APPROVE_BRING_LIQUIDITY */).bind(commonAdapter));
34065
+ vaultSettings.leafAdapters.push(commonAdapter.getBringLiquidityAdapter("bring_liquidity" /* BRING_LIQUIDITY */).bind(commonAdapter));
34066
+ return vaultSettings;
34067
+ }
34068
+ var AUDIT_URL3 = "https://docs.troves.fi/p/security#starknet-vault-kit";
34069
+ function getFAQs(lstSymbol, underlyingSymbol, isLST) {
34070
+ return [
34071
+ {
34072
+ question: `What is the Hyper ${lstSymbol} Vault?`,
34073
+ answer: `The Hyper ${lstSymbol} Vault is a tokenized strategy that automatically loops your ${lstSymbol} to create up to 5x leverage to hence yield in a very low risk manner.`
34074
+ },
34075
+ {
34076
+ question: "How does yield allocation work?",
34077
+ answer: `The strategy uses deposited ${lstSymbol} to collateralize it on Vesu, borrow more ${underlyingSymbol} to loop further. Instead of manually doing this, using flash loan, this leverage is created in a single gas efficient step. Our continuous monitoring systems gauge current yield and available liquidity in real time to make sure yield is optimal. For instance, if the looping becomes in-efficient in future, the strategy will rebalance to reduce leverage or simply hold ${lstSymbol} to continue earning yield.`
34078
+ },
34079
+ {
34080
+ question: "Which protocols/dApp are used??",
34081
+ answer: isLST ? /* @__PURE__ */ jsxs3("span", { children: [
34082
+ "Currently, the LST is from ",
34083
+ /* @__PURE__ */ jsx4("strong", { children: "Endur" }),
34084
+ " while ",
34085
+ /* @__PURE__ */ jsx4("strong", { children: "Vesu" }),
34086
+ " is used to collateralize the looped position."
34087
+ ] }) : /* @__PURE__ */ jsxs3("span", { children: [
34088
+ "Currently, the Yield Token is from ",
34089
+ /* @__PURE__ */ jsx4("strong", { children: "Re7 Labs (Midas)" }),
34090
+ " while ",
34091
+ /* @__PURE__ */ jsx4("strong", { children: "Vesu" }),
34092
+ " is used to collateralize the looped position."
34093
+ ] })
34094
+ },
34095
+ {
34096
+ question: "Can I get liquidated?",
34097
+ answer: "The strategy uses highly correlated assets which drastically reduces 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."
34098
+ },
34099
+ {
34100
+ question: "What do I receive when I deposit?",
34101
+ answer: "Depositors receive vault tokens representing their proportional share of the vault. These tokens entitle holders to both the principal and accrued yield."
34102
+ },
34103
+ {
34104
+ question: "How long do withdrawals take?",
34105
+ answer: "Withdrawals may take up to 1-2 hours to process, as the vault unwinds and settles liquidity routing across integrated protocols. In case of large withdrawals, to avoid slippage, we may slowly unwind the position, which could make the withdrawals longer."
34106
+ },
34107
+ {
34108
+ question: `Is the Hyper ${lstSymbol} Vault non-custodial?`,
34109
+ answer: `Yes. The Hyper ${lstSymbol} Vault operates entirely on-chain. Users always maintain control of their vault tokens, and the strategy is fully transparent.`
34110
+ },
34111
+ {
34112
+ question: "Is the Vault audited?",
34113
+ answer: `Yes. The Hyper ${lstSymbol} Vault is audited by Zellic. Look for safety icon beside the strategy name for more details.`
34114
+ },
34115
+ {
34116
+ question: "Are there any fees?",
34117
+ answer: "Troves charges a performance of 10% on the yield generated. The APY shown is net of this fee. This fee is only applied to the profits earned, ensuring that users retain their initial capital."
34118
+ }
34119
+ ];
34120
+ }
34121
+ var _riskFactor3 = [
34122
+ { type: "Smart Contract Risk" /* SMART_CONTRACT_RISK */, value: 2 /* WELL_AUDITED */, weight: 25, reason: "Audited by Zellic" },
34123
+ { type: "Liquidation Risk" /* LIQUIDATION_RISK */, value: 1 /* VERY_LOW_PROBABILITY */, weight: 25, reason: "The collateral and debt are highly correlated" },
34124
+ { type: "Technical Risk" /* TECHNICAL_RISK */, value: 1 /* STABLE_INFRASTRUCTURE */, weight: 25, reason: "Liquidation can only happen if vault is left un-monitored for weeks, which is highly unlikely. We actively monitor all services on a daily basis." },
34125
+ { type: "Depeg Risk" /* DEPEG_RISK */, value: 2 /* GENERALLY_STABLE */, weight: 25, reason: "Generally stable pegged assets" }
34126
+ ];
34127
+ var borrowableAssets = [
34128
+ "WBTC",
34129
+ "tBTC",
34130
+ "LBTC",
34131
+ "solvBTC"
34132
+ ];
34133
+ var hyperxSTRK = {
34134
+ vaultAddress: ContractAddr.from("0x46c7a54c82b1fe374353859f554a40b8bd31d3e30f742901579e7b57b1b5960"),
34135
+ manager: ContractAddr.from("0x5d499cd333757f461a0bedaca3dfc4d77320c773037e0aa299f22a6dbfdc03a"),
34136
+ vaultAllocator: ContractAddr.from("0x511d07953a09bc7c505970891507c5a2486d2ea22752601a14db092186d7caa"),
34137
+ redeemRequestNFT: ContractAddr.from("0x51e40b839dc0c2feca923f863072673b94abfa2483345be3b30b457a90d095"),
34138
+ aumOracle: ContractAddr.from("0x48cf709870a1a0d453d37de108e0c41b8b89819ef54f95abc0e2e1f98bbe937"),
34139
+ leafAdapters: [],
34140
+ adapters: [],
34141
+ targetHealthFactor: 1.1,
34142
+ minHealthFactor: 1.05,
34143
+ borrowable_assets: Global.getDefaultTokens().filter((token) => token.symbol === "STRK"),
34144
+ underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "STRK"),
34145
+ quoteAmountToFetchPrice: new Web3Number("100", Global.getDefaultTokens().find((token) => token.symbol === "STRK").decimals)
34146
+ };
34147
+ var hyperxWBTC = {
34148
+ vaultAddress: ContractAddr.from("0x2da9d0f96a46b453f55604313785dc866424240b1c6811d13bef594343db818"),
34149
+ manager: ContractAddr.from("0x75866db44c81e6986f06035206ee9c7d15833ddb22d6a22c016cfb5c866a491"),
34150
+ vaultAllocator: ContractAddr.from("0x57b5c1bb457b5e840a2714ae53ada87d77be2f3fd33a59b4fe709ef20c020c1"),
34151
+ redeemRequestNFT: ContractAddr.from("0x7a5dc288325456f05e70e9616e16bc02ffbe448f4b89f80b47c0970b989c7c"),
34152
+ aumOracle: ContractAddr.from("0x258f8a0ca0d21f542e48ad89d00e92dc4d9db4999084f50ef9c22dfb1e83023"),
34153
+ leafAdapters: [],
34154
+ adapters: [],
34155
+ targetHealthFactor: 1.1,
34156
+ minHealthFactor: 1.05,
34157
+ borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
34158
+ underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "WBTC"),
34159
+ quoteAmountToFetchPrice: new Web3Number("0.001", Global.getDefaultTokens().find((token) => token.symbol === "WBTC").decimals)
34160
+ };
34161
+ var hyperxtBTC = {
34162
+ vaultAddress: ContractAddr.from("0x47d5f68477e5637ce0e56436c6b5eee5a354e6828995dae106b11a48679328"),
34163
+ manager: ContractAddr.from("0xc4cc3e08029a0ae076f5fdfca70575abb78d23c5cd1c49a957f7e697885401"),
34164
+ vaultAllocator: ContractAddr.from("0x50bbd4fe69f841ecb13b2619fe50ebfa4e8944671b5d0ebf7868fd80c61b31e"),
34165
+ redeemRequestNFT: ContractAddr.from("0xeac9032f02057779816e38a6cb9185d12d86b3aacc9949b96b36de359c1e3"),
34166
+ aumOracle: ContractAddr.from("0x7e0d05cb7ba3f7db77a36c21c21583b5a524c2e685c08c24b3554911fb4a039"),
34167
+ leafAdapters: [],
34168
+ adapters: [],
34169
+ targetHealthFactor: 1.1,
34170
+ minHealthFactor: 1.05,
34171
+ borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
34172
+ underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "tBTC"),
34173
+ quoteAmountToFetchPrice: new Web3Number("0.001", Global.getDefaultTokens().find((token) => token.symbol === "tBTC").decimals)
34174
+ };
34175
+ var hyperxsBTC = {
34176
+ vaultAddress: ContractAddr.from("0x437ef1e7d0f100b2e070b7a65cafec0b2be31b0290776da8b4112f5473d8d9"),
34177
+ manager: ContractAddr.from("0xc9ac023090625b0be3f6532ca353f086746f9c09f939dbc1b2613f09e5f821"),
34178
+ vaultAllocator: ContractAddr.from("0x60c2d856936b975459a5b4eb28b8672d91f757bd76cebb6241f8d670185dc01"),
34179
+ redeemRequestNFT: ContractAddr.from("0x429e8ee8bc7ecd1ade72630d350a2e0f10f9a2507c45f188ba17fe8f2ab4cf3"),
34180
+ aumOracle: ContractAddr.from("0x149298ade3e79ec6cbdac6cfad289c57504eaf54e590939136ed1ceca60c345"),
34181
+ leafAdapters: [],
34182
+ adapters: [],
34183
+ targetHealthFactor: 1.1,
34184
+ minHealthFactor: 1.05,
34185
+ borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
34186
+ underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "solvBTC"),
34187
+ quoteAmountToFetchPrice: new Web3Number("0.001", Global.getDefaultTokens().find((token) => token.symbol === "solvBTC").decimals)
34188
+ };
34189
+ var hyperxLBTC = {
34190
+ vaultAddress: ContractAddr.from("0x64cf24d4883fe569926419a0569ab34497c6956a1a308fa883257f7486d7030"),
34191
+ manager: ContractAddr.from("0x203530a4022a99b8f4b406aaf33b0849d43ad7422c1d5cc14ff8c667abec6c0"),
34192
+ vaultAllocator: ContractAddr.from("0x7dbc8ccd4eabce6ea6c19e0e5c9ccca3a93bd510303b9e071cbe25fc508546e"),
34193
+ redeemRequestNFT: ContractAddr.from("0x5ee66a39af9aef3d0d48982b4a63e8bd2a5bad021916bd87fb0eae3a26800b8"),
34194
+ aumOracle: ContractAddr.from("0x23d69e4391fa72d10e625e7575d8bddbb4aff96f04503f83fdde23123bf41d0"),
34195
+ leafAdapters: [],
34196
+ adapters: [],
34197
+ targetHealthFactor: 1.1,
34198
+ minHealthFactor: 1.05,
34199
+ borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
34200
+ underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "LBTC"),
34201
+ quoteAmountToFetchPrice: new Web3Number("0.001", Global.getDefaultTokens().find((token) => token.symbol === "LBTC").decimals)
34202
+ };
34203
+ var hypermRe7BTC = {
34204
+ vaultAddress: ContractAddr.from("0x6c89b75d09de82477edb86b2c2918cfc1a5dc0177cfbdea46278386b6499645"),
34205
+ manager: ContractAddr.from("0x7bc2d0535e13352d3ab78ea047616a3162068294297304943d2302122a150a1"),
34206
+ vaultAllocator: ContractAddr.from("0x760f9cebca9d2ee624f4224591da6da8b3ea5fd2410590735709551bd4e7570"),
34207
+ redeemRequestNFT: ContractAddr.from("0x5e045ae0160f7650f8a4dd7c826f25630a89fe62434db4441e7e0075608180f"),
34208
+ aumOracle: ContractAddr.from("0x3958df341b838813c24efb9183c23bddd1c57d44b1b86c0dd57f67887b89fba"),
34209
+ leafAdapters: [],
34210
+ adapters: [],
34211
+ targetHealthFactor: 1.1,
34212
+ minHealthFactor: 1.05,
34213
+ borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
34214
+ underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "WBTC"),
34215
+ quoteAmountToFetchPrice: new Web3Number("0.001", Global.getDefaultTokens().find((token) => token.symbol === "mRe7BTC").decimals)
34216
+ };
34217
+ var hypermRe7YIELD = {
34218
+ vaultAddress: ContractAddr.from("0x42797ab4eb1f72787442e91a73d63a39e3a141c1106470a946ecc328db6896c"),
34219
+ manager: ContractAddr.from("0x435b45d40fbb406cf69ac84bb471e7b7a4ea2295d0893c05dd2db565295e77f"),
34220
+ vaultAllocator: ContractAddr.from("0x456c4c6afca90512aeb5c735d84405fea6e51ab06d1851ac8cdb0a235e14f15"),
34221
+ redeemRequestNFT: ContractAddr.from("0x4bbb25c2568af07967342833f7db1aece1be1be2330798dab4ee585aa6c2c72"),
34222
+ aumOracle: ContractAddr.from("0x3e1f2825158cafccc9b42a8165d17ceb6b8e966474d9c63587d338746888382"),
34223
+ leafAdapters: [],
34224
+ adapters: [],
34225
+ targetHealthFactor: 1.1,
34226
+ minHealthFactor: 1.05,
34227
+ borrowable_assets: [Global.getDefaultTokens().find((token) => token.symbol === "USDC")],
34228
+ underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "USDC"),
34229
+ quoteAmountToFetchPrice: new Web3Number("0.001", Global.getDefaultTokens().find((token) => token.symbol === "mRe7BTC").decimals)
34230
34230
  };
34231
+ function getInvestmentSteps(lstSymbol, underlyingSymbol) {
34232
+ return [
34233
+ `Deposit ${lstSymbol} into the vault`,
34234
+ `The vault manager loops the ${underlyingSymbol} to buy ${lstSymbol}`,
34235
+ `The vault manager collateralizes the ${lstSymbol} on Vesu`,
34236
+ `The vault manager borrows more ${underlyingSymbol} to loop further`,
34237
+ `If required, adjust leverage or re-allocate assets within pool on Vesu to optimize yield`
34238
+ ];
34239
+ }
34240
+ function getStrategySettings(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST) {
34241
+ return {
34242
+ name: `Hyper ${lstSymbol}`,
34243
+ description: getDescription(lstSymbol, underlyingSymbol),
34244
+ address: addresses.vaultAddress,
34245
+ launchBlock: 0,
34246
+ type: "Other",
34247
+ depositTokens: [Global.getDefaultTokens().find((token) => token.symbol === lstSymbol)],
34248
+ additionalInfo: getLooperSettings(lstSymbol, underlyingSymbol, addresses, lstSymbol === "xSTRK" ? VesuPools.Re7xSTRK : VesuPools.Re7xBTC),
34249
+ risk: {
34250
+ riskFactor: _riskFactor3,
34251
+ netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),
34252
+ notARisks: getNoRiskTags(_riskFactor3)
34253
+ },
34254
+ auditUrl: AUDIT_URL3,
34255
+ protocols: [Protocols.ENDUR, Protocols.VESU],
34256
+ maxTVL: Web3Number.fromWei(0, 18),
34257
+ contractDetails: getContractDetails(addresses),
34258
+ faqs: getFAQs(lstSymbol, underlyingSymbol, isLST),
34259
+ investmentSteps: getInvestmentSteps(lstSymbol, underlyingSymbol),
34260
+ isPreview,
34261
+ apyMethodology: isLST ? "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." : "Current annualized APY in terms of base asset of the Yield Token. There is no additional fee taken by Troves on yield token APY. We charge a 10% performance fee on the additional gain which is already accounted in the APY shown."
34262
+ };
34263
+ }
34264
+ var HyperLSTStrategies = [
34265
+ getStrategySettings("xSTRK", "STRK", hyperxSTRK, false, true),
34266
+ getStrategySettings("xWBTC", "WBTC", hyperxWBTC, false, false),
34267
+ getStrategySettings("xtBTC", "tBTC", hyperxtBTC, false, false),
34268
+ getStrategySettings("xsBTC", "solvBTC", hyperxsBTC, false, false),
34269
+ getStrategySettings("xLBTC", "LBTC", hyperxLBTC, false, false),
34270
+ getStrategySettings("mRe7BTC", "mRe7BTC", hypermRe7BTC, false, false),
34271
+ getStrategySettings("mRe7YIELD", "mRe7YIELD", hypermRe7YIELD, false, false)
34272
+ ];
34231
34273
 
34232
34274
  // src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx
34233
34275
  import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
@@ -34345,10 +34387,16 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34345
34387
  proofGroups,
34346
34388
  await proofsInfo.callConstructor({ amount })
34347
34389
  );
34348
- return [approveCall, transferCall, call];
34390
+ return {
34391
+ calls: [approveCall, transferCall, call],
34392
+ status: true
34393
+ };
34349
34394
  } catch (err) {
34350
34395
  logger.error(`error moving assets to vault allocator: ${err}`);
34351
- return [];
34396
+ return {
34397
+ calls: [],
34398
+ status: false
34399
+ };
34352
34400
  }
34353
34401
  }
34354
34402
  async shouldInvest() {
@@ -34597,9 +34645,10 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34597
34645
  const vesuAmountDifferenceAbs = vesuAmountDifference.abs();
34598
34646
  logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculated movements - Extended withdrawal: ${totalExtendedWithdrawal.toNumber()}, Extended deposit: ${totalExtendedDeposit.toNumber()}, Extended diff: ${extendedAmountDifference.toNumber()}, Projected wallet: ${projectedWalletBalance.toNumber()}, Vesu diff: ${vesuAmountDifference.toNumber()}`);
34599
34647
  let calls = [];
34648
+ let transactionResults = [];
34600
34649
  if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
34601
34650
  try {
34602
- const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
34651
+ const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
34603
34652
  {
34604
34653
  to: Protocols.VAULT.name,
34605
34654
  from: Protocols.EXTENDED.name,
@@ -34609,17 +34658,25 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34609
34658
  vesuAdapter
34610
34659
  );
34611
34660
  if (extendedStatus) {
34612
- calls.push(...extendedCalls);
34661
+ transactionResults.push({
34662
+ status: extendedStatus,
34663
+ calls: extendedCalls,
34664
+ transactionMetadata: {
34665
+ ...extendedTransactionMetadata,
34666
+ transactionType: "DEPOSIT"
34667
+ }
34668
+ });
34613
34669
  } else {
34614
- return [];
34670
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmount.abs() }, "NONE")];
34615
34671
  }
34616
34672
  } catch (err) {
34617
34673
  logger.error(`Failed moving assets to vault: ${err}`);
34674
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmount.abs() }, "NONE")];
34618
34675
  }
34619
34676
  }
34620
34677
  if (vesuAmount.isNegative() && vesuAmount.abs().greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
34621
34678
  try {
34622
- const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
34679
+ const { calls: vesuCalls, status: vesuStatus, transactionMetadata: vesuTransactionMetadata } = await this.moveAssets(
34623
34680
  {
34624
34681
  to: Protocols.EXTENDED.name,
34625
34682
  from: Protocols.VESU.name,
@@ -34628,18 +34685,26 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34628
34685
  extendedAdapter,
34629
34686
  vesuAdapter
34630
34687
  );
34631
- calls.push(...vesuCalls);
34632
34688
  if (!vesuStatus) {
34633
- return [];
34634
- }
34689
+ return [this.createTransactionResult([], false, { from: Protocols.VESU.name, to: Protocols.EXTENDED.name, amount: vesuAmount.abs() }, "NONE")];
34690
+ }
34691
+ transactionResults.push({
34692
+ status: vesuStatus,
34693
+ calls: vesuCalls,
34694
+ transactionMetadata: {
34695
+ ...vesuTransactionMetadata,
34696
+ transactionType: "DEPOSIT"
34697
+ }
34698
+ });
34635
34699
  } catch (err) {
34636
- logger.error(`Failed moving assets to vault: ${err}`);
34700
+ logger.error(`Failed moving assets to extended via vault allocator: ${err}`);
34701
+ return [this.createTransactionResult([], false, { from: Protocols.VESU.name, to: Protocols.EXTENDED.name, amount: vesuAmount.abs() }, "NONE")];
34637
34702
  }
34638
34703
  }
34639
34704
  if (extendedAmountDifferenceAbs.greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
34640
34705
  if (extendedAmountDifference.greaterThan(0)) {
34641
34706
  try {
34642
- const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
34707
+ const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
34643
34708
  {
34644
34709
  to: Protocols.EXTENDED.name,
34645
34710
  from: Protocols.VAULT.name,
@@ -34649,18 +34714,22 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34649
34714
  vesuAdapter
34650
34715
  );
34651
34716
  if (extendedStatus) {
34652
- calls.push(...extendedCalls);
34717
+ transactionResults.push({
34718
+ status: extendedStatus,
34719
+ calls: extendedCalls,
34720
+ transactionMetadata: extendedTransactionMetadata
34721
+ });
34653
34722
  } else {
34654
34723
  logger.error(`Failed to move assets to extended - operation returned false status`);
34655
- return [];
34724
+ return [this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.EXTENDED.name, amount: extendedAmountDifference }, "NONE")];
34656
34725
  }
34657
34726
  } catch (err) {
34658
34727
  logger.error(`Failed moving assets to extended: ${err}`);
34659
- return [];
34728
+ return [this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.EXTENDED.name, amount: extendedAmountDifference }, "NONE")];
34660
34729
  }
34661
34730
  } else if (extendedAmountDifference.lessThan(0)) {
34662
34731
  try {
34663
- const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
34732
+ const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
34664
34733
  {
34665
34734
  to: Protocols.VAULT.name,
34666
34735
  from: Protocols.EXTENDED.name,
@@ -34670,14 +34739,21 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34670
34739
  vesuAdapter
34671
34740
  );
34672
34741
  if (extendedStatus) {
34673
- calls.push(...extendedCalls);
34742
+ transactionResults.push({
34743
+ status: extendedStatus,
34744
+ calls: extendedCalls,
34745
+ transactionMetadata: {
34746
+ ...extendedTransactionMetadata,
34747
+ transactionType: "DEPOSIT"
34748
+ }
34749
+ });
34674
34750
  } else {
34675
34751
  logger.error(`Failed to withdraw from extended - operation returned false status`);
34676
- return [];
34752
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmountDifferenceAbs }, "NONE")];
34677
34753
  }
34678
34754
  } catch (err) {
34679
34755
  logger.error(`Failed moving assets from extended to vault: ${err}`);
34680
- return [];
34756
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmountDifferenceAbs }, "NONE")];
34681
34757
  }
34682
34758
  }
34683
34759
  }
@@ -34688,7 +34764,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34688
34764
  );
34689
34765
  } else {
34690
34766
  try {
34691
- const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
34767
+ const { calls: vesuCalls, status: vesuStatus, transactionMetadata: vesuTransactionMetadata } = await this.moveAssets(
34692
34768
  {
34693
34769
  to: Protocols.VAULT.name,
34694
34770
  from: Protocols.EXTENDED.name,
@@ -34699,20 +34775,46 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34699
34775
  );
34700
34776
  if (!vesuStatus) {
34701
34777
  logger.error(`Failed to move assets to vesu - operation returned false status`);
34702
- return [];
34778
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: vesuAmountDifference }, "NONE")];
34703
34779
  }
34704
- calls.push(...vesuCalls);
34780
+ transactionResults.push({
34781
+ status: vesuStatus,
34782
+ calls: vesuCalls,
34783
+ transactionMetadata: {
34784
+ ...vesuTransactionMetadata,
34785
+ transactionType: "DEPOSIT"
34786
+ }
34787
+ });
34705
34788
  } catch (err) {
34706
34789
  logger.error(`Failed moving assets to vault: ${err}`);
34707
- return [];
34790
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: vesuAmountDifference }, "NONE")];
34708
34791
  }
34709
34792
  }
34710
34793
  }
34711
- return calls;
34794
+ return transactionResults;
34712
34795
  } catch (err) {
34713
34796
  logger.error(`Failed moving assets to vesu: ${err}`);
34714
- return [];
34797
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: new Web3Number(0, USDC_TOKEN_DECIMALS) }, "NONE")];
34798
+ }
34799
+ }
34800
+ /**
34801
+ * Helper method to create transaction result with metadata
34802
+ */
34803
+ createTransactionResult(calls, status, params, transactionType) {
34804
+ if (status) {
34805
+ return {
34806
+ calls,
34807
+ status,
34808
+ transactionMetadata: {
34809
+ protocolFrom: params.from,
34810
+ protocolTo: params.to,
34811
+ transactionType,
34812
+ usdAmount: params.amount.abs().toFixed(),
34813
+ status: "PENDING"
34814
+ }
34815
+ };
34715
34816
  }
34817
+ return { calls: [], status: false, transactionMetadata: { protocolFrom: "", protocolTo: "", transactionType: "DEPOSIT", usdAmount: "0", status: "FAILED" } };
34716
34818
  }
34717
34819
  async moveAssets(params, extendedAdapter, vesuAdapter) {
34718
34820
  try {
@@ -34720,10 +34822,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34720
34822
  logger.error(
34721
34823
  `Invalid amount for moveAssets: ${params.amount.toNumber()}. Amount must be positive.`
34722
34824
  );
34723
- return {
34724
- calls: [],
34725
- status: false
34726
- };
34825
+ return this.createTransactionResult([], false, params, "NONE");
34727
34826
  }
34728
34827
  const amountAbs = params.amount.abs();
34729
34828
  if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
@@ -34731,10 +34830,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34731
34830
  logger.warn(
34732
34831
  `Amount ${amountAbs.toNumber()} is below minimum Extended movement amount ${extendedAdapter.minimumExtendedMovementAmount}. Skipping operation.`
34733
34832
  );
34734
- return {
34735
- calls: [],
34736
- status: false
34737
- };
34833
+ return this.createTransactionResult([], false, params, "NONE");
34738
34834
  }
34739
34835
  }
34740
34836
  if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
@@ -34742,19 +34838,13 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34742
34838
  logger.warn(
34743
34839
  `Amount ${amountAbs.toNumber()} is below minimum Vesu movement amount ${vesuAdapter.minimumVesuMovementAmount}. Skipping operation.`
34744
34840
  );
34745
- return {
34746
- calls: [],
34747
- status: false
34748
- };
34841
+ return this.createTransactionResult([], false, params, "NONE");
34749
34842
  }
34750
34843
  }
34751
34844
  const avnuAdapter = await this.getAvnuAdapter();
34752
34845
  if (!avnuAdapter) {
34753
34846
  logger.error(`avnu adapter not found: ${avnuAdapter}`);
34754
- return {
34755
- calls: [],
34756
- status: false
34757
- };
34847
+ return this.createTransactionResult([], false, params, "NONE");
34758
34848
  }
34759
34849
  logger.info(`moveAssets params, ${JSON.stringify(params)}`);
34760
34850
  const collateralToken = vesuAdapter.config.supportedPositions[0].asset;
@@ -34773,19 +34863,13 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34773
34863
  await proofsInfo.callConstructor({ amount: params.amount })
34774
34864
  );
34775
34865
  calls.push(call);
34776
- return {
34777
- calls: [call],
34778
- status: true
34779
- };
34866
+ return this.createTransactionResult(calls, true, params, "DEPOSIT");
34780
34867
  } else if (params.to === Protocols.VAULT.name && params.from === Protocols.EXTENDED.name) {
34781
34868
  const extendedLeverage = calculateExtendedLevergae();
34782
34869
  const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
34783
34870
  if (!extendedHoldings) {
34784
34871
  logger.error(`error getting extended holdings: ${extendedHoldings}`);
34785
- return {
34786
- calls: [],
34787
- status: false
34788
- };
34872
+ return this.createTransactionResult([], false, params, "NONE");
34789
34873
  }
34790
34874
  const extendedHoldingAmount = new Web3Number(
34791
34875
  extendedHoldings.availableForWithdrawal,
@@ -34812,36 +34896,36 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34812
34896
  const updatedHoldings = await extendedAdapter.getExtendedDepositAmount();
34813
34897
  if (!updatedHoldings || new Web3Number(updatedHoldings.availableForWithdrawal, USDC_TOKEN_DECIMALS).lessThan(params.amount.abs())) {
34814
34898
  logger.error(`Insufficient balance after opening position. Available: ${updatedHoldings?.availableForWithdrawal}, Needed: ${params.amount.abs()}`);
34815
- return { calls: [], status: false };
34899
+ return this.createTransactionResult([], false, params, "NONE");
34816
34900
  }
34817
34901
  }
34818
- const withdrawalFromExtended = await extendedAdapter.withdrawFromExtended(params.amount);
34819
- if (withdrawalFromExtended) {
34902
+ const {
34903
+ status: withdrawalFromExtendedStatus,
34904
+ receivedTxnHash: withdrawalFromExtendedTxnHash
34905
+ } = await extendedAdapter.withdrawFromExtended(params.amount);
34906
+ logger.info(`withdrawalFromExtendedStatus: ${withdrawalFromExtendedStatus}, withdrawalFromExtendedTxnHash: ${withdrawalFromExtendedTxnHash}`);
34907
+ if (withdrawalFromExtendedStatus && withdrawalFromExtendedTxnHash) {
34820
34908
  const extendedHoldings2 = await extendedAdapter.getExtendedDepositAmount();
34821
34909
  logger.info(`extendedHoldings after withdrawal ${extendedHoldings2?.availableForWithdrawal}`);
34822
34910
  await new Promise((resolve) => setTimeout(resolve, 5e3));
34823
- const calls = await this.moveAssetsToVaultAllocator(params.amount, extendedAdapter);
34824
- if (calls.length > 0) {
34825
- return {
34826
- calls,
34827
- status: true
34828
- };
34911
+ const { calls, status } = await this.moveAssetsToVaultAllocator(params.amount, extendedAdapter);
34912
+ if (calls.length > 0 && status) {
34913
+ return this.createTransactionResult(calls, true, params, "WITHDRAWAL");
34914
+ } else {
34915
+ return this.createTransactionResult([], true, params, "WITHDRAWAL");
34829
34916
  }
34917
+ } else if (withdrawalFromExtendedStatus && !withdrawalFromExtendedTxnHash) {
34918
+ logger.error("withdrawal from extended successful, but funds didn't get transferred to the wallet");
34919
+ return this.createTransactionResult([], true, params, "WITHDRAWAL");
34830
34920
  } else {
34831
34921
  logger.error("withdrawal from extended failed");
34832
- return {
34833
- calls: [],
34834
- status: false
34835
- };
34922
+ return this.createTransactionResult([], false, params, "NONE");
34836
34923
  }
34837
34924
  } else if (params.to === Protocols.VAULT.name && params.from === Protocols.VESU.name) {
34838
34925
  const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "close" /* CLOSE */);
34839
34926
  if (!isPriceDifferenceBetweenAvnuAndExtended) {
34840
34927
  logger.warn(`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
34841
- return {
34842
- calls: [],
34843
- status: false
34844
- };
34928
+ return this.createTransactionResult([], false, params, "NONE");
34845
34929
  }
34846
34930
  const vesuAmountInBTC = new Web3Number(
34847
34931
  params.amount.dividedBy(collateralPrice.price).toFixed(WBTC_TOKEN_DECIMALS),
@@ -34862,18 +34946,12 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34862
34946
  await swapProofsInfo.callConstructor({ amount: vesuAmountInBTC })
34863
34947
  );
34864
34948
  calls.push(swapCall);
34865
- return {
34866
- calls,
34867
- status: true
34868
- };
34949
+ return this.createTransactionResult(calls, true, params, "WITHDRAWAL");
34869
34950
  } else if (params.to === Protocols.EXTENDED.name && params.from === Protocols.VESU.name) {
34870
34951
  const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "close" /* CLOSE */);
34871
34952
  if (!isPriceDifferenceBetweenAvnuAndExtended) {
34872
34953
  logger.warn(`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
34873
- return {
34874
- calls: [],
34875
- status: false
34876
- };
34954
+ return this.createTransactionResult([], false, params, "NONE");
34877
34955
  }
34878
34956
  const vesuAmountInBTC = new Web3Number(
34879
34957
  params.amount.dividedBy(collateralPrice.price).toNumber(),
@@ -34904,127 +34982,21 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34904
34982
  await proofsInfoDeposit.callConstructor({ amount: params.amount })
34905
34983
  );
34906
34984
  calls.push(callDeposit);
34907
- return {
34908
- calls,
34909
- status: true
34910
- };
34985
+ return this.createTransactionResult(calls, true, params, "DEPOSIT");
34911
34986
  }
34912
- return {
34913
- calls: [],
34914
- status: false
34915
- };
34987
+ logger.error(`Unsupported assets movement: ${params.from} to ${params.to}`);
34988
+ return this.createTransactionResult([], false, params, "NONE");
34916
34989
  } catch (err) {
34917
34990
  logger.error(`error moving assets: ${err}`);
34918
- return {
34919
- calls: [],
34920
- status: false
34921
- };
34991
+ return this.createTransactionResult([], false, params, "NONE");
34922
34992
  }
34923
34993
  }
34924
34994
  async handleDeposit() {
34925
34995
  try {
34926
- const vesuAdapter = await this.getVesuAdapter();
34927
- const extendedAdapter = await this.getExtendedAdapter();
34928
- const avnuAdapter = await this.getAvnuAdapter();
34929
- if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client || !avnuAdapter) {
34930
- logger.error(
34931
- "vesu or extended adapter not found",
34932
- vesuAdapter,
34933
- extendedAdapter
34934
- );
34935
- return {
34936
- extendedAmountInBTC: new Web3Number(0, 0),
34937
- calls: []
34938
- };
34939
- }
34940
- const extendedLeverage = calculateExtendedLevergae();
34941
- const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "open" /* OPEN */);
34942
- if (!isPriceDifferenceBetweenAvnuAndExtended) {
34943
- logger.error("price difference between avnu and extended doesn't fit the range");
34944
- return {
34945
- extendedAmountInBTC: new Web3Number(0, 0),
34946
- calls: []
34947
- };
34948
- }
34949
- const position = await extendedAdapter.getAllOpenPositions();
34950
- if (!position) {
34951
- logger.error("error getting extended position", position);
34952
- return {
34953
- extendedAmountInBTC: new Web3Number(0, 0),
34954
- calls: []
34955
- };
34956
- }
34957
- const extendedPositionValue = position.length > 0 ? parseFloat(position[0].value) : 0;
34958
- const BUFFER_AMOUNT_IN_AVAILABLE_FOR_TRADE = BUFFER_USDC_IN_WITHDRAWAL;
34959
- const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
34960
- if (!extendedHoldings) {
34961
- logger.error(`error getting extended holdings: ${extendedHoldings}`);
34962
- return {
34963
- extendedAmountInBTC: new Web3Number(0, 0),
34964
- calls: []
34965
- };
34966
- }
34967
- const extendedHoldingAmount = new Web3Number(
34968
- extendedHoldings.availableForWithdrawal,
34969
- USDC_TOKEN_DECIMALS
34970
- );
34971
- const {
34972
- collateralTokenAmount
34973
- } = await vesuAdapter.vesuAdapter.getAssetPrices();
34974
- const { collateralPrice } = await this.getAssetPrices();
34975
- const { vesuAmountInBTC, extendedAmountInBTC } = calculateVesUPositionSizeGivenExtended(
34976
- extendedPositionValue,
34977
- extendedHoldingAmount.minus(BUFFER_AMOUNT_IN_AVAILABLE_FOR_TRADE),
34978
- collateralTokenAmount,
34979
- collateralPrice.price
34980
- );
34981
- logger.info(`vesuAmountInBTC ${vesuAmountInBTC}, extendedAmountInBTC ${extendedAmountInBTC}`);
34982
- let calls = [];
34983
- if (vesuAmountInBTC.greaterThan(MINIMUM_EXTENDED_POSITION_SIZE)) {
34984
- const proofsInfo = vesuAdapter.getProofs(true, this.getMerkleTree());
34985
- const proofGroups = proofsInfo.proofs;
34986
- const call = this.getManageCall(
34987
- proofGroups,
34988
- await proofsInfo.callConstructor({
34989
- amount: vesuAmountInBTC
34990
- })
34991
- );
34992
- const { amount: wbtcAmountInVaultAllocator } = await this.getUnusedBalanceWBTC();
34993
- if (wbtcAmountInVaultAllocator.lessThan(vesuAmountInBTC)) {
34994
- const swapProofsInfo = avnuAdapter.getProofs(true, this.getMerkleTree());
34995
- const swapProofGroups = swapProofsInfo.proofs;
34996
- const swapCall = this.getManageCall(
34997
- swapProofGroups,
34998
- await swapProofsInfo.callConstructor({
34999
- amount: vesuAmountInBTC
35000
- })
35001
- );
35002
- calls.push(swapCall);
35003
- }
35004
- calls.push(call);
35005
- }
35006
- const shortPosition = extendedAmountInBTC.multipliedBy(3).abs().greaterThan(MINIMUM_EXTENDED_POSITION_SIZE) ? await extendedAdapter.createOrder(
35007
- extendedLeverage.toString(),
35008
- extendedAmountInBTC.toNumber(),
35009
- "SELL" /* SELL */
35010
- ) : null;
35011
- if (!shortPosition && extendedAmountInBTC.multipliedBy(3).abs().greaterThan(MINIMUM_EXTENDED_POSITION_SIZE)) {
35012
- logger.error(`error creating short position thus no position to be opened on vesu: ${shortPosition}`);
35013
- return {
35014
- extendedAmountInBTC: new Web3Number(0, 0),
35015
- calls: []
35016
- };
35017
- }
35018
- return {
35019
- extendedAmountInBTC,
35020
- calls
35021
- };
34996
+ return this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.VAULT.name, amount: new Web3Number(0, 0) }, "NONE");
35022
34997
  } catch (err) {
35023
34998
  logger.error(`error handling deposit: ${err}`);
35024
- return {
35025
- extendedAmountInBTC: new Web3Number(0, 0),
35026
- calls: []
35027
- };
34999
+ return this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.VAULT.name, amount: new Web3Number(0, 0) }, "NONE");
35028
35000
  }
35029
35001
  }
35030
35002
  async checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, positionType) {
@@ -35069,12 +35041,8 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
35069
35041
  const withdrawCall2 = await this.getBringLiquidityCall({
35070
35042
  amount: usdcBalanceVaultAllocator.amount
35071
35043
  });
35072
- logger.info("withdraw call", withdrawCall2);
35073
35044
  calls.push(withdrawCall2);
35074
- return {
35075
- calls,
35076
- status: true
35077
- };
35045
+ return [this.createTransactionResult(calls, true, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "WITHDRAWAL")];
35078
35046
  }
35079
35047
  const vesuAdapter = await this.getVesuAdapter();
35080
35048
  const extendedAdapter = await this.getExtendedAdapter();
@@ -35083,11 +35051,9 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
35083
35051
  logger.error(
35084
35052
  `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
35085
35053
  );
35086
- return {
35087
- calls,
35088
- status
35089
- };
35054
+ return [this.createTransactionResult(calls, status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE")];
35090
35055
  }
35056
+ let transactionResults = [];
35091
35057
  const { collateralTokenAmount } = await vesuAdapter.vesuAdapter.getAssetPrices();
35092
35058
  const {
35093
35059
  collateralPrice
@@ -35096,10 +35062,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
35096
35062
  if (!extendedPositon) {
35097
35063
  status = false;
35098
35064
  logger.error("error getting extended position", extendedPositon);
35099
- return {
35100
- calls,
35101
- status
35102
- };
35065
+ return [this.createTransactionResult(calls, status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE")];
35103
35066
  }
35104
35067
  const amountDistributionForWithdrawal = await calculateAmountDistributionForWithdrawal(
35105
35068
  usdcBalanceDifference,
@@ -35112,14 +35075,11 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
35112
35075
  logger.error(
35113
35076
  `error calculating amount distribution for withdrawal: ${amountDistributionForWithdrawal}`
35114
35077
  );
35115
- return {
35116
- calls,
35117
- status
35118
- };
35078
+ return [this.createTransactionResult(calls, status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE")];
35119
35079
  }
35120
35080
  const { vesu_amount, extended_amount } = amountDistributionForWithdrawal;
35121
35081
  if (status && vesu_amount.greaterThan(0)) {
35122
- const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
35082
+ const { calls: vesuCalls, status: vesuStatus, transactionMetadata: vesuTransactionMetadata } = await this.moveAssets(
35123
35083
  {
35124
35084
  amount: vesu_amount,
35125
35085
  from: Protocols.VESU.name,
@@ -35129,10 +35089,14 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
35129
35089
  vesuAdapter
35130
35090
  );
35131
35091
  status = vesuStatus;
35132
- calls.push(...vesuCalls);
35092
+ transactionResults.push({
35093
+ status: vesuStatus,
35094
+ calls: vesuCalls,
35095
+ transactionMetadata: vesuTransactionMetadata
35096
+ });
35133
35097
  }
35134
35098
  if (status && extended_amount.greaterThan(0)) {
35135
- const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
35099
+ const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
35136
35100
  {
35137
35101
  amount: extended_amount,
35138
35102
  from: Protocols.EXTENDED.name,
@@ -35143,30 +35107,35 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
35143
35107
  );
35144
35108
  status = extendedStatus;
35145
35109
  if (status) {
35146
- calls.push(...extendedCalls);
35110
+ transactionResults.push({
35111
+ status: extendedStatus,
35112
+ calls: extendedCalls,
35113
+ transactionMetadata: extendedTransactionMetadata
35114
+ });
35147
35115
  } else {
35148
35116
  logger.error("error moving assets to vault: extendedStatus: ${extendedStatus}");
35149
- return {
35150
- calls: [],
35151
- status
35152
- };
35117
+ return [this.createTransactionResult([], status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE")];
35153
35118
  }
35154
35119
  }
35155
35120
  const withdrawCall = await this.getBringLiquidityCall({
35156
35121
  amount
35157
35122
  });
35158
35123
  logger.info("withdraw call", withdrawCall);
35159
- calls.push(withdrawCall);
35160
- return {
35161
- calls,
35162
- status
35163
- };
35124
+ transactionResults.push({
35125
+ status,
35126
+ calls: [withdrawCall],
35127
+ transactionMetadata: {
35128
+ protocolFrom: Protocols.VAULT.name,
35129
+ protocolTo: Protocols.NONE.name,
35130
+ transactionType: "WITHDRAWAL",
35131
+ usdAmount: amount.toFixed(),
35132
+ status: "PENDING"
35133
+ }
35134
+ });
35135
+ return transactionResults;
35164
35136
  } catch (err) {
35165
35137
  logger.error(`error handling withdrawal: ${err}`);
35166
- return {
35167
- calls: [],
35168
- status: false
35169
- };
35138
+ return [this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE")];
35170
35139
  }
35171
35140
  }
35172
35141
  async getAUM() {
@@ -35213,6 +35182,36 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
35213
35182
  splits: [realAUM, estimatedAUMDelta]
35214
35183
  };
35215
35184
  }
35185
+ async processTransactionDataFromSDK(txnData) {
35186
+ try {
35187
+ const txnsToBeExecuted = txnData.filter((txn) => {
35188
+ return txn.transactionMetadata.transactionType !== "NONE" && txn.transactionMetadata.protocolFrom !== "" && txn.transactionMetadata.protocolTo !== "";
35189
+ });
35190
+ const callsToBeExecutedFinal = txnsToBeExecuted.flatMap((txn) => txn.calls);
35191
+ const txnMetadata = txnsToBeExecuted.map((txn) => txn.transactionMetadata);
35192
+ return { callsToBeExecutedFinal, txnMetadata };
35193
+ } catch (err) {
35194
+ logger.error(`error processing transaction data from SDK: ${err}`);
35195
+ return null;
35196
+ }
35197
+ }
35198
+ async processTransactionMetadata(txnMetadata, extendedIntentFulfilled) {
35199
+ try {
35200
+ const txnMetadataNew = txnMetadata.map((txn) => {
35201
+ const isExtendedProtocol = txn.protocolFrom === Protocols.EXTENDED.name || txn.protocolTo === Protocols.EXTENDED.name;
35202
+ if (isExtendedProtocol) {
35203
+ txn.status = extendedIntentFulfilled ? "COMPLETED" : "PENDING";
35204
+ } else {
35205
+ txn.status = "COMPLETED";
35206
+ }
35207
+ return txn;
35208
+ });
35209
+ return txnMetadataNew;
35210
+ } catch (err) {
35211
+ logger.error(`error processing transaction data from SDK: ${err}`);
35212
+ return null;
35213
+ }
35214
+ }
35216
35215
  };
35217
35216
  function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
35218
35217
  vaultSettings.leafAdapters = [];
@@ -39087,6 +39086,7 @@ export {
39087
39086
  AssetOperationStatus,
39088
39087
  AssetOperationType,
39089
39088
  AutoCompounderSTRK,
39089
+ AvnuAdapter,
39090
39090
  AvnuWrapper,
39091
39091
  BaseAdapter,
39092
39092
  BaseStrategy,
@@ -39162,6 +39162,7 @@ export {
39162
39162
  calculateExtendedLevergae,
39163
39163
  calculateVesUPositionSizeGivenExtended,
39164
39164
  calculateVesuLeverage,
39165
+ calculateWBTCAmountToMaintainLTV,
39165
39166
  extensionMap,
39166
39167
  getContractDetails,
39167
39168
  getFAQs,