@strkfarm/sdk 1.0.40 → 1.0.42

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.
@@ -38168,6 +38168,19 @@ var strkfarm_risk_engine = (() => {
38168
38168
  };
38169
38169
  return swapInfo;
38170
38170
  }
38171
+ static buildZeroSwap(tokenToSell, address) {
38172
+ return {
38173
+ token_from_address: tokenToSell.address,
38174
+ token_from_amount: uint256_exports.bnToUint256(0),
38175
+ token_to_address: tokenToSell.address,
38176
+ token_to_amount: uint256_exports.bnToUint256(0),
38177
+ token_to_min_amount: uint256_exports.bnToUint256(0),
38178
+ beneficiary: address,
38179
+ integrator_fee_amount_bps: 0,
38180
+ integrator_fee_recipient: address,
38181
+ routes: []
38182
+ };
38183
+ }
38171
38184
  };
38172
38185
 
38173
38186
  // src/interfaces/common.ts
@@ -54789,7 +54802,10 @@ var strkfarm_risk_engine = (() => {
54789
54802
  const priceNow = await this.getCurrentPrice(blockIdentifier);
54790
54803
  let blockNow = typeof blockIdentifier == "number" ? blockIdentifier : (await this.config.provider.getBlockLatestAccepted()).block_number;
54791
54804
  const blockNowTime = typeof blockIdentifier == "number" ? (await this.config.provider.getBlockWithTxs(blockIdentifier)).timestamp : (/* @__PURE__ */ new Date()).getTime() / 1e3;
54792
- const blockBefore = Math.max(blockNow - sinceBlocks, this.metadata.launchBlock);
54805
+ const blockBefore = Math.max(
54806
+ blockNow - sinceBlocks,
54807
+ this.metadata.launchBlock
54808
+ );
54793
54809
  const adjustedSupplyNow = supplyNow.minus(
54794
54810
  await this.getHarvestRewardShares(blockBefore, blockNow)
54795
54811
  );
@@ -55182,14 +55198,24 @@ var strkfarm_risk_engine = (() => {
55182
55198
  _solveExpectedAmountsEq(availableAmount0, availableAmount1, ratio, price) {
55183
55199
  const y = ratio.multipliedBy(availableAmount1).minus(availableAmount0).dividedBy(ratio.plus(1 / price));
55184
55200
  const x = y.dividedBy(price);
55201
+ logger.verbose(
55202
+ `${_EkuboCLVault.name}: _solveExpectedAmountsEq => x: ${x.toString()}, y: ${y.toString()}, amount0: ${availableAmount0.toString()}, amount1: ${availableAmount1.toString()}`
55203
+ );
55204
+ if (ratio.eq(0)) {
55205
+ return {
55206
+ amount0: Web3Number.fromWei("0", availableAmount0.decimals),
55207
+ amount1: availableAmount1.minus(y),
55208
+ ratio: 0
55209
+ };
55210
+ }
55185
55211
  return {
55186
55212
  amount0: availableAmount0.plus(x),
55187
55213
  amount1: availableAmount1.minus(y),
55188
55214
  ratio: Number(ratio.toString())
55189
55215
  };
55190
55216
  }
55191
- async getSwapInfoToHandleUnused(considerRebalance = true) {
55192
- const poolKey = await this.getPoolKey();
55217
+ async unusedBalances(_poolKey) {
55218
+ const poolKey = _poolKey || await this.getPoolKey();
55193
55219
  const erc20Mod = new ERC20(this.config);
55194
55220
  const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
55195
55221
  const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
@@ -55210,11 +55236,24 @@ var strkfarm_risk_engine = (() => {
55210
55236
  const token1Price = await this.pricer.getPrice(token1Info.symbol);
55211
55237
  const token0PriceUsd = token0Price.price * Number(token0Bal1.toFixed(13));
55212
55238
  const token1PriceUsd = token1Price.price * Number(token1Bal1.toFixed(13));
55213
- if (token0PriceUsd > 1 && token1PriceUsd > 1) {
55214
- throw new Error(
55215
- "Both tokens are non-zero and above $1, call handle_fees first"
55216
- );
55217
- }
55239
+ return {
55240
+ token0: {
55241
+ amount: token0Bal1,
55242
+ tokenInfo: token0Info,
55243
+ usdValue: token0PriceUsd
55244
+ },
55245
+ token1: {
55246
+ amount: token1Bal1,
55247
+ tokenInfo: token1Info,
55248
+ usdValue: token1PriceUsd
55249
+ }
55250
+ };
55251
+ }
55252
+ async getSwapInfoToHandleUnused(considerRebalance = true) {
55253
+ const poolKey = await this.getPoolKey();
55254
+ const unusedBalances = await this.unusedBalances(poolKey);
55255
+ const { amount: token0Bal1, usdValue: token0PriceUsd } = unusedBalances.token0;
55256
+ const { amount: token1Bal1, usdValue: token1PriceUsd } = unusedBalances.token1;
55218
55257
  let token0Bal = token0Bal1;
55219
55258
  let token1Bal = token1Bal1;
55220
55259
  if (considerRebalance) {
@@ -55232,63 +55271,71 @@ var strkfarm_risk_engine = (() => {
55232
55271
  logger.verbose(
55233
55272
  `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => token0Bal: ${token0Bal.toString()}, token1Bal: ${token1Bal.toString()}`
55234
55273
  );
55235
- const newBounds = await this.getNewBounds();
55274
+ let ekuboBounds;
55275
+ if (considerRebalance) {
55276
+ ekuboBounds = await this.getNewBounds();
55277
+ } else {
55278
+ ekuboBounds = await this.getCurrentBounds();
55279
+ }
55236
55280
  logger.verbose(
55237
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => newBounds: ${newBounds.lowerTick}, ${newBounds.upperTick}`
55281
+ `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => newBounds: ${ekuboBounds.lowerTick}, ${ekuboBounds.upperTick}`
55238
55282
  );
55239
55283
  return await this.getSwapInfoGivenAmounts(
55240
55284
  poolKey,
55241
55285
  token0Bal,
55242
55286
  token1Bal,
55243
- newBounds
55287
+ ekuboBounds
55244
55288
  );
55245
55289
  }
55246
55290
  async getSwapInfoGivenAmounts(poolKey, token0Bal, token1Bal, bounds) {
55291
+ logger.verbose(
55292
+ `${_EkuboCLVault.name}: getSwapInfoGivenAmounts::pre => token0Bal: ${token0Bal.toString()}, token1Bal: ${token1Bal.toString()}`
55293
+ );
55247
55294
  let expectedAmounts = await this._getExpectedAmountsForLiquidity(
55248
55295
  token0Bal,
55249
55296
  token1Bal,
55250
55297
  bounds
55251
55298
  );
55252
55299
  logger.verbose(
55253
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => expectedAmounts: ${expectedAmounts.amount0.toString()}, ${expectedAmounts.amount1.toString()}`
55300
+ `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => expectedAmounts2: ${expectedAmounts.amount0.toString()}, ${expectedAmounts.amount1.toString()}`
55254
55301
  );
55255
55302
  let retry = 0;
55256
55303
  const maxRetry = 10;
55257
- while (retry < maxRetry) {
55258
- retry++;
55259
- if (expectedAmounts.amount0.lessThan(token0Bal) && expectedAmounts.amount1.lessThan(token1Bal)) {
55304
+ function assertValidAmounts(expectedAmounts2, token0Bal2, token1Bal2) {
55305
+ if (expectedAmounts2.amount0.lessThan(token0Bal2) && expectedAmounts2.amount1.lessThan(token1Bal2)) {
55260
55306
  throw new Error("Both tokens are decreased, something is wrong");
55261
55307
  }
55262
- if (expectedAmounts.amount0.greaterThan(token0Bal) && expectedAmounts.amount1.greaterThan(token1Bal)) {
55308
+ if (expectedAmounts2.amount0.greaterThan(token0Bal2) && expectedAmounts2.amount1.greaterThan(token1Bal2)) {
55263
55309
  throw new Error("Both tokens are increased, something is wrong");
55264
55310
  }
55265
- const tokenToSell = expectedAmounts.amount0.lessThan(token0Bal) ? poolKey.token0 : poolKey.token1;
55266
- const tokenToBuy = tokenToSell == poolKey.token0 ? poolKey.token1 : poolKey.token0;
55267
- let amountToSell = tokenToSell == poolKey.token0 ? token0Bal.minus(expectedAmounts.amount0) : token1Bal.minus(expectedAmounts.amount1);
55268
- const remainingSellAmount = tokenToSell == poolKey.token0 ? expectedAmounts.amount0 : expectedAmounts.amount1;
55269
- const tokenToBuyInfo = await Global.getTokenInfoFromAddr(tokenToBuy);
55270
- const expectedRatio = expectedAmounts.ratio;
55271
- logger.verbose(
55272
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => tokenToSell: ${tokenToSell.address}, tokenToBuy: ${tokenToBuy.address}, amountToSell: ${amountToSell.toWei()}`
55273
- );
55311
+ }
55312
+ function getSwapParams(expectedAmounts2, poolKey2, token0Bal2, token1Bal2) {
55313
+ const tokenToSell = expectedAmounts2.amount0.lessThan(token0Bal2) ? poolKey2.token0 : poolKey2.token1;
55314
+ const tokenToBuy = tokenToSell == poolKey2.token0 ? poolKey2.token1 : poolKey2.token0;
55315
+ const amountToSell = tokenToSell == poolKey2.token0 ? token0Bal2.minus(expectedAmounts2.amount0) : token1Bal2.minus(expectedAmounts2.amount1);
55316
+ const remainingSellAmount = tokenToSell == poolKey2.token0 ? expectedAmounts2.amount0 : expectedAmounts2.amount1;
55317
+ return { tokenToSell, tokenToBuy, amountToSell, remainingSellAmount };
55318
+ }
55319
+ while (retry < maxRetry) {
55320
+ retry++;
55274
55321
  logger.verbose(
55275
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => remainingSellAmount: ${remainingSellAmount.toString()}`
55322
+ `getSwapInfoGivenAmounts::Retry attempt: ${retry}/${maxRetry}`
55276
55323
  );
55324
+ assertValidAmounts(expectedAmounts, token0Bal, token1Bal);
55325
+ const { tokenToSell, tokenToBuy, amountToSell, remainingSellAmount } = getSwapParams(expectedAmounts, poolKey, token0Bal, token1Bal);
55326
+ const tokenToBuyInfo = await Global.getTokenInfoFromAddr(tokenToBuy);
55327
+ const expectedRatio = expectedAmounts.ratio;
55277
55328
  logger.verbose(
55278
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => expectedRatio: ${expectedRatio}`
55329
+ `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => iteration info: ${JSON.stringify({
55330
+ tokenToSell: tokenToSell.address,
55331
+ tokenToBuy: tokenToBuy.address,
55332
+ amountToSell: amountToSell.toString(),
55333
+ remainingSellAmount: remainingSellAmount.toString(),
55334
+ expectedRatio
55335
+ })}`
55279
55336
  );
55280
55337
  if (amountToSell.eq(0)) {
55281
- return {
55282
- token_from_address: tokenToSell.address,
55283
- token_from_amount: uint256_exports.bnToUint256(0),
55284
- token_to_address: tokenToSell.address,
55285
- token_to_amount: uint256_exports.bnToUint256(0),
55286
- token_to_min_amount: uint256_exports.bnToUint256(0),
55287
- beneficiary: this.address.address,
55288
- integrator_fee_amount_bps: 0,
55289
- integrator_fee_recipient: this.address.address,
55290
- routes: []
55291
- };
55338
+ return AvnuWrapper.buildZeroSwap(tokenToSell, this.address.address);
55292
55339
  }
55293
55340
  const quote = await this.avnu.getQuotes(
55294
55341
  tokenToSell.address,
@@ -55316,15 +55363,14 @@ var strkfarm_risk_engine = (() => {
55316
55363
  const swapPrice = tokenToSell == poolKey.token0 ? amountOut.dividedBy(amountToSell) : amountToSell.dividedBy(amountOut);
55317
55364
  const newRatio = tokenToSell == poolKey.token0 ? remainingSellAmount.dividedBy(token1Bal.plus(amountOut)) : token0Bal.plus(amountOut).dividedBy(remainingSellAmount);
55318
55365
  logger.verbose(
55319
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => amountOut: ${amountOut.toString()}`
55366
+ `${_EkuboCLVault.name} getSwapInfoToHandleUnused => iter post calc: ${JSON.stringify({
55367
+ amountOut: amountOut.toString(),
55368
+ swapPrice: swapPrice.toString(),
55369
+ newRatio: newRatio.toString()
55370
+ })}`
55320
55371
  );
55321
- logger.verbose(
55322
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => swapPrice: ${swapPrice.toString()}`
55323
- );
55324
- logger.verbose(
55325
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => newRatio: ${newRatio.toString()}`
55326
- );
55327
- if (Number(newRatio.toString()) > expectedRatio * 1.0000001 || Number(newRatio.toString()) < expectedRatio * 0.9999999) {
55372
+ const expectedPrecision = Math.min(7, tokenToBuyInfo.decimals - 2);
55373
+ if (Number(newRatio.toString()) > expectedRatio * (1 + 1 / 10 ** expectedPrecision) || Number(newRatio.toString()) < expectedRatio * (1 - 1 / 10 ** expectedPrecision)) {
55328
55374
  expectedAmounts = await this._solveExpectedAmountsEq(
55329
55375
  token0Bal,
55330
55376
  token1Bal,
@@ -55523,6 +55569,9 @@ var strkfarm_risk_engine = (() => {
55523
55569
  const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
55524
55570
  const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
55525
55571
  const bounds = await this.getCurrentBounds();
55572
+ logger.verbose(
55573
+ `${_EkuboCLVault.name}: harvest => unClaimedRewards: ${unClaimedRewards.length}`
55574
+ );
55526
55575
  const calls = [];
55527
55576
  for (let claim of unClaimedRewards) {
55528
55577
  const fee = claim.claim.amount.multipliedBy(this.metadata.additionalInfo.feeBps).dividedBy(1e4);
@@ -55555,12 +55604,28 @@ var strkfarm_risk_engine = (() => {
55555
55604
  18
55556
55605
  // cause its always STRK?
55557
55606
  );
55607
+ logger.verbose(
55608
+ `${_EkuboCLVault.name}: harvest => swap1Amount: ${swap1Amount}`
55609
+ );
55558
55610
  const remainingAmount = postFeeAmount.minus(swap1Amount);
55611
+ logger.verbose(
55612
+ `${_EkuboCLVault.name}: harvest => remainingAmount: ${remainingAmount}`
55613
+ );
55559
55614
  const swapInfo2 = {
55560
55615
  ...swapInfo,
55561
55616
  token_from_amount: uint256_exports.bnToUint256(remainingAmount.toWei())
55562
55617
  };
55563
55618
  swapInfo2.token_to_address = token1Info.address.address;
55619
+ logger.verbose(
55620
+ `${_EkuboCLVault.name}: harvest => swapInfo: ${JSON.stringify(
55621
+ swapInfo
55622
+ )}`
55623
+ );
55624
+ logger.verbose(
55625
+ `${_EkuboCLVault.name}: harvest => swapInfo2: ${JSON.stringify(
55626
+ swapInfo2
55627
+ )}`
55628
+ );
55564
55629
  const calldata = [
55565
55630
  claim.rewardsContract.address,
55566
55631
  {
@@ -55664,8 +55729,16 @@ var strkfarm_risk_engine = (() => {
55664
55729
  {
55665
55730
  question: "Is the strategy audited?",
55666
55731
  answer: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
55667
- "Yes, the strategy has been audited. You can review the audit report in our docs ",
55668
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { href: "https://docs.strkfarm.com/p/ekubo-cl-vaults#technical-details", style: { textDecoration: "underline", marginLeft: "5px" }, children: "Here" }),
55732
+ "Yes, the strategy has been audited. You can review the audit report in our docs",
55733
+ " ",
55734
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
55735
+ "a",
55736
+ {
55737
+ href: "https://docs.strkfarm.com/p/ekubo-cl-vaults#technical-details",
55738
+ style: { textDecoration: "underline", marginLeft: "5px" },
55739
+ children: "Here"
55740
+ }
55741
+ ),
55669
55742
  "."
55670
55743
  ] })
55671
55744
  }
@@ -55717,7 +55790,12 @@ var strkfarm_risk_engine = (() => {
55717
55790
  lstContract: ContractAddr.from(
55718
55791
  "0x028d709c875c0ceac3dce7065bec5328186dc89fe254527084d1689910954b0a"
55719
55792
  ),
55720
- feeBps: 1e3
55793
+ feeBps: 1e3,
55794
+ rebalanceConditions: {
55795
+ customShouldRebalance: async (currentPrice) => true,
55796
+ minWaitHours: 24,
55797
+ direction: "uponly"
55798
+ }
55721
55799
  },
55722
55800
  faqs: [
55723
55801
  ...faqs2,
@@ -55758,7 +55836,10 @@ var strkfarm_risk_engine = (() => {
55758
55836
  maxTVL: Web3Number.fromWei("0", 6),
55759
55837
  risk: {
55760
55838
  riskFactor: _riskFactorStable,
55761
- netRisk: _riskFactorStable.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactorStable.reduce((acc, curr) => acc + curr.weight, 0),
55839
+ netRisk: _riskFactorStable.reduce(
55840
+ (acc, curr) => acc + curr.value * curr.weight,
55841
+ 0
55842
+ ) / _riskFactorStable.reduce((acc, curr) => acc + curr.weight, 0),
55762
55843
  notARisks: getNoRiskTags(_riskFactorStable)
55763
55844
  },
55764
55845
  apyMethodology: "APY based on 7-day historical performance, including fees and rewards.",
@@ -55768,11 +55849,14 @@ var strkfarm_risk_engine = (() => {
55768
55849
  upper: 1
55769
55850
  },
55770
55851
  truePrice: 1,
55771
- feeBps: 1e3
55852
+ feeBps: 1e3,
55853
+ rebalanceConditions: {
55854
+ customShouldRebalance: async (currentPrice) => currentPrice > 0.99 && currentPrice < 1.01,
55855
+ minWaitHours: 6,
55856
+ direction: "any"
55857
+ }
55772
55858
  },
55773
- faqs: [
55774
- ...faqs2
55775
- ]
55859
+ faqs: [...faqs2]
55776
55860
  }
55777
55861
  ];
55778
55862
  return __toCommonJS(index_browser_exports);
@@ -1948,6 +1948,19 @@ var AvnuWrapper = class _AvnuWrapper {
1948
1948
  };
1949
1949
  return swapInfo;
1950
1950
  }
1951
+ static buildZeroSwap(tokenToSell, address) {
1952
+ return {
1953
+ token_from_address: tokenToSell.address,
1954
+ token_from_amount: uint256.bnToUint256(0),
1955
+ token_to_address: tokenToSell.address,
1956
+ token_to_amount: uint256.bnToUint256(0),
1957
+ token_to_min_amount: uint256.bnToUint256(0),
1958
+ beneficiary: address,
1959
+ integrator_fee_amount_bps: 0,
1960
+ integrator_fee_recipient: address,
1961
+ routes: []
1962
+ };
1963
+ }
1951
1964
  };
1952
1965
 
1953
1966
  // src/interfaces/common.ts
@@ -18583,7 +18596,10 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
18583
18596
  const priceNow = await this.getCurrentPrice(blockIdentifier);
18584
18597
  let blockNow = typeof blockIdentifier == "number" ? blockIdentifier : (await this.config.provider.getBlockLatestAccepted()).block_number;
18585
18598
  const blockNowTime = typeof blockIdentifier == "number" ? (await this.config.provider.getBlockWithTxs(blockIdentifier)).timestamp : (/* @__PURE__ */ new Date()).getTime() / 1e3;
18586
- const blockBefore = Math.max(blockNow - sinceBlocks, this.metadata.launchBlock);
18599
+ const blockBefore = Math.max(
18600
+ blockNow - sinceBlocks,
18601
+ this.metadata.launchBlock
18602
+ );
18587
18603
  const adjustedSupplyNow = supplyNow.minus(
18588
18604
  await this.getHarvestRewardShares(blockBefore, blockNow)
18589
18605
  );
@@ -18976,14 +18992,24 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
18976
18992
  _solveExpectedAmountsEq(availableAmount0, availableAmount1, ratio, price) {
18977
18993
  const y = ratio.multipliedBy(availableAmount1).minus(availableAmount0).dividedBy(ratio.plus(1 / price));
18978
18994
  const x = y.dividedBy(price);
18995
+ logger.verbose(
18996
+ `${_EkuboCLVault.name}: _solveExpectedAmountsEq => x: ${x.toString()}, y: ${y.toString()}, amount0: ${availableAmount0.toString()}, amount1: ${availableAmount1.toString()}`
18997
+ );
18998
+ if (ratio.eq(0)) {
18999
+ return {
19000
+ amount0: Web3Number.fromWei("0", availableAmount0.decimals),
19001
+ amount1: availableAmount1.minus(y),
19002
+ ratio: 0
19003
+ };
19004
+ }
18979
19005
  return {
18980
19006
  amount0: availableAmount0.plus(x),
18981
19007
  amount1: availableAmount1.minus(y),
18982
19008
  ratio: Number(ratio.toString())
18983
19009
  };
18984
19010
  }
18985
- async getSwapInfoToHandleUnused(considerRebalance = true) {
18986
- const poolKey = await this.getPoolKey();
19011
+ async unusedBalances(_poolKey) {
19012
+ const poolKey = _poolKey || await this.getPoolKey();
18987
19013
  const erc20Mod = new ERC20(this.config);
18988
19014
  const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
18989
19015
  const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
@@ -19004,11 +19030,24 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
19004
19030
  const token1Price = await this.pricer.getPrice(token1Info.symbol);
19005
19031
  const token0PriceUsd = token0Price.price * Number(token0Bal1.toFixed(13));
19006
19032
  const token1PriceUsd = token1Price.price * Number(token1Bal1.toFixed(13));
19007
- if (token0PriceUsd > 1 && token1PriceUsd > 1) {
19008
- throw new Error(
19009
- "Both tokens are non-zero and above $1, call handle_fees first"
19010
- );
19011
- }
19033
+ return {
19034
+ token0: {
19035
+ amount: token0Bal1,
19036
+ tokenInfo: token0Info,
19037
+ usdValue: token0PriceUsd
19038
+ },
19039
+ token1: {
19040
+ amount: token1Bal1,
19041
+ tokenInfo: token1Info,
19042
+ usdValue: token1PriceUsd
19043
+ }
19044
+ };
19045
+ }
19046
+ async getSwapInfoToHandleUnused(considerRebalance = true) {
19047
+ const poolKey = await this.getPoolKey();
19048
+ const unusedBalances = await this.unusedBalances(poolKey);
19049
+ const { amount: token0Bal1, usdValue: token0PriceUsd } = unusedBalances.token0;
19050
+ const { amount: token1Bal1, usdValue: token1PriceUsd } = unusedBalances.token1;
19012
19051
  let token0Bal = token0Bal1;
19013
19052
  let token1Bal = token1Bal1;
19014
19053
  if (considerRebalance) {
@@ -19026,63 +19065,71 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
19026
19065
  logger.verbose(
19027
19066
  `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => token0Bal: ${token0Bal.toString()}, token1Bal: ${token1Bal.toString()}`
19028
19067
  );
19029
- const newBounds = await this.getNewBounds();
19068
+ let ekuboBounds;
19069
+ if (considerRebalance) {
19070
+ ekuboBounds = await this.getNewBounds();
19071
+ } else {
19072
+ ekuboBounds = await this.getCurrentBounds();
19073
+ }
19030
19074
  logger.verbose(
19031
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => newBounds: ${newBounds.lowerTick}, ${newBounds.upperTick}`
19075
+ `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => newBounds: ${ekuboBounds.lowerTick}, ${ekuboBounds.upperTick}`
19032
19076
  );
19033
19077
  return await this.getSwapInfoGivenAmounts(
19034
19078
  poolKey,
19035
19079
  token0Bal,
19036
19080
  token1Bal,
19037
- newBounds
19081
+ ekuboBounds
19038
19082
  );
19039
19083
  }
19040
19084
  async getSwapInfoGivenAmounts(poolKey, token0Bal, token1Bal, bounds) {
19085
+ logger.verbose(
19086
+ `${_EkuboCLVault.name}: getSwapInfoGivenAmounts::pre => token0Bal: ${token0Bal.toString()}, token1Bal: ${token1Bal.toString()}`
19087
+ );
19041
19088
  let expectedAmounts = await this._getExpectedAmountsForLiquidity(
19042
19089
  token0Bal,
19043
19090
  token1Bal,
19044
19091
  bounds
19045
19092
  );
19046
19093
  logger.verbose(
19047
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => expectedAmounts: ${expectedAmounts.amount0.toString()}, ${expectedAmounts.amount1.toString()}`
19094
+ `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => expectedAmounts2: ${expectedAmounts.amount0.toString()}, ${expectedAmounts.amount1.toString()}`
19048
19095
  );
19049
19096
  let retry = 0;
19050
19097
  const maxRetry = 10;
19051
- while (retry < maxRetry) {
19052
- retry++;
19053
- if (expectedAmounts.amount0.lessThan(token0Bal) && expectedAmounts.amount1.lessThan(token1Bal)) {
19098
+ function assertValidAmounts(expectedAmounts2, token0Bal2, token1Bal2) {
19099
+ if (expectedAmounts2.amount0.lessThan(token0Bal2) && expectedAmounts2.amount1.lessThan(token1Bal2)) {
19054
19100
  throw new Error("Both tokens are decreased, something is wrong");
19055
19101
  }
19056
- if (expectedAmounts.amount0.greaterThan(token0Bal) && expectedAmounts.amount1.greaterThan(token1Bal)) {
19102
+ if (expectedAmounts2.amount0.greaterThan(token0Bal2) && expectedAmounts2.amount1.greaterThan(token1Bal2)) {
19057
19103
  throw new Error("Both tokens are increased, something is wrong");
19058
19104
  }
19059
- const tokenToSell = expectedAmounts.amount0.lessThan(token0Bal) ? poolKey.token0 : poolKey.token1;
19060
- const tokenToBuy = tokenToSell == poolKey.token0 ? poolKey.token1 : poolKey.token0;
19061
- let amountToSell = tokenToSell == poolKey.token0 ? token0Bal.minus(expectedAmounts.amount0) : token1Bal.minus(expectedAmounts.amount1);
19062
- const remainingSellAmount = tokenToSell == poolKey.token0 ? expectedAmounts.amount0 : expectedAmounts.amount1;
19063
- const tokenToBuyInfo = await Global.getTokenInfoFromAddr(tokenToBuy);
19064
- const expectedRatio = expectedAmounts.ratio;
19065
- logger.verbose(
19066
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => tokenToSell: ${tokenToSell.address}, tokenToBuy: ${tokenToBuy.address}, amountToSell: ${amountToSell.toWei()}`
19067
- );
19105
+ }
19106
+ function getSwapParams(expectedAmounts2, poolKey2, token0Bal2, token1Bal2) {
19107
+ const tokenToSell = expectedAmounts2.amount0.lessThan(token0Bal2) ? poolKey2.token0 : poolKey2.token1;
19108
+ const tokenToBuy = tokenToSell == poolKey2.token0 ? poolKey2.token1 : poolKey2.token0;
19109
+ const amountToSell = tokenToSell == poolKey2.token0 ? token0Bal2.minus(expectedAmounts2.amount0) : token1Bal2.minus(expectedAmounts2.amount1);
19110
+ const remainingSellAmount = tokenToSell == poolKey2.token0 ? expectedAmounts2.amount0 : expectedAmounts2.amount1;
19111
+ return { tokenToSell, tokenToBuy, amountToSell, remainingSellAmount };
19112
+ }
19113
+ while (retry < maxRetry) {
19114
+ retry++;
19068
19115
  logger.verbose(
19069
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => remainingSellAmount: ${remainingSellAmount.toString()}`
19116
+ `getSwapInfoGivenAmounts::Retry attempt: ${retry}/${maxRetry}`
19070
19117
  );
19118
+ assertValidAmounts(expectedAmounts, token0Bal, token1Bal);
19119
+ const { tokenToSell, tokenToBuy, amountToSell, remainingSellAmount } = getSwapParams(expectedAmounts, poolKey, token0Bal, token1Bal);
19120
+ const tokenToBuyInfo = await Global.getTokenInfoFromAddr(tokenToBuy);
19121
+ const expectedRatio = expectedAmounts.ratio;
19071
19122
  logger.verbose(
19072
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => expectedRatio: ${expectedRatio}`
19123
+ `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => iteration info: ${JSON.stringify({
19124
+ tokenToSell: tokenToSell.address,
19125
+ tokenToBuy: tokenToBuy.address,
19126
+ amountToSell: amountToSell.toString(),
19127
+ remainingSellAmount: remainingSellAmount.toString(),
19128
+ expectedRatio
19129
+ })}`
19073
19130
  );
19074
19131
  if (amountToSell.eq(0)) {
19075
- return {
19076
- token_from_address: tokenToSell.address,
19077
- token_from_amount: uint2564.bnToUint256(0),
19078
- token_to_address: tokenToSell.address,
19079
- token_to_amount: uint2564.bnToUint256(0),
19080
- token_to_min_amount: uint2564.bnToUint256(0),
19081
- beneficiary: this.address.address,
19082
- integrator_fee_amount_bps: 0,
19083
- integrator_fee_recipient: this.address.address,
19084
- routes: []
19085
- };
19132
+ return AvnuWrapper.buildZeroSwap(tokenToSell, this.address.address);
19086
19133
  }
19087
19134
  const quote = await this.avnu.getQuotes(
19088
19135
  tokenToSell.address,
@@ -19110,15 +19157,14 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
19110
19157
  const swapPrice = tokenToSell == poolKey.token0 ? amountOut.dividedBy(amountToSell) : amountToSell.dividedBy(amountOut);
19111
19158
  const newRatio = tokenToSell == poolKey.token0 ? remainingSellAmount.dividedBy(token1Bal.plus(amountOut)) : token0Bal.plus(amountOut).dividedBy(remainingSellAmount);
19112
19159
  logger.verbose(
19113
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => amountOut: ${amountOut.toString()}`
19160
+ `${_EkuboCLVault.name} getSwapInfoToHandleUnused => iter post calc: ${JSON.stringify({
19161
+ amountOut: amountOut.toString(),
19162
+ swapPrice: swapPrice.toString(),
19163
+ newRatio: newRatio.toString()
19164
+ })}`
19114
19165
  );
19115
- logger.verbose(
19116
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => swapPrice: ${swapPrice.toString()}`
19117
- );
19118
- logger.verbose(
19119
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => newRatio: ${newRatio.toString()}`
19120
- );
19121
- if (Number(newRatio.toString()) > expectedRatio * 1.0000001 || Number(newRatio.toString()) < expectedRatio * 0.9999999) {
19166
+ const expectedPrecision = Math.min(7, tokenToBuyInfo.decimals - 2);
19167
+ if (Number(newRatio.toString()) > expectedRatio * (1 + 1 / 10 ** expectedPrecision) || Number(newRatio.toString()) < expectedRatio * (1 - 1 / 10 ** expectedPrecision)) {
19122
19168
  expectedAmounts = await this._solveExpectedAmountsEq(
19123
19169
  token0Bal,
19124
19170
  token1Bal,
@@ -19317,6 +19363,9 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
19317
19363
  const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
19318
19364
  const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
19319
19365
  const bounds = await this.getCurrentBounds();
19366
+ logger.verbose(
19367
+ `${_EkuboCLVault.name}: harvest => unClaimedRewards: ${unClaimedRewards.length}`
19368
+ );
19320
19369
  const calls = [];
19321
19370
  for (let claim of unClaimedRewards) {
19322
19371
  const fee = claim.claim.amount.multipliedBy(this.metadata.additionalInfo.feeBps).dividedBy(1e4);
@@ -19349,12 +19398,28 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
19349
19398
  18
19350
19399
  // cause its always STRK?
19351
19400
  );
19401
+ logger.verbose(
19402
+ `${_EkuboCLVault.name}: harvest => swap1Amount: ${swap1Amount}`
19403
+ );
19352
19404
  const remainingAmount = postFeeAmount.minus(swap1Amount);
19405
+ logger.verbose(
19406
+ `${_EkuboCLVault.name}: harvest => remainingAmount: ${remainingAmount}`
19407
+ );
19353
19408
  const swapInfo2 = {
19354
19409
  ...swapInfo,
19355
19410
  token_from_amount: uint2564.bnToUint256(remainingAmount.toWei())
19356
19411
  };
19357
19412
  swapInfo2.token_to_address = token1Info.address.address;
19413
+ logger.verbose(
19414
+ `${_EkuboCLVault.name}: harvest => swapInfo: ${JSON.stringify(
19415
+ swapInfo
19416
+ )}`
19417
+ );
19418
+ logger.verbose(
19419
+ `${_EkuboCLVault.name}: harvest => swapInfo2: ${JSON.stringify(
19420
+ swapInfo2
19421
+ )}`
19422
+ );
19358
19423
  const calldata = [
19359
19424
  claim.rewardsContract.address,
19360
19425
  {
@@ -19458,8 +19523,16 @@ var faqs2 = [
19458
19523
  {
19459
19524
  question: "Is the strategy audited?",
19460
19525
  answer: /* @__PURE__ */ jsxs2("div", { children: [
19461
- "Yes, the strategy has been audited. You can review the audit report in our docs ",
19462
- /* @__PURE__ */ jsx2("a", { href: "https://docs.strkfarm.com/p/ekubo-cl-vaults#technical-details", style: { textDecoration: "underline", marginLeft: "5px" }, children: "Here" }),
19526
+ "Yes, the strategy has been audited. You can review the audit report in our docs",
19527
+ " ",
19528
+ /* @__PURE__ */ jsx2(
19529
+ "a",
19530
+ {
19531
+ href: "https://docs.strkfarm.com/p/ekubo-cl-vaults#technical-details",
19532
+ style: { textDecoration: "underline", marginLeft: "5px" },
19533
+ children: "Here"
19534
+ }
19535
+ ),
19463
19536
  "."
19464
19537
  ] })
19465
19538
  }
@@ -19511,7 +19584,12 @@ var EkuboCLVaultStrategies = [
19511
19584
  lstContract: ContractAddr.from(
19512
19585
  "0x028d709c875c0ceac3dce7065bec5328186dc89fe254527084d1689910954b0a"
19513
19586
  ),
19514
- feeBps: 1e3
19587
+ feeBps: 1e3,
19588
+ rebalanceConditions: {
19589
+ customShouldRebalance: async (currentPrice) => true,
19590
+ minWaitHours: 24,
19591
+ direction: "uponly"
19592
+ }
19515
19593
  },
19516
19594
  faqs: [
19517
19595
  ...faqs2,
@@ -19552,7 +19630,10 @@ var EkuboCLVaultStrategies = [
19552
19630
  maxTVL: Web3Number.fromWei("0", 6),
19553
19631
  risk: {
19554
19632
  riskFactor: _riskFactorStable,
19555
- netRisk: _riskFactorStable.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactorStable.reduce((acc, curr) => acc + curr.weight, 0),
19633
+ netRisk: _riskFactorStable.reduce(
19634
+ (acc, curr) => acc + curr.value * curr.weight,
19635
+ 0
19636
+ ) / _riskFactorStable.reduce((acc, curr) => acc + curr.weight, 0),
19556
19637
  notARisks: getNoRiskTags(_riskFactorStable)
19557
19638
  },
19558
19639
  apyMethodology: "APY based on 7-day historical performance, including fees and rewards.",
@@ -19562,11 +19643,14 @@ var EkuboCLVaultStrategies = [
19562
19643
  upper: 1
19563
19644
  },
19564
19645
  truePrice: 1,
19565
- feeBps: 1e3
19646
+ feeBps: 1e3,
19647
+ rebalanceConditions: {
19648
+ customShouldRebalance: async (currentPrice) => currentPrice > 0.99 && currentPrice < 1.01,
19649
+ minWaitHours: 6,
19650
+ direction: "any"
19651
+ }
19566
19652
  },
19567
- faqs: [
19568
- ...faqs2
19569
- ]
19653
+ faqs: [...faqs2]
19570
19654
  }
19571
19655
  ];
19572
19656
  export {
package/dist/index.d.ts CHANGED
@@ -289,6 +289,7 @@ interface SwapInfo {
289
289
  declare class AvnuWrapper {
290
290
  getQuotes(fromToken: string, toToken: string, amountWei: string, taker: string, retry?: number): Promise<Quote>;
291
291
  getSwapInfo(quote: Quote, taker: string, integratorFeeBps: number, integratorFeeRecipient: string, minAmount?: string): Promise<SwapInfo>;
292
+ static buildZeroSwap(tokenToSell: ContractAddr, address: string): SwapInfo;
292
293
  }
293
294
 
294
295
  declare class FatalError extends Error {
@@ -598,6 +599,11 @@ interface CLVaultStrategySettings {
598
599
  lstContract?: ContractAddr;
599
600
  truePrice?: number;
600
601
  feeBps: number;
602
+ rebalanceConditions: {
603
+ minWaitHours: number;
604
+ direction: "any" | "uponly";
605
+ customShouldRebalance: (currentPoolPrice: number) => Promise<boolean>;
606
+ };
601
607
  }
602
608
  declare class EkuboCLVault extends BaseStrategy<DualTokenInfo, DualActionAmount> {
603
609
  /** Contract address of the strategy */
@@ -672,6 +678,18 @@ declare class EkuboCLVault extends BaseStrategy<DualTokenInfo, DualActionAmount>
672
678
  */
673
679
  private _getExpectedAmountsForLiquidity;
674
680
  private _solveExpectedAmountsEq;
681
+ unusedBalances(_poolKey?: EkuboPoolKey): Promise<{
682
+ token0: {
683
+ amount: Web3Number;
684
+ tokenInfo: TokenInfo;
685
+ usdValue: number;
686
+ };
687
+ token1: {
688
+ amount: Web3Number;
689
+ tokenInfo: TokenInfo;
690
+ usdValue: number;
691
+ };
692
+ }>;
675
693
  getSwapInfoToHandleUnused(considerRebalance?: boolean): Promise<SwapInfo>;
676
694
  getSwapInfoGivenAmounts(poolKey: EkuboPoolKey, token0Bal: Web3Number, token1Bal: Web3Number, bounds: EkuboBounds): Promise<SwapInfo>;
677
695
  /**