@strkfarm/sdk 1.0.45 → 1.0.46

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.
@@ -57,7 +57,7 @@ export interface CLVaultStrategySettings {
57
57
  newBounds: {
58
58
  lower: number;
59
59
  upper: number;
60
- };
60
+ } | string; // if no bounds are set, can say `Managed by Re7`
61
61
  // to get true price
62
62
  lstContract?: ContractAddr;
63
63
  truePrice?: number; // useful for pools where price is known (e.g. USDC/USDT as 1)
@@ -619,7 +619,7 @@ export class EkuboCLVault extends BaseStrategy<
619
619
 
620
620
  static div2Power128(num: BigInt): number {
621
621
  return (
622
- Number((BigInt(num.toString()) * 1000000n) / BigInt(2 ** 128)) / 1000000
622
+ Number((BigInt(num.toString()) * BigInt(1e18)) / BigInt(2 ** 128)) / 1e18
623
623
  );
624
624
  }
625
625
 
@@ -647,12 +647,6 @@ export class EkuboCLVault extends BaseStrategy<
647
647
  tick_spacing: result.pool_key.tick_spacing.toString(),
648
648
  extension: result.pool_key.extension.toString(),
649
649
  };
650
- const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
651
- const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
652
- assert(
653
- token0Info.decimals == token1Info.decimals,
654
- "Tested only for equal decimals"
655
- );
656
650
  this.poolKey = poolKey;
657
651
  return poolKey;
658
652
  }
@@ -661,6 +655,10 @@ export class EkuboCLVault extends BaseStrategy<
661
655
  const poolKey = await this.getPoolKey();
662
656
  const currentPrice = await this._getCurrentPrice(poolKey);
663
657
 
658
+ if (typeof this.metadata.additionalInfo.newBounds === "string") {
659
+ throw new Error(`New bounds are managed known, to be set manually/externally`);
660
+ }
661
+
664
662
  const newLower =
665
663
  currentPrice.tick +
666
664
  Number(this.metadata.additionalInfo.newBounds.lower) *
@@ -684,12 +682,12 @@ export class EkuboCLVault extends BaseStrategy<
684
682
  * @returns {amount0, amount1}
685
683
  */
686
684
  private async _getExpectedAmountsForLiquidity(
687
- amount0: Web3Number,
688
- amount1: Web3Number,
685
+ inputAmount0: Web3Number,
686
+ inputAmount1: Web3Number,
689
687
  bounds: EkuboBounds,
690
688
  justUseInputAmount = true
691
689
  ) {
692
- assert(amount0.greaterThan(0) || amount1.greaterThan(0), "Amount is 0");
690
+ assert(inputAmount0.greaterThan(0) || inputAmount1.greaterThan(0), "Amount is 0");
693
691
 
694
692
  // get amount ratio for 1e18 liquidity
695
693
  const sampleLiq = 1e20;
@@ -713,47 +711,45 @@ export class EkuboCLVault extends BaseStrategy<
713
711
  );
714
712
  // Account for edge cases
715
713
  // i.e. when liquidity is out of range
716
- if (amount1.eq(0) && amount0.greaterThan(0)) {
714
+ if (inputAmount1.eq(0) && inputAmount0.greaterThan(0)) {
717
715
  if (sampleAmount1.eq(0)) {
718
716
  return {
719
- amount0: amount0,
720
- amount1: Web3Number.fromWei("0", amount1.decimals),
717
+ amount0: inputAmount0,
718
+ amount1: Web3Number.fromWei("0", inputAmount1.decimals),
721
719
  ratio: Infinity,
722
720
  };
723
721
  } else if (sampleAmount0.eq(0)) {
724
722
  // swap all to token1
725
723
  return {
726
- amount0: Web3Number.fromWei("0", amount0.decimals),
727
- amount1: amount0.multipliedBy(price),
724
+ amount0: Web3Number.fromWei("0", inputAmount0.decimals),
725
+ // to ensure decimal consistency, we start with 0
726
+ amount1: Web3Number.fromWei("0", inputAmount1.decimals).plus(inputAmount0.toString()).multipliedBy(price),
728
727
  ratio: 0,
729
728
  };
730
729
  }
731
- } else if (amount0.eq(0) && amount1.greaterThan(0)) {
730
+ } else if (inputAmount0.eq(0) && inputAmount1.greaterThan(0)) {
732
731
  if (sampleAmount0.eq(0)) {
733
732
  return {
734
- amount0: Web3Number.fromWei("0", amount0.decimals),
735
- amount1: amount1,
733
+ amount0: Web3Number.fromWei("0", inputAmount0.decimals),
734
+ amount1: inputAmount1,
736
735
  ratio: 0,
737
736
  };
738
737
  } else if (sampleAmount1.eq(0)) {
739
738
  // swap all to token0
740
739
  return {
741
- amount0: amount1.dividedBy(price),
742
- amount1: Web3Number.fromWei("0", amount1.decimals),
740
+ // to ensure decimal consistency, we start with 0
741
+ amount0: Web3Number.fromWei("0", inputAmount0.decimals).plus(inputAmount1.toString()).dividedBy(price),
742
+ amount1: Web3Number.fromWei("0", inputAmount1.decimals),
743
743
  ratio: Infinity,
744
744
  };
745
745
  }
746
746
  }
747
747
 
748
- // must make it general later
749
- assert(
750
- sampleAmount0.decimals == sampleAmount1.decimals,
751
- "Sample amounts have different decimals"
752
- );
753
748
  const ratioWeb3Number = sampleAmount0
754
749
  .multipliedBy(1e18)
755
750
  .dividedBy(sampleAmount1.toString())
756
751
  .dividedBy(1e18);
752
+
757
753
  const ratio: number = Number(ratioWeb3Number.toFixed(18));
758
754
  logger.verbose(
759
755
  `${EkuboCLVault.name}: ${
@@ -763,8 +759,8 @@ export class EkuboCLVault extends BaseStrategy<
763
759
 
764
760
  if (justUseInputAmount)
765
761
  return this._solveExpectedAmountsEq(
766
- amount0,
767
- amount1,
762
+ inputAmount0,
763
+ inputAmount1,
768
764
  ratioWeb3Number,
769
765
  price
770
766
  );
@@ -772,20 +768,20 @@ export class EkuboCLVault extends BaseStrategy<
772
768
  // we are at liberty to propose amounts outside the propsed amount
773
769
  // assuming amount0 and amount1 as independent values, compute other amounts
774
770
  // Also, if code came till here, it means both sample amounts are non-zero
775
- if (amount1.eq(0) && amount0.greaterThan(0)) {
771
+ if (inputAmount1.eq(0) && inputAmount0.greaterThan(0)) {
776
772
  // use amount0 as base and compute amount1 using ratio
777
- const _amount1 = amount0.dividedBy(ratioWeb3Number);
773
+ const _amount1 = new Web3Number(inputAmount0.toString(), inputAmount1.decimals).dividedBy(ratioWeb3Number);
778
774
  return {
779
- amount0: amount0,
775
+ amount0: inputAmount0,
780
776
  amount1: _amount1,
781
777
  ratio,
782
778
  };
783
- } else if (amount0.eq(0) && amount1.greaterThan(0)) {
779
+ } else if (inputAmount0.eq(0) && inputAmount1.greaterThan(0)) {
784
780
  // use amount1 as base and compute amount0 using ratio
785
- const _amount0 = amount1.multipliedBy(ratio);
781
+ const _amount0 = new Web3Number(inputAmount1.toString(), inputAmount0.decimals).multipliedBy(ratio);
786
782
  return {
787
783
  amount0: _amount0,
788
- amount1: amount1,
784
+ amount1: inputAmount1,
789
785
  ratio,
790
786
  };
791
787
  } else {
@@ -876,7 +872,7 @@ export class EkuboCLVault extends BaseStrategy<
876
872
  };
877
873
  }
878
874
 
879
- async getSwapInfoToHandleUnused(considerRebalance: boolean = true) {
875
+ async getSwapInfoToHandleUnused(considerRebalance: boolean = true, newBounds: EkuboBounds | null = null): Promise<SwapInfo> {
880
876
  const poolKey = await this.getPoolKey();
881
877
 
882
878
  // fetch current unused balances of vault
@@ -921,7 +917,9 @@ export class EkuboCLVault extends BaseStrategy<
921
917
 
922
918
  // get expected amounts for liquidity
923
919
  let ekuboBounds: EkuboBounds;
924
- if (considerRebalance) {
920
+ if (newBounds) {
921
+ ekuboBounds = newBounds;
922
+ } else if (considerRebalance) {
925
923
  ekuboBounds = await this.getNewBounds();
926
924
  } else {
927
925
  ekuboBounds = await this.getCurrentBounds();
@@ -1269,7 +1267,11 @@ export class EkuboCLVault extends BaseStrategy<
1269
1267
  );
1270
1268
  }
1271
1269
 
1272
- static i129ToNumber(i129: { mag: bigint; sign: number }) {
1270
+ static i129ToNumber(i129: { mag: bigint; sign: 0 | 1 | "true" | "false" }): bigint {
1271
+ if (i129.sign == 0 || i129.sign == 1) {
1272
+ return EkuboCLVault.i129ToNumber({mag: i129.mag, sign: i129.sign == 1 ? "true" : "false"});
1273
+ }
1274
+ assert(i129.sign.toString() == 'false' || i129.sign.toString() == 'true', "Invalid sign value");
1273
1275
  return i129.mag * (i129.sign.toString() == "false" ? 1n : -1n);
1274
1276
  }
1275
1277
 
@@ -1483,7 +1485,9 @@ export class EkuboCLVault extends BaseStrategy<
1483
1485
  subItems: [
1484
1486
  {
1485
1487
  key: "Range selection",
1486
- value: `${
1488
+ value: (typeof this.metadata.additionalInfo.newBounds == 'string') ?
1489
+ this.metadata.additionalInfo.newBounds :
1490
+ `${
1487
1491
  this.metadata.additionalInfo.newBounds.lower *
1488
1492
  Number(poolKey.tick_spacing)
1489
1493
  } to ${
@@ -1551,86 +1555,89 @@ const faqs: FAQ[] = [
1551
1555
  ),
1552
1556
  },
1553
1557
  ];
1558
+
1559
+ const xSTRKSTRK: IStrategyMetadata<CLVaultStrategySettings> = {
1560
+ name: "Ekubo xSTRK/STRK",
1561
+ description: (
1562
+ <div>
1563
+ <p>{_description.replace("{{POOL_NAME}}", "xSTRK/STRK")}</p>
1564
+ <ul
1565
+ style={{
1566
+ marginLeft: "20px",
1567
+ listStyle: "circle",
1568
+ fontSize: "12px",
1569
+ }}
1570
+ >
1571
+ <li style={{ marginTop: "10px" }}>
1572
+ During withdrawal, you may receive either or both tokens depending
1573
+ on market conditions and prevailing prices.
1574
+ </li>
1575
+ <li style={{ marginTop: "10px" }}>
1576
+ Sometimes you might see a negative APY — this is usually not a big
1577
+ deal. It happens when xSTRK's price drops on DEXes, but things
1578
+ typically bounce back within a few days or a week.
1579
+ </li>
1580
+ </ul>
1581
+ </div>
1582
+ ),
1583
+ address: ContractAddr.from(
1584
+ "0x01f083b98674bc21effee29ef443a00c7b9a500fd92cf30341a3da12c73f2324"
1585
+ ),
1586
+ launchBlock: 1209881,
1587
+ type: "Other",
1588
+ // must be same order as poolKey token0 and token1
1589
+ depositTokens: [
1590
+ Global.getDefaultTokens().find((t) => t.symbol === "xSTRK")!,
1591
+ Global.getDefaultTokens().find((t) => t.symbol === "STRK")!,
1592
+ ],
1593
+ protocols: [_protocol],
1594
+ auditUrl: AUDIT_URL,
1595
+ maxTVL: Web3Number.fromWei("0", 18),
1596
+ risk: {
1597
+ riskFactor: _riskFactor,
1598
+ netRisk:
1599
+ _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) /
1600
+ _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
1601
+ notARisks: getNoRiskTags(_riskFactor),
1602
+ },
1603
+ apyMethodology:
1604
+ "APY based on 7-day historical performance, including fees and rewards.",
1605
+ additionalInfo: {
1606
+ newBounds: {
1607
+ lower: -1,
1608
+ upper: 1,
1609
+ },
1610
+ lstContract: ContractAddr.from(
1611
+ "0x028d709c875c0ceac3dce7065bec5328186dc89fe254527084d1689910954b0a"
1612
+ ),
1613
+ feeBps: 1000,
1614
+ rebalanceConditions: {
1615
+ customShouldRebalance: async (currentPrice: number) => true,
1616
+ minWaitHours: 24,
1617
+ direction: "uponly",
1618
+ },
1619
+ },
1620
+ faqs: [
1621
+ ...faqs,
1622
+ {
1623
+ question: "Why might I see a negative APY?",
1624
+ answer:
1625
+ "A negative APY can occur when xSTRK's price drops on DEXes. This is usually temporary and tends to recover within a few days or a week.",
1626
+ },
1627
+ ],
1628
+ points: [{
1629
+ multiplier: 1,
1630
+ logo: 'https://endur.fi/favicon.ico',
1631
+ toolTip: "This strategy holds xSTRK and STRK tokens. Earn 1x Endur points on your xSTRK portion of Liquidity. STRK portion will earn Endur's DEX Bonus points. Points can be found on endur.fi.",
1632
+ }]
1633
+ };
1634
+
1554
1635
  /**
1555
1636
  * Represents the Vesu Rebalance Strategies.
1556
1637
  */
1557
1638
  export const EkuboCLVaultStrategies: IStrategyMetadata<CLVaultStrategySettings>[] =
1558
1639
  [
1559
- {
1560
- name: "Ekubo xSTRK/STRK",
1561
- description: (
1562
- <div>
1563
- <p>{_description.replace("{{POOL_NAME}}", "xSTRK/STRK")}</p>
1564
- <ul
1565
- style={{
1566
- marginLeft: "20px",
1567
- listStyle: "circle",
1568
- fontSize: "12px",
1569
- }}
1570
- >
1571
- <li style={{ marginTop: "10px" }}>
1572
- During withdrawal, you may receive either or both tokens depending
1573
- on market conditions and prevailing prices.
1574
- </li>
1575
- <li style={{ marginTop: "10px" }}>
1576
- Sometimes you might see a negative APY — this is usually not a big
1577
- deal. It happens when xSTRK's price drops on DEXes, but things
1578
- typically bounce back within a few days or a week.
1579
- </li>
1580
- </ul>
1581
- </div>
1582
- ),
1583
- address: ContractAddr.from(
1584
- "0x01f083b98674bc21effee29ef443a00c7b9a500fd92cf30341a3da12c73f2324"
1585
- ),
1586
- launchBlock: 1209881,
1587
- type: "Other",
1588
- // must be same order as poolKey token0 and token1
1589
- depositTokens: [
1590
- Global.getDefaultTokens().find((t) => t.symbol === "xSTRK")!,
1591
- Global.getDefaultTokens().find((t) => t.symbol === "STRK")!,
1592
- ],
1593
- protocols: [_protocol],
1594
- auditUrl: AUDIT_URL,
1595
- maxTVL: Web3Number.fromWei("0", 18),
1596
- risk: {
1597
- riskFactor: _riskFactor,
1598
- netRisk:
1599
- _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) /
1600
- _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
1601
- notARisks: getNoRiskTags(_riskFactor),
1602
- },
1603
- apyMethodology:
1604
- "APY based on 7-day historical performance, including fees and rewards.",
1605
- additionalInfo: {
1606
- newBounds: {
1607
- lower: -1,
1608
- upper: 1,
1609
- },
1610
- lstContract: ContractAddr.from(
1611
- "0x028d709c875c0ceac3dce7065bec5328186dc89fe254527084d1689910954b0a"
1612
- ),
1613
- feeBps: 1000,
1614
- rebalanceConditions: {
1615
- customShouldRebalance: async (currentPrice: number) => true,
1616
- minWaitHours: 24,
1617
- direction: "uponly",
1618
- },
1619
- },
1620
- faqs: [
1621
- ...faqs,
1622
- {
1623
- question: "Why might I see a negative APY?",
1624
- answer:
1625
- "A negative APY can occur when xSTRK's price drops on DEXes. This is usually temporary and tends to recover within a few days or a week.",
1626
- },
1627
- ],
1628
- points: [{
1629
- multiplier: 1,
1630
- logo: 'https://endur.fi/favicon.ico',
1631
- toolTip: "This strategy holds xSTRK and STRK tokens. Earn 1x Endur points on your xSTRK portion of Liquidity. STRK portion will earn Endur's DEX Bonus points. Points can be found on endur.fi.",
1632
- }]
1633
- },
1640
+ xSTRKSTRK,
1634
1641
  {
1635
1642
  name: "Ekubo USDC/USDT",
1636
1643
  description: (
@@ -1690,4 +1697,48 @@ export const EkuboCLVaultStrategies: IStrategyMetadata<CLVaultStrategySettings>[
1690
1697
  },
1691
1698
  faqs: [...faqs],
1692
1699
  },
1693
- ];
1700
+ // {
1701
+ // ...xSTRKSTRK,
1702
+ // name: "Ekubo STRK/USDC",
1703
+ // description: (
1704
+ // <div>
1705
+ // <p>{_description.replace("{{POOL_NAME}}", "STRK/USDC")}</p>
1706
+ // <ul
1707
+ // style={{
1708
+ // marginLeft: "20px",
1709
+ // listStyle: "circle",
1710
+ // fontSize: "12px",
1711
+ // }}
1712
+ // >
1713
+ // <li style={{ marginTop: "10px" }}>
1714
+ // During withdrawal, you may receive either or both tokens depending
1715
+ // on market conditions and prevailing prices.
1716
+ // </li>
1717
+ // </ul>
1718
+ // </div>
1719
+ // ),
1720
+ // address: ContractAddr.from(
1721
+ // "0xb7bd37121041261446d8eedec618955a4490641034942da688e8cbddea7b23"
1722
+ // ),
1723
+ // launchBlock: 1492136,
1724
+ // // must be same order as poolKey token0 and token1
1725
+ // depositTokens: [
1726
+ // Global.getDefaultTokens().find((t) => t.symbol === "STRK")!,
1727
+ // Global.getDefaultTokens().find((t) => t.symbol === "USDC")!,
1728
+ // ],
1729
+ // maxTVL: Web3Number.fromWei("0", 6),
1730
+ // additionalInfo: {
1731
+ // newBounds: "Managed by Re7",
1732
+ // feeBps: 1000,
1733
+ // rebalanceConditions: {
1734
+ // customShouldRebalance: async (currentPrice: number) =>
1735
+ // true,
1736
+ // minWaitHours: 6,
1737
+ // direction: "any",
1738
+ // },
1739
+ // },
1740
+ // },
1741
+ ];
1742
+
1743
+
1744
+ // 0x65b6a3ae00e7343ca8b2463d81401716c6581c18336206f31085c06a7d63936