@strkfarm/sdk 1.0.44 → 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,16 +1555,94 @@ 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
  [
1640
+ xSTRKSTRK,
1559
1641
  {
1560
- name: "Ekubo xSTRK/STRK",
1642
+ name: "Ekubo USDC/USDT",
1561
1643
  description: (
1562
1644
  <div>
1563
- <p>{_description.replace("{{POOL_NAME}}", "xSTRK/STRK")}</p>
1645
+ <p>{_description.replace("{{POOL_NAME}}", "USDC/USDT")}</p>
1564
1646
  <ul
1565
1647
  style={{
1566
1648
  marginLeft: "20px",
@@ -1572,33 +1654,30 @@ export const EkuboCLVaultStrategies: IStrategyMetadata<CLVaultStrategySettings>[
1572
1654
  During withdrawal, you may receive either or both tokens depending
1573
1655
  on market conditions and prevailing prices.
1574
1656
  </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
1657
  </ul>
1581
1658
  </div>
1582
1659
  ),
1583
1660
  address: ContractAddr.from(
1584
- "0x01f083b98674bc21effee29ef443a00c7b9a500fd92cf30341a3da12c73f2324"
1661
+ "0xd647ed735f0db52f2a5502b6e06ed21dc4284a43a36af4b60d3c80fbc56c91"
1585
1662
  ),
1586
- launchBlock: 1209881,
1663
+ launchBlock: 1385576,
1587
1664
  type: "Other",
1588
1665
  // must be same order as poolKey token0 and token1
1589
1666
  depositTokens: [
1590
- Global.getDefaultTokens().find((t) => t.symbol === "xSTRK")!,
1591
- Global.getDefaultTokens().find((t) => t.symbol === "STRK")!,
1667
+ Global.getDefaultTokens().find((t) => t.symbol === "USDC")!,
1668
+ Global.getDefaultTokens().find((t) => t.symbol === "USDT")!,
1592
1669
  ],
1593
1670
  protocols: [_protocol],
1594
1671
  auditUrl: AUDIT_URL,
1595
- maxTVL: Web3Number.fromWei("0", 18),
1672
+ maxTVL: Web3Number.fromWei("0", 6),
1596
1673
  risk: {
1597
- riskFactor: _riskFactor,
1674
+ riskFactor: _riskFactorStable,
1598
1675
  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),
1676
+ _riskFactorStable.reduce(
1677
+ (acc, curr) => acc + curr.value * curr.weight,
1678
+ 0
1679
+ ) / _riskFactorStable.reduce((acc, curr) => acc + curr.weight, 0),
1680
+ notARisks: getNoRiskTags(_riskFactorStable),
1602
1681
  },
1603
1682
  apyMethodology:
1604
1683
  "APY based on 7-day historical performance, including fees and rewards.",
@@ -1607,30 +1686,23 @@ export const EkuboCLVaultStrategies: IStrategyMetadata<CLVaultStrategySettings>[
1607
1686
  lower: -1,
1608
1687
  upper: 1,
1609
1688
  },
1610
- lstContract: ContractAddr.from(
1611
- "0x028d709c875c0ceac3dce7065bec5328186dc89fe254527084d1689910954b0a"
1612
- ),
1689
+ truePrice: 1,
1613
1690
  feeBps: 1000,
1614
1691
  rebalanceConditions: {
1615
- customShouldRebalance: async (currentPrice: number) => true,
1616
- minWaitHours: 24,
1617
- direction: "uponly",
1692
+ customShouldRebalance: async (currentPrice: number) =>
1693
+ currentPrice > 0.99 && currentPrice < 1.01,
1694
+ minWaitHours: 6,
1695
+ direction: "any",
1618
1696
  },
1619
1697
  },
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
- ],
1698
+ faqs: [...faqs],
1628
1699
  },
1629
1700
  // {
1630
- // name: "Ekubo USDC/USDT",
1701
+ // ...xSTRKSTRK,
1702
+ // name: "Ekubo STRK/USDC",
1631
1703
  // description: (
1632
1704
  // <div>
1633
- // <p>{_description.replace("{{POOL_NAME}}", "USDC/USDT")}</p>
1705
+ // <p>{_description.replace("{{POOL_NAME}}", "STRK/USDC")}</p>
1634
1706
  // <ul
1635
1707
  // style={{
1636
1708
  // marginLeft: "20px",
@@ -1646,43 +1718,27 @@ export const EkuboCLVaultStrategies: IStrategyMetadata<CLVaultStrategySettings>[
1646
1718
  // </div>
1647
1719
  // ),
1648
1720
  // address: ContractAddr.from(
1649
- // "0xd647ed735f0db52f2a5502b6e06ed21dc4284a43a36af4b60d3c80fbc56c91"
1721
+ // "0xb7bd37121041261446d8eedec618955a4490641034942da688e8cbddea7b23"
1650
1722
  // ),
1651
- // launchBlock: 1385576,
1652
- // type: "Other",
1723
+ // launchBlock: 1492136,
1653
1724
  // // must be same order as poolKey token0 and token1
1654
1725
  // depositTokens: [
1726
+ // Global.getDefaultTokens().find((t) => t.symbol === "STRK")!,
1655
1727
  // Global.getDefaultTokens().find((t) => t.symbol === "USDC")!,
1656
- // Global.getDefaultTokens().find((t) => t.symbol === "USDT")!,
1657
1728
  // ],
1658
- // protocols: [_protocol],
1659
- // auditUrl: AUDIT_URL,
1660
1729
  // maxTVL: Web3Number.fromWei("0", 6),
1661
- // risk: {
1662
- // riskFactor: _riskFactorStable,
1663
- // netRisk:
1664
- // _riskFactorStable.reduce(
1665
- // (acc, curr) => acc + curr.value * curr.weight,
1666
- // 0
1667
- // ) / _riskFactorStable.reduce((acc, curr) => acc + curr.weight, 0),
1668
- // notARisks: getNoRiskTags(_riskFactorStable),
1669
- // },
1670
- // apyMethodology:
1671
- // "APY based on 7-day historical performance, including fees and rewards.",
1672
1730
  // additionalInfo: {
1673
- // newBounds: {
1674
- // lower: -1,
1675
- // upper: 1,
1676
- // },
1677
- // truePrice: 1,
1731
+ // newBounds: "Managed by Re7",
1678
1732
  // feeBps: 1000,
1679
1733
  // rebalanceConditions: {
1680
1734
  // customShouldRebalance: async (currentPrice: number) =>
1681
- // currentPrice > 0.99 && currentPrice < 1.01,
1735
+ // true,
1682
1736
  // minWaitHours: 6,
1683
1737
  // direction: "any",
1684
1738
  // },
1685
1739
  // },
1686
- // faqs: [...faqs],
1687
1740
  // },
1688
- ];
1741
+ ];
1742
+
1743
+
1744
+ // 0x65b6a3ae00e7343ca8b2463d81401716c6581c18336206f31085c06a7d63936