@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.
package/dist/index.js CHANGED
@@ -28168,7 +28168,7 @@ var STRK_API_RPC = process.env.STRK_API_RPC ?? "https://mainnet.starknet.a5a.ch"
28168
28168
  var MAX_RETRIES = Number(process.env.MAX_RETRIES ?? 3);
28169
28169
  var MAX_DELAY = Number(process.env.MAX_DELAY ?? 100);
28170
28170
  var EXTEND_MARKET_NAME = "BTC-USD";
28171
- var LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ?? 10);
28171
+ var LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ?? 0.05);
28172
28172
  var REBALANCER_INTERVAL = Number(process.env.REBALANCER_INTERVAL ?? 18e4);
28173
28173
  var WITHDRAWAL_INTERVAL = Number(process.env.WITHDRAWAL_INTERVAL ?? 18e6);
28174
28174
  var INVESTING_INTERVAL = Number(process.env.INVESTING_INTERVAL ?? 18e4);
@@ -28425,6 +28425,7 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28425
28425
  vaultAllocator: config.vaultAllocator,
28426
28426
  id: ""
28427
28427
  });
28428
+ this.minimumVesuMovementAmount = config.minimumVesuMovementAmount ?? 5;
28428
28429
  this.tokenMarketData = new TokenMarketData(
28429
28430
  this.config.pricer,
28430
28431
  this.config.networkConfig
@@ -29771,7 +29772,9 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29771
29772
  timeout: this.config.extendedTimeout,
29772
29773
  retries: this.config.extendedRetries
29773
29774
  });
29775
+ this.minimumExtendedMovementAmount = this.config.minimumExtendedMovementAmount ?? 5;
29774
29776
  this.client = client;
29777
+ this.retryDelayForOrderStatus = this.config.retryDelayForOrderStatus ?? 3e3;
29775
29778
  }
29776
29779
  //abstract means the method has no implementation in this class; instead, child classes must implement it.
29777
29780
  async getAPY(supportedPosition) {
@@ -30069,8 +30072,47 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
30069
30072
  async withdrawFromExtended(amount) {
30070
30073
  try {
30071
30074
  if (!this.client) {
30072
- throw new Error("Client not initialized");
30075
+ logger.error("Client not initialized");
30076
+ return false;
30077
+ }
30078
+ if (amount.lessThanOrEqualTo(0)) {
30079
+ logger.error(
30080
+ `Invalid withdrawal amount: ${amount.toNumber()}. Amount must be positive.`
30081
+ );
30082
+ return false;
30083
+ }
30084
+ if (amount.lessThanOrEqualTo(this.minimumExtendedMovementAmount)) {
30085
+ logger.warn(
30086
+ `Withdrawal amount ${amount.toNumber()} is below minimum Extended movement amount ${this.minimumExtendedMovementAmount}. Skipping withdrawal.`
30087
+ );
30088
+ return false;
30089
+ }
30090
+ const holdings = await this.getExtendedDepositAmount();
30091
+ if (!holdings) {
30092
+ logger.error(
30093
+ "Cannot get holdings - unable to validate withdrawal amount"
30094
+ );
30095
+ return false;
30096
+ }
30097
+ const availableForWithdrawal = parseFloat(
30098
+ holdings.availableForWithdrawal
30099
+ );
30100
+ if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
30101
+ logger.error(
30102
+ `Invalid availableForWithdrawal: ${holdings.availableForWithdrawal}. Expected a finite, non-negative number.`
30103
+ );
30104
+ return false;
30105
+ }
30106
+ const withdrawalAmount = amount.toNumber();
30107
+ if (withdrawalAmount > availableForWithdrawal) {
30108
+ logger.error(
30109
+ `Withdrawal amount ${withdrawalAmount} exceeds available balance ${availableForWithdrawal}`
30110
+ );
30111
+ return false;
30073
30112
  }
30113
+ logger.info(
30114
+ `Withdrawing ${withdrawalAmount} from Extended. Available balance: ${availableForWithdrawal}`
30115
+ );
30074
30116
  const withdrawalRequest = await this.client.withdrawUSDC(
30075
30117
  amount.toFixed(2)
30076
30118
  );
@@ -30081,6 +30123,9 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
30081
30123
  );
30082
30124
  return withdrawalStatus;
30083
30125
  }
30126
+ logger.error(
30127
+ `Withdrawal request failed with status: ${withdrawalRequest.status}`
30128
+ );
30084
30129
  return false;
30085
30130
  } catch (error) {
30086
30131
  logger.error(`Error creating Withdraw Call: ${error}`);
@@ -30091,21 +30136,44 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
30091
30136
  return Promise.resolve(1);
30092
30137
  }
30093
30138
  async getExtendedDepositAmount() {
30094
- if (this.client === null) {
30095
- logger.error("error initializing client");
30096
- return void 0;
30097
- }
30098
- const result = await this.client.getHoldings();
30099
- if (!result) {
30100
- logger.error(`error getting holdings: ${result}`);
30101
- return void 0;
30102
- }
30103
- const holdings = result.data;
30104
- if (!holdings) {
30105
- logger.error(`error getting holdings: ${holdings}`);
30139
+ try {
30140
+ if (this.client === null) {
30141
+ logger.error("error initializing client - client is null");
30142
+ return void 0;
30143
+ }
30144
+ const result = await this.client.getHoldings();
30145
+ if (!result) {
30146
+ logger.error("error getting holdings - API returned null/undefined");
30147
+ return void 0;
30148
+ }
30149
+ if (result.status && result.status !== "OK") {
30150
+ logger.error(
30151
+ `error getting holdings - API returned status: ${result.status}`
30152
+ );
30153
+ return void 0;
30154
+ }
30155
+ const holdings = result.data;
30156
+ if (!holdings) {
30157
+ logger.warn(
30158
+ "holdings data is null/undefined - treating as zero balance"
30159
+ );
30160
+ return {
30161
+ collateral_name: "",
30162
+ balance: "0",
30163
+ equity: "0",
30164
+ availableForTrade: "0",
30165
+ availableForWithdrawal: "0",
30166
+ unrealisedPnl: "0",
30167
+ initialMargin: "0",
30168
+ marginRatio: "0",
30169
+ updatedTime: Date.now()
30170
+ };
30171
+ }
30172
+ return holdings;
30173
+ } catch (error) {
30174
+ logger.error(`error getting holdings - exception: ${error}`);
30106
30175
  return void 0;
30107
30176
  }
30108
- return holdings;
30109
30177
  }
30110
30178
  async setLeverage(leverage, marketName) {
30111
30179
  if (this.client === null) {
@@ -30147,38 +30215,24 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
30147
30215
  return result.data;
30148
30216
  }
30149
30217
  async getOrderStatus(orderId, marketName) {
30150
- if (this.client === null) {
30151
- logger.error("error initializing client");
30152
- return null;
30153
- }
30154
- let orderhistory = await this.getOrderHistory(marketName);
30155
- if (!orderhistory || orderhistory.length === 0) {
30156
- logger.error(`error getting order history: ${orderId}`);
30157
- } else {
30158
- const order = orderhistory.slice(0, 5).find((order2) => order2.id.toString() === orderId);
30159
- if (order) {
30160
- return order;
30218
+ try {
30219
+ if (this.client === null) {
30220
+ logger.error("error initializing client");
30221
+ return null;
30161
30222
  }
30162
- }
30163
- for (let attempt = 1; attempt <= 3; attempt++) {
30164
- await new Promise((resolve) => setTimeout(resolve, 3e3));
30165
- orderhistory = await this.getOrderHistory(marketName);
30223
+ const orderhistory = await this.getOrderHistory(marketName);
30166
30224
  if (!orderhistory || orderhistory.length === 0) {
30167
- logger.error(
30168
- `error getting order history on retry ${attempt}: ${orderId}`
30169
- );
30170
- continue;
30225
+ return null;
30171
30226
  }
30172
- const order = orderhistory.slice(0, 5).find((order2) => order2.id.toString() === orderId);
30227
+ const order = orderhistory.slice(0, 20).find((order2) => order2.id.toString() === orderId);
30173
30228
  if (order) {
30174
30229
  return order;
30175
30230
  }
30176
- logger.error(
30177
- `order not found in top 5 entries on retry ${attempt}: ${orderId}`
30178
- );
30231
+ return null;
30232
+ } catch (error) {
30233
+ logger.error(`error getting order status: ${error}`);
30234
+ return null;
30179
30235
  }
30180
- logger.error(`error getting order after all retries: ${orderId}`);
30181
- return null;
30182
30236
  }
30183
30237
  async fetchOrderBookBTCUSDC() {
30184
30238
  try {
@@ -30229,14 +30283,40 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
30229
30283
  logger.error("error depositing or setting leverage");
30230
30284
  return null;
30231
30285
  }
30232
- const positions = await this.getAllOpenPositions();
30233
- if (positions === null) {
30286
+ const { ask, bid } = await this.fetchOrderBookBTCUSDC();
30287
+ if (!ask || !bid || ask.lessThanOrEqualTo(0) || bid.lessThanOrEqualTo(0)) {
30288
+ logger.error(
30289
+ `Invalid orderbook prices: ask=${ask?.toNumber()}, bid=${bid?.toNumber()}`
30290
+ );
30234
30291
  return null;
30235
30292
  }
30236
- const { ask, bid } = await this.fetchOrderBookBTCUSDC();
30237
30293
  const spread = ask.minus(bid);
30238
- let price = ask.plus(bid).div(2);
30239
- side === "SELL" /* SELL */ ? price = price.minus(spread.times(0.2 * attempt)) : price = price.plus(spread.times(0.2 * attempt));
30294
+ const midPrice = ask.plus(bid).div(2);
30295
+ const MAX_PRICE_DEVIATION_MULTIPLIER = 0.5;
30296
+ const priceAdjustmentMultiplier = Math.min(
30297
+ 0.2 * attempt,
30298
+ MAX_PRICE_DEVIATION_MULTIPLIER
30299
+ );
30300
+ const priceAdjustment = spread.times(priceAdjustmentMultiplier);
30301
+ let price = midPrice;
30302
+ if (side === "SELL" /* SELL */) {
30303
+ price = midPrice.minus(priceAdjustment);
30304
+ } else {
30305
+ price = midPrice.plus(priceAdjustment);
30306
+ }
30307
+ const maxDeviation = midPrice.times(0.5);
30308
+ if (price.minus(midPrice).abs().greaterThan(maxDeviation)) {
30309
+ logger.error(
30310
+ `Price deviation too large on attempt ${attempt}: price=${price.toNumber()}, midPrice=${midPrice.toNumber()}, deviation=${price.minus(midPrice).abs().toNumber()}`
30311
+ );
30312
+ if (attempt >= maxAttempts) {
30313
+ return null;
30314
+ }
30315
+ price = side === "SELL" /* SELL */ ? midPrice.minus(maxDeviation) : midPrice.plus(maxDeviation);
30316
+ }
30317
+ logger.info(
30318
+ `createOrder attempt ${attempt}/${maxAttempts}: side=${side}, midPrice=${midPrice.toNumber()}, adjustedPrice=${price.toNumber()}, adjustment=${priceAdjustmentMultiplier * 100}%`
30319
+ );
30240
30320
  const amount_in_token = (btcAmount * parseInt(leverage)).toFixed(
30241
30321
  this.config.extendedPrecision
30242
30322
  );
@@ -30247,17 +30327,57 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
30247
30327
  price.toFixed(0),
30248
30328
  side
30249
30329
  );
30250
- if (!result) {
30330
+ if (!result || !result.position_id) {
30331
+ logger.error("Failed to create order - no position_id returned");
30251
30332
  return null;
30252
30333
  }
30253
- await new Promise((resolve) => setTimeout(resolve, 5e3));
30254
- const openOrder = await this.getOrderStatus(
30255
- result.position_id,
30334
+ const positionId = result.position_id;
30335
+ logger.info(
30336
+ `Order created with position_id: ${positionId}. Waiting for API to update...`
30337
+ );
30338
+ let openOrder = await this.getOrderStatus(
30339
+ positionId,
30256
30340
  this.config.extendedMarketName
30257
30341
  );
30258
- if (!openOrder || openOrder.status !== "FILLED" /* FILLED */) {
30342
+ const maxStatusRetries = 3;
30343
+ const statusRetryDelay = 5e3;
30344
+ if (!openOrder) {
30345
+ logger.warn(
30346
+ `Order ${positionId} not found in API yet. Retrying status fetch (max ${maxStatusRetries} times)...`
30347
+ );
30348
+ for (let statusRetry = 1; statusRetry <= maxStatusRetries; statusRetry++) {
30349
+ await new Promise((resolve) => setTimeout(resolve, statusRetryDelay));
30350
+ openOrder = await this.getOrderStatus(
30351
+ positionId,
30352
+ this.config.extendedMarketName
30353
+ );
30354
+ if (openOrder) {
30355
+ logger.info(
30356
+ `Order ${positionId} found after ${statusRetry} status retry(ies)`
30357
+ );
30358
+ break;
30359
+ }
30360
+ logger.warn(
30361
+ `Order ${positionId} still not found after ${statusRetry}/${maxStatusRetries} status retries`
30362
+ );
30363
+ }
30364
+ }
30365
+ if (openOrder && openOrder.status === "FILLED" /* FILLED */) {
30366
+ logger.info(
30367
+ `Order ${positionId} successfully filled with quantity ${openOrder.qty}`
30368
+ );
30369
+ return {
30370
+ position_id: positionId,
30371
+ btc_exposure: openOrder.qty
30372
+ };
30373
+ } else if (openOrder && openOrder.status !== "FILLED" /* FILLED */) {
30374
+ logger.warn(
30375
+ `Order ${positionId} found but status is ${openOrder.status}, not FILLED. Retrying order creation...`
30376
+ );
30259
30377
  if (attempt >= maxAttempts) {
30260
- logger.error("Max retries reached \u2014 could not verify open position");
30378
+ logger.error(
30379
+ `Max retries reached \u2014 order ${positionId} status is ${openOrder.status}, not FILLED`
30380
+ );
30261
30381
  return null;
30262
30382
  } else {
30263
30383
  const backoff = 2e3 * attempt;
@@ -30271,9 +30391,12 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
30271
30391
  );
30272
30392
  }
30273
30393
  } else {
30394
+ logger.warn(
30395
+ `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.`
30396
+ );
30274
30397
  return {
30275
- position_id: result.position_id,
30276
- btc_exposure: openOrder.qty
30398
+ position_id: positionId,
30399
+ btc_exposure: amount_in_token
30277
30400
  };
30278
30401
  }
30279
30402
  } catch (err) {
@@ -33609,7 +33732,8 @@ function getLooperSettings(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
33609
33732
  minHealthFactor: vaultSettings.minHealthFactor,
33610
33733
  quoteAmountToFetchPrice: vaultSettings.quoteAmountToFetchPrice,
33611
33734
  ...baseAdapterConfig,
33612
- supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }]
33735
+ supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }],
33736
+ minimumVesuMovementAmount: 0
33613
33737
  }));
33614
33738
  const unusedBalanceAdapter = new UnusedBalanceAdapter({
33615
33739
  ...baseAdapterConfig
@@ -33952,7 +34076,6 @@ var AvnuAdapter = class _AvnuAdapter extends BaseAdapter {
33952
34076
  toToken.decimals,
33953
34077
  true
33954
34078
  );
33955
- console.log(`${_AvnuAdapter.name}::getDepositCall quote: ${quote?.sellAmountInUsd}`);
33956
34079
  if (!quote) {
33957
34080
  logger.error("error getting quote from avnu");
33958
34081
  return [];
@@ -34293,11 +34416,41 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34293
34416
  }
34294
34417
  async shouldInvest() {
34295
34418
  try {
34419
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest starting`);
34296
34420
  const vesuAdapter = await this.getVesuAdapter();
34297
34421
  const extendedAdapter = await this.getExtendedAdapter();
34298
- if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
34422
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest adapters fetched: vesuAdapter=${!!vesuAdapter}, extendedAdapter=${!!extendedAdapter}, extendedAdapter.client=${!!extendedAdapter?.client}`);
34423
+ if (!vesuAdapter) {
34299
34424
  logger.error(
34300
- `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
34425
+ `Vesu adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
34426
+ );
34427
+ return {
34428
+ shouldInvest: false,
34429
+ vesuAmount: new Web3Number(0, 0),
34430
+ extendedAmount: new Web3Number(0, 0),
34431
+ extendedLeverage: 0,
34432
+ collateralPrice: 0,
34433
+ debtPrice: 0,
34434
+ vesuLeverage: 0
34435
+ };
34436
+ }
34437
+ if (!extendedAdapter) {
34438
+ logger.error(
34439
+ `Extended adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
34440
+ );
34441
+ return {
34442
+ shouldInvest: false,
34443
+ vesuAmount: new Web3Number(0, 0),
34444
+ extendedAmount: new Web3Number(0, 0),
34445
+ extendedLeverage: 0,
34446
+ collateralPrice: 0,
34447
+ debtPrice: 0,
34448
+ vesuLeverage: 0
34449
+ };
34450
+ }
34451
+ if (!extendedAdapter.client) {
34452
+ logger.error(
34453
+ `Extended adapter client not initialized. This may be a temporary initialization failure - check network connectivity and API availability.`
34301
34454
  );
34302
34455
  return {
34303
34456
  shouldInvest: false,
@@ -34309,10 +34462,58 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34309
34462
  vesuLeverage: 0
34310
34463
  };
34311
34464
  }
34465
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest calling getUnusedBalance`);
34312
34466
  const balance = await this.getUnusedBalance();
34467
+ if (!Number.isFinite(balance.usdValue) || balance.usdValue < 0) {
34468
+ logger.error(
34469
+ `Invalid balance.usdValue: ${balance.usdValue}. Expected a finite, non-negative number.`
34470
+ );
34471
+ return {
34472
+ shouldInvest: false,
34473
+ vesuAmount: new Web3Number(0, 0),
34474
+ extendedAmount: new Web3Number(0, 0),
34475
+ extendedLeverage: 0,
34476
+ collateralPrice: 0,
34477
+ debtPrice: 0,
34478
+ vesuLeverage: 0
34479
+ };
34480
+ }
34481
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest balance: ${balance.usdValue}`);
34313
34482
  const usdcBalanceOnExtended = await extendedAdapter.getExtendedDepositAmount();
34314
- const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).minus(LIMIT_BALANCE);
34315
- logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvest.toNumber()}`);
34483
+ if (usdcBalanceOnExtended) {
34484
+ const availableForWithdrawal = parseFloat(usdcBalanceOnExtended.availableForWithdrawal);
34485
+ if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
34486
+ logger.error(
34487
+ `Invalid usdcBalanceOnExtended.availableForWithdrawal: ${usdcBalanceOnExtended.availableForWithdrawal}. Expected a finite, non-negative number.`
34488
+ );
34489
+ return {
34490
+ shouldInvest: false,
34491
+ vesuAmount: new Web3Number(0, 0),
34492
+ extendedAmount: new Web3Number(0, 0),
34493
+ extendedLeverage: 0,
34494
+ collateralPrice: 0,
34495
+ debtPrice: 0,
34496
+ vesuLeverage: 0
34497
+ };
34498
+ }
34499
+ }
34500
+ const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).multipliedBy(1 - LIMIT_BALANCE);
34501
+ const amountToInvestNumber = amountToInvest.toNumber();
34502
+ if (!Number.isFinite(amountToInvestNumber)) {
34503
+ logger.error(
34504
+ `Invalid amountToInvest calculation result: ${amountToInvestNumber}. Calculation may have produced NaN or Infinity.`
34505
+ );
34506
+ return {
34507
+ shouldInvest: false,
34508
+ vesuAmount: new Web3Number(0, 0),
34509
+ extendedAmount: new Web3Number(0, 0),
34510
+ extendedLeverage: 0,
34511
+ collateralPrice: 0,
34512
+ debtPrice: 0,
34513
+ vesuLeverage: 0
34514
+ };
34515
+ }
34516
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvestNumber}`);
34316
34517
  if (amountToInvest.lessThan(0)) {
34317
34518
  return {
34318
34519
  shouldInvest: false,
@@ -34342,6 +34543,34 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34342
34543
  collateralPrice,
34343
34544
  debtPrice
34344
34545
  } = await this.getAssetPrices();
34546
+ if (!Number.isFinite(collateralPrice.price) || collateralPrice.price <= 0) {
34547
+ logger.error(
34548
+ `Invalid collateralPrice: ${collateralPrice.price}. Expected a finite, positive number.`
34549
+ );
34550
+ return {
34551
+ shouldInvest: false,
34552
+ vesuAmount: new Web3Number(0, 0),
34553
+ extendedAmount: new Web3Number(0, 0),
34554
+ extendedLeverage: 0,
34555
+ collateralPrice: 0,
34556
+ debtPrice: 0,
34557
+ vesuLeverage: 0
34558
+ };
34559
+ }
34560
+ if (!Number.isFinite(debtPrice.price) || debtPrice.price <= 0) {
34561
+ logger.error(
34562
+ `Invalid debtPrice: ${debtPrice.price}. Expected a finite, positive number.`
34563
+ );
34564
+ return {
34565
+ shouldInvest: false,
34566
+ vesuAmount: new Web3Number(0, 0),
34567
+ extendedAmount: new Web3Number(0, 0),
34568
+ extendedLeverage: 0,
34569
+ collateralPrice: 0,
34570
+ debtPrice: 0,
34571
+ vesuLeverage: 0
34572
+ };
34573
+ }
34345
34574
  const { vesu_amount, extended_amount, extended_leverage, vesu_leverage } = await calculateAmountDistribution(
34346
34575
  amountToInvest.toNumber(),
34347
34576
  extendedAdapter.client,
@@ -34392,14 +34621,46 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34392
34621
  try {
34393
34622
  const vesuAdapter = await this.getVesuAdapter();
34394
34623
  const extendedAdapter = await this.getExtendedAdapter();
34395
- let calls = [];
34396
34624
  if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
34397
34625
  logger.error(
34398
34626
  `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
34399
34627
  );
34400
- return calls;
34628
+ return [];
34629
+ }
34630
+ const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
34631
+ if (!extendedHoldings) {
34632
+ logger.error(`error getting extended holdings: ${extendedHoldings}`);
34633
+ return [];
34401
34634
  }
34402
- if (extendedAmount.lessThan(0)) {
34635
+ const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
34636
+ const usdcAmountOnExtendedAvailableForWithdrawal = parseFloat(
34637
+ extendedHoldings.availableForWithdrawal
34638
+ );
34639
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculating movements - Extended current: ${usdcAmountOnExtendedAvailableForWithdrawal}, Wallet: ${usdcAmountInWallet.toNumber()}, Target Extended: ${extendedAmount.toNumber()}, Target Vesu: ${vesuAmount.toNumber()}`);
34640
+ let totalExtendedWithdrawal = new Web3Number(0, USDC_TOKEN_DECIMALS);
34641
+ let totalExtendedDeposit = new Web3Number(0, USDC_TOKEN_DECIMALS);
34642
+ if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
34643
+ totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmount.abs());
34644
+ }
34645
+ const extendedTargetAmount = extendedAmount.abs();
34646
+ let projectedExtendedBalance = usdcAmountOnExtendedAvailableForWithdrawal;
34647
+ if (extendedAmount.isNegative()) {
34648
+ projectedExtendedBalance = projectedExtendedBalance - extendedAmount.abs().toNumber();
34649
+ }
34650
+ const extendedAmountDifference = extendedTargetAmount.minus(projectedExtendedBalance);
34651
+ const extendedAmountDifferenceAbs = extendedAmountDifference.abs();
34652
+ if (extendedAmountDifference.lessThan(0)) {
34653
+ totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmountDifferenceAbs);
34654
+ } else if (extendedAmountDifference.greaterThan(0)) {
34655
+ totalExtendedDeposit = totalExtendedDeposit.plus(extendedAmountDifference);
34656
+ }
34657
+ const vesuTargetAmount = vesuAmount.abs();
34658
+ const projectedWalletBalance = usdcAmountInWallet.plus(totalExtendedWithdrawal).minus(totalExtendedDeposit);
34659
+ let vesuAmountDifference = vesuTargetAmount.minus(projectedWalletBalance);
34660
+ const vesuAmountDifferenceAbs = vesuAmountDifference.abs();
34661
+ 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()}`);
34662
+ let calls = [];
34663
+ if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
34403
34664
  try {
34404
34665
  const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
34405
34666
  {
@@ -34419,7 +34680,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34419
34680
  logger.error(`Failed moving assets to vault: ${err}`);
34420
34681
  }
34421
34682
  }
34422
- if (vesuAmount.lessThan(0)) {
34683
+ if (vesuAmount.isNegative() && vesuAmount.abs().greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
34423
34684
  try {
34424
34685
  const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
34425
34686
  {
@@ -34438,48 +34699,76 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34438
34699
  logger.error(`Failed moving assets to vault: ${err}`);
34439
34700
  }
34440
34701
  }
34441
- const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
34442
- if (!extendedHoldings) {
34443
- logger.error(`error getting extended holdings: ${extendedHoldings}`);
34444
- return calls;
34445
- }
34446
- const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
34447
- const usdcAmountOnExtended = parseFloat(
34448
- extendedHoldings.availableForWithdrawal
34449
- );
34450
- if (extendedAmount.minus(usdcAmountOnExtended).greaterThan(0)) {
34451
- try {
34452
- const { calls: extendedCalls } = await this.moveAssets(
34453
- {
34454
- to: Protocols.EXTENDED.name,
34455
- from: Protocols.VAULT.name,
34456
- amount: extendedAmount.minus(usdcAmountOnExtended)
34457
- },
34458
- extendedAdapter,
34459
- vesuAdapter
34460
- );
34461
- calls.push(...extendedCalls);
34462
- } catch (err) {
34463
- logger.error(`Failed moving assets to extended: ${err}`);
34702
+ if (extendedAmountDifferenceAbs.greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
34703
+ if (extendedAmountDifference.greaterThan(0)) {
34704
+ try {
34705
+ const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
34706
+ {
34707
+ to: Protocols.EXTENDED.name,
34708
+ from: Protocols.VAULT.name,
34709
+ amount: extendedAmountDifference
34710
+ },
34711
+ extendedAdapter,
34712
+ vesuAdapter
34713
+ );
34714
+ if (extendedStatus) {
34715
+ calls.push(...extendedCalls);
34716
+ } else {
34717
+ logger.error(`Failed to move assets to extended - operation returned false status`);
34718
+ return [];
34719
+ }
34720
+ } catch (err) {
34721
+ logger.error(`Failed moving assets to extended: ${err}`);
34722
+ return [];
34723
+ }
34724
+ } else if (extendedAmountDifference.lessThan(0)) {
34725
+ try {
34726
+ const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
34727
+ {
34728
+ to: Protocols.VAULT.name,
34729
+ from: Protocols.EXTENDED.name,
34730
+ amount: extendedAmountDifferenceAbs
34731
+ },
34732
+ extendedAdapter,
34733
+ vesuAdapter
34734
+ );
34735
+ if (extendedStatus) {
34736
+ calls.push(...extendedCalls);
34737
+ } else {
34738
+ logger.error(`Failed to withdraw from extended - operation returned false status`);
34739
+ return [];
34740
+ }
34741
+ } catch (err) {
34742
+ logger.error(`Failed moving assets from extended to vault: ${err}`);
34743
+ return [];
34744
+ }
34464
34745
  }
34465
34746
  }
34466
- if (vesuAmount.minus(usdcAmountInWallet).greaterThan(0)) {
34467
- try {
34468
- const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
34469
- {
34470
- to: Protocols.VAULT.name,
34471
- from: Protocols.EXTENDED.name,
34472
- amount: vesuAmount.minus(usdcAmountInWallet)
34473
- },
34474
- extendedAdapter,
34475
- vesuAdapter
34747
+ if (vesuAmountDifferenceAbs.greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
34748
+ if (vesuAmountDifference.lessThanOrEqualTo(0)) {
34749
+ logger.warn(
34750
+ `Vesu amount difference is negative or zero: ${vesuAmountDifference.toNumber()}. Skipping operation.`
34476
34751
  );
34477
- if (!vesuStatus) {
34752
+ } else {
34753
+ try {
34754
+ const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
34755
+ {
34756
+ to: Protocols.VAULT.name,
34757
+ from: Protocols.EXTENDED.name,
34758
+ amount: vesuAmountDifference
34759
+ },
34760
+ extendedAdapter,
34761
+ vesuAdapter
34762
+ );
34763
+ if (!vesuStatus) {
34764
+ logger.error(`Failed to move assets to vesu - operation returned false status`);
34765
+ return [];
34766
+ }
34767
+ calls.push(...vesuCalls);
34768
+ } catch (err) {
34769
+ logger.error(`Failed moving assets to vault: ${err}`);
34478
34770
  return [];
34479
34771
  }
34480
- calls.push(...vesuCalls);
34481
- } catch (err) {
34482
- logger.error(`Failed moving assets to vault: ${err}`);
34483
34772
  }
34484
34773
  }
34485
34774
  return calls;
@@ -34490,6 +34779,38 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34490
34779
  }
34491
34780
  async moveAssets(params, extendedAdapter, vesuAdapter) {
34492
34781
  try {
34782
+ if (params.amount.lessThanOrEqualTo(0)) {
34783
+ logger.error(
34784
+ `Invalid amount for moveAssets: ${params.amount.toNumber()}. Amount must be positive.`
34785
+ );
34786
+ return {
34787
+ calls: [],
34788
+ status: false
34789
+ };
34790
+ }
34791
+ const amountAbs = params.amount.abs();
34792
+ if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
34793
+ if (amountAbs.lessThanOrEqualTo(extendedAdapter.minimumExtendedMovementAmount)) {
34794
+ logger.warn(
34795
+ `Amount ${amountAbs.toNumber()} is below minimum Extended movement amount ${extendedAdapter.minimumExtendedMovementAmount}. Skipping operation.`
34796
+ );
34797
+ return {
34798
+ calls: [],
34799
+ status: false
34800
+ };
34801
+ }
34802
+ }
34803
+ if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
34804
+ if (amountAbs.lessThanOrEqualTo(vesuAdapter.minimumVesuMovementAmount)) {
34805
+ logger.warn(
34806
+ `Amount ${amountAbs.toNumber()} is below minimum Vesu movement amount ${vesuAdapter.minimumVesuMovementAmount}. Skipping operation.`
34807
+ );
34808
+ return {
34809
+ calls: [],
34810
+ status: false
34811
+ };
34812
+ }
34813
+ }
34493
34814
  const avnuAdapter = await this.getAvnuAdapter();
34494
34815
  if (!avnuAdapter) {
34495
34816
  logger.error(`avnu adapter not found: ${avnuAdapter}`);
@@ -34550,12 +34871,13 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34550
34871
  );
34551
34872
  if (!openLongPosition) {
34552
34873
  logger.error(`error opening long position: ${openLongPosition}`);
34553
- return {
34554
- calls: [],
34555
- status: false
34556
- };
34557
34874
  }
34558
34875
  await new Promise((resolve) => setTimeout(resolve, 5e3));
34876
+ const updatedHoldings = await extendedAdapter.getExtendedDepositAmount();
34877
+ if (!updatedHoldings || new Web3Number(updatedHoldings.availableForWithdrawal, USDC_TOKEN_DECIMALS).lessThan(params.amount.abs())) {
34878
+ logger.error(`Insufficient balance after opening position. Available: ${updatedHoldings?.availableForWithdrawal}, Needed: ${params.amount.abs()}`);
34879
+ return { calls: [], status: false };
34880
+ }
34559
34881
  }
34560
34882
  const withdrawalFromExtended = await extendedAdapter.withdrawFromExtended(params.amount);
34561
34883
  if (withdrawalFromExtended) {
@@ -34928,7 +35250,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34928
35250
  };
34929
35251
  }
34930
35252
  };
34931
- function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendUrl, extendedApiKey, vaultIdExtended) {
35253
+ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus) {
34932
35254
  vaultSettings.leafAdapters = [];
34933
35255
  const wbtcToken = Global.getDefaultTokens().find(
34934
35256
  (token) => token.symbol === lstSymbol
@@ -34968,7 +35290,10 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
34968
35290
  extendedBaseUrl: "https://api.starknet.extended.exchange",
34969
35291
  extendedMarketName: "BTC-USD",
34970
35292
  extendedPrecision: 5,
34971
- avnuAdapter
35293
+ avnuAdapter,
35294
+ retryDelayForOrderStatus: minimumExtendedRetriesDelayForOrderStatus ?? 3e3,
35295
+ minimumExtendedMovementAmount: minimumExtendedMovementAmount ?? 5
35296
+ //5 usdcs
34972
35297
  });
34973
35298
  const vesuMultiplyAdapter = new VesuMultiplyAdapter({
34974
35299
  poolId: pool1,
@@ -34981,7 +35306,9 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
34981
35306
  supportedPositions: [
34982
35307
  { asset: wbtcToken, isDebt: false },
34983
35308
  { asset: usdcToken, isDebt: true }
34984
- ]
35309
+ ],
35310
+ minimumVesuMovementAmount: minimumVesuMovementAmount ?? 5
35311
+ //5 usdc
34985
35312
  });
34986
35313
  const unusedBalanceAdapter = new UnusedBalanceAdapter({
34987
35314
  ...baseAdapterConfig
@@ -35096,12 +35423,12 @@ var re7UsdcPrimeDevansh = {
35096
35423
  borrowable_assets: [Global.getDefaultTokens().find((token) => token.symbol === "WBTC")],
35097
35424
  minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP
35098
35425
  };
35099
- var VesuExtendedTestStrategies = (extendedBackendUrl, extendedApiKey, vaultIdExtended) => {
35426
+ var VesuExtendedTestStrategies = (extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus) => {
35100
35427
  return [
35101
- getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false, extendedBackendUrl, extendedApiKey, vaultIdExtended)
35428
+ getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus)
35102
35429
  ];
35103
35430
  };
35104
- function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendUrl, extendedApiKey, vaultIdExtended) {
35431
+ function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus) {
35105
35432
  return {
35106
35433
  name: `Extended Test ${underlyingSymbol}`,
35107
35434
  description: getDescription2(lstSymbol, underlyingSymbol),
@@ -35109,7 +35436,7 @@ function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses,
35109
35436
  launchBlock: 0,
35110
35437
  type: "Other",
35111
35438
  depositTokens: [Global.getDefaultTokens().find((token) => token.symbol === underlyingSymbol)],
35112
- additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendUrl, extendedApiKey, vaultIdExtended),
35439
+ additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus),
35113
35440
  risk: {
35114
35441
  riskFactor: _riskFactor3,
35115
35442
  netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),