@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.
package/dist/index.js CHANGED
@@ -2066,6 +2066,19 @@ var AvnuWrapper = class _AvnuWrapper {
2066
2066
  };
2067
2067
  return swapInfo;
2068
2068
  }
2069
+ static buildZeroSwap(tokenToSell, address) {
2070
+ return {
2071
+ token_from_address: tokenToSell.address,
2072
+ token_from_amount: import_starknet4.uint256.bnToUint256(0),
2073
+ token_to_address: tokenToSell.address,
2074
+ token_to_amount: import_starknet4.uint256.bnToUint256(0),
2075
+ token_to_min_amount: import_starknet4.uint256.bnToUint256(0),
2076
+ beneficiary: address,
2077
+ integrator_fee_amount_bps: 0,
2078
+ integrator_fee_recipient: address,
2079
+ routes: []
2080
+ };
2081
+ }
2069
2082
  };
2070
2083
 
2071
2084
  // src/interfaces/common.ts
@@ -18697,7 +18710,10 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
18697
18710
  const priceNow = await this.getCurrentPrice(blockIdentifier);
18698
18711
  let blockNow = typeof blockIdentifier == "number" ? blockIdentifier : (await this.config.provider.getBlockLatestAccepted()).block_number;
18699
18712
  const blockNowTime = typeof blockIdentifier == "number" ? (await this.config.provider.getBlockWithTxs(blockIdentifier)).timestamp : (/* @__PURE__ */ new Date()).getTime() / 1e3;
18700
- const blockBefore = Math.max(blockNow - sinceBlocks, this.metadata.launchBlock);
18713
+ const blockBefore = Math.max(
18714
+ blockNow - sinceBlocks,
18715
+ this.metadata.launchBlock
18716
+ );
18701
18717
  const adjustedSupplyNow = supplyNow.minus(
18702
18718
  await this.getHarvestRewardShares(blockBefore, blockNow)
18703
18719
  );
@@ -19090,14 +19106,24 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
19090
19106
  _solveExpectedAmountsEq(availableAmount0, availableAmount1, ratio, price) {
19091
19107
  const y = ratio.multipliedBy(availableAmount1).minus(availableAmount0).dividedBy(ratio.plus(1 / price));
19092
19108
  const x = y.dividedBy(price);
19109
+ logger.verbose(
19110
+ `${_EkuboCLVault.name}: _solveExpectedAmountsEq => x: ${x.toString()}, y: ${y.toString()}, amount0: ${availableAmount0.toString()}, amount1: ${availableAmount1.toString()}`
19111
+ );
19112
+ if (ratio.eq(0)) {
19113
+ return {
19114
+ amount0: Web3Number.fromWei("0", availableAmount0.decimals),
19115
+ amount1: availableAmount1.minus(y),
19116
+ ratio: 0
19117
+ };
19118
+ }
19093
19119
  return {
19094
19120
  amount0: availableAmount0.plus(x),
19095
19121
  amount1: availableAmount1.minus(y),
19096
19122
  ratio: Number(ratio.toString())
19097
19123
  };
19098
19124
  }
19099
- async getSwapInfoToHandleUnused(considerRebalance = true) {
19100
- const poolKey = await this.getPoolKey();
19125
+ async unusedBalances(_poolKey) {
19126
+ const poolKey = _poolKey || await this.getPoolKey();
19101
19127
  const erc20Mod = new ERC20(this.config);
19102
19128
  const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
19103
19129
  const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
@@ -19118,11 +19144,24 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
19118
19144
  const token1Price = await this.pricer.getPrice(token1Info.symbol);
19119
19145
  const token0PriceUsd = token0Price.price * Number(token0Bal1.toFixed(13));
19120
19146
  const token1PriceUsd = token1Price.price * Number(token1Bal1.toFixed(13));
19121
- if (token0PriceUsd > 1 && token1PriceUsd > 1) {
19122
- throw new Error(
19123
- "Both tokens are non-zero and above $1, call handle_fees first"
19124
- );
19125
- }
19147
+ return {
19148
+ token0: {
19149
+ amount: token0Bal1,
19150
+ tokenInfo: token0Info,
19151
+ usdValue: token0PriceUsd
19152
+ },
19153
+ token1: {
19154
+ amount: token1Bal1,
19155
+ tokenInfo: token1Info,
19156
+ usdValue: token1PriceUsd
19157
+ }
19158
+ };
19159
+ }
19160
+ async getSwapInfoToHandleUnused(considerRebalance = true) {
19161
+ const poolKey = await this.getPoolKey();
19162
+ const unusedBalances = await this.unusedBalances(poolKey);
19163
+ const { amount: token0Bal1, usdValue: token0PriceUsd } = unusedBalances.token0;
19164
+ const { amount: token1Bal1, usdValue: token1PriceUsd } = unusedBalances.token1;
19126
19165
  let token0Bal = token0Bal1;
19127
19166
  let token1Bal = token1Bal1;
19128
19167
  if (considerRebalance) {
@@ -19140,63 +19179,71 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
19140
19179
  logger.verbose(
19141
19180
  `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => token0Bal: ${token0Bal.toString()}, token1Bal: ${token1Bal.toString()}`
19142
19181
  );
19143
- const newBounds = await this.getNewBounds();
19182
+ let ekuboBounds;
19183
+ if (considerRebalance) {
19184
+ ekuboBounds = await this.getNewBounds();
19185
+ } else {
19186
+ ekuboBounds = await this.getCurrentBounds();
19187
+ }
19144
19188
  logger.verbose(
19145
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => newBounds: ${newBounds.lowerTick}, ${newBounds.upperTick}`
19189
+ `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => newBounds: ${ekuboBounds.lowerTick}, ${ekuboBounds.upperTick}`
19146
19190
  );
19147
19191
  return await this.getSwapInfoGivenAmounts(
19148
19192
  poolKey,
19149
19193
  token0Bal,
19150
19194
  token1Bal,
19151
- newBounds
19195
+ ekuboBounds
19152
19196
  );
19153
19197
  }
19154
19198
  async getSwapInfoGivenAmounts(poolKey, token0Bal, token1Bal, bounds) {
19199
+ logger.verbose(
19200
+ `${_EkuboCLVault.name}: getSwapInfoGivenAmounts::pre => token0Bal: ${token0Bal.toString()}, token1Bal: ${token1Bal.toString()}`
19201
+ );
19155
19202
  let expectedAmounts = await this._getExpectedAmountsForLiquidity(
19156
19203
  token0Bal,
19157
19204
  token1Bal,
19158
19205
  bounds
19159
19206
  );
19160
19207
  logger.verbose(
19161
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => expectedAmounts: ${expectedAmounts.amount0.toString()}, ${expectedAmounts.amount1.toString()}`
19208
+ `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => expectedAmounts2: ${expectedAmounts.amount0.toString()}, ${expectedAmounts.amount1.toString()}`
19162
19209
  );
19163
19210
  let retry = 0;
19164
19211
  const maxRetry = 10;
19165
- while (retry < maxRetry) {
19166
- retry++;
19167
- if (expectedAmounts.amount0.lessThan(token0Bal) && expectedAmounts.amount1.lessThan(token1Bal)) {
19212
+ function assertValidAmounts(expectedAmounts2, token0Bal2, token1Bal2) {
19213
+ if (expectedAmounts2.amount0.lessThan(token0Bal2) && expectedAmounts2.amount1.lessThan(token1Bal2)) {
19168
19214
  throw new Error("Both tokens are decreased, something is wrong");
19169
19215
  }
19170
- if (expectedAmounts.amount0.greaterThan(token0Bal) && expectedAmounts.amount1.greaterThan(token1Bal)) {
19216
+ if (expectedAmounts2.amount0.greaterThan(token0Bal2) && expectedAmounts2.amount1.greaterThan(token1Bal2)) {
19171
19217
  throw new Error("Both tokens are increased, something is wrong");
19172
19218
  }
19173
- const tokenToSell = expectedAmounts.amount0.lessThan(token0Bal) ? poolKey.token0 : poolKey.token1;
19174
- const tokenToBuy = tokenToSell == poolKey.token0 ? poolKey.token1 : poolKey.token0;
19175
- let amountToSell = tokenToSell == poolKey.token0 ? token0Bal.minus(expectedAmounts.amount0) : token1Bal.minus(expectedAmounts.amount1);
19176
- const remainingSellAmount = tokenToSell == poolKey.token0 ? expectedAmounts.amount0 : expectedAmounts.amount1;
19177
- const tokenToBuyInfo = await Global.getTokenInfoFromAddr(tokenToBuy);
19178
- const expectedRatio = expectedAmounts.ratio;
19179
- logger.verbose(
19180
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => tokenToSell: ${tokenToSell.address}, tokenToBuy: ${tokenToBuy.address}, amountToSell: ${amountToSell.toWei()}`
19181
- );
19219
+ }
19220
+ function getSwapParams(expectedAmounts2, poolKey2, token0Bal2, token1Bal2) {
19221
+ const tokenToSell = expectedAmounts2.amount0.lessThan(token0Bal2) ? poolKey2.token0 : poolKey2.token1;
19222
+ const tokenToBuy = tokenToSell == poolKey2.token0 ? poolKey2.token1 : poolKey2.token0;
19223
+ const amountToSell = tokenToSell == poolKey2.token0 ? token0Bal2.minus(expectedAmounts2.amount0) : token1Bal2.minus(expectedAmounts2.amount1);
19224
+ const remainingSellAmount = tokenToSell == poolKey2.token0 ? expectedAmounts2.amount0 : expectedAmounts2.amount1;
19225
+ return { tokenToSell, tokenToBuy, amountToSell, remainingSellAmount };
19226
+ }
19227
+ while (retry < maxRetry) {
19228
+ retry++;
19182
19229
  logger.verbose(
19183
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => remainingSellAmount: ${remainingSellAmount.toString()}`
19230
+ `getSwapInfoGivenAmounts::Retry attempt: ${retry}/${maxRetry}`
19184
19231
  );
19232
+ assertValidAmounts(expectedAmounts, token0Bal, token1Bal);
19233
+ const { tokenToSell, tokenToBuy, amountToSell, remainingSellAmount } = getSwapParams(expectedAmounts, poolKey, token0Bal, token1Bal);
19234
+ const tokenToBuyInfo = await Global.getTokenInfoFromAddr(tokenToBuy);
19235
+ const expectedRatio = expectedAmounts.ratio;
19185
19236
  logger.verbose(
19186
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => expectedRatio: ${expectedRatio}`
19237
+ `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => iteration info: ${JSON.stringify({
19238
+ tokenToSell: tokenToSell.address,
19239
+ tokenToBuy: tokenToBuy.address,
19240
+ amountToSell: amountToSell.toString(),
19241
+ remainingSellAmount: remainingSellAmount.toString(),
19242
+ expectedRatio
19243
+ })}`
19187
19244
  );
19188
19245
  if (amountToSell.eq(0)) {
19189
- return {
19190
- token_from_address: tokenToSell.address,
19191
- token_from_amount: import_starknet9.uint256.bnToUint256(0),
19192
- token_to_address: tokenToSell.address,
19193
- token_to_amount: import_starknet9.uint256.bnToUint256(0),
19194
- token_to_min_amount: import_starknet9.uint256.bnToUint256(0),
19195
- beneficiary: this.address.address,
19196
- integrator_fee_amount_bps: 0,
19197
- integrator_fee_recipient: this.address.address,
19198
- routes: []
19199
- };
19246
+ return AvnuWrapper.buildZeroSwap(tokenToSell, this.address.address);
19200
19247
  }
19201
19248
  const quote = await this.avnu.getQuotes(
19202
19249
  tokenToSell.address,
@@ -19224,15 +19271,14 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
19224
19271
  const swapPrice = tokenToSell == poolKey.token0 ? amountOut.dividedBy(amountToSell) : amountToSell.dividedBy(amountOut);
19225
19272
  const newRatio = tokenToSell == poolKey.token0 ? remainingSellAmount.dividedBy(token1Bal.plus(amountOut)) : token0Bal.plus(amountOut).dividedBy(remainingSellAmount);
19226
19273
  logger.verbose(
19227
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => amountOut: ${amountOut.toString()}`
19274
+ `${_EkuboCLVault.name} getSwapInfoToHandleUnused => iter post calc: ${JSON.stringify({
19275
+ amountOut: amountOut.toString(),
19276
+ swapPrice: swapPrice.toString(),
19277
+ newRatio: newRatio.toString()
19278
+ })}`
19228
19279
  );
19229
- logger.verbose(
19230
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => swapPrice: ${swapPrice.toString()}`
19231
- );
19232
- logger.verbose(
19233
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => newRatio: ${newRatio.toString()}`
19234
- );
19235
- if (Number(newRatio.toString()) > expectedRatio * 1.0000001 || Number(newRatio.toString()) < expectedRatio * 0.9999999) {
19280
+ const expectedPrecision = Math.min(7, tokenToBuyInfo.decimals - 2);
19281
+ if (Number(newRatio.toString()) > expectedRatio * (1 + 1 / 10 ** expectedPrecision) || Number(newRatio.toString()) < expectedRatio * (1 - 1 / 10 ** expectedPrecision)) {
19236
19282
  expectedAmounts = await this._solveExpectedAmountsEq(
19237
19283
  token0Bal,
19238
19284
  token1Bal,
@@ -19431,6 +19477,9 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
19431
19477
  const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
19432
19478
  const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
19433
19479
  const bounds = await this.getCurrentBounds();
19480
+ logger.verbose(
19481
+ `${_EkuboCLVault.name}: harvest => unClaimedRewards: ${unClaimedRewards.length}`
19482
+ );
19434
19483
  const calls = [];
19435
19484
  for (let claim of unClaimedRewards) {
19436
19485
  const fee = claim.claim.amount.multipliedBy(this.metadata.additionalInfo.feeBps).dividedBy(1e4);
@@ -19463,12 +19512,28 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
19463
19512
  18
19464
19513
  // cause its always STRK?
19465
19514
  );
19515
+ logger.verbose(
19516
+ `${_EkuboCLVault.name}: harvest => swap1Amount: ${swap1Amount}`
19517
+ );
19466
19518
  const remainingAmount = postFeeAmount.minus(swap1Amount);
19519
+ logger.verbose(
19520
+ `${_EkuboCLVault.name}: harvest => remainingAmount: ${remainingAmount}`
19521
+ );
19467
19522
  const swapInfo2 = {
19468
19523
  ...swapInfo,
19469
19524
  token_from_amount: import_starknet9.uint256.bnToUint256(remainingAmount.toWei())
19470
19525
  };
19471
19526
  swapInfo2.token_to_address = token1Info.address.address;
19527
+ logger.verbose(
19528
+ `${_EkuboCLVault.name}: harvest => swapInfo: ${JSON.stringify(
19529
+ swapInfo
19530
+ )}`
19531
+ );
19532
+ logger.verbose(
19533
+ `${_EkuboCLVault.name}: harvest => swapInfo2: ${JSON.stringify(
19534
+ swapInfo2
19535
+ )}`
19536
+ );
19472
19537
  const calldata = [
19473
19538
  claim.rewardsContract.address,
19474
19539
  {
@@ -19572,8 +19637,16 @@ var faqs2 = [
19572
19637
  {
19573
19638
  question: "Is the strategy audited?",
19574
19639
  answer: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
19575
- "Yes, the strategy has been audited. You can review the audit report in our docs ",
19576
- /* @__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" }),
19640
+ "Yes, the strategy has been audited. You can review the audit report in our docs",
19641
+ " ",
19642
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
19643
+ "a",
19644
+ {
19645
+ href: "https://docs.strkfarm.com/p/ekubo-cl-vaults#technical-details",
19646
+ style: { textDecoration: "underline", marginLeft: "5px" },
19647
+ children: "Here"
19648
+ }
19649
+ ),
19577
19650
  "."
19578
19651
  ] })
19579
19652
  }
@@ -19625,7 +19698,12 @@ var EkuboCLVaultStrategies = [
19625
19698
  lstContract: ContractAddr.from(
19626
19699
  "0x028d709c875c0ceac3dce7065bec5328186dc89fe254527084d1689910954b0a"
19627
19700
  ),
19628
- feeBps: 1e3
19701
+ feeBps: 1e3,
19702
+ rebalanceConditions: {
19703
+ customShouldRebalance: async (currentPrice) => true,
19704
+ minWaitHours: 24,
19705
+ direction: "uponly"
19706
+ }
19629
19707
  },
19630
19708
  faqs: [
19631
19709
  ...faqs2,
@@ -19666,7 +19744,10 @@ var EkuboCLVaultStrategies = [
19666
19744
  maxTVL: Web3Number.fromWei("0", 6),
19667
19745
  risk: {
19668
19746
  riskFactor: _riskFactorStable,
19669
- netRisk: _riskFactorStable.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactorStable.reduce((acc, curr) => acc + curr.weight, 0),
19747
+ netRisk: _riskFactorStable.reduce(
19748
+ (acc, curr) => acc + curr.value * curr.weight,
19749
+ 0
19750
+ ) / _riskFactorStable.reduce((acc, curr) => acc + curr.weight, 0),
19670
19751
  notARisks: getNoRiskTags(_riskFactorStable)
19671
19752
  },
19672
19753
  apyMethodology: "APY based on 7-day historical performance, including fees and rewards.",
@@ -19676,11 +19757,14 @@ var EkuboCLVaultStrategies = [
19676
19757
  upper: 1
19677
19758
  },
19678
19759
  truePrice: 1,
19679
- feeBps: 1e3
19760
+ feeBps: 1e3,
19761
+ rebalanceConditions: {
19762
+ customShouldRebalance: async (currentPrice) => currentPrice > 0.99 && currentPrice < 1.01,
19763
+ minWaitHours: 6,
19764
+ direction: "any"
19765
+ }
19680
19766
  },
19681
- faqs: [
19682
- ...faqs2
19683
- ]
19767
+ faqs: [...faqs2]
19684
19768
  }
19685
19769
  ];
19686
19770
 
package/dist/index.mjs CHANGED
@@ -1997,6 +1997,19 @@ var AvnuWrapper = class _AvnuWrapper {
1997
1997
  };
1998
1998
  return swapInfo;
1999
1999
  }
2000
+ static buildZeroSwap(tokenToSell, address) {
2001
+ return {
2002
+ token_from_address: tokenToSell.address,
2003
+ token_from_amount: uint256.bnToUint256(0),
2004
+ token_to_address: tokenToSell.address,
2005
+ token_to_amount: uint256.bnToUint256(0),
2006
+ token_to_min_amount: uint256.bnToUint256(0),
2007
+ beneficiary: address,
2008
+ integrator_fee_amount_bps: 0,
2009
+ integrator_fee_recipient: address,
2010
+ routes: []
2011
+ };
2012
+ }
2000
2013
  };
2001
2014
 
2002
2015
  // src/interfaces/common.ts
@@ -18632,7 +18645,10 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
18632
18645
  const priceNow = await this.getCurrentPrice(blockIdentifier);
18633
18646
  let blockNow = typeof blockIdentifier == "number" ? blockIdentifier : (await this.config.provider.getBlockLatestAccepted()).block_number;
18634
18647
  const blockNowTime = typeof blockIdentifier == "number" ? (await this.config.provider.getBlockWithTxs(blockIdentifier)).timestamp : (/* @__PURE__ */ new Date()).getTime() / 1e3;
18635
- const blockBefore = Math.max(blockNow - sinceBlocks, this.metadata.launchBlock);
18648
+ const blockBefore = Math.max(
18649
+ blockNow - sinceBlocks,
18650
+ this.metadata.launchBlock
18651
+ );
18636
18652
  const adjustedSupplyNow = supplyNow.minus(
18637
18653
  await this.getHarvestRewardShares(blockBefore, blockNow)
18638
18654
  );
@@ -19025,14 +19041,24 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
19025
19041
  _solveExpectedAmountsEq(availableAmount0, availableAmount1, ratio, price) {
19026
19042
  const y = ratio.multipliedBy(availableAmount1).minus(availableAmount0).dividedBy(ratio.plus(1 / price));
19027
19043
  const x = y.dividedBy(price);
19044
+ logger.verbose(
19045
+ `${_EkuboCLVault.name}: _solveExpectedAmountsEq => x: ${x.toString()}, y: ${y.toString()}, amount0: ${availableAmount0.toString()}, amount1: ${availableAmount1.toString()}`
19046
+ );
19047
+ if (ratio.eq(0)) {
19048
+ return {
19049
+ amount0: Web3Number.fromWei("0", availableAmount0.decimals),
19050
+ amount1: availableAmount1.minus(y),
19051
+ ratio: 0
19052
+ };
19053
+ }
19028
19054
  return {
19029
19055
  amount0: availableAmount0.plus(x),
19030
19056
  amount1: availableAmount1.minus(y),
19031
19057
  ratio: Number(ratio.toString())
19032
19058
  };
19033
19059
  }
19034
- async getSwapInfoToHandleUnused(considerRebalance = true) {
19035
- const poolKey = await this.getPoolKey();
19060
+ async unusedBalances(_poolKey) {
19061
+ const poolKey = _poolKey || await this.getPoolKey();
19036
19062
  const erc20Mod = new ERC20(this.config);
19037
19063
  const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
19038
19064
  const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
@@ -19053,11 +19079,24 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
19053
19079
  const token1Price = await this.pricer.getPrice(token1Info.symbol);
19054
19080
  const token0PriceUsd = token0Price.price * Number(token0Bal1.toFixed(13));
19055
19081
  const token1PriceUsd = token1Price.price * Number(token1Bal1.toFixed(13));
19056
- if (token0PriceUsd > 1 && token1PriceUsd > 1) {
19057
- throw new Error(
19058
- "Both tokens are non-zero and above $1, call handle_fees first"
19059
- );
19060
- }
19082
+ return {
19083
+ token0: {
19084
+ amount: token0Bal1,
19085
+ tokenInfo: token0Info,
19086
+ usdValue: token0PriceUsd
19087
+ },
19088
+ token1: {
19089
+ amount: token1Bal1,
19090
+ tokenInfo: token1Info,
19091
+ usdValue: token1PriceUsd
19092
+ }
19093
+ };
19094
+ }
19095
+ async getSwapInfoToHandleUnused(considerRebalance = true) {
19096
+ const poolKey = await this.getPoolKey();
19097
+ const unusedBalances = await this.unusedBalances(poolKey);
19098
+ const { amount: token0Bal1, usdValue: token0PriceUsd } = unusedBalances.token0;
19099
+ const { amount: token1Bal1, usdValue: token1PriceUsd } = unusedBalances.token1;
19061
19100
  let token0Bal = token0Bal1;
19062
19101
  let token1Bal = token1Bal1;
19063
19102
  if (considerRebalance) {
@@ -19075,63 +19114,71 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
19075
19114
  logger.verbose(
19076
19115
  `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => token0Bal: ${token0Bal.toString()}, token1Bal: ${token1Bal.toString()}`
19077
19116
  );
19078
- const newBounds = await this.getNewBounds();
19117
+ let ekuboBounds;
19118
+ if (considerRebalance) {
19119
+ ekuboBounds = await this.getNewBounds();
19120
+ } else {
19121
+ ekuboBounds = await this.getCurrentBounds();
19122
+ }
19079
19123
  logger.verbose(
19080
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => newBounds: ${newBounds.lowerTick}, ${newBounds.upperTick}`
19124
+ `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => newBounds: ${ekuboBounds.lowerTick}, ${ekuboBounds.upperTick}`
19081
19125
  );
19082
19126
  return await this.getSwapInfoGivenAmounts(
19083
19127
  poolKey,
19084
19128
  token0Bal,
19085
19129
  token1Bal,
19086
- newBounds
19130
+ ekuboBounds
19087
19131
  );
19088
19132
  }
19089
19133
  async getSwapInfoGivenAmounts(poolKey, token0Bal, token1Bal, bounds) {
19134
+ logger.verbose(
19135
+ `${_EkuboCLVault.name}: getSwapInfoGivenAmounts::pre => token0Bal: ${token0Bal.toString()}, token1Bal: ${token1Bal.toString()}`
19136
+ );
19090
19137
  let expectedAmounts = await this._getExpectedAmountsForLiquidity(
19091
19138
  token0Bal,
19092
19139
  token1Bal,
19093
19140
  bounds
19094
19141
  );
19095
19142
  logger.verbose(
19096
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => expectedAmounts: ${expectedAmounts.amount0.toString()}, ${expectedAmounts.amount1.toString()}`
19143
+ `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => expectedAmounts2: ${expectedAmounts.amount0.toString()}, ${expectedAmounts.amount1.toString()}`
19097
19144
  );
19098
19145
  let retry = 0;
19099
19146
  const maxRetry = 10;
19100
- while (retry < maxRetry) {
19101
- retry++;
19102
- if (expectedAmounts.amount0.lessThan(token0Bal) && expectedAmounts.amount1.lessThan(token1Bal)) {
19147
+ function assertValidAmounts(expectedAmounts2, token0Bal2, token1Bal2) {
19148
+ if (expectedAmounts2.amount0.lessThan(token0Bal2) && expectedAmounts2.amount1.lessThan(token1Bal2)) {
19103
19149
  throw new Error("Both tokens are decreased, something is wrong");
19104
19150
  }
19105
- if (expectedAmounts.amount0.greaterThan(token0Bal) && expectedAmounts.amount1.greaterThan(token1Bal)) {
19151
+ if (expectedAmounts2.amount0.greaterThan(token0Bal2) && expectedAmounts2.amount1.greaterThan(token1Bal2)) {
19106
19152
  throw new Error("Both tokens are increased, something is wrong");
19107
19153
  }
19108
- const tokenToSell = expectedAmounts.amount0.lessThan(token0Bal) ? poolKey.token0 : poolKey.token1;
19109
- const tokenToBuy = tokenToSell == poolKey.token0 ? poolKey.token1 : poolKey.token0;
19110
- let amountToSell = tokenToSell == poolKey.token0 ? token0Bal.minus(expectedAmounts.amount0) : token1Bal.minus(expectedAmounts.amount1);
19111
- const remainingSellAmount = tokenToSell == poolKey.token0 ? expectedAmounts.amount0 : expectedAmounts.amount1;
19112
- const tokenToBuyInfo = await Global.getTokenInfoFromAddr(tokenToBuy);
19113
- const expectedRatio = expectedAmounts.ratio;
19114
- logger.verbose(
19115
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => tokenToSell: ${tokenToSell.address}, tokenToBuy: ${tokenToBuy.address}, amountToSell: ${amountToSell.toWei()}`
19116
- );
19154
+ }
19155
+ function getSwapParams(expectedAmounts2, poolKey2, token0Bal2, token1Bal2) {
19156
+ const tokenToSell = expectedAmounts2.amount0.lessThan(token0Bal2) ? poolKey2.token0 : poolKey2.token1;
19157
+ const tokenToBuy = tokenToSell == poolKey2.token0 ? poolKey2.token1 : poolKey2.token0;
19158
+ const amountToSell = tokenToSell == poolKey2.token0 ? token0Bal2.minus(expectedAmounts2.amount0) : token1Bal2.minus(expectedAmounts2.amount1);
19159
+ const remainingSellAmount = tokenToSell == poolKey2.token0 ? expectedAmounts2.amount0 : expectedAmounts2.amount1;
19160
+ return { tokenToSell, tokenToBuy, amountToSell, remainingSellAmount };
19161
+ }
19162
+ while (retry < maxRetry) {
19163
+ retry++;
19117
19164
  logger.verbose(
19118
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => remainingSellAmount: ${remainingSellAmount.toString()}`
19165
+ `getSwapInfoGivenAmounts::Retry attempt: ${retry}/${maxRetry}`
19119
19166
  );
19167
+ assertValidAmounts(expectedAmounts, token0Bal, token1Bal);
19168
+ const { tokenToSell, tokenToBuy, amountToSell, remainingSellAmount } = getSwapParams(expectedAmounts, poolKey, token0Bal, token1Bal);
19169
+ const tokenToBuyInfo = await Global.getTokenInfoFromAddr(tokenToBuy);
19170
+ const expectedRatio = expectedAmounts.ratio;
19120
19171
  logger.verbose(
19121
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => expectedRatio: ${expectedRatio}`
19172
+ `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => iteration info: ${JSON.stringify({
19173
+ tokenToSell: tokenToSell.address,
19174
+ tokenToBuy: tokenToBuy.address,
19175
+ amountToSell: amountToSell.toString(),
19176
+ remainingSellAmount: remainingSellAmount.toString(),
19177
+ expectedRatio
19178
+ })}`
19122
19179
  );
19123
19180
  if (amountToSell.eq(0)) {
19124
- return {
19125
- token_from_address: tokenToSell.address,
19126
- token_from_amount: uint2564.bnToUint256(0),
19127
- token_to_address: tokenToSell.address,
19128
- token_to_amount: uint2564.bnToUint256(0),
19129
- token_to_min_amount: uint2564.bnToUint256(0),
19130
- beneficiary: this.address.address,
19131
- integrator_fee_amount_bps: 0,
19132
- integrator_fee_recipient: this.address.address,
19133
- routes: []
19134
- };
19181
+ return AvnuWrapper.buildZeroSwap(tokenToSell, this.address.address);
19135
19182
  }
19136
19183
  const quote = await this.avnu.getQuotes(
19137
19184
  tokenToSell.address,
@@ -19159,15 +19206,14 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
19159
19206
  const swapPrice = tokenToSell == poolKey.token0 ? amountOut.dividedBy(amountToSell) : amountToSell.dividedBy(amountOut);
19160
19207
  const newRatio = tokenToSell == poolKey.token0 ? remainingSellAmount.dividedBy(token1Bal.plus(amountOut)) : token0Bal.plus(amountOut).dividedBy(remainingSellAmount);
19161
19208
  logger.verbose(
19162
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => amountOut: ${amountOut.toString()}`
19209
+ `${_EkuboCLVault.name} getSwapInfoToHandleUnused => iter post calc: ${JSON.stringify({
19210
+ amountOut: amountOut.toString(),
19211
+ swapPrice: swapPrice.toString(),
19212
+ newRatio: newRatio.toString()
19213
+ })}`
19163
19214
  );
19164
- logger.verbose(
19165
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => swapPrice: ${swapPrice.toString()}`
19166
- );
19167
- logger.verbose(
19168
- `${_EkuboCLVault.name}: getSwapInfoToHandleUnused => newRatio: ${newRatio.toString()}`
19169
- );
19170
- if (Number(newRatio.toString()) > expectedRatio * 1.0000001 || Number(newRatio.toString()) < expectedRatio * 0.9999999) {
19215
+ const expectedPrecision = Math.min(7, tokenToBuyInfo.decimals - 2);
19216
+ if (Number(newRatio.toString()) > expectedRatio * (1 + 1 / 10 ** expectedPrecision) || Number(newRatio.toString()) < expectedRatio * (1 - 1 / 10 ** expectedPrecision)) {
19171
19217
  expectedAmounts = await this._solveExpectedAmountsEq(
19172
19218
  token0Bal,
19173
19219
  token1Bal,
@@ -19366,6 +19412,9 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
19366
19412
  const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
19367
19413
  const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
19368
19414
  const bounds = await this.getCurrentBounds();
19415
+ logger.verbose(
19416
+ `${_EkuboCLVault.name}: harvest => unClaimedRewards: ${unClaimedRewards.length}`
19417
+ );
19369
19418
  const calls = [];
19370
19419
  for (let claim of unClaimedRewards) {
19371
19420
  const fee = claim.claim.amount.multipliedBy(this.metadata.additionalInfo.feeBps).dividedBy(1e4);
@@ -19398,12 +19447,28 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
19398
19447
  18
19399
19448
  // cause its always STRK?
19400
19449
  );
19450
+ logger.verbose(
19451
+ `${_EkuboCLVault.name}: harvest => swap1Amount: ${swap1Amount}`
19452
+ );
19401
19453
  const remainingAmount = postFeeAmount.minus(swap1Amount);
19454
+ logger.verbose(
19455
+ `${_EkuboCLVault.name}: harvest => remainingAmount: ${remainingAmount}`
19456
+ );
19402
19457
  const swapInfo2 = {
19403
19458
  ...swapInfo,
19404
19459
  token_from_amount: uint2564.bnToUint256(remainingAmount.toWei())
19405
19460
  };
19406
19461
  swapInfo2.token_to_address = token1Info.address.address;
19462
+ logger.verbose(
19463
+ `${_EkuboCLVault.name}: harvest => swapInfo: ${JSON.stringify(
19464
+ swapInfo
19465
+ )}`
19466
+ );
19467
+ logger.verbose(
19468
+ `${_EkuboCLVault.name}: harvest => swapInfo2: ${JSON.stringify(
19469
+ swapInfo2
19470
+ )}`
19471
+ );
19407
19472
  const calldata = [
19408
19473
  claim.rewardsContract.address,
19409
19474
  {
@@ -19507,8 +19572,16 @@ var faqs2 = [
19507
19572
  {
19508
19573
  question: "Is the strategy audited?",
19509
19574
  answer: /* @__PURE__ */ jsxs2("div", { children: [
19510
- "Yes, the strategy has been audited. You can review the audit report in our docs ",
19511
- /* @__PURE__ */ jsx2("a", { href: "https://docs.strkfarm.com/p/ekubo-cl-vaults#technical-details", style: { textDecoration: "underline", marginLeft: "5px" }, children: "Here" }),
19575
+ "Yes, the strategy has been audited. You can review the audit report in our docs",
19576
+ " ",
19577
+ /* @__PURE__ */ jsx2(
19578
+ "a",
19579
+ {
19580
+ href: "https://docs.strkfarm.com/p/ekubo-cl-vaults#technical-details",
19581
+ style: { textDecoration: "underline", marginLeft: "5px" },
19582
+ children: "Here"
19583
+ }
19584
+ ),
19512
19585
  "."
19513
19586
  ] })
19514
19587
  }
@@ -19560,7 +19633,12 @@ var EkuboCLVaultStrategies = [
19560
19633
  lstContract: ContractAddr.from(
19561
19634
  "0x028d709c875c0ceac3dce7065bec5328186dc89fe254527084d1689910954b0a"
19562
19635
  ),
19563
- feeBps: 1e3
19636
+ feeBps: 1e3,
19637
+ rebalanceConditions: {
19638
+ customShouldRebalance: async (currentPrice) => true,
19639
+ minWaitHours: 24,
19640
+ direction: "uponly"
19641
+ }
19564
19642
  },
19565
19643
  faqs: [
19566
19644
  ...faqs2,
@@ -19601,7 +19679,10 @@ var EkuboCLVaultStrategies = [
19601
19679
  maxTVL: Web3Number.fromWei("0", 6),
19602
19680
  risk: {
19603
19681
  riskFactor: _riskFactorStable,
19604
- netRisk: _riskFactorStable.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactorStable.reduce((acc, curr) => acc + curr.weight, 0),
19682
+ netRisk: _riskFactorStable.reduce(
19683
+ (acc, curr) => acc + curr.value * curr.weight,
19684
+ 0
19685
+ ) / _riskFactorStable.reduce((acc, curr) => acc + curr.weight, 0),
19605
19686
  notARisks: getNoRiskTags(_riskFactorStable)
19606
19687
  },
19607
19688
  apyMethodology: "APY based on 7-day historical performance, including fees and rewards.",
@@ -19611,11 +19692,14 @@ var EkuboCLVaultStrategies = [
19611
19692
  upper: 1
19612
19693
  },
19613
19694
  truePrice: 1,
19614
- feeBps: 1e3
19695
+ feeBps: 1e3,
19696
+ rebalanceConditions: {
19697
+ customShouldRebalance: async (currentPrice) => currentPrice > 0.99 && currentPrice < 1.01,
19698
+ minWaitHours: 6,
19699
+ direction: "any"
19700
+ }
19615
19701
  },
19616
- faqs: [
19617
- ...faqs2
19618
- ]
19702
+ faqs: [...faqs2]
19619
19703
  }
19620
19704
  ];
19621
19705
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strkfarm/sdk",
3
- "version": "1.0.40",
3
+ "version": "1.0.42",
4
4
  "description": "STRKFarm TS SDK (Meant for our internal use, but feel free to use it)",
5
5
  "typings": "dist/index.d.ts",
6
6
  "types": "dist/index.d.ts",
@@ -4,6 +4,7 @@ import { Call, Uint256 } from "starknet";
4
4
  import { fetchBuildExecuteTransaction, fetchQuotes, Quote } from "@avnu/avnu-sdk";
5
5
  import { assert } from "../utils";
6
6
  import { logger } from "@/utils/logger";
7
+ import { ContractAddr } from "@/dataTypes";
7
8
 
8
9
  export interface Route {
9
10
  token_from: string,
@@ -109,4 +110,21 @@ export class AvnuWrapper {
109
110
 
110
111
  return swapInfo;
111
112
  }
113
+
114
+ static buildZeroSwap(
115
+ tokenToSell: ContractAddr,
116
+ address: string
117
+ ): SwapInfo {
118
+ return {
119
+ token_from_address: tokenToSell.address,
120
+ token_from_amount: uint256.bnToUint256(0),
121
+ token_to_address: tokenToSell.address,
122
+ token_to_amount: uint256.bnToUint256(0),
123
+ token_to_min_amount: uint256.bnToUint256(0),
124
+ beneficiary: address,
125
+ integrator_fee_amount_bps: 0,
126
+ integrator_fee_recipient: address,
127
+ routes: [],
128
+ };
129
+ }
112
130
  }