@strkfarm/sdk 1.0.28 → 1.0.29

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.
@@ -6912,6 +6912,7 @@ var strkfarm_risk_engine = (() => {
6912
6912
  __export(index_browser_exports, {
6913
6913
  AutoCompounderSTRK: () => AutoCompounderSTRK,
6914
6914
  AvnuWrapper: () => AvnuWrapper,
6915
+ BaseStrategy: () => BaseStrategy,
6915
6916
  ContractAddr: () => ContractAddr,
6916
6917
  ERC20: () => ERC20,
6917
6918
  EkuboCLVault: () => EkuboCLVault,
@@ -9435,19 +9436,19 @@ var strkfarm_risk_engine = (() => {
9435
9436
  return this.mul(10 ** this.decimals).toFixed(0);
9436
9437
  }
9437
9438
  multipliedBy(value) {
9438
- let _value = Number(value).toFixed(this.maxToFixedDecimals());
9439
+ const _value = this.getStandardString(value);
9439
9440
  return this.construct(this.mul(_value).toString(), this.decimals);
9440
9441
  }
9441
9442
  dividedBy(value) {
9442
- let _value = Number(value).toFixed(this.maxToFixedDecimals());
9443
+ const _value = this.getStandardString(value);
9443
9444
  return this.construct(this.div(_value).toString(), this.decimals);
9444
9445
  }
9445
9446
  plus(value) {
9446
- const _value = Number(value).toFixed(this.maxToFixedDecimals());
9447
+ const _value = this.getStandardString(value);
9447
9448
  return this.construct(this.add(_value).toString(), this.decimals);
9448
9449
  }
9449
9450
  minus(n, base2) {
9450
- const _value = Number(n).toFixed(this.maxToFixedDecimals());
9451
+ const _value = this.getStandardString(n);
9451
9452
  return this.construct(super.minus(_value, base2).toString(), this.decimals);
9452
9453
  }
9453
9454
  construct(value, decimals) {
@@ -9463,11 +9464,17 @@ var strkfarm_risk_engine = (() => {
9463
9464
  return this.toString();
9464
9465
  }
9465
9466
  maxToFixedDecimals() {
9466
- return Math.min(this.decimals, 13);
9467
+ return Math.min(this.decimals, 18);
9468
+ }
9469
+ getStandardString(value) {
9470
+ if (typeof value == "string") {
9471
+ return value;
9472
+ }
9473
+ return value.toFixed(this.maxToFixedDecimals());
9467
9474
  }
9468
9475
  };
9469
- import_bignumber.default.config({ DECIMAL_PLACES: 18 });
9470
- _Web3Number.config({ DECIMAL_PLACES: 18 });
9476
+ import_bignumber.default.config({ DECIMAL_PLACES: 18, ROUNDING_MODE: import_bignumber.default.ROUND_DOWN });
9477
+ _Web3Number.config({ DECIMAL_PLACES: 18, ROUNDING_MODE: import_bignumber.default.ROUND_DOWN });
9471
9478
 
9472
9479
  // src/dataTypes/bignumber.browser.ts
9473
9480
  var Web3Number = class _Web3Number2 extends _Web3Number {
@@ -27218,42 +27225,48 @@ ${JSON.stringify(data, null, 2)}`;
27218
27225
  logo: "https://assets.coingecko.com/coins/images/26433/small/starknet.png",
27219
27226
  address: ContractAddr.from("0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d"),
27220
27227
  decimals: 18,
27221
- coingeckId: "starknet"
27228
+ coingeckId: "starknet",
27229
+ displayDecimals: 2
27222
27230
  }, {
27223
27231
  name: "xSTRK",
27224
27232
  symbol: "xSTRK",
27225
27233
  logo: "https://dashboard.endur.fi/endur-fi.svg",
27226
27234
  address: ContractAddr.from("0x028d709c875c0ceac3dce7065bec5328186dc89fe254527084d1689910954b0a"),
27227
27235
  decimals: 18,
27228
- coingeckId: void 0
27236
+ coingeckId: void 0,
27237
+ displayDecimals: 2
27229
27238
  }, {
27230
27239
  name: "ETH",
27231
27240
  symbol: "ETH",
27232
27241
  logo: "https://opbnb.bscscan.com/token/images/ether.svg",
27233
27242
  address: ContractAddr.from("0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"),
27234
27243
  decimals: 18,
27235
- coingeckId: void 0
27244
+ coingeckId: void 0,
27245
+ displayDecimals: 4
27236
27246
  }, {
27237
27247
  name: "USDC",
27238
27248
  symbol: "USDC",
27239
27249
  logo: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
27240
27250
  address: ContractAddr.from("0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8"),
27241
27251
  decimals: 6,
27242
- coingeckId: void 0
27252
+ coingeckId: void 0,
27253
+ displayDecimals: 2
27243
27254
  }, {
27244
27255
  name: "USDT",
27245
27256
  symbol: "USDT",
27246
27257
  logo: "https://assets.coingecko.com/coins/images/325/small/Tether.png",
27247
27258
  address: ContractAddr.from("0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8"),
27248
27259
  decimals: 6,
27249
- coingeckId: void 0
27260
+ coingeckId: void 0,
27261
+ displayDecimals: 2
27250
27262
  }, {
27251
27263
  name: "WBTC",
27252
27264
  symbol: "WBTC",
27253
27265
  logo: "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png",
27254
27266
  address: ContractAddr.from("0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac"),
27255
27267
  decimals: 8,
27256
- coingeckId: void 0
27268
+ coingeckId: void 0,
27269
+ displayDecimals: 6
27257
27270
  }];
27258
27271
  var tokens = defaultTokens;
27259
27272
  var Global = class _Global {
@@ -27285,7 +27298,8 @@ ${JSON.stringify(data, null, 2)}`;
27285
27298
  address: ContractAddr.from(token.address),
27286
27299
  decimals: token.decimals,
27287
27300
  logo: token.logoUri,
27288
- coingeckId: token.extensions.coingeckoId
27301
+ coingeckId: token.extensions.coingeckoId,
27302
+ displayDecimals: 2
27289
27303
  });
27290
27304
  });
27291
27305
  console.log(tokens);
@@ -27655,7 +27669,8 @@ ${JSON.stringify(data, null, 2)}`;
27655
27669
  logo: "",
27656
27670
  decimals: pool.token.decimals,
27657
27671
  borrowFactor: Web3Number.fromWei(pool.borrow_factor.value, pool.borrow_factor.decimals),
27658
- collareralFactor
27672
+ collareralFactor,
27673
+ displayDecimals: 2
27659
27674
  };
27660
27675
  this.tokens.push(token);
27661
27676
  });
@@ -27771,7 +27786,7 @@ ${JSON.stringify(data, null, 2)}`;
27771
27786
  try {
27772
27787
  return await this.getPriceFromMyAPI(tokenSymbol);
27773
27788
  } catch (e) {
27774
- logger2.warn("getPriceFromMyAPI error", e);
27789
+ logger2.warn("getPriceFromMyAPI error", JSON.stringify(e.message || e));
27775
27790
  }
27776
27791
  logger2.log("getPrice coinbase", tokenSymbol);
27777
27792
  let retry = 0;
@@ -27791,7 +27806,7 @@ ${JSON.stringify(data, null, 2)}`;
27791
27806
  timestamp: /* @__PURE__ */ new Date()
27792
27807
  };
27793
27808
  } catch (e) {
27794
- logger2.warn("getPrice coinbase error", e, retry);
27809
+ logger2.warn("getPrice coinbase error", JSON.stringify(e.message || e));
27795
27810
  await new Promise((resolve) => setTimeout(resolve, retry * 1e3));
27796
27811
  }
27797
27812
  }
@@ -27805,9 +27820,6 @@ ${JSON.stringify(data, null, 2)}`;
27805
27820
  const priceInfo = await priceInfoRes.json();
27806
27821
  const now = /* @__PURE__ */ new Date();
27807
27822
  const priceTime = new Date(priceInfo.timestamp);
27808
- if (now.getTime() - priceTime.getTime() > 9e5) {
27809
- throw new Error("Price is stale");
27810
- }
27811
27823
  const price = Number(priceInfo.price);
27812
27824
  return {
27813
27825
  price,
@@ -29280,17 +29292,28 @@ ${JSON.stringify(data, null, 2)}`;
29280
29292
  }
29281
29293
 
29282
29294
  // src/modules/avnu.ts
29283
- var AvnuWrapper = class {
29284
- async getQuotes(fromToken, toToken, amountWei, taker) {
29295
+ var AvnuWrapper = class _AvnuWrapper {
29296
+ async getQuotes(fromToken, toToken, amountWei, taker, retry = 0) {
29297
+ const MAX_RETRY = 5;
29298
+ logger2.verbose(`${_AvnuWrapper.name}: getQuotes => Getting quotes for ${fromToken} -> ${toToken}, amount: ${amountWei}, taker: ${taker}, retry: ${retry}`);
29285
29299
  const params = {
29286
29300
  sellTokenAddress: fromToken,
29287
29301
  buyTokenAddress: toToken,
29288
29302
  sellAmount: amountWei,
29289
- takerAddress: taker
29303
+ takerAddress: taker,
29304
+ // excludeSources: ['Nostra', 'Haiko(Solvers)']
29305
+ excludeSources: ["Haiko(Solvers)"]
29306
+ // to resolve InvalidOraclePrice error
29290
29307
  };
29291
29308
  assert3(fromToken != toToken, "From and to tokens are the same");
29292
29309
  const quotes = await fetchQuotes(params);
29293
- assert3(quotes.length > 0, "No quotes found");
29310
+ if (quotes.length == 0) {
29311
+ if (retry < MAX_RETRY) {
29312
+ await new Promise((res) => setTimeout(res, 3e3));
29313
+ return await this.getQuotes(fromToken, toToken, amountWei, taker, retry + 1);
29314
+ }
29315
+ throw new Error("no quotes found");
29316
+ }
29294
29317
  return quotes[0];
29295
29318
  }
29296
29319
  async getSwapInfo(quote, taker, integratorFeeBps, integratorFeeRecipient, minAmount) {
@@ -30958,10 +30981,10 @@ ${JSON.stringify(data, null, 2)}`;
30958
30981
  async getTVL() {
30959
30982
  throw new Error("Not implemented");
30960
30983
  }
30961
- depositCall(amountInfo, receiver) {
30984
+ async depositCall(amountInfo, receiver) {
30962
30985
  throw new Error("Not implemented");
30963
30986
  }
30964
- withdrawCall(amountInfo, receiver, owner) {
30987
+ async withdrawCall(amountInfo, receiver, owner) {
30965
30988
  throw new Error("Not implemented");
30966
30989
  }
30967
30990
  };
@@ -30997,7 +31020,7 @@ ${JSON.stringify(data, null, 2)}`;
30997
31020
  * @param receiver - Address that will receive the strategy tokens
30998
31021
  * @returns Populated contract call for deposit
30999
31022
  */
31000
- depositCall(amountInfo, receiver) {
31023
+ async depositCall(amountInfo, receiver) {
31001
31024
  assert3(amountInfo.tokenInfo.address.eq(this.asset().address), "Deposit token mismatch");
31002
31025
  const assetContract = new Contract(vesu_rebalance_abi_default, this.asset().address.address, this.config.provider);
31003
31026
  const call1 = assetContract.populate("approve", [this.address.address, uint256_exports.bnToUint256(amountInfo.amount.toWei())]);
@@ -31011,7 +31034,7 @@ ${JSON.stringify(data, null, 2)}`;
31011
31034
  * @param owner - Address that owns the strategy tokens
31012
31035
  * @returns Populated contract call for withdrawal
31013
31036
  */
31014
- withdrawCall(amountInfo, receiver, owner) {
31037
+ async withdrawCall(amountInfo, receiver, owner) {
31015
31038
  return [this.contract.populate("withdraw", [uint256_exports.bnToUint256(amountInfo.amount.toWei()), receiver.address, owner.address])];
31016
31039
  }
31017
31040
  /**
@@ -36312,6 +36335,57 @@ ${JSON.stringify(data, null, 2)}`;
36312
36335
  }
36313
36336
  ];
36314
36337
 
36338
+ // src/modules/harvests.ts
36339
+ var Harvests = class _Harvests {
36340
+ constructor(config3) {
36341
+ this.config = config3;
36342
+ }
36343
+ getHarvests(addr) {
36344
+ throw new Error("Not implemented");
36345
+ }
36346
+ async getUnHarvestedRewards(addr) {
36347
+ const rewards = await this.getHarvests(addr);
36348
+ if (rewards.length == 0) return [];
36349
+ const unClaimed = [];
36350
+ const cls = await this.config.provider.getClassAt(rewards[0].rewardsContract.address);
36351
+ for (let reward of rewards) {
36352
+ const contract = new Contract(cls.abi, reward.rewardsContract.address, this.config.provider);
36353
+ const isClaimed = await contract.call("is_claimed", [reward.claim.id]);
36354
+ logger2.verbose(`${_Harvests.name}: isClaimed: ${isClaimed}`);
36355
+ if (isClaimed)
36356
+ return unClaimed;
36357
+ unClaimed.unshift(reward);
36358
+ }
36359
+ return unClaimed;
36360
+ }
36361
+ };
36362
+ var EkuboHarvests = class extends Harvests {
36363
+ async getHarvests(addr) {
36364
+ const STRK = "0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d";
36365
+ const EKUBO_API = `https://starknet-mainnet-api.ekubo.org/airdrops/${addr.address}?token=${STRK}`;
36366
+ const resultEkubo = await fetch(EKUBO_API);
36367
+ const items = await resultEkubo.json();
36368
+ const rewards = [];
36369
+ for (let i = 0; i < items.length; ++i) {
36370
+ const info = items[i];
36371
+ assert3(info.token == STRK, "expected strk token only");
36372
+ rewards.push({
36373
+ rewardsContract: ContractAddr.from(info.contract_address),
36374
+ token: ContractAddr.from(STRK),
36375
+ startDate: new Date(info.start_date),
36376
+ endDate: new Date(info.end_date),
36377
+ claim: {
36378
+ id: info.claim.id,
36379
+ amount: Web3Number.fromWei(info.claim.amount, 18),
36380
+ claimee: ContractAddr.from(info.claim.claimee)
36381
+ },
36382
+ proof: info.proof
36383
+ });
36384
+ }
36385
+ return rewards.sort((a, b) => b.endDate.getTime() - a.endDate.getTime());
36386
+ }
36387
+ };
36388
+
36315
36389
  // src/strategies/ekubo-cl-vault.ts
36316
36390
  var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
36317
36391
  /**
@@ -36336,11 +36410,66 @@ ${JSON.stringify(data, null, 2)}`;
36336
36410
  this.ekuboMathContract = new Contract(ekubo_math_abi_default, EKUBO_MATH, this.config.provider);
36337
36411
  this.avnu = new AvnuWrapper();
36338
36412
  }
36339
- depositCall(amountInfo, receiver) {
36340
- return [];
36413
+ async matchInputAmounts(amountInfo) {
36414
+ const bounds = await this.getCurrentBounds();
36415
+ const res = await this._getExpectedAmountsForLiquidity(
36416
+ amountInfo.token0.amount,
36417
+ amountInfo.token1.amount,
36418
+ bounds,
36419
+ false
36420
+ );
36421
+ return {
36422
+ token0: {
36423
+ tokenInfo: amountInfo.token0.tokenInfo,
36424
+ amount: res.amount0
36425
+ },
36426
+ token1: {
36427
+ tokenInfo: amountInfo.token1.tokenInfo,
36428
+ amount: res.amount1
36429
+ }
36430
+ };
36341
36431
  }
36342
- withdrawCall(amountInfo, receiver, owner) {
36343
- return [];
36432
+ /** Returns minimum amounts give given two amounts based on what can be added for liq */
36433
+ async getMinDepositAmounts(amountInfo) {
36434
+ const shares = await this.tokensToShares(amountInfo);
36435
+ const { amount0, amount1 } = await this.contract.call("convert_to_assets", [uint256_exports.bnToUint256(shares.toWei())]);
36436
+ return {
36437
+ token0: {
36438
+ tokenInfo: amountInfo.token0.tokenInfo,
36439
+ amount: Web3Number.fromWei(amount0.toString(), amountInfo.token0.tokenInfo.decimals)
36440
+ },
36441
+ token1: {
36442
+ tokenInfo: amountInfo.token1.tokenInfo,
36443
+ amount: Web3Number.fromWei(amount1.toString(), amountInfo.token1.tokenInfo.decimals)
36444
+ }
36445
+ };
36446
+ }
36447
+ async depositCall(amountInfo, receiver) {
36448
+ const updateAmountInfo = await this.getMinDepositAmounts(amountInfo);
36449
+ const token0Contract = new Contract(erc4626_abi_default, amountInfo.token0.tokenInfo.address.address, this.config.provider);
36450
+ const token1Contract = new Contract(erc4626_abi_default, amountInfo.token1.tokenInfo.address.address, this.config.provider);
36451
+ const call1 = token0Contract.populate("approve", [this.address.address, uint256_exports.bnToUint256(updateAmountInfo.token0.amount.toWei())]);
36452
+ const call2 = token1Contract.populate("approve", [this.address.address, uint256_exports.bnToUint256(updateAmountInfo.token1.amount.toWei())]);
36453
+ const call3 = this.contract.populate("deposit", [uint256_exports.bnToUint256(updateAmountInfo.token0.amount.toWei()), uint256_exports.bnToUint256(updateAmountInfo.token1.amount.toWei()), receiver.address]);
36454
+ const calls = [];
36455
+ if (updateAmountInfo.token0.amount.greaterThan(0)) calls.push(call1);
36456
+ if (updateAmountInfo.token1.amount.greaterThan(0)) calls.push(call2);
36457
+ return [...calls, call3];
36458
+ }
36459
+ async tokensToShares(amountInfo) {
36460
+ const shares = await this.contract.call("convert_to_shares", [
36461
+ uint256_exports.bnToUint256(amountInfo.token0.amount.toWei()),
36462
+ uint256_exports.bnToUint256(amountInfo.token1.amount.toWei())
36463
+ ]);
36464
+ return Web3Number.fromWei(shares.toString(), 18);
36465
+ }
36466
+ async withdrawCall(amountInfo, receiver, owner) {
36467
+ const shares = await this.tokensToShares(amountInfo);
36468
+ logger2.verbose(`${_EkuboCLVault.name}: withdrawCall: shares=${shares.toString()}`);
36469
+ return [this.contract.populate("withdraw", [
36470
+ uint256_exports.bnToUint256(shares.toWei()),
36471
+ receiver.address
36472
+ ])];
36344
36473
  }
36345
36474
  rebalanceCall(newBounds, swapParams) {
36346
36475
  return [this.contract.populate("rebalance", [
@@ -36359,14 +36488,113 @@ ${JSON.stringify(data, null, 2)}`;
36359
36488
  handleFeesCall() {
36360
36489
  return [this.contract.populate("handle_fees", [])];
36361
36490
  }
36362
- async getUserTVL(user) {
36363
- throw new Error("Not implemented");
36491
+ /**
36492
+ * Calculates assets before and now in a given token of TVL per share to observe growth
36493
+ * @returns {Promise<number>} The weighted average APY across all pools
36494
+ */
36495
+ async netAPY(blockIdentifier = "pending", sinceBlocks = 2e4) {
36496
+ const tvlNow = await this._getTVL(blockIdentifier);
36497
+ const supplyNow = await this.totalSupply(blockIdentifier);
36498
+ const priceNow = await this.getCurrentPrice(blockIdentifier);
36499
+ let blockNow = typeof blockIdentifier == "number" ? blockIdentifier : (await this.config.provider.getBlockLatestAccepted()).block_number;
36500
+ const blockNowTime = typeof blockIdentifier == "number" ? (await this.config.provider.getBlockWithTxs(blockIdentifier)).timestamp : (/* @__PURE__ */ new Date()).getTime() / 1e3;
36501
+ const blockBefore = blockNow - sinceBlocks;
36502
+ const adjustedSupplyNow = supplyNow.minus(await this.getHarvestRewardShares(blockBefore, blockNow));
36503
+ let blockBeforeInfo = await this.config.provider.getBlockWithTxs(blockBefore);
36504
+ const tvlBefore = await this._getTVL(blockBefore);
36505
+ const supplyBefore = await this.totalSupply(blockBefore);
36506
+ const priceBefore = await this.getCurrentPrice(blockBefore);
36507
+ const tvlInToken0Now = tvlNow.amount0.multipliedBy(priceNow.price).plus(tvlNow.amount1);
36508
+ const tvlPerShareNow = tvlInToken0Now.multipliedBy(1e18).dividedBy(adjustedSupplyNow);
36509
+ const tvlInToken0Bf = tvlBefore.amount0.multipliedBy(priceBefore.price).plus(tvlBefore.amount1);
36510
+ const tvlPerShareBf = tvlInToken0Bf.multipliedBy(1e18).dividedBy(supplyBefore);
36511
+ const timeDiffSeconds = blockNowTime - blockBeforeInfo.timestamp;
36512
+ logger2.verbose(`tvlInToken0Now: ${tvlInToken0Now.toString()}`);
36513
+ logger2.verbose(`tvlInToken0Bf: ${tvlInToken0Bf.toString()}`);
36514
+ logger2.verbose(`tvlPerShareNow: ${tvlPerShareNow.toString()}`);
36515
+ logger2.verbose(`tvlPerShareBf: ${tvlPerShareBf.toString()}`);
36516
+ logger2.verbose(`Price before: ${priceBefore.price.toString()}`);
36517
+ logger2.verbose(`Price now: ${priceNow.price.toString()}`);
36518
+ logger2.verbose(`Supply before: ${supplyBefore.toString()}`);
36519
+ logger2.verbose(`Supply now: ${adjustedSupplyNow.toString()}`);
36520
+ logger2.verbose(`Time diff in seconds: ${timeDiffSeconds}`);
36521
+ const apyForGivenBlocks = Number(tvlPerShareNow.minus(tvlPerShareBf).multipliedBy(1e4).dividedBy(tvlPerShareBf)) / 1e4;
36522
+ return apyForGivenBlocks * (365 * 24 * 3600) / timeDiffSeconds;
36523
+ }
36524
+ async getHarvestRewardShares(fromBlock, toBlock) {
36525
+ const len = Number(await this.contract.call("get_total_rewards"));
36526
+ let shares = Web3Number.fromWei(0, 18);
36527
+ for (let i = len - 1; i > 0; --i) {
36528
+ let record = await this.contract.call("get_rewards_info", [i]);
36529
+ logger2.verbose(`${_EkuboCLVault.name}: getHarvestRewardShares: ${i}`);
36530
+ console.log(record);
36531
+ const block = Number(record.block_number);
36532
+ if (block < fromBlock) {
36533
+ return shares;
36534
+ } else if (block > toBlock) {
36535
+ continue;
36536
+ } else {
36537
+ shares = shares.plus(Web3Number.fromWei(record.shares.toString(), 18));
36538
+ }
36539
+ logger2.verbose(`${_EkuboCLVault.name}: getHarvestRewardShares: ${i} => ${shares.toWei()}`);
36540
+ }
36541
+ return shares;
36364
36542
  }
36365
- async getTVL() {
36366
- const result = await this.contract.call("total_liquidity", []);
36367
- const bounds = await this.getCurrentBounds();
36368
- const { amount0, amount1 } = await this.getLiquidityToAmounts(Web3Number.fromWei(result.toString(), 18), bounds);
36369
- const poolKey = await this.getPoolKey();
36543
+ async balanceOf(user, blockIdentifier = "pending") {
36544
+ let bal = await this.contract.call("balance_of", [user.address]);
36545
+ return Web3Number.fromWei(bal.toString(), 18);
36546
+ }
36547
+ async getUserTVL(user, blockIdentifier = "pending") {
36548
+ let bal = await this.balanceOf(user, blockIdentifier);
36549
+ const assets = await this.contract.call("convert_to_assets", [uint256_exports.bnToUint256(bal.toWei())], {
36550
+ blockIdentifier
36551
+ });
36552
+ const poolKey = await this.getPoolKey(blockIdentifier);
36553
+ this.assertValidDepositTokens(poolKey);
36554
+ const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
36555
+ const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
36556
+ const amount0 = Web3Number.fromWei(assets.amount0.toString(), token0Info.decimals);
36557
+ const amount1 = Web3Number.fromWei(assets.amount1.toString(), token1Info.decimals);
36558
+ const P0 = await this.pricer.getPrice(token0Info.symbol);
36559
+ const P1 = await this.pricer.getPrice(token1Info.symbol);
36560
+ const token0Usd = Number(amount0.toFixed(13)) * P0.price;
36561
+ const token1Usd = Number(amount1.toFixed(13)) * P1.price;
36562
+ return {
36563
+ usdValue: token0Usd + token1Usd,
36564
+ token0: {
36565
+ tokenInfo: token0Info,
36566
+ amount: amount0,
36567
+ usdValue: token0Usd
36568
+ },
36569
+ token1: {
36570
+ tokenInfo: token1Info,
36571
+ amount: amount1,
36572
+ usdValue: token1Usd
36573
+ }
36574
+ };
36575
+ }
36576
+ async _getTVL(blockIdentifier = "pending") {
36577
+ const result = await this.contract.call("total_liquidity", [], {
36578
+ blockIdentifier
36579
+ });
36580
+ const bounds = await this.getCurrentBounds(blockIdentifier);
36581
+ const { amount0, amount1 } = await this.getLiquidityToAmounts(Web3Number.fromWei(result.toString(), 18), bounds, blockIdentifier);
36582
+ return { amount0, amount1 };
36583
+ }
36584
+ async totalSupply(blockIdentifier = "pending") {
36585
+ const res = await this.contract.call("total_supply", [], {
36586
+ blockIdentifier
36587
+ });
36588
+ return Web3Number.fromWei(res.toString(), 18);
36589
+ }
36590
+ assertValidDepositTokens(poolKey) {
36591
+ assert3(poolKey.token0.eq(this.metadata.depositTokens[0].address), "Expected token0 in depositTokens[0]");
36592
+ assert3(poolKey.token1.eq(this.metadata.depositTokens[1].address), "Expected token1 in depositTokens[1]");
36593
+ }
36594
+ async getTVL(blockIdentifier = "pending") {
36595
+ const { amount0, amount1 } = await this._getTVL(blockIdentifier);
36596
+ const poolKey = await this.getPoolKey(blockIdentifier);
36597
+ this.assertValidDepositTokens(poolKey);
36370
36598
  const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
36371
36599
  const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
36372
36600
  const P0 = await this.pricer.getPrice(token0Info.symbol);
@@ -36374,7 +36602,7 @@ ${JSON.stringify(data, null, 2)}`;
36374
36602
  const token0Usd = Number(amount0.toFixed(13)) * P0.price;
36375
36603
  const token1Usd = Number(amount1.toFixed(13)) * P1.price;
36376
36604
  return {
36377
- netUsdValue: token0Usd + token1Usd,
36605
+ usdValue: token0Usd + token1Usd,
36378
36606
  token0: {
36379
36607
  tokenInfo: token0Info,
36380
36608
  amount: amount0,
@@ -36414,7 +36642,7 @@ ${JSON.stringify(data, null, 2)}`;
36414
36642
  const token0Usd = Number(token0Web3.toFixed(13)) * P0.price;
36415
36643
  const token1Usd = Number(token1Web3.toFixed(13)) * P1.price;
36416
36644
  return {
36417
- netUsdValue: token0Usd + token1Usd,
36645
+ usdValue: token0Usd + token1Usd,
36418
36646
  token0: {
36419
36647
  tokenInfo: token0Info,
36420
36648
  amount: token0Web3,
@@ -36436,11 +36664,11 @@ ${JSON.stringify(data, null, 2)}`;
36436
36664
  const truePrice = Number(BigInt(result.toString()) * BigInt(1e9) / BigInt(1e18)) / 1e9;
36437
36665
  return truePrice;
36438
36666
  }
36439
- async getCurrentPrice() {
36440
- const poolKey = await this.getPoolKey();
36441
- return this._getCurrentPrice(poolKey);
36667
+ async getCurrentPrice(blockIdentifier = "pending") {
36668
+ const poolKey = await this.getPoolKey(blockIdentifier);
36669
+ return this._getCurrentPrice(poolKey, blockIdentifier);
36442
36670
  }
36443
- async _getCurrentPrice(poolKey) {
36671
+ async _getCurrentPrice(poolKey, blockIdentifier = "pending") {
36444
36672
  const priceInfo = await this.ekuboPositionsContract.call("get_pool_price", [
36445
36673
  {
36446
36674
  token0: poolKey.token0.address,
@@ -36449,17 +36677,24 @@ ${JSON.stringify(data, null, 2)}`;
36449
36677
  tick_spacing: poolKey.tick_spacing,
36450
36678
  extension: poolKey.extension
36451
36679
  }
36452
- ]);
36680
+ ], {
36681
+ blockIdentifier
36682
+ });
36453
36683
  const sqrtRatio = _EkuboCLVault.div2Power128(BigInt(priceInfo.sqrt_ratio.toString()));
36684
+ console.log(`EkuboCLVault: getCurrentPrice: blockIdentifier: ${blockIdentifier}, sqrtRatio: ${sqrtRatio}, ${priceInfo.sqrt_ratio.toString()}`);
36454
36685
  const price = sqrtRatio * sqrtRatio;
36455
36686
  const tick = _EkuboCLVault.priceToTick(price, true, Number(poolKey.tick_spacing));
36687
+ console.log(`EkuboCLVault: getCurrentPrice: blockIdentifier: ${blockIdentifier}, price: ${price}, tick: ${tick.mag}, ${tick.sign}`);
36456
36688
  return {
36457
36689
  price,
36458
- tick: tick.mag * (tick.sign == 0 ? 1 : -1)
36690
+ tick: tick.mag * (tick.sign == 0 ? 1 : -1),
36691
+ sqrtRatio: priceInfo.sqrt_ratio.toString()
36459
36692
  };
36460
36693
  }
36461
- async getCurrentBounds() {
36462
- const result = await this.contract.call("get_position_key", []);
36694
+ async getCurrentBounds(blockIdentifier = "pending") {
36695
+ const result = await this.contract.call("get_position_key", [], {
36696
+ blockIdentifier
36697
+ });
36463
36698
  return {
36464
36699
  lowerTick: _EkuboCLVault.i129ToNumber(result.bounds.lower),
36465
36700
  upperTick: _EkuboCLVault.i129ToNumber(result.bounds.upper)
@@ -36473,11 +36708,13 @@ ${JSON.stringify(data, null, 2)}`;
36473
36708
  const tick = Math.floor(value / tickSpacing) * tickSpacing;
36474
36709
  return this.tickToi129(tick);
36475
36710
  }
36476
- async getPoolKey() {
36711
+ async getPoolKey(blockIdentifier = "pending") {
36477
36712
  if (this.poolKey) {
36478
36713
  return this.poolKey;
36479
36714
  }
36480
- const result = await this.contract.call("get_settings", []);
36715
+ const result = await this.contract.call("get_settings", [], {
36716
+ blockIdentifier
36717
+ });
36481
36718
  const poolKey = {
36482
36719
  token0: ContractAddr.from(result.pool_key.token0.toString()),
36483
36720
  token1: ContractAddr.from(result.pool_key.token1.toString()),
@@ -36508,25 +36745,24 @@ ${JSON.stringify(data, null, 2)}`;
36508
36745
  * @param amount1: amount of token1
36509
36746
  * @returns {amount0, amount1}
36510
36747
  */
36511
- async _getExpectedAmountsForLiquidity(amount0, amount1, bounds) {
36748
+ async _getExpectedAmountsForLiquidity(amount0, amount1, bounds, justUseInputAmount = true) {
36512
36749
  assert3(amount0.greaterThan(0) || amount1.greaterThan(0), "Amount is 0");
36513
- const poolKey = await this.getPoolKey();
36514
- const sampleLiq = 1e18;
36750
+ const sampleLiq = 1e20;
36515
36751
  const { amount0: sampleAmount0, amount1: sampleAmount1 } = await this.getLiquidityToAmounts(Web3Number.fromWei(sampleLiq.toString(), 18), bounds);
36516
36752
  logger2.verbose(`${_EkuboCLVault.name}: _getExpectedAmountsForLiquidity => sampleAmount0: ${sampleAmount0.toString()}, sampleAmount1: ${sampleAmount1.toString()}`);
36517
- assert3(!sampleAmount0.eq(0) && !sampleAmount1.eq(0), "Sample amount is 0");
36753
+ assert3(!sampleAmount0.eq(0) || !sampleAmount1.eq(0), "Sample amount is 0");
36518
36754
  const price = await (await this.getCurrentPrice()).price;
36519
36755
  logger2.verbose(`${_EkuboCLVault.name}: _getExpectedAmountsForLiquidity => price: ${price}`);
36520
36756
  if (amount1.eq(0) && amount0.greaterThan(0)) {
36521
36757
  if (sampleAmount1.eq(0)) {
36522
36758
  return {
36523
36759
  amount0,
36524
- amount1: Web3Number.fromWei("0", 18),
36760
+ amount1: Web3Number.fromWei("0", amount1.decimals),
36525
36761
  ratio: Infinity
36526
36762
  };
36527
36763
  } else if (sampleAmount0.eq(0)) {
36528
36764
  return {
36529
- amount0: Web3Number.fromWei("0", 18),
36765
+ amount0: Web3Number.fromWei("0", amount0.decimals),
36530
36766
  amount1: amount0.multipliedBy(price),
36531
36767
  ratio: 0
36532
36768
  };
@@ -36534,21 +36770,41 @@ ${JSON.stringify(data, null, 2)}`;
36534
36770
  } else if (amount0.eq(0) && amount1.greaterThan(0)) {
36535
36771
  if (sampleAmount0.eq(0)) {
36536
36772
  return {
36537
- amount0: Web3Number.fromWei("0", 18),
36773
+ amount0: Web3Number.fromWei("0", amount0.decimals),
36538
36774
  amount1,
36539
36775
  ratio: 0
36540
36776
  };
36541
36777
  } else if (sampleAmount1.eq(0)) {
36542
36778
  return {
36543
36779
  amount0: amount1.dividedBy(price),
36544
- amount1: Web3Number.fromWei("0", 18),
36780
+ amount1: Web3Number.fromWei("0", amount1.decimals),
36545
36781
  ratio: Infinity
36546
36782
  };
36547
36783
  }
36548
36784
  }
36549
- const ratio = sampleAmount0.multipliedBy(1e18).dividedBy(sampleAmount1.toString()).dividedBy(1e18);
36785
+ assert3(sampleAmount0.decimals == sampleAmount1.decimals, "Sample amounts have different decimals");
36786
+ const ratioWeb3Number = sampleAmount0.multipliedBy(1e18).dividedBy(sampleAmount1.toString()).dividedBy(1e18);
36787
+ const ratio = Number(ratioWeb3Number.toFixed(18));
36550
36788
  logger2.verbose(`${_EkuboCLVault.name}: ${this.metadata.name} => ratio: ${ratio.toString()}`);
36551
- return this._solveExpectedAmountsEq(amount0, amount1, ratio, price);
36789
+ if (justUseInputAmount)
36790
+ return this._solveExpectedAmountsEq(amount0, amount1, ratioWeb3Number, price);
36791
+ if (amount1.eq(0) && amount0.greaterThan(0)) {
36792
+ const _amount1 = amount0.dividedBy(ratioWeb3Number);
36793
+ return {
36794
+ amount0,
36795
+ amount1: _amount1,
36796
+ ratio
36797
+ };
36798
+ } else if (amount0.eq(0) && amount1.greaterThan(0)) {
36799
+ const _amount0 = amount1.multipliedBy(ratio);
36800
+ return {
36801
+ amount0: _amount0,
36802
+ amount1,
36803
+ ratio
36804
+ };
36805
+ } else {
36806
+ throw new Error("Both amounts are non-zero, cannot compute expected amounts");
36807
+ }
36552
36808
  }
36553
36809
  _solveExpectedAmountsEq(availableAmount0, availableAmount1, ratio, price) {
36554
36810
  const y = ratio.multipliedBy(availableAmount1).minus(availableAmount0).dividedBy(ratio.plus(1 / price));
@@ -36562,10 +36818,11 @@ ${JSON.stringify(data, null, 2)}`;
36562
36818
  async getSwapInfoToHandleUnused(considerRebalance = true) {
36563
36819
  const poolKey = await this.getPoolKey();
36564
36820
  const erc20Mod = new ERC20(this.config);
36565
- const token0Bal1 = await erc20Mod.balanceOf(poolKey.token0, this.address.address, 18);
36566
- const token1Bal1 = await erc20Mod.balanceOf(poolKey.token1, this.address.address, 18);
36567
36821
  const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
36568
36822
  const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
36823
+ const token0Bal1 = await erc20Mod.balanceOf(poolKey.token0, this.address.address, token0Info.decimals);
36824
+ const token1Bal1 = await erc20Mod.balanceOf(poolKey.token1, this.address.address, token1Info.decimals);
36825
+ logger2.verbose(`${_EkuboCLVault.name}: getSwapInfoToHandleUnused => token0Bal1: ${token0Bal1.toString()}, token1Bal1: ${token1Bal1.toString()}`);
36569
36826
  const token0Price = await this.pricer.getPrice(token0Info.symbol);
36570
36827
  const token1Price = await this.pricer.getPrice(token1Info.symbol);
36571
36828
  const token0PriceUsd = token0Price.price * Number(token0Bal1.toFixed(13));
@@ -36576,6 +36833,7 @@ ${JSON.stringify(data, null, 2)}`;
36576
36833
  let token0Bal = token0Bal1;
36577
36834
  let token1Bal = token1Bal1;
36578
36835
  if (considerRebalance) {
36836
+ logger2.verbose(`${_EkuboCLVault.name}: getSwapInfoToHandleUnused => considerRebalance: true`);
36579
36837
  const tvl = await this.getTVL();
36580
36838
  token0Bal = token0Bal.plus(tvl.token0.amount.toString());
36581
36839
  token1Bal = token1Bal.plus(tvl.token1.amount.toString());
@@ -36585,7 +36843,10 @@ ${JSON.stringify(data, null, 2)}`;
36585
36843
  logger2.verbose(`${_EkuboCLVault.name}: getSwapInfoToHandleUnused => token0Bal: ${token0Bal.toString()}, token1Bal: ${token1Bal.toString()}`);
36586
36844
  const newBounds = await this.getNewBounds();
36587
36845
  logger2.verbose(`${_EkuboCLVault.name}: getSwapInfoToHandleUnused => newBounds: ${newBounds.lowerTick}, ${newBounds.upperTick}`);
36588
- let expectedAmounts = await this._getExpectedAmountsForLiquidity(token0Bal, token1Bal, newBounds);
36846
+ return await this.getSwapInfoGivenAmounts(poolKey, token0Bal, token1Bal, newBounds);
36847
+ }
36848
+ async getSwapInfoGivenAmounts(poolKey, token0Bal, token1Bal, bounds) {
36849
+ let expectedAmounts = await this._getExpectedAmountsForLiquidity(token0Bal, token1Bal, bounds);
36589
36850
  logger2.verbose(`${_EkuboCLVault.name}: getSwapInfoToHandleUnused => expectedAmounts: ${expectedAmounts.amount0.toString()}, ${expectedAmounts.amount1.toString()}`);
36590
36851
  let retry = 0;
36591
36852
  const maxRetry = 10;
@@ -36606,6 +36867,19 @@ ${JSON.stringify(data, null, 2)}`;
36606
36867
  logger2.verbose(`${_EkuboCLVault.name}: getSwapInfoToHandleUnused => tokenToSell: ${tokenToSell.address}, tokenToBuy: ${tokenToBuy.address}, amountToSell: ${amountToSell.toWei()}`);
36607
36868
  logger2.verbose(`${_EkuboCLVault.name}: getSwapInfoToHandleUnused => remainingSellAmount: ${remainingSellAmount.toString()}`);
36608
36869
  logger2.verbose(`${_EkuboCLVault.name}: getSwapInfoToHandleUnused => expectedRatio: ${expectedRatio}`);
36870
+ if (amountToSell.eq(0)) {
36871
+ return {
36872
+ token_from_address: tokenToSell.address,
36873
+ token_from_amount: uint256_exports.bnToUint256(0),
36874
+ token_to_address: tokenToSell.address,
36875
+ token_to_amount: uint256_exports.bnToUint256(0),
36876
+ token_to_min_amount: uint256_exports.bnToUint256(0),
36877
+ beneficiary: this.address.address,
36878
+ integrator_fee_amount_bps: 0,
36879
+ integrator_fee_recipient: this.address.address,
36880
+ routes: []
36881
+ };
36882
+ }
36609
36883
  const quote = await this.avnu.getQuotes(tokenToSell.address, tokenToBuy.address, amountToSell.toWei(), this.address.address);
36610
36884
  if (remainingSellAmount.eq(0)) {
36611
36885
  const minAmountOut = Web3Number.fromWei(quote.buyAmount.toString(), tokenToBuyInfo.decimals).multipliedBy(0.9999);
@@ -36628,6 +36902,73 @@ ${JSON.stringify(data, null, 2)}`;
36628
36902
  }
36629
36903
  throw new Error("Failed to get swap info");
36630
36904
  }
36905
+ /**
36906
+ * Attempts to rebalance the vault by iteratively adjusting swap amounts if initial attempt fails.
36907
+ * Uses binary search approach to find optimal swap amount.
36908
+ *
36909
+ * @param newBounds - The new tick bounds to rebalance to
36910
+ * @param swapInfo - Initial swap parameters for rebalancing
36911
+ * @param acc - Account to estimate gas fees with
36912
+ * @param retry - Current retry attempt number (default 0)
36913
+ * @param adjustmentFactor - Percentage to adjust swap amount by (default 1)
36914
+ * @param isToken0Deficit - Whether token0 balance needs increasing (default true)
36915
+ * @returns Array of contract calls needed for rebalancing
36916
+ * @throws Error if max retries reached without successful rebalance
36917
+ */
36918
+ async rebalanceIter(swapInfo, acc, estimateCall, retry = 0, adjustmentFactor = 1, isToken0Deficit = true) {
36919
+ const MAX_RETRIES = 20;
36920
+ const MIN_ADJUSTMENT = 1e-3;
36921
+ logger2.verbose(
36922
+ `Rebalancing ${this.metadata.name}: retry=${retry}, adjustment=${adjustmentFactor}%, token0Deficit=${isToken0Deficit}`
36923
+ );
36924
+ const fromAmount = uint256_exports.uint256ToBN(swapInfo.token_from_amount);
36925
+ logger2.verbose(
36926
+ `Selling ${fromAmount.toString()} of token ${swapInfo.token_from_address}`
36927
+ );
36928
+ try {
36929
+ const calls = await estimateCall(swapInfo);
36930
+ await acc.estimateInvokeFee(calls);
36931
+ return calls;
36932
+ } catch (err2) {
36933
+ if (retry >= MAX_RETRIES) {
36934
+ logger2.error(`Rebalance failed after ${MAX_RETRIES} retries`);
36935
+ throw err2;
36936
+ }
36937
+ if (adjustmentFactor < MIN_ADJUSTMENT) {
36938
+ logger2.error("Adjustment factor too small, likely oscillating");
36939
+ throw new Error("Failed to converge on valid swap amount");
36940
+ }
36941
+ logger2.error(`Rebalance attempt ${retry + 1} failed, adjusting swap amount...`);
36942
+ const newSwapInfo = { ...swapInfo };
36943
+ const currentAmount = Web3Number.fromWei(fromAmount.toString(), 18);
36944
+ if (err2.message.includes("invalid token0 balance") || err2.message.includes("invalid token0 amount")) {
36945
+ logger2.verbose("Reducing swap amount - excess token0");
36946
+ newSwapInfo.token_from_amount = uint256_exports.bnToUint256(
36947
+ currentAmount.multipliedBy((100 - adjustmentFactor) / 100).toWei()
36948
+ );
36949
+ adjustmentFactor = isToken0Deficit ? adjustmentFactor * 2 : adjustmentFactor / 2;
36950
+ isToken0Deficit = true;
36951
+ } else if (err2.message.includes("invalid token1 balance") || err2.message.includes("invalid token1 amount")) {
36952
+ logger2.verbose("Increasing swap amount - excess token1");
36953
+ newSwapInfo.token_from_amount = uint256_exports.bnToUint256(
36954
+ currentAmount.multipliedBy((100 + adjustmentFactor) / 100).toWei()
36955
+ );
36956
+ adjustmentFactor = isToken0Deficit ? adjustmentFactor / 2 : adjustmentFactor * 2;
36957
+ isToken0Deficit = false;
36958
+ } else {
36959
+ logger2.error("Unexpected error:", err2);
36960
+ }
36961
+ newSwapInfo.token_to_min_amount = uint256_exports.bnToUint256("0");
36962
+ return this.rebalanceIter(
36963
+ newSwapInfo,
36964
+ acc,
36965
+ estimateCall,
36966
+ retry + 1,
36967
+ adjustmentFactor,
36968
+ isToken0Deficit
36969
+ );
36970
+ }
36971
+ }
36631
36972
  static tickToi129(tick) {
36632
36973
  if (tick < 0) {
36633
36974
  return {
@@ -36650,21 +36991,23 @@ ${JSON.stringify(data, null, 2)}`;
36650
36991
  static tickToPrice(tick) {
36651
36992
  return Math.pow(1.000001, Number(tick));
36652
36993
  }
36653
- async getLiquidityToAmounts(liquidity, bounds) {
36654
- const currentPrice = await this.getCurrentPrice();
36655
- const lowerPrice = await _EkuboCLVault.tickToPrice(bounds.lowerTick);
36656
- const upperPrice = await _EkuboCLVault.tickToPrice(bounds.upperTick);
36994
+ async getLiquidityToAmounts(liquidity, bounds, blockIdentifier = "pending", _poolKey = null, _currentPrice = null) {
36995
+ const currentPrice = _currentPrice || await this.getCurrentPrice(blockIdentifier);
36996
+ const lowerPrice = _EkuboCLVault.tickToPrice(bounds.lowerTick);
36997
+ const upperPrice = _EkuboCLVault.tickToPrice(bounds.upperTick);
36657
36998
  logger2.verbose(`${_EkuboCLVault.name}: getLiquidityToAmounts => currentPrice: ${currentPrice.price}, lowerPrice: ${lowerPrice}, upperPrice: ${upperPrice}`);
36658
36999
  const result = await this.ekuboMathContract.call("liquidity_delta_to_amount_delta", [
36659
- uint256_exports.bnToUint256(_EkuboCLVault.priceToSqrtRatio(currentPrice.price).toString()),
37000
+ uint256_exports.bnToUint256(currentPrice.sqrtRatio),
36660
37001
  {
36661
37002
  mag: liquidity.toWei(),
36662
37003
  sign: 0
36663
37004
  },
36664
37005
  uint256_exports.bnToUint256(_EkuboCLVault.priceToSqrtRatio(lowerPrice).toString()),
36665
37006
  uint256_exports.bnToUint256(_EkuboCLVault.priceToSqrtRatio(upperPrice).toString())
36666
- ]);
36667
- const poolKey = await this.getPoolKey();
37007
+ ], {
37008
+ blockIdentifier
37009
+ });
37010
+ const poolKey = _poolKey || await this.getPoolKey(blockIdentifier);
36668
37011
  const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
36669
37012
  const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
36670
37013
  const amount0 = Web3Number.fromWei(_EkuboCLVault.i129ToNumber(result.amount0).toString(), token0Info.decimals);
@@ -36674,32 +37017,110 @@ ${JSON.stringify(data, null, 2)}`;
36674
37017
  amount1
36675
37018
  };
36676
37019
  }
37020
+ async harvest(acc) {
37021
+ const ekuboHarvests = new EkuboHarvests(this.config);
37022
+ const unClaimedRewards = await ekuboHarvests.getUnHarvestedRewards(this.address);
37023
+ const poolKey = await this.getPoolKey();
37024
+ const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
37025
+ const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
37026
+ const bounds = await this.getCurrentBounds();
37027
+ const calls = [];
37028
+ for (let claim of unClaimedRewards) {
37029
+ const fee = claim.claim.amount.multipliedBy(this.metadata.additionalInfo.feeBps).dividedBy(1e4);
37030
+ const postFeeAmount = claim.claim.amount.minus(fee);
37031
+ const isToken1 = claim.token.eq(poolKey.token1);
37032
+ logger2.verbose(`${_EkuboCLVault.name}: harvest => Processing claim, isToken1: ${isToken1} amount: ${postFeeAmount.toWei()}`);
37033
+ const token0Amt = isToken1 ? new Web3Number(0, token0Info.decimals) : postFeeAmount;
37034
+ const token1Amt = isToken1 ? postFeeAmount : new Web3Number(0, token0Info.decimals);
37035
+ logger2.verbose(`${_EkuboCLVault.name}: harvest => token0Amt: ${token0Amt.toString()}, token1Amt: ${token1Amt.toString()}`);
37036
+ const swapInfo = await this.getSwapInfoGivenAmounts(poolKey, token0Amt, token1Amt, bounds);
37037
+ swapInfo.token_to_address = token0Info.address.address;
37038
+ logger2.verbose(`${_EkuboCLVault.name}: harvest => swapInfo: ${JSON.stringify(swapInfo)}`);
37039
+ logger2.verbose(`${_EkuboCLVault.name}: harvest => claim: ${JSON.stringify(claim)}`);
37040
+ const harvestEstimateCall = async (swapInfo1) => {
37041
+ const swap1Amount = Web3Number.fromWei(uint256_exports.uint256ToBN(swapInfo1.token_from_amount).toString(), 18);
37042
+ const remainingAmount = postFeeAmount.minus(swap1Amount);
37043
+ const swapInfo2 = { ...swapInfo, token_from_amount: uint256_exports.bnToUint256(remainingAmount.toWei()) };
37044
+ swapInfo2.token_to_address = token1Info.address.address;
37045
+ const calldata = [
37046
+ claim.rewardsContract.address,
37047
+ {
37048
+ id: claim.claim.id,
37049
+ amount: claim.claim.amount.toWei(),
37050
+ claimee: claim.claim.claimee.address
37051
+ },
37052
+ claim.proof.map((p) => num_exports.getDecimalString(p)),
37053
+ swapInfo,
37054
+ swapInfo2
37055
+ ];
37056
+ logger2.verbose(`${_EkuboCLVault.name}: harvest => calldata: ${JSON.stringify(calldata)}`);
37057
+ return [this.contract.populate("harvest", calldata)];
37058
+ };
37059
+ const _callsFinal = await this.rebalanceIter(swapInfo, acc, harvestEstimateCall);
37060
+ logger2.verbose(`${_EkuboCLVault.name}: harvest => _callsFinal: ${JSON.stringify(_callsFinal)}`);
37061
+ calls.push(..._callsFinal);
37062
+ }
37063
+ return calls;
37064
+ }
37065
+ async getInvestmentFlows() {
37066
+ const netYield = await this.netAPY();
37067
+ const poolKey = await this.getPoolKey();
37068
+ const linkedFlow = {
37069
+ title: this.metadata.name,
37070
+ subItems: [{ key: "Pool", value: `${(_EkuboCLVault.div2Power128(BigInt(poolKey.fee)) * 100).toFixed(2)}%, ${poolKey.tick_spacing} tick spacing` }],
37071
+ linkedFlows: [],
37072
+ style: { backgroundColor: "#35484f" /* Blue */.valueOf() }
37073
+ };
37074
+ const baseFlow = {
37075
+ id: "base",
37076
+ title: "Your Deposit",
37077
+ subItems: [{ key: `Net yield`, value: `${(netYield * 100).toFixed(2)}%` }, { key: `Performance Fee`, value: `${(this.metadata.additionalInfo.feeBps / 100).toFixed(2)}%` }],
37078
+ linkedFlows: [linkedFlow],
37079
+ style: { backgroundColor: "#6e53dc" /* Purple */.valueOf() }
37080
+ };
37081
+ const rebalanceFlow = {
37082
+ id: "rebalance",
37083
+ title: "Automated Rebalance",
37084
+ subItems: [{
37085
+ key: "Range selection",
37086
+ value: `${this.metadata.additionalInfo.newBounds.lower * Number(poolKey.tick_spacing)} to ${this.metadata.additionalInfo.newBounds.upper * Number(poolKey.tick_spacing)} ticks`
37087
+ }],
37088
+ linkedFlows: [linkedFlow],
37089
+ style: { backgroundColor: "purple" /* Green */.valueOf() }
37090
+ };
37091
+ return [baseFlow, rebalanceFlow];
37092
+ }
36677
37093
  };
36678
- var _description2 = "Automatically rebalances liquidity near current price to maximize yield while reducing the necessity to manually rebalance positions frequently. Fees earn and Defi spring rewards are automatically re-invested.";
37094
+ var _description2 = "Deploys your {{POOL_NAME}} into an Ekubo liquidity pool, automatically rebalancing positions around the current price to optimize yield and reduce the need for manual adjustments. Trading fees and DeFi Spring rewards are automatically compounded back into the strategy. In return, you receive an ERC-20 token representing your share of the strategy. The APY is calculated based on 7-day historical performance.";
36679
37095
  var _protocol2 = { name: "Ekubo", logo: "https://app.ekubo.org/favicon.ico" };
36680
37096
  var _riskFactor2 = [
36681
37097
  { type: "Smart Contract Risk" /* SMART_CONTRACT_RISK */, value: 0.5, weight: 25 },
36682
37098
  { type: "Impermanent Loss Risk" /* IMPERMANENT_LOSS */, value: 1, weight: 75 }
36683
37099
  ];
37100
+ var AUDIT_URL2 = "https://assets.strkfarm.com/strkfarm/audit_report_vesu_and_ekubo_strats.pdf";
36684
37101
  var EkuboCLVaultStrategies = [{
36685
37102
  name: "Ekubo xSTRK/STRK",
36686
- description: _description2,
37103
+ description: _description2.replace("{{POOL_NAME}}", "xSTRK/STRK"),
36687
37104
  address: ContractAddr.from("0x01f083b98674bc21effee29ef443a00c7b9a500fd92cf30341a3da12c73f2324"),
36688
37105
  type: "Other",
36689
- depositTokens: [Global.getDefaultTokens().find((t) => t.symbol === "STRK"), Global.getDefaultTokens().find((t) => t.symbol === "xSTRK")],
37106
+ // must be same order as poolKey token0 and token1
37107
+ depositTokens: [Global.getDefaultTokens().find((t) => t.symbol === "xSTRK"), Global.getDefaultTokens().find((t) => t.symbol === "STRK")],
36690
37108
  protocols: [_protocol2],
37109
+ auditUrl: AUDIT_URL2,
36691
37110
  maxTVL: Web3Number.fromWei("0", 18),
36692
37111
  risk: {
36693
37112
  riskFactor: _riskFactor2,
36694
37113
  netRisk: _riskFactor2.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor2.reduce((acc, curr) => acc + curr.weight, 0),
36695
37114
  notARisks: getNoRiskTags(_riskFactor2)
36696
37115
  },
37116
+ apyMethodology: "APY based on 7-day historical performance, including fees and rewards.",
36697
37117
  additionalInfo: {
36698
37118
  newBounds: {
36699
37119
  lower: -1,
36700
37120
  upper: 1
36701
37121
  },
36702
- lstContract: ContractAddr.from("0x028d709c875c0ceac3dce7065bec5328186dc89fe254527084d1689910954b0a")
37122
+ lstContract: ContractAddr.from("0x028d709c875c0ceac3dce7065bec5328186dc89fe254527084d1689910954b0a"),
37123
+ feeBps: 1e3
36703
37124
  }
36704
37125
  }];
36705
37126
  return __toCommonJS(index_browser_exports);