@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.
@@ -28351,7 +28351,7 @@ var STRK_API_RPC = process.env.STRK_API_RPC ?? "https://mainnet.starknet.a5a.ch"
28351
28351
  var MAX_RETRIES = Number(process.env.MAX_RETRIES ?? 3);
28352
28352
  var MAX_DELAY = Number(process.env.MAX_DELAY ?? 100);
28353
28353
  var EXTEND_MARKET_NAME = "BTC-USD";
28354
- var LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ?? 10);
28354
+ var LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ?? 0.05);
28355
28355
  var REBALANCER_INTERVAL = Number(process.env.REBALANCER_INTERVAL ?? 18e4);
28356
28356
  var WITHDRAWAL_INTERVAL = Number(process.env.WITHDRAWAL_INTERVAL ?? 18e6);
28357
28357
  var INVESTING_INTERVAL = Number(process.env.INVESTING_INTERVAL ?? 18e4);
@@ -28608,6 +28608,7 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
28608
28608
  vaultAllocator: config.vaultAllocator,
28609
28609
  id: ""
28610
28610
  });
28611
+ this.minimumVesuMovementAmount = config.minimumVesuMovementAmount ?? 5;
28611
28612
  this.tokenMarketData = new TokenMarketData(
28612
28613
  this.config.pricer,
28613
28614
  this.config.networkConfig
@@ -29618,7 +29619,9 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29618
29619
  timeout: this.config.extendedTimeout,
29619
29620
  retries: this.config.extendedRetries
29620
29621
  });
29622
+ this.minimumExtendedMovementAmount = this.config.minimumExtendedMovementAmount ?? 5;
29621
29623
  this.client = client;
29624
+ this.retryDelayForOrderStatus = this.config.retryDelayForOrderStatus ?? 3e3;
29622
29625
  }
29623
29626
  //abstract means the method has no implementation in this class; instead, child classes must implement it.
29624
29627
  async getAPY(supportedPosition) {
@@ -29916,8 +29919,47 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29916
29919
  async withdrawFromExtended(amount) {
29917
29920
  try {
29918
29921
  if (!this.client) {
29919
- throw new Error("Client not initialized");
29922
+ logger.error("Client not initialized");
29923
+ return false;
29924
+ }
29925
+ if (amount.lessThanOrEqualTo(0)) {
29926
+ logger.error(
29927
+ `Invalid withdrawal amount: ${amount.toNumber()}. Amount must be positive.`
29928
+ );
29929
+ return false;
29930
+ }
29931
+ if (amount.lessThanOrEqualTo(this.minimumExtendedMovementAmount)) {
29932
+ logger.warn(
29933
+ `Withdrawal amount ${amount.toNumber()} is below minimum Extended movement amount ${this.minimumExtendedMovementAmount}. Skipping withdrawal.`
29934
+ );
29935
+ return false;
29936
+ }
29937
+ const holdings = await this.getExtendedDepositAmount();
29938
+ if (!holdings) {
29939
+ logger.error(
29940
+ "Cannot get holdings - unable to validate withdrawal amount"
29941
+ );
29942
+ return false;
29943
+ }
29944
+ const availableForWithdrawal = parseFloat(
29945
+ holdings.availableForWithdrawal
29946
+ );
29947
+ if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
29948
+ logger.error(
29949
+ `Invalid availableForWithdrawal: ${holdings.availableForWithdrawal}. Expected a finite, non-negative number.`
29950
+ );
29951
+ return false;
29952
+ }
29953
+ const withdrawalAmount = amount.toNumber();
29954
+ if (withdrawalAmount > availableForWithdrawal) {
29955
+ logger.error(
29956
+ `Withdrawal amount ${withdrawalAmount} exceeds available balance ${availableForWithdrawal}`
29957
+ );
29958
+ return false;
29920
29959
  }
29960
+ logger.info(
29961
+ `Withdrawing ${withdrawalAmount} from Extended. Available balance: ${availableForWithdrawal}`
29962
+ );
29921
29963
  const withdrawalRequest = await this.client.withdrawUSDC(
29922
29964
  amount.toFixed(2)
29923
29965
  );
@@ -29928,6 +29970,9 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29928
29970
  );
29929
29971
  return withdrawalStatus;
29930
29972
  }
29973
+ logger.error(
29974
+ `Withdrawal request failed with status: ${withdrawalRequest.status}`
29975
+ );
29931
29976
  return false;
29932
29977
  } catch (error) {
29933
29978
  logger.error(`Error creating Withdraw Call: ${error}`);
@@ -29938,21 +29983,44 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29938
29983
  return Promise.resolve(1);
29939
29984
  }
29940
29985
  async getExtendedDepositAmount() {
29941
- if (this.client === null) {
29942
- logger.error("error initializing client");
29943
- return void 0;
29944
- }
29945
- const result = await this.client.getHoldings();
29946
- if (!result) {
29947
- logger.error(`error getting holdings: ${result}`);
29948
- return void 0;
29949
- }
29950
- const holdings = result.data;
29951
- if (!holdings) {
29952
- logger.error(`error getting holdings: ${holdings}`);
29986
+ try {
29987
+ if (this.client === null) {
29988
+ logger.error("error initializing client - client is null");
29989
+ return void 0;
29990
+ }
29991
+ const result = await this.client.getHoldings();
29992
+ if (!result) {
29993
+ logger.error("error getting holdings - API returned null/undefined");
29994
+ return void 0;
29995
+ }
29996
+ if (result.status && result.status !== "OK") {
29997
+ logger.error(
29998
+ `error getting holdings - API returned status: ${result.status}`
29999
+ );
30000
+ return void 0;
30001
+ }
30002
+ const holdings = result.data;
30003
+ if (!holdings) {
30004
+ logger.warn(
30005
+ "holdings data is null/undefined - treating as zero balance"
30006
+ );
30007
+ return {
30008
+ collateral_name: "",
30009
+ balance: "0",
30010
+ equity: "0",
30011
+ availableForTrade: "0",
30012
+ availableForWithdrawal: "0",
30013
+ unrealisedPnl: "0",
30014
+ initialMargin: "0",
30015
+ marginRatio: "0",
30016
+ updatedTime: Date.now()
30017
+ };
30018
+ }
30019
+ return holdings;
30020
+ } catch (error) {
30021
+ logger.error(`error getting holdings - exception: ${error}`);
29953
30022
  return void 0;
29954
30023
  }
29955
- return holdings;
29956
30024
  }
29957
30025
  async setLeverage(leverage, marketName) {
29958
30026
  if (this.client === null) {
@@ -29994,38 +30062,24 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
29994
30062
  return result.data;
29995
30063
  }
29996
30064
  async getOrderStatus(orderId, marketName) {
29997
- if (this.client === null) {
29998
- logger.error("error initializing client");
29999
- return null;
30000
- }
30001
- let orderhistory = await this.getOrderHistory(marketName);
30002
- if (!orderhistory || orderhistory.length === 0) {
30003
- logger.error(`error getting order history: ${orderId}`);
30004
- } else {
30005
- const order = orderhistory.slice(0, 5).find((order2) => order2.id.toString() === orderId);
30006
- if (order) {
30007
- return order;
30065
+ try {
30066
+ if (this.client === null) {
30067
+ logger.error("error initializing client");
30068
+ return null;
30008
30069
  }
30009
- }
30010
- for (let attempt = 1; attempt <= 3; attempt++) {
30011
- await new Promise((resolve) => setTimeout(resolve, 3e3));
30012
- orderhistory = await this.getOrderHistory(marketName);
30070
+ const orderhistory = await this.getOrderHistory(marketName);
30013
30071
  if (!orderhistory || orderhistory.length === 0) {
30014
- logger.error(
30015
- `error getting order history on retry ${attempt}: ${orderId}`
30016
- );
30017
- continue;
30072
+ return null;
30018
30073
  }
30019
- const order = orderhistory.slice(0, 5).find((order2) => order2.id.toString() === orderId);
30074
+ const order = orderhistory.slice(0, 20).find((order2) => order2.id.toString() === orderId);
30020
30075
  if (order) {
30021
30076
  return order;
30022
30077
  }
30023
- logger.error(
30024
- `order not found in top 5 entries on retry ${attempt}: ${orderId}`
30025
- );
30078
+ return null;
30079
+ } catch (error) {
30080
+ logger.error(`error getting order status: ${error}`);
30081
+ return null;
30026
30082
  }
30027
- logger.error(`error getting order after all retries: ${orderId}`);
30028
- return null;
30029
30083
  }
30030
30084
  async fetchOrderBookBTCUSDC() {
30031
30085
  try {
@@ -30076,14 +30130,40 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
30076
30130
  logger.error("error depositing or setting leverage");
30077
30131
  return null;
30078
30132
  }
30079
- const positions = await this.getAllOpenPositions();
30080
- if (positions === null) {
30133
+ const { ask, bid } = await this.fetchOrderBookBTCUSDC();
30134
+ if (!ask || !bid || ask.lessThanOrEqualTo(0) || bid.lessThanOrEqualTo(0)) {
30135
+ logger.error(
30136
+ `Invalid orderbook prices: ask=${ask?.toNumber()}, bid=${bid?.toNumber()}`
30137
+ );
30081
30138
  return null;
30082
30139
  }
30083
- const { ask, bid } = await this.fetchOrderBookBTCUSDC();
30084
30140
  const spread = ask.minus(bid);
30085
- let price = ask.plus(bid).div(2);
30086
- side === "SELL" /* SELL */ ? price = price.minus(spread.times(0.2 * attempt)) : price = price.plus(spread.times(0.2 * attempt));
30141
+ const midPrice = ask.plus(bid).div(2);
30142
+ const MAX_PRICE_DEVIATION_MULTIPLIER = 0.5;
30143
+ const priceAdjustmentMultiplier = Math.min(
30144
+ 0.2 * attempt,
30145
+ MAX_PRICE_DEVIATION_MULTIPLIER
30146
+ );
30147
+ const priceAdjustment = spread.times(priceAdjustmentMultiplier);
30148
+ let price = midPrice;
30149
+ if (side === "SELL" /* SELL */) {
30150
+ price = midPrice.minus(priceAdjustment);
30151
+ } else {
30152
+ price = midPrice.plus(priceAdjustment);
30153
+ }
30154
+ const maxDeviation = midPrice.times(0.5);
30155
+ if (price.minus(midPrice).abs().greaterThan(maxDeviation)) {
30156
+ logger.error(
30157
+ `Price deviation too large on attempt ${attempt}: price=${price.toNumber()}, midPrice=${midPrice.toNumber()}, deviation=${price.minus(midPrice).abs().toNumber()}`
30158
+ );
30159
+ if (attempt >= maxAttempts) {
30160
+ return null;
30161
+ }
30162
+ price = side === "SELL" /* SELL */ ? midPrice.minus(maxDeviation) : midPrice.plus(maxDeviation);
30163
+ }
30164
+ logger.info(
30165
+ `createOrder attempt ${attempt}/${maxAttempts}: side=${side}, midPrice=${midPrice.toNumber()}, adjustedPrice=${price.toNumber()}, adjustment=${priceAdjustmentMultiplier * 100}%`
30166
+ );
30087
30167
  const amount_in_token = (btcAmount * parseInt(leverage)).toFixed(
30088
30168
  this.config.extendedPrecision
30089
30169
  );
@@ -30094,17 +30174,57 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
30094
30174
  price.toFixed(0),
30095
30175
  side
30096
30176
  );
30097
- if (!result) {
30177
+ if (!result || !result.position_id) {
30178
+ logger.error("Failed to create order - no position_id returned");
30098
30179
  return null;
30099
30180
  }
30100
- await new Promise((resolve) => setTimeout(resolve, 5e3));
30101
- const openOrder = await this.getOrderStatus(
30102
- result.position_id,
30181
+ const positionId = result.position_id;
30182
+ logger.info(
30183
+ `Order created with position_id: ${positionId}. Waiting for API to update...`
30184
+ );
30185
+ let openOrder = await this.getOrderStatus(
30186
+ positionId,
30103
30187
  this.config.extendedMarketName
30104
30188
  );
30105
- if (!openOrder || openOrder.status !== "FILLED" /* FILLED */) {
30189
+ const maxStatusRetries = 3;
30190
+ const statusRetryDelay = 5e3;
30191
+ if (!openOrder) {
30192
+ logger.warn(
30193
+ `Order ${positionId} not found in API yet. Retrying status fetch (max ${maxStatusRetries} times)...`
30194
+ );
30195
+ for (let statusRetry = 1; statusRetry <= maxStatusRetries; statusRetry++) {
30196
+ await new Promise((resolve) => setTimeout(resolve, statusRetryDelay));
30197
+ openOrder = await this.getOrderStatus(
30198
+ positionId,
30199
+ this.config.extendedMarketName
30200
+ );
30201
+ if (openOrder) {
30202
+ logger.info(
30203
+ `Order ${positionId} found after ${statusRetry} status retry(ies)`
30204
+ );
30205
+ break;
30206
+ }
30207
+ logger.warn(
30208
+ `Order ${positionId} still not found after ${statusRetry}/${maxStatusRetries} status retries`
30209
+ );
30210
+ }
30211
+ }
30212
+ if (openOrder && openOrder.status === "FILLED" /* FILLED */) {
30213
+ logger.info(
30214
+ `Order ${positionId} successfully filled with quantity ${openOrder.qty}`
30215
+ );
30216
+ return {
30217
+ position_id: positionId,
30218
+ btc_exposure: openOrder.qty
30219
+ };
30220
+ } else if (openOrder && openOrder.status !== "FILLED" /* FILLED */) {
30221
+ logger.warn(
30222
+ `Order ${positionId} found but status is ${openOrder.status}, not FILLED. Retrying order creation...`
30223
+ );
30106
30224
  if (attempt >= maxAttempts) {
30107
- logger.error("Max retries reached \u2014 could not verify open position");
30225
+ logger.error(
30226
+ `Max retries reached \u2014 order ${positionId} status is ${openOrder.status}, not FILLED`
30227
+ );
30108
30228
  return null;
30109
30229
  } else {
30110
30230
  const backoff = 2e3 * attempt;
@@ -30118,9 +30238,12 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
30118
30238
  );
30119
30239
  }
30120
30240
  } else {
30241
+ logger.warn(
30242
+ `Order ${positionId} not found in API after ${maxStatusRetries} status retries (API update delayed ~30s). We got position_id from creation, so order exists. Returning position_id - status will be checked in next loop iteration.`
30243
+ );
30121
30244
  return {
30122
- position_id: result.position_id,
30123
- btc_exposure: openOrder.qty
30245
+ position_id: positionId,
30246
+ btc_exposure: amount_in_token
30124
30247
  };
30125
30248
  }
30126
30249
  } catch (err) {
@@ -33456,7 +33579,8 @@ function getLooperSettings(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
33456
33579
  minHealthFactor: vaultSettings.minHealthFactor,
33457
33580
  quoteAmountToFetchPrice: vaultSettings.quoteAmountToFetchPrice,
33458
33581
  ...baseAdapterConfig,
33459
- supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }]
33582
+ supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }],
33583
+ minimumVesuMovementAmount: 0
33460
33584
  }));
33461
33585
  const unusedBalanceAdapter = new UnusedBalanceAdapter({
33462
33586
  ...baseAdapterConfig
@@ -33799,7 +33923,6 @@ var AvnuAdapter = class _AvnuAdapter extends BaseAdapter {
33799
33923
  toToken.decimals,
33800
33924
  true
33801
33925
  );
33802
- console.log(`${_AvnuAdapter.name}::getDepositCall quote: ${quote?.sellAmountInUsd}`);
33803
33926
  if (!quote) {
33804
33927
  logger.error("error getting quote from avnu");
33805
33928
  return [];
@@ -34140,11 +34263,41 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34140
34263
  }
34141
34264
  async shouldInvest() {
34142
34265
  try {
34266
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest starting`);
34143
34267
  const vesuAdapter = await this.getVesuAdapter();
34144
34268
  const extendedAdapter = await this.getExtendedAdapter();
34145
- if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
34269
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest adapters fetched: vesuAdapter=${!!vesuAdapter}, extendedAdapter=${!!extendedAdapter}, extendedAdapter.client=${!!extendedAdapter?.client}`);
34270
+ if (!vesuAdapter) {
34146
34271
  logger.error(
34147
- `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
34272
+ `Vesu adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
34273
+ );
34274
+ return {
34275
+ shouldInvest: false,
34276
+ vesuAmount: new Web3Number(0, 0),
34277
+ extendedAmount: new Web3Number(0, 0),
34278
+ extendedLeverage: 0,
34279
+ collateralPrice: 0,
34280
+ debtPrice: 0,
34281
+ vesuLeverage: 0
34282
+ };
34283
+ }
34284
+ if (!extendedAdapter) {
34285
+ logger.error(
34286
+ `Extended adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
34287
+ );
34288
+ return {
34289
+ shouldInvest: false,
34290
+ vesuAmount: new Web3Number(0, 0),
34291
+ extendedAmount: new Web3Number(0, 0),
34292
+ extendedLeverage: 0,
34293
+ collateralPrice: 0,
34294
+ debtPrice: 0,
34295
+ vesuLeverage: 0
34296
+ };
34297
+ }
34298
+ if (!extendedAdapter.client) {
34299
+ logger.error(
34300
+ `Extended adapter client not initialized. This may be a temporary initialization failure - check network connectivity and API availability.`
34148
34301
  );
34149
34302
  return {
34150
34303
  shouldInvest: false,
@@ -34156,10 +34309,58 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34156
34309
  vesuLeverage: 0
34157
34310
  };
34158
34311
  }
34312
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest calling getUnusedBalance`);
34159
34313
  const balance = await this.getUnusedBalance();
34314
+ if (!Number.isFinite(balance.usdValue) || balance.usdValue < 0) {
34315
+ logger.error(
34316
+ `Invalid balance.usdValue: ${balance.usdValue}. Expected a finite, non-negative number.`
34317
+ );
34318
+ return {
34319
+ shouldInvest: false,
34320
+ vesuAmount: new Web3Number(0, 0),
34321
+ extendedAmount: new Web3Number(0, 0),
34322
+ extendedLeverage: 0,
34323
+ collateralPrice: 0,
34324
+ debtPrice: 0,
34325
+ vesuLeverage: 0
34326
+ };
34327
+ }
34328
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest balance: ${balance.usdValue}`);
34160
34329
  const usdcBalanceOnExtended = await extendedAdapter.getExtendedDepositAmount();
34161
- const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).minus(LIMIT_BALANCE);
34162
- logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvest.toNumber()}`);
34330
+ if (usdcBalanceOnExtended) {
34331
+ const availableForWithdrawal = parseFloat(usdcBalanceOnExtended.availableForWithdrawal);
34332
+ if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
34333
+ logger.error(
34334
+ `Invalid usdcBalanceOnExtended.availableForWithdrawal: ${usdcBalanceOnExtended.availableForWithdrawal}. Expected a finite, non-negative number.`
34335
+ );
34336
+ return {
34337
+ shouldInvest: false,
34338
+ vesuAmount: new Web3Number(0, 0),
34339
+ extendedAmount: new Web3Number(0, 0),
34340
+ extendedLeverage: 0,
34341
+ collateralPrice: 0,
34342
+ debtPrice: 0,
34343
+ vesuLeverage: 0
34344
+ };
34345
+ }
34346
+ }
34347
+ const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).multipliedBy(1 - LIMIT_BALANCE);
34348
+ const amountToInvestNumber = amountToInvest.toNumber();
34349
+ if (!Number.isFinite(amountToInvestNumber)) {
34350
+ logger.error(
34351
+ `Invalid amountToInvest calculation result: ${amountToInvestNumber}. Calculation may have produced NaN or Infinity.`
34352
+ );
34353
+ return {
34354
+ shouldInvest: false,
34355
+ vesuAmount: new Web3Number(0, 0),
34356
+ extendedAmount: new Web3Number(0, 0),
34357
+ extendedLeverage: 0,
34358
+ collateralPrice: 0,
34359
+ debtPrice: 0,
34360
+ vesuLeverage: 0
34361
+ };
34362
+ }
34363
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvestNumber}`);
34163
34364
  if (amountToInvest.lessThan(0)) {
34164
34365
  return {
34165
34366
  shouldInvest: false,
@@ -34189,6 +34390,34 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34189
34390
  collateralPrice,
34190
34391
  debtPrice
34191
34392
  } = await this.getAssetPrices();
34393
+ if (!Number.isFinite(collateralPrice.price) || collateralPrice.price <= 0) {
34394
+ logger.error(
34395
+ `Invalid collateralPrice: ${collateralPrice.price}. Expected a finite, positive number.`
34396
+ );
34397
+ return {
34398
+ shouldInvest: false,
34399
+ vesuAmount: new Web3Number(0, 0),
34400
+ extendedAmount: new Web3Number(0, 0),
34401
+ extendedLeverage: 0,
34402
+ collateralPrice: 0,
34403
+ debtPrice: 0,
34404
+ vesuLeverage: 0
34405
+ };
34406
+ }
34407
+ if (!Number.isFinite(debtPrice.price) || debtPrice.price <= 0) {
34408
+ logger.error(
34409
+ `Invalid debtPrice: ${debtPrice.price}. Expected a finite, positive number.`
34410
+ );
34411
+ return {
34412
+ shouldInvest: false,
34413
+ vesuAmount: new Web3Number(0, 0),
34414
+ extendedAmount: new Web3Number(0, 0),
34415
+ extendedLeverage: 0,
34416
+ collateralPrice: 0,
34417
+ debtPrice: 0,
34418
+ vesuLeverage: 0
34419
+ };
34420
+ }
34192
34421
  const { vesu_amount, extended_amount, extended_leverage, vesu_leverage } = await calculateAmountDistribution(
34193
34422
  amountToInvest.toNumber(),
34194
34423
  extendedAdapter.client,
@@ -34239,14 +34468,46 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34239
34468
  try {
34240
34469
  const vesuAdapter = await this.getVesuAdapter();
34241
34470
  const extendedAdapter = await this.getExtendedAdapter();
34242
- let calls = [];
34243
34471
  if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
34244
34472
  logger.error(
34245
34473
  `vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
34246
34474
  );
34247
- return calls;
34475
+ return [];
34476
+ }
34477
+ const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
34478
+ if (!extendedHoldings) {
34479
+ logger.error(`error getting extended holdings: ${extendedHoldings}`);
34480
+ return [];
34248
34481
  }
34249
- if (extendedAmount.lessThan(0)) {
34482
+ const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
34483
+ const usdcAmountOnExtendedAvailableForWithdrawal = parseFloat(
34484
+ extendedHoldings.availableForWithdrawal
34485
+ );
34486
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculating movements - Extended current: ${usdcAmountOnExtendedAvailableForWithdrawal}, Wallet: ${usdcAmountInWallet.toNumber()}, Target Extended: ${extendedAmount.toNumber()}, Target Vesu: ${vesuAmount.toNumber()}`);
34487
+ let totalExtendedWithdrawal = new Web3Number(0, USDC_TOKEN_DECIMALS);
34488
+ let totalExtendedDeposit = new Web3Number(0, USDC_TOKEN_DECIMALS);
34489
+ if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
34490
+ totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmount.abs());
34491
+ }
34492
+ const extendedTargetAmount = extendedAmount.abs();
34493
+ let projectedExtendedBalance = usdcAmountOnExtendedAvailableForWithdrawal;
34494
+ if (extendedAmount.isNegative()) {
34495
+ projectedExtendedBalance = projectedExtendedBalance - extendedAmount.abs().toNumber();
34496
+ }
34497
+ const extendedAmountDifference = extendedTargetAmount.minus(projectedExtendedBalance);
34498
+ const extendedAmountDifferenceAbs = extendedAmountDifference.abs();
34499
+ if (extendedAmountDifference.lessThan(0)) {
34500
+ totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmountDifferenceAbs);
34501
+ } else if (extendedAmountDifference.greaterThan(0)) {
34502
+ totalExtendedDeposit = totalExtendedDeposit.plus(extendedAmountDifference);
34503
+ }
34504
+ const vesuTargetAmount = vesuAmount.abs();
34505
+ const projectedWalletBalance = usdcAmountInWallet.plus(totalExtendedWithdrawal).minus(totalExtendedDeposit);
34506
+ let vesuAmountDifference = vesuTargetAmount.minus(projectedWalletBalance);
34507
+ const vesuAmountDifferenceAbs = vesuAmountDifference.abs();
34508
+ logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculated movements - Extended withdrawal: ${totalExtendedWithdrawal.toNumber()}, Extended deposit: ${totalExtendedDeposit.toNumber()}, Extended diff: ${extendedAmountDifference.toNumber()}, Projected wallet: ${projectedWalletBalance.toNumber()}, Vesu diff: ${vesuAmountDifference.toNumber()}`);
34509
+ let calls = [];
34510
+ if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
34250
34511
  try {
34251
34512
  const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
34252
34513
  {
@@ -34266,7 +34527,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34266
34527
  logger.error(`Failed moving assets to vault: ${err}`);
34267
34528
  }
34268
34529
  }
34269
- if (vesuAmount.lessThan(0)) {
34530
+ if (vesuAmount.isNegative() && vesuAmount.abs().greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
34270
34531
  try {
34271
34532
  const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
34272
34533
  {
@@ -34285,48 +34546,76 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34285
34546
  logger.error(`Failed moving assets to vault: ${err}`);
34286
34547
  }
34287
34548
  }
34288
- const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
34289
- if (!extendedHoldings) {
34290
- logger.error(`error getting extended holdings: ${extendedHoldings}`);
34291
- return calls;
34292
- }
34293
- const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
34294
- const usdcAmountOnExtended = parseFloat(
34295
- extendedHoldings.availableForWithdrawal
34296
- );
34297
- if (extendedAmount.minus(usdcAmountOnExtended).greaterThan(0)) {
34298
- try {
34299
- const { calls: extendedCalls } = await this.moveAssets(
34300
- {
34301
- to: Protocols.EXTENDED.name,
34302
- from: Protocols.VAULT.name,
34303
- amount: extendedAmount.minus(usdcAmountOnExtended)
34304
- },
34305
- extendedAdapter,
34306
- vesuAdapter
34307
- );
34308
- calls.push(...extendedCalls);
34309
- } catch (err) {
34310
- logger.error(`Failed moving assets to extended: ${err}`);
34549
+ if (extendedAmountDifferenceAbs.greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
34550
+ if (extendedAmountDifference.greaterThan(0)) {
34551
+ try {
34552
+ const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
34553
+ {
34554
+ to: Protocols.EXTENDED.name,
34555
+ from: Protocols.VAULT.name,
34556
+ amount: extendedAmountDifference
34557
+ },
34558
+ extendedAdapter,
34559
+ vesuAdapter
34560
+ );
34561
+ if (extendedStatus) {
34562
+ calls.push(...extendedCalls);
34563
+ } else {
34564
+ logger.error(`Failed to move assets to extended - operation returned false status`);
34565
+ return [];
34566
+ }
34567
+ } catch (err) {
34568
+ logger.error(`Failed moving assets to extended: ${err}`);
34569
+ return [];
34570
+ }
34571
+ } else if (extendedAmountDifference.lessThan(0)) {
34572
+ try {
34573
+ const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
34574
+ {
34575
+ to: Protocols.VAULT.name,
34576
+ from: Protocols.EXTENDED.name,
34577
+ amount: extendedAmountDifferenceAbs
34578
+ },
34579
+ extendedAdapter,
34580
+ vesuAdapter
34581
+ );
34582
+ if (extendedStatus) {
34583
+ calls.push(...extendedCalls);
34584
+ } else {
34585
+ logger.error(`Failed to withdraw from extended - operation returned false status`);
34586
+ return [];
34587
+ }
34588
+ } catch (err) {
34589
+ logger.error(`Failed moving assets from extended to vault: ${err}`);
34590
+ return [];
34591
+ }
34311
34592
  }
34312
34593
  }
34313
- if (vesuAmount.minus(usdcAmountInWallet).greaterThan(0)) {
34314
- try {
34315
- const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
34316
- {
34317
- to: Protocols.VAULT.name,
34318
- from: Protocols.EXTENDED.name,
34319
- amount: vesuAmount.minus(usdcAmountInWallet)
34320
- },
34321
- extendedAdapter,
34322
- vesuAdapter
34594
+ if (vesuAmountDifferenceAbs.greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
34595
+ if (vesuAmountDifference.lessThanOrEqualTo(0)) {
34596
+ logger.warn(
34597
+ `Vesu amount difference is negative or zero: ${vesuAmountDifference.toNumber()}. Skipping operation.`
34323
34598
  );
34324
- if (!vesuStatus) {
34599
+ } else {
34600
+ try {
34601
+ const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
34602
+ {
34603
+ to: Protocols.VAULT.name,
34604
+ from: Protocols.EXTENDED.name,
34605
+ amount: vesuAmountDifference
34606
+ },
34607
+ extendedAdapter,
34608
+ vesuAdapter
34609
+ );
34610
+ if (!vesuStatus) {
34611
+ logger.error(`Failed to move assets to vesu - operation returned false status`);
34612
+ return [];
34613
+ }
34614
+ calls.push(...vesuCalls);
34615
+ } catch (err) {
34616
+ logger.error(`Failed moving assets to vault: ${err}`);
34325
34617
  return [];
34326
34618
  }
34327
- calls.push(...vesuCalls);
34328
- } catch (err) {
34329
- logger.error(`Failed moving assets to vault: ${err}`);
34330
34619
  }
34331
34620
  }
34332
34621
  return calls;
@@ -34337,6 +34626,38 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34337
34626
  }
34338
34627
  async moveAssets(params, extendedAdapter, vesuAdapter) {
34339
34628
  try {
34629
+ if (params.amount.lessThanOrEqualTo(0)) {
34630
+ logger.error(
34631
+ `Invalid amount for moveAssets: ${params.amount.toNumber()}. Amount must be positive.`
34632
+ );
34633
+ return {
34634
+ calls: [],
34635
+ status: false
34636
+ };
34637
+ }
34638
+ const amountAbs = params.amount.abs();
34639
+ if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
34640
+ if (amountAbs.lessThanOrEqualTo(extendedAdapter.minimumExtendedMovementAmount)) {
34641
+ logger.warn(
34642
+ `Amount ${amountAbs.toNumber()} is below minimum Extended movement amount ${extendedAdapter.minimumExtendedMovementAmount}. Skipping operation.`
34643
+ );
34644
+ return {
34645
+ calls: [],
34646
+ status: false
34647
+ };
34648
+ }
34649
+ }
34650
+ if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
34651
+ if (amountAbs.lessThanOrEqualTo(vesuAdapter.minimumVesuMovementAmount)) {
34652
+ logger.warn(
34653
+ `Amount ${amountAbs.toNumber()} is below minimum Vesu movement amount ${vesuAdapter.minimumVesuMovementAmount}. Skipping operation.`
34654
+ );
34655
+ return {
34656
+ calls: [],
34657
+ status: false
34658
+ };
34659
+ }
34660
+ }
34340
34661
  const avnuAdapter = await this.getAvnuAdapter();
34341
34662
  if (!avnuAdapter) {
34342
34663
  logger.error(`avnu adapter not found: ${avnuAdapter}`);
@@ -34397,12 +34718,13 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34397
34718
  );
34398
34719
  if (!openLongPosition) {
34399
34720
  logger.error(`error opening long position: ${openLongPosition}`);
34400
- return {
34401
- calls: [],
34402
- status: false
34403
- };
34404
34721
  }
34405
34722
  await new Promise((resolve) => setTimeout(resolve, 5e3));
34723
+ const updatedHoldings = await extendedAdapter.getExtendedDepositAmount();
34724
+ if (!updatedHoldings || new Web3Number(updatedHoldings.availableForWithdrawal, USDC_TOKEN_DECIMALS).lessThan(params.amount.abs())) {
34725
+ logger.error(`Insufficient balance after opening position. Available: ${updatedHoldings?.availableForWithdrawal}, Needed: ${params.amount.abs()}`);
34726
+ return { calls: [], status: false };
34727
+ }
34406
34728
  }
34407
34729
  const withdrawalFromExtended = await extendedAdapter.withdrawFromExtended(params.amount);
34408
34730
  if (withdrawalFromExtended) {
@@ -34775,7 +35097,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
34775
35097
  };
34776
35098
  }
34777
35099
  };
34778
- function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendUrl, extendedApiKey, vaultIdExtended) {
35100
+ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus) {
34779
35101
  vaultSettings.leafAdapters = [];
34780
35102
  const wbtcToken = Global.getDefaultTokens().find(
34781
35103
  (token) => token.symbol === lstSymbol
@@ -34815,7 +35137,10 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
34815
35137
  extendedBaseUrl: "https://api.starknet.extended.exchange",
34816
35138
  extendedMarketName: "BTC-USD",
34817
35139
  extendedPrecision: 5,
34818
- avnuAdapter
35140
+ avnuAdapter,
35141
+ retryDelayForOrderStatus: minimumExtendedRetriesDelayForOrderStatus ?? 3e3,
35142
+ minimumExtendedMovementAmount: minimumExtendedMovementAmount ?? 5
35143
+ //5 usdcs
34819
35144
  });
34820
35145
  const vesuMultiplyAdapter = new VesuMultiplyAdapter({
34821
35146
  poolId: pool1,
@@ -34828,7 +35153,9 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
34828
35153
  supportedPositions: [
34829
35154
  { asset: wbtcToken, isDebt: false },
34830
35155
  { asset: usdcToken, isDebt: true }
34831
- ]
35156
+ ],
35157
+ minimumVesuMovementAmount: minimumVesuMovementAmount ?? 5
35158
+ //5 usdc
34832
35159
  });
34833
35160
  const unusedBalanceAdapter = new UnusedBalanceAdapter({
34834
35161
  ...baseAdapterConfig
@@ -34943,12 +35270,12 @@ var re7UsdcPrimeDevansh = {
34943
35270
  borrowable_assets: [Global.getDefaultTokens().find((token) => token.symbol === "WBTC")],
34944
35271
  minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP
34945
35272
  };
34946
- var VesuExtendedTestStrategies = (extendedBackendUrl, extendedApiKey, vaultIdExtended) => {
35273
+ var VesuExtendedTestStrategies = (extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus) => {
34947
35274
  return [
34948
- getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false, extendedBackendUrl, extendedApiKey, vaultIdExtended)
35275
+ getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus)
34949
35276
  ];
34950
35277
  };
34951
- function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendUrl, extendedApiKey, vaultIdExtended) {
35278
+ function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus) {
34952
35279
  return {
34953
35280
  name: `Extended Test ${underlyingSymbol}`,
34954
35281
  description: getDescription2(lstSymbol, underlyingSymbol),
@@ -34956,7 +35283,7 @@ function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses,
34956
35283
  launchBlock: 0,
34957
35284
  type: "Other",
34958
35285
  depositTokens: [Global.getDefaultTokens().find((token) => token.symbol === underlyingSymbol)],
34959
- additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendUrl, extendedApiKey, vaultIdExtended),
35286
+ additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus),
34960
35287
  risk: {
34961
35288
  riskFactor: _riskFactor3,
34962
35289
  netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),