@strkfarm/sdk 2.0.0-dev.29 → 2.0.0-dev.30

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.
@@ -5800,7 +5800,7 @@ var EkuboQuoter = class _EkuboQuoter {
5800
5800
  async _callQuoterApi(fromToken, toToken, amount, retry = 0) {
5801
5801
  try {
5802
5802
  const url = this.ENDPOINT.replace("{{AMOUNT}}", amount.toWei()).replace("{{TOKEN_FROM_ADDRESS}}", fromToken).replace("{{TOKEN_TO_ADDRESS}}", toToken);
5803
- logger.verbose(`EkuboQuoter::_callQuoterApi url: ${url}`);
5803
+ logger.info(`EkuboQuoter::_callQuoterApi url: ${url}`);
5804
5804
  const quote = await axios6.get(url);
5805
5805
  return quote.data;
5806
5806
  } catch (error) {
@@ -5973,6 +5973,9 @@ var PricerLST = class extends Pricer {
5973
5973
  }
5974
5974
  };
5975
5975
 
5976
+ // src/modules/ExtendedWrapperSDk/wrapper.ts
5977
+ import BigNumber3 from "bignumber.js";
5978
+
5976
5979
  // src/modules/ExtendedWrapperSDk/types.ts
5977
5980
  var OrderSide = /* @__PURE__ */ ((OrderSide2) => {
5978
5981
  OrderSide2["BUY"] = "BUY";
@@ -6057,8 +6060,60 @@ var AssetOperationStatus = /* @__PURE__ */ ((AssetOperationStatus3) => {
6057
6060
  })(AssetOperationStatus || {});
6058
6061
 
6059
6062
  // src/modules/ExtendedWrapperSDk/wrapper.ts
6063
+ function asRecord(v) {
6064
+ return v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
6065
+ }
6066
+ function pickTradingConfig(row) {
6067
+ const tc = row.trading_config ?? row.tradingConfig;
6068
+ return asRecord(tc);
6069
+ }
6070
+ function readTcString(tc, snake, camel) {
6071
+ const v = tc[snake] ?? tc[camel];
6072
+ if (v === void 0 || v === null) return void 0;
6073
+ return String(v).trim();
6074
+ }
6075
+ function tradingRulesFromMarketRow(marketName, row) {
6076
+ const r = asRecord(row);
6077
+ if (!r) {
6078
+ throw new Error(`ExtendedWrapper: invalid market payload for ${marketName}`);
6079
+ }
6080
+ const tc = pickTradingConfig(r);
6081
+ if (!tc) {
6082
+ throw new Error(`ExtendedWrapper: missing tradingConfig for market ${marketName}`);
6083
+ }
6084
+ const minS = readTcString(tc, "min_order_size", "minOrderSize");
6085
+ const qtyStep = readTcString(tc, "min_order_size_change", "minOrderSizeChange");
6086
+ const pxStep = readTcString(tc, "min_price_change", "minPriceChange");
6087
+ if (!minS || !qtyStep || !pxStep) {
6088
+ throw new Error(`ExtendedWrapper: incomplete tradingConfig for market ${marketName}`);
6089
+ }
6090
+ const minOrderSize = new BigNumber3(minS);
6091
+ const qty = new BigNumber3(qtyStep);
6092
+ const px = new BigNumber3(pxStep);
6093
+ if (!minOrderSize.isFinite() || minOrderSize.lte(0)) {
6094
+ throw new Error(`ExtendedWrapper: invalid minOrderSize for ${marketName}`);
6095
+ }
6096
+ if (!qty.isFinite() || qty.lte(0)) {
6097
+ throw new Error(`ExtendedWrapper: invalid minOrderSizeChange for ${marketName}`);
6098
+ }
6099
+ if (!px.isFinite() || px.lte(0)) {
6100
+ throw new Error(`ExtendedWrapper: invalid minPriceChange for ${marketName}`);
6101
+ }
6102
+ return { minOrderSize, qtyStep: qty, priceStep: px };
6103
+ }
6104
+ function roundToStepBn(value, step) {
6105
+ if (step.lte(0)) return value;
6106
+ return value.div(step).round(0, BigNumber3.ROUND_HALF_UP).times(step);
6107
+ }
6108
+ function formatBnForApi(bn, step) {
6109
+ const dp = Math.max(step.decimalPlaces() ?? 0, bn.decimalPlaces() ?? 0, 0);
6110
+ return Number(bn.toFixed(Math.min(80, dp))).toString();
6111
+ }
6060
6112
  var ExtendedWrapper = class {
6061
6113
  constructor(config) {
6114
+ /** Per-market rules from GET /markets (tradingConfig); retained for process lifetime (no TTL). */
6115
+ this.marketTradingRulesCache = /* @__PURE__ */ new Map();
6116
+ this.marketTradingRulesInflight = /* @__PURE__ */ new Map();
6062
6117
  this.apiKey = config.apiKey;
6063
6118
  this.timeout = config.timeout || 3e4;
6064
6119
  this.retries = config.retries || 3;
@@ -6122,13 +6177,75 @@ var ExtendedWrapper = class {
6122
6177
  }
6123
6178
  throw lastError || new Error("Request failed after all retries");
6124
6179
  }
6180
+ async resolveTradingRules(marketName) {
6181
+ const cached = this.marketTradingRulesCache.get(marketName);
6182
+ if (cached) return cached;
6183
+ const existing = this.marketTradingRulesInflight.get(marketName);
6184
+ if (existing) return existing;
6185
+ const inflight = (async () => {
6186
+ const res = await this.getMarkets(marketName);
6187
+ if (res.status !== "OK") {
6188
+ throw new Error(
6189
+ `ExtendedWrapper: getMarkets failed for ${marketName}: ${res.message}`
6190
+ );
6191
+ }
6192
+ const rows = res.data;
6193
+ if (!Array.isArray(rows) || rows.length === 0) {
6194
+ throw new Error(
6195
+ `ExtendedWrapper: empty markets response for ${marketName}`
6196
+ );
6197
+ }
6198
+ const row = rows.find((m) => asRecord(m)?.name === marketName);
6199
+ if (!row) {
6200
+ throw new Error(
6201
+ `ExtendedWrapper: market ${marketName} not found in markets list`
6202
+ );
6203
+ }
6204
+ const rules = tradingRulesFromMarketRow(marketName, row);
6205
+ this.marketTradingRulesCache.set(marketName, rules);
6206
+ return rules;
6207
+ })();
6208
+ this.marketTradingRulesInflight.set(marketName, inflight);
6209
+ void inflight.finally(() => {
6210
+ if (this.marketTradingRulesInflight.get(marketName) === inflight) {
6211
+ this.marketTradingRulesInflight.delete(marketName);
6212
+ }
6213
+ });
6214
+ return inflight;
6215
+ }
6125
6216
  /**
6126
6217
  * Create a new order on Extended Exchange
6127
6218
  */
6128
6219
  async createOrder(request) {
6220
+ const rules = await this.resolveTradingRules(request.market_name);
6221
+ const amountBn = new BigNumber3(String(request.amount).trim());
6222
+ const priceBn = new BigNumber3(String(request.price).trim());
6223
+ if (!amountBn.isFinite() || amountBn.lte(0)) {
6224
+ throw new Error(`ExtendedWrapper: invalid order amount=${request.amount}`);
6225
+ }
6226
+ if (!priceBn.isFinite() || priceBn.lte(0)) {
6227
+ throw new Error(`ExtendedWrapper: invalid order price=${request.price}`);
6228
+ }
6229
+ if (amountBn.lt(rules.minOrderSize)) {
6230
+ throw new Error(
6231
+ `ExtendedWrapper: order amount ${request.amount} is below minOrderSize ${rules.minOrderSize.toFixed()} for ${request.market_name}`
6232
+ );
6233
+ }
6234
+ const adjAmount = roundToStepBn(amountBn, rules.qtyStep);
6235
+ const adjPrice = roundToStepBn(priceBn, rules.priceStep);
6236
+ if (adjAmount.lt(rules.minOrderSize)) {
6237
+ throw new Error(
6238
+ `ExtendedWrapper: amount after tick rounding ${formatBnForApi(adjAmount, rules.qtyStep)} is below minOrderSize ${rules.minOrderSize.toFixed()} (${request.market_name})`
6239
+ );
6240
+ }
6241
+ const payload = {
6242
+ ...request,
6243
+ amount: formatBnForApi(adjAmount, rules.qtyStep),
6244
+ price: formatBnForApi(adjPrice, rules.priceStep)
6245
+ };
6129
6246
  return this.makeRequest("/api/v1/orders", false, {
6130
6247
  method: "POST",
6131
- body: JSON.stringify(request)
6248
+ body: JSON.stringify(payload)
6132
6249
  });
6133
6250
  }
6134
6251
  /**
@@ -8097,6 +8214,7 @@ var vesu_rebalance_abi_default = [
8097
8214
  var CacheClass = class {
8098
8215
  constructor() {
8099
8216
  this.cache = /* @__PURE__ */ new Map();
8217
+ this.isCacheEnabled = true;
8100
8218
  }
8101
8219
  setCache(key, data, ttl = 6e4) {
8102
8220
  const timestamp = Date.now();
@@ -8104,7 +8222,7 @@ var CacheClass = class {
8104
8222
  }
8105
8223
  getCache(key) {
8106
8224
  const cachedData = this.cache.get(key);
8107
- if (!cachedData || !this.isCacheValid(key)) {
8225
+ if (!cachedData || !this.isCacheValid(key) || !this.isCacheEnabled) {
8108
8226
  return null;
8109
8227
  }
8110
8228
  return cachedData.data;
@@ -8115,6 +8233,12 @@ var CacheClass = class {
8115
8233
  const { timestamp, ttl } = cachedData;
8116
8234
  return Date.now() - timestamp <= ttl;
8117
8235
  }
8236
+ disableCache() {
8237
+ this.isCacheEnabled = false;
8238
+ }
8239
+ enableCache() {
8240
+ this.isCacheEnabled = true;
8241
+ }
8118
8242
  };
8119
8243
 
8120
8244
  // src/strategies/base-strategy.ts
@@ -28905,7 +29029,7 @@ var VesuAdapter = class _VesuAdapter extends CacheClass {
28905
29029
  throw new Error("LTV is 0");
28906
29030
  }
28907
29031
  this.setCache(CACHE_KEY, ltv, 3e5);
28908
- return this.getCache(CACHE_KEY);
29032
+ return ltv;
28909
29033
  }
28910
29034
  async getPositions(config, blockNumber = "latest") {
28911
29035
  if (!this.pricer) {
@@ -28989,6 +29113,9 @@ var VesuAdapter = class _VesuAdapter extends CacheClass {
28989
29113
  debtPrice = (await pricer.getPrice(this.config.debt.priceProxySymbol || this.config.debt.symbol)).price;
28990
29114
  }
28991
29115
  logger.verbose(`VesuAdapter::getAssetPrices collateralPrice: ${collateralPrice}, debtPrice: ${debtPrice}`);
29116
+ if (isNaN(collateralPrice) || isNaN(debtPrice) || collateralPrice == 0 || debtPrice == 0) {
29117
+ throw new Error(`VesuAdapter::getAssetPrices collateralPrice: ${collateralPrice}, debtPrice: ${debtPrice}`);
29118
+ }
28992
29119
  return {
28993
29120
  collateralTokenAmount,
28994
29121
  collateralUSDAmount,
@@ -34627,20 +34754,23 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
34627
34754
  }
34628
34755
  _buildZeroAmountSwapsWithWeights(quote, token, reverseRoutes = false) {
34629
34756
  const swaps = quote.splits.map((split) => {
34630
- const routeNodes = split.route.map((_route) => ({
34631
- pool_key: {
34632
- token0: ContractAddr.from(_route.pool_key.token0),
34633
- token1: ContractAddr.from(_route.pool_key.token1),
34634
- fee: _route.pool_key.fee,
34635
- tick_spacing: _route.pool_key.tick_spacing.toString(),
34636
- extension: _route.pool_key.extension
34637
- },
34638
- sqrt_ratio_limit: Web3Number.fromWei(_route.sqrt_ratio_limit, 18),
34639
- skip_ahead: Web3Number.fromWei(_route.skip_ahead, 0)
34640
- }));
34641
- if (reverseRoutes) {
34642
- routeNodes.reverse();
34643
- }
34757
+ let sellToken = token.address;
34758
+ const routeNodes = split.route.map((_route) => {
34759
+ let isSellToken0 = sellToken.eqString(_route.pool_key.token0);
34760
+ isSellToken0 = reverseRoutes ? !isSellToken0 : isSellToken0;
34761
+ sellToken = isSellToken0 ? ContractAddr.from(_route.pool_key.token1) : ContractAddr.from(_route.pool_key.token0);
34762
+ return {
34763
+ pool_key: {
34764
+ token0: ContractAddr.from(_route.pool_key.token0),
34765
+ token1: ContractAddr.from(_route.pool_key.token1),
34766
+ fee: _route.pool_key.fee,
34767
+ tick_spacing: _route.pool_key.tick_spacing.toString(),
34768
+ extension: _route.pool_key.extension
34769
+ },
34770
+ sqrt_ratio_limit: isSellToken0 ? Web3Number.fromWei(MIN_SQRT_RATIO_LIMIT.toString(), 18) : Web3Number.fromWei(MAX_SQRT_RATIO_LIMIT.toString(), 18),
34771
+ skip_ahead: Web3Number.fromWei(_route.skip_ahead, 0)
34772
+ };
34773
+ });
34644
34774
  return {
34645
34775
  route: routeNodes,
34646
34776
  token_amount: {
@@ -34962,6 +35092,7 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
34962
35092
  collateralToken.address.address,
34963
35093
  requiredAmount
34964
35094
  );
35095
+ logger.info(`VesuMultiplyAdapter::_getIncreaseCalldata requiredAmount: ${requiredAmount}`);
34965
35096
  if (marginSwapQuote.price_impact > 0.01) {
34966
35097
  throw new Error(
34967
35098
  `VesuMultiplyAdapter: Margin swap price impact too high (${marginSwapQuote.price_impact})`
@@ -34988,7 +35119,7 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
34988
35119
  legLTV,
34989
35120
  dexPrice
34990
35121
  );
34991
- logger.verbose(
35122
+ logger.info(
34992
35123
  `${_VesuMultiplyAdapter.name}::_getIncreaseCalldata debtAmount: ${debtAmount}, addedCollateral: ${addedCollateral}`
34993
35124
  );
34994
35125
  let leverSwap = [];
@@ -35006,8 +35137,10 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
35006
35137
  collateralToken.address.address,
35007
35138
  params.leverSwap?.exactOutput?.abs()
35008
35139
  );
35140
+ logger.info(`VesuMultiplyAdapter::_getIncreaseCalldata amount: ${params.leverSwap?.exactOutput?.abs()}`);
35009
35141
  debtAmount = Web3Number.fromWei(swapQuote.total_calculated, debtToken.decimals).abs();
35010
35142
  }
35143
+ logger.info(`VesuMultiplyAdapter::_getIncreaseCalldata debtAmount: ${debtAmount}`);
35011
35144
  swapQuote = await ekuboQuoter.getQuoteExactInput(
35012
35145
  debtToken.address.address,
35013
35146
  collateralToken.address.address,
@@ -35034,7 +35167,7 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
35034
35167
  await new Promise((resolve) => setTimeout(resolve, 1e4));
35035
35168
  } else {
35036
35169
  throw new Error(
35037
- `VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`
35170
+ `VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap, debtAmount=${debtAmount.toNumber()}, collateralPrice=${collateralPrice}, debtPrice=${debtPrice}`
35038
35171
  );
35039
35172
  }
35040
35173
  } catch (error) {
@@ -36405,14 +36538,6 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
36405
36538
  logger.error("error initializing client");
36406
36539
  return null;
36407
36540
  }
36408
- const setLeverage = await this.setLeverage(
36409
- leverage,
36410
- this.config.extendedMarketName
36411
- );
36412
- if (!setLeverage) {
36413
- logger.error("error depositing or setting leverage");
36414
- return null;
36415
- }
36416
36541
  const { ask, bid } = await this.fetchOrderBookFromExtended();
36417
36542
  if (!ask || !bid || ask.lessThanOrEqualTo(0) || bid.lessThanOrEqualTo(0)) {
36418
36543
  logger.error(
@@ -36552,13 +36677,13 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
36552
36677
  async createExtendedPositon(client, marketName, amount, price, side) {
36553
36678
  try {
36554
36679
  const result = side === "SELL" /* SELL */ ? await client.createSellOrder(marketName, amount, price, {
36555
- postOnly: false,
36556
- reduceOnly: false,
36557
- timeInForce: "IOC" /* IOC */
36680
+ post_only: false,
36681
+ reduce_only: false,
36682
+ time_in_force: "IOC" /* IOC */
36558
36683
  }) : await client.createBuyOrder(marketName, amount, price, {
36559
- postOnly: false,
36560
- reduceOnly: true,
36561
- timeInForce: "IOC" /* IOC */
36684
+ post_only: false,
36685
+ reduce_only: true,
36686
+ time_in_force: "IOC" /* IOC */
36562
36687
  });
36563
36688
  if (result.data.id) {
36564
36689
  const position_id = result.data.id.toString();
@@ -42023,20 +42148,42 @@ function mergeDeltas(a, b) {
42023
42148
  dTransferVesuToExt: a.dTransferVesuToExt + b.dTransferVesuToExt
42024
42149
  };
42025
42150
  }
42026
- function drawFunds(need, keys, pool) {
42151
+ function routableDrawAmount(avail, need, minRoutable) {
42152
+ if (avail <= 0 || need <= 0) return 0;
42153
+ const raw = Math.min(avail, need);
42154
+ if (raw <= 0) return 0;
42155
+ if (minRoutable <= 0) return raw;
42156
+ return raw > minRoutable ? raw : 0;
42157
+ }
42158
+ function drawFunds(need, keys, pool, minRoutable) {
42027
42159
  const draws = {};
42028
42160
  let unmet = need;
42029
42161
  for (const k of keys) {
42030
42162
  if (unmet <= 0) break;
42031
42163
  const avail = pool[k];
42032
- if (avail <= 0) continue;
42033
- const take = Math.min(avail, unmet);
42164
+ const take = routableDrawAmount(avail, unmet, minRoutable);
42165
+ if (take <= 0) continue;
42034
42166
  draws[k] = take;
42035
42167
  pool[k] -= take;
42036
42168
  unmet -= take;
42037
42169
  }
42038
42170
  return { draws, filled: need - unmet, unmet };
42039
42171
  }
42172
+ function drawExtendedAggregated(need, pool, minRoutable) {
42173
+ const draws = {};
42174
+ if (need <= 0) return { draws, filled: 0, unmet: 0 };
42175
+ const totalCap = Math.max(0, pool.extAvlWithdraw) + Math.max(0, pool.extUpnl);
42176
+ const want = routableDrawAmount(totalCap, need, minRoutable);
42177
+ if (want <= 0) return { draws, filled: 0, unmet: need };
42178
+ const fromAvl = Math.min(Math.max(0, pool.extAvlWithdraw), want);
42179
+ pool.extAvlWithdraw -= fromAvl;
42180
+ const fromUpnl = Math.min(Math.max(0, pool.extUpnl), want - fromAvl);
42181
+ pool.extUpnl -= fromUpnl;
42182
+ if (fromAvl > 0) draws.extAvlWithdraw = fromAvl;
42183
+ if (fromUpnl > 0) draws.extUpnl = fromUpnl;
42184
+ const filled = fromAvl + fromUpnl;
42185
+ return { draws, filled, unmet: need - filled };
42186
+ }
42040
42187
  function sumKeys(draws, keys) {
42041
42188
  return keys.reduce((s, k) => s + (draws[k] ?? 0), 0);
42042
42189
  }
@@ -42047,33 +42194,39 @@ function applyDrawsToDeltas(d, draws, sign) {
42047
42194
  d.dExtAvlWithdraw += sign * (draws.extAvlWithdraw ?? 0);
42048
42195
  d.dExtUpnl += sign * (draws.extUpnl ?? 0);
42049
42196
  }
42050
- function fixExtMargin(ext, price, pool) {
42197
+ function fixExtMargin(ext, price, pool, config) {
42051
42198
  const d = emptyDeltas();
42052
42199
  const deficit = computeExtDeficit(ext, price);
42053
42200
  if (deficit <= 0) return { d, unmet: 0 };
42054
- const { draws, filled, unmet } = drawFunds(deficit, ["walletUsd", "vaUsd", "vesuBorrowCapacity"], pool);
42201
+ const minR = config.minRoutableUsd ?? 0;
42202
+ const { draws, filled, unmet } = drawFunds(deficit, ["walletUsd", "vaUsd", "vesuBorrowCapacity"], pool, minR);
42055
42203
  applyDrawsToDeltas(d, draws, -1);
42056
42204
  d.dExtAvlWithdraw += filled;
42057
42205
  const fromVesu = draws.vesuBorrowCapacity ?? 0;
42058
42206
  if (fromVesu > 0) d.dTransferVesuToExt += fromVesu;
42059
42207
  return { d, unmet };
42060
42208
  }
42061
- function fixVesuMargin(vesu, price, pool, hfBuffer) {
42209
+ function fixVesuMargin(vesu, price, pool, hfBuffer, config) {
42062
42210
  const d = emptyDeltas();
42063
42211
  const hf = computeVesuHF(vesu, price);
42064
42212
  if (hf >= vesu.targetHF - hfBuffer) return { d, unmet: 0 };
42065
42213
  const repayTokens = computeVesuDebtRepay(vesu, price);
42066
42214
  const repayUsd = repayTokens * vesu.debtPrice;
42067
- const { draws, filled, unmet } = drawFunds(repayUsd, ["vaUsd", "walletUsd", "extAvlWithdraw", "extUpnl"], pool);
42068
- applyDrawsToDeltas(d, draws, -1);
42215
+ const minR = config.minRoutableUsd ?? 0;
42216
+ const rMain = drawFunds(repayUsd, ["vaUsd", "walletUsd"], pool, minR);
42217
+ applyDrawsToDeltas(d, rMain.draws, -1);
42218
+ const rExt = drawExtendedAggregated(rMain.unmet, pool, minR);
42219
+ applyDrawsToDeltas(d, rExt.draws, -1);
42220
+ const filled = rMain.filled + rExt.filled;
42221
+ const unmet = rExt.unmet;
42069
42222
  d.dVesuDebt -= filled / vesu.debtPrice;
42070
- const fromExt = sumKeys(draws, ["extAvlWithdraw", "extUpnl"]);
42223
+ const fromExt = sumKeys(rExt.draws, ["extAvlWithdraw", "extUpnl"]);
42071
42224
  if (fromExt > 0) d.dTransferVesuToExt -= fromExt;
42072
42225
  return { d, unmet };
42073
42226
  }
42074
42227
  function phase1(ext, vesu, price, pool, config) {
42075
- const extResult = fixExtMargin(ext, price, pool);
42076
- const vesuResult = fixVesuMargin(vesu, price, pool, config.hfBuffer);
42228
+ const extResult = fixExtMargin(ext, price, pool, config);
42229
+ const vesuResult = fixVesuMargin(vesu, price, pool, config.hfBuffer, config);
42077
42230
  return {
42078
42231
  deltas: mergeDeltas(extResult.d, vesuResult.d),
42079
42232
  extDeficitRemaining: extResult.unmet,
@@ -42113,26 +42266,31 @@ function roundFinalPosition(extPos, vesuPos, rawF, precision) {
42113
42266
  }
42114
42267
  return Math.max(0, Math.min(fFromExt, fFromVesu));
42115
42268
  }
42116
- function phase2(extPos, vesuPos, extEquity, vesuDebt, vesu, extLev, price, pool, precision) {
42269
+ function phase2(extPos, vesuPos, extEquity, vesuDebt, vesu, extLev, price, pool, config) {
42117
42270
  const d = emptyDeltas();
42271
+ const precision = config.positionPrecision;
42272
+ const minR = config.minRoutableUsd ?? 0;
42118
42273
  const targetLTV = computeVesuTargetLTV(vesu);
42119
42274
  const imbalance = extPos - vesuPos;
42120
42275
  let fundedGrowthBtc = 0;
42121
42276
  if (!isNegligible(imbalance, precision)) {
42122
42277
  if (imbalance > 0) {
42123
42278
  const equityCostUsd = computeVesuGrowthCost(imbalance, vesu, price);
42124
- const { draws, filled } = drawFunds(equityCostUsd, ["vaUsd", "walletUsd", "extAvlWithdraw", "extUpnl"], pool);
42125
- applyDrawsToDeltas(d, draws, -1);
42279
+ const rMain = drawFunds(equityCostUsd, ["vaUsd", "walletUsd"], pool, minR);
42280
+ applyDrawsToDeltas(d, rMain.draws, -1);
42281
+ const rExt = drawExtendedAggregated(rMain.unmet, pool, minR);
42282
+ applyDrawsToDeltas(d, rExt.draws, -1);
42283
+ const filled = rMain.filled + rExt.filled;
42126
42284
  const grownBtc = computeVesuGrowthFromEquity(filled, vesu, price);
42127
42285
  d.dVesuPosition += grownBtc;
42128
42286
  fundedGrowthBtc = grownBtc;
42129
42287
  d.dVesuDebt += computeVesuGrowthDebt(grownBtc, vesu, price);
42130
- const fromExt = sumKeys(draws, ["extAvlWithdraw", "extUpnl"]);
42288
+ const fromExt = sumKeys(rExt.draws, ["extAvlWithdraw", "extUpnl"]);
42131
42289
  if (fromExt > 0) d.dTransferVesuToExt -= fromExt;
42132
42290
  } else {
42133
42291
  const absImbalance = -imbalance;
42134
42292
  const marginCostUsd = absImbalance * price / extLev;
42135
- const { draws, filled } = drawFunds(marginCostUsd, ["walletUsd", "vaUsd", "vesuBorrowCapacity"], pool);
42293
+ const { draws, filled } = drawFunds(marginCostUsd, ["walletUsd", "vaUsd", "vesuBorrowCapacity"], pool, minR);
42136
42294
  applyDrawsToDeltas(d, draws, -1);
42137
42295
  const grownBtc = filled * extLev / price;
42138
42296
  d.dExtPosition += grownBtc;
@@ -42173,6 +42331,7 @@ function phase2(extPos, vesuPos, extEquity, vesuDebt, vesu, extLev, price, pool,
42173
42331
  return d;
42174
42332
  }
42175
42333
  function rebalance(inputs) {
42334
+ logger.info(`ltv-imbalance-rebalance-math::rebalance inputs=${JSON.stringify(inputs)}`);
42176
42335
  const { ext, vesu, btcPrice, config } = inputs;
42177
42336
  const pool = { ...inputs.funding };
42178
42337
  const p1 = phase1(ext, vesu, btcPrice, pool, config);
@@ -42189,7 +42348,7 @@ function rebalance(inputs) {
42189
42348
  ext.leverage,
42190
42349
  btcPrice,
42191
42350
  pool,
42192
- config.positionPrecision
42351
+ config
42193
42352
  );
42194
42353
  return mergeDeltas(p1.deltas, p2);
42195
42354
  }
@@ -42770,15 +42929,15 @@ var SolveBudget = class {
42770
42929
  return this.vesuPoolStates[0];
42771
42930
  }
42772
42931
  // ── Derived getters (buffered where applicable) ─────────────────────
42773
- /** Buffered VA USD: strategy-asset slot + optional USDC slot. */
42932
+ /** Buffered VA USD: non-stable asset slot (if any) + USDC slot. */
42774
42933
  get vaUsd() {
42775
- return this.bufferedTokenUsd(this.vaultAssetBalance) + this.bufferedTokenUsd(this.vaultUsdcBalance);
42934
+ return this.bufferedTokenUsd(this.vaultUsdcBalance);
42776
42935
  }
42777
42936
  /** Buffered USD in VA strategy-asset bucket only. */
42778
42937
  get vaAssetUsd() {
42779
42938
  return this.bufferedTokenUsd(this.vaultAssetBalance);
42780
42939
  }
42781
- /** Buffered USD in VA USDC bucket (0 when asset === USDC). */
42940
+ /** Buffered USD in VA USDC bucket (includes full VA idle when asset === USDC). */
42782
42941
  get vaUsdcUsd() {
42783
42942
  return this.bufferedTokenUsd(this.vaultUsdcBalance);
42784
42943
  }
@@ -42860,9 +43019,13 @@ var SolveBudget = class {
42860
43019
  get vesuRebalanceFlags() {
42861
43020
  return this.shouldVesuRebalance;
42862
43021
  }
42863
- /** Raw USD in VA (USDC slot + asset slot); spend caps when executing transfers. */
43022
+ /** Raw USD in VA (USDC slot + non-stable asset slot when distinct); spend caps when executing transfers. */
42864
43023
  _vaRawUsd() {
42865
- return this._rawTokenUsd(this.vaultUsdcBalance) + this._rawTokenUsd(this.vaultAssetBalance);
43024
+ return this._rawTokenUsd(this.vaultUsdcBalance);
43025
+ }
43026
+ /** VA liquidity usable for repay / {@link spendVaRawUsd} (matches nominal balances after any {@link applyBuffer} scaling). */
43027
+ get vaRawUsd() {
43028
+ return this._vaRawUsd();
42866
43029
  }
42867
43030
  _walletRawUsd() {
42868
43031
  return this._rawTokenUsd(this.walletBalance);
@@ -42938,7 +43101,7 @@ var SolveBudget = class {
42938
43101
  rem -= fromUsdc;
42939
43102
  }
42940
43103
  if (rem > 0 && this.vaultAssetBalance) {
42941
- this._deductUsdFromTokenBalance(this.vaultAssetBalance, rem);
43104
+ throw new Error(`Not implemented: spendVA with vaultAssetBalance`);
42942
43105
  }
42943
43106
  this._recomputeUnusedBalance();
42944
43107
  logger.debug(`SolveBudget::spendVA usedRaw=${usedRaw}, vaUsd=${this.vaUsd}, totalUnused=${this.totalUnused}`);
@@ -42948,7 +43111,10 @@ var SolveBudget = class {
42948
43111
  * Spend nominal/raw USD from VA (e.g. Vesu repay, on-chain USDC). Does not apply the safety buffer to the cap.
42949
43112
  */
42950
43113
  spendVaRawUsd(rawUsdDesired) {
42951
- const capRaw = this._rawTokenUsd(this.vaultUsdcBalance) + this._rawTokenUsd(this.vaultAssetBalance);
43114
+ const capRaw = (
43115
+ // this._rawTokenUsd(this.vaultUsdcBalance) + this._rawTokenUsd(this.vaultAssetBalance);
43116
+ this._rawTokenUsd(this.vaultUsdcBalance)
43117
+ );
42952
43118
  const usedRaw = Math.min(capRaw, Math.max(0, rawUsdDesired));
42953
43119
  if (usedRaw <= CASE_THRESHOLD_USD) return 0;
42954
43120
  let rem = usedRaw;
@@ -42958,7 +43124,7 @@ var SolveBudget = class {
42958
43124
  rem -= fromUsdc;
42959
43125
  }
42960
43126
  if (rem > 0 && this.vaultAssetBalance) {
42961
- this._deductUsdFromTokenBalance(this.vaultAssetBalance, rem);
43127
+ throw new Error(`Not implemented: spendVaRawUsd with vaultAssetBalance`);
42962
43128
  }
42963
43129
  this._recomputeUnusedBalance();
42964
43130
  logger.debug(`SolveBudget::spendVaRawUsd usedRaw=${usedRaw}, vaUsd=${this.vaUsd}, totalUnused=${this.totalUnused}`);
@@ -42973,7 +43139,7 @@ var SolveBudget = class {
42973
43139
  if (this.vaultUsdcBalance) {
42974
43140
  this._addUsdToTokenBalance(this.vaultUsdcBalance, rawUsd);
42975
43141
  } else if (this.vaultAssetBalance) {
42976
- this._addUsdToTokenBalance(this.vaultAssetBalance, rawUsd);
43142
+ throw new Error(`Not implemented: addToVA with vaultAssetBalance`);
42977
43143
  }
42978
43144
  this._recomputeUnusedBalance();
42979
43145
  logger.debug(`SolveBudget::addToVA rawUsd=${rawUsd}, vaUsd=${this.vaUsd}, totalUnused=${this.totalUnused}`);
@@ -43012,7 +43178,7 @@ var SolveBudget = class {
43012
43178
  if (isSpend) {
43013
43179
  const capRaw = this.extendedBalance?.availableForWithdrawal?.toNumber() ?? 0;
43014
43180
  const useRaw = Math.min(capRaw, desiredRaw);
43015
- if (useRaw <= CASE_THRESHOLD_USD) return 0;
43181
+ if (useRaw <= 0) return 0;
43016
43182
  rawDelta = -useRaw;
43017
43183
  } else {
43018
43184
  rawDelta = desiredRaw;
@@ -43032,7 +43198,7 @@ var SolveBudget = class {
43032
43198
  if (isSpend) {
43033
43199
  const capRaw = this.extendedBalance?.unrealisedPnl?.toNumber() ?? 0;
43034
43200
  const useRaw = Math.min(capRaw, desiredRaw);
43035
- if (useRaw <= CASE_THRESHOLD_USD) return 0;
43201
+ if (useRaw <= 0) return 0;
43036
43202
  rawDelta = -useRaw;
43037
43203
  } else {
43038
43204
  rawDelta = desiredRaw;
@@ -43047,10 +43213,12 @@ var SolveBudget = class {
43047
43213
  return rawDelta;
43048
43214
  }
43049
43215
  spendExtAvailTrade(rawDesired) {
43050
- const used = this._updateExtAvailWithdraw(rawDesired, true);
43051
- const usedUpnl = this._updateExtAvailUpnl(rawDesired, true);
43052
- logger.debug(`SolveBudget::updateExtAvailTrade rawSum=${used + usedUpnl}, extAvailTrade=${this.extAvailTrade}, totalUnused=${this.totalUnused}`);
43053
- return used + usedUpnl;
43216
+ const usedWd = this._updateExtAvailWithdraw(rawDesired, true);
43217
+ const tookWd = Math.abs(usedWd);
43218
+ const rem = rawDesired - tookWd;
43219
+ const usedUpnl = rem > 0 ? this._updateExtAvailUpnl(rem, true) : 0;
43220
+ logger.debug(`SolveBudget::updateExtAvailTrade rawSum=${usedWd + usedUpnl}, extAvailTrade=${this.extAvailTrade}, totalUnused=${this.totalUnused}`);
43221
+ return usedWd + usedUpnl;
43054
43222
  }
43055
43223
  // simply reduces available amounts, but maintains equity and balance.
43056
43224
  spendExtAvailTradeToEquityOnly(rawDesired) {
@@ -43370,7 +43538,7 @@ var ExtendedSVKVesuStateManager = class {
43370
43538
  this._fetchExtendedPositions()
43371
43539
  ]);
43372
43540
  logger.verbose(
43373
- `${this._tag}::_refresh VA asset ${vaultAssetBalance.token.symbol}=$${vaultAssetBalance.usdValue.toFixed(2)}${vaultUsdcBalance ? `, VA USDC=$${vaultUsdcBalance.usdValue.toFixed(2)}` : ""}, wallet=${walletBalance.usdValue}`
43541
+ `${this._tag}::_refresh ${vaultAssetBalance ? `VA asset ${vaultAssetBalance.token.symbol}=$${vaultAssetBalance.usdValue.toFixed(2)}, ` : ""}VA USDC=${vaultUsdcBalance.usdValue.toFixed(2)}, wallet=${walletBalance.usdValue}`
43374
43542
  );
43375
43543
  const unusedBalance = this._computeUnusedBalances(
43376
43544
  vaultAssetBalance,
@@ -43395,23 +43563,28 @@ var ExtendedSVKVesuStateManager = class {
43395
43563
  },
43396
43564
  vesuPoolStates
43397
43565
  });
43566
+ this._budget.logStateSummary();
43398
43567
  const totalUnusedUsd = unusedBalance.reduce(
43399
43568
  (acc, b) => acc + b.usdValue,
43400
43569
  0
43401
43570
  );
43402
43571
  logger.info(
43403
- `${this._tag}::_refresh completed \u2014 unusedBalances: ${unusedBalance.length} tokens, totalUnusedUsd: ${totalUnusedUsd.toFixed(2)}, extendedPositions: ${extendedPositions.length}, vesuPools: ${vesuPoolStates.length} - availableForTrade: ${extendedBalance?.availableForTrade.toNumber()} - availableForWithdrawal: ${extendedBalance?.availableForWithdrawal.toNumber()} - unrealisedPnl: ${extendedBalance?.unrealisedPnl.toNumber()} - extendedBalance::balance: ${extendedBalance?.balance.toNumber()} - extendedBalance::pendingDeposit: ${extendedBalance?.pendingDeposit.toNumber()} - extendedBalance::equity: ${extendedBalance?.equity.toNumber()}`
43572
+ `${this._tag}::_refresh completed \u2014 unusedBalances: ${unusedBalance.length} tokens [${unusedBalance.map((b) => `${b.token.symbol}=$${b.usdValue.toFixed(2)}`).join(", ")}], totalUnusedUsd: ${totalUnusedUsd.toFixed(2)}, extendedPositions: ${extendedPositions.length} [${extendedPositions.map((p) => `${p.instrument}=${p.size.toFixed(6)} ${p.side}, ${p.valueUsd.toFixed(6)} ${p.instrument}`).join(", ")}], vesuPools: ${vesuPoolStates.length} [${vesuPoolStates.map((p) => `${p.poolId.shortString()}=${p.debtAmount.toFixed(6)} ${p.debtToken.symbol}, ${p.collateralAmount.toFixed(6)} ${p.collateralToken.symbol}`).join(", ")}], availableForTrade: ${extendedBalance?.availableForTrade.toNumber()} - availableForWithdrawal: ${extendedBalance?.availableForWithdrawal.toNumber()} - unrealisedPnl: ${extendedBalance?.unrealisedPnl.toNumber()} - extendedBalance::balance: ${extendedBalance?.balance.toNumber()} - extendedBalance::pendingDeposit: ${extendedBalance?.pendingDeposit.toNumber()} - extendedBalance::equity: ${extendedBalance?.equity.toNumber()}`
43404
43573
  );
43405
43574
  }
43406
43575
  // todo add communication check with python server of extended. if not working, throw error in solve function.
43407
- /** True when strategy asset and USDC share one token — VA USDC slot is unused (all in asset balance). */
43576
+ /** True when strategy asset and USDC share one token — VA idle balance is tracked as USDC, not as asset. */
43408
43577
  _vaultAssetAndUsdcAreSameToken() {
43409
43578
  return this._config.assetToken.address.eq(this._config.usdcToken.address);
43410
43579
  }
43411
43580
  /**
43412
- * Reads the {@link StateManagerConfig.assetToken} balance idle in the vault allocator.
43581
+ * Reads idle {@link StateManagerConfig.assetToken} in the vault allocator when it differs from USDC.
43582
+ * When asset and USDC are the same token, returns null (that balance is reported via {@link _fetchVaultAllocatorUsdcBalanceIfDistinct} only).
43413
43583
  */
43414
43584
  async _fetchVaultAllocatorAssetBalance() {
43585
+ if (this._vaultAssetAndUsdcAreSameToken()) {
43586
+ return null;
43587
+ }
43415
43588
  const { assetToken, vaultAllocator, networkConfig, pricer } = this._config;
43416
43589
  const balance = await new ERC20(networkConfig).balanceOf(
43417
43590
  assetToken.address,
@@ -43423,11 +43596,9 @@ var ExtendedSVKVesuStateManager = class {
43423
43596
  return { token: assetToken, amount: balance, usdValue };
43424
43597
  }
43425
43598
  /**
43426
- * Reads {@link StateManagerConfig.usdcToken} in the vault allocator when it differs from
43427
- * {@link StateManagerConfig.assetToken}. Otherwise returns null (treat VA USDC as 0; stablecoin is only under asset).
43599
+ * Reads {@link StateManagerConfig.usdcToken} idle in the vault allocator (always distinct asset or USDC-as-asset).
43428
43600
  */
43429
43601
  async _fetchVaultAllocatorUsdcBalanceIfDistinct() {
43430
- if (this._vaultAssetAndUsdcAreSameToken()) return null;
43431
43602
  const { usdcToken, vaultAllocator, networkConfig, pricer } = this._config;
43432
43603
  const balance = await new ERC20(networkConfig).balanceOf(
43433
43604
  usdcToken.address,
@@ -43441,7 +43612,7 @@ var ExtendedSVKVesuStateManager = class {
43441
43612
  return { token: usdcToken, amount: balance, usdValue };
43442
43613
  }
43443
43614
  /**
43444
- * Merges vault-allocator asset, optional vault-allocator USDC, and operator wallet
43615
+ * Merges vault-allocator asset (if any), vault-allocator USDC, and operator wallet
43445
43616
  * balances into entries keyed by token address.
43446
43617
  */
43447
43618
  _computeUnusedBalances(vaultAssetBalance, vaultUsdcBalance, walletBalance) {
@@ -43453,8 +43624,8 @@ var ExtendedSVKVesuStateManager = class {
43453
43624
  usdValue: tb.usdValue
43454
43625
  });
43455
43626
  };
43456
- put(vaultAssetBalance);
43457
- if (vaultUsdcBalance) put(vaultUsdcBalance);
43627
+ if (vaultAssetBalance) put(vaultAssetBalance);
43628
+ put(vaultUsdcBalance);
43458
43629
  const key = walletBalance.token.address.toString();
43459
43630
  const existing = balanceMap.get(key);
43460
43631
  if (existing) {
@@ -43973,7 +44144,10 @@ var ExtendedSVKVesuStateManager = class {
43973
44144
  // ── ExecutionRoute-building helpers ─────────────────────────────────────────────
43974
44145
  // ── Atomic route builders ────────────────────────────────────────────
43975
44146
  _buildVesuRepayRoutes(totalUsd, routes) {
43976
- const { used, spendsByPool } = this._budget.repayVesuBorrowCapacity(totalUsd);
44147
+ const vaCap = this._budget.vaRawUsd;
44148
+ const repayUsd = Math.min(totalUsd, vaCap);
44149
+ if (repayUsd <= CASE_THRESHOLD_USD) return;
44150
+ const { used, spendsByPool } = this._budget.repayVesuBorrowCapacity(repayUsd);
43977
44151
  for (const route of spendsByPool) {
43978
44152
  routes.push({ type: "VESU_REPAY" /* VESU_REPAY */, ...route, priority: routes.length });
43979
44153
  }
@@ -44067,7 +44241,7 @@ var ExtendedSVKVesuStateManager = class {
44067
44241
  return { routes, remaining: tryAmount };
44068
44242
  }
44069
44243
  _getVAToEXTENDEDRoute(tryAmount, routes, shouldAddWaitRoute = true) {
44070
- const usable = Math.min(tryAmount, this._budget.vaUsd);
44244
+ const usable = Math.min(tryAmount, this._budget.vaUsdcUsd);
44071
44245
  if (usable > CASE_THRESHOLD_USD) {
44072
44246
  const vaUsed = this._budget.spendVA(usable);
44073
44247
  this._budget.addToExtAvailTrade(vaUsed);
@@ -44082,7 +44256,7 @@ var ExtendedSVKVesuStateManager = class {
44082
44256
  }
44083
44257
  _getExtendedToWalletRoute(tryAmount, routes, shouldAddWaitRoute = true) {
44084
44258
  if (tryAmount <= CASE_THRESHOLD_USD) return { routes, remaining: tryAmount };
44085
- const rawCap = this._budget.extAvailWithdraw + this._budget.extAvailUpnl;
44259
+ const rawCap = this._budget.extAvailWithdraw + Math.max(0, this._budget.extAvailUpnl);
44086
44260
  const rawSpend = Math.min(tryAmount, rawCap);
44087
44261
  if (rawSpend <= CASE_THRESHOLD_USD) return { routes, remaining: tryAmount };
44088
44262
  const rawOut = this._budget.spendExtAvailTrade(rawSpend);
@@ -44272,7 +44446,9 @@ var ExtendedSVKVesuStateManager = class {
44272
44446
  * Design: accumulate all ext-to-wallet moves, add transfer routes at the end (principle #3).
44273
44447
  */
44274
44448
  /**
44275
- * Unified LTV classifier. Computes both Vesu repay and Extended margin needs,
44449
+ * Unified LTV / exposure classifier: `rebalance()` drives both LTV (debt, margin,
44450
+ * funding) and Vesu↔Extended position alignment. There is no separate imbalance pass.
44451
+ * Computes both Vesu repay and Extended margin needs,
44276
44452
  * then builds all routes in a single pass with no duplicate transfers.
44277
44453
  *
44278
44454
  * Vesu repay priority: VA > Wallet > ExtAvl > ExtUpnl
@@ -44328,7 +44504,8 @@ var ExtendedSVKVesuStateManager = class {
44328
44504
  },
44329
44505
  config: {
44330
44506
  positionPrecision: COLLATERAL_PRECISION,
44331
- hfBuffer: 0.05
44507
+ hfBuffer: 0.05,
44508
+ minRoutableUsd: CASE_THRESHOLD_USD
44332
44509
  }
44333
44510
  };
44334
44511
  }
@@ -44339,8 +44516,9 @@ var ExtendedSVKVesuStateManager = class {
44339
44516
  }
44340
44517
  /**
44341
44518
  * Turn pure rebalance() deltas into execution routes.
44342
- * Order: Vesu multiply (decrease/increase) → Extended lever → aggregated transfers
44343
- * (REALISE_PNL, EXTENDED_TO_WALLET + WAIT, WALLET_TO_VA, VESU_BORROW, VESU_REPAY, VA_TO_EXTENDED).
44519
+ * Order: Vesu multiply decrease → Extended decrease → aggregated transfers
44520
+ * (REALISE_PNL, EXTENDED_TO_WALLET + WAIT, WALLET_TO_VA, VESU_BORROW, VESU_REPAY, VA_TO_EXTENDED),
44521
+ * then Vesu multiply increase and Extended increase (need VA / Extended funded first).
44344
44522
  */
44345
44523
  _buildLtvRoutesFromRebalanceDeltas(d) {
44346
44524
  const routes = [];
@@ -44352,6 +44530,7 @@ var ExtendedSVKVesuStateManager = class {
44352
44530
  const targetLtv = VesuConfig.targetLtv;
44353
44531
  const btcEps = 10 ** -COLLATERAL_PRECISION;
44354
44532
  let multiplyDebtRepayUsd = 0;
44533
+ logger.info(`${this._tag}::_buildLtvRoutesFromRebalanceDeltas d=${JSON.stringify(d)}`);
44355
44534
  if (d.dVesuPosition < -btcEps) {
44356
44535
  const xBtc = -d.dVesuPosition;
44357
44536
  const transferUsdFromVesu = Math.max(0, d.dTransferVesuToExt);
@@ -44370,12 +44549,28 @@ var ExtendedSVKVesuStateManager = class {
44370
44549
  if (d.dVesuDebt < 0) {
44371
44550
  const needRepayUsd = -d.dVesuDebt * debtPrice;
44372
44551
  const multiplyRepayUsd = Math.min(needRepayUsd, swapLegMaxRepayUsd);
44552
+ logger.info(`${this._tag}::_buildLtvRoutesFromRebalanceDeltas ${JSON.stringify({
44553
+ needRepayUsd,
44554
+ multiplyRepayUsd
44555
+ })}`);
44373
44556
  debtTokenDelta = -(multiplyRepayUsd / debtPrice);
44374
44557
  } else {
44375
44558
  debtTokenDelta = -debtUsdFallback;
44376
44559
  }
44377
44560
  const debtAmtW3 = new Web3Number(debtTokenDelta.toFixed(USDC_TOKEN_DECIMALS), USDC_TOKEN_DECIMALS);
44378
44561
  multiplyDebtRepayUsd = Math.abs(debtTokenDelta) * debtPrice;
44562
+ logger.info(`${this._tag}::_buildLtvRoutesFromRebalanceDeltas ${JSON.stringify({
44563
+ debtTokenDelta,
44564
+ debtUsdFallback,
44565
+ swapLegMaxRepayUsd,
44566
+ xBtc,
44567
+ marginBtc,
44568
+ swappedBtc,
44569
+ transferUsdFromVesu,
44570
+ debtPrice,
44571
+ targetLtv,
44572
+ multiplyDebtRepayUsd
44573
+ })}`);
44379
44574
  routes.push({
44380
44575
  type: "VESU_MULTIPLY_DECREASE_LEVER" /* VESU_MULTIPLY_DECREASE_LEVER */,
44381
44576
  poolId: vesuAdapter.config.poolId,
@@ -44396,19 +44591,68 @@ var ExtendedSVKVesuStateManager = class {
44396
44591
  if (transferUsdFromVesu > CASE_THRESHOLD_USD) {
44397
44592
  this._budget.addToVA(transferUsdFromVesu);
44398
44593
  }
44399
- } else if (d.dVesuPosition > btcEps) {
44594
+ }
44595
+ if (d.dExtPosition < -btcEps) {
44596
+ const amt = new Web3Number(d.dExtPosition.toFixed(COLLATERAL_PRECISION), 8);
44597
+ routes.push({
44598
+ type: "EXTENDED_DECREASE_LEVER" /* EXTENDED_DECREASE_LEVER */,
44599
+ amount: amt,
44600
+ instrument,
44601
+ priority: routes.length
44602
+ });
44603
+ this._budget.applyExtendedExposureDelta(instrument, amt, price);
44604
+ }
44605
+ const negUpnl = Math.min(0, d.dExtUpnl);
44606
+ const negExtAvl = Math.min(0, d.dExtAvlWithdraw);
44607
+ let hadExtendedOut = false;
44608
+ if (negUpnl < -CASE_THRESHOLD_USD) {
44609
+ this._getUpnlRoute(Math.abs(negUpnl), routes);
44610
+ hadExtendedOut = true;
44611
+ }
44612
+ const extToWalletUsd = (negExtAvl < -CASE_THRESHOLD_USD ? Math.abs(negExtAvl) : 0) + (negUpnl < -CASE_THRESHOLD_USD ? Math.abs(negUpnl) : 0);
44613
+ logger.info(`${this._tag}::_buildLtvRoutesFromRebalanceDeltas extToWalletUsd=${extToWalletUsd}, negExtAvl=${negExtAvl}, negUpnl=${negUpnl}`);
44614
+ if (extToWalletUsd > CASE_THRESHOLD_USD) {
44615
+ this._getExtendedToWalletRoute(extToWalletUsd, routes);
44616
+ hadExtendedOut = true;
44617
+ } else {
44618
+ if (d.dVesuDebt < 0) {
44619
+ d.dVesuDebt += (negExtAvl < 0 && negExtAvl > -CASE_THRESHOLD_USD ? Math.abs(negExtAvl) : 0) + (negUpnl < 0 && negUpnl > -CASE_THRESHOLD_USD ? Math.abs(negUpnl) : 0);
44620
+ }
44621
+ }
44622
+ logger.info(`${this._tag}::_buildLtvRoutesFromRebalanceDeltas d=${JSON.stringify(d)}`);
44623
+ const walletPull = Math.abs(Math.min(0, d.dWalletUsd));
44624
+ const walletToVaUsd = walletPull + extToWalletUsd;
44625
+ if (walletToVaUsd > CASE_THRESHOLD_USD) {
44626
+ this._getWALLETToVARoute(walletToVaUsd, routes);
44627
+ }
44628
+ if (d.dVesuBorrowCapacity < -CASE_THRESHOLD_USD) {
44629
+ this._buildVesuBorrowRoutes(Math.abs(d.dVesuBorrowCapacity), routes);
44630
+ }
44631
+ const totalDebtRepayUsd = d.dVesuDebt < 0 ? -d.dVesuDebt * debtPrice : 0;
44632
+ logger.info(`${this._tag}::_buildLtvRoutesFromRebalanceDeltas totalDebtRepayUsd=${totalDebtRepayUsd}`);
44633
+ let standaloneRepayUsd = Math.max(0, totalDebtRepayUsd - multiplyDebtRepayUsd);
44634
+ logger.info(`${this._tag}::_buildLtvRoutesFromRebalanceDeltas standaloneRepayUsd=${standaloneRepayUsd}`);
44635
+ if (standaloneRepayUsd > this._budget.vaRawUsd) {
44636
+ if (Math.abs(standaloneRepayUsd - this._budget.vaRawUsd) < CASE_THRESHOLD_USD) {
44637
+ standaloneRepayUsd = this._budget.vaRawUsd;
44638
+ } else {
44639
+ throw new Error(`${this._tag}::_buildLtvRoutesFromRebalanceDeltas standaloneRepayUsd=${standaloneRepayUsd} > vaRawUsd=${this._budget.vaRawUsd}`);
44640
+ }
44641
+ }
44642
+ if (standaloneRepayUsd > CASE_THRESHOLD_USD) {
44643
+ this._buildVesuRepayRoutes(standaloneRepayUsd, routes);
44644
+ }
44645
+ const posExtEq = Math.max(0, d.dExtAvlWithdraw);
44646
+ const vaToExtUsd = posExtEq > CASE_THRESHOLD_USD ? posExtEq : 0;
44647
+ if (vaToExtUsd > CASE_THRESHOLD_USD) {
44648
+ this._getVAToEXTENDEDRoute(vaToExtUsd, routes, hadExtendedOut);
44649
+ }
44650
+ if (d.dVesuPosition > btcEps) {
44400
44651
  const vesuDepositAmount = new Web3Number(
44401
44652
  (d.dVesuPosition * price * (1 - targetLtv)).toFixed(USDC_TOKEN_DECIMALS),
44402
44653
  USDC_TOKEN_DECIMALS
44403
44654
  );
44404
44655
  if (vesuDepositAmount.toNumber() > CASE_THRESHOLD_USD) {
44405
- routes.push({
44406
- type: "AVNU_DEPOSIT_SWAP" /* AVNU_DEPOSIT_SWAP */,
44407
- priority: routes.length,
44408
- fromToken: vesuAdapter.config.collateral.symbol,
44409
- fromAmount: vesuDepositAmount,
44410
- toToken: vesuAdapter.config.debt.symbol
44411
- });
44412
44656
  }
44413
44657
  const collateralDelta = new Web3Number(
44414
44658
  d.dVesuPosition.toFixed(COLLATERAL_PRECISION),
@@ -44419,8 +44663,9 @@ var ExtendedSVKVesuStateManager = class {
44419
44663
  new Web3Number(Math.min(availableBorrowCapacity, vesuDepositAmount.toNumber()).toFixed(USDC_TOKEN_DECIMALS), USDC_TOKEN_DECIMALS)
44420
44664
  );
44421
44665
  const collPx = pool.collateralPrice || 1;
44666
+ const marginUsdAmount = externalDepositAmount.toNumber() * (pool.debtPrice ?? 1);
44422
44667
  const swappedAmount = new Web3Number(
44423
- (externalDepositAmount.toNumber() * (pool.debtPrice ?? 1) / collPx).toFixed(6),
44668
+ (marginUsdAmount / collPx).toFixed(6),
44424
44669
  vesuAdapter.config.collateral.decimals
44425
44670
  );
44426
44671
  const debtDeltaTokens = new Web3Number(
@@ -44444,17 +44689,9 @@ var ExtendedSVKVesuStateManager = class {
44444
44689
  collateralDelta,
44445
44690
  debtDeltaTokens
44446
44691
  );
44692
+ this._budget.spendVA(marginUsdAmount);
44447
44693
  }
44448
- if (d.dExtPosition < -btcEps) {
44449
- const amt = new Web3Number(d.dExtPosition.toFixed(COLLATERAL_PRECISION), 8);
44450
- routes.push({
44451
- type: "EXTENDED_DECREASE_LEVER" /* EXTENDED_DECREASE_LEVER */,
44452
- amount: amt,
44453
- instrument,
44454
- priority: routes.length
44455
- });
44456
- this._budget.applyExtendedExposureDelta(instrument, amt, price);
44457
- } else if (d.dExtPosition > btcEps) {
44694
+ if (d.dExtPosition > btcEps) {
44458
44695
  const amt = new Web3Number(d.dExtPosition.toFixed(COLLATERAL_PRECISION), 8);
44459
44696
  routes.push({
44460
44697
  type: "EXTENDED_INCREASE_LEVER" /* EXTENDED_INCREASE_LEVER */,
@@ -44464,36 +44701,6 @@ var ExtendedSVKVesuStateManager = class {
44464
44701
  });
44465
44702
  this._budget.applyExtendedExposureDelta(instrument, amt, price);
44466
44703
  }
44467
- const negUpnl = Math.min(0, d.dExtUpnl);
44468
- const negExtAvl = Math.min(0, d.dExtAvlWithdraw);
44469
- let hadExtendedOut = false;
44470
- if (negUpnl < -CASE_THRESHOLD_USD) {
44471
- this._getUpnlRoute(Math.abs(negUpnl), routes);
44472
- hadExtendedOut = true;
44473
- }
44474
- const extToWalletUsd = (negExtAvl < -CASE_THRESHOLD_USD ? Math.abs(negExtAvl) : 0) + (negUpnl < -CASE_THRESHOLD_USD ? Math.abs(negUpnl) : 0);
44475
- if (extToWalletUsd > CASE_THRESHOLD_USD) {
44476
- this._getExtendedToWalletRoute(extToWalletUsd, routes);
44477
- hadExtendedOut = true;
44478
- }
44479
- const walletPull = Math.abs(Math.min(0, d.dWalletUsd));
44480
- const walletToVaUsd = walletPull + extToWalletUsd;
44481
- if (walletToVaUsd > CASE_THRESHOLD_USD) {
44482
- this._getWALLETToVARoute(walletToVaUsd, routes);
44483
- }
44484
- if (d.dVesuBorrowCapacity < -CASE_THRESHOLD_USD) {
44485
- this._buildVesuBorrowRoutes(Math.abs(d.dVesuBorrowCapacity), routes);
44486
- }
44487
- const totalDebtRepayUsd = d.dVesuDebt < 0 ? -d.dVesuDebt * debtPrice : 0;
44488
- const standaloneRepayUsd = Math.max(0, totalDebtRepayUsd - multiplyDebtRepayUsd);
44489
- if (standaloneRepayUsd > CASE_THRESHOLD_USD) {
44490
- this._buildVesuRepayRoutes(standaloneRepayUsd, routes);
44491
- }
44492
- const posExtEq = Math.max(0, d.dExtAvlWithdraw);
44493
- const vaToExtUsd = posExtEq > CASE_THRESHOLD_USD ? posExtEq : 0;
44494
- if (vaToExtUsd > CASE_THRESHOLD_USD) {
44495
- this._getVAToEXTENDEDRoute(vaToExtUsd, routes, hadExtendedOut);
44496
- }
44497
44704
  return routes;
44498
44705
  }
44499
44706
  // ── LTV Vesu route builders ───────────────────────────────────────────
@@ -44652,48 +44859,76 @@ var ExtendedSVKVesuStateManager = class {
44652
44859
  const extendedTarget = total / (1 + extendedLeverage / vesuLeverage);
44653
44860
  const extendedInitial = extAvlWithdraw + extUpnl;
44654
44861
  let delta = extendedTarget - extendedInitial;
44655
- let dExtAvlWithdraw = 0, dExtUpnl = 0, dVaUsd = 0, dWalletUsd = 0, dVesuBorrowCapacity = 0;
44862
+ let dExtAvlWithdraw = 0, dExtUpnl = 0, dVaUsd = 0, dWalletUsd = 0, dVesuBorrowCapacity = 0, finalVaUsd = vaUsd, finalExtended = extAvlWithdraw + Math.max(extUpnl, 0);
44656
44863
  if (delta > 0) {
44657
44864
  let need = delta;
44658
- const takeWalletUsd = Math.min(walletUsd, need);
44865
+ const eps = CASE_THRESHOLD_USD;
44866
+ const takeWalletUsd = routableDrawAmount(walletUsd, need, eps);
44659
44867
  dWalletUsd -= takeWalletUsd;
44660
44868
  need -= takeWalletUsd;
44661
- const takeVaUsd = Math.min(vaUsd, need);
44869
+ const takeVaUsd = routableDrawAmount(vaUsd, need, eps);
44662
44870
  dVaUsd -= takeVaUsd;
44663
44871
  need -= takeVaUsd;
44664
- const takeVesuBorrowCapacity = Math.min(vesuBorrowCapacity, need);
44872
+ finalVaUsd -= takeVaUsd;
44873
+ finalVaUsd += walletUsd - takeWalletUsd;
44874
+ const takeVesuBorrowCapacity = routableDrawAmount(vesuBorrowCapacity, need, eps);
44665
44875
  dVesuBorrowCapacity -= takeVesuBorrowCapacity;
44666
44876
  need -= takeVesuBorrowCapacity;
44877
+ finalVaUsd += vesuBorrowCapacity - takeVesuBorrowCapacity;
44667
44878
  const received = delta - need;
44668
44879
  const eco1Sum = extAvlWithdraw + extUpnl;
44880
+ finalExtended += received;
44669
44881
  if (eco1Sum >= 0) {
44670
44882
  dExtAvlWithdraw += received;
44671
44883
  } else {
44672
- throw new Error(`${this._tag}: Unexpected case`);
44884
+ const hole = -eco1Sum;
44885
+ const fillUpnl = Math.min(received, hole);
44886
+ dExtUpnl += fillUpnl;
44887
+ dExtAvlWithdraw += received - fillUpnl;
44888
+ finalExtended -= fillUpnl;
44673
44889
  }
44674
- if (need > 0) {
44890
+ if (need > CASE_THRESHOLD_USD) {
44675
44891
  throw new Error(`${this._tag}: Insufficient funds to cover margin needs`);
44676
44892
  }
44677
44893
  } else if (delta < 0) {
44678
44894
  let need = -delta;
44679
- const takeExtAvlWithdraw = Math.min(extAvlWithdraw, need);
44895
+ const takeExtAvlWithdraw = Math.min(Math.max(extAvlWithdraw, 0), need);
44680
44896
  dExtAvlWithdraw -= takeExtAvlWithdraw;
44681
- need -= takeExtAvlWithdraw;
44682
- const takeExtUpnl = Math.min(extUpnl, need);
44897
+ const takeExtUpnl = Math.min(Math.max(extUpnl, 0), need);
44683
44898
  dExtUpnl -= takeExtUpnl;
44684
- need -= takeExtUpnl;
44899
+ const netDrawableAmount = takeExtAvlWithdraw + takeExtUpnl;
44900
+ if (netDrawableAmount > CASE_THRESHOLD_USD) {
44901
+ need -= netDrawableAmount;
44902
+ finalExtended -= netDrawableAmount;
44903
+ }
44685
44904
  const sent = -delta - need;
44686
44905
  const eco2Sum = vaUsd + walletUsd + vesuBorrowCapacity;
44906
+ const netWalletUsd = walletUsd < CASE_THRESHOLD_USD ? 0 : walletUsd;
44907
+ finalVaUsd += sent + netWalletUsd;
44687
44908
  if (eco2Sum >= 0) {
44688
44909
  dWalletUsd += sent;
44689
44910
  } else {
44690
44911
  throw new Error(`${this._tag}: Unexpected case`);
44691
44912
  }
44692
- if (need > 0) {
44913
+ if (need > CASE_THRESHOLD_USD) {
44693
44914
  throw new Error(`${this._tag}: Insufficient funds to cover margin needs`);
44694
44915
  }
44695
44916
  }
44696
- return { dExtAvlWithdraw, dExtUpnl, dVaUsd, dWalletUsd, dVesuBorrowCapacity, isExtendedToVesu: delta < 0 };
44917
+ return { dExtAvlWithdraw, dExtUpnl, dVaUsd, dWalletUsd, dVesuBorrowCapacity, finalVaUsd, finalExtended, isExtendedToVesu: delta < 0 };
44918
+ }
44919
+ _scaleVesuPoolDeltasByFactor(deltas, scale) {
44920
+ if (scale >= 1 - 1e-15) return deltas;
44921
+ return deltas.map((d) => ({
44922
+ ...d,
44923
+ collateralDelta: new Web3Number(
44924
+ (d.collateralDelta.toNumber() * scale).toFixed(COLLATERAL_PRECISION),
44925
+ d.collateralToken.decimals
44926
+ ),
44927
+ debtDelta: new Web3Number(
44928
+ (d.debtDelta.toNumber() * scale).toFixed(USDC_TOKEN_DECIMALS),
44929
+ USDC_TOKEN_DECIMALS
44930
+ )
44931
+ }));
44697
44932
  }
44698
44933
  /**
44699
44934
  * 3. New Deposits / Excess Funds
@@ -44709,6 +44944,11 @@ var ExtendedSVKVesuStateManager = class {
44709
44944
  * Computes allocation split between Vesu and Extended, then sources
44710
44945
  * funds and creates lever-increase routes.
44711
44946
  *
44947
+ * Order: {@link _rebalanceFunds} first → project VA / Extended liquid after the same funding
44948
+ * routes (wallet→VA, borrow→VA, VA→Extended, Extended→wallet→VA) → ideal Vesu/Extended deltas
44949
+ * from distributable split → cap common BTC by min(Vesu fundable, Extended fundable) → scale
44950
+ * Vesu deltas and recompute Extended deltas so both sides stay matched.
44951
+ *
44712
44952
  * Fund flow (single pass — avoid VA→Extended then Extended→wallet round-trips):
44713
44953
  * 1) Treat Vesu borrow headroom that the multiply route will consume as covering
44714
44954
  * part of the Vesu USDC need (no standalone VESU_BORROW for that slice). Cap
@@ -44731,15 +44971,9 @@ var ExtendedSVKVesuStateManager = class {
44731
44971
  withdrawAmount
44732
44972
  );
44733
44973
  if (distributableAmount.toNumber() <= CASE_THRESHOLD_USD) return [];
44734
- const { vesuAllocationUsd, extendedAllocationUsd } = this._computeAllocationSplit(distributableAmount);
44735
- const vesuDeltas = this._computePerPoolCollateralDeltas(
44736
- vesuAllocationUsd
44737
- );
44738
- const extendedPositionDeltas = this._computeExtendedPositionDeltas(vesuDeltas);
44739
- const vesuDepositAmount = this._computeVesuDepositAmount(vesuDeltas);
44740
44974
  const vesuLeverage = calculateVesuLeverage();
44741
44975
  const extendedLeverage = calculateExtendedLevergae();
44742
- const { dExtAvlWithdraw, dExtUpnl, dVaUsd, dWalletUsd, dVesuBorrowCapacity, isExtendedToVesu } = this._rebalanceFunds({
44976
+ const { dExtAvlWithdraw, dExtUpnl, dVaUsd, dWalletUsd, dVesuBorrowCapacity, isExtendedToVesu, finalVaUsd, finalExtended } = this._rebalanceFunds({
44743
44977
  extAvlWithdraw: this._budget.extAvailWithdraw,
44744
44978
  extUpnl: this._budget.extAvailUpnl,
44745
44979
  vaUsd: this._budget.vaUsd,
@@ -44748,6 +44982,23 @@ var ExtendedSVKVesuStateManager = class {
44748
44982
  vesuLeverage,
44749
44983
  extendedLeverage
44750
44984
  });
44985
+ logger.info(`${this._tag}::_classifyDeposits dExtAvlWithdraw=${dExtAvlWithdraw}, dExtUpnl=${dExtUpnl}, dVaUsd=${dVaUsd}, dWalletUsd=${dWalletUsd}, dVesuBorrowCapacity=${dVesuBorrowCapacity}, isExtendedToVesu=${isExtendedToVesu}, finalVaUsd=${finalVaUsd}`);
44986
+ let vesuDeltas = this._computePerPoolCollateralDeltas(new Web3Number(finalVaUsd.toFixed(USDC_TOKEN_DECIMALS), USDC_TOKEN_DECIMALS));
44987
+ const collateralPrice = this._budget.vesuPools[0]?.collateralPrice ?? 0;
44988
+ const collateralDecimals = this._budget.vesuPools[0]?.collateralToken.decimals ?? 0;
44989
+ let _extendedPositionDelta = new Web3Number((finalExtended * extendedLeverage / collateralPrice).toFixed(USDC_TOKEN_DECIMALS), collateralDecimals).toFixedRoundDown(COLLATERAL_PRECISION);
44990
+ logger.info(`${this._tag}::_classifyDeposits extendedPositionDelta=${_extendedPositionDelta}`);
44991
+ logger.info(`${this._tag}::_classifyDeposits vesuDeltas=${JSON.stringify(vesuDeltas)}`);
44992
+ assert(vesuDeltas.length == 1, "vesuDeltas should have only one delta");
44993
+ const minPositionDelta = Math.min(vesuDeltas[0].collateralDelta.toNumber(), Number(_extendedPositionDelta));
44994
+ logger.info(`${this._tag}::_classifyDeposits minPositionDelta=${minPositionDelta}`);
44995
+ vesuDeltas[0].collateralDelta = new Web3Number(minPositionDelta.toFixed(COLLATERAL_PRECISION), vesuDeltas[0].collateralDelta.decimals);
44996
+ const extendedPositionDeltas = [{
44997
+ instrument: this._config.extendedAdapter.config.extendedMarketName ?? "BTC-USD",
44998
+ delta: new Web3Number(minPositionDelta.toFixed(COLLATERAL_PRECISION), collateralDecimals)
44999
+ }];
45000
+ const vesuDepositAmount = this._computeVesuDepositAmount(vesuDeltas);
45001
+ logger.info(`${this._tag}::_classifyDeposits vesuDepositAmount=${vesuDepositAmount}`);
44751
45002
  const routes = [];
44752
45003
  if (isExtendedToVesu) {
44753
45004
  if (dExtUpnl < 0) {
@@ -44775,13 +45026,6 @@ var ExtendedSVKVesuStateManager = class {
44775
45026
  }
44776
45027
  for (const vesuDelta of vesuDeltas) {
44777
45028
  if (!skipAvnuDepositSwap && vesuDepositAmount.toNumber() > CASE_THRESHOLD_USD) {
44778
- routes.push({
44779
- type: "AVNU_DEPOSIT_SWAP" /* AVNU_DEPOSIT_SWAP */,
44780
- priority: routes.length,
44781
- fromToken: vesuDelta.collateralToken.symbol,
44782
- fromAmount: vesuDepositAmount,
44783
- toToken: vesuDelta.debtToken.symbol
44784
- });
44785
45029
  }
44786
45030
  if (vesuDelta.collateralDelta.toNumber() > 0) {
44787
45031
  const availableBorrowCapacity = this._budget.vesuBorrowCapacity;
@@ -45761,14 +46005,6 @@ var _ExecutionService = class _ExecutionService {
45761
46005
  );
45762
46006
  return this._executeStandardCase(caseEntry, activeRoutes);
45763
46007
  }
45764
- const setLevResult = await this._config.extendedAdapter.setLeverage(calculateExtendedLevergae().toString(), this._config.extendedAdapter.config.extendedMarketName);
45765
- if (!setLevResult) {
45766
- logger.error(
45767
- `${this._tag}::_executeCoordinatedCase failed to set leverage`
45768
- );
45769
- results.push(this._failureResult(extendedRoute));
45770
- return results;
45771
- }
45772
46008
  const isIncrease = _ExecutionService.INCREASE_EXPOSURE_ROUTES.has(
45773
46009
  extendedRoute.type
45774
46010
  );
@@ -45789,8 +46025,9 @@ var _ExecutionService = class _ExecutionService {
45789
46025
  onChainCalls = callArrays.flat();
45790
46026
  } catch (err) {
45791
46027
  logger.error(
45792
- `${this._tag}::_executeCoordinatedCase on-chain call construction failed: ${err}`
46028
+ `${this._tag}::_executeCoordinatedCase on-chain call construction failed:`
45793
46029
  );
46030
+ console.error(err);
45794
46031
  await this._emitEvent("FAILURE" /* FAILURE */, {
45795
46032
  routeSummary: `coordinated on-chain build for case "${caseEntry.case.id}"`,
45796
46033
  error: `${err}`
@@ -45862,7 +46099,7 @@ var _ExecutionService = class _ExecutionService {
45862
46099
  }
45863
46100
  const timeoutMs = this._config.extendedFillTimeoutMs ?? DEFAULT_EXTENDED_FILL_TIMEOUT_MS;
45864
46101
  const extResult = await this._executeExtendedLimitOrderWithRecovery(
45865
- btcAmount,
46102
+ Math.abs(btcAmount),
45866
46103
  executionPrice,
45867
46104
  side,
45868
46105
  {
@@ -46390,7 +46627,7 @@ var _ExecutionService = class _ExecutionService {
46390
46627
  return this._failureResult(route);
46391
46628
  }
46392
46629
  const closeResult = await this._executeExtendedLimitOrderWithRecovery(
46393
- positionToClose.toNumber(),
46630
+ Math.abs(positionToClose.toNumber()),
46394
46631
  midPrice,
46395
46632
  "BUY" /* BUY */
46396
46633
  );
@@ -46408,7 +46645,7 @@ var _ExecutionService = class _ExecutionService {
46408
46645
  `${this._tag}::_executeRealisePnl reopening ${positionToClose.toNumber()} on ${route.instrument}`
46409
46646
  );
46410
46647
  const reopenResult = await this._executeExtendedLimitOrderWithRecovery(
46411
- positionToClose.toNumber(),
46648
+ Math.abs(positionToClose.toNumber()),
46412
46649
  midPrice,
46413
46650
  "SELL" /* SELL */
46414
46651
  );
@@ -46462,7 +46699,7 @@ var _ExecutionService = class _ExecutionService {
46462
46699
  return this._failureResult(route);
46463
46700
  }
46464
46701
  const result = await this._executeExtendedLimitOrderWithRecovery(
46465
- route.amount.toNumber(),
46702
+ Math.abs(route.amount.toNumber()),
46466
46703
  midPrice,
46467
46704
  "SELL" /* SELL */
46468
46705
  );
@@ -46510,7 +46747,7 @@ var _ExecutionService = class _ExecutionService {
46510
46747
  return this._failureResult(route);
46511
46748
  }
46512
46749
  const result = await this._executeExtendedLimitOrderWithRecovery(
46513
- route.amount.toNumber(),
46750
+ Math.abs(route.amount.toNumber()),
46514
46751
  midPrice,
46515
46752
  "BUY" /* BUY */
46516
46753
  );
@@ -47133,16 +47370,16 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
47133
47370
  ];
47134
47371
  }
47135
47372
  };
47136
- function getLooperSettings3(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
47373
+ function getLooperSettings3(collateralSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
47137
47374
  vaultSettings.leafAdapters = [];
47138
47375
  const wbtcToken = Global.getDefaultTokens().find(
47139
- (token) => token.symbol === lstSymbol
47376
+ (token) => token.symbol === collateralSymbol
47140
47377
  );
47141
47378
  const usdcToken = Global.getDefaultTokens().find(
47142
47379
  (token) => token.symbol === underlyingSymbol
47143
47380
  );
47144
47381
  const baseAdapterConfig = {
47145
- baseToken: wbtcToken,
47382
+ baseToken: usdcToken,
47146
47383
  supportedPositions: [
47147
47384
  { asset: usdcToken, isDebt: true },
47148
47385
  { asset: wbtcToken, isDebt: false }
@@ -47242,7 +47479,7 @@ function getLooperSettings3(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
47242
47479
  vaultAddress: vaultSettings.vaultAddress,
47243
47480
  vaultAllocator: vaultSettings.vaultAllocator,
47244
47481
  manager: vaultSettings.manager,
47245
- asset: wbtcToken.address
47482
+ asset: usdcToken.address
47246
47483
  });
47247
47484
  vaultSettings.leafAdapters.push(() => vesuMultiplyAdapter.getDepositLeaf());
47248
47485
  vaultSettings.leafAdapters.push(() => vesuMultiplyAdapter.getWithdrawLeaf());
@@ -47376,6 +47613,39 @@ var re7UsdcPrimeDevansh = {
47376
47613
  minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP,
47377
47614
  walletAddress: "0x024b563C1C7d41B32BF4EFB9F38828508a65Be2d6e25268E9f63F22C5e9E51c5"
47378
47615
  };
47616
+ var pureUsdc = {
47617
+ vaultAddress: ContractAddr.from(
47618
+ "0x745c972db65bdee10022fd875dd328c7f40a90849135b6a0f875a40f3c632ae"
47619
+ ),
47620
+ manager: ContractAddr.from(
47621
+ "0x364e0894edefb616ec090f57f5c0274517fcd98ab276ae1f021c5e962fa1deb"
47622
+ ),
47623
+ vaultAllocator: ContractAddr.from(
47624
+ "0x6fceed28e03a96091877568893df0dd89b9bb80fec30da2b742dacbd5526179"
47625
+ ),
47626
+ redeemRequestNFT: ContractAddr.from(
47627
+ "0x501c2b87728e22c6dfcebe4c0b2b3a9fba5845606e4d59fa7bf591badcbb42"
47628
+ ),
47629
+ aumOracle: ContractAddr.from(
47630
+ "0x6ccd95f5765242695d3c75e1440b1d0b30efac8babb864ce15729977b97cb82"
47631
+ ),
47632
+ leafAdapters: [],
47633
+ adapters: [],
47634
+ targetHealthFactor: 1.4,
47635
+ minHealthFactor: 1.35,
47636
+ underlyingToken: Global.getDefaultTokens().find(
47637
+ (token) => token.symbol === "USDC"
47638
+ ),
47639
+ quoteAmountToFetchPrice: new Web3Number(
47640
+ "0.001",
47641
+ Global.getDefaultTokens().find((token) => token.symbol === "USDC").decimals
47642
+ ),
47643
+ borrowable_assets: [
47644
+ Global.getDefaultTokens().find((token) => token.symbol === "USDC")
47645
+ ],
47646
+ minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP,
47647
+ walletAddress: "0x058571C23da5FEdd4e36003FAE3fE2fA9782f2692E552f081839142B10770D0B"
47648
+ };
47379
47649
  var VesuExtendedTestStrategies = (extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) => {
47380
47650
  return [
47381
47651
  getStrategySettingsVesuExtended(
@@ -47392,14 +47662,29 @@ var VesuExtendedTestStrategies = (extendedBackendReadUrl, extendedBackendWriteUr
47392
47662
  minimumExtendedRetriesDelayForOrderStatus,
47393
47663
  minimumExtendedPriceDifferenceForSwapOpen,
47394
47664
  maximumExtendedPriceDifferenceForSwapClosing
47665
+ ),
47666
+ getStrategySettingsVesuExtended(
47667
+ "WBTC",
47668
+ "USDC",
47669
+ pureUsdc,
47670
+ false,
47671
+ false,
47672
+ extendedBackendReadUrl,
47673
+ extendedBackendWriteUrl,
47674
+ vaultIdExtended,
47675
+ minimumExtendedMovementAmount,
47676
+ minimumVesuMovementAmount,
47677
+ minimumExtendedRetriesDelayForOrderStatus,
47678
+ minimumExtendedPriceDifferenceForSwapOpen,
47679
+ maximumExtendedPriceDifferenceForSwapClosing
47395
47680
  )
47396
47681
  ];
47397
47682
  };
47398
- function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
47683
+ function getStrategySettingsVesuExtended(collateralSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
47399
47684
  return {
47400
47685
  id: `extended_${underlyingSymbol.toLowerCase()}_test`,
47401
47686
  name: `Extended Test ${underlyingSymbol}`,
47402
- description: getDescription3(lstSymbol, underlyingSymbol),
47687
+ description: getDescription3(collateralSymbol, underlyingSymbol),
47403
47688
  address: addresses.vaultAddress,
47404
47689
  launchBlock: 0,
47405
47690
  type: "Other",
@@ -47413,7 +47698,7 @@ function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses,
47413
47698
  )
47414
47699
  ],
47415
47700
  additionalInfo: getLooperSettings3(
47416
- lstSymbol,
47701
+ collateralSymbol,
47417
47702
  underlyingSymbol,
47418
47703
  addresses,
47419
47704
  VesuPools.Re7USDCPrime,
@@ -47434,8 +47719,8 @@ function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses,
47434
47719
  auditUrl: AUDIT_URL4,
47435
47720
  protocols: [Protocols.ENDUR, Protocols.VESU],
47436
47721
  contractDetails: getContractDetails(addresses),
47437
- faqs: getFAQs2(lstSymbol, underlyingSymbol, isLST),
47438
- investmentSteps: getInvestmentSteps(lstSymbol, underlyingSymbol),
47722
+ faqs: getFAQs2(collateralSymbol, underlyingSymbol, isLST),
47723
+ investmentSteps: getInvestmentSteps(collateralSymbol, underlyingSymbol),
47439
47724
  isPreview,
47440
47725
  apyMethodology: isLST ? "Current annualized APY in terms of base asset of the LST. There is no additional fee taken by Troves on LST APY. We charge a 10% performance fee on the additional gain which is already accounted in the APY shown." : "Current annualized APY in terms of base asset of the Yield Token. There is no additional fee taken by Troves on yield token APY. We charge a 10% performance fee on the additional gain which is already accounted in the APY shown.",
47441
47726
  security: {