@strkfarm/sdk 2.0.0-dev.7 → 2.0.0-dev.8

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.
@@ -29919,8 +29919,47 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29919
29919
  async withdrawFromExtended(amount) {
29920
29920
  try {
29921
29921
  if (!this.client) {
29922
- throw new Error("Client not initialized");
29922
+ logger.error("Client not initialized");
29923
+ return false;
29924
+ }
29925
+ if (amount.lessThanOrEqualTo(0)) {
29926
+ logger.error(
29927
+ `Invalid withdrawal amount: ${amount.toNumber()}. Amount must be positive.`
29928
+ );
29929
+ return false;
29930
+ }
29931
+ if (amount.lessThanOrEqualTo(this.minimumExtendedMovementAmount)) {
29932
+ logger.warn(
29933
+ `Withdrawal amount ${amount.toNumber()} is below minimum Extended movement amount ${this.minimumExtendedMovementAmount}. Skipping withdrawal.`
29934
+ );
29935
+ return false;
29936
+ }
29937
+ const holdings = await this.getExtendedDepositAmount();
29938
+ if (!holdings) {
29939
+ logger.error(
29940
+ "Cannot get holdings - unable to validate withdrawal amount"
29941
+ );
29942
+ return false;
29943
+ }
29944
+ const availableForWithdrawal = parseFloat(
29945
+ holdings.availableForWithdrawal
29946
+ );
29947
+ if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
29948
+ logger.error(
29949
+ `Invalid availableForWithdrawal: ${holdings.availableForWithdrawal}. Expected a finite, non-negative number.`
29950
+ );
29951
+ return false;
29952
+ }
29953
+ const withdrawalAmount = amount.toNumber();
29954
+ if (withdrawalAmount > availableForWithdrawal) {
29955
+ logger.error(
29956
+ `Withdrawal amount ${withdrawalAmount} exceeds available balance ${availableForWithdrawal}`
29957
+ );
29958
+ return false;
29923
29959
  }
29960
+ logger.info(
29961
+ `Withdrawing ${withdrawalAmount} from Extended. Available balance: ${availableForWithdrawal}`
29962
+ );
29924
29963
  const withdrawalRequest = await this.client.withdrawUSDC(
29925
29964
  amount.toFixed(2)
29926
29965
  );
@@ -29931,6 +29970,9 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29931
29970
  );
29932
29971
  return withdrawalStatus;
29933
29972
  }
29973
+ logger.error(
29974
+ `Withdrawal request failed with status: ${withdrawalRequest.status}`
29975
+ );
29934
29976
  return false;
29935
29977
  } catch (error) {
29936
29978
  logger.error(`Error creating Withdraw Call: ${error}`);
@@ -29941,21 +29983,44 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29941
29983
  return Promise.resolve(1);
29942
29984
  }
29943
29985
  async getExtendedDepositAmount() {
29944
- if (this.client === null) {
29945
- logger.error("error initializing client");
29946
- return void 0;
29947
- }
29948
- const result = await this.client.getHoldings();
29949
- if (!result) {
29950
- logger.error(`error getting holdings: ${result}`);
29951
- return void 0;
29952
- }
29953
- const holdings = result.data;
29954
- if (!holdings) {
29955
- logger.error(`error getting holdings: ${holdings}`);
29986
+ try {
29987
+ if (this.client === null) {
29988
+ logger.error("error initializing client - client is null");
29989
+ return void 0;
29990
+ }
29991
+ const result = await this.client.getHoldings();
29992
+ if (!result) {
29993
+ logger.error("error getting holdings - API returned null/undefined");
29994
+ return void 0;
29995
+ }
29996
+ if (result.status && result.status !== "OK") {
29997
+ logger.error(
29998
+ `error getting holdings - API returned status: ${result.status}`
29999
+ );
30000
+ return void 0;
30001
+ }
30002
+ const holdings = result.data;
30003
+ if (!holdings) {
30004
+ logger.warn(
30005
+ "holdings data is null/undefined - treating as zero balance"
30006
+ );
30007
+ return {
30008
+ collateral_name: "",
30009
+ balance: "0",
30010
+ equity: "0",
30011
+ availableForTrade: "0",
30012
+ availableForWithdrawal: "0",
30013
+ unrealisedPnl: "0",
30014
+ initialMargin: "0",
30015
+ marginRatio: "0",
30016
+ updatedTime: Date.now()
30017
+ };
30018
+ }
30019
+ return holdings;
30020
+ } catch (error) {
30021
+ logger.error(`error getting holdings - exception: ${error}`);
29956
30022
  return void 0;
29957
30023
  }
29958
- return holdings;
29959
30024
  }
29960
30025
  async setLeverage(leverage, marketName) {
29961
30026
  if (this.client === null) {
@@ -29997,38 +30062,24 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29997
30062
  return result.data;
29998
30063
  }
29999
30064
  async getOrderStatus(orderId, marketName) {
30000
- if (this.client === null) {
30001
- logger.error("error initializing client");
30002
- return null;
30003
- }
30004
- let orderhistory = await this.getOrderHistory(marketName);
30005
- if (!orderhistory || orderhistory.length === 0) {
30006
- logger.error(`error getting order history: ${orderId}`);
30007
- } else {
30008
- const order = orderhistory.slice(0, 10).find((order2) => order2.id.toString() === orderId);
30009
- if (order) {
30010
- return order;
30065
+ try {
30066
+ if (this.client === null) {
30067
+ logger.error("error initializing client");
30068
+ return null;
30011
30069
  }
30012
- }
30013
- for (let attempt = 1; attempt <= 5; attempt++) {
30014
- await new Promise((resolve) => setTimeout(resolve, this.retryDelayForOrderStatus));
30015
- orderhistory = await this.getOrderHistory(marketName);
30070
+ const orderhistory = await this.getOrderHistory(marketName);
30016
30071
  if (!orderhistory || orderhistory.length === 0) {
30017
- logger.error(
30018
- `error getting order history on retry ${attempt}: ${orderId}`
30019
- );
30020
- continue;
30072
+ return null;
30021
30073
  }
30022
- const order = orderhistory.slice(0, 5).find((order2) => order2.id.toString() === orderId);
30023
- if (order && order.status === "FILLED" /* FILLED */) {
30074
+ const order = orderhistory.slice(0, 20).find((order2) => order2.id.toString() === orderId);
30075
+ if (order) {
30024
30076
  return order;
30025
30077
  }
30026
- logger.error(
30027
- `order not found in top 15 entries on retry ${attempt}: ${orderId}`
30028
- );
30078
+ return null;
30079
+ } catch (error) {
30080
+ logger.error(`error getting order status: ${error}`);
30081
+ return null;
30029
30082
  }
30030
- logger.error(`error getting order after all retries: ${orderId}`);
30031
- return null;
30032
30083
  }
30033
30084
  async fetchOrderBookBTCUSDC() {
30034
30085
  try {
@@ -30079,14 +30130,40 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
30079
30130
  logger.error("error depositing or setting leverage");
30080
30131
  return null;
30081
30132
  }
30082
- const positions = await this.getAllOpenPositions();
30083
- if (positions === null) {
30133
+ const { ask, bid } = await this.fetchOrderBookBTCUSDC();
30134
+ if (!ask || !bid || ask.lessThanOrEqualTo(0) || bid.lessThanOrEqualTo(0)) {
30135
+ logger.error(
30136
+ `Invalid orderbook prices: ask=${ask?.toNumber()}, bid=${bid?.toNumber()}`
30137
+ );
30084
30138
  return null;
30085
30139
  }
30086
- const { ask, bid } = await this.fetchOrderBookBTCUSDC();
30087
30140
  const spread = ask.minus(bid);
30088
- let price = ask.plus(bid).div(2);
30089
- side === "SELL" /* SELL */ ? price = price.minus(spread.times(0.2 * attempt)) : price = price.plus(spread.times(0.2 * attempt));
30141
+ const midPrice = ask.plus(bid).div(2);
30142
+ const MAX_PRICE_DEVIATION_MULTIPLIER = 0.5;
30143
+ const priceAdjustmentMultiplier = Math.min(
30144
+ 0.2 * attempt,
30145
+ MAX_PRICE_DEVIATION_MULTIPLIER
30146
+ );
30147
+ const priceAdjustment = spread.times(priceAdjustmentMultiplier);
30148
+ let price = midPrice;
30149
+ if (side === "SELL" /* SELL */) {
30150
+ price = midPrice.minus(priceAdjustment);
30151
+ } else {
30152
+ price = midPrice.plus(priceAdjustment);
30153
+ }
30154
+ const maxDeviation = midPrice.times(0.5);
30155
+ if (price.minus(midPrice).abs().greaterThan(maxDeviation)) {
30156
+ logger.error(
30157
+ `Price deviation too large on attempt ${attempt}: price=${price.toNumber()}, midPrice=${midPrice.toNumber()}, deviation=${price.minus(midPrice).abs().toNumber()}`
30158
+ );
30159
+ if (attempt >= maxAttempts) {
30160
+ return null;
30161
+ }
30162
+ price = side === "SELL" /* SELL */ ? midPrice.minus(maxDeviation) : midPrice.plus(maxDeviation);
30163
+ }
30164
+ logger.info(
30165
+ `createOrder attempt ${attempt}/${maxAttempts}: side=${side}, midPrice=${midPrice.toNumber()}, adjustedPrice=${price.toNumber()}, adjustment=${priceAdjustmentMultiplier * 100}%`
30166
+ );
30090
30167
  const amount_in_token = (btcAmount * parseInt(leverage)).toFixed(
30091
30168
  this.config.extendedPrecision
30092
30169
  );
@@ -30097,17 +30174,57 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
30097
30174
  price.toFixed(0),
30098
30175
  side
30099
30176
  );
30100
- if (!result) {
30177
+ if (!result || !result.position_id) {
30178
+ logger.error("Failed to create order - no position_id returned");
30101
30179
  return null;
30102
30180
  }
30103
- await new Promise((resolve) => setTimeout(resolve, 5e3));
30104
- const openOrder = await this.getOrderStatus(
30105
- result.position_id,
30181
+ const positionId = result.position_id;
30182
+ logger.info(
30183
+ `Order created with position_id: ${positionId}. Waiting for API to update...`
30184
+ );
30185
+ let openOrder = await this.getOrderStatus(
30186
+ positionId,
30106
30187
  this.config.extendedMarketName
30107
30188
  );
30189
+ const maxStatusRetries = 3;
30190
+ const statusRetryDelay = 5e3;
30108
30191
  if (!openOrder) {
30192
+ logger.warn(
30193
+ `Order ${positionId} not found in API yet. Retrying status fetch (max ${maxStatusRetries} times)...`
30194
+ );
30195
+ for (let statusRetry = 1; statusRetry <= maxStatusRetries; statusRetry++) {
30196
+ await new Promise((resolve) => setTimeout(resolve, statusRetryDelay));
30197
+ openOrder = await this.getOrderStatus(
30198
+ positionId,
30199
+ this.config.extendedMarketName
30200
+ );
30201
+ if (openOrder) {
30202
+ logger.info(
30203
+ `Order ${positionId} found after ${statusRetry} status retry(ies)`
30204
+ );
30205
+ break;
30206
+ }
30207
+ logger.warn(
30208
+ `Order ${positionId} still not found after ${statusRetry}/${maxStatusRetries} status retries`
30209
+ );
30210
+ }
30211
+ }
30212
+ if (openOrder && openOrder.status === "FILLED" /* FILLED */) {
30213
+ logger.info(
30214
+ `Order ${positionId} successfully filled with quantity ${openOrder.qty}`
30215
+ );
30216
+ return {
30217
+ position_id: positionId,
30218
+ btc_exposure: openOrder.qty
30219
+ };
30220
+ } else if (openOrder && openOrder.status !== "FILLED" /* FILLED */) {
30221
+ logger.warn(
30222
+ `Order ${positionId} found but status is ${openOrder.status}, not FILLED. Retrying order creation...`
30223
+ );
30109
30224
  if (attempt >= maxAttempts) {
30110
- logger.error("Max retries reached \u2014 could not verify open position");
30225
+ logger.error(
30226
+ `Max retries reached \u2014 order ${positionId} status is ${openOrder.status}, not FILLED`
30227
+ );
30111
30228
  return null;
30112
30229
  } else {
30113
30230
  const backoff = 2e3 * attempt;
@@ -30121,9 +30238,12 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
30121
30238
  );
30122
30239
  }
30123
30240
  } else {
30241
+ logger.warn(
30242
+ `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.`
30243
+ );
30124
30244
  return {
30125
- position_id: result.position_id,
30126
- btc_exposure: openOrder.qty
30245
+ position_id: positionId,
30246
+ btc_exposure: amount_in_token
30127
30247
  };
30128
30248
  }
30129
30249
  } catch (err) {
@@ -34143,11 +34263,27 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34143
34263
  }
34144
34264
  async shouldInvest() {
34145
34265
  try {
34266
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest starting`);
34146
34267
  const vesuAdapter = await this.getVesuAdapter();
34147
34268
  const extendedAdapter = await this.getExtendedAdapter();
34148
- if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
34269
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest adapters fetched: vesuAdapter=${!!vesuAdapter}, extendedAdapter=${!!extendedAdapter}, extendedAdapter.client=${!!extendedAdapter?.client}`);
34270
+ if (!vesuAdapter) {
34149
34271
  logger.error(
34150
- `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
34272
+ `Vesu adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
34273
+ );
34274
+ return {
34275
+ shouldInvest: false,
34276
+ vesuAmount: new Web3Number(0, 0),
34277
+ extendedAmount: new Web3Number(0, 0),
34278
+ extendedLeverage: 0,
34279
+ collateralPrice: 0,
34280
+ debtPrice: 0,
34281
+ vesuLeverage: 0
34282
+ };
34283
+ }
34284
+ if (!extendedAdapter) {
34285
+ logger.error(
34286
+ `Extended adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
34151
34287
  );
34152
34288
  return {
34153
34289
  shouldInvest: false,
@@ -34159,10 +34295,72 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34159
34295
  vesuLeverage: 0
34160
34296
  };
34161
34297
  }
34298
+ if (!extendedAdapter.client) {
34299
+ logger.error(
34300
+ `Extended adapter client not initialized. This may be a temporary initialization failure - check network connectivity and API availability.`
34301
+ );
34302
+ return {
34303
+ shouldInvest: false,
34304
+ vesuAmount: new Web3Number(0, 0),
34305
+ extendedAmount: new Web3Number(0, 0),
34306
+ extendedLeverage: 0,
34307
+ collateralPrice: 0,
34308
+ debtPrice: 0,
34309
+ vesuLeverage: 0
34310
+ };
34311
+ }
34312
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest calling getUnusedBalance`);
34162
34313
  const balance = await this.getUnusedBalance();
34314
+ if (!Number.isFinite(balance.usdValue) || balance.usdValue < 0) {
34315
+ logger.error(
34316
+ `Invalid balance.usdValue: ${balance.usdValue}. Expected a finite, non-negative number.`
34317
+ );
34318
+ return {
34319
+ shouldInvest: false,
34320
+ vesuAmount: new Web3Number(0, 0),
34321
+ extendedAmount: new Web3Number(0, 0),
34322
+ extendedLeverage: 0,
34323
+ collateralPrice: 0,
34324
+ debtPrice: 0,
34325
+ vesuLeverage: 0
34326
+ };
34327
+ }
34328
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest balance: ${balance.usdValue}`);
34163
34329
  const usdcBalanceOnExtended = await extendedAdapter.getExtendedDepositAmount();
34330
+ if (usdcBalanceOnExtended) {
34331
+ const availableForWithdrawal = parseFloat(usdcBalanceOnExtended.availableForWithdrawal);
34332
+ if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
34333
+ logger.error(
34334
+ `Invalid usdcBalanceOnExtended.availableForWithdrawal: ${usdcBalanceOnExtended.availableForWithdrawal}. Expected a finite, non-negative number.`
34335
+ );
34336
+ return {
34337
+ shouldInvest: false,
34338
+ vesuAmount: new Web3Number(0, 0),
34339
+ extendedAmount: new Web3Number(0, 0),
34340
+ extendedLeverage: 0,
34341
+ collateralPrice: 0,
34342
+ debtPrice: 0,
34343
+ vesuLeverage: 0
34344
+ };
34345
+ }
34346
+ }
34164
34347
  const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).multipliedBy(1 - LIMIT_BALANCE);
34165
- logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvest.toNumber()}`);
34348
+ const amountToInvestNumber = amountToInvest.toNumber();
34349
+ if (!Number.isFinite(amountToInvestNumber)) {
34350
+ logger.error(
34351
+ `Invalid amountToInvest calculation result: ${amountToInvestNumber}. Calculation may have produced NaN or Infinity.`
34352
+ );
34353
+ return {
34354
+ shouldInvest: false,
34355
+ vesuAmount: new Web3Number(0, 0),
34356
+ extendedAmount: new Web3Number(0, 0),
34357
+ extendedLeverage: 0,
34358
+ collateralPrice: 0,
34359
+ debtPrice: 0,
34360
+ vesuLeverage: 0
34361
+ };
34362
+ }
34363
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvestNumber}`);
34166
34364
  if (amountToInvest.lessThan(0)) {
34167
34365
  return {
34168
34366
  shouldInvest: false,
@@ -34192,6 +34390,34 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34192
34390
  collateralPrice,
34193
34391
  debtPrice
34194
34392
  } = await this.getAssetPrices();
34393
+ if (!Number.isFinite(collateralPrice.price) || collateralPrice.price <= 0) {
34394
+ logger.error(
34395
+ `Invalid collateralPrice: ${collateralPrice.price}. Expected a finite, positive number.`
34396
+ );
34397
+ return {
34398
+ shouldInvest: false,
34399
+ vesuAmount: new Web3Number(0, 0),
34400
+ extendedAmount: new Web3Number(0, 0),
34401
+ extendedLeverage: 0,
34402
+ collateralPrice: 0,
34403
+ debtPrice: 0,
34404
+ vesuLeverage: 0
34405
+ };
34406
+ }
34407
+ if (!Number.isFinite(debtPrice.price) || debtPrice.price <= 0) {
34408
+ logger.error(
34409
+ `Invalid debtPrice: ${debtPrice.price}. Expected a finite, positive number.`
34410
+ );
34411
+ return {
34412
+ shouldInvest: false,
34413
+ vesuAmount: new Web3Number(0, 0),
34414
+ extendedAmount: new Web3Number(0, 0),
34415
+ extendedLeverage: 0,
34416
+ collateralPrice: 0,
34417
+ debtPrice: 0,
34418
+ vesuLeverage: 0
34419
+ };
34420
+ }
34195
34421
  const { vesu_amount, extended_amount, extended_leverage, vesu_leverage } = await calculateAmountDistribution(
34196
34422
  amountToInvest.toNumber(),
34197
34423
  extendedAdapter.client,
@@ -34242,13 +34468,45 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34242
34468
  try {
34243
34469
  const vesuAdapter = await this.getVesuAdapter();
34244
34470
  const extendedAdapter = await this.getExtendedAdapter();
34245
- let calls = [];
34246
34471
  if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
34247
34472
  logger.error(
34248
34473
  `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
34249
34474
  );
34250
- return calls;
34475
+ return [];
34476
+ }
34477
+ const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
34478
+ if (!extendedHoldings) {
34479
+ logger.error(`error getting extended holdings: ${extendedHoldings}`);
34480
+ return [];
34251
34481
  }
34482
+ const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
34483
+ const usdcAmountOnExtendedAvailableForWithdrawal = parseFloat(
34484
+ extendedHoldings.availableForWithdrawal
34485
+ );
34486
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculating movements - Extended current: ${usdcAmountOnExtendedAvailableForWithdrawal}, Wallet: ${usdcAmountInWallet.toNumber()}, Target Extended: ${extendedAmount.toNumber()}, Target Vesu: ${vesuAmount.toNumber()}`);
34487
+ let totalExtendedWithdrawal = new Web3Number(0, USDC_TOKEN_DECIMALS);
34488
+ let totalExtendedDeposit = new Web3Number(0, USDC_TOKEN_DECIMALS);
34489
+ if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
34490
+ totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmount.abs());
34491
+ }
34492
+ const extendedTargetAmount = extendedAmount.abs();
34493
+ let projectedExtendedBalance = usdcAmountOnExtendedAvailableForWithdrawal;
34494
+ if (extendedAmount.isNegative()) {
34495
+ projectedExtendedBalance = projectedExtendedBalance - extendedAmount.abs().toNumber();
34496
+ }
34497
+ const extendedAmountDifference = extendedTargetAmount.minus(projectedExtendedBalance);
34498
+ const extendedAmountDifferenceAbs = extendedAmountDifference.abs();
34499
+ if (extendedAmountDifference.lessThan(0)) {
34500
+ totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmountDifferenceAbs);
34501
+ } else if (extendedAmountDifference.greaterThan(0)) {
34502
+ totalExtendedDeposit = totalExtendedDeposit.plus(extendedAmountDifference);
34503
+ }
34504
+ const vesuTargetAmount = vesuAmount.abs();
34505
+ const projectedWalletBalance = usdcAmountInWallet.plus(totalExtendedWithdrawal).minus(totalExtendedDeposit);
34506
+ let vesuAmountDifference = vesuTargetAmount.minus(projectedWalletBalance);
34507
+ const vesuAmountDifferenceAbs = vesuAmountDifference.abs();
34508
+ 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()}`);
34509
+ let calls = [];
34252
34510
  if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
34253
34511
  try {
34254
34512
  const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
@@ -34269,7 +34527,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34269
34527
  logger.error(`Failed moving assets to vault: ${err}`);
34270
34528
  }
34271
34529
  }
34272
- if (vesuAmount.isNegative() && vesuAmount.lessThan(vesuAdapter.minimumVesuMovementAmount)) {
34530
+ if (vesuAmount.isNegative() && vesuAmount.abs().greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
34273
34531
  try {
34274
34532
  const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
34275
34533
  {
@@ -34288,48 +34546,76 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34288
34546
  logger.error(`Failed moving assets to vault: ${err}`);
34289
34547
  }
34290
34548
  }
34291
- const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
34292
- if (!extendedHoldings) {
34293
- logger.error(`error getting extended holdings: ${extendedHoldings}`);
34294
- return calls;
34295
- }
34296
- const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
34297
- const usdcAmountOnExtended = parseFloat(
34298
- extendedHoldings.availableForWithdrawal
34299
- );
34300
- if (extendedAmount.minus(usdcAmountOnExtended).greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
34301
- try {
34302
- const { calls: extendedCalls } = await this.moveAssets(
34303
- {
34304
- to: Protocols.EXTENDED.name,
34305
- from: Protocols.VAULT.name,
34306
- amount: extendedAmount.minus(usdcAmountOnExtended)
34307
- },
34308
- extendedAdapter,
34309
- vesuAdapter
34310
- );
34311
- calls.push(...extendedCalls);
34312
- } catch (err) {
34313
- logger.error(`Failed moving assets to extended: ${err}`);
34549
+ if (extendedAmountDifferenceAbs.greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
34550
+ if (extendedAmountDifference.greaterThan(0)) {
34551
+ try {
34552
+ const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
34553
+ {
34554
+ to: Protocols.EXTENDED.name,
34555
+ from: Protocols.VAULT.name,
34556
+ amount: extendedAmountDifference
34557
+ },
34558
+ extendedAdapter,
34559
+ vesuAdapter
34560
+ );
34561
+ if (extendedStatus) {
34562
+ calls.push(...extendedCalls);
34563
+ } else {
34564
+ logger.error(`Failed to move assets to extended - operation returned false status`);
34565
+ return [];
34566
+ }
34567
+ } catch (err) {
34568
+ logger.error(`Failed moving assets to extended: ${err}`);
34569
+ return [];
34570
+ }
34571
+ } else if (extendedAmountDifference.lessThan(0)) {
34572
+ try {
34573
+ const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
34574
+ {
34575
+ to: Protocols.VAULT.name,
34576
+ from: Protocols.EXTENDED.name,
34577
+ amount: extendedAmountDifferenceAbs
34578
+ },
34579
+ extendedAdapter,
34580
+ vesuAdapter
34581
+ );
34582
+ if (extendedStatus) {
34583
+ calls.push(...extendedCalls);
34584
+ } else {
34585
+ logger.error(`Failed to withdraw from extended - operation returned false status`);
34586
+ return [];
34587
+ }
34588
+ } catch (err) {
34589
+ logger.error(`Failed moving assets from extended to vault: ${err}`);
34590
+ return [];
34591
+ }
34314
34592
  }
34315
34593
  }
34316
- if (vesuAmount.minus(usdcAmountInWallet).greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
34317
- try {
34318
- const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
34319
- {
34320
- to: Protocols.VAULT.name,
34321
- from: Protocols.EXTENDED.name,
34322
- amount: vesuAmount.minus(usdcAmountInWallet)
34323
- },
34324
- extendedAdapter,
34325
- vesuAdapter
34594
+ if (vesuAmountDifferenceAbs.greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
34595
+ if (vesuAmountDifference.lessThanOrEqualTo(0)) {
34596
+ logger.warn(
34597
+ `Vesu amount difference is negative or zero: ${vesuAmountDifference.toNumber()}. Skipping operation.`
34326
34598
  );
34327
- if (!vesuStatus) {
34599
+ } else {
34600
+ try {
34601
+ const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
34602
+ {
34603
+ to: Protocols.VAULT.name,
34604
+ from: Protocols.EXTENDED.name,
34605
+ amount: vesuAmountDifference
34606
+ },
34607
+ extendedAdapter,
34608
+ vesuAdapter
34609
+ );
34610
+ if (!vesuStatus) {
34611
+ logger.error(`Failed to move assets to vesu - operation returned false status`);
34612
+ return [];
34613
+ }
34614
+ calls.push(...vesuCalls);
34615
+ } catch (err) {
34616
+ logger.error(`Failed moving assets to vault: ${err}`);
34328
34617
  return [];
34329
34618
  }
34330
- calls.push(...vesuCalls);
34331
- } catch (err) {
34332
- logger.error(`Failed moving assets to vault: ${err}`);
34333
34619
  }
34334
34620
  }
34335
34621
  return calls;
@@ -34340,6 +34626,38 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34340
34626
  }
34341
34627
  async moveAssets(params, extendedAdapter, vesuAdapter) {
34342
34628
  try {
34629
+ if (params.amount.lessThanOrEqualTo(0)) {
34630
+ logger.error(
34631
+ `Invalid amount for moveAssets: ${params.amount.toNumber()}. Amount must be positive.`
34632
+ );
34633
+ return {
34634
+ calls: [],
34635
+ status: false
34636
+ };
34637
+ }
34638
+ const amountAbs = params.amount.abs();
34639
+ if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
34640
+ if (amountAbs.lessThanOrEqualTo(extendedAdapter.minimumExtendedMovementAmount)) {
34641
+ logger.warn(
34642
+ `Amount ${amountAbs.toNumber()} is below minimum Extended movement amount ${extendedAdapter.minimumExtendedMovementAmount}. Skipping operation.`
34643
+ );
34644
+ return {
34645
+ calls: [],
34646
+ status: false
34647
+ };
34648
+ }
34649
+ }
34650
+ if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
34651
+ if (amountAbs.lessThanOrEqualTo(vesuAdapter.minimumVesuMovementAmount)) {
34652
+ logger.warn(
34653
+ `Amount ${amountAbs.toNumber()} is below minimum Vesu movement amount ${vesuAdapter.minimumVesuMovementAmount}. Skipping operation.`
34654
+ );
34655
+ return {
34656
+ calls: [],
34657
+ status: false
34658
+ };
34659
+ }
34660
+ }
34343
34661
  const avnuAdapter = await this.getAvnuAdapter();
34344
34662
  if (!avnuAdapter) {
34345
34663
  logger.error(`avnu adapter not found: ${avnuAdapter}`);
@@ -34400,12 +34718,13 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34400
34718
  );
34401
34719
  if (!openLongPosition) {
34402
34720
  logger.error(`error opening long position: ${openLongPosition}`);
34403
- return {
34404
- calls: [],
34405
- status: false
34406
- };
34407
34721
  }
34408
34722
  await new Promise((resolve) => setTimeout(resolve, 5e3));
34723
+ const updatedHoldings = await extendedAdapter.getExtendedDepositAmount();
34724
+ if (!updatedHoldings || new Web3Number(updatedHoldings.availableForWithdrawal, USDC_TOKEN_DECIMALS).lessThan(params.amount.abs())) {
34725
+ logger.error(`Insufficient balance after opening position. Available: ${updatedHoldings?.availableForWithdrawal}, Needed: ${params.amount.abs()}`);
34726
+ return { calls: [], status: false };
34727
+ }
34409
34728
  }
34410
34729
  const withdrawalFromExtended = await extendedAdapter.withdrawFromExtended(params.amount);
34411
34730
  if (withdrawalFromExtended) {