@strkfarm/sdk 1.1.70 → 2.0.0-dev.1

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.
Files changed (53) hide show
  1. package/dist/cli.js +2 -2
  2. package/dist/cli.mjs +2 -2
  3. package/dist/index.browser.global.js +66861 -59746
  4. package/dist/index.browser.mjs +24970 -18579
  5. package/dist/index.d.ts +1969 -776
  6. package/dist/index.js +25264 -18850
  7. package/dist/index.mjs +25463 -19089
  8. package/package.json +80 -76
  9. package/src/data/extended-deposit.abi.json +3613 -0
  10. package/src/data/universal-vault.abi.json +135 -20
  11. package/src/dataTypes/address.ts +8 -1
  12. package/src/global.ts +240 -193
  13. package/src/interfaces/common.tsx +26 -2
  14. package/src/modules/ExtendedWrapperSDk/index.ts +62 -0
  15. package/src/modules/ExtendedWrapperSDk/types.ts +311 -0
  16. package/src/modules/ExtendedWrapperSDk/wrapper.ts +395 -0
  17. package/src/modules/avnu.ts +17 -4
  18. package/src/modules/ekubo-quoter.ts +98 -10
  19. package/src/modules/erc20.ts +67 -21
  20. package/src/modules/harvests.ts +16 -29
  21. package/src/modules/index.ts +5 -1
  22. package/src/modules/lst-apr.ts +36 -0
  23. package/src/modules/midas.ts +159 -0
  24. package/src/modules/pricer-from-api.ts +2 -2
  25. package/src/modules/pricer-lst.ts +1 -1
  26. package/src/modules/pricer.ts +3 -38
  27. package/src/modules/token-market-data.ts +202 -0
  28. package/src/node/deployer.ts +1 -36
  29. package/src/strategies/autoCompounderStrk.ts +1 -1
  30. package/src/strategies/base-strategy.ts +20 -3
  31. package/src/strategies/ekubo-cl-vault.tsx +123 -306
  32. package/src/strategies/index.ts +4 -1
  33. package/src/strategies/svk-strategy.ts +247 -0
  34. package/src/strategies/universal-adapters/adapter-optimizer.ts +65 -0
  35. package/src/strategies/universal-adapters/adapter-utils.ts +5 -1
  36. package/src/strategies/universal-adapters/avnu-adapter.ts +418 -0
  37. package/src/strategies/universal-adapters/baseAdapter.ts +181 -153
  38. package/src/strategies/universal-adapters/common-adapter.ts +98 -77
  39. package/src/strategies/universal-adapters/extended-adapter.ts +544 -0
  40. package/src/strategies/universal-adapters/index.ts +5 -1
  41. package/src/strategies/universal-adapters/unused-balance-adapter.ts +109 -0
  42. package/src/strategies/universal-adapters/vesu-adapter.ts +220 -218
  43. package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +924 -0
  44. package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +58 -51
  45. package/src/strategies/universal-lst-muliplier-strategy.tsx +707 -774
  46. package/src/strategies/universal-strategy.tsx +1098 -1180
  47. package/src/strategies/vesu-extended-strategy/services/operationService.ts +28 -0
  48. package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +77 -0
  49. package/src/strategies/vesu-extended-strategy/utils/constants.ts +48 -0
  50. package/src/strategies/vesu-extended-strategy/utils/helper.ts +374 -0
  51. package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +992 -0
  52. package/src/strategies/vesu-rebalance.tsx +16 -19
  53. package/src/utils/health-factor-math.ts +11 -5
@@ -8,6 +8,7 @@ import {
8
8
  IInvestmentFlow,
9
9
  IProtocol,
10
10
  IStrategyMetadata,
11
+ Protocols,
11
12
  RiskFactor,
12
13
  RiskType,
13
14
  TokenInfo,
@@ -29,7 +30,7 @@ import EkuboMathAbi from "@/data/ekubo-math.abi.json";
29
30
  import ERC4626Abi from "@/data/erc4626.abi.json";
30
31
  import { Global } from "@/global";
31
32
  import { AvnuWrapper, ERC20, SwapInfo } from "@/modules";
32
- import { BaseStrategy } from "./base-strategy";
33
+ import { APYInfo, BaseStrategy, SingleTokenInfo } from "./base-strategy";
33
34
  import { DualActionAmount } from "./base-strategy";
34
35
  import { DualTokenInfo } from "./base-strategy";
35
36
  import { log } from "winston";
@@ -37,10 +38,10 @@ import { EkuboHarvests, HarvestInfo } from "@/modules/harvests";
37
38
  import { logger } from "@/utils/logger";
38
39
  import { COMMON_CONTRACTS } from "./constants";
39
40
  import { DepegRiskLevel, ImpermanentLossLevel, MarketRiskLevel, SmartContractRiskLevel } from "@/interfaces/risks";
40
- import { from, gql } from "@apollo/client";
41
+ import { gql } from "@apollo/client";
41
42
  import apolloClient from "@/modules/apollo-client";
42
43
  import { binarySearch } from "@/utils/math-utils";
43
- import { Quote } from "@avnu/avnu-sdk";
44
+ import { PositionInfo } from "./universal-adapters/baseAdapter";
44
45
 
45
46
  export interface EkuboPoolKey {
46
47
  token0: ContractAddr;
@@ -417,41 +418,22 @@ export class EkuboCLVault extends BaseStrategy<
417
418
  const tvlBefore = await this._getTVL(blockBefore);
418
419
  const supplyBefore = await this.totalSupply(blockBefore);
419
420
  const priceBefore = await this.getCurrentPrice(blockBefore);
420
- const poolKey = await this.getPoolKey(blockBefore);
421
- logger.verbose(`priceBefore: ${priceBefore.price.toString()}`);
422
- logger.verbose(`priceNow: ${priceNow.price.toString()}`);
423
- logger.verbose(`tvlBefore: ${JSON.stringify(tvlBefore)}`);
424
- logger.verbose(`tvlNow: ${JSON.stringify(tvlNow)}`);
425
-
426
- const isQuoteTokenToken0 = this.metadata.additionalInfo.quoteAsset.address.eq(poolKey.token0);
427
- logger.verbose(`isQuoteTokenToken0: ${isQuoteTokenToken0}`);
428
- let tvlBeforeInBaseAsset = Web3Number.fromWei(0, this.metadata.additionalInfo.quoteAsset.decimals);
429
- let tvlNowInBaseAsset = Web3Number.fromWei(0, this.metadata.additionalInfo.quoteAsset.decimals);
430
- if (!isQuoteTokenToken0) {
431
- tvlNowInBaseAsset = (tvlNow.amount0
432
- .multipliedBy(priceNow.price))
433
- .plus(tvlNow.amount1);
434
- tvlBeforeInBaseAsset = (tvlBefore.amount0
435
- .multipliedBy(priceBefore.price))
436
- .plus(tvlBefore.amount1);
437
- } else {
438
- tvlNowInBaseAsset = (tvlNow.amount1
439
- .multipliedBy(1 / priceNow.price))
440
- .plus(tvlNow.amount0);
441
- tvlBeforeInBaseAsset = (tvlBefore.amount1
442
- .multipliedBy(1 / priceBefore.price))
443
- .plus(tvlBefore.amount0);
444
- }
445
- const tvlPerShareNow = tvlNowInBaseAsset
421
+
422
+ const tvlInToken0Now = (tvlNow.amount0
423
+ .multipliedBy(priceNow.price))
424
+ .plus(tvlNow.amount1);
425
+ const tvlPerShareNow = tvlInToken0Now
446
426
  .multipliedBy(1e18)
447
427
  .dividedBy(adjustedSupplyNow.toString());
448
-
449
- const tvlPerShareBf = tvlBeforeInBaseAsset
428
+ const tvlInToken0Bf = (tvlBefore.amount0
429
+ .multipliedBy(priceBefore.price))
430
+ .plus(tvlBefore.amount1);
431
+ const tvlPerShareBf = tvlInToken0Bf
450
432
  .multipliedBy(1e18)
451
433
  .dividedBy(supplyBefore.toString());
452
434
  const timeDiffSeconds = blockNowTime - blockBeforeInfo.timestamp;
453
- logger.verbose(`tvlNowInBaseAsset: ${tvlNowInBaseAsset.toString()}`);
454
- logger.verbose(`tvlBeforeInBaseAsset: ${tvlBeforeInBaseAsset.toString()}`);
435
+ logger.verbose(`tvlInToken0Now: ${tvlInToken0Now.toString()}`);
436
+ logger.verbose(`tvlInToken0Bf: ${tvlInToken0Bf.toString()}`);
455
437
  logger.verbose(`tvlPerShareNow: ${tvlPerShareNow.toString()}`);
456
438
  logger.verbose(`tvlPerShareBf: ${tvlPerShareBf.toString()}`);
457
439
  logger.verbose(`Price before: ${priceBefore.price.toString()}`);
@@ -503,15 +485,20 @@ export class EkuboCLVault extends BaseStrategy<
503
485
  blockIdentifier: BlockIdentifier = "latest",
504
486
  sinceBlocks = 600000,
505
487
  timeperiod: '24h' | '7d' | '30d' | '3m' = '24h' // temp thing for fee based APY
506
- ): Promise<number> {
507
- // ! switch to USDC later
508
- const isUSDCQouteToken = this.metadata.additionalInfo.quoteAsset.symbol === "USDC.e";
488
+ ): Promise<APYInfo> {
489
+ const isUSDCQouteToken = this.metadata.additionalInfo.quoteAsset.symbol === "USDC";
509
490
  if (!isUSDCQouteToken) {
510
491
  // good for LSTs and stables
511
- return this.netSharesBasedTrueAPY(blockIdentifier, sinceBlocks);
492
+ return {
493
+ net: await this.netSharesBasedTrueAPY(blockIdentifier, sinceBlocks),
494
+ splits: []
495
+ };
512
496
  } else {
513
497
  // good for non-stables
514
- return this.feeBasedAPY(timeperiod);
498
+ return {
499
+ net: await this.feeBasedAPY(timeperiod),
500
+ splits: []
501
+ };
515
502
  }
516
503
  }
517
504
 
@@ -798,37 +785,43 @@ export class EkuboCLVault extends BaseStrategy<
798
785
  amount: tvlInfo.token0.amount,
799
786
  usdValue: tvlInfo.token0.usdValue,
800
787
  token: tvlInfo.token0.tokenInfo,
801
- remarks: `Liquidity in Ekubo`
788
+ remarks: `Liquidity in Ekubo`,
789
+ protocol: Protocols.EKUBO
802
790
  },
803
791
  {
804
792
  amount: fees.token0.amount,
805
793
  usdValue: fees.token0.usdValue,
806
794
  token: fees.token0.tokenInfo,
807
- remarks: "Uncollected Fees in Ekubo"
795
+ remarks: "Uncollected Fees in Ekubo",
796
+ protocol: Protocols.EKUBO
808
797
  },
809
798
  {
810
799
  amount: unusedBalance.token0.amount,
811
800
  usdValue: unusedBalance.token0.usdValue,
812
801
  token: unusedBalance.token0.tokenInfo,
813
- remarks: "Unused Balance in the Vault"
802
+ remarks: "Unused Balance in the Vault",
803
+ protocol: Protocols.NONE
814
804
  },
815
805
  {
816
806
  amount: tvlInfo.token1.amount,
817
807
  usdValue: tvlInfo.token1.usdValue,
818
808
  token: tvlInfo.token1.tokenInfo,
819
- remarks: "Liquidity in Ekubo"
809
+ remarks: "Liquidity in Ekubo",
810
+ protocol: Protocols.EKUBO
820
811
  },
821
812
  {
822
813
  amount: fees.token1.amount,
823
814
  usdValue: fees.token1.usdValue,
824
815
  token: fees.token1.tokenInfo,
825
- remarks: "Uncollected Fees in Ekubo"
816
+ remarks: "Uncollected Fees in Ekubo",
817
+ protocol: Protocols.EKUBO
826
818
  },
827
819
  {
828
820
  amount: unusedBalance.token1.amount,
829
821
  usdValue: unusedBalance.token1.usdValue,
830
822
  token: unusedBalance.token1.tokenInfo,
831
- remarks: "Unused Balance in the Vault"
823
+ remarks: "Unused Balance in the Vault",
824
+ protocol: Protocols.NONE
832
825
  }
833
826
  ];
834
827
  }
@@ -1033,12 +1026,6 @@ export class EkuboCLVault extends BaseStrategy<
1033
1026
  amount1: availableAmount1.minus(y),
1034
1027
  ratio: 0,
1035
1028
  };
1036
- } else if (ratio.eq(Infinity)) {
1037
- return {
1038
- amount0: availableAmount0,
1039
- amount1: Web3Number.fromWei("0", availableAmount1.decimals),
1040
- ratio: Infinity,
1041
- };
1042
1029
  }
1043
1030
  return {
1044
1031
  amount0: availableAmount0.plus(x),
@@ -1088,12 +1075,7 @@ export class EkuboCLVault extends BaseStrategy<
1088
1075
  };
1089
1076
  }
1090
1077
 
1091
- async getSwapInfoToHandleUnused(
1092
- considerRebalance: boolean = true,
1093
- newBounds: EkuboBounds | null = null,
1094
- maxIterations = 20, priceRatioPrecision = 4,
1095
- getQuoteCallback: (tokenToSell: string, tokenToBuy: string, amountWei: string, beneficiary: string) => Promise<Quote> = this.avnu.getQuotes
1096
- ): Promise<SwapInfo> {
1078
+ async getSwapInfoToHandleUnused(considerRebalance: boolean = true, newBounds: EkuboBounds | null = null, maxIterations = 20, priceRatioPrecision = 4): Promise<SwapInfo> {
1097
1079
  const poolKey = await this.getPoolKey();
1098
1080
 
1099
1081
  // fetch current unused balances of vault
@@ -1158,8 +1140,7 @@ export class EkuboCLVault extends BaseStrategy<
1158
1140
  token1Bal,
1159
1141
  ekuboBounds,
1160
1142
  maxIterations,
1161
- priceRatioPrecision,
1162
- getQuoteCallback
1143
+ priceRatioPrecision
1163
1144
  );
1164
1145
  }
1165
1146
 
@@ -1205,7 +1186,6 @@ export class EkuboCLVault extends BaseStrategy<
1205
1186
  const tokenToSell = expectedAmounts.amount0.lessThan(token0Bal)
1206
1187
  ? poolKey.token0
1207
1188
  : poolKey.token1;
1208
- logger.verbose(`getSwapParams => tokenToSell: ${tokenToSell.address}, expectedAmounts: ${expectedAmounts.amount0.toString()}, bal0: ${token0Bal.toString()}`);
1209
1189
  // The other token is the one to buy
1210
1190
  const tokenToBuy =
1211
1191
  tokenToSell == poolKey.token0 ? poolKey.token1 : poolKey.token0;
@@ -1244,8 +1224,7 @@ export class EkuboCLVault extends BaseStrategy<
1244
1224
  token1Bal: Web3Number,
1245
1225
  bounds: EkuboBounds,
1246
1226
  maxIterations: number = 20,
1247
- priceRatioPrecision: number = 4,
1248
- getQuoteCallback: (tokenToSell: string, tokenToBuy: string, amountWei: string, beneficiary: string) => Promise<Quote> = this.avnu.getQuotes
1227
+ priceRatioPrecision: number = 4
1249
1228
  ): Promise<SwapInfo> {
1250
1229
  logger.verbose(
1251
1230
  `${
@@ -1300,7 +1279,12 @@ export class EkuboCLVault extends BaseStrategy<
1300
1279
  }
1301
1280
 
1302
1281
  // Get a quote for swapping the calculated amount
1303
- const quote = await getQuoteCallback(tokenToSell.address, tokenToBuy.address, amountToSell.toWei(), this.address.address);
1282
+ const quote = await this.avnu.getQuotes(
1283
+ tokenToSell.address,
1284
+ tokenToBuy.address,
1285
+ amountToSell.toWei(),
1286
+ this.address.address
1287
+ );
1304
1288
 
1305
1289
  // If all of the token is to be swapped, return the swap info directly
1306
1290
  if (remainingSellAmount.eq(0)) {
@@ -1410,11 +1394,8 @@ export class EkuboCLVault extends BaseStrategy<
1410
1394
  * @param retry - Current retry attempt number (default 0)
1411
1395
  * @param adjustmentFactor - Percentage to adjust swap amount by (default 1)
1412
1396
  * @param isToken0Deficit - Whether token0 balance needs increasing (default true)
1413
- * @param MAX_RETRIES - Maximum number of retries (default 40)
1414
- * @param sameErrorCount - For certain errors, we just retry with same amount again. This is the count of such retries (default { count: 0, error: null })
1415
- * @param MAX_SAME_ERROR_COUNT - For certain errors, we just retry with same amount again. This limits such retries (default 10)
1416
1397
  * @returns Array of contract calls needed for rebalancing
1417
- * @throws Error if max retries reached without successful rebalance or max same errors reached
1398
+ * @throws Error if max retries reached without successful rebalance
1418
1399
  */
1419
1400
  async rebalanceIter(
1420
1401
  swapInfo: SwapInfo,
@@ -1424,23 +1405,15 @@ export class EkuboCLVault extends BaseStrategy<
1424
1405
  retry = 0,
1425
1406
  lowerLimit = 0n,
1426
1407
  upperLimit = 0n,
1427
- MAX_RETRIES = 40,
1428
- sameErrorCount: { count: number, error: null | string } = { count: 0, error: null },
1429
- MAX_SAME_ERROR_COUNT = 10
1408
+ MAX_RETRIES = 40
1430
1409
  ): Promise<Call[]> {
1431
1410
 
1432
1411
  logger.verbose(
1433
1412
  `Rebalancing ${this.metadata.name}: ` +
1434
- `retry=${retry}, lowerLimit=${lowerLimit}, upperLimit=${upperLimit}, isSellTokenToken0=${isSellTokenToken0}, MAX_RETRIES=${MAX_RETRIES}, sameErrorCount=${sameErrorCount.error} (${sameErrorCount.count})`
1413
+ `retry=${retry}, lowerLimit=${lowerLimit}, upperLimit=${upperLimit}, isSellTokenToken0=${isSellTokenToken0}`
1435
1414
  );
1436
1415
 
1437
- if (sameErrorCount.count >= MAX_SAME_ERROR_COUNT) {
1438
- logger.error(`Rebalance failed after ${MAX_SAME_ERROR_COUNT} same errors`);
1439
- throw new Error(`Rebalance failed after ${MAX_SAME_ERROR_COUNT} same errors`);
1440
- }
1441
-
1442
1416
  const fromAmount = uint256.uint256ToBN(swapInfo.token_from_amount);
1443
- const fromTokenInfo = await Global.getTokenInfoFromAddr(ContractAddr.from(swapInfo.token_from_address));
1444
1417
  logger.verbose(
1445
1418
  `Selling ${fromAmount.toString()} of token ${swapInfo.token_from_address}`
1446
1419
  );
@@ -1460,8 +1433,8 @@ export class EkuboCLVault extends BaseStrategy<
1460
1433
  );
1461
1434
 
1462
1435
  const newSwapInfo = { ...swapInfo };
1463
- const currentAmount = Web3Number.fromWei(fromAmount.toString(), fromTokenInfo.decimals);
1464
- logger.verbose(`Current amount: ${currentAmount.toString()}, lowerLimit: ${lowerLimit.toString()}, upperLimit: ${upperLimit.toString()}`);
1436
+ const currentAmount = Web3Number.fromWei(fromAmount.toString(), 18); // 18 is ok, as its toWei eventually anyways
1437
+ logger.verbose(`Current amount: ${currentAmount.toString()}`);
1465
1438
  if (
1466
1439
  err.message.includes("invalid token0 balance") ||
1467
1440
  err.message.includes("invalid token0 amount")
@@ -1514,43 +1487,11 @@ export class EkuboCLVault extends BaseStrategy<
1514
1487
  }
1515
1488
  newSwapInfo.token_from_amount = uint256.bnToUint256(nextAmount);
1516
1489
  }
1517
- } else if (err.message.includes("Residual tokens")) {
1518
- logger.error("Residual tokens");
1519
- if (sameErrorCount.error == "Residual tokens") {
1520
- sameErrorCount.count++;
1521
- } else {
1522
- sameErrorCount.error = "Residual tokens";
1523
- sameErrorCount.count = 1;
1524
- }
1525
- // dont do anything, just try again.
1526
- } else if (err.message.includes("Insufficient tokens received")) {
1527
- logger.error("Insufficient tokens received");
1528
- if (sameErrorCount.error == "Insufficient tokens received") {
1529
- sameErrorCount.count++;
1530
- } else {
1531
- sameErrorCount.error = "Insufficient tokens received";
1532
- sameErrorCount.count = 1;
1533
- }
1534
- // dont do anything, just try again.
1535
- } else if (err.message.includes("Could not reach the end of the program")) {
1536
- logger.error("Could not reach the end of the program, may be the block is full (could be a temp/permanent gas issue)");
1537
- if (sameErrorCount.error == "Could not reach the end of the program") {
1538
- sameErrorCount.count++;
1539
- } else {
1540
- sameErrorCount.error = "Could not reach the end of the program";
1541
- sameErrorCount.count = 1;
1542
- }
1543
- // just try again.
1544
1490
  } else {
1545
1491
  logger.error("Unexpected error:", err);
1546
1492
  throw err;
1547
1493
  }
1548
1494
  newSwapInfo.token_to_min_amount = uint256.bnToUint256("0");
1549
-
1550
- // if (uint256.uint256ToBN(newSwapInfo.token_from_amount) == fromAmount && sameErrorCount.error == 'loop-stuck') {
1551
- // logger.error("Swap amount did not change, cannot proceed");
1552
- // sameErrorCount = { count: MAX_SAME_ERROR_COUNT, error: null };
1553
- // }
1554
1495
  return this.rebalanceIter(
1555
1496
  newSwapInfo,
1556
1497
  acc,
@@ -1558,10 +1499,7 @@ export class EkuboCLVault extends BaseStrategy<
1558
1499
  isSellTokenToken0,
1559
1500
  retry + 1,
1560
1501
  lowerLimit,
1561
- upperLimit,
1562
- MAX_RETRIES,
1563
- sameErrorCount,
1564
- MAX_SAME_ERROR_COUNT
1502
+ upperLimit
1565
1503
  );
1566
1504
  }
1567
1505
  }
@@ -1654,34 +1592,20 @@ export class EkuboCLVault extends BaseStrategy<
1654
1592
  };
1655
1593
  }
1656
1594
 
1657
- async getPendingRewards(): Promise<HarvestInfo[]> {
1595
+ async harvest(acc: Account, maxIterations = 20, priceRatioPrecision = 4): Promise<Call[]> {
1658
1596
  const ekuboHarvests = new EkuboHarvests(this.config);
1659
- return await ekuboHarvests.getUnHarvestedRewards(this.address);
1660
- }
1661
-
1662
- async harvest(acc: Account, maxIterations = 20, priceRatioPrecision = 4, minRewardAmount: Web3Number = new Web3Number(0, 18)): Promise<Call[]> {
1663
- const _pendingRewards = await this.getPendingRewards();
1664
- const pendingRewards = _pendingRewards.filter(claim => claim.actualReward.greaterThanOrEqualTo(minRewardAmount));
1665
- if (pendingRewards.length == 0) {
1666
- logger.verbose(`${EkuboCLVault.name}: harvest => no pending rewards found`);
1667
- return [];
1668
- }
1669
- // get necessary info for the harvest
1597
+ const unClaimedRewards = await ekuboHarvests.getUnHarvestedRewards(
1598
+ this.address
1599
+ );
1670
1600
  const poolKey = await this.getPoolKey();
1671
1601
  const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
1672
1602
  const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
1673
1603
  const bounds = await this.getCurrentBounds();
1674
1604
  logger.verbose(
1675
- `${EkuboCLVault.name}: harvest => unClaimedRewards: ${pendingRewards.length}`
1605
+ `${EkuboCLVault.name}: harvest => unClaimedRewards: ${unClaimedRewards.length}`
1676
1606
  );
1677
-
1678
- // execute the harvest
1679
1607
  const calls: Call[] = [];
1680
- // do one at a time.
1681
- const chosenClaim = pendingRewards[0];
1682
- logger.info(`${EkuboCLVault.name}: harvest => doing one at a time`);
1683
- logger.info(`${EkuboCLVault.name}: harvest => chosenClaim -> Claim ID: ${chosenClaim.claim.id}, Amount: ${chosenClaim.claim.amount.toString()}, actualAmount: ${chosenClaim.actualReward.toString()}, addr: ${chosenClaim.claim.claimee.toString()}`);
1684
- for (let claim of [chosenClaim]) {
1608
+ for (let claim of unClaimedRewards) {
1685
1609
  const fee = claim.claim.amount
1686
1610
  .multipliedBy(this.metadata.additionalInfo.feeBps)
1687
1611
  .dividedBy(10000);
@@ -1754,50 +1678,60 @@ export class EkuboCLVault extends BaseStrategy<
1754
1678
  logger.verbose(
1755
1679
  `${
1756
1680
  EkuboCLVault.name
1757
- }: harvest => token0Amt: ${token0Amt.toFixed(18)}, token1Amt: ${token1Amt.toFixed(18)}`
1681
+ }: harvest => token0Amt: ${token0Amt.toString()}, token1Amt: ${token1Amt.toString()}`
1682
+ );
1683
+
1684
+ // THis function cannot handle swapping of non-STRK pool,
1685
+ // bcz atleast one of token0Amt or token1Amt are in STRK terms.
1686
+ const swapInfo = await this.getSwapInfoGivenAmounts(
1687
+ poolKey,
1688
+ token0Amt,
1689
+ token1Amt,
1690
+ bounds,
1691
+ maxIterations,
1692
+ priceRatioPrecision
1693
+ );
1694
+ swapInfo.token_to_address = token0Info.address.address;
1695
+ logger.verbose(
1696
+ `${EkuboCLVault.name}: harvest => swapInfo: ${JSON.stringify(swapInfo)}`
1758
1697
  );
1759
1698
 
1760
1699
  logger.verbose(
1761
1700
  `${EkuboCLVault.name}: harvest => claim: ${JSON.stringify(claim)}`
1762
1701
  );
1763
- const claimTokenInfo = await Global.getTokenInfoFromAddr(claim.token);
1764
- const harvestEstimateCall = async (baseSwapInfo: SwapInfo) => {
1765
- // - the base swap if actual swap from claim token to non-claim token
1766
- // - the other swap is just claim token to claim token (e.g. STRK to STRK)
1767
- // which is just dummy
1768
- let baseSwapAmount = Web3Number.fromWei(
1769
- uint256.uint256ToBN(baseSwapInfo.token_from_amount).toString(),
1770
- claimTokenInfo.decimals
1702
+ const harvestEstimateCall = async (swapInfo1: SwapInfo) => {
1703
+ const swap1Amount = Web3Number.fromWei(
1704
+ uint256.uint256ToBN(swapInfo1.token_from_amount).toString(),
1705
+ 18 // cause its always STRK?
1771
1706
  ).minimum(
1772
- postFeeAmount.toFixed(claimTokenInfo.decimals)
1707
+ postFeeAmount.toFixed(18) // cause always strk
1773
1708
  ); // ensure we don't swap more than we have
1774
- if (baseSwapAmount.lt(0.0001)) {
1775
- baseSwapAmount = new Web3Number(0, claimTokenInfo.decimals);
1776
- }
1777
- baseSwapInfo.token_from_amount = uint256.bnToUint256(baseSwapAmount.toWei());
1709
+ swapInfo.token_from_amount = uint256.bnToUint256(swap1Amount.toWei());
1710
+ swapInfo.token_to_min_amount = uint256.bnToUint256(
1711
+ swap1Amount.multipliedBy(0).toWei() // placeholder
1712
+ ); // 0.01% slippage
1778
1713
 
1779
- const isToken0ClaimToken = claim.token.eq(poolKey.token0);
1780
1714
  logger.verbose(
1781
- `${EkuboCLVault.name}: harvest => isToken0ClaimToken: ${isToken0ClaimToken}, baseSwapAmount: ${baseSwapAmount}`
1715
+ `${EkuboCLVault.name}: harvest => swap1Amount: ${swap1Amount}`
1782
1716
  );
1783
1717
 
1784
- const remainingAmount = postFeeAmount.minus(baseSwapAmount).maximum(0);
1718
+ const remainingAmount = postFeeAmount.minus(swap1Amount).maximum(0);
1785
1719
  logger.verbose(
1786
1720
  `${EkuboCLVault.name}: harvest => remainingAmount: ${remainingAmount}`
1787
1721
  );
1788
-
1789
- // obv, same to same
1790
- let dummySwapInfo = AvnuWrapper.buildZeroSwap(claim.token, this.address.address, claim.token);
1791
- dummySwapInfo.token_from_amount = uint256.bnToUint256(remainingAmount.toWei());
1792
-
1722
+ const swapInfo2 = {
1723
+ ...swapInfo,
1724
+ token_from_amount: uint256.bnToUint256(remainingAmount.toWei()),
1725
+ };
1726
+ swapInfo2.token_to_address = token1Info.address.address;
1793
1727
  logger.verbose(
1794
- `${EkuboCLVault.name}: harvest => dummySwapInfo: ${JSON.stringify(
1795
- dummySwapInfo
1728
+ `${EkuboCLVault.name}: harvest => swapInfo: ${JSON.stringify(
1729
+ swapInfo
1796
1730
  )}`
1797
1731
  );
1798
1732
  logger.verbose(
1799
- `${EkuboCLVault.name}: harvest => baseSwapInfo: ${JSON.stringify(
1800
- baseSwapInfo
1733
+ `${EkuboCLVault.name}: harvest => swapInfo2: ${JSON.stringify(
1734
+ swapInfo2
1801
1735
  )}`
1802
1736
  );
1803
1737
  const calldata = [
@@ -1808,41 +1742,18 @@ export class EkuboCLVault extends BaseStrategy<
1808
1742
  claimee: claim.claim.claimee.address,
1809
1743
  },
1810
1744
  claim.proof.map((p) => num.getDecimalString(p)),
1811
- isToken0ClaimToken ? dummySwapInfo : baseSwapInfo, // is token0 claim token, its just dummy swap
1812
- isToken0ClaimToken ? baseSwapInfo : dummySwapInfo,
1745
+ swapInfo,
1746
+ swapInfo2,
1813
1747
  ];
1748
+ logger.verbose(
1749
+ `${EkuboCLVault.name}: harvest => calldata: ${JSON.stringify(
1750
+ calldata
1751
+ )}`
1752
+ );
1814
1753
  return [this.contract.populate("harvest", calldata)];
1815
1754
  };
1816
-
1817
- // if token0 == claim token, then the base swapInfo is from claim token to token1
1818
- // if token1 == claim token, then the base swapInfo is from claim token to token0
1819
- const isToken0ClaimToken = claim.token.eq(poolKey.token0);
1820
- let baseSwapInfo = AvnuWrapper.buildZeroSwap(claim.token, this.address.address, isToken0ClaimToken ? token1Info.address : token0Info.address);
1821
- baseSwapInfo.token_from_amount = uint256.bnToUint256(postFeeAmount.toWei()); // we try to swap all to start with
1822
-
1823
- // if token0 != claim token, then we swap from claim token to token0
1824
- if (postFeeAmount.greaterThan(0) && !isToken0ClaimToken) {
1825
- const avnuWrapper = new AvnuWrapper();
1826
- const quote = await avnuWrapper.getQuotes(
1827
- claim.token.address,
1828
- token0Info.address.address,
1829
- postFeeAmount.toWei(),
1830
- this.address.address
1831
- );
1832
- baseSwapInfo = await avnuWrapper.getSwapInfo(quote, this.address.address, 0, this.address.address);
1833
- } else if (postFeeAmount.greaterThan(0) && isToken0ClaimToken) {
1834
- // if token0 == claim token, then we swap from claim token to token1
1835
- const avnuWrapper = new AvnuWrapper();
1836
- const quote = await avnuWrapper.getQuotes(
1837
- claim.token.address,
1838
- token1Info.address.address,
1839
- postFeeAmount.toWei(),
1840
- this.address.address
1841
- );
1842
- baseSwapInfo = await avnuWrapper.getSwapInfo(quote, this.address.address, 0, this.address.address);
1843
- }
1844
1755
  const _callsFinal = await this.rebalanceIter(
1845
- baseSwapInfo,
1756
+ swapInfo,
1846
1757
  acc,
1847
1758
  harvestEstimateCall,
1848
1759
  claim.token.eq(poolKey.token0),
@@ -1912,47 +1823,39 @@ export class EkuboCLVault extends BaseStrategy<
1912
1823
  }) {
1913
1824
  const { postFeeAmount, claim, token0Info, token1Info, acc } = params;
1914
1825
  let harvestCall: Call | null = null;
1915
- logger.verbose(`${EkuboCLVault.name}: harvestMismatchEstimateCallFn => postFeeAmount: ${postFeeAmount.toString()}`);
1916
1826
 
1917
- let attempt = 0;
1918
- let MAX_ATTEMPTS = 50;
1919
1827
  const binarySearchCallbackFn = async (mid: bigint) => {
1920
- attempt++;
1921
- logger.verbose(`${EkuboCLVault.name}: harvestMismatchEstimateCallFn => mid: ${mid}, attempt: ${attempt}/${MAX_ATTEMPTS}`);
1922
1828
  const rewardPart2 = BigInt(postFeeAmount.toWei()) - mid;
1923
1829
  const avnuWrapper = new AvnuWrapper();
1924
1830
  const beneficiary = this.address.address;
1925
1831
 
1926
1832
  // get quote for 1st part
1927
- const quote1Prom = avnuWrapper.getQuotes(
1833
+ const quote1 = await avnuWrapper.getQuotes(
1928
1834
  claim.token.address,
1929
1835
  token0Info.address.address,
1930
1836
  mid.toString(),
1931
1837
  beneficiary
1932
1838
  );
1933
- const quote2Prom = avnuWrapper.getQuotes(
1934
- claim.token.address,
1935
- token1Info.address.address,
1936
- rewardPart2.toString(),
1937
- beneficiary
1938
- );
1939
- const [quote1, quote2] = await Promise.all([quote1Prom, quote2Prom]);
1940
-
1941
1839
  // default min amount is ok
1942
1840
  const swapInfo1 = await avnuWrapper.getSwapInfo(
1943
1841
  quote1,
1944
1842
  beneficiary,
1945
- 0, // fee bps
1843
+ 0,
1946
1844
  beneficiary
1947
1845
  );
1948
1846
 
1949
1847
  // get quote for 2nd part
1950
-
1848
+ const quote2 = await avnuWrapper.getQuotes(
1849
+ claim.token.address,
1850
+ token1Info.address.address,
1851
+ rewardPart2.toString(),
1852
+ beneficiary
1853
+ );
1951
1854
  // default min amount is ok
1952
1855
  const swapInfo2 = await avnuWrapper.getSwapInfo(
1953
1856
  quote2,
1954
1857
  beneficiary,
1955
- 0, // fee bps
1858
+ 0,
1956
1859
  beneficiary
1957
1860
  );
1958
1861
 
@@ -1971,19 +1874,15 @@ export class EkuboCLVault extends BaseStrategy<
1971
1874
  ];
1972
1875
  harvestCall = this.contract.populate("harvest", calldata)
1973
1876
  const gas = await acc.estimateInvokeFee(harvestCall);
1974
- logger.verbose(`${EkuboCLVault.name}: harvestMismatchEstimateCallFn => gas: ${gas.overall_fee.toString()}, attempt: ${attempt}/${MAX_ATTEMPTS}`);
1975
1877
  return 'found';
1976
1878
  } catch (err: any) {
1977
1879
  if (err.message.includes('invalid token0 amount')) {
1978
- logger.verbose(`${EkuboCLVault.name}: harvestMismatchEstimateCallFn => invalid token0 amount, attempt: ${attempt}/${MAX_ATTEMPTS}`);
1979
1880
  // too much token0 amount left, may be swap less to token0
1980
1881
  return 'go_low';
1981
1882
  } else if (err.message.includes('invalid token1 amount')) {
1982
- logger.verbose(`${EkuboCLVault.name}: harvestMismatchEstimateCallFn => invalid token1 amount, attempt: ${attempt}/${MAX_ATTEMPTS}`);
1983
1883
  // too much token1 balance left, may be swap more to token0
1984
1884
  return 'go_high';
1985
1885
  }
1986
- logger.verbose(`${EkuboCLVault.name}: harvestMismatchEstimateCallFn => error: ${err.message}, attempt: ${attempt}/${MAX_ATTEMPTS}`);
1987
1886
  return 'retry';
1988
1887
  }
1989
1888
  }
@@ -2016,7 +1915,7 @@ export class EkuboCLVault extends BaseStrategy<
2016
1915
  id: "base",
2017
1916
  title: "Your Deposit",
2018
1917
  subItems: [
2019
- { key: `Net yield`, value: `${(netYield * 100).toFixed(2)}%` },
1918
+ { key: `Net yield`, value: `${(netYield.net * 100).toFixed(2)}%` },
2020
1919
  {
2021
1920
  key: `Performance Fee`,
2022
1921
  value: `${(this.metadata.additionalInfo.feeBps / 100).toFixed(2)}%`,
@@ -2303,7 +2202,7 @@ const lstStrategies: IStrategyMetadata<CLVaultStrategySettings>[] = [
2303
2202
 
2304
2203
  const ETHUSDCRe7Strategy: IStrategyMetadata<CLVaultStrategySettings> = {
2305
2204
  ...xSTRKSTRK,
2306
- name: "Ekubo ETH/USDC.e",
2205
+ name: "Ekubo ETH/USDC",
2307
2206
  description: <></>,
2308
2207
  address: ContractAddr.from(
2309
2208
  "0x160d8fa4569ef6a12e6bf47cb943d7b5ebba8a41a69a14c1d943050ba5ff947"
@@ -2312,7 +2211,7 @@ const ETHUSDCRe7Strategy: IStrategyMetadata<CLVaultStrategySettings> = {
2312
2211
  // must be same order as poolKey token0 and token1
2313
2212
  depositTokens: [
2314
2213
  Global.getDefaultTokens().find((t) => t.symbol === "ETH")!,
2315
- Global.getDefaultTokens().find((t) => t.symbol === "USDC.e")!
2214
+ Global.getDefaultTokens().find((t) => t.symbol === "USDC")!
2316
2215
  ],
2317
2216
  apyMethodology:
2318
2217
  "Annualized fee APY, calculated as fees earned in the last 7d divided by TVL",
@@ -2326,7 +2225,7 @@ const ETHUSDCRe7Strategy: IStrategyMetadata<CLVaultStrategySettings> = {
2326
2225
  minWaitHours: 6,
2327
2226
  direction: "any"
2328
2227
  },
2329
- quoteAsset: Global.getDefaultTokens().find((t) => t.symbol === "USDC.e")!,
2228
+ quoteAsset: Global.getDefaultTokens().find((t) => t.symbol === "USDC")!,
2330
2229
  },
2331
2230
  faqs: [
2332
2231
  ...faqs,
@@ -2350,7 +2249,7 @@ const RE7Strategies: IStrategyMetadata<CLVaultStrategySettings>[] = [
2350
2249
  ETHUSDCRe7Strategy,
2351
2250
  {
2352
2251
  ...ETHUSDCRe7Strategy,
2353
- name: "Ekubo USDC.e/USDT",
2252
+ name: "Ekubo USDC/USDT",
2354
2253
  description: <></>,
2355
2254
  address: ContractAddr.from(
2356
2255
  "0x3a4f8debaf12af97bb911099bc011d63d6c208d4c5ba8e15d7f437785b0aaa2"
@@ -2358,7 +2257,7 @@ const RE7Strategies: IStrategyMetadata<CLVaultStrategySettings>[] = [
2358
2257
  launchBlock: 1506139,
2359
2258
  // must be same order as poolKey token0 and token1
2360
2259
  depositTokens: [
2361
- Global.getDefaultTokens().find((t) => t.symbol === "USDC.e")!,
2260
+ Global.getDefaultTokens().find((t) => t.symbol === "USDC")!,
2362
2261
  Global.getDefaultTokens().find((t) => t.symbol === "USDT")!
2363
2262
  ],
2364
2263
  risk: {
@@ -2371,7 +2270,7 @@ const RE7Strategies: IStrategyMetadata<CLVaultStrategySettings>[] = [
2371
2270
  },
2372
2271
  {
2373
2272
  ...ETHUSDCRe7Strategy,
2374
- name: "Ekubo STRK/USDC.e",
2273
+ name: "Ekubo STRK/USDC",
2375
2274
  description: <></>,
2376
2275
  address: ContractAddr.from(
2377
2276
  "0x351b36d0d9d8b40010658825adeeddb1397436cd41acd0ff6c6e23aaa8b5b30"
@@ -2380,7 +2279,7 @@ const RE7Strategies: IStrategyMetadata<CLVaultStrategySettings>[] = [
2380
2279
  // must be same order as poolKey token0 and token1
2381
2280
  depositTokens: [
2382
2281
  Global.getDefaultTokens().find((t) => t.symbol === "STRK")!,
2383
- Global.getDefaultTokens().find((t) => t.symbol === "USDC.e")!
2282
+ Global.getDefaultTokens().find((t) => t.symbol === "USDC")!
2384
2283
  ],
2385
2284
  risk: highRisk,
2386
2285
  },
@@ -2401,7 +2300,7 @@ const RE7Strategies: IStrategyMetadata<CLVaultStrategySettings>[] = [
2401
2300
  },
2402
2301
  {
2403
2302
  ...ETHUSDCRe7Strategy,
2404
- name: "Ekubo WBTC/USDC.e",
2303
+ name: "Ekubo WBTC/USDC",
2405
2304
  description: <></>,
2406
2305
  address: ContractAddr.from(
2407
2306
  "0x2bcaef2eb7706875a5fdc6853dd961a0590f850bc3a031c59887189b5e84ba1"
@@ -2410,13 +2309,13 @@ const RE7Strategies: IStrategyMetadata<CLVaultStrategySettings>[] = [
2410
2309
  // must be same order as poolKey token0 and token1
2411
2310
  depositTokens: [
2412
2311
  Global.getDefaultTokens().find((t) => t.symbol === "WBTC")!,
2413
- Global.getDefaultTokens().find((t) => t.symbol === "USDC.e")!
2312
+ Global.getDefaultTokens().find((t) => t.symbol === "USDC")!
2414
2313
  ],
2415
2314
  risk: mediumRisk,
2416
2315
  },
2417
2316
  {
2418
2317
  ...ETHUSDCRe7Strategy,
2419
- name: "Ekubo tBTC/USDC.e",
2318
+ name: "Ekubo tBTC/USDC",
2420
2319
  description: <></>,
2421
2320
  address: ContractAddr.from(
2422
2321
  "0x4aad891a2d4432fba06b6558631bb13f6bbd7f6f33ab8c3111e344889ea4456"
@@ -2425,7 +2324,7 @@ const RE7Strategies: IStrategyMetadata<CLVaultStrategySettings>[] = [
2425
2324
  // must be same order as poolKey token0 and token1
2426
2325
  depositTokens: [
2427
2326
  Global.getDefaultTokens().find((t) => t.symbol === "tBTC")!,
2428
- Global.getDefaultTokens().find((t) => t.symbol === "USDC.e")!
2327
+ Global.getDefaultTokens().find((t) => t.symbol === "USDC")!
2429
2328
  ],
2430
2329
  risk: mediumRisk,
2431
2330
  },
@@ -2458,88 +2357,6 @@ const RE7Strategies: IStrategyMetadata<CLVaultStrategySettings>[] = [
2458
2357
  Global.getDefaultTokens().find((t) => t.symbol === "STRK")!
2459
2358
  ],
2460
2359
  risk: highRisk,
2461
- },
2462
- {
2463
- ...ETHUSDCRe7Strategy,
2464
- name: "Ekubo USDC/USDT",
2465
- description: <></>,
2466
- address: ContractAddr.from(
2467
- "0x5203a08b471e46bf33990ac83aff577bbe5a5d789e61de2c6531e3c4773d1c9"
2468
- ),
2469
- launchBlock: 3998018,
2470
- // must be same order as poolKey token0 and token1
2471
- depositTokens: [
2472
- Global.getDefaultTokens().find((t) => t.symbol === "USDC")!,
2473
- Global.getDefaultTokens().find((t) => t.symbol === "USDT")!
2474
- ],
2475
- risk: {
2476
- riskFactor: _stableCoinPoolRiskFactors,
2477
- netRisk:
2478
- _stableCoinPoolRiskFactors.reduce((acc, curr) => acc + curr.value * curr.weight, 0) /
2479
- _stableCoinPoolRiskFactors.reduce((acc, curr) => acc + curr.weight, 0),
2480
- notARisks: getNoRiskTags(_stableCoinPoolRiskFactors),
2481
- },
2482
- additionalInfo: {
2483
- ...ETHUSDCRe7Strategy.additionalInfo,
2484
- quoteAsset: Global.getDefaultTokens().find((t) => t.symbol === "USDC")!,
2485
- }
2486
- },
2487
- {
2488
- ...ETHUSDCRe7Strategy,
2489
- name: "Ekubo ETH/USDC",
2490
- description: <></>,
2491
- address: ContractAddr.from(
2492
- "0x4d00c7423b3c0fae3640f6099ac97acbfd8708f099e09bfe3a7a6a680399228"
2493
- ),
2494
- launchBlock: 3998025,
2495
- // must be same order as poolKey token0 and token1
2496
- depositTokens: [
2497
- Global.getDefaultTokens().find((t) => t.symbol === "USDC")!,
2498
- Global.getDefaultTokens().find((t) => t.symbol === "ETH")!,
2499
- ],
2500
- risk: highRisk,
2501
- additionalInfo: {
2502
- ...ETHUSDCRe7Strategy.additionalInfo,
2503
- quoteAsset: Global.getDefaultTokens().find((t) => t.symbol === "USDC")!,
2504
- }
2505
- },
2506
- {
2507
- ...ETHUSDCRe7Strategy,
2508
- name: "Ekubo STRK/USDC",
2509
- description: <></>,
2510
- address: ContractAddr.from(
2511
- "0x4de22bd0a8eb4d0a18736e66dd36d20ba50bc106346bbfac3dbeaac1ab37ce1"
2512
- ),
2513
- launchBlock: 3998030,
2514
- // must be same order as poolKey token0 and token1
2515
- depositTokens: [
2516
- Global.getDefaultTokens().find((t) => t.symbol === "USDC")!,
2517
- Global.getDefaultTokens().find((t) => t.symbol === "STRK")!,
2518
- ],
2519
- risk: highRisk,
2520
- additionalInfo: {
2521
- ...ETHUSDCRe7Strategy.additionalInfo,
2522
- quoteAsset: Global.getDefaultTokens().find((t) => t.symbol === "USDC")!,
2523
- }
2524
- },
2525
- {
2526
- ...ETHUSDCRe7Strategy,
2527
- name: "Ekubo WBTC/USDC",
2528
- description: <></>,
2529
- address: ContractAddr.from(
2530
- "0x76101c3b80af1103c9c6d541ca627f61b5ae7ae79d7fce96ccdf7bdb648450d"
2531
- ),
2532
- launchBlock: 3998034,
2533
- // must be same order as poolKey token0 and token1
2534
- depositTokens: [
2535
- Global.getDefaultTokens().find((t) => t.symbol === "USDC")!,
2536
- Global.getDefaultTokens().find((t) => t.symbol === "WBTC")!,
2537
- ],
2538
- risk: mediumRisk,
2539
- additionalInfo: {
2540
- ...ETHUSDCRe7Strategy.additionalInfo,
2541
- quoteAsset: Global.getDefaultTokens().find((t) => t.symbol === "USDC")!,
2542
- }
2543
2360
  }
2544
2361
  ];
2545
2362