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