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

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.
@@ -93946,8 +93946,47 @@ spurious results.`);
93946
93946
  async withdrawFromExtended(amount) {
93947
93947
  try {
93948
93948
  if (!this.client) {
93949
- throw new Error("Client not initialized");
93949
+ logger2.error("Client not initialized");
93950
+ return false;
93951
+ }
93952
+ if (amount.lessThanOrEqualTo(0)) {
93953
+ logger2.error(
93954
+ `Invalid withdrawal amount: ${amount.toNumber()}. Amount must be positive.`
93955
+ );
93956
+ return false;
93950
93957
  }
93958
+ if (amount.lessThanOrEqualTo(this.minimumExtendedMovementAmount)) {
93959
+ logger2.warn(
93960
+ `Withdrawal amount ${amount.toNumber()} is below minimum Extended movement amount ${this.minimumExtendedMovementAmount}. Skipping withdrawal.`
93961
+ );
93962
+ return false;
93963
+ }
93964
+ const holdings = await this.getExtendedDepositAmount();
93965
+ if (!holdings) {
93966
+ logger2.error(
93967
+ "Cannot get holdings - unable to validate withdrawal amount"
93968
+ );
93969
+ return false;
93970
+ }
93971
+ const availableForWithdrawal = parseFloat(
93972
+ holdings.availableForWithdrawal
93973
+ );
93974
+ if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
93975
+ logger2.error(
93976
+ `Invalid availableForWithdrawal: ${holdings.availableForWithdrawal}. Expected a finite, non-negative number.`
93977
+ );
93978
+ return false;
93979
+ }
93980
+ const withdrawalAmount = amount.toNumber();
93981
+ if (withdrawalAmount > availableForWithdrawal) {
93982
+ logger2.error(
93983
+ `Withdrawal amount ${withdrawalAmount} exceeds available balance ${availableForWithdrawal}`
93984
+ );
93985
+ return false;
93986
+ }
93987
+ logger2.info(
93988
+ `Withdrawing ${withdrawalAmount} from Extended. Available balance: ${availableForWithdrawal}`
93989
+ );
93951
93990
  const withdrawalRequest = await this.client.withdrawUSDC(
93952
93991
  amount.toFixed(2)
93953
93992
  );
@@ -93958,6 +93997,9 @@ spurious results.`);
93958
93997
  );
93959
93998
  return withdrawalStatus;
93960
93999
  }
94000
+ logger2.error(
94001
+ `Withdrawal request failed with status: ${withdrawalRequest.status}`
94002
+ );
93961
94003
  return false;
93962
94004
  } catch (error2) {
93963
94005
  logger2.error(`Error creating Withdraw Call: ${error2}`);
@@ -93968,21 +94010,44 @@ spurious results.`);
93968
94010
  return Promise.resolve(1);
93969
94011
  }
93970
94012
  async getExtendedDepositAmount() {
93971
- if (this.client === null) {
93972
- logger2.error("error initializing client");
93973
- return void 0;
93974
- }
93975
- const result2 = await this.client.getHoldings();
93976
- if (!result2) {
93977
- logger2.error(`error getting holdings: ${result2}`);
93978
- return void 0;
93979
- }
93980
- const holdings = result2.data;
93981
- if (!holdings) {
93982
- logger2.error(`error getting holdings: ${holdings}`);
94013
+ try {
94014
+ if (this.client === null) {
94015
+ logger2.error("error initializing client - client is null");
94016
+ return void 0;
94017
+ }
94018
+ const result2 = await this.client.getHoldings();
94019
+ if (!result2) {
94020
+ logger2.error("error getting holdings - API returned null/undefined");
94021
+ return void 0;
94022
+ }
94023
+ if (result2.status && result2.status !== "OK") {
94024
+ logger2.error(
94025
+ `error getting holdings - API returned status: ${result2.status}`
94026
+ );
94027
+ return void 0;
94028
+ }
94029
+ const holdings = result2.data;
94030
+ if (!holdings) {
94031
+ logger2.warn(
94032
+ "holdings data is null/undefined - treating as zero balance"
94033
+ );
94034
+ return {
94035
+ collateral_name: "",
94036
+ balance: "0",
94037
+ equity: "0",
94038
+ availableForTrade: "0",
94039
+ availableForWithdrawal: "0",
94040
+ unrealisedPnl: "0",
94041
+ initialMargin: "0",
94042
+ marginRatio: "0",
94043
+ updatedTime: Date.now()
94044
+ };
94045
+ }
94046
+ return holdings;
94047
+ } catch (error2) {
94048
+ logger2.error(`error getting holdings - exception: ${error2}`);
93983
94049
  return void 0;
93984
94050
  }
93985
- return holdings;
93986
94051
  }
93987
94052
  async setLeverage(leverage, marketName) {
93988
94053
  if (this.client === null) {
@@ -94024,38 +94089,24 @@ spurious results.`);
94024
94089
  return result2.data;
94025
94090
  }
94026
94091
  async getOrderStatus(orderId, marketName) {
94027
- if (this.client === null) {
94028
- logger2.error("error initializing client");
94029
- return null;
94030
- }
94031
- let orderhistory = await this.getOrderHistory(marketName);
94032
- if (!orderhistory || orderhistory.length === 0) {
94033
- logger2.error(`error getting order history: ${orderId}`);
94034
- } else {
94035
- const order = orderhistory.slice(0, 10).find((order2) => order2.id.toString() === orderId);
94036
- if (order) {
94037
- return order;
94092
+ try {
94093
+ if (this.client === null) {
94094
+ logger2.error("error initializing client");
94095
+ return null;
94038
94096
  }
94039
- }
94040
- for (let attempt = 1; attempt <= 5; attempt++) {
94041
- await new Promise((resolve) => setTimeout(resolve, this.retryDelayForOrderStatus));
94042
- orderhistory = await this.getOrderHistory(marketName);
94097
+ const orderhistory = await this.getOrderHistory(marketName);
94043
94098
  if (!orderhistory || orderhistory.length === 0) {
94044
- logger2.error(
94045
- `error getting order history on retry ${attempt}: ${orderId}`
94046
- );
94047
- continue;
94099
+ return null;
94048
94100
  }
94049
- const order = orderhistory.slice(0, 5).find((order2) => order2.id.toString() === orderId);
94050
- if (order && order.status === "FILLED" /* FILLED */) {
94101
+ const order = orderhistory.slice(0, 20).find((order2) => order2.id.toString() === orderId);
94102
+ if (order) {
94051
94103
  return order;
94052
94104
  }
94053
- logger2.error(
94054
- `order not found in top 15 entries on retry ${attempt}: ${orderId}`
94055
- );
94105
+ return null;
94106
+ } catch (error2) {
94107
+ logger2.error(`error getting order status: ${error2}`);
94108
+ return null;
94056
94109
  }
94057
- logger2.error(`error getting order after all retries: ${orderId}`);
94058
- return null;
94059
94110
  }
94060
94111
  async fetchOrderBookBTCUSDC() {
94061
94112
  try {
@@ -94106,14 +94157,40 @@ spurious results.`);
94106
94157
  logger2.error("error depositing or setting leverage");
94107
94158
  return null;
94108
94159
  }
94109
- const positions = await this.getAllOpenPositions();
94110
- if (positions === null) {
94160
+ const { ask, bid } = await this.fetchOrderBookBTCUSDC();
94161
+ if (!ask || !bid || ask.lessThanOrEqualTo(0) || bid.lessThanOrEqualTo(0)) {
94162
+ logger2.error(
94163
+ `Invalid orderbook prices: ask=${ask?.toNumber()}, bid=${bid?.toNumber()}`
94164
+ );
94111
94165
  return null;
94112
94166
  }
94113
- const { ask, bid } = await this.fetchOrderBookBTCUSDC();
94114
94167
  const spread3 = ask.minus(bid);
94115
- let price = ask.plus(bid).div(2);
94116
- side === "SELL" /* SELL */ ? price = price.minus(spread3.times(0.2 * attempt)) : price = price.plus(spread3.times(0.2 * attempt));
94168
+ const midPrice = ask.plus(bid).div(2);
94169
+ const MAX_PRICE_DEVIATION_MULTIPLIER = 0.5;
94170
+ const priceAdjustmentMultiplier = Math.min(
94171
+ 0.2 * attempt,
94172
+ MAX_PRICE_DEVIATION_MULTIPLIER
94173
+ );
94174
+ const priceAdjustment = spread3.times(priceAdjustmentMultiplier);
94175
+ let price = midPrice;
94176
+ if (side === "SELL" /* SELL */) {
94177
+ price = midPrice.minus(priceAdjustment);
94178
+ } else {
94179
+ price = midPrice.plus(priceAdjustment);
94180
+ }
94181
+ const maxDeviation = midPrice.times(0.5);
94182
+ if (price.minus(midPrice).abs().greaterThan(maxDeviation)) {
94183
+ logger2.error(
94184
+ `Price deviation too large on attempt ${attempt}: price=${price.toNumber()}, midPrice=${midPrice.toNumber()}, deviation=${price.minus(midPrice).abs().toNumber()}`
94185
+ );
94186
+ if (attempt >= maxAttempts) {
94187
+ return null;
94188
+ }
94189
+ price = side === "SELL" /* SELL */ ? midPrice.minus(maxDeviation) : midPrice.plus(maxDeviation);
94190
+ }
94191
+ logger2.info(
94192
+ `createOrder attempt ${attempt}/${maxAttempts}: side=${side}, midPrice=${midPrice.toNumber()}, adjustedPrice=${price.toNumber()}, adjustment=${priceAdjustmentMultiplier * 100}%`
94193
+ );
94117
94194
  const amount_in_token = (btcAmount * parseInt(leverage)).toFixed(
94118
94195
  this.config.extendedPrecision
94119
94196
  );
@@ -94124,17 +94201,57 @@ spurious results.`);
94124
94201
  price.toFixed(0),
94125
94202
  side
94126
94203
  );
94127
- if (!result2) {
94204
+ if (!result2 || !result2.position_id) {
94205
+ logger2.error("Failed to create order - no position_id returned");
94128
94206
  return null;
94129
94207
  }
94130
- await new Promise((resolve) => setTimeout(resolve, 5e3));
94131
- const openOrder = await this.getOrderStatus(
94132
- result2.position_id,
94208
+ const positionId = result2.position_id;
94209
+ logger2.info(
94210
+ `Order created with position_id: ${positionId}. Waiting for API to update...`
94211
+ );
94212
+ let openOrder = await this.getOrderStatus(
94213
+ positionId,
94133
94214
  this.config.extendedMarketName
94134
94215
  );
94216
+ const maxStatusRetries = 3;
94217
+ const statusRetryDelay = 5e3;
94135
94218
  if (!openOrder) {
94219
+ logger2.warn(
94220
+ `Order ${positionId} not found in API yet. Retrying status fetch (max ${maxStatusRetries} times)...`
94221
+ );
94222
+ for (let statusRetry = 1; statusRetry <= maxStatusRetries; statusRetry++) {
94223
+ await new Promise((resolve) => setTimeout(resolve, statusRetryDelay));
94224
+ openOrder = await this.getOrderStatus(
94225
+ positionId,
94226
+ this.config.extendedMarketName
94227
+ );
94228
+ if (openOrder) {
94229
+ logger2.info(
94230
+ `Order ${positionId} found after ${statusRetry} status retry(ies)`
94231
+ );
94232
+ break;
94233
+ }
94234
+ logger2.warn(
94235
+ `Order ${positionId} still not found after ${statusRetry}/${maxStatusRetries} status retries`
94236
+ );
94237
+ }
94238
+ }
94239
+ if (openOrder && openOrder.status === "FILLED" /* FILLED */) {
94240
+ logger2.info(
94241
+ `Order ${positionId} successfully filled with quantity ${openOrder.qty}`
94242
+ );
94243
+ return {
94244
+ position_id: positionId,
94245
+ btc_exposure: openOrder.qty
94246
+ };
94247
+ } else if (openOrder && openOrder.status !== "FILLED" /* FILLED */) {
94248
+ logger2.warn(
94249
+ `Order ${positionId} found but status is ${openOrder.status}, not FILLED. Retrying order creation...`
94250
+ );
94136
94251
  if (attempt >= maxAttempts) {
94137
- logger2.error("Max retries reached \u2014 could not verify open position");
94252
+ logger2.error(
94253
+ `Max retries reached \u2014 order ${positionId} status is ${openOrder.status}, not FILLED`
94254
+ );
94138
94255
  return null;
94139
94256
  } else {
94140
94257
  const backoff = 2e3 * attempt;
@@ -94148,9 +94265,12 @@ spurious results.`);
94148
94265
  );
94149
94266
  }
94150
94267
  } else {
94268
+ logger2.warn(
94269
+ `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.`
94270
+ );
94151
94271
  return {
94152
- position_id: result2.position_id,
94153
- btc_exposure: openOrder.qty
94272
+ position_id: positionId,
94273
+ btc_exposure: amount_in_token
94154
94274
  };
94155
94275
  }
94156
94276
  } catch (err2) {
@@ -94195,32 +94315,101 @@ spurious results.`);
94195
94315
  }
94196
94316
  }
94197
94317
  async getDepositOrWithdrawalStatus(orderId, operationsType) {
94198
- try {
94199
- let transferHistory = await this.client.getAssetOperations({
94200
- operationsType: [operationsType],
94201
- operationsStatus: ["COMPLETED" /* COMPLETED */]
94202
- });
94203
- if (operationsType === "DEPOSIT" /* DEPOSIT */) {
94204
- const myTransferStatus = transferHistory.data.find(
94205
- (operation) => operation.transactionHash === orderId
94206
- );
94207
- if (!myTransferStatus) {
94208
- return true;
94318
+ const maxAttempts = 5;
94319
+ const retryDelayMs = 3e4;
94320
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
94321
+ try {
94322
+ let transferHistory = await this.client.getAssetOperations({
94323
+ operationsType: [operationsType],
94324
+ operationsStatus: ["COMPLETED" /* COMPLETED */]
94325
+ });
94326
+ if (operationsType === "DEPOSIT" /* DEPOSIT */) {
94327
+ const myTransferStatus = transferHistory.data.find(
94328
+ (operation) => operation.transactionHash === orderId
94329
+ );
94330
+ if (!myTransferStatus) {
94331
+ if (attempt < maxAttempts) {
94332
+ logger2.info(
94333
+ `Deposit operation not found for transactionHash ${orderId}, retrying (attempt ${attempt}/${maxAttempts})...`
94334
+ );
94335
+ await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
94336
+ continue;
94337
+ }
94338
+ logger2.warn(
94339
+ `Deposit operation not found for transactionHash ${orderId} after ${maxAttempts} attempts`
94340
+ );
94341
+ return false;
94342
+ }
94343
+ if (myTransferStatus.status === "COMPLETED" /* COMPLETED */) {
94344
+ logger2.info(
94345
+ `Deposit operation ${orderId} completed successfully`
94346
+ );
94347
+ return true;
94348
+ } else {
94349
+ if (attempt < maxAttempts) {
94350
+ logger2.info(
94351
+ `Deposit operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`
94352
+ );
94353
+ await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
94354
+ continue;
94355
+ }
94356
+ logger2.warn(
94357
+ `Deposit operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`
94358
+ );
94359
+ return false;
94360
+ }
94361
+ } else {
94362
+ const myTransferStatus = transferHistory.data.find(
94363
+ (operation) => operation.id.toString() === orderId.toString()
94364
+ );
94365
+ if (!myTransferStatus) {
94366
+ if (attempt < maxAttempts) {
94367
+ logger2.info(
94368
+ `Withdrawal status not found for orderId ${orderId} in completed operations, retrying (attempt ${attempt}/${maxAttempts})...`
94369
+ );
94370
+ await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
94371
+ continue;
94372
+ }
94373
+ logger2.warn(
94374
+ `Withdrawal operation not found for orderId ${orderId} after ${maxAttempts} attempts`
94375
+ );
94376
+ return false;
94377
+ }
94378
+ if (myTransferStatus.status === "COMPLETED" /* COMPLETED */) {
94379
+ logger2.info(
94380
+ `Withdrawal operation ${orderId} completed successfully`
94381
+ );
94382
+ return true;
94383
+ } else {
94384
+ if (attempt < maxAttempts) {
94385
+ logger2.info(
94386
+ `Withdrawal operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`
94387
+ );
94388
+ await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
94389
+ continue;
94390
+ }
94391
+ logger2.warn(
94392
+ `Withdrawal operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`
94393
+ );
94394
+ return false;
94395
+ }
94209
94396
  }
94210
- return true;
94211
- } else {
94212
- const myTransferStatus = transferHistory.data.find(
94213
- (operation) => operation.id.toString() === orderId.toString()
94397
+ } catch (err2) {
94398
+ logger2.error(
94399
+ `error getting deposit or withdrawal status (attempt ${attempt}/${maxAttempts}): ${err2}`
94214
94400
  );
94215
- if (!myTransferStatus) {
94216
- return true;
94401
+ if (attempt < maxAttempts) {
94402
+ logger2.info(`Retrying after ${retryDelayMs}ms...`);
94403
+ await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
94404
+ continue;
94217
94405
  }
94218
- return true;
94406
+ logger2.error(
94407
+ `Max retry attempts reached for getDepositOrWithdrawalStatus`
94408
+ );
94409
+ return false;
94219
94410
  }
94220
- } catch (err2) {
94221
- logger2.error(`error getting deposit or withdrawal status: ${err2}`);
94222
- return false;
94223
94411
  }
94412
+ return false;
94224
94413
  }
94225
94414
  };
94226
94415
 
@@ -98165,11 +98354,27 @@ spurious results.`);
98165
98354
  }
98166
98355
  async shouldInvest() {
98167
98356
  try {
98357
+ logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest starting`);
98168
98358
  const vesuAdapter = await this.getVesuAdapter();
98169
98359
  const extendedAdapter = await this.getExtendedAdapter();
98170
- if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
98360
+ logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest adapters fetched: vesuAdapter=${!!vesuAdapter}, extendedAdapter=${!!extendedAdapter}, extendedAdapter.client=${!!extendedAdapter?.client}`);
98361
+ if (!vesuAdapter) {
98171
98362
  logger2.error(
98172
- `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
98363
+ `Vesu adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
98364
+ );
98365
+ return {
98366
+ shouldInvest: false,
98367
+ vesuAmount: new Web3Number(0, 0),
98368
+ extendedAmount: new Web3Number(0, 0),
98369
+ extendedLeverage: 0,
98370
+ collateralPrice: 0,
98371
+ debtPrice: 0,
98372
+ vesuLeverage: 0
98373
+ };
98374
+ }
98375
+ if (!extendedAdapter) {
98376
+ logger2.error(
98377
+ `Extended adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
98173
98378
  );
98174
98379
  return {
98175
98380
  shouldInvest: false,
@@ -98181,10 +98386,72 @@ spurious results.`);
98181
98386
  vesuLeverage: 0
98182
98387
  };
98183
98388
  }
98389
+ if (!extendedAdapter.client) {
98390
+ logger2.error(
98391
+ `Extended adapter client not initialized. This may be a temporary initialization failure - check network connectivity and API availability.`
98392
+ );
98393
+ return {
98394
+ shouldInvest: false,
98395
+ vesuAmount: new Web3Number(0, 0),
98396
+ extendedAmount: new Web3Number(0, 0),
98397
+ extendedLeverage: 0,
98398
+ collateralPrice: 0,
98399
+ debtPrice: 0,
98400
+ vesuLeverage: 0
98401
+ };
98402
+ }
98403
+ logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest calling getUnusedBalance`);
98184
98404
  const balance = await this.getUnusedBalance();
98405
+ if (!Number.isFinite(balance.usdValue) || balance.usdValue < 0) {
98406
+ logger2.error(
98407
+ `Invalid balance.usdValue: ${balance.usdValue}. Expected a finite, non-negative number.`
98408
+ );
98409
+ return {
98410
+ shouldInvest: false,
98411
+ vesuAmount: new Web3Number(0, 0),
98412
+ extendedAmount: new Web3Number(0, 0),
98413
+ extendedLeverage: 0,
98414
+ collateralPrice: 0,
98415
+ debtPrice: 0,
98416
+ vesuLeverage: 0
98417
+ };
98418
+ }
98419
+ logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest balance: ${balance.usdValue}`);
98185
98420
  const usdcBalanceOnExtended = await extendedAdapter.getExtendedDepositAmount();
98421
+ if (usdcBalanceOnExtended) {
98422
+ const availableForWithdrawal = parseFloat(usdcBalanceOnExtended.availableForWithdrawal);
98423
+ if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
98424
+ logger2.error(
98425
+ `Invalid usdcBalanceOnExtended.availableForWithdrawal: ${usdcBalanceOnExtended.availableForWithdrawal}. Expected a finite, non-negative number.`
98426
+ );
98427
+ return {
98428
+ shouldInvest: false,
98429
+ vesuAmount: new Web3Number(0, 0),
98430
+ extendedAmount: new Web3Number(0, 0),
98431
+ extendedLeverage: 0,
98432
+ collateralPrice: 0,
98433
+ debtPrice: 0,
98434
+ vesuLeverage: 0
98435
+ };
98436
+ }
98437
+ }
98186
98438
  const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).multipliedBy(1 - LIMIT_BALANCE);
98187
- logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvest.toNumber()}`);
98439
+ const amountToInvestNumber = amountToInvest.toNumber();
98440
+ if (!Number.isFinite(amountToInvestNumber)) {
98441
+ logger2.error(
98442
+ `Invalid amountToInvest calculation result: ${amountToInvestNumber}. Calculation may have produced NaN or Infinity.`
98443
+ );
98444
+ return {
98445
+ shouldInvest: false,
98446
+ vesuAmount: new Web3Number(0, 0),
98447
+ extendedAmount: new Web3Number(0, 0),
98448
+ extendedLeverage: 0,
98449
+ collateralPrice: 0,
98450
+ debtPrice: 0,
98451
+ vesuLeverage: 0
98452
+ };
98453
+ }
98454
+ logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvestNumber}`);
98188
98455
  if (amountToInvest.lessThan(0)) {
98189
98456
  return {
98190
98457
  shouldInvest: false,
@@ -98214,6 +98481,34 @@ spurious results.`);
98214
98481
  collateralPrice,
98215
98482
  debtPrice
98216
98483
  } = await this.getAssetPrices();
98484
+ if (!Number.isFinite(collateralPrice.price) || collateralPrice.price <= 0) {
98485
+ logger2.error(
98486
+ `Invalid collateralPrice: ${collateralPrice.price}. Expected a finite, positive number.`
98487
+ );
98488
+ return {
98489
+ shouldInvest: false,
98490
+ vesuAmount: new Web3Number(0, 0),
98491
+ extendedAmount: new Web3Number(0, 0),
98492
+ extendedLeverage: 0,
98493
+ collateralPrice: 0,
98494
+ debtPrice: 0,
98495
+ vesuLeverage: 0
98496
+ };
98497
+ }
98498
+ if (!Number.isFinite(debtPrice.price) || debtPrice.price <= 0) {
98499
+ logger2.error(
98500
+ `Invalid debtPrice: ${debtPrice.price}. Expected a finite, positive number.`
98501
+ );
98502
+ return {
98503
+ shouldInvest: false,
98504
+ vesuAmount: new Web3Number(0, 0),
98505
+ extendedAmount: new Web3Number(0, 0),
98506
+ extendedLeverage: 0,
98507
+ collateralPrice: 0,
98508
+ debtPrice: 0,
98509
+ vesuLeverage: 0
98510
+ };
98511
+ }
98217
98512
  const { vesu_amount, extended_amount, extended_leverage, vesu_leverage } = await calculateAmountDistribution(
98218
98513
  amountToInvest.toNumber(),
98219
98514
  extendedAdapter.client,
@@ -98264,13 +98559,45 @@ spurious results.`);
98264
98559
  try {
98265
98560
  const vesuAdapter = await this.getVesuAdapter();
98266
98561
  const extendedAdapter = await this.getExtendedAdapter();
98267
- let calls = [];
98268
98562
  if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
98269
98563
  logger2.error(
98270
98564
  `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
98271
98565
  );
98272
- return calls;
98566
+ return [];
98567
+ }
98568
+ const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
98569
+ if (!extendedHoldings) {
98570
+ logger2.error(`error getting extended holdings: ${extendedHoldings}`);
98571
+ return [];
98273
98572
  }
98573
+ const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
98574
+ const usdcAmountOnExtendedAvailableForWithdrawal = parseFloat(
98575
+ extendedHoldings.availableForWithdrawal
98576
+ );
98577
+ logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculating movements - Extended current: ${usdcAmountOnExtendedAvailableForWithdrawal}, Wallet: ${usdcAmountInWallet.toNumber()}, Target Extended: ${extendedAmount.toNumber()}, Target Vesu: ${vesuAmount.toNumber()}`);
98578
+ let totalExtendedWithdrawal = new Web3Number(0, USDC_TOKEN_DECIMALS);
98579
+ let totalExtendedDeposit = new Web3Number(0, USDC_TOKEN_DECIMALS);
98580
+ if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
98581
+ totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmount.abs());
98582
+ }
98583
+ const extendedTargetAmount = extendedAmount.abs();
98584
+ let projectedExtendedBalance = usdcAmountOnExtendedAvailableForWithdrawal;
98585
+ if (extendedAmount.isNegative()) {
98586
+ projectedExtendedBalance = projectedExtendedBalance - extendedAmount.abs().toNumber();
98587
+ }
98588
+ const extendedAmountDifference = extendedTargetAmount.minus(projectedExtendedBalance);
98589
+ const extendedAmountDifferenceAbs = extendedAmountDifference.abs();
98590
+ if (extendedAmountDifference.lessThan(0)) {
98591
+ totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmountDifferenceAbs);
98592
+ } else if (extendedAmountDifference.greaterThan(0)) {
98593
+ totalExtendedDeposit = totalExtendedDeposit.plus(extendedAmountDifference);
98594
+ }
98595
+ const vesuTargetAmount = vesuAmount.abs();
98596
+ const projectedWalletBalance = usdcAmountInWallet.plus(totalExtendedWithdrawal).minus(totalExtendedDeposit);
98597
+ let vesuAmountDifference = vesuTargetAmount.minus(projectedWalletBalance);
98598
+ const vesuAmountDifferenceAbs = vesuAmountDifference.abs();
98599
+ logger2.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()}`);
98600
+ let calls = [];
98274
98601
  if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
98275
98602
  try {
98276
98603
  const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
@@ -98291,7 +98618,7 @@ spurious results.`);
98291
98618
  logger2.error(`Failed moving assets to vault: ${err2}`);
98292
98619
  }
98293
98620
  }
98294
- if (vesuAmount.isNegative() && vesuAmount.lessThan(vesuAdapter.minimumVesuMovementAmount)) {
98621
+ if (vesuAmount.isNegative() && vesuAmount.abs().greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
98295
98622
  try {
98296
98623
  const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
98297
98624
  {
@@ -98310,48 +98637,76 @@ spurious results.`);
98310
98637
  logger2.error(`Failed moving assets to vault: ${err2}`);
98311
98638
  }
98312
98639
  }
98313
- const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
98314
- if (!extendedHoldings) {
98315
- logger2.error(`error getting extended holdings: ${extendedHoldings}`);
98316
- return calls;
98317
- }
98318
- const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
98319
- const usdcAmountOnExtended = parseFloat(
98320
- extendedHoldings.availableForWithdrawal
98321
- );
98322
- if (extendedAmount.minus(usdcAmountOnExtended).greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
98323
- try {
98324
- const { calls: extendedCalls } = await this.moveAssets(
98325
- {
98326
- to: Protocols.EXTENDED.name,
98327
- from: Protocols.VAULT.name,
98328
- amount: extendedAmount.minus(usdcAmountOnExtended)
98329
- },
98330
- extendedAdapter,
98331
- vesuAdapter
98332
- );
98333
- calls.push(...extendedCalls);
98334
- } catch (err2) {
98335
- logger2.error(`Failed moving assets to extended: ${err2}`);
98640
+ if (extendedAmountDifferenceAbs.greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
98641
+ if (extendedAmountDifference.greaterThan(0)) {
98642
+ try {
98643
+ const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
98644
+ {
98645
+ to: Protocols.EXTENDED.name,
98646
+ from: Protocols.VAULT.name,
98647
+ amount: extendedAmountDifference
98648
+ },
98649
+ extendedAdapter,
98650
+ vesuAdapter
98651
+ );
98652
+ if (extendedStatus) {
98653
+ calls.push(...extendedCalls);
98654
+ } else {
98655
+ logger2.error(`Failed to move assets to extended - operation returned false status`);
98656
+ return [];
98657
+ }
98658
+ } catch (err2) {
98659
+ logger2.error(`Failed moving assets to extended: ${err2}`);
98660
+ return [];
98661
+ }
98662
+ } else if (extendedAmountDifference.lessThan(0)) {
98663
+ try {
98664
+ const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
98665
+ {
98666
+ to: Protocols.VAULT.name,
98667
+ from: Protocols.EXTENDED.name,
98668
+ amount: extendedAmountDifferenceAbs
98669
+ },
98670
+ extendedAdapter,
98671
+ vesuAdapter
98672
+ );
98673
+ if (extendedStatus) {
98674
+ calls.push(...extendedCalls);
98675
+ } else {
98676
+ logger2.error(`Failed to withdraw from extended - operation returned false status`);
98677
+ return [];
98678
+ }
98679
+ } catch (err2) {
98680
+ logger2.error(`Failed moving assets from extended to vault: ${err2}`);
98681
+ return [];
98682
+ }
98336
98683
  }
98337
98684
  }
98338
- if (vesuAmount.minus(usdcAmountInWallet).greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
98339
- try {
98340
- const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
98341
- {
98342
- to: Protocols.VAULT.name,
98343
- from: Protocols.EXTENDED.name,
98344
- amount: vesuAmount.minus(usdcAmountInWallet)
98345
- },
98346
- extendedAdapter,
98347
- vesuAdapter
98685
+ if (vesuAmountDifferenceAbs.greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
98686
+ if (vesuAmountDifference.lessThanOrEqualTo(0)) {
98687
+ logger2.warn(
98688
+ `Vesu amount difference is negative or zero: ${vesuAmountDifference.toNumber()}. Skipping operation.`
98348
98689
  );
98349
- if (!vesuStatus) {
98690
+ } else {
98691
+ try {
98692
+ const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
98693
+ {
98694
+ to: Protocols.VAULT.name,
98695
+ from: Protocols.EXTENDED.name,
98696
+ amount: vesuAmountDifference
98697
+ },
98698
+ extendedAdapter,
98699
+ vesuAdapter
98700
+ );
98701
+ if (!vesuStatus) {
98702
+ logger2.error(`Failed to move assets to vesu - operation returned false status`);
98703
+ return [];
98704
+ }
98705
+ calls.push(...vesuCalls);
98706
+ } catch (err2) {
98707
+ logger2.error(`Failed moving assets to vault: ${err2}`);
98350
98708
  return [];
98351
98709
  }
98352
- calls.push(...vesuCalls);
98353
- } catch (err2) {
98354
- logger2.error(`Failed moving assets to vault: ${err2}`);
98355
98710
  }
98356
98711
  }
98357
98712
  return calls;
@@ -98362,6 +98717,38 @@ spurious results.`);
98362
98717
  }
98363
98718
  async moveAssets(params, extendedAdapter, vesuAdapter) {
98364
98719
  try {
98720
+ if (params.amount.lessThanOrEqualTo(0)) {
98721
+ logger2.error(
98722
+ `Invalid amount for moveAssets: ${params.amount.toNumber()}. Amount must be positive.`
98723
+ );
98724
+ return {
98725
+ calls: [],
98726
+ status: false
98727
+ };
98728
+ }
98729
+ const amountAbs = params.amount.abs();
98730
+ if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
98731
+ if (amountAbs.lessThanOrEqualTo(extendedAdapter.minimumExtendedMovementAmount)) {
98732
+ logger2.warn(
98733
+ `Amount ${amountAbs.toNumber()} is below minimum Extended movement amount ${extendedAdapter.minimumExtendedMovementAmount}. Skipping operation.`
98734
+ );
98735
+ return {
98736
+ calls: [],
98737
+ status: false
98738
+ };
98739
+ }
98740
+ }
98741
+ if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
98742
+ if (amountAbs.lessThanOrEqualTo(vesuAdapter.minimumVesuMovementAmount)) {
98743
+ logger2.warn(
98744
+ `Amount ${amountAbs.toNumber()} is below minimum Vesu movement amount ${vesuAdapter.minimumVesuMovementAmount}. Skipping operation.`
98745
+ );
98746
+ return {
98747
+ calls: [],
98748
+ status: false
98749
+ };
98750
+ }
98751
+ }
98365
98752
  const avnuAdapter = await this.getAvnuAdapter();
98366
98753
  if (!avnuAdapter) {
98367
98754
  logger2.error(`avnu adapter not found: ${avnuAdapter}`);
@@ -98422,18 +98809,18 @@ spurious results.`);
98422
98809
  );
98423
98810
  if (!openLongPosition) {
98424
98811
  logger2.error(`error opening long position: ${openLongPosition}`);
98425
- return {
98426
- calls: [],
98427
- status: false
98428
- };
98429
98812
  }
98430
- await new Promise((resolve) => setTimeout(resolve, 5e3));
98813
+ const updatedHoldings = await extendedAdapter.getExtendedDepositAmount();
98814
+ if (!updatedHoldings || new Web3Number(updatedHoldings.availableForWithdrawal, USDC_TOKEN_DECIMALS).lessThan(params.amount.abs())) {
98815
+ logger2.error(`Insufficient balance after opening position. Available: ${updatedHoldings?.availableForWithdrawal}, Needed: ${params.amount.abs()}`);
98816
+ return { calls: [], status: false };
98817
+ }
98431
98818
  }
98432
98819
  const withdrawalFromExtended = await extendedAdapter.withdrawFromExtended(params.amount);
98433
98820
  if (withdrawalFromExtended) {
98434
98821
  const extendedHoldings2 = await extendedAdapter.getExtendedDepositAmount();
98435
98822
  logger2.info(`extendedHoldings after withdrawal ${extendedHoldings2?.availableForWithdrawal}`);
98436
- await new Promise((resolve) => setTimeout(resolve, 1e4));
98823
+ await new Promise((resolve) => setTimeout(resolve, 2e3));
98437
98824
  const calls = await this.moveAssetsToVaultAllocator(params.amount, extendedAdapter);
98438
98825
  if (calls.length > 0) {
98439
98826
  return {