@strkfarm/sdk 2.0.0-dev.2 → 2.0.0-dev.21

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.js CHANGED
@@ -43,11 +43,13 @@ __export(index_exports, {
43
43
  AssetOperationStatus: () => AssetOperationStatus,
44
44
  AssetOperationType: () => AssetOperationType,
45
45
  AutoCompounderSTRK: () => AutoCompounderSTRK,
46
+ AvnuAdapter: () => AvnuAdapter,
46
47
  AvnuWrapper: () => AvnuWrapper,
47
48
  BaseAdapter: () => BaseAdapter,
48
49
  BaseStrategy: () => BaseStrategy,
49
50
  CommonAdapter: () => CommonAdapter,
50
51
  ContractAddr: () => ContractAddr,
52
+ CycleType: () => CycleType,
51
53
  Deployer: () => deployer_default,
52
54
  ERC20: () => ERC20,
53
55
  EXTENDED_CONTRACT: () => EXTENDED_CONTRACT,
@@ -76,6 +78,7 @@ __export(index_exports, {
76
78
  PRICE_ROUTER: () => PRICE_ROUTER,
77
79
  PasswordJsonCryptoUtil: () => PasswordJsonCryptoUtil,
78
80
  PositionSide: () => PositionSide,
81
+ PositionTypeAvnuExtended: () => PositionTypeAvnuExtended,
79
82
  Pragma: () => Pragma,
80
83
  Pricer: () => Pricer,
81
84
  PricerBase: () => PricerBase,
@@ -125,6 +128,7 @@ __export(index_exports, {
125
128
  calculateExtendedLevergae: () => calculateExtendedLevergae,
126
129
  calculateVesUPositionSizeGivenExtended: () => calculateVesUPositionSizeGivenExtended,
127
130
  calculateVesuLeverage: () => calculateVesuLeverage,
131
+ calculateWBTCAmountToMaintainLTV: () => calculateWBTCAmountToMaintainLTV,
128
132
  extensionMap: () => extensionMap,
129
133
  getAPIUsingHeadlessBrowser: () => getAPIUsingHeadlessBrowser,
130
134
  getContractDetails: () => getContractDetails,
@@ -4474,20 +4478,13 @@ var EkuboQuoter = class _EkuboQuoter {
4474
4478
  async getDexPrice(baseToken, quoteToken, amount) {
4475
4479
  const lstTokenInfo = baseToken;
4476
4480
  const lstUnderlyingTokenInfo = quoteToken;
4477
- console.log("lstTokenInfo", lstTokenInfo);
4478
- console.log("lstUnderlyingTokenInfo", lstUnderlyingTokenInfo);
4479
- console.log("amount", amount);
4480
4481
  const quote = await this.getQuote(
4481
4482
  lstTokenInfo.address.address,
4482
4483
  lstUnderlyingTokenInfo.address.address,
4483
4484
  amount
4484
4485
  );
4485
- console.log("quote", quote);
4486
4486
  const outputAmount = Web3Number.fromWei(quote.total_calculated, lstUnderlyingTokenInfo.decimals);
4487
- console.log("outputAmount", outputAmount);
4488
- console.log("amount", amount);
4489
4487
  const price = outputAmount.toNumber() / amount.toNumber();
4490
- console.log("price", price);
4491
4488
  logger.verbose(`${_EkuboQuoter.name}:: LST Dex Price: ${price}`);
4492
4489
  return price;
4493
4490
  }
@@ -4506,16 +4503,12 @@ var EkuboQuoter = class _EkuboQuoter {
4506
4503
  // debt collateral
4507
4504
  async getSwapLimitAmount(fromToken, toToken, amount, max_slippage = 2e-3) {
4508
4505
  const isExactAmountIn = amount.greaterThanOrEqualTo(0);
4509
- console.log("isExactAmountIn", isExactAmountIn);
4510
4506
  logger.verbose(`${_EkuboQuoter.name}::getSwapLimitAmount isExactAmountIn: ${isExactAmountIn}, fromToken: ${fromToken.symbol}, toToken: ${toToken.symbol}, amount: ${amount}`);
4511
4507
  const isYieldToken = this.tokenMarketData.isAPYSupported(toToken);
4512
4508
  console.log("isYieldToken", isYieldToken);
4513
4509
  const baseToken = isExactAmountIn ? toToken : fromToken;
4514
4510
  const quoteToken = isExactAmountIn ? fromToken : toToken;
4515
- console.log("baseToken", baseToken);
4516
- console.log("quoteToken", quoteToken);
4517
4511
  const dexPrice = await this.getDexPrice(baseToken, quoteToken, amount);
4518
- console.log("dexPrice", dexPrice);
4519
4512
  const trueExchangeRate = isYieldToken ? await this.tokenMarketData.getTruePrice(baseToken) : dexPrice;
4520
4513
  console.log("trueExchangeRate", trueExchangeRate);
4521
4514
  if (isExactAmountIn) {
@@ -4546,7 +4539,6 @@ var EkuboQuoter = class _EkuboQuoter {
4546
4539
  return quote.splits.map((split) => {
4547
4540
  const isNegativeAmount = BigInt(split.amount_specified) <= 0n;
4548
4541
  const token = isNegativeAmount ? toTokenInfo : fromTokenInfo;
4549
- console.log("token for withdrawal", token, isNegativeAmount);
4550
4542
  return {
4551
4543
  route: split.route.map((_route) => ({
4552
4544
  pool_key: {
@@ -27219,11 +27211,6 @@ var VesuAdapter = class _VesuAdapter extends CacheClass {
27219
27211
  if (!this.pricer) {
27220
27212
  throw new Error("Pricer is not initialized");
27221
27213
  }
27222
- const CACHE_KEY = `positions_${blockNumber}_${this.config.poolId.shortString()}_${this.config.collateral.symbol}_${this.config.debt.symbol}`;
27223
- const cacheData = this.getCache(CACHE_KEY);
27224
- if (cacheData) {
27225
- return cacheData;
27226
- }
27227
27214
  const { contract, isV2 } = this.getVesuSingletonContract(config, this.config.poolId);
27228
27215
  const output = await contract.call(isV2 ? "position" : "position_unsafe", [
27229
27216
  ...isV2 ? [] : [this.config.poolId.address],
@@ -27249,7 +27236,6 @@ var VesuAdapter = class _VesuAdapter extends CacheClass {
27249
27236
  usdValue: debtAmount.multipliedBy(token2Price.price).toNumber(),
27250
27237
  remarks: "Debt"
27251
27238
  }];
27252
- this.setCache(CACHE_KEY, value, 6e4);
27253
27239
  return value.map((v) => ({ ...v, protocol: Protocols.VESU }));
27254
27240
  }
27255
27241
  async getCollateralization(config, blockNumber = "latest") {
@@ -28172,15 +28158,14 @@ var MAX_PRICE_DROP_PERCENTAGE = Number(process.env.MAX_PRICE_DROP_PERCENTAGE ??
28172
28158
  var MAX_LTV_BTC_USDC = 0.8428;
28173
28159
  var MAX_LIQUIDATION_RATIO = 0.86;
28174
28160
  var VAULT_ID_EXTENDED = process.env.VAULT_ID_EXTENDED ?? 220774;
28175
- var WALLET_ADDRESS = process.env.WALLET_ADDRESS ?? "0x07b84bb6E87588BdAde0bfe6173A615b3C220F9C3803456aE183C50EA1d15Ba1";
28176
- var TESTNET_WALLET_ADDRESS = process.env.TESTNET_WALLET_ADDRESS ?? "0x07b84bb6E87588BdAde0bfe6173A615b3C220F9C3803456aE183C50EA1d15Ba1";
28177
- var TEST_WALLET_2 = process.env.TEST_WALLET_2 ?? "0x004C1bdC61DAc7947F3C93d0163d660012E2aB0521567f7155fcf502848791A7";
28161
+ var WALLET_ADDRESS = process.env.WALLET_ADDRESS ?? "0x007E24592287427aaE9d291770B17d582E8A45f3aE54228F998793Ec769B7D13";
28178
28162
  var STRK_API_TEST_RPC = process.env.STRK_API_TEST_RPC ?? "https://sepolia.starknet.a5a.ch";
28179
28163
  var STRK_API_RPC = process.env.STRK_API_RPC ?? "https://mainnet.starknet.a5a.ch";
28180
28164
  var MAX_RETRIES = Number(process.env.MAX_RETRIES ?? 3);
28181
28165
  var MAX_DELAY = Number(process.env.MAX_DELAY ?? 100);
28182
28166
  var EXTEND_MARKET_NAME = "BTC-USD";
28183
- var LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ?? 10);
28167
+ var LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ?? 0.05);
28168
+ var LIMIT_BALANCE_VALUE = 10;
28184
28169
  var REBALANCER_INTERVAL = Number(process.env.REBALANCER_INTERVAL ?? 18e4);
28185
28170
  var WITHDRAWAL_INTERVAL = Number(process.env.WITHDRAWAL_INTERVAL ?? 18e6);
28186
28171
  var INVESTING_INTERVAL = Number(process.env.INVESTING_INTERVAL ?? 18e4);
@@ -28198,8 +28183,6 @@ var PRICE_MAX_SLIPPAGE_EKUBO = Number(process.env.PRICE_MAX_SLIPPAGE_EKUBO ?? 5e
28198
28183
  var MINIMUM_DEBT_AMOUNT_VESU_FOR_REBALANCING = Number(process.env.MINIMUM_DEBT_AMOUNT_VESU_FOR_REBALANCING ?? 1);
28199
28184
  var MINIMUM_EXTENDED_POSITION_SIZE = 1e-4;
28200
28185
  var MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP = 1e-5;
28201
- var MAX_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED = 700;
28202
- var MIN_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED = -100;
28203
28186
 
28204
28187
  // src/strategies/vesu-extended-strategy/utils/helper.ts
28205
28188
  var returnFormattedAmount = (amount, toTokenDecimals) => {
@@ -28219,8 +28202,7 @@ var calculateAmountDistribution = async (amount, client, marketName, collateralP
28219
28202
  vesu_leverage: 0
28220
28203
  };
28221
28204
  }
28222
- const extendedBTCExposure = extendedPosition.length > 0 ? new Web3Number(extendedPosition[0].size, WBTC_TOKEN_DECIMALS) : new Web3Number(0, WBTC_TOKEN_DECIMALS);
28223
- const extendedExposureUSD = extendedBTCExposure.multipliedBy(collateralPrice);
28205
+ const extendedExposureUSD = extendedPosition.length > 0 ? new Web3Number(extendedPosition[0].value, WBTC_TOKEN_DECIMALS) : new Web3Number(0, WBTC_TOKEN_DECIMALS);
28224
28206
  const vesuBTCExposureUSD = collateralUnits.multipliedBy(collateralPrice);
28225
28207
  const numerator1 = vesu_leverage * amount + vesuBTCExposureUSD.toNumber();
28226
28208
  const numerator2 = extendedExposureUSD.toNumber();
@@ -28257,7 +28239,6 @@ var calculateAmountDistributionForWithdrawal = async (amountInUsdc, collateralPr
28257
28239
  return null;
28258
28240
  }
28259
28241
  const extendedExposureUSD = extendedPosition.length > 0 ? new Web3Number(extendedPosition[0].value, USDC_TOKEN_DECIMALS) : new Web3Number(0, USDC_TOKEN_DECIMALS);
28260
- console.log("THe collateral is", collateralPrice, collateralUnits);
28261
28242
  const vesuExposureUSD = collateralUnits.multipliedBy(collateralPrice);
28262
28243
  if (vesuExposureUSD.lessThan(0)) {
28263
28244
  return {
@@ -28314,10 +28295,10 @@ var calculateExtendedLevergae = () => {
28314
28295
  const extended_leverage_max = 1 / (MAINTENANCE_MARGIN + MAX_PRICE_DROP_PERCENTAGE);
28315
28296
  return Math.floor(extended_leverage_max);
28316
28297
  };
28317
- var calculateDebtAmount = (collateralAmount, debtAmount, debtPrice, maxLtv = MAX_LTV_BTC_USDC, addedAmount, collateralPrice, isDeposit) => {
28298
+ var calculateDebtAmount = (collateralAmount, debtAmount, debtPrice, maxLtv = MAX_LIQUIDATION_RATIO, addedAmount, collateralPrice, isDeposit) => {
28318
28299
  try {
28319
- const marginAmount = addedAmount.multipliedBy(isDeposit ? 1 : -1);
28320
- const numerator1 = collateralAmount.plus(addedAmount).multipliedBy(collateralPrice).multipliedBy(maxLtv);
28300
+ const addedCollateral = addedAmount.multipliedBy(isDeposit ? 1 : -1);
28301
+ const numerator1 = collateralAmount.plus(addedCollateral).multipliedBy(collateralPrice).multipliedBy(maxLtv);
28321
28302
  const numerator2 = debtAmount.multipliedBy(debtPrice).multipliedBy(TARGET_HF);
28322
28303
  const denominator = TARGET_HF - maxLtv;
28323
28304
  const x_debt_usd = numerator1.minus(numerator2).dividedBy(denominator);
@@ -28352,19 +28333,34 @@ var calculateAmountDepositOnExtendedWhenIncurringLosses = async (client) => {
28352
28333
  const extendedHoldings = await client.getHoldings();
28353
28334
  const extended_leverage = calculateExtendedLevergae();
28354
28335
  const latestPosition = (await client.getPositions()).data.pop();
28355
- console.log("the latest position is", latestPosition, extendedHoldings);
28356
28336
  if (!extendedHoldings || !latestPosition) {
28357
28337
  logger.error(`error getting extended position: extendedHoldings=${extendedHoldings}, latestPosition=${latestPosition}`);
28358
28338
  return null;
28359
28339
  }
28360
- const positionValueInUSD = latestPosition.value;
28340
+ const positionValueInUSD = new Web3Number(latestPosition.value, USDC_TOKEN_DECIMALS);
28361
28341
  const equity = extendedHoldings.data.equity;
28362
- const deposit = Number(positionValueInUSD) / extended_leverage - Number(equity);
28363
- return new Web3Number(Math.floor(deposit / 0.2) * 0.2, USDC_TOKEN_DECIMALS);
28342
+ const deposit = positionValueInUSD.dividedBy(extended_leverage).minus(equity).toFixed(2);
28343
+ return new Web3Number(deposit, USDC_TOKEN_DECIMALS);
28364
28344
  } catch (err) {
28345
+ logger.error(`error calculating amount deposit on extended when incurring losses: ${err}`);
28365
28346
  return null;
28366
28347
  }
28367
28348
  };
28349
+ var calculateWBTCAmountToMaintainLTV = (collateralAmount, debtAmount, debtPrice, maxLtv = MAX_LIQUIDATION_RATIO, collateralPrice, targetHF = TARGET_HF) => {
28350
+ try {
28351
+ const numerator1 = collateralAmount.multipliedBy(collateralPrice).multipliedBy(maxLtv);
28352
+ const numerator2 = debtAmount.multipliedBy(debtPrice).multipliedBy(targetHF);
28353
+ const denominator = maxLtv;
28354
+ const collateralAmountToMaintainLTV = numerator2.minus(numerator1).dividedBy(denominator);
28355
+ let deltaCollateralAmountUnits = new Web3Number(
28356
+ collateralAmountToMaintainLTV.dividedBy(collateralPrice).toFixed(WBTC_TOKEN_DECIMALS),
28357
+ WBTC_TOKEN_DECIMALS
28358
+ );
28359
+ return { deltaCollateralAmountUnits };
28360
+ } catch (err) {
28361
+ return { deltaCollateralAmountUnits: null };
28362
+ }
28363
+ };
28368
28364
  var calculateExposureDelta = (exposure_extended, exposure_vesu) => {
28369
28365
  const exposure_delta = new Web3Number(exposure_extended - exposure_vesu, 2);
28370
28366
  return exposure_delta.absoluteValue().toNumber();
@@ -28439,21 +28435,36 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28439
28435
  vaultAllocator: config.vaultAllocator,
28440
28436
  id: ""
28441
28437
  });
28442
- this.tokenMarketData = new TokenMarketData(this.config.pricer, this.config.networkConfig);
28438
+ this.minimumVesuMovementAmount = config.minimumVesuMovementAmount ?? 5;
28439
+ this.tokenMarketData = new TokenMarketData(
28440
+ this.config.pricer,
28441
+ this.config.networkConfig
28442
+ );
28443
28443
  }
28444
28444
  async getAPY(supportedPosition) {
28445
28445
  const CACHE_KEY = `apy_${this.config.poolId.address}_${supportedPosition.asset.symbol}`;
28446
28446
  const cacheData = this.getCache(CACHE_KEY);
28447
- console.log(`${_VesuMultiplyAdapter.name}::getAPY cacheData: ${JSON.stringify(cacheData)}`, this.vesuAdapter.config.poolId.shortString(), this.vesuAdapter.config.collateral.symbol, this.vesuAdapter.config.debt.symbol);
28447
+ console.log(
28448
+ `${_VesuMultiplyAdapter.name}::getAPY cacheData: ${JSON.stringify(
28449
+ cacheData
28450
+ )}`,
28451
+ this.vesuAdapter.config.poolId.shortString(),
28452
+ this.vesuAdapter.config.collateral.symbol,
28453
+ this.vesuAdapter.config.debt.symbol
28454
+ );
28448
28455
  if (cacheData) {
28449
28456
  return cacheData;
28450
28457
  }
28451
28458
  try {
28452
28459
  const allVesuPools = await VesuAdapter.getVesuPools();
28453
28460
  const asset = supportedPosition.asset;
28454
- const pool = allVesuPools.pools.find((p) => this.vesuAdapter.config.poolId.eqString(import_starknet21.num.getHexString(p.id)));
28461
+ const pool = allVesuPools.pools.find(
28462
+ (p) => this.vesuAdapter.config.poolId.eqString(import_starknet21.num.getHexString(p.id))
28463
+ );
28455
28464
  if (!pool) {
28456
- logger.warn(`VesuMultiplyAdapter: Pool not found for token ${asset.symbol}`);
28465
+ logger.warn(
28466
+ `VesuMultiplyAdapter: Pool not found for token ${asset.symbol}`
28467
+ );
28457
28468
  return {
28458
28469
  apy: 0,
28459
28470
  type: "base" /* BASE */
@@ -28463,7 +28474,9 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28463
28474
  (a) => a.symbol.toLowerCase() === asset.symbol.toLowerCase()
28464
28475
  )?.stats;
28465
28476
  if (!assetStats) {
28466
- logger.warn(`VesuMultiplyAdapter: Asset stats not found for token ${asset.symbol}`);
28477
+ logger.warn(
28478
+ `VesuMultiplyAdapter: Asset stats not found for token ${asset.symbol}`
28479
+ );
28467
28480
  return {
28468
28481
  apy: 0,
28469
28482
  type: "base" /* BASE */
@@ -28474,7 +28487,9 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28474
28487
  apy = Number(assetStats.borrowApr?.value || 0) / 1e18;
28475
28488
  } else {
28476
28489
  const isAssetBTC = asset.symbol.toLowerCase().includes("btc");
28477
- const baseAPY = Number(isAssetBTC ? assetStats.btcFiSupplyApr?.value + assetStats.supplyApy?.value : assetStats.supplyApy?.value || 0) / 1e18;
28490
+ const baseAPY = Number(
28491
+ isAssetBTC ? assetStats.btcFiSupplyApr?.value + assetStats.supplyApy?.value : assetStats.supplyApy?.value || 0
28492
+ ) / 1e18;
28478
28493
  const rewardAPY = Number(assetStats.defiSpringSupplyApr?.value || "0") / 1e18;
28479
28494
  const isSupported = this.tokenMarketData.isAPYSupported(asset);
28480
28495
  apy = baseAPY + rewardAPY;
@@ -28490,7 +28505,10 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28490
28505
  this.setCache(CACHE_KEY, result, 3e5);
28491
28506
  return result;
28492
28507
  } catch (error) {
28493
- logger.error(`VesuMultiplyAdapter: Error getting APY for ${supportedPosition.asset.symbol}:`, error);
28508
+ logger.error(
28509
+ `VesuMultiplyAdapter: Error getting APY for ${supportedPosition.asset.symbol}:`,
28510
+ error
28511
+ );
28494
28512
  throw error;
28495
28513
  }
28496
28514
  }
@@ -28503,12 +28521,16 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28503
28521
  try {
28504
28522
  this.vesuAdapter.networkConfig = this.config.networkConfig;
28505
28523
  this.vesuAdapter.pricer = this.config.pricer;
28506
- const positions = await this.vesuAdapter.getPositions(this.config.networkConfig);
28524
+ const positions = await this.vesuAdapter.getPositions(
28525
+ this.config.networkConfig
28526
+ );
28507
28527
  let position = positions.find(
28508
28528
  (p) => p.token.address.eq(supportedPosition.asset.address)
28509
28529
  );
28510
28530
  if (!position) {
28511
- logger.warn(`VesuMultiplyAdapter: Position not found for token ${supportedPosition.asset.symbol}`);
28531
+ logger.warn(
28532
+ `VesuMultiplyAdapter: Position not found for token ${supportedPosition.asset.symbol}`
28533
+ );
28512
28534
  return {
28513
28535
  amount: new Web3Number("0", supportedPosition.asset.decimals),
28514
28536
  remarks: "Position not found"
@@ -28521,12 +28543,18 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28521
28543
  this.setCache(CACHE_KEY, position, 6e4);
28522
28544
  return position;
28523
28545
  } catch (error) {
28524
- logger.error(`VesuMultiplyAdapter: Error getting position for ${supportedPosition.asset.symbol}:`, error);
28546
+ logger.error(
28547
+ `VesuMultiplyAdapter: Error getting position for ${supportedPosition.asset.symbol}:`,
28548
+ error
28549
+ );
28525
28550
  throw error;
28526
28551
  }
28527
28552
  }
28528
28553
  async maxBorrowableAPY() {
28529
- const collateralAPY = await this.getAPY({ asset: this.config.collateral, isDebt: false });
28554
+ const collateralAPY = await this.getAPY({
28555
+ asset: this.config.collateral,
28556
+ isDebt: false
28557
+ });
28530
28558
  const apy = collateralAPY.apy * 0.8;
28531
28559
  return apy;
28532
28560
  }
@@ -28536,9 +28564,15 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28536
28564
  try {
28537
28565
  this.vesuAdapter.networkConfig = this.config.networkConfig;
28538
28566
  this.vesuAdapter.pricer = this.config.pricer;
28539
- const positions = await this.vesuAdapter.getPositions(this.config.networkConfig);
28540
- const collateralPosition = positions.find((p) => p.token.address.eq(collateral.address));
28541
- const debtPosition = positions.find((p) => p.token.address.eq(debt.address));
28567
+ const positions = await this.vesuAdapter.getPositions(
28568
+ this.config.networkConfig
28569
+ );
28570
+ const collateralPosition = positions.find(
28571
+ (p) => p.token.address.eq(collateral.address)
28572
+ );
28573
+ const debtPosition = positions.find(
28574
+ (p) => p.token.address.eq(debt.address)
28575
+ );
28542
28576
  if (!collateralPosition || !debtPosition) {
28543
28577
  throw new Error("Could not find current positions");
28544
28578
  }
@@ -28548,13 +28582,23 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28548
28582
  debt,
28549
28583
  maxBorrowableAPY
28550
28584
  );
28551
- logger.verbose(`VesuMultiplyAdapter: Max borrowable: ${maxBorrowable.toNumber()}`);
28552
- const debtCap = await this.vesuAdapter.getDebtCap(this.config.networkConfig);
28585
+ logger.verbose(
28586
+ `VesuMultiplyAdapter: Max borrowable: ${maxBorrowable.toNumber()}`
28587
+ );
28588
+ const debtCap = await this.vesuAdapter.getDebtCap(
28589
+ this.config.networkConfig
28590
+ );
28553
28591
  logger.verbose(`VesuMultiplyAdapter: Debt cap: ${debtCap.toNumber()}`);
28554
28592
  const actualMaxBorrowable = maxBorrowable.minimum(debtCap);
28555
- logger.verbose(`VesuMultiplyAdapter: Actual max borrowable: ${actualMaxBorrowable.toNumber()}`);
28556
- const maxLTV = await this.vesuAdapter.getLTVConfig(this.config.networkConfig);
28557
- const collateralPrice = await this.config.pricer.getPrice(collateral.symbol);
28593
+ logger.verbose(
28594
+ `VesuMultiplyAdapter: Actual max borrowable: ${actualMaxBorrowable.toNumber()}`
28595
+ );
28596
+ const maxLTV = await this.vesuAdapter.getLTVConfig(
28597
+ this.config.networkConfig
28598
+ );
28599
+ const collateralPrice = await this.config.pricer.getPrice(
28600
+ collateral.symbol
28601
+ );
28558
28602
  if (collateralPrice.price === 0) {
28559
28603
  throw new Error("Collateral price is 0");
28560
28604
  }
@@ -28572,14 +28616,25 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28572
28616
  );
28573
28617
  const maxDepositAmount = amount ? amount.minimum(maxCollateralFromDebt) : maxCollateralFromDebt;
28574
28618
  const usdValue = await this.getUSDValue(collateral, maxDepositAmount);
28575
- logger.verbose(`VesuMultiplyAdapter: Max deposit::USD value: ${usdValue}, amount: ${maxDepositAmount.toNumber()}`);
28576
- const apys = await Promise.all([this.getAPY({ asset: collateral, isDebt: false }), this.getAPY({ asset: debt, isDebt: true })]);
28577
- logger.verbose(`VesuMultiplyAdapter: Apys: ${apys[0].apy}, ${apys[1].apy}`);
28619
+ logger.verbose(
28620
+ `VesuMultiplyAdapter: Max deposit::USD value: ${usdValue}, amount: ${maxDepositAmount.toNumber()}`
28621
+ );
28622
+ const apys = await Promise.all([
28623
+ this.getAPY({ asset: collateral, isDebt: false }),
28624
+ this.getAPY({ asset: debt, isDebt: true })
28625
+ ]);
28626
+ logger.verbose(
28627
+ `VesuMultiplyAdapter: Apys: ${apys[0].apy}, ${apys[1].apy}`
28628
+ );
28578
28629
  const borrowAmountUSD = actualMaxBorrowable.multipliedBy(debtPrice.price);
28579
- logger.verbose(`VesuMultiplyAdapter: Borrow amount: ${actualMaxBorrowable.toNumber()}, borrow amount USD: ${borrowAmountUSD.toNumber()}`);
28630
+ logger.verbose(
28631
+ `VesuMultiplyAdapter: Borrow amount: ${actualMaxBorrowable.toNumber()}, borrow amount USD: ${borrowAmountUSD.toNumber()}`
28632
+ );
28580
28633
  const netCollateralUSD = usdValue + borrowAmountUSD.toNumber();
28581
28634
  const netAPY = (apys[0].apy * netCollateralUSD + apys[1].apy * borrowAmountUSD.toNumber()) / usdValue;
28582
- logger.verbose(`VesuMultiplyAdapter: Max deposit amount: ${maxDepositAmount.toNumber()}, netAPY: ${netAPY}`);
28635
+ logger.verbose(
28636
+ `VesuMultiplyAdapter: Max deposit amount: ${maxDepositAmount.toNumber()}, netAPY: ${netAPY}`
28637
+ );
28583
28638
  return {
28584
28639
  tokenInfo: collateral,
28585
28640
  amount: maxDepositAmount,
@@ -28592,7 +28647,10 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28592
28647
  protocol: this.protocol
28593
28648
  };
28594
28649
  } catch (error) {
28595
- logger.error(`VesuMultiplyAdapter: Error calculating max deposit:`, error);
28650
+ logger.error(
28651
+ `VesuMultiplyAdapter: Error calculating max deposit:`,
28652
+ error
28653
+ );
28596
28654
  throw error;
28597
28655
  }
28598
28656
  }
@@ -28602,9 +28660,15 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28602
28660
  try {
28603
28661
  this.vesuAdapter.networkConfig = this.config.networkConfig;
28604
28662
  this.vesuAdapter.pricer = this.config.pricer;
28605
- const positions = await this.vesuAdapter.getPositions(this.config.networkConfig);
28606
- const collateralPosition = positions.find((p) => p.token.address.eq(collateral.address));
28607
- const debtPosition = positions.find((p) => p.token.address.eq(this.config.debt.address));
28663
+ const positions = await this.vesuAdapter.getPositions(
28664
+ this.config.networkConfig
28665
+ );
28666
+ const collateralPosition = positions.find(
28667
+ (p) => p.token.address.eq(collateral.address)
28668
+ );
28669
+ const debtPosition = positions.find(
28670
+ (p) => p.token.address.eq(this.config.debt.address)
28671
+ );
28608
28672
  if (!collateralPosition || !debtPosition) {
28609
28673
  throw new Error("Could not find current positions");
28610
28674
  }
@@ -28614,11 +28678,20 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28614
28678
  const result = maxWithdrawable.greaterThan(0) ? maxWithdrawable : new Web3Number("0", collateral.decimals);
28615
28679
  const usdValue = await this.getUSDValue(collateral, result);
28616
28680
  const debtUSD = debtPosition.usdValue;
28617
- logger.verbose(`VesuMultiplyAdapter: Debt USD: ${debtUSD}, collateral USD: ${usdValue}`);
28618
- const apys = await Promise.all([this.getAPY({ asset: collateral, isDebt: false }), this.getAPY({ asset: debt, isDebt: true })]);
28619
- logger.verbose(`VesuMultiplyAdapter: Apys: ${apys[0].apy}, ${apys[1].apy}`);
28681
+ logger.verbose(
28682
+ `VesuMultiplyAdapter: Debt USD: ${debtUSD}, collateral USD: ${usdValue}`
28683
+ );
28684
+ const apys = await Promise.all([
28685
+ this.getAPY({ asset: collateral, isDebt: false }),
28686
+ this.getAPY({ asset: debt, isDebt: true })
28687
+ ]);
28688
+ logger.verbose(
28689
+ `VesuMultiplyAdapter: Apys: ${apys[0].apy}, ${apys[1].apy}`
28690
+ );
28620
28691
  const netAPY = usdValue - debtUSD > 0 ? (apys[0].apy * usdValue + apys[1].apy * debtUSD) / (usdValue - debtUSD) : 0;
28621
- logger.verbose(`VesuMultiplyAdapter: Max withdraw amount: ${result.toNumber()}, netAPY: ${netAPY}`);
28692
+ logger.verbose(
28693
+ `VesuMultiplyAdapter: Max withdraw amount: ${result.toNumber()}, netAPY: ${netAPY}`
28694
+ );
28622
28695
  return {
28623
28696
  tokenInfo: collateral,
28624
28697
  amount: result,
@@ -28631,14 +28704,19 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28631
28704
  protocol: this.protocol
28632
28705
  };
28633
28706
  } catch (error) {
28634
- logger.error(`VesuMultiplyAdapter: Error calculating max withdraw:`, error);
28707
+ logger.error(
28708
+ `VesuMultiplyAdapter: Error calculating max withdraw:`,
28709
+ error
28710
+ );
28635
28711
  throw error;
28636
28712
  }
28637
28713
  }
28638
28714
  _getDepositLeaf() {
28639
28715
  const collateral = this.config.collateral;
28640
28716
  const debt = this.config.debt;
28641
- const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(this.config.poolId);
28717
+ const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
28718
+ this.config.poolId
28719
+ );
28642
28720
  const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
28643
28721
  return [
28644
28722
  // Approval step for collateral
@@ -28702,7 +28780,9 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28702
28780
  ];
28703
28781
  }
28704
28782
  _getWithdrawLeaf() {
28705
- const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(this.config.poolId);
28783
+ const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
28784
+ this.config.poolId
28785
+ );
28706
28786
  const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
28707
28787
  const collateral = this.config.collateral;
28708
28788
  const debt = this.config.debt;
@@ -28759,33 +28839,51 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28759
28839
  const leafConfigs = this._getDepositLeaf();
28760
28840
  const leaves = leafConfigs.map((config) => {
28761
28841
  const { target, method, packedArguments, sanitizer, id } = config;
28762
- const leaf = this.constructSimpleLeafData({
28763
- id,
28764
- target,
28765
- method,
28766
- packedArguments
28767
- }, sanitizer);
28842
+ const leaf = this.constructSimpleLeafData(
28843
+ {
28844
+ id,
28845
+ target,
28846
+ method,
28847
+ packedArguments
28848
+ },
28849
+ sanitizer
28850
+ );
28768
28851
  return leaf;
28769
28852
  });
28770
- return { leaves, callConstructor: this.getDepositCall.bind(this) };
28853
+ return {
28854
+ leaves,
28855
+ callConstructor: this.getDepositCall.bind(
28856
+ this
28857
+ )
28858
+ };
28771
28859
  }
28772
28860
  getWithdrawAdapter() {
28773
28861
  const leafConfigs = this._getWithdrawLeaf();
28774
28862
  const leaves = leafConfigs.map((config) => {
28775
28863
  const { target, method, packedArguments, sanitizer, id } = config;
28776
- const leaf = this.constructSimpleLeafData({
28777
- id,
28778
- target,
28779
- method,
28780
- packedArguments
28781
- }, sanitizer);
28864
+ const leaf = this.constructSimpleLeafData(
28865
+ {
28866
+ id,
28867
+ target,
28868
+ method,
28869
+ packedArguments
28870
+ },
28871
+ sanitizer
28872
+ );
28782
28873
  return leaf;
28783
28874
  });
28784
- return { leaves, callConstructor: this.getWithdrawCall.bind(this) };
28875
+ return {
28876
+ leaves,
28877
+ callConstructor: this.getWithdrawCall.bind(
28878
+ this
28879
+ )
28880
+ };
28785
28881
  }
28786
28882
  async getDepositCall(params) {
28787
28883
  const collateral = this.config.collateral;
28788
- const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(this.config.poolId);
28884
+ const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
28885
+ this.config.poolId
28886
+ );
28789
28887
  const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
28790
28888
  const uint256MarginAmount = import_starknet21.uint256.bnToUint256(params.amount.toWei());
28791
28889
  return [
@@ -28857,7 +28955,9 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28857
28955
  ];
28858
28956
  }
28859
28957
  async getWithdrawCall(params) {
28860
- const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(this.config.poolId);
28958
+ const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
28959
+ this.config.poolId
28960
+ );
28861
28961
  const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
28862
28962
  return [
28863
28963
  // Switch delegation on
@@ -28912,7 +29012,11 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28912
29012
  ];
28913
29013
  }
28914
29014
  async getMultiplyCallCalldata(params, isDeposit) {
28915
- logger.verbose(`${_VesuMultiplyAdapter.name}::getMultiplyCallCalldata params: ${JSON.stringify(params)}, isDeposit: ${isDeposit}, collateral: ${this.config.collateral.symbol}, debt: ${this.config.debt.symbol}`);
29015
+ logger.verbose(
29016
+ `${_VesuMultiplyAdapter.name}::getMultiplyCallCalldata params: ${JSON.stringify(
29017
+ params
29018
+ )}, isDeposit: ${isDeposit}, collateral: ${this.config.collateral.symbol}, debt: ${this.config.debt.symbol}`
29019
+ );
28916
29020
  const { isV2 } = getVesuSingletonAddress(this.config.poolId);
28917
29021
  const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
28918
29022
  const multiplyContract = new import_starknet21.Contract({
@@ -28922,42 +29026,83 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28922
29026
  });
28923
29027
  let leverSwap = [];
28924
29028
  let leverSwapLimitAmount = Web3Number.fromWei(0, this.config.debt.decimals);
28925
- const existingPositions = await this.vesuAdapter.getPositions(this.config.networkConfig);
28926
- const collateralisation = await this.vesuAdapter.getCollateralization(this.config.networkConfig);
29029
+ const existingPositions = await this.vesuAdapter.getPositions(
29030
+ this.config.networkConfig
29031
+ );
29032
+ const collateralisation = await this.vesuAdapter.getCollateralization(
29033
+ this.config.networkConfig
29034
+ );
28927
29035
  const existingCollateralInfo = existingPositions[0];
28928
29036
  const existingDebtInfo = existingPositions[1];
28929
29037
  const isDexPriceRequired = existingDebtInfo.token.symbol !== "USDC";
28930
- logger.debug(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall existingCollateralInfo: ${JSON.stringify(existingCollateralInfo)},
28931
- existingDebtInfo: ${JSON.stringify(existingDebtInfo)}, collateralisation: ${JSON.stringify(collateralisation)}`);
29038
+ logger.debug(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall existingCollateralInfo: ${JSON.stringify(
29039
+ existingCollateralInfo
29040
+ )},
29041
+ existingDebtInfo: ${JSON.stringify(
29042
+ existingDebtInfo
29043
+ )}, collateralisation: ${JSON.stringify(collateralisation)}`);
28932
29044
  const collateralPrice = collateralisation[0].usdValue > 0 ? collateralisation[0].usdValue / existingCollateralInfo.amount.toNumber() : (await this.config.pricer.getPrice(this.config.collateral.symbol)).price;
28933
29045
  const debtPrice = collateralisation[1].usdValue > 0 ? collateralisation[1].usdValue / existingDebtInfo.amount.toNumber() : (await this.config.pricer.getPrice(this.config.debt.symbol)).price;
28934
- logger.debug(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall collateralPrice: ${collateralPrice}, debtPrice: ${debtPrice}`);
28935
- const legLTV = await this.vesuAdapter.getLTVConfig(this.config.networkConfig);
28936
- const ekuboQuoter = new EkuboQuoter(this.config.networkConfig, this.config.pricer);
28937
- const dexPrice = isDexPriceRequired ? await ekuboQuoter.getDexPrice(this.config.collateral, this.config.debt, this.config.quoteAmountToFetchPrice) : 1;
28938
- logger.verbose(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall dexPrice: ${dexPrice}, ltv: ${legLTV}`);
29046
+ logger.debug(
29047
+ `${_VesuMultiplyAdapter.name}::getVesuMultiplyCall collateralPrice: ${collateralPrice}, debtPrice: ${debtPrice}`
29048
+ );
29049
+ const legLTV = await this.vesuAdapter.getLTVConfig(
29050
+ this.config.networkConfig
29051
+ );
29052
+ const ekuboQuoter = new EkuboQuoter(
29053
+ this.config.networkConfig,
29054
+ this.config.pricer
29055
+ );
29056
+ const dexPrice = isDexPriceRequired ? await ekuboQuoter.getDexPrice(
29057
+ this.config.collateral,
29058
+ this.config.debt,
29059
+ this.config.quoteAmountToFetchPrice
29060
+ ) : 1;
29061
+ logger.verbose(
29062
+ `${_VesuMultiplyAdapter.name}::getVesuMultiplyCall dexPrice: ${dexPrice}, ltv: ${legLTV}`
29063
+ );
28939
29064
  const addedCollateral = params.amount.multipliedBy(isDeposit ? 1 : -1);
28940
- logger.verbose(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall addedCollateral: ${addedCollateral}`);
29065
+ logger.verbose(
29066
+ `${_VesuMultiplyAdapter.name}::getVesuMultiplyCall addedCollateral: ${addedCollateral}`
29067
+ );
28941
29068
  const numeratorPart1 = existingCollateralInfo.amount.plus(addedCollateral).multipliedBy(collateralPrice).multipliedBy(legLTV);
28942
- logger.verbose(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart1: ${numeratorPart1}`);
29069
+ logger.verbose(
29070
+ `${_VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart1: ${numeratorPart1}`
29071
+ );
28943
29072
  const numeratorPart2 = existingDebtInfo.amount.multipliedBy(debtPrice).multipliedBy(this.config.targetHealthFactor);
28944
- logger.verbose(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart2: ${numeratorPart2}`);
29073
+ logger.verbose(
29074
+ `${_VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart2: ${numeratorPart2}`
29075
+ );
28945
29076
  const denominatorPart = this.config.targetHealthFactor - legLTV / dexPrice;
28946
- logger.verbose(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall denominatorPart: ${denominatorPart}`);
29077
+ logger.verbose(
29078
+ `${_VesuMultiplyAdapter.name}::getVesuMultiplyCall denominatorPart: ${denominatorPart}`
29079
+ );
28947
29080
  const x_debt_usd = numeratorPart1.minus(numeratorPart2).dividedBy(denominatorPart);
28948
- logger.verbose(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall x_debt_usd: ${x_debt_usd}`);
28949
- logger.debug(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart1: ${numeratorPart1}, numeratorPart2: ${numeratorPart2}, denominatorPart: ${denominatorPart}`);
28950
- let debtAmount = new Web3Number(x_debt_usd.dividedBy(debtPrice).toFixed(this.config.debt.decimals), this.config.debt.decimals);
29081
+ logger.verbose(
29082
+ `${_VesuMultiplyAdapter.name}::getVesuMultiplyCall x_debt_usd: ${x_debt_usd}`
29083
+ );
29084
+ logger.debug(
29085
+ `${_VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart1: ${numeratorPart1}, numeratorPart2: ${numeratorPart2}, denominatorPart: ${denominatorPart}`
29086
+ );
29087
+ let debtAmount = new Web3Number(
29088
+ x_debt_usd.dividedBy(debtPrice).toFixed(this.config.debt.decimals),
29089
+ this.config.debt.decimals
29090
+ );
28951
29091
  const marginAmount = addedCollateral;
28952
29092
  const collateralToken = this.config.collateral;
28953
29093
  const debtToken = this.config.debt;
28954
- const debtAmountInCollateralUnits = new Web3Number(debtAmount.multipliedBy(debtPrice).dividedBy(collateralPrice).multipliedBy(10 ** collateralToken.decimals).toFixed(0), collateralToken.decimals);
29094
+ const debtAmountInCollateralUnits = new Web3Number(
29095
+ debtAmount.multipliedBy(debtPrice).dividedBy(collateralPrice).multipliedBy(10 ** collateralToken.decimals).toFixed(0),
29096
+ collateralToken.decimals
29097
+ );
28955
29098
  const isIncrease = debtAmount.greaterThanOrEqualTo(0);
28956
29099
  if (isIncrease && debtAmount.lessThan(0)) {
28957
29100
  } else if (!isIncrease && debtAmount.greaterThan(0)) {
28958
29101
  debtAmount = Web3Number.fromWei(0, this.config.debt.decimals);
28959
29102
  }
28960
- logger.verbose(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall debtAmount: ${debtAmount}, marginAmount: ${marginAmount}`);
29103
+ logger.verbose(
29104
+ `${_VesuMultiplyAdapter.name}::getVesuMultiplyCall debtAmount: ${debtAmount}, marginAmount: ${marginAmount}`
29105
+ );
28961
29106
  if (!debtAmount.isZero()) {
28962
29107
  try {
28963
29108
  const swapQuote = await ekuboQuoter.getQuote(
@@ -28967,26 +29112,49 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28967
29112
  // negative for exact amount out
28968
29113
  );
28969
29114
  if (swapQuote.price_impact < 0.01) {
28970
- leverSwap = ekuboQuoter.getVesuMultiplyQuote(swapQuote, debtToken, collateralToken);
29115
+ leverSwap = debtAmount.isNegative() ? ekuboQuoter.getVesuMultiplyQuote(
29116
+ swapQuote,
29117
+ collateralToken,
29118
+ debtToken
29119
+ ) : ekuboQuoter.getVesuMultiplyQuote(
29120
+ swapQuote,
29121
+ debtToken,
29122
+ collateralToken
29123
+ );
28971
29124
  const MAX_SLIPPAGE = 2e-3;
28972
29125
  if (debtAmount.greaterThan(0)) {
28973
29126
  leverSwapLimitAmount = debtAmount.multipliedBy(1 + MAX_SLIPPAGE);
28974
29127
  } else if (debtAmount.lessThan(0)) {
28975
29128
  leverSwapLimitAmount = debtAmount.abs().multipliedBy(1 - MAX_SLIPPAGE);
28976
29129
  } else {
28977
- leverSwapLimitAmount = Web3Number.fromWei(0, this.config.debt.decimals);
29130
+ leverSwapLimitAmount = Web3Number.fromWei(
29131
+ 0,
29132
+ this.config.debt.decimals
29133
+ );
28978
29134
  }
28979
29135
  await new Promise((resolve) => setTimeout(resolve, 1e4));
28980
29136
  } else {
28981
- throw new Error(`VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`);
29137
+ throw new Error(
29138
+ `VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`
29139
+ );
28982
29140
  }
28983
29141
  } catch (error) {
28984
- throw new Error(`VesuMultiplyAdapter: Failed to get swap quote: ${error}`);
29142
+ throw new Error(
29143
+ `VesuMultiplyAdapter: Failed to get swap quote: ${error}`
29144
+ );
28985
29145
  }
28986
29146
  }
28987
- const multiplyParams = await this.getLeverParams(isIncrease, params, leverSwap, leverSwapLimitAmount);
29147
+ const multiplyParams = await this.getLeverParams(
29148
+ isIncrease,
29149
+ params,
29150
+ leverSwap,
29151
+ leverSwapLimitAmount
29152
+ );
28988
29153
  const call = multiplyContract.populate("modify_lever", {
28989
- modify_lever_params: this.formatMultiplyParams(isIncrease, multiplyParams)
29154
+ modify_lever_params: this.formatMultiplyParams(
29155
+ isIncrease,
29156
+ multiplyParams
29157
+ )
28990
29158
  });
28991
29159
  return call.calldata;
28992
29160
  }
@@ -29000,7 +29168,10 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
29000
29168
  add_margin: params.amount,
29001
29169
  // multiplied by collateral decimals in format
29002
29170
  margin_swap: [],
29003
- margin_swap_limit_amount: Web3Number.fromWei(0, this.config.collateral.decimals),
29171
+ margin_swap_limit_amount: Web3Number.fromWei(
29172
+ 0,
29173
+ this.config.collateral.decimals
29174
+ ),
29004
29175
  lever_swap: leverSwap,
29005
29176
  lever_swap_limit_amount: leverSwapLimitAmount
29006
29177
  } : {
@@ -29014,7 +29185,10 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
29014
29185
  lever_swap_limit_amount: leverSwapLimitAmount,
29015
29186
  lever_swap_weights: [],
29016
29187
  withdraw_swap: [],
29017
- withdraw_swap_limit_amount: Web3Number.fromWei(0, this.config.collateral.decimals),
29188
+ withdraw_swap_limit_amount: Web3Number.fromWei(
29189
+ 0,
29190
+ this.config.collateral.decimals
29191
+ ),
29018
29192
  withdraw_swap_weights: [],
29019
29193
  close_position: false
29020
29194
  };
@@ -29030,12 +29204,16 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
29030
29204
  });
29031
29205
  let leverSwap = [];
29032
29206
  let leverSwapLimitAmount = Web3Number.fromWei(0, this.config.debt.decimals);
29033
- const existingPositions = await this.vesuAdapter.getPositions(this.config.networkConfig);
29207
+ const existingPositions = await this.vesuAdapter.getPositions(
29208
+ this.config.networkConfig
29209
+ );
29034
29210
  const existingCollateralInfo = existingPositions[0];
29035
29211
  const existingDebtInfo = existingPositions[1];
29036
29212
  const collateralToken = this.config.collateral;
29037
29213
  const debtToken = this.config.debt;
29038
- const collateralPrice = await this.config.pricer.getPrice(collateralToken.symbol);
29214
+ const collateralPrice = await this.config.pricer.getPrice(
29215
+ collateralToken.symbol
29216
+ );
29039
29217
  const debtPrice = await this.config.pricer.getPrice(debtToken.symbol);
29040
29218
  const { deltadebtAmountUnits: debtAmountToRepay } = calculateDebtReductionAmountForWithdrawal(
29041
29219
  existingDebtInfo.amount,
@@ -29049,8 +29227,14 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
29049
29227
  if (!debtAmountToRepay) {
29050
29228
  throw new Error("error calculating debt amount to repay");
29051
29229
  }
29052
- const ekuboQuoter = new EkuboQuoter(this.config.networkConfig, this.config.pricer);
29053
- const debtInDebtUnits = new Web3Number(debtAmountToRepay, debtToken.decimals).dividedBy(debtPrice.price).multipliedBy(10 ** debtToken.decimals);
29230
+ const ekuboQuoter = new EkuboQuoter(
29231
+ this.config.networkConfig,
29232
+ this.config.pricer
29233
+ );
29234
+ const debtInDebtUnits = new Web3Number(
29235
+ debtAmountToRepay,
29236
+ debtToken.decimals
29237
+ ).dividedBy(debtPrice.price).multipliedBy(10 ** debtToken.decimals);
29054
29238
  const swapQuote = await ekuboQuoter.getQuote(
29055
29239
  debtToken.address.address,
29056
29240
  collateralToken.address.address,
@@ -29058,12 +29242,23 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
29058
29242
  );
29059
29243
  const MAX_SLIPPAGE = 2e-3;
29060
29244
  if (swapQuote.price_impact < 25e-4) {
29061
- leverSwap = ekuboQuoter.getVesuMultiplyQuote(swapQuote, collateralToken, debtToken);
29245
+ leverSwap = ekuboQuoter.getVesuMultiplyQuote(
29246
+ swapQuote,
29247
+ collateralToken,
29248
+ debtToken
29249
+ );
29062
29250
  } else {
29063
- logger.error(`VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`);
29251
+ logger.error(
29252
+ `VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`
29253
+ );
29064
29254
  }
29065
29255
  leverSwapLimitAmount = new Web3Number(debtAmountToRepay, debtToken.decimals).abs().multipliedBy(1 + MAX_SLIPPAGE);
29066
- const multiplyParams = await this.getLeverParams(false, params, leverSwap, leverSwapLimitAmount);
29256
+ const multiplyParams = await this.getLeverParams(
29257
+ false,
29258
+ params,
29259
+ leverSwap,
29260
+ leverSwapLimitAmount
29261
+ );
29067
29262
  const call = multiplyContract.populate("modify_lever", {
29068
29263
  modify_lever_params: this.formatMultiplyParams(false, multiplyParams)
29069
29264
  });
@@ -29073,100 +29268,132 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
29073
29268
  if (isIncrease) {
29074
29269
  const _params2 = params;
29075
29270
  return {
29076
- action: new import_starknet21.CairoCustomEnum({ IncreaseLever: {
29077
- pool_id: _params2.pool_id.toBigInt(),
29078
- collateral_asset: _params2.collateral_asset.toBigInt(),
29079
- debt_asset: _params2.debt_asset.toBigInt(),
29080
- user: _params2.user.toBigInt(),
29081
- add_margin: BigInt(_params2.add_margin.toWei()),
29082
- margin_swap: _params2.margin_swap.map((swap) => ({
29271
+ action: new import_starknet21.CairoCustomEnum({
29272
+ IncreaseLever: {
29273
+ pool_id: _params2.pool_id.toBigInt(),
29274
+ collateral_asset: _params2.collateral_asset.toBigInt(),
29275
+ debt_asset: _params2.debt_asset.toBigInt(),
29276
+ user: _params2.user.toBigInt(),
29277
+ add_margin: BigInt(_params2.add_margin.toWei()),
29278
+ margin_swap: _params2.margin_swap.map((swap) => ({
29279
+ route: swap.route.map((route) => ({
29280
+ pool_key: {
29281
+ token0: route.pool_key.token0.toBigInt(),
29282
+ token1: route.pool_key.token1.toBigInt(),
29283
+ fee: route.pool_key.fee,
29284
+ tick_spacing: route.pool_key.tick_spacing,
29285
+ extension: BigInt(
29286
+ import_starknet21.num.hexToDecimalString(route.pool_key.extension)
29287
+ )
29288
+ },
29289
+ sqrt_ratio_limit: import_starknet21.uint256.bnToUint256(
29290
+ route.sqrt_ratio_limit.toWei()
29291
+ ),
29292
+ skip_ahead: BigInt(100)
29293
+ })),
29294
+ token_amount: {
29295
+ token: swap.token_amount.token.toBigInt(),
29296
+ amount: swap.token_amount.amount.toI129()
29297
+ }
29298
+ })),
29299
+ margin_swap_limit_amount: BigInt(
29300
+ _params2.margin_swap_limit_amount.toWei()
29301
+ ),
29302
+ lever_swap: _params2.lever_swap.map((swap) => ({
29303
+ route: swap.route.map((route) => ({
29304
+ pool_key: {
29305
+ token0: route.pool_key.token0.toBigInt(),
29306
+ token1: route.pool_key.token1.toBigInt(),
29307
+ fee: route.pool_key.fee,
29308
+ tick_spacing: route.pool_key.tick_spacing,
29309
+ extension: BigInt(
29310
+ import_starknet21.num.hexToDecimalString(route.pool_key.extension)
29311
+ )
29312
+ },
29313
+ sqrt_ratio_limit: import_starknet21.uint256.bnToUint256(
29314
+ route.sqrt_ratio_limit.toWei()
29315
+ ),
29316
+ skip_ahead: BigInt(0)
29317
+ })),
29318
+ token_amount: {
29319
+ token: swap.token_amount.token.toBigInt(),
29320
+ amount: swap.token_amount.amount.toI129()
29321
+ }
29322
+ })),
29323
+ lever_swap_limit_amount: BigInt(
29324
+ _params2.lever_swap_limit_amount.toWei()
29325
+ )
29326
+ }
29327
+ })
29328
+ };
29329
+ }
29330
+ const _params = params;
29331
+ return {
29332
+ action: new import_starknet21.CairoCustomEnum({
29333
+ DecreaseLever: {
29334
+ pool_id: _params.pool_id.toBigInt(),
29335
+ collateral_asset: _params.collateral_asset.toBigInt(),
29336
+ debt_asset: _params.debt_asset.toBigInt(),
29337
+ user: _params.user.toBigInt(),
29338
+ sub_margin: BigInt(_params.sub_margin.toWei()),
29339
+ recipient: _params.recipient.toBigInt(),
29340
+ lever_swap: _params.lever_swap.map((swap) => ({
29083
29341
  route: swap.route.map((route) => ({
29084
29342
  pool_key: {
29085
29343
  token0: route.pool_key.token0.toBigInt(),
29086
29344
  token1: route.pool_key.token1.toBigInt(),
29087
29345
  fee: route.pool_key.fee,
29088
29346
  tick_spacing: route.pool_key.tick_spacing,
29089
- extension: BigInt(import_starknet21.num.hexToDecimalString(route.pool_key.extension))
29347
+ extension: ContractAddr.from(
29348
+ route.pool_key.extension
29349
+ ).toBigInt()
29090
29350
  },
29091
- sqrt_ratio_limit: import_starknet21.uint256.bnToUint256(route.sqrt_ratio_limit.toWei()),
29092
- skip_ahead: BigInt(100)
29351
+ sqrt_ratio_limit: import_starknet21.uint256.bnToUint256(
29352
+ route.sqrt_ratio_limit.toWei()
29353
+ ),
29354
+ skip_ahead: BigInt(route.skip_ahead.toWei())
29093
29355
  })),
29094
29356
  token_amount: {
29095
29357
  token: swap.token_amount.token.toBigInt(),
29096
29358
  amount: swap.token_amount.amount.toI129()
29097
29359
  }
29098
29360
  })),
29099
- margin_swap_limit_amount: BigInt(_params2.margin_swap_limit_amount.toWei()),
29100
- lever_swap: _params2.lever_swap.map((swap) => ({
29361
+ lever_swap_limit_amount: BigInt(
29362
+ _params.lever_swap_limit_amount.toWei()
29363
+ ),
29364
+ lever_swap_weights: _params.lever_swap_weights.map(
29365
+ (weight) => BigInt(weight.toWei())
29366
+ ),
29367
+ withdraw_swap: _params.withdraw_swap.map((swap) => ({
29101
29368
  route: swap.route.map((route) => ({
29102
29369
  pool_key: {
29103
29370
  token0: route.pool_key.token0.toBigInt(),
29104
29371
  token1: route.pool_key.token1.toBigInt(),
29105
29372
  fee: route.pool_key.fee,
29106
29373
  tick_spacing: route.pool_key.tick_spacing,
29107
- extension: BigInt(import_starknet21.num.hexToDecimalString(route.pool_key.extension))
29374
+ extension: ContractAddr.from(
29375
+ route.pool_key.extension
29376
+ ).toBigInt()
29108
29377
  },
29109
- sqrt_ratio_limit: import_starknet21.uint256.bnToUint256(route.sqrt_ratio_limit.toWei()),
29110
- skip_ahead: BigInt(0)
29378
+ sqrt_ratio_limit: import_starknet21.uint256.bnToUint256(
29379
+ route.sqrt_ratio_limit.toWei()
29380
+ ),
29381
+ skip_ahead: BigInt(route.skip_ahead.toWei())
29111
29382
  })),
29112
29383
  token_amount: {
29113
29384
  token: swap.token_amount.token.toBigInt(),
29114
29385
  amount: swap.token_amount.amount.toI129()
29115
29386
  }
29116
29387
  })),
29117
- lever_swap_limit_amount: BigInt(_params2.lever_swap_limit_amount.toWei())
29118
- } })
29119
- };
29120
- }
29121
- const _params = params;
29122
- return {
29123
- action: new import_starknet21.CairoCustomEnum({ DecreaseLever: {
29124
- pool_id: _params.pool_id.toBigInt(),
29125
- collateral_asset: _params.collateral_asset.toBigInt(),
29126
- debt_asset: _params.debt_asset.toBigInt(),
29127
- user: _params.user.toBigInt(),
29128
- sub_margin: BigInt(_params.sub_margin.toWei()),
29129
- recipient: _params.recipient.toBigInt(),
29130
- lever_swap: _params.lever_swap.map((swap) => ({
29131
- route: swap.route.map((route) => ({
29132
- pool_key: {
29133
- token0: route.pool_key.token0.toBigInt(),
29134
- token1: route.pool_key.token1.toBigInt(),
29135
- fee: route.pool_key.fee,
29136
- tick_spacing: route.pool_key.tick_spacing,
29137
- extension: ContractAddr.from(route.pool_key.extension).toBigInt()
29138
- },
29139
- sqrt_ratio_limit: import_starknet21.uint256.bnToUint256(route.sqrt_ratio_limit.toWei()),
29140
- skip_ahead: BigInt(route.skip_ahead.toWei())
29141
- })),
29142
- token_amount: {
29143
- token: swap.token_amount.token.toBigInt(),
29144
- amount: swap.token_amount.amount.toI129()
29145
- }
29146
- })),
29147
- lever_swap_limit_amount: BigInt(_params.lever_swap_limit_amount.toWei()),
29148
- lever_swap_weights: _params.lever_swap_weights.map((weight) => BigInt(weight.toWei())),
29149
- withdraw_swap: _params.withdraw_swap.map((swap) => ({
29150
- route: swap.route.map((route) => ({
29151
- pool_key: {
29152
- token0: route.pool_key.token0.toBigInt(),
29153
- token1: route.pool_key.token1.toBigInt(),
29154
- fee: route.pool_key.fee,
29155
- tick_spacing: route.pool_key.tick_spacing,
29156
- extension: ContractAddr.from(route.pool_key.extension).toBigInt()
29157
- },
29158
- sqrt_ratio_limit: import_starknet21.uint256.bnToUint256(route.sqrt_ratio_limit.toWei()),
29159
- skip_ahead: BigInt(route.skip_ahead.toWei())
29160
- })),
29161
- token_amount: {
29162
- token: swap.token_amount.token.toBigInt(),
29163
- amount: swap.token_amount.amount.toI129()
29164
- }
29165
- })),
29166
- withdraw_swap_limit_amount: BigInt(_params.withdraw_swap_limit_amount.toWei()),
29167
- withdraw_swap_weights: _params.withdraw_swap_weights.map((weight) => BigInt(weight.toWei())),
29168
- close_position: _params.close_position
29169
- } })
29388
+ withdraw_swap_limit_amount: BigInt(
29389
+ _params.withdraw_swap_limit_amount.toWei()
29390
+ ),
29391
+ withdraw_swap_weights: _params.withdraw_swap_weights.map(
29392
+ (weight) => BigInt(weight.toWei())
29393
+ ),
29394
+ close_position: _params.close_position
29395
+ }
29396
+ })
29170
29397
  };
29171
29398
  }
29172
29399
  async getHealthFactor() {
@@ -29175,11 +29402,15 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
29175
29402
  }
29176
29403
  async getNetAPY() {
29177
29404
  const positions = await this.getPositions();
29178
- logger.verbose(`${this.name}::getNetAPY: positions: ${JSON.stringify(positions)}`);
29405
+ logger.verbose(
29406
+ `${this.name}::getNetAPY: positions: ${JSON.stringify(positions)}`
29407
+ );
29179
29408
  const allZero = positions.every((p) => p.usdValue === 0);
29180
29409
  if (allZero) {
29181
29410
  const collateralUSD = 1e3;
29182
- const maxLTV = await this.vesuAdapter.getLTVConfig(this.config.networkConfig);
29411
+ const maxLTV = await this.vesuAdapter.getLTVConfig(
29412
+ this.config.networkConfig
29413
+ );
29183
29414
  const targetHF = this.config.targetHealthFactor;
29184
29415
  const maxDebt = HealthFactorMath.getMaxDebtAmountOnLooping(
29185
29416
  new Web3Number(collateralUSD, this.config.collateral.decimals),
@@ -29322,7 +29553,22 @@ var ExtendedWrapper = class {
29322
29553
  `HTTP ${response.status}: ${errorData.detail || response.statusText}`
29323
29554
  );
29324
29555
  }
29325
- const data = await response.json();
29556
+ const text = await response.text();
29557
+ const MAX_SAFE_INTEGER_STR = "9007199254740991";
29558
+ const largeIntegerRegex = /"data"\s*:\s*(\d{16,})/g;
29559
+ const modifiedText = text.replace(largeIntegerRegex, (match, largeInt) => {
29560
+ if (largeInt.length > MAX_SAFE_INTEGER_STR.length || largeInt.length === MAX_SAFE_INTEGER_STR.length && largeInt > MAX_SAFE_INTEGER_STR) {
29561
+ return `"data":"${largeInt}"`;
29562
+ }
29563
+ return match;
29564
+ });
29565
+ const data = JSON.parse(modifiedText);
29566
+ if (data && typeof data.data === "string" && /^\d+$/.test(data.data)) {
29567
+ const numValue = Number(data.data);
29568
+ if (Number.isSafeInteger(numValue)) {
29569
+ data.data = numValue;
29570
+ }
29571
+ }
29326
29572
  return data;
29327
29573
  } catch (error) {
29328
29574
  lastError = error;
@@ -29382,6 +29628,7 @@ var ExtendedWrapper = class {
29382
29628
  }
29383
29629
  /**
29384
29630
  * Initiate a withdrawal from Extended Exchange
29631
+ * Returns data as number | string to preserve precision for large integers
29385
29632
  */
29386
29633
  async withdraw(request) {
29387
29634
  return this.makeRequest("/api/v1/withdraw", {
@@ -29520,6 +29767,7 @@ var ExtendedWrapper = class {
29520
29767
  }
29521
29768
  /**
29522
29769
  * Withdraw USDC (convenience method)
29770
+ * Returns data as number | string to preserve precision for large integers
29523
29771
  */
29524
29772
  async withdrawUSDC(amount) {
29525
29773
  return this.withdraw({ amount, asset: "USDC" });
@@ -29529,11 +29777,13 @@ var ExtendedWrapper = class {
29529
29777
  * @param marketName - The name of the market to get funding rates for
29530
29778
  * @returns The funding rates for the specified market
29531
29779
  */
29532
- async getFundingRates(marketName, side) {
29780
+ async getFundingRates(marketName, side, startTime, endTime) {
29781
+ const endTimeParam = endTime !== void 0 ? `&end_time=${endTime}` : "";
29782
+ const startTimeParam = startTime !== void 0 ? `&start_time=${startTime}` : "";
29533
29783
  return this.makeRequest(
29534
29784
  `/api/v1/markets/funding-rates?market_name=${encodeURIComponent(
29535
29785
  marketName
29536
- )}&side=${encodeURIComponent(side)}`
29786
+ )}&side=${encodeURIComponent(side)}${startTimeParam}${endTimeParam}`
29537
29787
  );
29538
29788
  }
29539
29789
  };
@@ -29546,18 +29796,20 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29546
29796
  super(config, _ExtendedAdapter.name, Protocols.EXTENDED);
29547
29797
  this.config = config;
29548
29798
  const client = new wrapper_default({
29549
- baseUrl: this.config.extendedBackendUrl,
29550
- apiKey: this.config.extendedApiKey,
29799
+ baseUrl: this.config.extendedBackendWriteUrl,
29800
+ apiKey: "",
29551
29801
  timeout: this.config.extendedTimeout,
29552
29802
  retries: this.config.extendedRetries
29553
29803
  });
29804
+ this.minimumExtendedMovementAmount = this.config.minimumExtendedMovementAmount ?? 5;
29554
29805
  this.client = client;
29806
+ this.retryDelayForOrderStatus = this.config.retryDelayForOrderStatus ?? 3e3;
29555
29807
  }
29556
29808
  //abstract means the method has no implementation in this class; instead, child classes must implement it.
29557
29809
  async getAPY(supportedPosition) {
29558
29810
  const side = supportedPosition.isDebt ? "LONG" : "SHORT";
29559
- const fundingRates = await this.client.getFundingRates(this.config.extendedMarketName, side);
29560
- if (fundingRates.status !== "OK") {
29811
+ const fundingRates = await this.getFundingRates(side);
29812
+ if (!fundingRates.success) {
29561
29813
  logger.error("error getting funding rates", fundingRates);
29562
29814
  return { apy: 0, type: "base" /* BASE */ };
29563
29815
  }
@@ -29565,10 +29817,26 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29565
29817
  const apy = Number(fundingRate.f) * 365 * 24;
29566
29818
  return { apy, type: "base" /* BASE */ };
29567
29819
  }
29568
- async getPosition(supportedPosition) {
29569
- if (!this.client) {
29570
- throw new Error("Client not initialized");
29820
+ async getFundingRates(side, startTime, endTime) {
29821
+ try {
29822
+ const response = await import_axios8.default.get(`${this.config.extendedBackendReadUrl}/fundingRates/${this.config.extendedMarketName}/${side}`, {
29823
+ params: {
29824
+ startTime: startTime ? startTime.toString() : void 0,
29825
+ endTime: endTime ? endTime.toString() : void 0
29826
+ }
29827
+ });
29828
+ if (!response.data.success) {
29829
+ logger.error("error getting funding rates", response.data);
29830
+ return { success: false, data: [] };
29831
+ }
29832
+ logger.info("success getting funding rates", response.data.data);
29833
+ return { success: true, data: response.data.data };
29834
+ } catch (err) {
29835
+ logger.error("error getting funding rates", err);
29836
+ return { success: false, data: [] };
29571
29837
  }
29838
+ }
29839
+ async getPosition(supportedPosition) {
29572
29840
  const holdings = await this.getExtendedDepositAmount();
29573
29841
  if (!holdings) {
29574
29842
  throw new Error("No position found");
@@ -29576,7 +29844,7 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29576
29844
  const amount = holdings.equity;
29577
29845
  return Promise.resolve({
29578
29846
  amount: new Web3Number(amount, 0),
29579
- remarks: `${holdings.availableForWithdrawal} ${holdings.equity}`
29847
+ remarks: `Extended Equity`
29580
29848
  });
29581
29849
  }
29582
29850
  async maxDeposit(amount) {
@@ -29600,14 +29868,14 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29600
29868
  });
29601
29869
  }
29602
29870
  _getDepositLeaf() {
29603
- const usdceToken = Global.getDefaultTokens().find((token) => token.symbol === "USDCe");
29871
+ const usdceToken = Global.getDefaultTokens().find(
29872
+ (token) => token.symbol === "USDCe"
29873
+ );
29604
29874
  return [
29605
29875
  {
29606
29876
  target: this.config.supportedPositions[0].asset.address,
29607
29877
  method: "approve",
29608
- packedArguments: [
29609
- AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()
29610
- ],
29878
+ packedArguments: [AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()],
29611
29879
  id: `extended_approve_${this.config.supportedPositions[0].asset.symbol}`,
29612
29880
  sanitizer: AVNU_LEGACY_SANITIZER
29613
29881
  },
@@ -29638,25 +29906,33 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29638
29906
  const leafConfigs = this._getSwapFromLegacyLeaf();
29639
29907
  const leaves = leafConfigs.map((config) => {
29640
29908
  const { target, method, packedArguments, sanitizer, id } = config;
29641
- const leaf = this.constructSimpleLeafData({
29642
- id,
29643
- target,
29644
- method,
29645
- packedArguments
29646
- }, sanitizer);
29909
+ const leaf = this.constructSimpleLeafData(
29910
+ {
29911
+ id,
29912
+ target,
29913
+ method,
29914
+ packedArguments
29915
+ },
29916
+ sanitizer
29917
+ );
29647
29918
  return leaf;
29648
29919
  });
29649
- return { leaves, callConstructor: this.getSwapFromLegacyCall.bind(this) };
29920
+ return {
29921
+ leaves,
29922
+ callConstructor: this.getSwapFromLegacyCall.bind(
29923
+ this
29924
+ )
29925
+ };
29650
29926
  }
29651
29927
  _getSwapFromLegacyLeaf() {
29652
- const usdceToken = Global.getDefaultTokens().find((token) => token.symbol === "USDCe");
29928
+ const usdceToken = Global.getDefaultTokens().find(
29929
+ (token) => token.symbol === "USDCe"
29930
+ );
29653
29931
  return [
29654
29932
  {
29655
29933
  target: usdceToken.address,
29656
29934
  method: "approve",
29657
- packedArguments: [
29658
- AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()
29659
- ],
29935
+ packedArguments: [AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()],
29660
29936
  id: `extendedswaplegacyapprove_${usdceToken.symbol}`,
29661
29937
  sanitizer: AVNU_LEGACY_SANITIZER
29662
29938
  },
@@ -29675,11 +29951,13 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29675
29951
  async getDepositCall(params) {
29676
29952
  try {
29677
29953
  const usdcToken = this.config.supportedPositions[0].asset;
29678
- const usdceToken = Global.getDefaultTokens().find((token) => token.symbol === "USDCe");
29679
- const salt = Math.floor(
29680
- Math.random() * 10 ** usdcToken.decimals
29954
+ const usdceToken = Global.getDefaultTokens().find(
29955
+ (token) => token.symbol === "USDCe"
29956
+ );
29957
+ const salt = Math.floor(Math.random() * 10 ** usdcToken.decimals);
29958
+ const amount = import_starknet22.uint256.bnToUint256(
29959
+ params.amount.multipliedBy(10).toWei()
29681
29960
  );
29682
- const amount = import_starknet22.uint256.bnToUint256(params.amount.multipliedBy(10).toWei());
29683
29961
  const quotes = await this.config.avnuAdapter.getQuotesAvnu(
29684
29962
  usdcToken.address.toString(),
29685
29963
  usdceToken.address.toString(),
@@ -29692,7 +29970,9 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29692
29970
  logger.error("error getting quotes from avnu");
29693
29971
  return [];
29694
29972
  }
29695
- const getCalldata = await this.config.avnuAdapter.getSwapCallData(quotes);
29973
+ const getCalldata = await this.config.avnuAdapter.getSwapCallData(
29974
+ quotes
29975
+ );
29696
29976
  const swapCallData = getCalldata[0];
29697
29977
  return [
29698
29978
  {
@@ -29768,8 +30048,12 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29768
30048
  async getSwapFromLegacyCall(params) {
29769
30049
  try {
29770
30050
  const usdcToken = this.config.supportedPositions[0].asset;
29771
- const usdceToken = Global.getDefaultTokens().find((token) => token.symbol === "USDCe");
29772
- const amount = import_starknet22.uint256.bnToUint256(params.amount.multipliedBy(10).toWei());
30051
+ const usdceToken = Global.getDefaultTokens().find(
30052
+ (token) => token.symbol === "USDCe"
30053
+ );
30054
+ const amount = import_starknet22.uint256.bnToUint256(
30055
+ params.amount.multipliedBy(10).toWei()
30056
+ );
29773
30057
  const quotes = await this.config.avnuAdapter.getQuotesAvnu(
29774
30058
  usdceToken.address.toString(),
29775
30059
  usdcToken.address.toString(),
@@ -29782,7 +30066,9 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29782
30066
  logger.error("error getting quotes from avnu");
29783
30067
  return [];
29784
30068
  }
29785
- const getCalldata = await this.config.avnuAdapter.getSwapCallData(quotes);
30069
+ const getCalldata = await this.config.avnuAdapter.getSwapCallData(
30070
+ quotes
30071
+ );
29786
30072
  const swapCallData = getCalldata[0];
29787
30073
  return [
29788
30074
  {
@@ -29828,38 +30114,131 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29828
30114
  async withdrawFromExtended(amount) {
29829
30115
  try {
29830
30116
  if (!this.client) {
29831
- throw new Error("Client not initialized");
30117
+ logger.error("Client not initialized");
30118
+ return {
30119
+ status: false,
30120
+ receivedTxnHash: false
30121
+ };
30122
+ }
30123
+ if (amount.lessThanOrEqualTo(0)) {
30124
+ logger.error(
30125
+ `Invalid withdrawal amount: ${amount.toNumber()}. Amount must be positive.`
30126
+ );
30127
+ return {
30128
+ status: false,
30129
+ receivedTxnHash: false
30130
+ };
30131
+ }
30132
+ if (amount.lessThanOrEqualTo(this.minimumExtendedMovementAmount)) {
30133
+ logger.warn(
30134
+ `Withdrawal amount ${amount.toNumber()} is below minimum Extended movement amount ${this.minimumExtendedMovementAmount}. Skipping withdrawal.`
30135
+ );
30136
+ return {
30137
+ status: false,
30138
+ receivedTxnHash: false
30139
+ };
30140
+ }
30141
+ const holdings = await this.getExtendedDepositAmount();
30142
+ if (!holdings) {
30143
+ logger.error(
30144
+ "Cannot get holdings - unable to validate withdrawal amount"
30145
+ );
30146
+ return {
30147
+ status: false,
30148
+ receivedTxnHash: false
30149
+ };
30150
+ }
30151
+ const availableForWithdrawal = parseFloat(
30152
+ holdings.availableForWithdrawal
30153
+ );
30154
+ if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
30155
+ logger.error(
30156
+ `Invalid availableForWithdrawal: ${holdings.availableForWithdrawal}. Expected a finite, non-negative number.`
30157
+ );
30158
+ return {
30159
+ status: false,
30160
+ receivedTxnHash: false
30161
+ };
30162
+ }
30163
+ const withdrawalAmount = amount.toNumber();
30164
+ if (withdrawalAmount > availableForWithdrawal) {
30165
+ logger.error(
30166
+ `Withdrawal amount ${withdrawalAmount} exceeds available balance ${availableForWithdrawal}`
30167
+ );
30168
+ return {
30169
+ status: false,
30170
+ receivedTxnHash: false
30171
+ };
29832
30172
  }
29833
- const withdrawalRequest = await this.client.withdrawUSDC(amount.toFixed(2));
30173
+ logger.info(
30174
+ `Withdrawing ${withdrawalAmount} from Extended. Available balance: ${availableForWithdrawal}`
30175
+ );
30176
+ const withdrawalRequest = await this.client.withdrawUSDC(
30177
+ amount.toFixed(2)
30178
+ );
29834
30179
  if (withdrawalRequest.status === "OK") {
29835
- const withdrawalStatus = await this.getDepositOrWithdrawalStatus(withdrawalRequest.data, "WITHDRAWAL" /* WITHDRAWAL */);
29836
- return withdrawalStatus;
30180
+ const withdrawalStatus = await this.getDepositOrWithdrawalStatus(
30181
+ withdrawalRequest.data,
30182
+ "WITHDRAWAL" /* WITHDRAWAL */
30183
+ );
30184
+ return {
30185
+ status: true,
30186
+ receivedTxnHash: withdrawalStatus
30187
+ };
29837
30188
  }
29838
- return false;
30189
+ logger.error(
30190
+ `Withdrawal request failed with status: ${withdrawalRequest.status}`
30191
+ );
30192
+ return {
30193
+ status: false,
30194
+ receivedTxnHash: false
30195
+ };
29839
30196
  } catch (error) {
29840
30197
  logger.error(`Error creating Withdraw Call: ${error}`);
29841
- return false;
30198
+ return {
30199
+ status: false,
30200
+ receivedTxnHash: false
30201
+ };
29842
30202
  }
29843
30203
  }
29844
30204
  async getHealthFactor() {
29845
30205
  return Promise.resolve(1);
29846
30206
  }
29847
30207
  async getExtendedDepositAmount() {
29848
- if (this.client === null) {
29849
- logger.error("error initializing client");
29850
- return void 0;
29851
- }
29852
- const result = await this.client.getHoldings();
29853
- if (!result) {
29854
- logger.error(`error getting holdings: ${result}`);
29855
- return void 0;
29856
- }
29857
- const holdings = result.data;
29858
- if (!holdings) {
29859
- logger.error(`error getting holdings: ${holdings}`);
30208
+ try {
30209
+ const result = await import_axios8.default.get(`${this.config.extendedBackendReadUrl}/holdings`);
30210
+ if (!result.data) {
30211
+ logger.error("error getting holdings - API returned null/undefined");
30212
+ return void 0;
30213
+ }
30214
+ if (!result.data.success) {
30215
+ logger.error(
30216
+ `error getting holdings - API returned status: ${result.status}`
30217
+ );
30218
+ return void 0;
30219
+ }
30220
+ const holdings = result.data.data;
30221
+ if (!holdings) {
30222
+ logger.warn(
30223
+ "holdings data is null/undefined - treating as zero balance"
30224
+ );
30225
+ return {
30226
+ collateral_name: "",
30227
+ balance: "0",
30228
+ equity: "0",
30229
+ availableForTrade: "0",
30230
+ availableForWithdrawal: "0",
30231
+ unrealisedPnl: "0",
30232
+ initialMargin: "0",
30233
+ marginRatio: "0",
30234
+ updatedTime: Date.now()
30235
+ };
30236
+ }
30237
+ return holdings;
30238
+ } catch (error) {
30239
+ logger.error(`error getting holdings - exception: ${error}`);
29860
30240
  return void 0;
29861
30241
  }
29862
- return holdings;
29863
30242
  }
29864
30243
  async setLeverage(leverage, marketName) {
29865
30244
  if (this.client === null) {
@@ -29876,46 +30255,52 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29876
30255
  return false;
29877
30256
  }
29878
30257
  async getAllOpenPositions() {
29879
- if (this.client === null) {
29880
- logger.error("error initializing client");
29881
- return null;
29882
- }
29883
- const response = await this.client.getPositionsForMarket(
29884
- this.config.extendedMarketName
29885
- );
29886
- if (response.status === "OK") {
29887
- if (response.data.length === 0) {
29888
- return [];
29889
- } else {
29890
- return response.data;
30258
+ try {
30259
+ const response = await import_axios8.default.get(`${this.config.extendedBackendReadUrl}/positions`);
30260
+ if (response.data.success) {
30261
+ if (response.data.data.length === 0) {
30262
+ return [];
30263
+ } else {
30264
+ return response.data.data;
30265
+ }
29891
30266
  }
30267
+ return null;
30268
+ } catch (err) {
30269
+ logger.error("error getting all open positions", err);
30270
+ return null;
29892
30271
  }
29893
- return null;
29894
30272
  }
29895
30273
  async getOrderHistory(marketName) {
29896
- if (this.client === null) {
29897
- logger.error("error initializing client");
30274
+ try {
30275
+ const result = await import_axios8.default.get(`${this.config.extendedBackendReadUrl}/marketOrders/${marketName}`);
30276
+ if (!result.data.success) {
30277
+ return null;
30278
+ }
30279
+ return result.data.data;
30280
+ } catch (err) {
30281
+ logger.error("error getting order history", err);
29898
30282
  return null;
29899
30283
  }
29900
- const result = await this.client.getOrderHistory(marketName);
29901
- return result.data;
29902
30284
  }
29903
30285
  async getOrderStatus(orderId, marketName) {
29904
- if (this.client === null) {
29905
- logger.error("error initializing client");
29906
- return null;
29907
- }
29908
- const orderhistory = await this.getOrderHistory(marketName);
29909
- if (!orderhistory || orderhistory.length === 0) {
29910
- logger.error(`error getting order: ${orderId}`);
30286
+ try {
30287
+ if (this.client === null) {
30288
+ logger.error("error initializing client");
30289
+ return null;
30290
+ }
30291
+ const orderhistory = await this.getOrderHistory(marketName);
30292
+ if (!orderhistory || orderhistory.length === 0) {
30293
+ return null;
30294
+ }
30295
+ const order = orderhistory.slice(0, 20).find((order2) => order2.id.toString() === orderId);
30296
+ if (order) {
30297
+ return order;
30298
+ }
29911
30299
  return null;
29912
- }
29913
- const order = orderhistory.slice(0, 3).find((order2) => order2.id.toString() === orderId);
29914
- if (!order) {
29915
- logger.error(`error getting order: ${order}`);
30300
+ } catch (error) {
30301
+ logger.error(`error getting order status: ${error}`);
29916
30302
  return null;
29917
30303
  }
29918
- return order;
29919
30304
  }
29920
30305
  async fetchOrderBookBTCUSDC() {
29921
30306
  try {
@@ -29966,14 +30351,40 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29966
30351
  logger.error("error depositing or setting leverage");
29967
30352
  return null;
29968
30353
  }
29969
- const positions = await this.getAllOpenPositions();
29970
- if (positions === null) {
30354
+ const { ask, bid } = await this.fetchOrderBookBTCUSDC();
30355
+ if (!ask || !bid || ask.lessThanOrEqualTo(0) || bid.lessThanOrEqualTo(0)) {
30356
+ logger.error(
30357
+ `Invalid orderbook prices: ask=${ask?.toNumber()}, bid=${bid?.toNumber()}`
30358
+ );
29971
30359
  return null;
29972
30360
  }
29973
- const { ask, bid } = await this.fetchOrderBookBTCUSDC();
29974
30361
  const spread = ask.minus(bid);
29975
- let price = ask.plus(bid).div(2);
29976
- side === "SELL" /* SELL */ ? price = price.minus(spread.times(0.2 * attempt)) : price = price.plus(spread.times(0.2 * attempt));
30362
+ const midPrice = ask.plus(bid).div(2);
30363
+ const MAX_PRICE_DEVIATION_MULTIPLIER = 0.5;
30364
+ const priceAdjustmentMultiplier = Math.min(
30365
+ 0.2 * attempt,
30366
+ MAX_PRICE_DEVIATION_MULTIPLIER
30367
+ );
30368
+ const priceAdjustment = spread.times(priceAdjustmentMultiplier);
30369
+ let price = midPrice;
30370
+ if (side === "SELL" /* SELL */) {
30371
+ price = midPrice.minus(priceAdjustment);
30372
+ } else {
30373
+ price = midPrice.plus(priceAdjustment);
30374
+ }
30375
+ const maxDeviation = midPrice.times(0.5);
30376
+ if (price.minus(midPrice).abs().greaterThan(maxDeviation)) {
30377
+ logger.error(
30378
+ `Price deviation too large on attempt ${attempt}: price=${price.toNumber()}, midPrice=${midPrice.toNumber()}, deviation=${price.minus(midPrice).abs().toNumber()}`
30379
+ );
30380
+ if (attempt >= maxAttempts) {
30381
+ return null;
30382
+ }
30383
+ price = side === "SELL" /* SELL */ ? midPrice.minus(maxDeviation) : midPrice.plus(maxDeviation);
30384
+ }
30385
+ logger.info(
30386
+ `createOrder attempt ${attempt}/${maxAttempts}: side=${side}, midPrice=${midPrice.toNumber()}, adjustedPrice=${price.toNumber()}, adjustment=${priceAdjustmentMultiplier * 100}%`
30387
+ );
29977
30388
  const amount_in_token = (btcAmount * parseInt(leverage)).toFixed(
29978
30389
  this.config.extendedPrecision
29979
30390
  );
@@ -29984,14 +30395,57 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29984
30395
  price.toFixed(0),
29985
30396
  side
29986
30397
  );
29987
- if (!result) {
30398
+ if (!result || !result.position_id) {
30399
+ logger.error("Failed to create order - no position_id returned");
29988
30400
  return null;
29989
30401
  }
29990
- await new Promise((resolve) => setTimeout(resolve, 5e3));
29991
- const openOrder = await this.getOrderStatus(result.position_id, this.config.extendedMarketName);
29992
- if (!openOrder || openOrder.status !== "FILLED" /* FILLED */) {
30402
+ const positionId = result.position_id;
30403
+ logger.info(
30404
+ `Order created with position_id: ${positionId}. Waiting for API to update...`
30405
+ );
30406
+ let openOrder = await this.getOrderStatus(
30407
+ positionId,
30408
+ this.config.extendedMarketName
30409
+ );
30410
+ const maxStatusRetries = 3;
30411
+ const statusRetryDelay = 5e3;
30412
+ if (!openOrder) {
30413
+ logger.warn(
30414
+ `Order ${positionId} not found in API yet. Retrying status fetch (max ${maxStatusRetries} times)...`
30415
+ );
30416
+ for (let statusRetry = 1; statusRetry <= maxStatusRetries; statusRetry++) {
30417
+ await new Promise((resolve) => setTimeout(resolve, statusRetryDelay));
30418
+ openOrder = await this.getOrderStatus(
30419
+ positionId,
30420
+ this.config.extendedMarketName
30421
+ );
30422
+ if (openOrder) {
30423
+ logger.info(
30424
+ `Order ${positionId} found after ${statusRetry} status retry(ies)`
30425
+ );
30426
+ break;
30427
+ }
30428
+ logger.warn(
30429
+ `Order ${positionId} still not found after ${statusRetry}/${maxStatusRetries} status retries`
30430
+ );
30431
+ }
30432
+ }
30433
+ if (openOrder && openOrder.status === "FILLED" /* FILLED */) {
30434
+ logger.info(
30435
+ `Order ${positionId} successfully filled with quantity ${openOrder.qty}`
30436
+ );
30437
+ return {
30438
+ position_id: positionId,
30439
+ btc_exposure: openOrder.qty
30440
+ };
30441
+ } else if (openOrder && openOrder.status !== "FILLED" /* FILLED */) {
30442
+ logger.warn(
30443
+ `Order ${positionId} found but status is ${openOrder.status}, not FILLED. Retrying order creation...`
30444
+ );
29993
30445
  if (attempt >= maxAttempts) {
29994
- logger.error("Max retries reached \u2014 could not verify open position");
30446
+ logger.error(
30447
+ `Max retries reached \u2014 order ${positionId} status is ${openOrder.status}, not FILLED`
30448
+ );
29995
30449
  return null;
29996
30450
  } else {
29997
30451
  const backoff = 2e3 * attempt;
@@ -30005,13 +30459,18 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
30005
30459
  );
30006
30460
  }
30007
30461
  } else {
30462
+ logger.warn(
30463
+ `Order ${positionId} not found in API after ${maxStatusRetries} status retries (API update delayed ~30s). We got position_id from creation, so order exists. Returning position_id - status will be checked in next loop iteration.`
30464
+ );
30008
30465
  return {
30009
- position_id: result.position_id,
30010
- btc_exposure: openOrder.qty
30466
+ position_id: positionId,
30467
+ btc_exposure: amount_in_token
30011
30468
  };
30012
30469
  }
30013
30470
  } catch (err) {
30014
- logger.error(`createShortOrder failed on attempt ${attempt}: ${err.message}`);
30471
+ logger.error(
30472
+ `createShortOrder failed on attempt ${attempt}: ${err.message}`
30473
+ );
30015
30474
  if (attempt < maxAttempts) {
30016
30475
  const backoff = 1200 * attempt;
30017
30476
  logger.info(`Retrying after ${backoff}ms...`);
@@ -30050,28 +30509,101 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
30050
30509
  }
30051
30510
  }
30052
30511
  async getDepositOrWithdrawalStatus(orderId, operationsType) {
30053
- try {
30054
- let transferHistory = await this.client.getAssetOperations({
30055
- operationsType: [operationsType],
30056
- operationsStatus: ["COMPLETED" /* COMPLETED */]
30057
- });
30058
- if (operationsType === "DEPOSIT" /* DEPOSIT */) {
30059
- const myTransferStatus = transferHistory.data.find((operation) => operation.transactionHash === orderId);
30060
- if (!myTransferStatus) {
30061
- return true;
30512
+ const maxAttempts = 15;
30513
+ const retryDelayMs = 3e4;
30514
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
30515
+ try {
30516
+ let transferHistory = await this.client.getAssetOperations({
30517
+ operationsType: [operationsType],
30518
+ operationsStatus: ["COMPLETED" /* COMPLETED */]
30519
+ });
30520
+ if (operationsType === "DEPOSIT" /* DEPOSIT */) {
30521
+ const myTransferStatus = transferHistory.data.find(
30522
+ (operation) => operation.transactionHash?.toLowerCase() === orderId.toString().toLowerCase()
30523
+ );
30524
+ if (!myTransferStatus) {
30525
+ if (attempt < maxAttempts) {
30526
+ logger.info(
30527
+ `Deposit operation not found for transactionHash ${orderId}, retrying (attempt ${attempt}/${maxAttempts})...`
30528
+ );
30529
+ await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
30530
+ continue;
30531
+ }
30532
+ logger.warn(
30533
+ `Deposit operation not found for transactionHash ${orderId} after ${maxAttempts} attempts`
30534
+ );
30535
+ return false;
30536
+ }
30537
+ if (myTransferStatus.status === "COMPLETED" /* COMPLETED */) {
30538
+ logger.info(
30539
+ `Deposit operation ${orderId} completed successfully`
30540
+ );
30541
+ return true;
30542
+ } else {
30543
+ if (attempt < maxAttempts) {
30544
+ logger.info(
30545
+ `Deposit operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`
30546
+ );
30547
+ await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
30548
+ continue;
30549
+ }
30550
+ logger.warn(
30551
+ `Deposit operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`
30552
+ );
30553
+ return false;
30554
+ }
30555
+ } else {
30556
+ const myTransferStatus = transferHistory.data.find(
30557
+ (operation) => operation.id === orderId.toString()
30558
+ );
30559
+ if (!myTransferStatus) {
30560
+ if (attempt < maxAttempts) {
30561
+ logger.info(
30562
+ `Withdrawal status not found for orderId ${orderId} in completed operations, retrying (attempt ${attempt}/${maxAttempts})...`
30563
+ );
30564
+ await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
30565
+ continue;
30566
+ }
30567
+ logger.warn(
30568
+ `Withdrawal operation not found for orderId ${orderId} after ${maxAttempts} attempts`
30569
+ );
30570
+ return false;
30571
+ }
30572
+ if (myTransferStatus.status === "COMPLETED" /* COMPLETED */) {
30573
+ logger.info(
30574
+ `Withdrawal operation ${orderId} completed successfully`
30575
+ );
30576
+ return true;
30577
+ } else {
30578
+ if (attempt < maxAttempts) {
30579
+ logger.info(
30580
+ `Withdrawal operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`
30581
+ );
30582
+ await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
30583
+ continue;
30584
+ }
30585
+ logger.warn(
30586
+ `Withdrawal operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`
30587
+ );
30588
+ return false;
30589
+ }
30062
30590
  }
30063
- return true;
30064
- } else {
30065
- const myTransferStatus = transferHistory.data.find((operation) => operation.id.toString() === orderId.toString());
30066
- if (!myTransferStatus) {
30067
- return true;
30591
+ } catch (err) {
30592
+ logger.error(
30593
+ `error getting deposit or withdrawal status (attempt ${attempt}/${maxAttempts}): ${err}`
30594
+ );
30595
+ if (attempt < maxAttempts) {
30596
+ logger.info(`Retrying after ${retryDelayMs}ms...`);
30597
+ await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
30598
+ continue;
30068
30599
  }
30069
- return true;
30600
+ logger.error(
30601
+ `Max retry attempts reached for getDepositOrWithdrawalStatus`
30602
+ );
30603
+ return false;
30070
30604
  }
30071
- } catch (err) {
30072
- logger.error(`error getting deposit or withdrawal status: ${err}`);
30073
- return false;
30074
30605
  }
30606
+ return false;
30075
30607
  }
30076
30608
  };
30077
30609
 
@@ -30151,12 +30683,351 @@ var UnusedBalanceAdapter = class _UnusedBalanceAdapter extends BaseAdapter {
30151
30683
  }
30152
30684
  };
30153
30685
 
30686
+ // src/strategies/universal-adapters/avnu-adapter.ts
30687
+ var import_starknet23 = require("starknet");
30688
+ var import_axios9 = __toESM(require("axios"));
30689
+ var AvnuAdapter = class _AvnuAdapter extends BaseAdapter {
30690
+ constructor(config) {
30691
+ super(config, _AvnuAdapter.name, Protocols.AVNU);
30692
+ this.config = config;
30693
+ this.avnuWrapper = new AvnuWrapper();
30694
+ }
30695
+ //abstract means the method has no implementation in this class; instead, child classes must implement it.
30696
+ async getAPY(supportedPosition) {
30697
+ return Promise.resolve({ apy: 0, type: "base" /* BASE */ });
30698
+ }
30699
+ async getPosition(supportedPosition) {
30700
+ return Promise.resolve({ amount: new Web3Number(0, 0), remarks: "Avnu Positions" });
30701
+ }
30702
+ async maxDeposit(amount) {
30703
+ return Promise.resolve({
30704
+ tokenInfo: this.config.baseToken,
30705
+ amount: new Web3Number(0, 0),
30706
+ usdValue: 0,
30707
+ apy: { apy: 0, type: "base" /* BASE */ },
30708
+ protocol: Protocols.AVNU,
30709
+ remarks: ""
30710
+ });
30711
+ }
30712
+ async maxWithdraw() {
30713
+ return Promise.resolve({
30714
+ tokenInfo: this.config.baseToken,
30715
+ amount: new Web3Number(0, 0),
30716
+ usdValue: 0,
30717
+ apy: { apy: 0, type: "base" /* BASE */ },
30718
+ protocol: Protocols.AVNU,
30719
+ remarks: ""
30720
+ });
30721
+ }
30722
+ _getDepositLeaf() {
30723
+ const vaultAllocator = ContractAddr.from(
30724
+ this.config.vaultAllocator.address
30725
+ );
30726
+ return [
30727
+ {
30728
+ target: this.config.supportedPositions[0].asset.address,
30729
+ method: "approve",
30730
+ packedArguments: [
30731
+ AVNU_EXCHANGE.toBigInt()
30732
+ ],
30733
+ sanitizer: SIMPLE_SANITIZER,
30734
+ id: `approve_${this.config.supportedPositions[0].asset.symbol}`
30735
+ },
30736
+ {
30737
+ target: AVNU_EXCHANGE,
30738
+ method: "multi_route_swap",
30739
+ packedArguments: [
30740
+ this.config.supportedPositions[0].asset.address.toBigInt(),
30741
+ //usdc
30742
+ this.config.supportedPositions[1].asset.address.toBigInt(),
30743
+ //wbtc
30744
+ vaultAllocator.toBigInt()
30745
+ ],
30746
+ sanitizer: SIMPLE_SANITIZER,
30747
+ id: `asutb_${this.config.supportedPositions[0].asset.symbol}_${this.config.supportedPositions[1].asset.symbol}`
30748
+ }
30749
+ ];
30750
+ }
30751
+ _getWithdrawLeaf() {
30752
+ const vaultAllocator = ContractAddr.from(
30753
+ this.config.vaultAllocator.address
30754
+ );
30755
+ const toToken = this.config.supportedPositions[0].asset;
30756
+ const fromToken = this.config.supportedPositions[1].asset;
30757
+ return [
30758
+ {
30759
+ target: fromToken.address,
30760
+ method: "approve",
30761
+ packedArguments: [
30762
+ AVNU_EXCHANGE.toBigInt()
30763
+ ],
30764
+ sanitizer: SIMPLE_SANITIZER,
30765
+ id: `approve_${fromToken.symbol}`
30766
+ },
30767
+ {
30768
+ target: AVNU_EXCHANGE,
30769
+ method: "multi_route_swap",
30770
+ packedArguments: [
30771
+ fromToken.address.toBigInt(),
30772
+ //wbtc
30773
+ toToken.address.toBigInt(),
30774
+ //usdc
30775
+ vaultAllocator.toBigInt()
30776
+ ],
30777
+ sanitizer: SIMPLE_SANITIZER,
30778
+ id: `asbtu_${fromToken.symbol}_${fromToken.symbol}`
30779
+ }
30780
+ ];
30781
+ }
30782
+ _getLegacySwapLeaf() {
30783
+ return [];
30784
+ }
30785
+ async getDepositCall(params) {
30786
+ try {
30787
+ const fromToken = this.config.supportedPositions[0].asset;
30788
+ const toToken = this.config.supportedPositions[1].asset;
30789
+ const vaultAllocator = ContractAddr.from(
30790
+ this.config.vaultAllocator.address
30791
+ );
30792
+ const quote = await this.getQuotesAvnu(
30793
+ fromToken.address.toString(),
30794
+ toToken.address.toString(),
30795
+ params.amount.toNumber(),
30796
+ vaultAllocator.address.toString(),
30797
+ toToken.decimals,
30798
+ true
30799
+ );
30800
+ if (!quote) {
30801
+ logger.error("error getting quote from avnu");
30802
+ return [];
30803
+ }
30804
+ const getCalldata = await this.avnuWrapper.getSwapCallData(
30805
+ quote,
30806
+ vaultAllocator.address
30807
+ );
30808
+ const swapCallData = getCalldata[0];
30809
+ const amount = import_starknet23.uint256.bnToUint256(quote.sellAmountInUsd * 10 ** 7);
30810
+ return [
30811
+ {
30812
+ sanitizer: SIMPLE_SANITIZER,
30813
+ call: {
30814
+ contractAddress: fromToken.address,
30815
+ selector: import_starknet23.hash.getSelectorFromName("approve"),
30816
+ calldata: [
30817
+ AVNU_EXCHANGE.toBigInt(),
30818
+ toBigInt(amount.low.toString()),
30819
+ // amount low
30820
+ toBigInt(amount.high.toString())
30821
+ // amount high
30822
+ ]
30823
+ }
30824
+ },
30825
+ {
30826
+ sanitizer: SIMPLE_SANITIZER,
30827
+ call: {
30828
+ contractAddress: AVNU_EXCHANGE,
30829
+ selector: import_starknet23.hash.getSelectorFromName("multi_route_swap"),
30830
+ calldata: swapCallData
30831
+ }
30832
+ }
30833
+ ];
30834
+ } catch (error) {
30835
+ logger.error(`Error getting Avnu quote: ${error}`);
30836
+ return [];
30837
+ }
30838
+ }
30839
+ //Swap wbtc to usdc
30840
+ async getWithdrawCall(params) {
30841
+ try {
30842
+ const toToken = this.config.supportedPositions[0].asset;
30843
+ const fromToken = this.config.supportedPositions[1].asset;
30844
+ const vaultAllocator = ContractAddr.from(
30845
+ this.config.vaultAllocator.address
30846
+ );
30847
+ const quote = await this.getQuotesAvnu(
30848
+ fromToken.address.toString(),
30849
+ toToken.address.toString(),
30850
+ params.amount.toNumber(),
30851
+ vaultAllocator.address.toString(),
30852
+ fromToken.decimals,
30853
+ false
30854
+ );
30855
+ if (!quote) {
30856
+ logger.error("No quotes available for this swap, error in quotes avnu");
30857
+ return [];
30858
+ }
30859
+ const getCalldata = await this.avnuWrapper.getSwapCallData(
30860
+ quote,
30861
+ vaultAllocator.address
30862
+ );
30863
+ const swapCallData = getCalldata[0];
30864
+ const amount = import_starknet23.uint256.bnToUint256(params.amount.toWei());
30865
+ return [
30866
+ {
30867
+ sanitizer: SIMPLE_SANITIZER,
30868
+ call: {
30869
+ contractAddress: fromToken.address,
30870
+ selector: import_starknet23.hash.getSelectorFromName("approve"),
30871
+ calldata: [
30872
+ AVNU_EXCHANGE.toBigInt(),
30873
+ toBigInt(amount.low.toString()),
30874
+ // amount low
30875
+ toBigInt(amount.high.toString())
30876
+ // amount high
30877
+ ]
30878
+ }
30879
+ },
30880
+ {
30881
+ sanitizer: SIMPLE_SANITIZER,
30882
+ call: {
30883
+ contractAddress: AVNU_EXCHANGE,
30884
+ selector: import_starknet23.hash.getSelectorFromName("multi_route_swap"),
30885
+ calldata: swapCallData
30886
+ }
30887
+ }
30888
+ ];
30889
+ } catch (error) {
30890
+ logger.error(`Error getting Avnu quote: ${error}`);
30891
+ return [];
30892
+ }
30893
+ }
30894
+ async getSwapCallData(quote) {
30895
+ return await this.avnuWrapper.getSwapCallData(quote, this.config.vaultAllocator.address);
30896
+ }
30897
+ async getHealthFactor() {
30898
+ return Promise.resolve(1);
30899
+ }
30900
+ async fetchQuoteWithRetry(params, retries = 5) {
30901
+ for (let attempt = 0; attempt < retries; attempt++) {
30902
+ try {
30903
+ const response = await import_axios9.default.get(this.config.baseUrl, { params });
30904
+ if (response.data && response.data.length > 0) {
30905
+ return response;
30906
+ }
30907
+ throw new Error("Empty response data");
30908
+ } catch (err) {
30909
+ logger.error(`Error fetching quote with retry: ${err}`);
30910
+ if (attempt === retries - 1) {
30911
+ throw err;
30912
+ }
30913
+ await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
30914
+ }
30915
+ }
30916
+ throw new Error("Failed to fetch quote after retries");
30917
+ }
30918
+ async getQuotesAvnu(from_token_address, to_token_address, amount, takerAddress, toTokenDecimals, usdcToBtc, maxIterations = 5, tolerance = 5e3) {
30919
+ try {
30920
+ const fromToken = this.config.supportedPositions[0].asset;
30921
+ const toToken = this.config.supportedPositions[1].asset;
30922
+ if (!usdcToBtc) {
30923
+ const sellAmount2 = returnFormattedAmount(amount, toTokenDecimals);
30924
+ const params2 = {
30925
+ sellTokenAddress: from_token_address,
30926
+ buyTokenAddress: to_token_address,
30927
+ takerAddress,
30928
+ sellAmount: sellAmount2
30929
+ };
30930
+ const finalQuote2 = await this.fetchQuoteWithRetry(params2);
30931
+ if (!finalQuote2.data.length) {
30932
+ logger.error("No quotes available for this swap, error in quotes avnu");
30933
+ return null;
30934
+ }
30935
+ const dataObject2 = finalQuote2.data[0];
30936
+ return dataObject2;
30937
+ }
30938
+ const btcPrice = await this.getPriceOfToken(toToken.address.toString());
30939
+ if (!btcPrice) {
30940
+ logger.error(`error getting btc price: ${btcPrice}`);
30941
+ return null;
30942
+ }
30943
+ const estimatedUsdcAmount = Math.floor(amount * btcPrice);
30944
+ logger.info(`${_AvnuAdapter.name}::getQuotesAvnu estimatedUsdcAmount: ${estimatedUsdcAmount}`);
30945
+ const targetBtcBig = BigInt(returnFormattedAmount(amount, toTokenDecimals));
30946
+ logger.info(`${_AvnuAdapter.name}::getQuotesAvnu targetBtcBig: ${targetBtcBig}`);
30947
+ let low = BigInt(
30948
+ Math.floor(
30949
+ estimatedUsdcAmount * 10 ** fromToken.decimals * 0.9
30950
+ )
30951
+ );
30952
+ let high = BigInt(
30953
+ Math.floor(
30954
+ estimatedUsdcAmount * 10 ** fromToken.decimals * 1.1
30955
+ )
30956
+ );
30957
+ let mid = 0n;
30958
+ for (let i = 0; i < maxIterations; i++) {
30959
+ mid = (low + high) / 2n;
30960
+ const sellAmount2 = returnFormattedAmount(Number(mid), 0);
30961
+ const quote = await this.fetchQuoteWithRetry({
30962
+ sellTokenAddress: from_token_address,
30963
+ buyTokenAddress: to_token_address,
30964
+ takerAddress,
30965
+ sellAmount: sellAmount2
30966
+ });
30967
+ const gotBtc = BigInt(quote.data[0].buyAmount);
30968
+ if (gotBtc === targetBtcBig) return quote.data[0];
30969
+ if (gotBtc > targetBtcBig) {
30970
+ high = mid;
30971
+ } else {
30972
+ low = mid;
30973
+ }
30974
+ if (gotBtc >= targetBtcBig && gotBtc <= targetBtcBig + BigInt(tolerance)) {
30975
+ return quote.data[0];
30976
+ }
30977
+ }
30978
+ let sellAmount = returnFormattedAmount(
30979
+ Number(mid),
30980
+ 0
30981
+ );
30982
+ const params = {
30983
+ sellTokenAddress: from_token_address,
30984
+ buyTokenAddress: to_token_address,
30985
+ takerAddress,
30986
+ sellAmount
30987
+ };
30988
+ const finalQuote = await this.fetchQuoteWithRetry(params);
30989
+ if (!finalQuote.data.length) {
30990
+ logger.error("No quotes available for this swap, error in quotes avnu");
30991
+ return null;
30992
+ }
30993
+ const dataObject = finalQuote.data[0];
30994
+ const wbtcAmountOut = parseInt(dataObject.buyAmount.toString(), 16);
30995
+ logger.info(`${_AvnuAdapter.name}::getQuotesAvnu finalAmountOfWbtcOut : ${wbtcAmountOut} ${dataObject.buyAmount} ${dataObject.sellAmount.toString()} ${dataObject.sellAmount.toString()}`);
30996
+ return dataObject;
30997
+ } catch (err) {
30998
+ logger.error(`No quotes available for this swap: ${err}`);
30999
+ return null;
31000
+ }
31001
+ }
31002
+ async getPriceOfToken(tokenAddress, retries = MAX_RETRIES) {
31003
+ try {
31004
+ const url = `https://starknet.impulse.avnu.fi/v1/tokens/${tokenAddress}/prices/line`;
31005
+ const response = await import_axios9.default.get(url);
31006
+ const length = response.data.length;
31007
+ return response.data[length - 1].value;
31008
+ } catch (err) {
31009
+ if (retries > 0) {
31010
+ await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
31011
+ return this.getPriceOfToken(tokenAddress, retries - 1);
31012
+ } else {
31013
+ logger.error(`Failed to fetch price for ${tokenAddress} after ${MAX_RETRIES} attempts`);
31014
+ return null;
31015
+ }
31016
+ }
31017
+ }
31018
+ };
31019
+
30154
31020
  // src/strategies/universal-strategy.tsx
30155
31021
  var AUMTypes = /* @__PURE__ */ ((AUMTypes2) => {
30156
31022
  AUMTypes2["FINALISED"] = "finalised";
30157
31023
  AUMTypes2["DEFISPRING"] = "defispring";
30158
31024
  return AUMTypes2;
30159
31025
  })(AUMTypes || {});
31026
+ var PositionTypeAvnuExtended = /* @__PURE__ */ ((PositionTypeAvnuExtended2) => {
31027
+ PositionTypeAvnuExtended2["OPEN"] = "open";
31028
+ PositionTypeAvnuExtended2["CLOSE"] = "close";
31029
+ return PositionTypeAvnuExtended2;
31030
+ })(PositionTypeAvnuExtended || {});
30160
31031
  var UNIVERSAL_MANAGE_IDS = /* @__PURE__ */ ((UNIVERSAL_MANAGE_IDS2) => {
30161
31032
  UNIVERSAL_MANAGE_IDS2["FLASH_LOAN"] = "flash_loan_init";
30162
31033
  UNIVERSAL_MANAGE_IDS2["VESU_LEG1"] = "vesu_leg1";
@@ -30184,7 +31055,7 @@ function getContractDetails(settings) {
30184
31055
  }
30185
31056
 
30186
31057
  // src/strategies/svk-strategy.ts
30187
- var import_starknet23 = require("starknet");
31058
+ var import_starknet24 = require("starknet");
30188
31059
 
30189
31060
  // src/data/universal-vault.abi.json
30190
31061
  var universal_vault_abi_default = [
@@ -32511,12 +33382,12 @@ var SVKStrategy = class extends BaseStrategy {
32511
33382
  this.pricer = pricer;
32512
33383
  this.metadata = metadata;
32513
33384
  this.address = metadata.address;
32514
- this.contract = new import_starknet23.Contract({
33385
+ this.contract = new import_starknet24.Contract({
32515
33386
  abi: universal_vault_abi_default,
32516
33387
  address: this.address.address,
32517
33388
  providerOrAccount: this.config.provider
32518
33389
  });
32519
- this.managerContract = new import_starknet23.Contract({
33390
+ this.managerContract = new import_starknet24.Contract({
32520
33391
  abi: vault_manager_abi_default,
32521
33392
  address: this.metadata.additionalInfo.manager.address,
32522
33393
  providerOrAccount: this.config.provider
@@ -32629,7 +33500,7 @@ var SVKStrategy = class extends BaseStrategy {
32629
33500
  getSetManagerCall(strategist, root = this.getMerkleRoot()) {
32630
33501
  return this.managerContract.populate("set_manage_root", [
32631
33502
  strategist.address,
32632
- import_starknet23.num.getHexString(root)
33503
+ import_starknet24.num.getHexString(root)
32633
33504
  ]);
32634
33505
  }
32635
33506
  /**
@@ -33337,7 +34208,8 @@ function getLooperSettings(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
33337
34208
  minHealthFactor: vaultSettings.minHealthFactor,
33338
34209
  quoteAmountToFetchPrice: vaultSettings.quoteAmountToFetchPrice,
33339
34210
  ...baseAdapterConfig,
33340
- supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }]
34211
+ supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }],
34212
+ minimumVesuMovementAmount: 0
33341
34213
  }));
33342
34214
  const unusedBalanceAdapter = new UnusedBalanceAdapter({
33343
34215
  ...baseAdapterConfig
@@ -33566,335 +34438,15 @@ var HyperLSTStrategies = [
33566
34438
  getStrategySettings("mRe7YIELD", "mRe7YIELD", hypermRe7YIELD, false, false)
33567
34439
  ];
33568
34440
 
33569
- // src/strategies/universal-adapters/avnu-adapter.ts
33570
- var import_starknet24 = require("starknet");
33571
- var import_axios9 = __toESM(require("axios"));
33572
- var AvnuAdapter = class _AvnuAdapter extends BaseAdapter {
33573
- constructor(config) {
33574
- super(config, _AvnuAdapter.name, Protocols.AVNU);
33575
- this.config = config;
33576
- this.avnuWrapper = new AvnuWrapper();
33577
- }
33578
- //abstract means the method has no implementation in this class; instead, child classes must implement it.
33579
- async getAPY(supportedPosition) {
33580
- return Promise.resolve({ apy: 0, type: "base" /* BASE */ });
33581
- }
33582
- async getPosition(supportedPosition) {
33583
- return Promise.resolve({ amount: new Web3Number(0, 0), remarks: "" });
33584
- }
33585
- async maxDeposit(amount) {
33586
- return Promise.resolve({
33587
- tokenInfo: this.config.baseToken,
33588
- amount: new Web3Number(0, 0),
33589
- usdValue: 0,
33590
- apy: { apy: 0, type: "base" /* BASE */ },
33591
- protocol: Protocols.AVNU,
33592
- remarks: ""
33593
- });
33594
- }
33595
- async maxWithdraw() {
33596
- return Promise.resolve({
33597
- tokenInfo: this.config.baseToken,
33598
- amount: new Web3Number(0, 0),
33599
- usdValue: 0,
33600
- apy: { apy: 0, type: "base" /* BASE */ },
33601
- protocol: Protocols.AVNU,
33602
- remarks: ""
33603
- });
33604
- }
33605
- _getDepositLeaf() {
33606
- const vaultAllocator = ContractAddr.from(
33607
- this.config.vaultAllocator.address
33608
- );
33609
- return [
33610
- {
33611
- target: this.config.supportedPositions[0].asset.address,
33612
- method: "approve",
33613
- packedArguments: [
33614
- AVNU_EXCHANGE.toBigInt()
33615
- ],
33616
- sanitizer: SIMPLE_SANITIZER,
33617
- id: `approve_${this.config.supportedPositions[0].asset.symbol}`
33618
- },
33619
- {
33620
- target: AVNU_EXCHANGE,
33621
- method: "multi_route_swap",
33622
- packedArguments: [
33623
- this.config.supportedPositions[0].asset.address.toBigInt(),
33624
- //usdc
33625
- this.config.supportedPositions[1].asset.address.toBigInt(),
33626
- //wbtc
33627
- vaultAllocator.toBigInt()
33628
- ],
33629
- sanitizer: SIMPLE_SANITIZER,
33630
- id: `asutb_${this.config.supportedPositions[0].asset.symbol}_${this.config.supportedPositions[1].asset.symbol}`
33631
- }
33632
- ];
33633
- }
33634
- _getWithdrawLeaf() {
33635
- const vaultAllocator = ContractAddr.from(
33636
- this.config.vaultAllocator.address
33637
- );
33638
- const toToken = this.config.supportedPositions[0].asset;
33639
- const fromToken = this.config.supportedPositions[1].asset;
33640
- return [
33641
- {
33642
- target: fromToken.address,
33643
- method: "approve",
33644
- packedArguments: [
33645
- AVNU_EXCHANGE.toBigInt()
33646
- ],
33647
- sanitizer: SIMPLE_SANITIZER,
33648
- id: `approve_${fromToken.symbol}`
33649
- },
33650
- {
33651
- target: AVNU_EXCHANGE,
33652
- method: "multi_route_swap",
33653
- packedArguments: [
33654
- fromToken.address.toBigInt(),
33655
- //wbtc
33656
- toToken.address.toBigInt(),
33657
- //usdc
33658
- vaultAllocator.toBigInt()
33659
- ],
33660
- sanitizer: SIMPLE_SANITIZER,
33661
- id: `asbtu_${fromToken.symbol}_${fromToken.symbol}`
33662
- }
33663
- ];
33664
- }
33665
- _getLegacySwapLeaf() {
33666
- return [];
33667
- }
33668
- async getDepositCall(params) {
33669
- try {
33670
- const fromToken = this.config.supportedPositions[0].asset;
33671
- const toToken = this.config.supportedPositions[1].asset;
33672
- const vaultAllocator = ContractAddr.from(
33673
- this.config.vaultAllocator.address
33674
- );
33675
- const quote = await this.getQuotesAvnu(
33676
- fromToken.address.toString(),
33677
- toToken.address.toString(),
33678
- params.amount.toNumber(),
33679
- vaultAllocator.address.toString(),
33680
- toToken.decimals,
33681
- true
33682
- );
33683
- if (!quote) {
33684
- logger.error("error getting quote from avnu");
33685
- return [];
33686
- }
33687
- const getCalldata = await this.avnuWrapper.getSwapCallData(
33688
- quote,
33689
- vaultAllocator.address
33690
- );
33691
- const swapCallData = getCalldata[0];
33692
- const amount = import_starknet24.uint256.bnToUint256(quote.sellAmountInUsd * 10 ** 7);
33693
- return [
33694
- {
33695
- sanitizer: SIMPLE_SANITIZER,
33696
- call: {
33697
- contractAddress: fromToken.address,
33698
- selector: import_starknet24.hash.getSelectorFromName("approve"),
33699
- calldata: [
33700
- AVNU_EXCHANGE.toBigInt(),
33701
- toBigInt(amount.low.toString()),
33702
- // amount low
33703
- toBigInt(amount.high.toString())
33704
- // amount high
33705
- ]
33706
- }
33707
- },
33708
- {
33709
- sanitizer: SIMPLE_SANITIZER,
33710
- call: {
33711
- contractAddress: AVNU_EXCHANGE,
33712
- selector: import_starknet24.hash.getSelectorFromName("multi_route_swap"),
33713
- calldata: swapCallData
33714
- }
33715
- }
33716
- ];
33717
- } catch (error) {
33718
- logger.error(`Error getting Avnu quote: ${error}`);
33719
- return [];
33720
- }
33721
- }
33722
- //Swap wbtc to usdc
33723
- async getWithdrawCall(params) {
33724
- try {
33725
- const toToken = this.config.supportedPositions[0].asset;
33726
- const fromToken = this.config.supportedPositions[1].asset;
33727
- const vaultAllocator = ContractAddr.from(
33728
- this.config.vaultAllocator.address
33729
- );
33730
- const quote = await this.getQuotesAvnu(
33731
- fromToken.address.toString(),
33732
- toToken.address.toString(),
33733
- params.amount.toNumber(),
33734
- vaultAllocator.address.toString(),
33735
- fromToken.decimals,
33736
- false
33737
- );
33738
- if (!quote) {
33739
- logger.error("No quotes available for this swap, error in quotes avnu");
33740
- return [];
33741
- }
33742
- const getCalldata = await this.avnuWrapper.getSwapCallData(
33743
- quote,
33744
- vaultAllocator.address
33745
- );
33746
- const swapCallData = getCalldata[0];
33747
- const amount = import_starknet24.uint256.bnToUint256(params.amount.toWei());
33748
- return [
33749
- {
33750
- sanitizer: SIMPLE_SANITIZER,
33751
- call: {
33752
- contractAddress: fromToken.address,
33753
- selector: import_starknet24.hash.getSelectorFromName("approve"),
33754
- calldata: [
33755
- AVNU_EXCHANGE.toBigInt(),
33756
- toBigInt(amount.low.toString()),
33757
- // amount low
33758
- toBigInt(amount.high.toString())
33759
- // amount high
33760
- ]
33761
- }
33762
- },
33763
- {
33764
- sanitizer: SIMPLE_SANITIZER,
33765
- call: {
33766
- contractAddress: AVNU_EXCHANGE,
33767
- selector: import_starknet24.hash.getSelectorFromName("multi_route_swap"),
33768
- calldata: swapCallData
33769
- }
33770
- }
33771
- ];
33772
- } catch (error) {
33773
- logger.error(`Error getting Avnu quote: ${error}`);
33774
- return [];
33775
- }
33776
- }
33777
- async getSwapCallData(quote) {
33778
- return await this.avnuWrapper.getSwapCallData(quote, this.config.vaultAllocator.address);
33779
- }
33780
- async getHealthFactor() {
33781
- return Promise.resolve(1);
33782
- }
33783
- async fetchQuoteWithRetry(params, retries = 5) {
33784
- for (let attempt = 0; attempt < retries; attempt++) {
33785
- try {
33786
- const response = await import_axios9.default.get(this.config.baseUrl, { params });
33787
- if (response.data && response.data.length > 0) {
33788
- return response;
33789
- }
33790
- throw new Error("Empty response data");
33791
- } catch (err) {
33792
- logger.error(`Error fetching quote with retry: ${err}`);
33793
- if (attempt === retries - 1) {
33794
- throw err;
33795
- }
33796
- await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
33797
- }
33798
- }
33799
- throw new Error("Failed to fetch quote after retries");
33800
- }
33801
- async getQuotesAvnu(from_token_address, to_token_address, amount, takerAddress, toTokenDecimals, usdcToBtc, maxIterations = 5, tolerance = 1e4) {
33802
- try {
33803
- const fromToken = this.config.supportedPositions[0].asset;
33804
- const toToken = this.config.supportedPositions[1].asset;
33805
- if (!usdcToBtc) {
33806
- const sellAmount2 = returnFormattedAmount(amount, toTokenDecimals);
33807
- const params2 = {
33808
- sellTokenAddress: from_token_address,
33809
- buyTokenAddress: to_token_address,
33810
- takerAddress,
33811
- sellAmount: sellAmount2
33812
- };
33813
- const finalQuote2 = await this.fetchQuoteWithRetry(params2);
33814
- if (!finalQuote2.data.length) {
33815
- logger.error("No quotes available for this swap, error in quotes avnu");
33816
- return null;
33817
- }
33818
- const dataObject2 = finalQuote2.data[0];
33819
- return dataObject2;
33820
- }
33821
- const btcPrice = await this.getPriceOfToken(toToken.address.toString());
33822
- if (!btcPrice) {
33823
- logger.error(`error getting btc price: ${btcPrice}`);
33824
- return null;
33825
- }
33826
- const estimatedUsdcAmount = Math.floor(amount * btcPrice);
33827
- const targetBtcBig = BigInt(returnFormattedAmount(amount, toTokenDecimals));
33828
- let low = BigInt(
33829
- Math.floor(
33830
- estimatedUsdcAmount * 10 ** fromToken.decimals * 0.9
33831
- )
33832
- );
33833
- let high = BigInt(
33834
- Math.floor(
33835
- estimatedUsdcAmount * 10 ** fromToken.decimals * 1.1
33836
- )
33837
- );
33838
- let mid = 0n;
33839
- for (let i = 0; i < maxIterations; i++) {
33840
- mid = (low + high) / 2n;
33841
- const sellAmount2 = returnFormattedAmount(Number(mid), 0);
33842
- const quote = await this.fetchQuoteWithRetry({
33843
- sellTokenAddress: from_token_address,
33844
- buyTokenAddress: to_token_address,
33845
- takerAddress,
33846
- sellAmount: sellAmount2
33847
- });
33848
- const gotBtc = BigInt(quote.data[0].buyAmount);
33849
- if (gotBtc === targetBtcBig) return quote.data[0];
33850
- if (gotBtc > targetBtcBig) {
33851
- high = mid;
33852
- } else {
33853
- low = mid;
33854
- }
33855
- if (gotBtc >= targetBtcBig && gotBtc <= targetBtcBig + BigInt(tolerance)) {
33856
- return quote.data[0];
33857
- }
33858
- }
33859
- let sellAmount = returnFormattedAmount(
33860
- Number(mid),
33861
- 0
33862
- );
33863
- const params = {
33864
- sellTokenAddress: from_token_address,
33865
- buyTokenAddress: to_token_address,
33866
- takerAddress,
33867
- sellAmount
33868
- };
33869
- const finalQuote = await this.fetchQuoteWithRetry(params);
33870
- if (!finalQuote.data.length) {
33871
- logger.error("No quotes available for this swap, error in quotes avnu");
33872
- return null;
33873
- }
33874
- const dataObject = finalQuote.data[0];
33875
- return dataObject;
33876
- } catch (err) {
33877
- logger.error(`No quotes available for this swap: ${err}`);
33878
- return null;
33879
- }
33880
- }
33881
- async getPriceOfToken(tokenAddress, retries = MAX_RETRIES) {
33882
- try {
33883
- const url = `https://starknet.impulse.avnu.fi/v1/tokens/${tokenAddress}/prices/line`;
33884
- const response = await import_axios9.default.get(url);
33885
- const length = response.data.length;
33886
- return response.data[length - 1].value;
33887
- } catch (err) {
33888
- if (retries > 0) {
33889
- await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
33890
- return this.getPriceOfToken(tokenAddress, retries - 1);
33891
- } else {
33892
- logger.error(`Failed to fetch price for ${tokenAddress} after ${MAX_RETRIES} attempts`);
33893
- return null;
33894
- }
33895
- }
33896
- }
33897
- };
34441
+ // src/strategies/vesu-extended-strategy/types/transaction-metadata.ts
34442
+ var CycleType = /* @__PURE__ */ ((CycleType2) => {
34443
+ CycleType2["INVESTMENT"] = "INVESTMENT";
34444
+ CycleType2["REBALANCE_PRICE_DROP"] = "REBALANCE_PRICE_DROP";
34445
+ CycleType2["REBALANCE_PRICE_RISE"] = "REBALANCE_PRICE_RISE";
34446
+ CycleType2["WITHDRAWAL"] = "WITHDRAWAL";
34447
+ CycleType2["DELTA_NEUTRAL_ADJUSTMENT"] = "DELTA_NEUTRAL_ADJUSTMENT";
34448
+ return CycleType2;
34449
+ })(CycleType || {});
33898
34450
 
33899
34451
  // src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx
33900
34452
  var import_jsx_runtime5 = require("react/jsx-runtime");
@@ -33994,15 +34546,30 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
33994
34546
  const usdceToken = Global.getDefaultTokens().find(
33995
34547
  (token) => token.symbol === "USDCe"
33996
34548
  );
34549
+ const walletBalance = await new ERC20(this.config).balanceOf(
34550
+ usdceToken.address,
34551
+ WALLET_ADDRESS,
34552
+ usdceToken.decimals
34553
+ );
34554
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssetsToVaultAllocator walletBalance: ${walletBalance}`);
34555
+ const amountToBeTransferred = amount.minimum(walletBalance);
34556
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssetsToVaultAllocator amountToBeTransferred: ${amountToBeTransferred.toNumber()}`);
34557
+ if (amountToBeTransferred.lessThan(0)) {
34558
+ logger.error(`${_VesuExtendedMultiplierStrategy.name}::moveAssetsToVaultAllocator amountToBeTransferred is less than 0: ${amountToBeTransferred.toNumber()}`);
34559
+ return {
34560
+ calls: [],
34561
+ status: false
34562
+ };
34563
+ }
33997
34564
  const approveCall = new ERC20(this.config).approve(
33998
34565
  usdceToken.address,
33999
34566
  this.metadata.additionalInfo.vaultAllocator,
34000
- amount
34567
+ amountToBeTransferred
34001
34568
  );
34002
34569
  const transferCall = new ERC20(this.config).transfer(
34003
34570
  usdceToken.address,
34004
34571
  this.metadata.additionalInfo.vaultAllocator,
34005
- amount
34572
+ amountToBeTransferred
34006
34573
  );
34007
34574
  const proofsInfo = extendedAdapter.getProofsForFromLegacySwap(
34008
34575
  this.getMerkleTree()
@@ -34010,21 +34577,29 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34010
34577
  const proofGroups = proofsInfo.proofs;
34011
34578
  const call = this.getManageCall(
34012
34579
  proofGroups,
34013
- await proofsInfo.callConstructor({ amount })
34580
+ await proofsInfo.callConstructor({ amount: amountToBeTransferred })
34014
34581
  );
34015
- return [approveCall, transferCall, call];
34582
+ return {
34583
+ calls: [approveCall, transferCall, call],
34584
+ status: true
34585
+ };
34016
34586
  } catch (err) {
34017
34587
  logger.error(`error moving assets to vault allocator: ${err}`);
34018
- return [];
34588
+ return {
34589
+ calls: [],
34590
+ status: false
34591
+ };
34019
34592
  }
34020
34593
  }
34021
34594
  async shouldInvest() {
34022
34595
  try {
34596
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest starting`);
34023
34597
  const vesuAdapter = await this.getVesuAdapter();
34024
34598
  const extendedAdapter = await this.getExtendedAdapter();
34025
- if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
34599
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest adapters fetched: vesuAdapter=${!!vesuAdapter}, extendedAdapter=${!!extendedAdapter}, extendedAdapter.client=${!!extendedAdapter?.client}`);
34600
+ if (!vesuAdapter) {
34026
34601
  logger.error(
34027
- `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
34602
+ `Vesu adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
34028
34603
  );
34029
34604
  return {
34030
34605
  shouldInvest: false,
@@ -34036,10 +34611,87 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34036
34611
  vesuLeverage: 0
34037
34612
  };
34038
34613
  }
34614
+ if (!extendedAdapter) {
34615
+ logger.error(
34616
+ `Extended adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
34617
+ );
34618
+ return {
34619
+ shouldInvest: false,
34620
+ vesuAmount: new Web3Number(0, 0),
34621
+ extendedAmount: new Web3Number(0, 0),
34622
+ extendedLeverage: 0,
34623
+ collateralPrice: 0,
34624
+ debtPrice: 0,
34625
+ vesuLeverage: 0
34626
+ };
34627
+ }
34628
+ if (!extendedAdapter.client) {
34629
+ logger.error(
34630
+ `Extended adapter client not initialized. This may be a temporary initialization failure - check network connectivity and API availability.`
34631
+ );
34632
+ return {
34633
+ shouldInvest: false,
34634
+ vesuAmount: new Web3Number(0, 0),
34635
+ extendedAmount: new Web3Number(0, 0),
34636
+ extendedLeverage: 0,
34637
+ collateralPrice: 0,
34638
+ debtPrice: 0,
34639
+ vesuLeverage: 0
34640
+ };
34641
+ }
34642
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest calling getUnusedBalance`);
34039
34643
  const balance = await this.getUnusedBalance();
34644
+ if (!Number.isFinite(balance.usdValue) || balance.usdValue < 0) {
34645
+ logger.error(
34646
+ `Invalid balance.usdValue: ${balance.usdValue}. Expected a finite, non-negative number.`
34647
+ );
34648
+ return {
34649
+ shouldInvest: false,
34650
+ vesuAmount: new Web3Number(0, 0),
34651
+ extendedAmount: new Web3Number(0, 0),
34652
+ extendedLeverage: 0,
34653
+ collateralPrice: 0,
34654
+ debtPrice: 0,
34655
+ vesuLeverage: 0
34656
+ };
34657
+ }
34658
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest balance: ${balance.usdValue}`);
34040
34659
  const usdcBalanceOnExtended = await extendedAdapter.getExtendedDepositAmount();
34041
- const amountToInvest = balance.amount.plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).minus(LIMIT_BALANCE);
34042
- if (amountToInvest.lessThan(0)) {
34660
+ if (usdcBalanceOnExtended) {
34661
+ const availableForWithdrawal = parseFloat(usdcBalanceOnExtended.availableForWithdrawal);
34662
+ if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
34663
+ logger.error(
34664
+ `Invalid usdcBalanceOnExtended.availableForWithdrawal: ${usdcBalanceOnExtended.availableForWithdrawal}. Expected a finite, non-negative number.`
34665
+ );
34666
+ return {
34667
+ shouldInvest: false,
34668
+ vesuAmount: new Web3Number(0, 0),
34669
+ extendedAmount: new Web3Number(0, 0),
34670
+ extendedLeverage: 0,
34671
+ collateralPrice: 0,
34672
+ debtPrice: 0,
34673
+ vesuLeverage: 0
34674
+ };
34675
+ }
34676
+ }
34677
+ const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).multipliedBy(1 - LIMIT_BALANCE);
34678
+ const amountToInvestNumber = amountToInvest.toNumber();
34679
+ if (!Number.isFinite(amountToInvestNumber)) {
34680
+ logger.error(
34681
+ `Invalid amountToInvest calculation result: ${amountToInvestNumber}. Calculation may have produced NaN or Infinity.`
34682
+ );
34683
+ return {
34684
+ shouldInvest: false,
34685
+ vesuAmount: new Web3Number(0, 0),
34686
+ extendedAmount: new Web3Number(0, 0),
34687
+ extendedLeverage: 0,
34688
+ collateralPrice: 0,
34689
+ debtPrice: 0,
34690
+ vesuLeverage: 0
34691
+ };
34692
+ }
34693
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvestNumber}`);
34694
+ if (amountToInvest.lessThan(LIMIT_BALANCE_VALUE)) {
34043
34695
  return {
34044
34696
  shouldInvest: false,
34045
34697
  vesuAmount: new Web3Number(0, 0),
@@ -34068,6 +34720,34 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34068
34720
  collateralPrice,
34069
34721
  debtPrice
34070
34722
  } = await this.getAssetPrices();
34723
+ if (!Number.isFinite(collateralPrice.price) || collateralPrice.price <= 0) {
34724
+ logger.error(
34725
+ `Invalid collateralPrice: ${collateralPrice.price}. Expected a finite, positive number.`
34726
+ );
34727
+ return {
34728
+ shouldInvest: false,
34729
+ vesuAmount: new Web3Number(0, 0),
34730
+ extendedAmount: new Web3Number(0, 0),
34731
+ extendedLeverage: 0,
34732
+ collateralPrice: 0,
34733
+ debtPrice: 0,
34734
+ vesuLeverage: 0
34735
+ };
34736
+ }
34737
+ if (!Number.isFinite(debtPrice.price) || debtPrice.price <= 0) {
34738
+ logger.error(
34739
+ `Invalid debtPrice: ${debtPrice.price}. Expected a finite, positive number.`
34740
+ );
34741
+ return {
34742
+ shouldInvest: false,
34743
+ vesuAmount: new Web3Number(0, 0),
34744
+ extendedAmount: new Web3Number(0, 0),
34745
+ extendedLeverage: 0,
34746
+ collateralPrice: 0,
34747
+ debtPrice: 0,
34748
+ vesuLeverage: 0
34749
+ };
34750
+ }
34071
34751
  const { vesu_amount, extended_amount, extended_leverage, vesu_leverage } = await calculateAmountDistribution(
34072
34752
  amountToInvest.toNumber(),
34073
34753
  extendedAdapter.client,
@@ -34091,6 +34771,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34091
34771
  vesuLeverage: 0
34092
34772
  };
34093
34773
  }
34774
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest vesu_amount: ${vesu_amount.toNumber()}, extended_amount: ${extended_amount.toNumber()}`);
34094
34775
  return {
34095
34776
  shouldInvest: true,
34096
34777
  vesuAmount: vesu_amount,
@@ -34117,111 +34798,251 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34117
34798
  try {
34118
34799
  const vesuAdapter = await this.getVesuAdapter();
34119
34800
  const extendedAdapter = await this.getExtendedAdapter();
34120
- let calls = [];
34121
34801
  if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
34122
34802
  logger.error(
34123
34803
  `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
34124
34804
  );
34125
- return calls;
34805
+ return [];
34126
34806
  }
34127
- if (extendedAmount.lessThan(0)) {
34807
+ const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
34808
+ if (!extendedHoldings) {
34809
+ logger.error(`error getting extended holdings: ${extendedHoldings}`);
34810
+ return [];
34811
+ }
34812
+ const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
34813
+ const usdcAmountOnExtendedAvailableForWithdrawal = parseFloat(
34814
+ extendedHoldings.availableForWithdrawal
34815
+ );
34816
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculating movements - Extended current: ${usdcAmountOnExtendedAvailableForWithdrawal}, Wallet: ${usdcAmountInWallet.toNumber()}, Target Extended: ${extendedAmount.toNumber()}, Target Vesu: ${vesuAmount.toNumber()}`);
34817
+ let totalExtendedWithdrawal = new Web3Number(0, USDC_TOKEN_DECIMALS);
34818
+ let totalExtendedDeposit = new Web3Number(0, USDC_TOKEN_DECIMALS);
34819
+ if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
34820
+ totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmount.abs());
34821
+ }
34822
+ const extendedTargetAmount = extendedAmount.abs();
34823
+ let projectedExtendedBalance = usdcAmountOnExtendedAvailableForWithdrawal;
34824
+ if (extendedAmount.isNegative()) {
34825
+ projectedExtendedBalance = projectedExtendedBalance - extendedAmount.abs().toNumber();
34826
+ }
34827
+ const extendedAmountDifference = extendedTargetAmount.minus(projectedExtendedBalance);
34828
+ const extendedAmountDifferenceAbs = extendedAmountDifference.abs();
34829
+ if (extendedAmountDifference.lessThan(0)) {
34830
+ totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmountDifferenceAbs);
34831
+ } else if (extendedAmountDifference.greaterThan(0)) {
34832
+ totalExtendedDeposit = totalExtendedDeposit.plus(extendedAmountDifference);
34833
+ }
34834
+ const vesuTargetAmount = vesuAmount.abs();
34835
+ const projectedWalletBalance = usdcAmountInWallet.plus(totalExtendedWithdrawal).minus(totalExtendedDeposit);
34836
+ let vesuAmountDifference = vesuTargetAmount.minus(projectedWalletBalance);
34837
+ const vesuAmountDifferenceAbs = vesuAmountDifference.abs();
34838
+ 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()}`);
34839
+ let calls = [];
34840
+ let transactionResults = [];
34841
+ if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
34128
34842
  try {
34129
- const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
34843
+ const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
34130
34844
  {
34131
34845
  to: Protocols.VAULT.name,
34132
34846
  from: Protocols.EXTENDED.name,
34133
- amount: extendedAmount.abs()
34847
+ amount: extendedAmount.abs(),
34848
+ cycleType: "INVESTMENT" /* INVESTMENT */
34134
34849
  },
34135
34850
  extendedAdapter,
34136
34851
  vesuAdapter
34137
34852
  );
34138
34853
  if (extendedStatus) {
34139
- calls.push(...extendedCalls);
34854
+ transactionResults.push({
34855
+ status: extendedStatus,
34856
+ calls: extendedCalls,
34857
+ transactionMetadata: {
34858
+ ...extendedTransactionMetadata,
34859
+ transactionType: "DEPOSIT"
34860
+ }
34861
+ });
34140
34862
  } else {
34141
- return [];
34863
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmount.abs() }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34142
34864
  }
34143
34865
  } catch (err) {
34144
34866
  logger.error(`Failed moving assets to vault: ${err}`);
34867
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmount.abs() }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34145
34868
  }
34146
34869
  }
34147
- if (vesuAmount.lessThan(0)) {
34870
+ if (vesuAmount.isNegative() && vesuAmount.abs().greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
34148
34871
  try {
34149
- const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
34872
+ const { calls: vesuCalls, status: vesuStatus, transactionMetadata: vesuTransactionMetadata } = await this.moveAssets(
34150
34873
  {
34151
34874
  to: Protocols.EXTENDED.name,
34152
34875
  from: Protocols.VESU.name,
34153
- amount: vesuAmount.abs()
34876
+ amount: vesuAmount.abs(),
34877
+ cycleType: "INVESTMENT" /* INVESTMENT */
34154
34878
  },
34155
34879
  extendedAdapter,
34156
34880
  vesuAdapter
34157
34881
  );
34158
- calls.push(...vesuCalls);
34159
34882
  if (!vesuStatus) {
34160
- return [];
34161
- }
34883
+ return [this.createTransactionResult([], false, { from: Protocols.VESU.name, to: Protocols.EXTENDED.name, amount: vesuAmount.abs() }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34884
+ }
34885
+ transactionResults.push({
34886
+ status: vesuStatus,
34887
+ calls: vesuCalls,
34888
+ transactionMetadata: {
34889
+ ...vesuTransactionMetadata,
34890
+ transactionType: "DEPOSIT"
34891
+ }
34892
+ });
34162
34893
  } catch (err) {
34163
- logger.error(`Failed moving assets to vault: ${err}`);
34894
+ logger.error(`Failed moving assets to extended via vault allocator: ${err}`);
34895
+ return [this.createTransactionResult([], false, { from: Protocols.VESU.name, to: Protocols.EXTENDED.name, amount: vesuAmount.abs() }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34164
34896
  }
34165
34897
  }
34166
- const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
34167
- if (!extendedHoldings) {
34168
- logger.error(`error getting extended holdings: ${extendedHoldings}`);
34169
- return calls;
34170
- }
34171
- const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
34172
- const usdcAmountOnExtended = parseFloat(
34173
- extendedHoldings.availableForWithdrawal
34174
- );
34175
- if (extendedAmount.minus(usdcAmountOnExtended).greaterThan(0)) {
34176
- try {
34177
- const { calls: extendedCalls } = await this.moveAssets(
34178
- {
34179
- to: Protocols.EXTENDED.name,
34180
- from: Protocols.VAULT.name,
34181
- amount: extendedAmount.minus(usdcAmountOnExtended)
34182
- },
34183
- extendedAdapter,
34184
- vesuAdapter
34185
- );
34186
- calls.push(...extendedCalls);
34187
- } catch (err) {
34188
- logger.error(`Failed moving assets to extended: ${err}`);
34898
+ if (extendedAmountDifferenceAbs.greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
34899
+ if (extendedAmountDifference.greaterThan(0)) {
34900
+ try {
34901
+ const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
34902
+ {
34903
+ to: Protocols.EXTENDED.name,
34904
+ from: Protocols.VAULT.name,
34905
+ amount: extendedAmountDifference,
34906
+ cycleType: "INVESTMENT" /* INVESTMENT */
34907
+ },
34908
+ extendedAdapter,
34909
+ vesuAdapter
34910
+ );
34911
+ if (extendedStatus) {
34912
+ transactionResults.push({
34913
+ status: extendedStatus,
34914
+ calls: extendedCalls,
34915
+ transactionMetadata: extendedTransactionMetadata
34916
+ });
34917
+ } else {
34918
+ logger.error(`Failed to move assets to extended - operation returned false status`);
34919
+ return [this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.EXTENDED.name, amount: extendedAmountDifference }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34920
+ }
34921
+ } catch (err) {
34922
+ logger.error(`Failed moving assets to extended: ${err}`);
34923
+ return [this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.EXTENDED.name, amount: extendedAmountDifference }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34924
+ }
34925
+ } else if (extendedAmountDifference.lessThan(0)) {
34926
+ try {
34927
+ const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
34928
+ {
34929
+ to: Protocols.VAULT.name,
34930
+ from: Protocols.EXTENDED.name,
34931
+ amount: extendedAmountDifferenceAbs,
34932
+ cycleType: "INVESTMENT" /* INVESTMENT */
34933
+ },
34934
+ extendedAdapter,
34935
+ vesuAdapter
34936
+ );
34937
+ if (extendedStatus) {
34938
+ transactionResults.push({
34939
+ status: extendedStatus,
34940
+ calls: extendedCalls,
34941
+ transactionMetadata: {
34942
+ ...extendedTransactionMetadata,
34943
+ transactionType: "DEPOSIT"
34944
+ }
34945
+ });
34946
+ } else {
34947
+ logger.error(`Failed to withdraw from extended - operation returned false status`);
34948
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmountDifferenceAbs }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34949
+ }
34950
+ } catch (err) {
34951
+ logger.error(`Failed moving assets from extended to vault: ${err}`);
34952
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmountDifferenceAbs }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34953
+ }
34189
34954
  }
34190
34955
  }
34191
- if (vesuAmount.minus(usdcAmountInWallet).greaterThan(0)) {
34192
- try {
34193
- const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
34194
- {
34195
- to: Protocols.VAULT.name,
34196
- from: Protocols.EXTENDED.name,
34197
- amount: vesuAmount.minus(usdcAmountInWallet)
34198
- },
34199
- extendedAdapter,
34200
- vesuAdapter
34956
+ if (vesuAmountDifferenceAbs.greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
34957
+ if (vesuAmountDifference.lessThanOrEqualTo(0)) {
34958
+ logger.warn(
34959
+ `Vesu amount difference is negative or zero: ${vesuAmountDifference.toNumber()}. Skipping operation.`
34201
34960
  );
34202
- if (!vesuStatus) {
34203
- return [];
34961
+ } else {
34962
+ try {
34963
+ const { calls: vesuCalls, status: vesuStatus, transactionMetadata: vesuTransactionMetadata } = await this.moveAssets(
34964
+ {
34965
+ to: Protocols.VAULT.name,
34966
+ from: Protocols.EXTENDED.name,
34967
+ amount: vesuAmountDifference,
34968
+ cycleType: "INVESTMENT" /* INVESTMENT */
34969
+ },
34970
+ extendedAdapter,
34971
+ vesuAdapter
34972
+ );
34973
+ if (!vesuStatus) {
34974
+ logger.error(`Failed to move assets to vesu - operation returned false status`);
34975
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: vesuAmountDifference }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34976
+ }
34977
+ transactionResults.push({
34978
+ status: vesuStatus,
34979
+ calls: vesuCalls,
34980
+ transactionMetadata: {
34981
+ ...vesuTransactionMetadata,
34982
+ transactionType: "DEPOSIT"
34983
+ }
34984
+ });
34985
+ } catch (err) {
34986
+ logger.error(`Failed moving assets to vault: ${err}`);
34987
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: vesuAmountDifference }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34204
34988
  }
34205
- calls.push(...vesuCalls);
34206
- } catch (err) {
34207
- logger.error(`Failed moving assets to vault: ${err}`);
34208
34989
  }
34209
34990
  }
34210
- return calls;
34991
+ return transactionResults;
34211
34992
  } catch (err) {
34212
34993
  logger.error(`Failed moving assets to vesu: ${err}`);
34213
- return [];
34994
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: new Web3Number(0, USDC_TOKEN_DECIMALS) }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34995
+ }
34996
+ }
34997
+ /**
34998
+ * Helper method to create transaction result with metadata
34999
+ */
35000
+ createTransactionResult(calls, status, params, transactionType, cycleType) {
35001
+ if (status) {
35002
+ return {
35003
+ calls,
35004
+ status,
35005
+ transactionMetadata: {
35006
+ protocolFrom: params.from,
35007
+ protocolTo: params.to,
35008
+ transactionType,
35009
+ usdAmount: params.amount.abs().toFixed(),
35010
+ status: "PENDING",
35011
+ cycleType
35012
+ }
35013
+ };
34214
35014
  }
35015
+ return { calls: [], status: false, transactionMetadata: { protocolFrom: "", protocolTo: "", transactionType: "DEPOSIT", usdAmount: "0", status: "FAILED", cycleType } };
34215
35016
  }
34216
35017
  async moveAssets(params, extendedAdapter, vesuAdapter) {
34217
35018
  try {
35019
+ if (params.amount.lessThanOrEqualTo(0)) {
35020
+ logger.error(
35021
+ `Invalid amount for moveAssets: ${params.amount.toNumber()}. Amount must be positive.`
35022
+ );
35023
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
35024
+ }
35025
+ const amountAbs = params.amount.abs();
35026
+ if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
35027
+ if (amountAbs.lessThanOrEqualTo(extendedAdapter.minimumExtendedMovementAmount)) {
35028
+ logger.warn(
35029
+ `Amount ${amountAbs.toNumber()} is below minimum Extended movement amount ${extendedAdapter.minimumExtendedMovementAmount}. Skipping operation.`
35030
+ );
35031
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
35032
+ }
35033
+ }
35034
+ if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
35035
+ if (amountAbs.lessThanOrEqualTo(vesuAdapter.minimumVesuMovementAmount)) {
35036
+ logger.warn(
35037
+ `Amount ${amountAbs.toNumber()} is below minimum Vesu movement amount ${vesuAdapter.minimumVesuMovementAmount}. Skipping operation.`
35038
+ );
35039
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
35040
+ }
35041
+ }
34218
35042
  const avnuAdapter = await this.getAvnuAdapter();
34219
35043
  if (!avnuAdapter) {
34220
35044
  logger.error(`avnu adapter not found: ${avnuAdapter}`);
34221
- return {
34222
- calls: [],
34223
- status: false
34224
- };
35045
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
34225
35046
  }
34226
35047
  logger.info(`moveAssets params, ${JSON.stringify(params)}`);
34227
35048
  const collateralToken = vesuAdapter.config.supportedPositions[0].asset;
@@ -34240,61 +35061,72 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34240
35061
  await proofsInfo.callConstructor({ amount: params.amount })
34241
35062
  );
34242
35063
  calls.push(call);
34243
- return {
34244
- calls: [call],
34245
- status: true
34246
- };
35064
+ return this.createTransactionResult(calls, true, params, "DEPOSIT", params.cycleType);
34247
35065
  } else if (params.to === Protocols.VAULT.name && params.from === Protocols.EXTENDED.name) {
34248
35066
  const extendedLeverage = calculateExtendedLevergae();
34249
35067
  const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
34250
35068
  if (!extendedHoldings) {
34251
35069
  logger.error(`error getting extended holdings: ${extendedHoldings}`);
34252
- return {
34253
- calls: [],
34254
- status: false
34255
- };
35070
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
34256
35071
  }
34257
35072
  const extendedHoldingAmount = new Web3Number(
34258
35073
  extendedHoldings.availableForWithdrawal,
34259
35074
  USDC_TOKEN_DECIMALS
34260
35075
  );
34261
- const leftAmountAfterWithdrawalAmountInAccount = params.amount.minus(extendedHoldingAmount);
34262
- const btcAmount = leftAmountAfterWithdrawalAmountInAccount.dividedBy(collateralPrice.price);
34263
- const openLongPosition = await extendedAdapter.createOrder(
34264
- extendedLeverage.toString(),
34265
- btcAmount.toNumber(),
34266
- "BUY" /* BUY */
34267
- );
34268
- if (!openLongPosition) {
34269
- logger.error(`error opening long position: ${openLongPosition}`);
34270
- return {
34271
- calls: [],
34272
- status: false
34273
- };
35076
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssets extendedHoldingAmount: ${extendedHoldingAmount.toNumber()}`);
35077
+ if (params.amount.abs().greaterThan(extendedHoldingAmount)) {
35078
+ const leftAmountAfterWithdrawalAmountInAccount = params.amount.abs().minus(extendedHoldingAmount);
35079
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssets leftAmountAfterWithdrawalAmountInAccount: ${leftAmountAfterWithdrawalAmountInAccount.toNumber()}`);
35080
+ const btcAmount = leftAmountAfterWithdrawalAmountInAccount.dividedBy(collateralPrice.price);
35081
+ const openLongPosition = btcAmount.multipliedBy(3).greaterThan(MINIMUM_EXTENDED_POSITION_SIZE) ? await extendedAdapter.createOrder(
35082
+ extendedLeverage.toString(),
35083
+ btcAmount.toNumber(),
35084
+ "BUY" /* BUY */
35085
+ ) : await extendedAdapter.createOrder(
35086
+ extendedLeverage.toString(),
35087
+ 34e-6,
35088
+ // just in case amount falls short then we need to create a withdrawal
35089
+ "BUY" /* BUY */
35090
+ );
35091
+ if (!openLongPosition) {
35092
+ logger.error(`error opening long position: ${openLongPosition}`);
35093
+ }
35094
+ const updatedHoldings = await extendedAdapter.getExtendedDepositAmount();
35095
+ if (!updatedHoldings || new Web3Number(updatedHoldings.availableForWithdrawal, USDC_TOKEN_DECIMALS).lessThan(params.amount.abs())) {
35096
+ logger.error(`Insufficient balance after opening position. Available: ${updatedHoldings?.availableForWithdrawal}, Needed: ${params.amount.abs()}`);
35097
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
35098
+ }
34274
35099
  }
34275
- await new Promise((resolve) => setTimeout(resolve, 5e3));
34276
- const withdrawalFromExtended = await extendedAdapter.withdrawFromExtended(params.amount);
34277
- if (withdrawalFromExtended) {
35100
+ const {
35101
+ status: withdrawalFromExtendedStatus,
35102
+ receivedTxnHash: withdrawalFromExtendedTxnHash
35103
+ } = await extendedAdapter.withdrawFromExtended(params.amount);
35104
+ logger.info(`withdrawalFromExtendedStatus: ${withdrawalFromExtendedStatus}, withdrawalFromExtendedTxnHash: ${withdrawalFromExtendedTxnHash}`);
35105
+ if (withdrawalFromExtendedStatus && withdrawalFromExtendedTxnHash) {
34278
35106
  const extendedHoldings2 = await extendedAdapter.getExtendedDepositAmount();
34279
- logger.info(`extendedHoldings after withdrawal ${extendedHoldings2}`);
34280
- await new Promise((resolve) => setTimeout(resolve, 1e4));
34281
- const calls = await this.moveAssetsToVaultAllocator(params.amount, extendedAdapter);
34282
- if (calls.length > 0) {
34283
- return {
34284
- calls,
34285
- status: true
34286
- };
35107
+ logger.info(`extendedHoldings after withdrawal ${extendedHoldings2?.availableForWithdrawal}`);
35108
+ await new Promise((resolve) => setTimeout(resolve, 5e3));
35109
+ const { calls, status } = await this.moveAssetsToVaultAllocator(params.amount, extendedAdapter);
35110
+ if (calls.length > 0 && status) {
35111
+ return this.createTransactionResult(calls, true, params, "WITHDRAWAL", params.cycleType);
35112
+ } else {
35113
+ return this.createTransactionResult([], true, params, "WITHDRAWAL", params.cycleType);
34287
35114
  }
35115
+ } else if (withdrawalFromExtendedStatus && !withdrawalFromExtendedTxnHash) {
35116
+ logger.error("withdrawal from extended successful, but funds didn't get transferred to the wallet");
35117
+ return this.createTransactionResult([], true, params, "WITHDRAWAL", params.cycleType);
34288
35118
  } else {
34289
35119
  logger.error("withdrawal from extended failed");
34290
- return {
34291
- calls: [],
34292
- status: false
34293
- };
35120
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
34294
35121
  }
34295
35122
  } else if (params.to === Protocols.VAULT.name && params.from === Protocols.VESU.name) {
35123
+ const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "close" /* CLOSE */);
35124
+ if (!isPriceDifferenceBetweenAvnuAndExtended) {
35125
+ logger.warn(`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
35126
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
35127
+ }
34296
35128
  const vesuAmountInBTC = new Web3Number(
34297
- params.amount.dividedBy(collateralPrice.price).toNumber(),
35129
+ params.amount.dividedBy(collateralPrice.price).toFixed(WBTC_TOKEN_DECIMALS),
34298
35130
  collateralToken.decimals
34299
35131
  );
34300
35132
  const proofsInfo = vesuAdapter.getProofs(false, this.getMerkleTree());
@@ -34312,11 +35144,13 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34312
35144
  await swapProofsInfo.callConstructor({ amount: vesuAmountInBTC })
34313
35145
  );
34314
35146
  calls.push(swapCall);
34315
- return {
34316
- calls,
34317
- status: true
34318
- };
35147
+ return this.createTransactionResult(calls, true, params, "WITHDRAWAL", params.cycleType);
34319
35148
  } else if (params.to === Protocols.EXTENDED.name && params.from === Protocols.VESU.name) {
35149
+ const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "close" /* CLOSE */);
35150
+ if (!isPriceDifferenceBetweenAvnuAndExtended) {
35151
+ logger.warn(`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
35152
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
35153
+ }
34320
35154
  const vesuAmountInBTC = new Web3Number(
34321
35155
  params.amount.dividedBy(collateralPrice.price).toNumber(),
34322
35156
  collateralToken.decimals
@@ -34346,131 +35180,32 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34346
35180
  await proofsInfoDeposit.callConstructor({ amount: params.amount })
34347
35181
  );
34348
35182
  calls.push(callDeposit);
34349
- return {
34350
- calls,
34351
- status: true
34352
- };
35183
+ return this.createTransactionResult(calls, true, params, "DEPOSIT", params.cycleType);
34353
35184
  }
34354
- return {
34355
- calls: [],
34356
- status: false
34357
- };
35185
+ logger.error(`Unsupported assets movement: ${params.from} to ${params.to}`);
35186
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
34358
35187
  } catch (err) {
34359
35188
  logger.error(`error moving assets: ${err}`);
34360
- return {
34361
- calls: [],
34362
- status: false
34363
- };
35189
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
34364
35190
  }
34365
35191
  }
34366
35192
  async handleDeposit() {
34367
35193
  try {
34368
- const vesuAdapter = await this.getVesuAdapter();
34369
- const extendedAdapter = await this.getExtendedAdapter();
34370
- const avnuAdapter = await this.getAvnuAdapter();
34371
- if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client || !avnuAdapter) {
34372
- logger.error(
34373
- "vesu or extended adapter not found",
34374
- vesuAdapter,
34375
- extendedAdapter
34376
- );
34377
- return {
34378
- extendedAmountInBTC: new Web3Number(0, 0),
34379
- calls: []
34380
- };
34381
- }
34382
- const extendedLeverage = calculateExtendedLevergae();
34383
- const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter);
34384
- if (!isPriceDifferenceBetweenAvnuAndExtended) {
34385
- logger.error("price difference between avnu and extended doesn't fit the range");
34386
- return {
34387
- extendedAmountInBTC: new Web3Number(0, 0),
34388
- calls: []
34389
- };
34390
- }
34391
- const position = await extendedAdapter.getAllOpenPositions();
34392
- if (!position) {
34393
- logger.error("error getting extended position", position);
34394
- return {
34395
- extendedAmountInBTC: new Web3Number(0, 0),
34396
- calls: []
34397
- };
34398
- }
34399
- const extendedPositionValue = position.length > 0 ? parseFloat(position[0].value) : 0;
34400
- const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
34401
- if (!extendedHoldings) {
34402
- logger.error(`error getting extended holdings: ${extendedHoldings}`);
34403
- return {
34404
- extendedAmountInBTC: new Web3Number(0, 0),
34405
- calls: []
34406
- };
34407
- }
34408
- const extendedHoldingAmount = new Web3Number(
34409
- extendedHoldings.availableForWithdrawal,
34410
- USDC_TOKEN_DECIMALS
34411
- );
34412
- const {
34413
- collateralTokenAmount
34414
- } = await vesuAdapter.vesuAdapter.getAssetPrices();
34415
- const { collateralPrice } = await this.getAssetPrices();
34416
- const { vesuAmountInBTC, extendedAmountInBTC } = calculateVesUPositionSizeGivenExtended(
34417
- extendedPositionValue,
34418
- extendedHoldingAmount,
34419
- collateralTokenAmount,
34420
- collateralPrice.price
34421
- );
34422
- logger.info(`vesuAmountInBTC ${vesuAmountInBTC}, extendedAmountInBTC ${extendedAmountInBTC}`);
34423
- let calls = [];
34424
- if (vesuAmountInBTC.greaterThan(MINIMUM_EXTENDED_POSITION_SIZE)) {
34425
- const proofsInfo = vesuAdapter.getProofs(true, this.getMerkleTree());
34426
- const proofGroups = proofsInfo.proofs;
34427
- const call = this.getManageCall(
34428
- proofGroups,
34429
- await proofsInfo.callConstructor({
34430
- amount: vesuAmountInBTC
34431
- })
34432
- );
34433
- const { amount: wbtcAmountInVaultAllocator } = await this.getUnusedBalanceWBTC();
34434
- if (wbtcAmountInVaultAllocator.lessThan(vesuAmountInBTC)) {
34435
- logger.info(`WBTC amount in vault allocator is less than vesu amount required in WBTC thus swapping, wbtcAmountInVaultAllocator: ${wbtcAmountInVaultAllocator}, vesuAmountInBTC: ${vesuAmountInBTC}`);
34436
- const swapProofsInfo = avnuAdapter.getProofs(true, this.getMerkleTree());
34437
- const swapProofGroups = swapProofsInfo.proofs;
34438
- const swapCall = this.getManageCall(
34439
- swapProofGroups,
34440
- await swapProofsInfo.callConstructor({
34441
- amount: vesuAmountInBTC
34442
- })
34443
- );
34444
- calls.push(swapCall);
34445
- }
34446
- calls.push(call);
34447
- }
34448
- const shortPosition = extendedAmountInBTC.multipliedBy(3).abs().greaterThan(MINIMUM_EXTENDED_POSITION_SIZE) ? await extendedAdapter.createOrder(
34449
- extendedLeverage.toString(),
34450
- extendedAmountInBTC.toNumber(),
34451
- "SELL" /* SELL */
34452
- ) : null;
34453
- if (!shortPosition && extendedAmountInBTC.multipliedBy(3).abs().greaterThan(MINIMUM_EXTENDED_POSITION_SIZE)) {
34454
- logger.error(`error creating short position thus no position to be opened on vesu: ${shortPosition}`);
34455
- return {
34456
- extendedAmountInBTC: new Web3Number(0, 0),
34457
- calls: []
34458
- };
34459
- }
34460
- return {
34461
- extendedAmountInBTC,
34462
- calls
34463
- };
35194
+ return this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.VAULT.name, amount: new Web3Number(0, 0) }, "NONE", "INVESTMENT" /* INVESTMENT */);
34464
35195
  } catch (err) {
34465
35196
  logger.error(`error handling deposit: ${err}`);
34466
- return {
34467
- extendedAmountInBTC: new Web3Number(0, 0),
34468
- calls: []
34469
- };
34470
- ;
35197
+ return this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.VAULT.name, amount: new Web3Number(0, 0) }, "NONE", "INVESTMENT" /* INVESTMENT */);
34471
35198
  }
34472
35199
  }
34473
- async checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter) {
35200
+ /**
35201
+ * Check if the price difference between avnu and extended is within the acceptable range to enhance the position size or close the position
35202
+ * @param extendedAdapter - the extended adapter
35203
+ * @param vesuAdapter - the vesu adapter
35204
+ * @param avnuAdapter - the avnu adapter
35205
+ * @param positionType - the position type (open or close)
35206
+ * @returns true if the price difference is within the acceptable range, false otherwise
35207
+ */
35208
+ async checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, positionType) {
34474
35209
  const {
34475
35210
  ask,
34476
35211
  bid
@@ -34482,13 +35217,30 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34482
35217
  logger.error(`error getting btc price avnu: ${btcPriceAvnu}`);
34483
35218
  return false;
34484
35219
  }
34485
- const priceDifference = price.minus(btcPriceAvnu).toNumber();
34486
- if (priceDifference < MAX_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED && priceDifference > MIN_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED) {
34487
- return true;
35220
+ logger.info(`price: ${price}`);
35221
+ logger.info(`btcPriceAvnu: ${btcPriceAvnu}`);
35222
+ const priceDifference = new Web3Number(price.minus(btcPriceAvnu).toFixed(2), 0);
35223
+ logger.info(`priceDifference: ${priceDifference}`);
35224
+ if (priceDifference.isNegative()) {
35225
+ return false;
35226
+ }
35227
+ if (positionType === "open" /* OPEN */) {
35228
+ logger.info(`price difference between avnu and extended for open position: ${priceDifference.toNumber()}, minimumExtendedPriceDifferenceForSwapOpen: ${avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen}`);
35229
+ const result = priceDifference.greaterThanOrEqualTo(avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen);
35230
+ logger.info(`result: ${result}`);
35231
+ return result;
35232
+ } else {
35233
+ logger.info(`price difference between avnu and extended for close position: ${priceDifference.toNumber()}, maximumExtendedPriceDifferenceForSwapClosing: ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
35234
+ const result = priceDifference.lessThanOrEqualTo(avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing);
35235
+ logger.info(`result: ${result}`);
35236
+ return result;
34488
35237
  }
34489
- logger.error(`price difference between avnu and extended doesn't fit the range, priceDifference: ${priceDifference}`);
34490
- return false;
34491
35238
  }
35239
+ /**
35240
+ * Handle the withdrawal of assets from the vault
35241
+ * @param amount - the amount to withdraw in USDC
35242
+ * @returns the calls to be executed and the status of the calls generated along with the metadata for the calls
35243
+ */
34492
35244
  async handleWithdraw(amount) {
34493
35245
  try {
34494
35246
  const usdcBalanceVaultAllocator = await this.getUnusedBalance();
@@ -34500,12 +35252,8 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34500
35252
  const withdrawCall2 = await this.getBringLiquidityCall({
34501
35253
  amount: usdcBalanceVaultAllocator.amount
34502
35254
  });
34503
- logger.info("withdraw call", withdrawCall2);
34504
35255
  calls.push(withdrawCall2);
34505
- return {
34506
- calls,
34507
- status: true
34508
- };
35256
+ return [this.createTransactionResult(calls, true, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "WITHDRAWAL", "WITHDRAWAL" /* WITHDRAWAL */)];
34509
35257
  }
34510
35258
  const vesuAdapter = await this.getVesuAdapter();
34511
35259
  const extendedAdapter = await this.getExtendedAdapter();
@@ -34514,11 +35262,9 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34514
35262
  logger.error(
34515
35263
  `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
34516
35264
  );
34517
- return {
34518
- calls,
34519
- status
34520
- };
35265
+ return [this.createTransactionResult(calls, status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
34521
35266
  }
35267
+ let transactionResults = [];
34522
35268
  const { collateralTokenAmount } = await vesuAdapter.vesuAdapter.getAssetPrices();
34523
35269
  const {
34524
35270
  collateralPrice
@@ -34527,10 +35273,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34527
35273
  if (!extendedPositon) {
34528
35274
  status = false;
34529
35275
  logger.error("error getting extended position", extendedPositon);
34530
- return {
34531
- calls,
34532
- status
34533
- };
35276
+ return [this.createTransactionResult(calls, status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
34534
35277
  }
34535
35278
  const amountDistributionForWithdrawal = await calculateAmountDistributionForWithdrawal(
34536
35279
  usdcBalanceDifference,
@@ -34543,61 +35286,70 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34543
35286
  logger.error(
34544
35287
  `error calculating amount distribution for withdrawal: ${amountDistributionForWithdrawal}`
34545
35288
  );
34546
- return {
34547
- calls,
34548
- status
34549
- };
35289
+ return [this.createTransactionResult(calls, status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
34550
35290
  }
34551
35291
  const { vesu_amount, extended_amount } = amountDistributionForWithdrawal;
34552
35292
  if (status && vesu_amount.greaterThan(0)) {
34553
- const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
35293
+ const { calls: vesuCalls, status: vesuStatus, transactionMetadata: vesuTransactionMetadata } = await this.moveAssets(
34554
35294
  {
34555
35295
  amount: vesu_amount,
34556
35296
  from: Protocols.VESU.name,
34557
- to: Protocols.VAULT.name
35297
+ to: Protocols.VAULT.name,
35298
+ cycleType: "WITHDRAWAL" /* WITHDRAWAL */
34558
35299
  },
34559
35300
  extendedAdapter,
34560
35301
  vesuAdapter
34561
35302
  );
34562
35303
  status = vesuStatus;
34563
- calls.push(...vesuCalls);
35304
+ transactionResults.push({
35305
+ status: vesuStatus,
35306
+ calls: vesuCalls,
35307
+ transactionMetadata: vesuTransactionMetadata
35308
+ });
34564
35309
  }
34565
35310
  if (status && extended_amount.greaterThan(0)) {
34566
- const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
35311
+ const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
34567
35312
  {
34568
35313
  amount: extended_amount,
34569
35314
  from: Protocols.EXTENDED.name,
34570
- to: Protocols.VAULT.name
35315
+ to: Protocols.VAULT.name,
35316
+ cycleType: "WITHDRAWAL" /* WITHDRAWAL */
34571
35317
  },
34572
35318
  extendedAdapter,
34573
35319
  vesuAdapter
34574
35320
  );
34575
35321
  status = extendedStatus;
34576
35322
  if (status) {
34577
- calls.push(...extendedCalls);
35323
+ transactionResults.push({
35324
+ status: extendedStatus,
35325
+ calls: extendedCalls,
35326
+ transactionMetadata: extendedTransactionMetadata
35327
+ });
34578
35328
  } else {
34579
35329
  logger.error("error moving assets to vault: extendedStatus: ${extendedStatus}");
34580
- return {
34581
- calls: [],
34582
- status
34583
- };
35330
+ return [this.createTransactionResult([], status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
34584
35331
  }
34585
35332
  }
34586
35333
  const withdrawCall = await this.getBringLiquidityCall({
34587
35334
  amount
34588
35335
  });
34589
35336
  logger.info("withdraw call", withdrawCall);
34590
- calls.push(withdrawCall);
34591
- return {
34592
- calls,
34593
- status
34594
- };
35337
+ transactionResults.push({
35338
+ status,
35339
+ calls: [withdrawCall],
35340
+ transactionMetadata: {
35341
+ protocolFrom: Protocols.VAULT.name,
35342
+ protocolTo: Protocols.NONE.name,
35343
+ transactionType: "WITHDRAWAL",
35344
+ usdAmount: amount.toFixed(),
35345
+ status: "PENDING",
35346
+ cycleType: "WITHDRAWAL" /* WITHDRAWAL */
35347
+ }
35348
+ });
35349
+ return transactionResults;
34595
35350
  } catch (err) {
34596
35351
  logger.error(`error handling withdrawal: ${err}`);
34597
- return {
34598
- calls: [],
34599
- status: false
34600
- };
35352
+ return [this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
34601
35353
  }
34602
35354
  }
34603
35355
  async getAUM() {
@@ -34644,8 +35396,182 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34644
35396
  splits: [realAUM, estimatedAUMDelta]
34645
35397
  };
34646
35398
  }
35399
+ async processTransactionDataFromSDK(txnData) {
35400
+ try {
35401
+ const txnsToBeExecuted = txnData.filter((txn) => {
35402
+ return txn.transactionMetadata.transactionType !== "NONE" && txn.transactionMetadata.protocolFrom !== "" && txn.transactionMetadata.protocolTo !== "";
35403
+ });
35404
+ const callsToBeExecutedFinal = txnsToBeExecuted.flatMap((txn) => txn.calls);
35405
+ const txnMetadata = txnsToBeExecuted.map((txn) => txn.transactionMetadata);
35406
+ return { callsToBeExecutedFinal, txnMetadata };
35407
+ } catch (err) {
35408
+ logger.error(`error processing transaction data from SDK: ${err}`);
35409
+ return null;
35410
+ }
35411
+ }
35412
+ async processTransactionMetadata(txnMetadata, extendedIntentFulfilled) {
35413
+ try {
35414
+ const txnMetadataNew = txnMetadata.map((txn) => {
35415
+ const isExtendedProtocol = txn.protocolFrom === Protocols.EXTENDED.name || txn.protocolTo === Protocols.EXTENDED.name;
35416
+ if (isExtendedProtocol) {
35417
+ txn.status = extendedIntentFulfilled ? "COMPLETED" : "PENDING";
35418
+ } else {
35419
+ txn.status = "COMPLETED";
35420
+ }
35421
+ return txn;
35422
+ });
35423
+ return txnMetadataNew;
35424
+ } catch (err) {
35425
+ logger.error(`error processing transaction data from SDK: ${err}`);
35426
+ return null;
35427
+ }
35428
+ }
35429
+ async getMaxBorrowableAmount() {
35430
+ const vesuAdapter = await this.getVesuAdapter();
35431
+ const extendedAdapter = await this.getExtendedAdapter();
35432
+ if (!vesuAdapter || !extendedAdapter) {
35433
+ return new Web3Number(0, 0);
35434
+ }
35435
+ const extendedFundingRate = new Web3Number((await extendedAdapter.getNetAPY()).toFixed(4), 0);
35436
+ const extendedPositions = await extendedAdapter.getAllOpenPositions();
35437
+ if (!extendedPositions || extendedPositions.length === 0) {
35438
+ logger.info(`no extended positions found`);
35439
+ return new Web3Number(0, 0);
35440
+ }
35441
+ const extendePositionSizeUSD = new Web3Number(extendedPositions[0].value || 0, 0);
35442
+ const vesuPositions = await vesuAdapter.getPositions();
35443
+ const vesuSupplyApy = vesuPositions[0].apy.apy;
35444
+ const vesuCollateralSizeUSD = new Web3Number(vesuPositions[0].usdValue.toFixed(USDC_TOKEN_DECIMALS), USDC_TOKEN_DECIMALS);
35445
+ const vesuDebtSizeUSD = new Web3Number(vesuPositions[1].usdValue.toFixed(USDC_TOKEN_DECIMALS), USDC_TOKEN_DECIMALS);
35446
+ const num1 = extendePositionSizeUSD.multipliedBy(extendedFundingRate);
35447
+ const num22 = vesuCollateralSizeUSD.multipliedBy(vesuSupplyApy);
35448
+ const num32 = vesuDebtSizeUSD.abs();
35449
+ const maxBorrowApy = num1.plus(num22).minus(0.1).dividedBy(num32);
35450
+ const vesuMaxBorrowableAmount = await vesuAdapter.vesuAdapter.getMaxBorrowableByInterestRate(this.config, vesuAdapter.config.debt, maxBorrowApy.toNumber());
35451
+ return new Web3Number(vesuMaxBorrowableAmount.toFixed(USDC_TOKEN_DECIMALS), USDC_TOKEN_DECIMALS);
35452
+ }
35453
+ async getVesuHealthFactors() {
35454
+ const vesuAdapter = await this.getVesuAdapter();
35455
+ const extendedAdapter = await this.getExtendedAdapter();
35456
+ if (!vesuAdapter || !extendedAdapter) {
35457
+ return [0, 0];
35458
+ }
35459
+ const vesuPositions = await vesuAdapter.getPositions();
35460
+ const vesuCollateralSizeUSD = new Web3Number(vesuPositions[0].usdValue.toFixed(USDC_TOKEN_DECIMALS), 0);
35461
+ const vesuDebtSizeUSD = new Web3Number(vesuPositions[1].usdValue.toFixed(USDC_TOKEN_DECIMALS), 0);
35462
+ const actualLtv = vesuDebtSizeUSD.dividedBy(vesuCollateralSizeUSD).abs();
35463
+ logger.info(`actualLtv: ${actualLtv.toNumber()}`);
35464
+ const maxLtv = new Web3Number(await vesuAdapter.vesuAdapter.getLTVConfig(this.config), 4);
35465
+ const healthFactor = new Web3Number(maxLtv.dividedBy(actualLtv).toFixed(4), 4);
35466
+ logger.info(`healthFactor: ${healthFactor.toNumber()}`);
35467
+ const extendedBalance = await extendedAdapter.getExtendedDepositAmount();
35468
+ if (!extendedBalance) {
35469
+ return [0, 0];
35470
+ }
35471
+ const extendedLeverage = new Web3Number((Number(extendedBalance.marginRatio) * 100).toFixed(4), 4);
35472
+ logger.info(`extendedLeverage: ${extendedLeverage.toNumber()}`);
35473
+ return [healthFactor.toNumber(), extendedLeverage.toNumber()];
35474
+ }
35475
+ async netAPY() {
35476
+ const allPositions = [];
35477
+ for (let adapter of this.metadata.additionalInfo.adapters) {
35478
+ if (adapter.adapter.name !== ExtendedAdapter.name) {
35479
+ let positions = await adapter.adapter.getPositions();
35480
+ if (positions.length > 0) {
35481
+ allPositions.push(...positions);
35482
+ }
35483
+ }
35484
+ }
35485
+ const extendedAdapter = await this.getExtendedAdapter();
35486
+ if (!extendedAdapter) {
35487
+ return {
35488
+ net: 0,
35489
+ splits: []
35490
+ };
35491
+ }
35492
+ let vesuPositions = allPositions.filter((item) => item.protocol === Protocols.VESU);
35493
+ vesuPositions.map((item) => {
35494
+ item.apy.apy = item.apy.apy * 0.1;
35495
+ });
35496
+ const extendedPositions = await extendedAdapter.getAllOpenPositions();
35497
+ const usdcToken = Global.getDefaultTokens().find((token) => token.symbol === "USDC");
35498
+ if (!extendedPositions || !usdcToken) {
35499
+ return {
35500
+ net: 0,
35501
+ splits: []
35502
+ };
35503
+ }
35504
+ const extendedPosition = extendedPositions[0] || 0;
35505
+ const extendedEquity = (await extendedAdapter.getExtendedDepositAmount())?.equity || 0;
35506
+ const extendedApy = await extendedAdapter.getNetAPY();
35507
+ const totalHoldingsUSDValue = allPositions.reduce((acc, curr) => acc + curr.usdValue, 0) + Number(extendedEquity);
35508
+ console.log(totalHoldingsUSDValue);
35509
+ const extendedPositionSizeMultipliedByApy = Number(extendedPosition.value) * extendedApy;
35510
+ let weightedAPYs = allPositions.reduce((acc, curr) => acc + curr.apy.apy * curr.usdValue, 0) + extendedPositionSizeMultipliedByApy;
35511
+ console.log(weightedAPYs);
35512
+ const netAPY = weightedAPYs / totalHoldingsUSDValue;
35513
+ console.log(netAPY);
35514
+ allPositions.push({
35515
+ tokenInfo: usdcToken,
35516
+ amount: new Web3Number(extendedPosition.size, 0),
35517
+ usdValue: Number(extendedEquity),
35518
+ apy: { apy: extendedApy, type: "base" /* BASE */ },
35519
+ remarks: "finalised" /* FINALISED */,
35520
+ protocol: Protocols.EXTENDED
35521
+ });
35522
+ return {
35523
+ net: netAPY,
35524
+ splits: allPositions.map((p) => ({ apy: p.apy.apy, id: p.remarks ?? "" }))
35525
+ };
35526
+ }
35527
+ async getWalletHoldings() {
35528
+ const usdceToken = Global.getDefaultTokens().find((token) => token.symbol === "USDCe");
35529
+ const wbtcToken = Global.getDefaultTokens().find((token) => token.symbol === "WBTC");
35530
+ const usdcToken = Global.getDefaultTokens().find((token) => token.symbol === "USDC");
35531
+ if (!usdceToken || !wbtcToken || !usdcToken) {
35532
+ return [];
35533
+ }
35534
+ const walletAddress = this.metadata.additionalInfo.walletAddress;
35535
+ const usdceWalletBalance = await new ERC20(this.config).balanceOf(
35536
+ usdceToken.address,
35537
+ walletAddress,
35538
+ usdceToken.decimals
35539
+ );
35540
+ const usdcWalletBalance = await new ERC20(this.config).balanceOf(
35541
+ usdcToken.address,
35542
+ walletAddress,
35543
+ usdcToken.decimals
35544
+ );
35545
+ const wbtcWalletBalance = await new ERC20(this.config).balanceOf(
35546
+ wbtcToken.address,
35547
+ walletAddress,
35548
+ wbtcToken.decimals
35549
+ );
35550
+ const price = await this.pricer.getPrice(usdceToken.symbol);
35551
+ const wbtcPrice = await this.pricer.getPrice(wbtcToken.symbol);
35552
+ const usdceUsdValue = Number(usdceWalletBalance.toFixed(usdceToken.decimals)) * price.price;
35553
+ const usdcUsdValue = Number(usdcWalletBalance.toFixed(usdcToken.decimals)) * price.price;
35554
+ const wbtcUsdValue = Number(wbtcWalletBalance.toFixed(wbtcToken.decimals)) * wbtcPrice.price;
35555
+ return [
35556
+ {
35557
+ tokenInfo: usdceToken,
35558
+ amount: usdceWalletBalance,
35559
+ usdValue: usdceUsdValue
35560
+ },
35561
+ {
35562
+ tokenInfo: usdcToken,
35563
+ amount: usdcWalletBalance,
35564
+ usdValue: usdcUsdValue
35565
+ },
35566
+ {
35567
+ tokenInfo: wbtcToken,
35568
+ amount: wbtcWalletBalance,
35569
+ usdValue: wbtcUsdValue
35570
+ }
35571
+ ];
35572
+ }
34647
35573
  };
34648
- function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendUrl, extendedApiKey, vaultIdExtended) {
35574
+ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
34649
35575
  vaultSettings.leafAdapters = [];
34650
35576
  const wbtcToken = Global.getDefaultTokens().find(
34651
35577
  (token) => token.symbol === lstSymbol
@@ -34669,7 +35595,9 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
34669
35595
  ...baseAdapterConfig,
34670
35596
  avnuContract: AVNU_MIDDLEWARE,
34671
35597
  slippage: 0.01,
34672
- baseUrl: AVNU_QUOTE_URL
35598
+ baseUrl: AVNU_QUOTE_URL,
35599
+ minimumExtendedPriceDifferenceForSwapOpen,
35600
+ maximumExtendedPriceDifferenceForSwapClosing
34673
35601
  });
34674
35602
  const extendedAdapter = new ExtendedAdapter({
34675
35603
  ...baseAdapterConfig,
@@ -34678,14 +35606,17 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
34678
35606
  ],
34679
35607
  vaultIdExtended,
34680
35608
  extendedContract: EXTENDED_CONTRACT,
34681
- extendedBackendUrl,
34682
- extendedApiKey,
35609
+ extendedBackendWriteUrl,
35610
+ extendedBackendReadUrl,
34683
35611
  extendedTimeout: 3e4,
34684
35612
  extendedRetries: 3,
34685
35613
  extendedBaseUrl: "https://api.starknet.extended.exchange",
34686
35614
  extendedMarketName: "BTC-USD",
34687
35615
  extendedPrecision: 5,
34688
- avnuAdapter
35616
+ avnuAdapter,
35617
+ retryDelayForOrderStatus: minimumExtendedRetriesDelayForOrderStatus ?? 3e3,
35618
+ minimumExtendedMovementAmount: minimumExtendedMovementAmount ?? 5
35619
+ //5 usdcs
34689
35620
  });
34690
35621
  const vesuMultiplyAdapter = new VesuMultiplyAdapter({
34691
35622
  poolId: pool1,
@@ -34698,7 +35629,9 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
34698
35629
  supportedPositions: [
34699
35630
  { asset: wbtcToken, isDebt: false },
34700
35631
  { asset: usdcToken, isDebt: true }
34701
- ]
35632
+ ],
35633
+ minimumVesuMovementAmount: minimumVesuMovementAmount ?? 5
35634
+ //5 usdc
34702
35635
  });
34703
35636
  const unusedBalanceAdapter = new UnusedBalanceAdapter({
34704
35637
  ...baseAdapterConfig
@@ -34794,11 +35727,11 @@ function VaultDescription2(lstSymbol, underlyingSymbol) {
34794
35727
  ] });
34795
35728
  }
34796
35729
  var re7UsdcPrimeDevansh = {
34797
- vaultAddress: ContractAddr.from("0x520a2e945dd0762e5284fc1b012f62ca04e238e105eb362d5e0ce208928729d"),
34798
- manager: ContractAddr.from("0x6abe24d31cbc16d7c4acb2421a826f96273e225b4a2d168d91e65123da0bfb9"),
34799
- vaultAllocator: ContractAddr.from("0x6e4f716e22efb164ee4a831233e513f45396ad3be4cff3c07386be0226febed"),
34800
- redeemRequestNFT: ContractAddr.from("0x66060e1874e05506b18e6029188ec49bf231a411ad57642311bbdf3cb22e5f"),
34801
- aumOracle: ContractAddr.from("0x301d883b9b45c76132638e39326b3f464c492599623263d405ec0df991e27ab"),
35730
+ vaultAddress: ContractAddr.from("0x058905be22d6a81792df79425dc9641cf3e1b77f36748631b7d7e5d713a32b55"),
35731
+ manager: ContractAddr.from("0x02648d703783feb2d967cf0520314cb5aa800d69a9426f3e3b317395af44de16"),
35732
+ vaultAllocator: ContractAddr.from("0x07d533c838eab6a4d854dd3aea96a55993fccd35821921970d00bde946b63b6f"),
35733
+ redeemRequestNFT: ContractAddr.from("0x01ef91f08fb99729c00f82fc6e0ece37917bcc43952596c19996259dc8adbbba"),
35734
+ aumOracle: ContractAddr.from("0x030b6acfec162f5d6e72b8a4d2798aedce78fb39de78a8f549f7cd277ae8bc8d"),
34802
35735
  leafAdapters: [],
34803
35736
  adapters: [],
34804
35737
  targetHealthFactor: 1.4,
@@ -34811,14 +35744,15 @@ var re7UsdcPrimeDevansh = {
34811
35744
  Global.getDefaultTokens().find((token) => token.symbol === "WBTC").decimals
34812
35745
  ),
34813
35746
  borrowable_assets: [Global.getDefaultTokens().find((token) => token.symbol === "WBTC")],
34814
- minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP
35747
+ minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP,
35748
+ walletAddress: WALLET_ADDRESS
34815
35749
  };
34816
- var VesuExtendedTestStrategies = (extendedBackendUrl, extendedApiKey, vaultIdExtended) => {
35750
+ var VesuExtendedTestStrategies = (extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) => {
34817
35751
  return [
34818
- getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false, extendedBackendUrl, extendedApiKey, vaultIdExtended)
35752
+ getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing)
34819
35753
  ];
34820
35754
  };
34821
- function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendUrl, extendedApiKey, vaultIdExtended) {
35755
+ function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
34822
35756
  return {
34823
35757
  name: `Extended Test ${underlyingSymbol}`,
34824
35758
  description: getDescription2(lstSymbol, underlyingSymbol),
@@ -34826,7 +35760,7 @@ function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses,
34826
35760
  launchBlock: 0,
34827
35761
  type: "Other",
34828
35762
  depositTokens: [Global.getDefaultTokens().find((token) => token.symbol === underlyingSymbol)],
34829
- additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendUrl, extendedApiKey, vaultIdExtended),
35763
+ additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing),
34830
35764
  risk: {
34831
35765
  riskFactor: _riskFactor3,
34832
35766
  netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),
@@ -39070,11 +40004,13 @@ var deployer_default = Deployer;
39070
40004
  AssetOperationStatus,
39071
40005
  AssetOperationType,
39072
40006
  AutoCompounderSTRK,
40007
+ AvnuAdapter,
39073
40008
  AvnuWrapper,
39074
40009
  BaseAdapter,
39075
40010
  BaseStrategy,
39076
40011
  CommonAdapter,
39077
40012
  ContractAddr,
40013
+ CycleType,
39078
40014
  Deployer,
39079
40015
  ERC20,
39080
40016
  EXTENDED_CONTRACT,
@@ -39103,6 +40039,7 @@ var deployer_default = Deployer;
39103
40039
  PRICE_ROUTER,
39104
40040
  PasswordJsonCryptoUtil,
39105
40041
  PositionSide,
40042
+ PositionTypeAvnuExtended,
39106
40043
  Pragma,
39107
40044
  Pricer,
39108
40045
  PricerBase,
@@ -39152,6 +40089,7 @@ var deployer_default = Deployer;
39152
40089
  calculateExtendedLevergae,
39153
40090
  calculateVesUPositionSizeGivenExtended,
39154
40091
  calculateVesuLeverage,
40092
+ calculateWBTCAmountToMaintainLTV,
39155
40093
  extensionMap,
39156
40094
  getAPIUsingHeadlessBrowser,
39157
40095
  getContractDetails,