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

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,349 @@ 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
+ return dataObject;
30995
+ } catch (err) {
30996
+ logger.error(`No quotes available for this swap: ${err}`);
30997
+ return null;
30998
+ }
30999
+ }
31000
+ async getPriceOfToken(tokenAddress, retries = MAX_RETRIES) {
31001
+ try {
31002
+ const url = `https://starknet.impulse.avnu.fi/v1/tokens/${tokenAddress}/prices/line`;
31003
+ const response = await import_axios9.default.get(url);
31004
+ const length = response.data.length;
31005
+ return response.data[length - 1].value;
31006
+ } catch (err) {
31007
+ if (retries > 0) {
31008
+ await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
31009
+ return this.getPriceOfToken(tokenAddress, retries - 1);
31010
+ } else {
31011
+ logger.error(`Failed to fetch price for ${tokenAddress} after ${MAX_RETRIES} attempts`);
31012
+ return null;
31013
+ }
31014
+ }
31015
+ }
31016
+ };
31017
+
30154
31018
  // src/strategies/universal-strategy.tsx
30155
31019
  var AUMTypes = /* @__PURE__ */ ((AUMTypes2) => {
30156
31020
  AUMTypes2["FINALISED"] = "finalised";
30157
31021
  AUMTypes2["DEFISPRING"] = "defispring";
30158
31022
  return AUMTypes2;
30159
31023
  })(AUMTypes || {});
31024
+ var PositionTypeAvnuExtended = /* @__PURE__ */ ((PositionTypeAvnuExtended2) => {
31025
+ PositionTypeAvnuExtended2["OPEN"] = "open";
31026
+ PositionTypeAvnuExtended2["CLOSE"] = "close";
31027
+ return PositionTypeAvnuExtended2;
31028
+ })(PositionTypeAvnuExtended || {});
30160
31029
  var UNIVERSAL_MANAGE_IDS = /* @__PURE__ */ ((UNIVERSAL_MANAGE_IDS2) => {
30161
31030
  UNIVERSAL_MANAGE_IDS2["FLASH_LOAN"] = "flash_loan_init";
30162
31031
  UNIVERSAL_MANAGE_IDS2["VESU_LEG1"] = "vesu_leg1";
@@ -30184,7 +31053,7 @@ function getContractDetails(settings) {
30184
31053
  }
30185
31054
 
30186
31055
  // src/strategies/svk-strategy.ts
30187
- var import_starknet23 = require("starknet");
31056
+ var import_starknet24 = require("starknet");
30188
31057
 
30189
31058
  // src/data/universal-vault.abi.json
30190
31059
  var universal_vault_abi_default = [
@@ -32511,12 +33380,12 @@ var SVKStrategy = class extends BaseStrategy {
32511
33380
  this.pricer = pricer;
32512
33381
  this.metadata = metadata;
32513
33382
  this.address = metadata.address;
32514
- this.contract = new import_starknet23.Contract({
33383
+ this.contract = new import_starknet24.Contract({
32515
33384
  abi: universal_vault_abi_default,
32516
33385
  address: this.address.address,
32517
33386
  providerOrAccount: this.config.provider
32518
33387
  });
32519
- this.managerContract = new import_starknet23.Contract({
33388
+ this.managerContract = new import_starknet24.Contract({
32520
33389
  abi: vault_manager_abi_default,
32521
33390
  address: this.metadata.additionalInfo.manager.address,
32522
33391
  providerOrAccount: this.config.provider
@@ -32629,7 +33498,7 @@ var SVKStrategy = class extends BaseStrategy {
32629
33498
  getSetManagerCall(strategist, root = this.getMerkleRoot()) {
32630
33499
  return this.managerContract.populate("set_manage_root", [
32631
33500
  strategist.address,
32632
- import_starknet23.num.getHexString(root)
33501
+ import_starknet24.num.getHexString(root)
32633
33502
  ]);
32634
33503
  }
32635
33504
  /**
@@ -33337,7 +34206,8 @@ function getLooperSettings(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
33337
34206
  minHealthFactor: vaultSettings.minHealthFactor,
33338
34207
  quoteAmountToFetchPrice: vaultSettings.quoteAmountToFetchPrice,
33339
34208
  ...baseAdapterConfig,
33340
- supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }]
34209
+ supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }],
34210
+ minimumVesuMovementAmount: 0
33341
34211
  }));
33342
34212
  const unusedBalanceAdapter = new UnusedBalanceAdapter({
33343
34213
  ...baseAdapterConfig
@@ -33566,335 +34436,15 @@ var HyperLSTStrategies = [
33566
34436
  getStrategySettings("mRe7YIELD", "mRe7YIELD", hypermRe7YIELD, false, false)
33567
34437
  ];
33568
34438
 
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
- };
34439
+ // src/strategies/vesu-extended-strategy/types/transaction-metadata.ts
34440
+ var CycleType = /* @__PURE__ */ ((CycleType2) => {
34441
+ CycleType2["INVESTMENT"] = "INVESTMENT";
34442
+ CycleType2["REBALANCE_PRICE_DROP"] = "REBALANCE_PRICE_DROP";
34443
+ CycleType2["REBALANCE_PRICE_RISE"] = "REBALANCE_PRICE_RISE";
34444
+ CycleType2["WITHDRAWAL"] = "WITHDRAWAL";
34445
+ CycleType2["DELTA_NEUTRAL_ADJUSTMENT"] = "DELTA_NEUTRAL_ADJUSTMENT";
34446
+ return CycleType2;
34447
+ })(CycleType || {});
33898
34448
 
33899
34449
  // src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx
33900
34450
  var import_jsx_runtime5 = require("react/jsx-runtime");
@@ -33994,15 +34544,30 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
33994
34544
  const usdceToken = Global.getDefaultTokens().find(
33995
34545
  (token) => token.symbol === "USDCe"
33996
34546
  );
34547
+ const walletBalance = await new ERC20(this.config).balanceOf(
34548
+ usdceToken.address,
34549
+ WALLET_ADDRESS,
34550
+ usdceToken.decimals
34551
+ );
34552
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssetsToVaultAllocator walletBalance: ${walletBalance}`);
34553
+ const amountToBeTransferred = amount.minimum(walletBalance);
34554
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssetsToVaultAllocator amountToBeTransferred: ${amountToBeTransferred.toNumber()}`);
34555
+ if (amountToBeTransferred.lessThan(0)) {
34556
+ logger.error(`${_VesuExtendedMultiplierStrategy.name}::moveAssetsToVaultAllocator amountToBeTransferred is less than 0: ${amountToBeTransferred.toNumber()}`);
34557
+ return {
34558
+ calls: [],
34559
+ status: false
34560
+ };
34561
+ }
33997
34562
  const approveCall = new ERC20(this.config).approve(
33998
34563
  usdceToken.address,
33999
34564
  this.metadata.additionalInfo.vaultAllocator,
34000
- amount
34565
+ amountToBeTransferred
34001
34566
  );
34002
34567
  const transferCall = new ERC20(this.config).transfer(
34003
34568
  usdceToken.address,
34004
34569
  this.metadata.additionalInfo.vaultAllocator,
34005
- amount
34570
+ amountToBeTransferred
34006
34571
  );
34007
34572
  const proofsInfo = extendedAdapter.getProofsForFromLegacySwap(
34008
34573
  this.getMerkleTree()
@@ -34010,21 +34575,29 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34010
34575
  const proofGroups = proofsInfo.proofs;
34011
34576
  const call = this.getManageCall(
34012
34577
  proofGroups,
34013
- await proofsInfo.callConstructor({ amount })
34578
+ await proofsInfo.callConstructor({ amount: amountToBeTransferred })
34014
34579
  );
34015
- return [approveCall, transferCall, call];
34580
+ return {
34581
+ calls: [approveCall, transferCall, call],
34582
+ status: true
34583
+ };
34016
34584
  } catch (err) {
34017
34585
  logger.error(`error moving assets to vault allocator: ${err}`);
34018
- return [];
34586
+ return {
34587
+ calls: [],
34588
+ status: false
34589
+ };
34019
34590
  }
34020
34591
  }
34021
34592
  async shouldInvest() {
34022
34593
  try {
34594
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest starting`);
34023
34595
  const vesuAdapter = await this.getVesuAdapter();
34024
34596
  const extendedAdapter = await this.getExtendedAdapter();
34025
- if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
34597
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest adapters fetched: vesuAdapter=${!!vesuAdapter}, extendedAdapter=${!!extendedAdapter}, extendedAdapter.client=${!!extendedAdapter?.client}`);
34598
+ if (!vesuAdapter) {
34026
34599
  logger.error(
34027
- `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
34600
+ `Vesu adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
34028
34601
  );
34029
34602
  return {
34030
34603
  shouldInvest: false,
@@ -34036,10 +34609,87 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34036
34609
  vesuLeverage: 0
34037
34610
  };
34038
34611
  }
34612
+ if (!extendedAdapter) {
34613
+ logger.error(
34614
+ `Extended adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
34615
+ );
34616
+ return {
34617
+ shouldInvest: false,
34618
+ vesuAmount: new Web3Number(0, 0),
34619
+ extendedAmount: new Web3Number(0, 0),
34620
+ extendedLeverage: 0,
34621
+ collateralPrice: 0,
34622
+ debtPrice: 0,
34623
+ vesuLeverage: 0
34624
+ };
34625
+ }
34626
+ if (!extendedAdapter.client) {
34627
+ logger.error(
34628
+ `Extended adapter client not initialized. This may be a temporary initialization failure - check network connectivity and API availability.`
34629
+ );
34630
+ return {
34631
+ shouldInvest: false,
34632
+ vesuAmount: new Web3Number(0, 0),
34633
+ extendedAmount: new Web3Number(0, 0),
34634
+ extendedLeverage: 0,
34635
+ collateralPrice: 0,
34636
+ debtPrice: 0,
34637
+ vesuLeverage: 0
34638
+ };
34639
+ }
34640
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest calling getUnusedBalance`);
34039
34641
  const balance = await this.getUnusedBalance();
34642
+ if (!Number.isFinite(balance.usdValue) || balance.usdValue < 0) {
34643
+ logger.error(
34644
+ `Invalid balance.usdValue: ${balance.usdValue}. Expected a finite, non-negative number.`
34645
+ );
34646
+ return {
34647
+ shouldInvest: false,
34648
+ vesuAmount: new Web3Number(0, 0),
34649
+ extendedAmount: new Web3Number(0, 0),
34650
+ extendedLeverage: 0,
34651
+ collateralPrice: 0,
34652
+ debtPrice: 0,
34653
+ vesuLeverage: 0
34654
+ };
34655
+ }
34656
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest balance: ${balance.usdValue}`);
34040
34657
  const usdcBalanceOnExtended = await extendedAdapter.getExtendedDepositAmount();
34041
- const amountToInvest = balance.amount.plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).minus(LIMIT_BALANCE);
34042
- if (amountToInvest.lessThan(0)) {
34658
+ if (usdcBalanceOnExtended) {
34659
+ const availableForWithdrawal = parseFloat(usdcBalanceOnExtended.availableForWithdrawal);
34660
+ if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
34661
+ logger.error(
34662
+ `Invalid usdcBalanceOnExtended.availableForWithdrawal: ${usdcBalanceOnExtended.availableForWithdrawal}. Expected a finite, non-negative number.`
34663
+ );
34664
+ return {
34665
+ shouldInvest: false,
34666
+ vesuAmount: new Web3Number(0, 0),
34667
+ extendedAmount: new Web3Number(0, 0),
34668
+ extendedLeverage: 0,
34669
+ collateralPrice: 0,
34670
+ debtPrice: 0,
34671
+ vesuLeverage: 0
34672
+ };
34673
+ }
34674
+ }
34675
+ const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).multipliedBy(1 - LIMIT_BALANCE);
34676
+ const amountToInvestNumber = amountToInvest.toNumber();
34677
+ if (!Number.isFinite(amountToInvestNumber)) {
34678
+ logger.error(
34679
+ `Invalid amountToInvest calculation result: ${amountToInvestNumber}. Calculation may have produced NaN or Infinity.`
34680
+ );
34681
+ return {
34682
+ shouldInvest: false,
34683
+ vesuAmount: new Web3Number(0, 0),
34684
+ extendedAmount: new Web3Number(0, 0),
34685
+ extendedLeverage: 0,
34686
+ collateralPrice: 0,
34687
+ debtPrice: 0,
34688
+ vesuLeverage: 0
34689
+ };
34690
+ }
34691
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvestNumber}`);
34692
+ if (amountToInvest.lessThan(LIMIT_BALANCE_VALUE)) {
34043
34693
  return {
34044
34694
  shouldInvest: false,
34045
34695
  vesuAmount: new Web3Number(0, 0),
@@ -34068,6 +34718,34 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34068
34718
  collateralPrice,
34069
34719
  debtPrice
34070
34720
  } = await this.getAssetPrices();
34721
+ if (!Number.isFinite(collateralPrice.price) || collateralPrice.price <= 0) {
34722
+ logger.error(
34723
+ `Invalid collateralPrice: ${collateralPrice.price}. Expected a finite, positive number.`
34724
+ );
34725
+ return {
34726
+ shouldInvest: false,
34727
+ vesuAmount: new Web3Number(0, 0),
34728
+ extendedAmount: new Web3Number(0, 0),
34729
+ extendedLeverage: 0,
34730
+ collateralPrice: 0,
34731
+ debtPrice: 0,
34732
+ vesuLeverage: 0
34733
+ };
34734
+ }
34735
+ if (!Number.isFinite(debtPrice.price) || debtPrice.price <= 0) {
34736
+ logger.error(
34737
+ `Invalid debtPrice: ${debtPrice.price}. Expected a finite, positive number.`
34738
+ );
34739
+ return {
34740
+ shouldInvest: false,
34741
+ vesuAmount: new Web3Number(0, 0),
34742
+ extendedAmount: new Web3Number(0, 0),
34743
+ extendedLeverage: 0,
34744
+ collateralPrice: 0,
34745
+ debtPrice: 0,
34746
+ vesuLeverage: 0
34747
+ };
34748
+ }
34071
34749
  const { vesu_amount, extended_amount, extended_leverage, vesu_leverage } = await calculateAmountDistribution(
34072
34750
  amountToInvest.toNumber(),
34073
34751
  extendedAdapter.client,
@@ -34091,6 +34769,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34091
34769
  vesuLeverage: 0
34092
34770
  };
34093
34771
  }
34772
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest vesu_amount: ${vesu_amount.toNumber()}, extended_amount: ${extended_amount.toNumber()}`);
34094
34773
  return {
34095
34774
  shouldInvest: true,
34096
34775
  vesuAmount: vesu_amount,
@@ -34117,111 +34796,251 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34117
34796
  try {
34118
34797
  const vesuAdapter = await this.getVesuAdapter();
34119
34798
  const extendedAdapter = await this.getExtendedAdapter();
34120
- let calls = [];
34121
34799
  if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
34122
34800
  logger.error(
34123
34801
  `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
34124
34802
  );
34125
- return calls;
34803
+ return [];
34126
34804
  }
34127
- if (extendedAmount.lessThan(0)) {
34805
+ const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
34806
+ if (!extendedHoldings) {
34807
+ logger.error(`error getting extended holdings: ${extendedHoldings}`);
34808
+ return [];
34809
+ }
34810
+ const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
34811
+ const usdcAmountOnExtendedAvailableForWithdrawal = parseFloat(
34812
+ extendedHoldings.availableForWithdrawal
34813
+ );
34814
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculating movements - Extended current: ${usdcAmountOnExtendedAvailableForWithdrawal}, Wallet: ${usdcAmountInWallet.toNumber()}, Target Extended: ${extendedAmount.toNumber()}, Target Vesu: ${vesuAmount.toNumber()}`);
34815
+ let totalExtendedWithdrawal = new Web3Number(0, USDC_TOKEN_DECIMALS);
34816
+ let totalExtendedDeposit = new Web3Number(0, USDC_TOKEN_DECIMALS);
34817
+ if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
34818
+ totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmount.abs());
34819
+ }
34820
+ const extendedTargetAmount = extendedAmount.abs();
34821
+ let projectedExtendedBalance = usdcAmountOnExtendedAvailableForWithdrawal;
34822
+ if (extendedAmount.isNegative()) {
34823
+ projectedExtendedBalance = projectedExtendedBalance - extendedAmount.abs().toNumber();
34824
+ }
34825
+ const extendedAmountDifference = extendedTargetAmount.minus(projectedExtendedBalance);
34826
+ const extendedAmountDifferenceAbs = extendedAmountDifference.abs();
34827
+ if (extendedAmountDifference.lessThan(0)) {
34828
+ totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmountDifferenceAbs);
34829
+ } else if (extendedAmountDifference.greaterThan(0)) {
34830
+ totalExtendedDeposit = totalExtendedDeposit.plus(extendedAmountDifference);
34831
+ }
34832
+ const vesuTargetAmount = vesuAmount.abs();
34833
+ const projectedWalletBalance = usdcAmountInWallet.plus(totalExtendedWithdrawal).minus(totalExtendedDeposit);
34834
+ let vesuAmountDifference = vesuTargetAmount.minus(projectedWalletBalance);
34835
+ const vesuAmountDifferenceAbs = vesuAmountDifference.abs();
34836
+ 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()}`);
34837
+ let calls = [];
34838
+ let transactionResults = [];
34839
+ if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
34128
34840
  try {
34129
- const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
34841
+ const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
34130
34842
  {
34131
34843
  to: Protocols.VAULT.name,
34132
34844
  from: Protocols.EXTENDED.name,
34133
- amount: extendedAmount.abs()
34845
+ amount: extendedAmount.abs(),
34846
+ cycleType: "INVESTMENT" /* INVESTMENT */
34134
34847
  },
34135
34848
  extendedAdapter,
34136
34849
  vesuAdapter
34137
34850
  );
34138
34851
  if (extendedStatus) {
34139
- calls.push(...extendedCalls);
34852
+ transactionResults.push({
34853
+ status: extendedStatus,
34854
+ calls: extendedCalls,
34855
+ transactionMetadata: {
34856
+ ...extendedTransactionMetadata,
34857
+ transactionType: "DEPOSIT"
34858
+ }
34859
+ });
34140
34860
  } else {
34141
- return [];
34861
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmount.abs() }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34142
34862
  }
34143
34863
  } catch (err) {
34144
34864
  logger.error(`Failed moving assets to vault: ${err}`);
34865
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmount.abs() }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34145
34866
  }
34146
34867
  }
34147
- if (vesuAmount.lessThan(0)) {
34868
+ if (vesuAmount.isNegative() && vesuAmount.abs().greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
34148
34869
  try {
34149
- const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
34870
+ const { calls: vesuCalls, status: vesuStatus, transactionMetadata: vesuTransactionMetadata } = await this.moveAssets(
34150
34871
  {
34151
34872
  to: Protocols.EXTENDED.name,
34152
34873
  from: Protocols.VESU.name,
34153
- amount: vesuAmount.abs()
34874
+ amount: vesuAmount.abs(),
34875
+ cycleType: "INVESTMENT" /* INVESTMENT */
34154
34876
  },
34155
34877
  extendedAdapter,
34156
34878
  vesuAdapter
34157
34879
  );
34158
- calls.push(...vesuCalls);
34159
34880
  if (!vesuStatus) {
34160
- return [];
34161
- }
34881
+ return [this.createTransactionResult([], false, { from: Protocols.VESU.name, to: Protocols.EXTENDED.name, amount: vesuAmount.abs() }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34882
+ }
34883
+ transactionResults.push({
34884
+ status: vesuStatus,
34885
+ calls: vesuCalls,
34886
+ transactionMetadata: {
34887
+ ...vesuTransactionMetadata,
34888
+ transactionType: "DEPOSIT"
34889
+ }
34890
+ });
34162
34891
  } catch (err) {
34163
- logger.error(`Failed moving assets to vault: ${err}`);
34892
+ logger.error(`Failed moving assets to extended via vault allocator: ${err}`);
34893
+ return [this.createTransactionResult([], false, { from: Protocols.VESU.name, to: Protocols.EXTENDED.name, amount: vesuAmount.abs() }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34164
34894
  }
34165
34895
  }
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}`);
34896
+ if (extendedAmountDifferenceAbs.greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
34897
+ if (extendedAmountDifference.greaterThan(0)) {
34898
+ try {
34899
+ const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
34900
+ {
34901
+ to: Protocols.EXTENDED.name,
34902
+ from: Protocols.VAULT.name,
34903
+ amount: extendedAmountDifference,
34904
+ cycleType: "INVESTMENT" /* INVESTMENT */
34905
+ },
34906
+ extendedAdapter,
34907
+ vesuAdapter
34908
+ );
34909
+ if (extendedStatus) {
34910
+ transactionResults.push({
34911
+ status: extendedStatus,
34912
+ calls: extendedCalls,
34913
+ transactionMetadata: extendedTransactionMetadata
34914
+ });
34915
+ } else {
34916
+ logger.error(`Failed to move assets to extended - operation returned false status`);
34917
+ return [this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.EXTENDED.name, amount: extendedAmountDifference }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34918
+ }
34919
+ } catch (err) {
34920
+ logger.error(`Failed moving assets to extended: ${err}`);
34921
+ return [this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.EXTENDED.name, amount: extendedAmountDifference }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34922
+ }
34923
+ } else if (extendedAmountDifference.lessThan(0)) {
34924
+ try {
34925
+ const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
34926
+ {
34927
+ to: Protocols.VAULT.name,
34928
+ from: Protocols.EXTENDED.name,
34929
+ amount: extendedAmountDifferenceAbs,
34930
+ cycleType: "INVESTMENT" /* INVESTMENT */
34931
+ },
34932
+ extendedAdapter,
34933
+ vesuAdapter
34934
+ );
34935
+ if (extendedStatus) {
34936
+ transactionResults.push({
34937
+ status: extendedStatus,
34938
+ calls: extendedCalls,
34939
+ transactionMetadata: {
34940
+ ...extendedTransactionMetadata,
34941
+ transactionType: "DEPOSIT"
34942
+ }
34943
+ });
34944
+ } else {
34945
+ logger.error(`Failed to withdraw from extended - operation returned false status`);
34946
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmountDifferenceAbs }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34947
+ }
34948
+ } catch (err) {
34949
+ logger.error(`Failed moving assets from extended to vault: ${err}`);
34950
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmountDifferenceAbs }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34951
+ }
34189
34952
  }
34190
34953
  }
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
34954
+ if (vesuAmountDifferenceAbs.greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
34955
+ if (vesuAmountDifference.lessThanOrEqualTo(0)) {
34956
+ logger.warn(
34957
+ `Vesu amount difference is negative or zero: ${vesuAmountDifference.toNumber()}. Skipping operation.`
34201
34958
  );
34202
- if (!vesuStatus) {
34203
- return [];
34959
+ } else {
34960
+ try {
34961
+ const { calls: vesuCalls, status: vesuStatus, transactionMetadata: vesuTransactionMetadata } = await this.moveAssets(
34962
+ {
34963
+ to: Protocols.VAULT.name,
34964
+ from: Protocols.EXTENDED.name,
34965
+ amount: vesuAmountDifference,
34966
+ cycleType: "INVESTMENT" /* INVESTMENT */
34967
+ },
34968
+ extendedAdapter,
34969
+ vesuAdapter
34970
+ );
34971
+ if (!vesuStatus) {
34972
+ logger.error(`Failed to move assets to vesu - operation returned false status`);
34973
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: vesuAmountDifference }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34974
+ }
34975
+ transactionResults.push({
34976
+ status: vesuStatus,
34977
+ calls: vesuCalls,
34978
+ transactionMetadata: {
34979
+ ...vesuTransactionMetadata,
34980
+ transactionType: "DEPOSIT"
34981
+ }
34982
+ });
34983
+ } catch (err) {
34984
+ logger.error(`Failed moving assets to vault: ${err}`);
34985
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: vesuAmountDifference }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34204
34986
  }
34205
- calls.push(...vesuCalls);
34206
- } catch (err) {
34207
- logger.error(`Failed moving assets to vault: ${err}`);
34208
34987
  }
34209
34988
  }
34210
- return calls;
34989
+ return transactionResults;
34211
34990
  } catch (err) {
34212
34991
  logger.error(`Failed moving assets to vesu: ${err}`);
34213
- return [];
34992
+ return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: new Web3Number(0, USDC_TOKEN_DECIMALS) }, "NONE", "INVESTMENT" /* INVESTMENT */)];
34993
+ }
34994
+ }
34995
+ /**
34996
+ * Helper method to create transaction result with metadata
34997
+ */
34998
+ createTransactionResult(calls, status, params, transactionType, cycleType) {
34999
+ if (status) {
35000
+ return {
35001
+ calls,
35002
+ status,
35003
+ transactionMetadata: {
35004
+ protocolFrom: params.from,
35005
+ protocolTo: params.to,
35006
+ transactionType,
35007
+ usdAmount: params.amount.abs().toFixed(),
35008
+ status: "PENDING",
35009
+ cycleType
35010
+ }
35011
+ };
34214
35012
  }
35013
+ return { calls: [], status: false, transactionMetadata: { protocolFrom: "", protocolTo: "", transactionType: "DEPOSIT", usdAmount: "0", status: "FAILED", cycleType } };
34215
35014
  }
34216
35015
  async moveAssets(params, extendedAdapter, vesuAdapter) {
34217
35016
  try {
35017
+ if (params.amount.lessThanOrEqualTo(0)) {
35018
+ logger.error(
35019
+ `Invalid amount for moveAssets: ${params.amount.toNumber()}. Amount must be positive.`
35020
+ );
35021
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
35022
+ }
35023
+ const amountAbs = params.amount.abs();
35024
+ if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
35025
+ if (amountAbs.lessThanOrEqualTo(extendedAdapter.minimumExtendedMovementAmount)) {
35026
+ logger.warn(
35027
+ `Amount ${amountAbs.toNumber()} is below minimum Extended movement amount ${extendedAdapter.minimumExtendedMovementAmount}. Skipping operation.`
35028
+ );
35029
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
35030
+ }
35031
+ }
35032
+ if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
35033
+ if (amountAbs.lessThanOrEqualTo(vesuAdapter.minimumVesuMovementAmount)) {
35034
+ logger.warn(
35035
+ `Amount ${amountAbs.toNumber()} is below minimum Vesu movement amount ${vesuAdapter.minimumVesuMovementAmount}. Skipping operation.`
35036
+ );
35037
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
35038
+ }
35039
+ }
34218
35040
  const avnuAdapter = await this.getAvnuAdapter();
34219
35041
  if (!avnuAdapter) {
34220
35042
  logger.error(`avnu adapter not found: ${avnuAdapter}`);
34221
- return {
34222
- calls: [],
34223
- status: false
34224
- };
35043
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
34225
35044
  }
34226
35045
  logger.info(`moveAssets params, ${JSON.stringify(params)}`);
34227
35046
  const collateralToken = vesuAdapter.config.supportedPositions[0].asset;
@@ -34240,61 +35059,72 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34240
35059
  await proofsInfo.callConstructor({ amount: params.amount })
34241
35060
  );
34242
35061
  calls.push(call);
34243
- return {
34244
- calls: [call],
34245
- status: true
34246
- };
35062
+ return this.createTransactionResult(calls, true, params, "DEPOSIT", params.cycleType);
34247
35063
  } else if (params.to === Protocols.VAULT.name && params.from === Protocols.EXTENDED.name) {
34248
35064
  const extendedLeverage = calculateExtendedLevergae();
34249
35065
  const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
34250
35066
  if (!extendedHoldings) {
34251
35067
  logger.error(`error getting extended holdings: ${extendedHoldings}`);
34252
- return {
34253
- calls: [],
34254
- status: false
34255
- };
35068
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
34256
35069
  }
34257
35070
  const extendedHoldingAmount = new Web3Number(
34258
35071
  extendedHoldings.availableForWithdrawal,
34259
35072
  USDC_TOKEN_DECIMALS
34260
35073
  );
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
- };
35074
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssets extendedHoldingAmount: ${extendedHoldingAmount.toNumber()}`);
35075
+ if (params.amount.abs().greaterThan(extendedHoldingAmount)) {
35076
+ const leftAmountAfterWithdrawalAmountInAccount = params.amount.abs().minus(extendedHoldingAmount);
35077
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssets leftAmountAfterWithdrawalAmountInAccount: ${leftAmountAfterWithdrawalAmountInAccount.toNumber()}`);
35078
+ const btcAmount = leftAmountAfterWithdrawalAmountInAccount.dividedBy(collateralPrice.price);
35079
+ const openLongPosition = btcAmount.multipliedBy(3).greaterThan(MINIMUM_EXTENDED_POSITION_SIZE) ? await extendedAdapter.createOrder(
35080
+ extendedLeverage.toString(),
35081
+ btcAmount.toNumber(),
35082
+ "BUY" /* BUY */
35083
+ ) : await extendedAdapter.createOrder(
35084
+ extendedLeverage.toString(),
35085
+ 34e-6,
35086
+ // just in case amount falls short then we need to create a withdrawal
35087
+ "BUY" /* BUY */
35088
+ );
35089
+ if (!openLongPosition) {
35090
+ logger.error(`error opening long position: ${openLongPosition}`);
35091
+ }
35092
+ const updatedHoldings = await extendedAdapter.getExtendedDepositAmount();
35093
+ if (!updatedHoldings || new Web3Number(updatedHoldings.availableForWithdrawal, USDC_TOKEN_DECIMALS).lessThan(params.amount.abs())) {
35094
+ logger.error(`Insufficient balance after opening position. Available: ${updatedHoldings?.availableForWithdrawal}, Needed: ${params.amount.abs()}`);
35095
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
35096
+ }
34274
35097
  }
34275
- await new Promise((resolve) => setTimeout(resolve, 5e3));
34276
- const withdrawalFromExtended = await extendedAdapter.withdrawFromExtended(params.amount);
34277
- if (withdrawalFromExtended) {
35098
+ const {
35099
+ status: withdrawalFromExtendedStatus,
35100
+ receivedTxnHash: withdrawalFromExtendedTxnHash
35101
+ } = await extendedAdapter.withdrawFromExtended(params.amount);
35102
+ logger.info(`withdrawalFromExtendedStatus: ${withdrawalFromExtendedStatus}, withdrawalFromExtendedTxnHash: ${withdrawalFromExtendedTxnHash}`);
35103
+ if (withdrawalFromExtendedStatus && withdrawalFromExtendedTxnHash) {
34278
35104
  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
- };
35105
+ logger.info(`extendedHoldings after withdrawal ${extendedHoldings2?.availableForWithdrawal}`);
35106
+ await new Promise((resolve) => setTimeout(resolve, 5e3));
35107
+ const { calls, status } = await this.moveAssetsToVaultAllocator(params.amount, extendedAdapter);
35108
+ if (calls.length > 0 && status) {
35109
+ return this.createTransactionResult(calls, true, params, "WITHDRAWAL", params.cycleType);
35110
+ } else {
35111
+ return this.createTransactionResult([], true, params, "WITHDRAWAL", params.cycleType);
34287
35112
  }
35113
+ } else if (withdrawalFromExtendedStatus && !withdrawalFromExtendedTxnHash) {
35114
+ logger.error("withdrawal from extended successful, but funds didn't get transferred to the wallet");
35115
+ return this.createTransactionResult([], true, params, "WITHDRAWAL", params.cycleType);
34288
35116
  } else {
34289
35117
  logger.error("withdrawal from extended failed");
34290
- return {
34291
- calls: [],
34292
- status: false
34293
- };
35118
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
34294
35119
  }
34295
35120
  } else if (params.to === Protocols.VAULT.name && params.from === Protocols.VESU.name) {
35121
+ const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "close" /* CLOSE */);
35122
+ if (!isPriceDifferenceBetweenAvnuAndExtended) {
35123
+ logger.warn(`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
35124
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
35125
+ }
34296
35126
  const vesuAmountInBTC = new Web3Number(
34297
- params.amount.dividedBy(collateralPrice.price).toNumber(),
35127
+ params.amount.dividedBy(collateralPrice.price).toFixed(WBTC_TOKEN_DECIMALS),
34298
35128
  collateralToken.decimals
34299
35129
  );
34300
35130
  const proofsInfo = vesuAdapter.getProofs(false, this.getMerkleTree());
@@ -34312,11 +35142,13 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34312
35142
  await swapProofsInfo.callConstructor({ amount: vesuAmountInBTC })
34313
35143
  );
34314
35144
  calls.push(swapCall);
34315
- return {
34316
- calls,
34317
- status: true
34318
- };
35145
+ return this.createTransactionResult(calls, true, params, "WITHDRAWAL", params.cycleType);
34319
35146
  } else if (params.to === Protocols.EXTENDED.name && params.from === Protocols.VESU.name) {
35147
+ const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "close" /* CLOSE */);
35148
+ if (!isPriceDifferenceBetweenAvnuAndExtended) {
35149
+ logger.warn(`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
35150
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
35151
+ }
34320
35152
  const vesuAmountInBTC = new Web3Number(
34321
35153
  params.amount.dividedBy(collateralPrice.price).toNumber(),
34322
35154
  collateralToken.decimals
@@ -34346,131 +35178,32 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34346
35178
  await proofsInfoDeposit.callConstructor({ amount: params.amount })
34347
35179
  );
34348
35180
  calls.push(callDeposit);
34349
- return {
34350
- calls,
34351
- status: true
34352
- };
35181
+ return this.createTransactionResult(calls, true, params, "DEPOSIT", params.cycleType);
34353
35182
  }
34354
- return {
34355
- calls: [],
34356
- status: false
34357
- };
35183
+ logger.error(`Unsupported assets movement: ${params.from} to ${params.to}`);
35184
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
34358
35185
  } catch (err) {
34359
35186
  logger.error(`error moving assets: ${err}`);
34360
- return {
34361
- calls: [],
34362
- status: false
34363
- };
35187
+ return this.createTransactionResult([], false, params, "NONE", params.cycleType);
34364
35188
  }
34365
35189
  }
34366
35190
  async handleDeposit() {
34367
35191
  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
- };
35192
+ return this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.VAULT.name, amount: new Web3Number(0, 0) }, "NONE", "INVESTMENT" /* INVESTMENT */);
34464
35193
  } catch (err) {
34465
35194
  logger.error(`error handling deposit: ${err}`);
34466
- return {
34467
- extendedAmountInBTC: new Web3Number(0, 0),
34468
- calls: []
34469
- };
34470
- ;
35195
+ return this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.VAULT.name, amount: new Web3Number(0, 0) }, "NONE", "INVESTMENT" /* INVESTMENT */);
34471
35196
  }
34472
35197
  }
34473
- async checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter) {
35198
+ /**
35199
+ * Check if the price difference between avnu and extended is within the acceptable range to enhance the position size or close the position
35200
+ * @param extendedAdapter - the extended adapter
35201
+ * @param vesuAdapter - the vesu adapter
35202
+ * @param avnuAdapter - the avnu adapter
35203
+ * @param positionType - the position type (open or close)
35204
+ * @returns true if the price difference is within the acceptable range, false otherwise
35205
+ */
35206
+ async checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, positionType) {
34474
35207
  const {
34475
35208
  ask,
34476
35209
  bid
@@ -34482,13 +35215,30 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34482
35215
  logger.error(`error getting btc price avnu: ${btcPriceAvnu}`);
34483
35216
  return false;
34484
35217
  }
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;
35218
+ logger.info(`price: ${price}`);
35219
+ logger.info(`btcPriceAvnu: ${btcPriceAvnu}`);
35220
+ const priceDifference = new Web3Number(price.minus(btcPriceAvnu).toFixed(2), 0);
35221
+ logger.info(`priceDifference: ${priceDifference}`);
35222
+ if (priceDifference.isNegative()) {
35223
+ return false;
35224
+ }
35225
+ if (positionType === "open" /* OPEN */) {
35226
+ logger.info(`price difference between avnu and extended for open position: ${priceDifference.toNumber()}, minimumExtendedPriceDifferenceForSwapOpen: ${avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen}`);
35227
+ const result = priceDifference.greaterThanOrEqualTo(avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen);
35228
+ logger.info(`result: ${result}`);
35229
+ return result;
35230
+ } else {
35231
+ logger.info(`price difference between avnu and extended for close position: ${priceDifference.toNumber()}, maximumExtendedPriceDifferenceForSwapClosing: ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
35232
+ const result = priceDifference.lessThanOrEqualTo(avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing);
35233
+ logger.info(`result: ${result}`);
35234
+ return result;
34488
35235
  }
34489
- logger.error(`price difference between avnu and extended doesn't fit the range, priceDifference: ${priceDifference}`);
34490
- return false;
34491
35236
  }
35237
+ /**
35238
+ * Handle the withdrawal of assets from the vault
35239
+ * @param amount - the amount to withdraw in USDC
35240
+ * @returns the calls to be executed and the status of the calls generated along with the metadata for the calls
35241
+ */
34492
35242
  async handleWithdraw(amount) {
34493
35243
  try {
34494
35244
  const usdcBalanceVaultAllocator = await this.getUnusedBalance();
@@ -34500,12 +35250,8 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34500
35250
  const withdrawCall2 = await this.getBringLiquidityCall({
34501
35251
  amount: usdcBalanceVaultAllocator.amount
34502
35252
  });
34503
- logger.info("withdraw call", withdrawCall2);
34504
35253
  calls.push(withdrawCall2);
34505
- return {
34506
- calls,
34507
- status: true
34508
- };
35254
+ return [this.createTransactionResult(calls, true, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "WITHDRAWAL", "WITHDRAWAL" /* WITHDRAWAL */)];
34509
35255
  }
34510
35256
  const vesuAdapter = await this.getVesuAdapter();
34511
35257
  const extendedAdapter = await this.getExtendedAdapter();
@@ -34514,11 +35260,9 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34514
35260
  logger.error(
34515
35261
  `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
34516
35262
  );
34517
- return {
34518
- calls,
34519
- status
34520
- };
35263
+ return [this.createTransactionResult(calls, status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
34521
35264
  }
35265
+ let transactionResults = [];
34522
35266
  const { collateralTokenAmount } = await vesuAdapter.vesuAdapter.getAssetPrices();
34523
35267
  const {
34524
35268
  collateralPrice
@@ -34527,10 +35271,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34527
35271
  if (!extendedPositon) {
34528
35272
  status = false;
34529
35273
  logger.error("error getting extended position", extendedPositon);
34530
- return {
34531
- calls,
34532
- status
34533
- };
35274
+ return [this.createTransactionResult(calls, status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
34534
35275
  }
34535
35276
  const amountDistributionForWithdrawal = await calculateAmountDistributionForWithdrawal(
34536
35277
  usdcBalanceDifference,
@@ -34543,61 +35284,70 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34543
35284
  logger.error(
34544
35285
  `error calculating amount distribution for withdrawal: ${amountDistributionForWithdrawal}`
34545
35286
  );
34546
- return {
34547
- calls,
34548
- status
34549
- };
35287
+ return [this.createTransactionResult(calls, status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
34550
35288
  }
34551
35289
  const { vesu_amount, extended_amount } = amountDistributionForWithdrawal;
34552
35290
  if (status && vesu_amount.greaterThan(0)) {
34553
- const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
35291
+ const { calls: vesuCalls, status: vesuStatus, transactionMetadata: vesuTransactionMetadata } = await this.moveAssets(
34554
35292
  {
34555
35293
  amount: vesu_amount,
34556
35294
  from: Protocols.VESU.name,
34557
- to: Protocols.VAULT.name
35295
+ to: Protocols.VAULT.name,
35296
+ cycleType: "WITHDRAWAL" /* WITHDRAWAL */
34558
35297
  },
34559
35298
  extendedAdapter,
34560
35299
  vesuAdapter
34561
35300
  );
34562
35301
  status = vesuStatus;
34563
- calls.push(...vesuCalls);
35302
+ transactionResults.push({
35303
+ status: vesuStatus,
35304
+ calls: vesuCalls,
35305
+ transactionMetadata: vesuTransactionMetadata
35306
+ });
34564
35307
  }
34565
35308
  if (status && extended_amount.greaterThan(0)) {
34566
- const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
35309
+ const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
34567
35310
  {
34568
35311
  amount: extended_amount,
34569
35312
  from: Protocols.EXTENDED.name,
34570
- to: Protocols.VAULT.name
35313
+ to: Protocols.VAULT.name,
35314
+ cycleType: "WITHDRAWAL" /* WITHDRAWAL */
34571
35315
  },
34572
35316
  extendedAdapter,
34573
35317
  vesuAdapter
34574
35318
  );
34575
35319
  status = extendedStatus;
34576
35320
  if (status) {
34577
- calls.push(...extendedCalls);
35321
+ transactionResults.push({
35322
+ status: extendedStatus,
35323
+ calls: extendedCalls,
35324
+ transactionMetadata: extendedTransactionMetadata
35325
+ });
34578
35326
  } else {
34579
35327
  logger.error("error moving assets to vault: extendedStatus: ${extendedStatus}");
34580
- return {
34581
- calls: [],
34582
- status
34583
- };
35328
+ return [this.createTransactionResult([], status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
34584
35329
  }
34585
35330
  }
34586
35331
  const withdrawCall = await this.getBringLiquidityCall({
34587
35332
  amount
34588
35333
  });
34589
35334
  logger.info("withdraw call", withdrawCall);
34590
- calls.push(withdrawCall);
34591
- return {
34592
- calls,
34593
- status
34594
- };
35335
+ transactionResults.push({
35336
+ status,
35337
+ calls: [withdrawCall],
35338
+ transactionMetadata: {
35339
+ protocolFrom: Protocols.VAULT.name,
35340
+ protocolTo: Protocols.NONE.name,
35341
+ transactionType: "WITHDRAWAL",
35342
+ usdAmount: amount.toFixed(),
35343
+ status: "PENDING",
35344
+ cycleType: "WITHDRAWAL" /* WITHDRAWAL */
35345
+ }
35346
+ });
35347
+ return transactionResults;
34595
35348
  } catch (err) {
34596
35349
  logger.error(`error handling withdrawal: ${err}`);
34597
- return {
34598
- calls: [],
34599
- status: false
34600
- };
35350
+ return [this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
34601
35351
  }
34602
35352
  }
34603
35353
  async getAUM() {
@@ -34644,8 +35394,182 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34644
35394
  splits: [realAUM, estimatedAUMDelta]
34645
35395
  };
34646
35396
  }
35397
+ async processTransactionDataFromSDK(txnData) {
35398
+ try {
35399
+ const txnsToBeExecuted = txnData.filter((txn) => {
35400
+ return txn.transactionMetadata.transactionType !== "NONE" && txn.transactionMetadata.protocolFrom !== "" && txn.transactionMetadata.protocolTo !== "";
35401
+ });
35402
+ const callsToBeExecutedFinal = txnsToBeExecuted.flatMap((txn) => txn.calls);
35403
+ const txnMetadata = txnsToBeExecuted.map((txn) => txn.transactionMetadata);
35404
+ return { callsToBeExecutedFinal, txnMetadata };
35405
+ } catch (err) {
35406
+ logger.error(`error processing transaction data from SDK: ${err}`);
35407
+ return null;
35408
+ }
35409
+ }
35410
+ async processTransactionMetadata(txnMetadata, extendedIntentFulfilled) {
35411
+ try {
35412
+ const txnMetadataNew = txnMetadata.map((txn) => {
35413
+ const isExtendedProtocol = txn.protocolFrom === Protocols.EXTENDED.name || txn.protocolTo === Protocols.EXTENDED.name;
35414
+ if (isExtendedProtocol) {
35415
+ txn.status = extendedIntentFulfilled ? "COMPLETED" : "PENDING";
35416
+ } else {
35417
+ txn.status = "COMPLETED";
35418
+ }
35419
+ return txn;
35420
+ });
35421
+ return txnMetadataNew;
35422
+ } catch (err) {
35423
+ logger.error(`error processing transaction data from SDK: ${err}`);
35424
+ return null;
35425
+ }
35426
+ }
35427
+ async getMaxBorrowableAmount() {
35428
+ const vesuAdapter = await this.getVesuAdapter();
35429
+ const extendedAdapter = await this.getExtendedAdapter();
35430
+ if (!vesuAdapter || !extendedAdapter) {
35431
+ return new Web3Number(0, 0);
35432
+ }
35433
+ const extendedFundingRate = new Web3Number((await extendedAdapter.getNetAPY()).toFixed(4), 0);
35434
+ const extendedPositions = await extendedAdapter.getAllOpenPositions();
35435
+ if (!extendedPositions || extendedPositions.length === 0) {
35436
+ logger.info(`no extended positions found`);
35437
+ return new Web3Number(0, 0);
35438
+ }
35439
+ const extendePositionSizeUSD = new Web3Number(extendedPositions[0].value || 0, 0);
35440
+ const vesuPositions = await vesuAdapter.getPositions();
35441
+ const vesuSupplyApy = vesuPositions[0].apy.apy;
35442
+ const vesuCollateralSizeUSD = new Web3Number(vesuPositions[0].usdValue.toFixed(USDC_TOKEN_DECIMALS), USDC_TOKEN_DECIMALS);
35443
+ const vesuDebtSizeUSD = new Web3Number(vesuPositions[1].usdValue.toFixed(USDC_TOKEN_DECIMALS), USDC_TOKEN_DECIMALS);
35444
+ const num1 = extendePositionSizeUSD.multipliedBy(extendedFundingRate);
35445
+ const num22 = vesuCollateralSizeUSD.multipliedBy(vesuSupplyApy);
35446
+ const num32 = vesuDebtSizeUSD.abs();
35447
+ const maxBorrowApy = num1.plus(num22).minus(0.1).dividedBy(num32);
35448
+ const vesuMaxBorrowableAmount = await vesuAdapter.vesuAdapter.getMaxBorrowableByInterestRate(this.config, vesuAdapter.config.debt, maxBorrowApy.toNumber());
35449
+ return new Web3Number(vesuMaxBorrowableAmount.toFixed(USDC_TOKEN_DECIMALS), USDC_TOKEN_DECIMALS);
35450
+ }
35451
+ async getVesuHealthFactors() {
35452
+ const vesuAdapter = await this.getVesuAdapter();
35453
+ const extendedAdapter = await this.getExtendedAdapter();
35454
+ if (!vesuAdapter || !extendedAdapter) {
35455
+ return [0, 0];
35456
+ }
35457
+ const vesuPositions = await vesuAdapter.getPositions();
35458
+ const vesuCollateralSizeUSD = new Web3Number(vesuPositions[0].usdValue.toFixed(USDC_TOKEN_DECIMALS), 0);
35459
+ const vesuDebtSizeUSD = new Web3Number(vesuPositions[1].usdValue.toFixed(USDC_TOKEN_DECIMALS), 0);
35460
+ const actualLtv = vesuDebtSizeUSD.dividedBy(vesuCollateralSizeUSD).abs();
35461
+ logger.info(`actualLtv: ${actualLtv.toNumber()}`);
35462
+ const maxLtv = new Web3Number(await vesuAdapter.vesuAdapter.getLTVConfig(this.config), 4);
35463
+ const healthFactor = new Web3Number(maxLtv.dividedBy(actualLtv).toFixed(4), 4);
35464
+ logger.info(`healthFactor: ${healthFactor.toNumber()}`);
35465
+ const extendedBalance = await extendedAdapter.getExtendedDepositAmount();
35466
+ if (!extendedBalance) {
35467
+ return [0, 0];
35468
+ }
35469
+ const extendedLeverage = new Web3Number((Number(extendedBalance.marginRatio) * 100).toFixed(4), 4);
35470
+ logger.info(`extendedLeverage: ${extendedLeverage.toNumber()}`);
35471
+ return [healthFactor.toNumber(), extendedLeverage.toNumber()];
35472
+ }
35473
+ async netAPY() {
35474
+ const allPositions = [];
35475
+ for (let adapter of this.metadata.additionalInfo.adapters) {
35476
+ if (adapter.adapter.name !== ExtendedAdapter.name) {
35477
+ let positions = await adapter.adapter.getPositions();
35478
+ if (positions.length > 0) {
35479
+ allPositions.push(...positions);
35480
+ }
35481
+ }
35482
+ }
35483
+ const extendedAdapter = await this.getExtendedAdapter();
35484
+ if (!extendedAdapter) {
35485
+ return {
35486
+ net: 0,
35487
+ splits: []
35488
+ };
35489
+ }
35490
+ let vesuPositions = allPositions.filter((item) => item.protocol === Protocols.VESU);
35491
+ vesuPositions.map((item) => {
35492
+ item.apy.apy = item.apy.apy * 0.1;
35493
+ });
35494
+ const extendedPositions = await extendedAdapter.getAllOpenPositions();
35495
+ const usdcToken = Global.getDefaultTokens().find((token) => token.symbol === "USDC");
35496
+ if (!extendedPositions || !usdcToken) {
35497
+ return {
35498
+ net: 0,
35499
+ splits: []
35500
+ };
35501
+ }
35502
+ const extendedPosition = extendedPositions[0] || 0;
35503
+ const extendedEquity = (await extendedAdapter.getExtendedDepositAmount())?.equity || 0;
35504
+ const extendedApy = await extendedAdapter.getNetAPY();
35505
+ const totalHoldingsUSDValue = allPositions.reduce((acc, curr) => acc + curr.usdValue, 0) + Number(extendedEquity);
35506
+ console.log(totalHoldingsUSDValue);
35507
+ const extendedPositionSizeMultipliedByApy = Number(extendedPosition.value) * extendedApy;
35508
+ let weightedAPYs = allPositions.reduce((acc, curr) => acc + curr.apy.apy * curr.usdValue, 0) + extendedPositionSizeMultipliedByApy;
35509
+ console.log(weightedAPYs);
35510
+ const netAPY = weightedAPYs / totalHoldingsUSDValue;
35511
+ console.log(netAPY);
35512
+ allPositions.push({
35513
+ tokenInfo: usdcToken,
35514
+ amount: new Web3Number(extendedPosition.size, 0),
35515
+ usdValue: Number(extendedEquity),
35516
+ apy: { apy: extendedApy, type: "base" /* BASE */ },
35517
+ remarks: "finalised" /* FINALISED */,
35518
+ protocol: Protocols.EXTENDED
35519
+ });
35520
+ return {
35521
+ net: netAPY,
35522
+ splits: allPositions.map((p) => ({ apy: p.apy.apy, id: p.remarks ?? "" }))
35523
+ };
35524
+ }
35525
+ async getWalletHoldings() {
35526
+ const usdceToken = Global.getDefaultTokens().find((token) => token.symbol === "USDCe");
35527
+ const wbtcToken = Global.getDefaultTokens().find((token) => token.symbol === "WBTC");
35528
+ const usdcToken = Global.getDefaultTokens().find((token) => token.symbol === "USDC");
35529
+ if (!usdceToken || !wbtcToken || !usdcToken) {
35530
+ return [];
35531
+ }
35532
+ const walletAddress = this.metadata.additionalInfo.walletAddress;
35533
+ const usdceWalletBalance = await new ERC20(this.config).balanceOf(
35534
+ usdceToken.address,
35535
+ walletAddress,
35536
+ usdceToken.decimals
35537
+ );
35538
+ const usdcWalletBalance = await new ERC20(this.config).balanceOf(
35539
+ usdcToken.address,
35540
+ walletAddress,
35541
+ usdcToken.decimals
35542
+ );
35543
+ const wbtcWalletBalance = await new ERC20(this.config).balanceOf(
35544
+ wbtcToken.address,
35545
+ walletAddress,
35546
+ wbtcToken.decimals
35547
+ );
35548
+ const price = await this.pricer.getPrice(usdceToken.symbol);
35549
+ const wbtcPrice = await this.pricer.getPrice(wbtcToken.symbol);
35550
+ const usdceUsdValue = Number(usdceWalletBalance.toFixed(usdceToken.decimals)) * price.price;
35551
+ const usdcUsdValue = Number(usdcWalletBalance.toFixed(usdcToken.decimals)) * price.price;
35552
+ const wbtcUsdValue = Number(wbtcWalletBalance.toFixed(wbtcToken.decimals)) * wbtcPrice.price;
35553
+ return [
35554
+ {
35555
+ tokenInfo: usdceToken,
35556
+ amount: usdceWalletBalance,
35557
+ usdValue: usdceUsdValue
35558
+ },
35559
+ {
35560
+ tokenInfo: usdcToken,
35561
+ amount: usdcWalletBalance,
35562
+ usdValue: usdcUsdValue
35563
+ },
35564
+ {
35565
+ tokenInfo: wbtcToken,
35566
+ amount: wbtcWalletBalance,
35567
+ usdValue: wbtcUsdValue
35568
+ }
35569
+ ];
35570
+ }
34647
35571
  };
34648
- function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendUrl, extendedApiKey, vaultIdExtended) {
35572
+ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
34649
35573
  vaultSettings.leafAdapters = [];
34650
35574
  const wbtcToken = Global.getDefaultTokens().find(
34651
35575
  (token) => token.symbol === lstSymbol
@@ -34669,7 +35593,9 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
34669
35593
  ...baseAdapterConfig,
34670
35594
  avnuContract: AVNU_MIDDLEWARE,
34671
35595
  slippage: 0.01,
34672
- baseUrl: AVNU_QUOTE_URL
35596
+ baseUrl: AVNU_QUOTE_URL,
35597
+ minimumExtendedPriceDifferenceForSwapOpen,
35598
+ maximumExtendedPriceDifferenceForSwapClosing
34673
35599
  });
34674
35600
  const extendedAdapter = new ExtendedAdapter({
34675
35601
  ...baseAdapterConfig,
@@ -34678,14 +35604,17 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
34678
35604
  ],
34679
35605
  vaultIdExtended,
34680
35606
  extendedContract: EXTENDED_CONTRACT,
34681
- extendedBackendUrl,
34682
- extendedApiKey,
35607
+ extendedBackendWriteUrl,
35608
+ extendedBackendReadUrl,
34683
35609
  extendedTimeout: 3e4,
34684
35610
  extendedRetries: 3,
34685
35611
  extendedBaseUrl: "https://api.starknet.extended.exchange",
34686
35612
  extendedMarketName: "BTC-USD",
34687
35613
  extendedPrecision: 5,
34688
- avnuAdapter
35614
+ avnuAdapter,
35615
+ retryDelayForOrderStatus: minimumExtendedRetriesDelayForOrderStatus ?? 3e3,
35616
+ minimumExtendedMovementAmount: minimumExtendedMovementAmount ?? 5
35617
+ //5 usdcs
34689
35618
  });
34690
35619
  const vesuMultiplyAdapter = new VesuMultiplyAdapter({
34691
35620
  poolId: pool1,
@@ -34698,7 +35627,9 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
34698
35627
  supportedPositions: [
34699
35628
  { asset: wbtcToken, isDebt: false },
34700
35629
  { asset: usdcToken, isDebt: true }
34701
- ]
35630
+ ],
35631
+ minimumVesuMovementAmount: minimumVesuMovementAmount ?? 5
35632
+ //5 usdc
34702
35633
  });
34703
35634
  const unusedBalanceAdapter = new UnusedBalanceAdapter({
34704
35635
  ...baseAdapterConfig
@@ -34794,11 +35725,11 @@ function VaultDescription2(lstSymbol, underlyingSymbol) {
34794
35725
  ] });
34795
35726
  }
34796
35727
  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"),
35728
+ vaultAddress: ContractAddr.from("0x058905be22d6a81792df79425dc9641cf3e1b77f36748631b7d7e5d713a32b55"),
35729
+ manager: ContractAddr.from("0x02648d703783feb2d967cf0520314cb5aa800d69a9426f3e3b317395af44de16"),
35730
+ vaultAllocator: ContractAddr.from("0x07d533c838eab6a4d854dd3aea96a55993fccd35821921970d00bde946b63b6f"),
35731
+ redeemRequestNFT: ContractAddr.from("0x01ef91f08fb99729c00f82fc6e0ece37917bcc43952596c19996259dc8adbbba"),
35732
+ aumOracle: ContractAddr.from("0x030b6acfec162f5d6e72b8a4d2798aedce78fb39de78a8f549f7cd277ae8bc8d"),
34802
35733
  leafAdapters: [],
34803
35734
  adapters: [],
34804
35735
  targetHealthFactor: 1.4,
@@ -34811,14 +35742,15 @@ var re7UsdcPrimeDevansh = {
34811
35742
  Global.getDefaultTokens().find((token) => token.symbol === "WBTC").decimals
34812
35743
  ),
34813
35744
  borrowable_assets: [Global.getDefaultTokens().find((token) => token.symbol === "WBTC")],
34814
- minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP
35745
+ minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP,
35746
+ walletAddress: WALLET_ADDRESS
34815
35747
  };
34816
- var VesuExtendedTestStrategies = (extendedBackendUrl, extendedApiKey, vaultIdExtended) => {
35748
+ var VesuExtendedTestStrategies = (extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) => {
34817
35749
  return [
34818
- getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false, extendedBackendUrl, extendedApiKey, vaultIdExtended)
35750
+ getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing)
34819
35751
  ];
34820
35752
  };
34821
- function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendUrl, extendedApiKey, vaultIdExtended) {
35753
+ function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
34822
35754
  return {
34823
35755
  name: `Extended Test ${underlyingSymbol}`,
34824
35756
  description: getDescription2(lstSymbol, underlyingSymbol),
@@ -34826,7 +35758,7 @@ function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses,
34826
35758
  launchBlock: 0,
34827
35759
  type: "Other",
34828
35760
  depositTokens: [Global.getDefaultTokens().find((token) => token.symbol === underlyingSymbol)],
34829
- additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendUrl, extendedApiKey, vaultIdExtended),
35761
+ additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing),
34830
35762
  risk: {
34831
35763
  riskFactor: _riskFactor3,
34832
35764
  netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),
@@ -39070,11 +40002,13 @@ var deployer_default = Deployer;
39070
40002
  AssetOperationStatus,
39071
40003
  AssetOperationType,
39072
40004
  AutoCompounderSTRK,
40005
+ AvnuAdapter,
39073
40006
  AvnuWrapper,
39074
40007
  BaseAdapter,
39075
40008
  BaseStrategy,
39076
40009
  CommonAdapter,
39077
40010
  ContractAddr,
40011
+ CycleType,
39078
40012
  Deployer,
39079
40013
  ERC20,
39080
40014
  EXTENDED_CONTRACT,
@@ -39103,6 +40037,7 @@ var deployer_default = Deployer;
39103
40037
  PRICE_ROUTER,
39104
40038
  PasswordJsonCryptoUtil,
39105
40039
  PositionSide,
40040
+ PositionTypeAvnuExtended,
39106
40041
  Pragma,
39107
40042
  Pricer,
39108
40043
  PricerBase,
@@ -39152,6 +40087,7 @@ var deployer_default = Deployer;
39152
40087
  calculateExtendedLevergae,
39153
40088
  calculateVesUPositionSizeGivenExtended,
39154
40089
  calculateVesuLeverage,
40090
+ calculateWBTCAmountToMaintainLTV,
39155
40091
  extensionMap,
39156
40092
  getAPIUsingHeadlessBrowser,
39157
40093
  getContractDetails,