@strkfarm/sdk 2.0.0-dev.6 → 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.
@@ -92380,7 +92380,7 @@ spurious results.`);
92380
92380
  var MAX_RETRIES = Number(process.env.MAX_RETRIES ?? 3);
92381
92381
  var MAX_DELAY = Number(process.env.MAX_DELAY ?? 100);
92382
92382
  var EXTEND_MARKET_NAME = "BTC-USD";
92383
- var LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ?? 10);
92383
+ var LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ?? 0.05);
92384
92384
  var REBALANCER_INTERVAL = Number(process.env.REBALANCER_INTERVAL ?? 18e4);
92385
92385
  var WITHDRAWAL_INTERVAL = Number(process.env.WITHDRAWAL_INTERVAL ?? 18e6);
92386
92386
  var INVESTING_INTERVAL = Number(process.env.INVESTING_INTERVAL ?? 18e4);
@@ -92637,6 +92637,7 @@ spurious results.`);
92637
92637
  vaultAllocator: config3.vaultAllocator,
92638
92638
  id: ""
92639
92639
  });
92640
+ this.minimumVesuMovementAmount = config3.minimumVesuMovementAmount ?? 5;
92640
92641
  this.tokenMarketData = new TokenMarketData(
92641
92642
  this.config.pricer,
92642
92643
  this.config.networkConfig
@@ -93645,7 +93646,9 @@ spurious results.`);
93645
93646
  timeout: this.config.extendedTimeout,
93646
93647
  retries: this.config.extendedRetries
93647
93648
  });
93649
+ this.minimumExtendedMovementAmount = this.config.minimumExtendedMovementAmount ?? 5;
93648
93650
  this.client = client;
93651
+ this.retryDelayForOrderStatus = this.config.retryDelayForOrderStatus ?? 3e3;
93649
93652
  }
93650
93653
  //abstract means the method has no implementation in this class; instead, child classes must implement it.
93651
93654
  async getAPY(supportedPosition) {
@@ -93943,8 +93946,47 @@ spurious results.`);
93943
93946
  async withdrawFromExtended(amount) {
93944
93947
  try {
93945
93948
  if (!this.client) {
93946
- 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;
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;
93947
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
+ );
93948
93990
  const withdrawalRequest = await this.client.withdrawUSDC(
93949
93991
  amount.toFixed(2)
93950
93992
  );
@@ -93955,6 +93997,9 @@ spurious results.`);
93955
93997
  );
93956
93998
  return withdrawalStatus;
93957
93999
  }
94000
+ logger2.error(
94001
+ `Withdrawal request failed with status: ${withdrawalRequest.status}`
94002
+ );
93958
94003
  return false;
93959
94004
  } catch (error2) {
93960
94005
  logger2.error(`Error creating Withdraw Call: ${error2}`);
@@ -93965,21 +94010,44 @@ spurious results.`);
93965
94010
  return Promise.resolve(1);
93966
94011
  }
93967
94012
  async getExtendedDepositAmount() {
93968
- if (this.client === null) {
93969
- logger2.error("error initializing client");
93970
- return void 0;
93971
- }
93972
- const result2 = await this.client.getHoldings();
93973
- if (!result2) {
93974
- logger2.error(`error getting holdings: ${result2}`);
93975
- return void 0;
93976
- }
93977
- const holdings = result2.data;
93978
- if (!holdings) {
93979
- 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}`);
93980
94049
  return void 0;
93981
94050
  }
93982
- return holdings;
93983
94051
  }
93984
94052
  async setLeverage(leverage, marketName) {
93985
94053
  if (this.client === null) {
@@ -94021,38 +94089,24 @@ spurious results.`);
94021
94089
  return result2.data;
94022
94090
  }
94023
94091
  async getOrderStatus(orderId, marketName) {
94024
- if (this.client === null) {
94025
- logger2.error("error initializing client");
94026
- return null;
94027
- }
94028
- let orderhistory = await this.getOrderHistory(marketName);
94029
- if (!orderhistory || orderhistory.length === 0) {
94030
- logger2.error(`error getting order history: ${orderId}`);
94031
- } else {
94032
- const order = orderhistory.slice(0, 5).find((order2) => order2.id.toString() === orderId);
94033
- if (order) {
94034
- return order;
94092
+ try {
94093
+ if (this.client === null) {
94094
+ logger2.error("error initializing client");
94095
+ return null;
94035
94096
  }
94036
- }
94037
- for (let attempt = 1; attempt <= 3; attempt++) {
94038
- await new Promise((resolve) => setTimeout(resolve, 3e3));
94039
- orderhistory = await this.getOrderHistory(marketName);
94097
+ const orderhistory = await this.getOrderHistory(marketName);
94040
94098
  if (!orderhistory || orderhistory.length === 0) {
94041
- logger2.error(
94042
- `error getting order history on retry ${attempt}: ${orderId}`
94043
- );
94044
- continue;
94099
+ return null;
94045
94100
  }
94046
- const order = orderhistory.slice(0, 5).find((order2) => order2.id.toString() === orderId);
94101
+ const order = orderhistory.slice(0, 20).find((order2) => order2.id.toString() === orderId);
94047
94102
  if (order) {
94048
94103
  return order;
94049
94104
  }
94050
- logger2.error(
94051
- `order not found in top 5 entries on retry ${attempt}: ${orderId}`
94052
- );
94105
+ return null;
94106
+ } catch (error2) {
94107
+ logger2.error(`error getting order status: ${error2}`);
94108
+ return null;
94053
94109
  }
94054
- logger2.error(`error getting order after all retries: ${orderId}`);
94055
- return null;
94056
94110
  }
94057
94111
  async fetchOrderBookBTCUSDC() {
94058
94112
  try {
@@ -94103,14 +94157,40 @@ spurious results.`);
94103
94157
  logger2.error("error depositing or setting leverage");
94104
94158
  return null;
94105
94159
  }
94106
- const positions = await this.getAllOpenPositions();
94107
- 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
+ );
94108
94165
  return null;
94109
94166
  }
94110
- const { ask, bid } = await this.fetchOrderBookBTCUSDC();
94111
94167
  const spread3 = ask.minus(bid);
94112
- let price = ask.plus(bid).div(2);
94113
- 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
+ );
94114
94194
  const amount_in_token = (btcAmount * parseInt(leverage)).toFixed(
94115
94195
  this.config.extendedPrecision
94116
94196
  );
@@ -94121,17 +94201,57 @@ spurious results.`);
94121
94201
  price.toFixed(0),
94122
94202
  side
94123
94203
  );
94124
- if (!result2) {
94204
+ if (!result2 || !result2.position_id) {
94205
+ logger2.error("Failed to create order - no position_id returned");
94125
94206
  return null;
94126
94207
  }
94127
- await new Promise((resolve) => setTimeout(resolve, 5e3));
94128
- const openOrder = await this.getOrderStatus(
94129
- 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,
94130
94214
  this.config.extendedMarketName
94131
94215
  );
94132
- if (!openOrder || openOrder.status !== "FILLED" /* FILLED */) {
94216
+ const maxStatusRetries = 3;
94217
+ const statusRetryDelay = 5e3;
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
+ );
94133
94251
  if (attempt >= maxAttempts) {
94134
- 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
+ );
94135
94255
  return null;
94136
94256
  } else {
94137
94257
  const backoff = 2e3 * attempt;
@@ -94145,9 +94265,12 @@ spurious results.`);
94145
94265
  );
94146
94266
  }
94147
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
+ );
94148
94271
  return {
94149
- position_id: result2.position_id,
94150
- btc_exposure: openOrder.qty
94272
+ position_id: positionId,
94273
+ btc_exposure: amount_in_token
94151
94274
  };
94152
94275
  }
94153
94276
  } catch (err2) {
@@ -97480,7 +97603,8 @@ spurious results.`);
97480
97603
  minHealthFactor: vaultSettings.minHealthFactor,
97481
97604
  quoteAmountToFetchPrice: vaultSettings.quoteAmountToFetchPrice,
97482
97605
  ...baseAdapterConfig,
97483
- supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }]
97606
+ supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }],
97607
+ minimumVesuMovementAmount: 0
97484
97608
  }));
97485
97609
  const unusedBalanceAdapter = new UnusedBalanceAdapter({
97486
97610
  ...baseAdapterConfig
@@ -97821,7 +97945,6 @@ spurious results.`);
97821
97945
  toToken.decimals,
97822
97946
  true
97823
97947
  );
97824
- console.log(`${_AvnuAdapter.name}::getDepositCall quote: ${quote?.sellAmountInUsd}`);
97825
97948
  if (!quote) {
97826
97949
  logger2.error("error getting quote from avnu");
97827
97950
  return [];
@@ -98162,11 +98285,27 @@ spurious results.`);
98162
98285
  }
98163
98286
  async shouldInvest() {
98164
98287
  try {
98288
+ logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest starting`);
98165
98289
  const vesuAdapter = await this.getVesuAdapter();
98166
98290
  const extendedAdapter = await this.getExtendedAdapter();
98167
- if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
98291
+ logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest adapters fetched: vesuAdapter=${!!vesuAdapter}, extendedAdapter=${!!extendedAdapter}, extendedAdapter.client=${!!extendedAdapter?.client}`);
98292
+ if (!vesuAdapter) {
98168
98293
  logger2.error(
98169
- `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
98294
+ `Vesu adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
98295
+ );
98296
+ return {
98297
+ shouldInvest: false,
98298
+ vesuAmount: new Web3Number(0, 0),
98299
+ extendedAmount: new Web3Number(0, 0),
98300
+ extendedLeverage: 0,
98301
+ collateralPrice: 0,
98302
+ debtPrice: 0,
98303
+ vesuLeverage: 0
98304
+ };
98305
+ }
98306
+ if (!extendedAdapter) {
98307
+ logger2.error(
98308
+ `Extended adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
98170
98309
  );
98171
98310
  return {
98172
98311
  shouldInvest: false,
@@ -98178,10 +98317,72 @@ spurious results.`);
98178
98317
  vesuLeverage: 0
98179
98318
  };
98180
98319
  }
98320
+ if (!extendedAdapter.client) {
98321
+ logger2.error(
98322
+ `Extended adapter client not initialized. This may be a temporary initialization failure - check network connectivity and API availability.`
98323
+ );
98324
+ return {
98325
+ shouldInvest: false,
98326
+ vesuAmount: new Web3Number(0, 0),
98327
+ extendedAmount: new Web3Number(0, 0),
98328
+ extendedLeverage: 0,
98329
+ collateralPrice: 0,
98330
+ debtPrice: 0,
98331
+ vesuLeverage: 0
98332
+ };
98333
+ }
98334
+ logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest calling getUnusedBalance`);
98181
98335
  const balance = await this.getUnusedBalance();
98336
+ if (!Number.isFinite(balance.usdValue) || balance.usdValue < 0) {
98337
+ logger2.error(
98338
+ `Invalid balance.usdValue: ${balance.usdValue}. Expected a finite, non-negative number.`
98339
+ );
98340
+ return {
98341
+ shouldInvest: false,
98342
+ vesuAmount: new Web3Number(0, 0),
98343
+ extendedAmount: new Web3Number(0, 0),
98344
+ extendedLeverage: 0,
98345
+ collateralPrice: 0,
98346
+ debtPrice: 0,
98347
+ vesuLeverage: 0
98348
+ };
98349
+ }
98350
+ logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest balance: ${balance.usdValue}`);
98182
98351
  const usdcBalanceOnExtended = await extendedAdapter.getExtendedDepositAmount();
98183
- const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).minus(LIMIT_BALANCE);
98184
- logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvest.toNumber()}`);
98352
+ if (usdcBalanceOnExtended) {
98353
+ const availableForWithdrawal = parseFloat(usdcBalanceOnExtended.availableForWithdrawal);
98354
+ if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
98355
+ logger2.error(
98356
+ `Invalid usdcBalanceOnExtended.availableForWithdrawal: ${usdcBalanceOnExtended.availableForWithdrawal}. Expected a finite, non-negative number.`
98357
+ );
98358
+ return {
98359
+ shouldInvest: false,
98360
+ vesuAmount: new Web3Number(0, 0),
98361
+ extendedAmount: new Web3Number(0, 0),
98362
+ extendedLeverage: 0,
98363
+ collateralPrice: 0,
98364
+ debtPrice: 0,
98365
+ vesuLeverage: 0
98366
+ };
98367
+ }
98368
+ }
98369
+ const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).multipliedBy(1 - LIMIT_BALANCE);
98370
+ const amountToInvestNumber = amountToInvest.toNumber();
98371
+ if (!Number.isFinite(amountToInvestNumber)) {
98372
+ logger2.error(
98373
+ `Invalid amountToInvest calculation result: ${amountToInvestNumber}. Calculation may have produced NaN or Infinity.`
98374
+ );
98375
+ return {
98376
+ shouldInvest: false,
98377
+ vesuAmount: new Web3Number(0, 0),
98378
+ extendedAmount: new Web3Number(0, 0),
98379
+ extendedLeverage: 0,
98380
+ collateralPrice: 0,
98381
+ debtPrice: 0,
98382
+ vesuLeverage: 0
98383
+ };
98384
+ }
98385
+ logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvestNumber}`);
98185
98386
  if (amountToInvest.lessThan(0)) {
98186
98387
  return {
98187
98388
  shouldInvest: false,
@@ -98211,6 +98412,34 @@ spurious results.`);
98211
98412
  collateralPrice,
98212
98413
  debtPrice
98213
98414
  } = await this.getAssetPrices();
98415
+ if (!Number.isFinite(collateralPrice.price) || collateralPrice.price <= 0) {
98416
+ logger2.error(
98417
+ `Invalid collateralPrice: ${collateralPrice.price}. Expected a finite, positive number.`
98418
+ );
98419
+ return {
98420
+ shouldInvest: false,
98421
+ vesuAmount: new Web3Number(0, 0),
98422
+ extendedAmount: new Web3Number(0, 0),
98423
+ extendedLeverage: 0,
98424
+ collateralPrice: 0,
98425
+ debtPrice: 0,
98426
+ vesuLeverage: 0
98427
+ };
98428
+ }
98429
+ if (!Number.isFinite(debtPrice.price) || debtPrice.price <= 0) {
98430
+ logger2.error(
98431
+ `Invalid debtPrice: ${debtPrice.price}. Expected a finite, positive number.`
98432
+ );
98433
+ return {
98434
+ shouldInvest: false,
98435
+ vesuAmount: new Web3Number(0, 0),
98436
+ extendedAmount: new Web3Number(0, 0),
98437
+ extendedLeverage: 0,
98438
+ collateralPrice: 0,
98439
+ debtPrice: 0,
98440
+ vesuLeverage: 0
98441
+ };
98442
+ }
98214
98443
  const { vesu_amount, extended_amount, extended_leverage, vesu_leverage } = await calculateAmountDistribution(
98215
98444
  amountToInvest.toNumber(),
98216
98445
  extendedAdapter.client,
@@ -98261,14 +98490,46 @@ spurious results.`);
98261
98490
  try {
98262
98491
  const vesuAdapter = await this.getVesuAdapter();
98263
98492
  const extendedAdapter = await this.getExtendedAdapter();
98264
- let calls = [];
98265
98493
  if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
98266
98494
  logger2.error(
98267
98495
  `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
98268
98496
  );
98269
- return calls;
98497
+ return [];
98270
98498
  }
98271
- if (extendedAmount.lessThan(0)) {
98499
+ const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
98500
+ if (!extendedHoldings) {
98501
+ logger2.error(`error getting extended holdings: ${extendedHoldings}`);
98502
+ return [];
98503
+ }
98504
+ const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
98505
+ const usdcAmountOnExtendedAvailableForWithdrawal = parseFloat(
98506
+ extendedHoldings.availableForWithdrawal
98507
+ );
98508
+ logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculating movements - Extended current: ${usdcAmountOnExtendedAvailableForWithdrawal}, Wallet: ${usdcAmountInWallet.toNumber()}, Target Extended: ${extendedAmount.toNumber()}, Target Vesu: ${vesuAmount.toNumber()}`);
98509
+ let totalExtendedWithdrawal = new Web3Number(0, USDC_TOKEN_DECIMALS);
98510
+ let totalExtendedDeposit = new Web3Number(0, USDC_TOKEN_DECIMALS);
98511
+ if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
98512
+ totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmount.abs());
98513
+ }
98514
+ const extendedTargetAmount = extendedAmount.abs();
98515
+ let projectedExtendedBalance = usdcAmountOnExtendedAvailableForWithdrawal;
98516
+ if (extendedAmount.isNegative()) {
98517
+ projectedExtendedBalance = projectedExtendedBalance - extendedAmount.abs().toNumber();
98518
+ }
98519
+ const extendedAmountDifference = extendedTargetAmount.minus(projectedExtendedBalance);
98520
+ const extendedAmountDifferenceAbs = extendedAmountDifference.abs();
98521
+ if (extendedAmountDifference.lessThan(0)) {
98522
+ totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmountDifferenceAbs);
98523
+ } else if (extendedAmountDifference.greaterThan(0)) {
98524
+ totalExtendedDeposit = totalExtendedDeposit.plus(extendedAmountDifference);
98525
+ }
98526
+ const vesuTargetAmount = vesuAmount.abs();
98527
+ const projectedWalletBalance = usdcAmountInWallet.plus(totalExtendedWithdrawal).minus(totalExtendedDeposit);
98528
+ let vesuAmountDifference = vesuTargetAmount.minus(projectedWalletBalance);
98529
+ const vesuAmountDifferenceAbs = vesuAmountDifference.abs();
98530
+ 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()}`);
98531
+ let calls = [];
98532
+ if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
98272
98533
  try {
98273
98534
  const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
98274
98535
  {
@@ -98288,7 +98549,7 @@ spurious results.`);
98288
98549
  logger2.error(`Failed moving assets to vault: ${err2}`);
98289
98550
  }
98290
98551
  }
98291
- if (vesuAmount.lessThan(0)) {
98552
+ if (vesuAmount.isNegative() && vesuAmount.abs().greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
98292
98553
  try {
98293
98554
  const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
98294
98555
  {
@@ -98307,48 +98568,76 @@ spurious results.`);
98307
98568
  logger2.error(`Failed moving assets to vault: ${err2}`);
98308
98569
  }
98309
98570
  }
98310
- const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
98311
- if (!extendedHoldings) {
98312
- logger2.error(`error getting extended holdings: ${extendedHoldings}`);
98313
- return calls;
98314
- }
98315
- const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
98316
- const usdcAmountOnExtended = parseFloat(
98317
- extendedHoldings.availableForWithdrawal
98318
- );
98319
- if (extendedAmount.minus(usdcAmountOnExtended).greaterThan(0)) {
98320
- try {
98321
- const { calls: extendedCalls } = await this.moveAssets(
98322
- {
98323
- to: Protocols.EXTENDED.name,
98324
- from: Protocols.VAULT.name,
98325
- amount: extendedAmount.minus(usdcAmountOnExtended)
98326
- },
98327
- extendedAdapter,
98328
- vesuAdapter
98329
- );
98330
- calls.push(...extendedCalls);
98331
- } catch (err2) {
98332
- logger2.error(`Failed moving assets to extended: ${err2}`);
98571
+ if (extendedAmountDifferenceAbs.greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
98572
+ if (extendedAmountDifference.greaterThan(0)) {
98573
+ try {
98574
+ const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
98575
+ {
98576
+ to: Protocols.EXTENDED.name,
98577
+ from: Protocols.VAULT.name,
98578
+ amount: extendedAmountDifference
98579
+ },
98580
+ extendedAdapter,
98581
+ vesuAdapter
98582
+ );
98583
+ if (extendedStatus) {
98584
+ calls.push(...extendedCalls);
98585
+ } else {
98586
+ logger2.error(`Failed to move assets to extended - operation returned false status`);
98587
+ return [];
98588
+ }
98589
+ } catch (err2) {
98590
+ logger2.error(`Failed moving assets to extended: ${err2}`);
98591
+ return [];
98592
+ }
98593
+ } else if (extendedAmountDifference.lessThan(0)) {
98594
+ try {
98595
+ const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
98596
+ {
98597
+ to: Protocols.VAULT.name,
98598
+ from: Protocols.EXTENDED.name,
98599
+ amount: extendedAmountDifferenceAbs
98600
+ },
98601
+ extendedAdapter,
98602
+ vesuAdapter
98603
+ );
98604
+ if (extendedStatus) {
98605
+ calls.push(...extendedCalls);
98606
+ } else {
98607
+ logger2.error(`Failed to withdraw from extended - operation returned false status`);
98608
+ return [];
98609
+ }
98610
+ } catch (err2) {
98611
+ logger2.error(`Failed moving assets from extended to vault: ${err2}`);
98612
+ return [];
98613
+ }
98333
98614
  }
98334
98615
  }
98335
- if (vesuAmount.minus(usdcAmountInWallet).greaterThan(0)) {
98336
- try {
98337
- const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
98338
- {
98339
- to: Protocols.VAULT.name,
98340
- from: Protocols.EXTENDED.name,
98341
- amount: vesuAmount.minus(usdcAmountInWallet)
98342
- },
98343
- extendedAdapter,
98344
- vesuAdapter
98616
+ if (vesuAmountDifferenceAbs.greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
98617
+ if (vesuAmountDifference.lessThanOrEqualTo(0)) {
98618
+ logger2.warn(
98619
+ `Vesu amount difference is negative or zero: ${vesuAmountDifference.toNumber()}. Skipping operation.`
98345
98620
  );
98346
- if (!vesuStatus) {
98621
+ } else {
98622
+ try {
98623
+ const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
98624
+ {
98625
+ to: Protocols.VAULT.name,
98626
+ from: Protocols.EXTENDED.name,
98627
+ amount: vesuAmountDifference
98628
+ },
98629
+ extendedAdapter,
98630
+ vesuAdapter
98631
+ );
98632
+ if (!vesuStatus) {
98633
+ logger2.error(`Failed to move assets to vesu - operation returned false status`);
98634
+ return [];
98635
+ }
98636
+ calls.push(...vesuCalls);
98637
+ } catch (err2) {
98638
+ logger2.error(`Failed moving assets to vault: ${err2}`);
98347
98639
  return [];
98348
98640
  }
98349
- calls.push(...vesuCalls);
98350
- } catch (err2) {
98351
- logger2.error(`Failed moving assets to vault: ${err2}`);
98352
98641
  }
98353
98642
  }
98354
98643
  return calls;
@@ -98359,6 +98648,38 @@ spurious results.`);
98359
98648
  }
98360
98649
  async moveAssets(params, extendedAdapter, vesuAdapter) {
98361
98650
  try {
98651
+ if (params.amount.lessThanOrEqualTo(0)) {
98652
+ logger2.error(
98653
+ `Invalid amount for moveAssets: ${params.amount.toNumber()}. Amount must be positive.`
98654
+ );
98655
+ return {
98656
+ calls: [],
98657
+ status: false
98658
+ };
98659
+ }
98660
+ const amountAbs = params.amount.abs();
98661
+ if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
98662
+ if (amountAbs.lessThanOrEqualTo(extendedAdapter.minimumExtendedMovementAmount)) {
98663
+ logger2.warn(
98664
+ `Amount ${amountAbs.toNumber()} is below minimum Extended movement amount ${extendedAdapter.minimumExtendedMovementAmount}. Skipping operation.`
98665
+ );
98666
+ return {
98667
+ calls: [],
98668
+ status: false
98669
+ };
98670
+ }
98671
+ }
98672
+ if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
98673
+ if (amountAbs.lessThanOrEqualTo(vesuAdapter.minimumVesuMovementAmount)) {
98674
+ logger2.warn(
98675
+ `Amount ${amountAbs.toNumber()} is below minimum Vesu movement amount ${vesuAdapter.minimumVesuMovementAmount}. Skipping operation.`
98676
+ );
98677
+ return {
98678
+ calls: [],
98679
+ status: false
98680
+ };
98681
+ }
98682
+ }
98362
98683
  const avnuAdapter = await this.getAvnuAdapter();
98363
98684
  if (!avnuAdapter) {
98364
98685
  logger2.error(`avnu adapter not found: ${avnuAdapter}`);
@@ -98419,12 +98740,13 @@ spurious results.`);
98419
98740
  );
98420
98741
  if (!openLongPosition) {
98421
98742
  logger2.error(`error opening long position: ${openLongPosition}`);
98422
- return {
98423
- calls: [],
98424
- status: false
98425
- };
98426
98743
  }
98427
98744
  await new Promise((resolve) => setTimeout(resolve, 5e3));
98745
+ const updatedHoldings = await extendedAdapter.getExtendedDepositAmount();
98746
+ if (!updatedHoldings || new Web3Number(updatedHoldings.availableForWithdrawal, USDC_TOKEN_DECIMALS).lessThan(params.amount.abs())) {
98747
+ logger2.error(`Insufficient balance after opening position. Available: ${updatedHoldings?.availableForWithdrawal}, Needed: ${params.amount.abs()}`);
98748
+ return { calls: [], status: false };
98749
+ }
98428
98750
  }
98429
98751
  const withdrawalFromExtended = await extendedAdapter.withdrawFromExtended(params.amount);
98430
98752
  if (withdrawalFromExtended) {
@@ -98797,7 +99119,7 @@ spurious results.`);
98797
99119
  };
98798
99120
  }
98799
99121
  };
98800
- function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendUrl, extendedApiKey, vaultIdExtended) {
99122
+ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus) {
98801
99123
  vaultSettings.leafAdapters = [];
98802
99124
  const wbtcToken = Global.getDefaultTokens().find(
98803
99125
  (token) => token.symbol === lstSymbol
@@ -98837,7 +99159,10 @@ spurious results.`);
98837
99159
  extendedBaseUrl: "https://api.starknet.extended.exchange",
98838
99160
  extendedMarketName: "BTC-USD",
98839
99161
  extendedPrecision: 5,
98840
- avnuAdapter
99162
+ avnuAdapter,
99163
+ retryDelayForOrderStatus: minimumExtendedRetriesDelayForOrderStatus ?? 3e3,
99164
+ minimumExtendedMovementAmount: minimumExtendedMovementAmount ?? 5
99165
+ //5 usdcs
98841
99166
  });
98842
99167
  const vesuMultiplyAdapter = new VesuMultiplyAdapter({
98843
99168
  poolId: pool1,
@@ -98850,7 +99175,9 @@ spurious results.`);
98850
99175
  supportedPositions: [
98851
99176
  { asset: wbtcToken, isDebt: false },
98852
99177
  { asset: usdcToken, isDebt: true }
98853
- ]
99178
+ ],
99179
+ minimumVesuMovementAmount: minimumVesuMovementAmount ?? 5
99180
+ //5 usdc
98854
99181
  });
98855
99182
  const unusedBalanceAdapter = new UnusedBalanceAdapter({
98856
99183
  ...baseAdapterConfig
@@ -98965,12 +99292,12 @@ spurious results.`);
98965
99292
  borrowable_assets: [Global.getDefaultTokens().find((token) => token.symbol === "WBTC")],
98966
99293
  minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP
98967
99294
  };
98968
- var VesuExtendedTestStrategies = (extendedBackendUrl, extendedApiKey, vaultIdExtended) => {
99295
+ var VesuExtendedTestStrategies = (extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus) => {
98969
99296
  return [
98970
- getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false, extendedBackendUrl, extendedApiKey, vaultIdExtended)
99297
+ getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus)
98971
99298
  ];
98972
99299
  };
98973
- function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendUrl, extendedApiKey, vaultIdExtended) {
99300
+ function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus) {
98974
99301
  return {
98975
99302
  name: `Extended Test ${underlyingSymbol}`,
98976
99303
  description: getDescription2(lstSymbol, underlyingSymbol),
@@ -98978,7 +99305,7 @@ spurious results.`);
98978
99305
  launchBlock: 0,
98979
99306
  type: "Other",
98980
99307
  depositTokens: [Global.getDefaultTokens().find((token) => token.symbol === underlyingSymbol)],
98981
- additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendUrl, extendedApiKey, vaultIdExtended),
99308
+ additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus),
98982
99309
  risk: {
98983
99310
  riskFactor: _riskFactor3,
98984
99311
  netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),