@net-protocol/score 0.1.0 → 0.1.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.
package/dist/index.js CHANGED
@@ -1657,6 +1657,283 @@ var dynamic_split_strategy_default = [
1657
1657
  }
1658
1658
  ];
1659
1659
 
1660
+ // src/abis/multi-version-uniswap-bulk-pool-finder.json
1661
+ var multi_version_uniswap_bulk_pool_finder_default = [
1662
+ {
1663
+ type: "function",
1664
+ name: "V2_FACTORY",
1665
+ inputs: [],
1666
+ outputs: [{ name: "", type: "address", internalType: "address" }],
1667
+ stateMutability: "view"
1668
+ },
1669
+ {
1670
+ type: "function",
1671
+ name: "V3_FACTORY",
1672
+ inputs: [],
1673
+ outputs: [{ name: "", type: "address", internalType: "address" }],
1674
+ stateMutability: "view"
1675
+ },
1676
+ {
1677
+ type: "function",
1678
+ name: "V4_POOL_MANAGER",
1679
+ inputs: [],
1680
+ outputs: [{ name: "", type: "address", internalType: "address" }],
1681
+ stateMutability: "view"
1682
+ },
1683
+ {
1684
+ type: "function",
1685
+ name: "_checkV4PoolExternal",
1686
+ inputs: [
1687
+ {
1688
+ name: "poolKey",
1689
+ type: "tuple",
1690
+ internalType: "struct PoolKey",
1691
+ components: [
1692
+ {
1693
+ name: "currency0",
1694
+ type: "address",
1695
+ internalType: "Currency"
1696
+ },
1697
+ {
1698
+ name: "currency1",
1699
+ type: "address",
1700
+ internalType: "Currency"
1701
+ },
1702
+ { name: "fee", type: "uint24", internalType: "uint24" },
1703
+ { name: "tickSpacing", type: "int24", internalType: "int24" },
1704
+ {
1705
+ name: "hooks",
1706
+ type: "address",
1707
+ internalType: "contract IHooks"
1708
+ }
1709
+ ]
1710
+ }
1711
+ ],
1712
+ outputs: [{ name: "exists", type: "bool", internalType: "bool" }],
1713
+ stateMutability: "view"
1714
+ },
1715
+ {
1716
+ type: "function",
1717
+ name: "getPoolsMultiVersion",
1718
+ inputs: [
1719
+ {
1720
+ name: "params",
1721
+ type: "tuple",
1722
+ internalType: "struct MultiVersionUniswapBulkPoolFinder.PoolFinderParams",
1723
+ components: [
1724
+ {
1725
+ name: "tokenAs",
1726
+ type: "address[]",
1727
+ internalType: "address[]"
1728
+ },
1729
+ {
1730
+ name: "tokenBs",
1731
+ type: "address[]",
1732
+ internalType: "address[]"
1733
+ },
1734
+ { name: "fees", type: "uint24[]", internalType: "uint24[]" },
1735
+ {
1736
+ name: "v4TickSpacings",
1737
+ type: "int24[]",
1738
+ internalType: "int24[]"
1739
+ },
1740
+ {
1741
+ name: "v4Hooks",
1742
+ type: "address[]",
1743
+ internalType: "address[]"
1744
+ }
1745
+ ]
1746
+ }
1747
+ ],
1748
+ outputs: [
1749
+ {
1750
+ name: "pools",
1751
+ type: "tuple[]",
1752
+ internalType: "struct MultiVersionUniswapBulkPoolFinder.PoolDiscovery[]",
1753
+ components: [
1754
+ {
1755
+ name: "pairIndex",
1756
+ type: "uint256",
1757
+ internalType: "uint256"
1758
+ },
1759
+ { name: "version", type: "uint8", internalType: "uint8" },
1760
+ {
1761
+ name: "poolAddress",
1762
+ type: "address",
1763
+ internalType: "address"
1764
+ },
1765
+ {
1766
+ name: "poolKey",
1767
+ type: "tuple",
1768
+ internalType: "struct PoolKey",
1769
+ components: [
1770
+ {
1771
+ name: "currency0",
1772
+ type: "address",
1773
+ internalType: "Currency"
1774
+ },
1775
+ {
1776
+ name: "currency1",
1777
+ type: "address",
1778
+ internalType: "Currency"
1779
+ },
1780
+ { name: "fee", type: "uint24", internalType: "uint24" },
1781
+ {
1782
+ name: "tickSpacing",
1783
+ type: "int24",
1784
+ internalType: "int24"
1785
+ },
1786
+ {
1787
+ name: "hooks",
1788
+ type: "address",
1789
+ internalType: "contract IHooks"
1790
+ }
1791
+ ]
1792
+ },
1793
+ { name: "fee", type: "uint24", internalType: "uint24" },
1794
+ { name: "tickSpacing", type: "int24", internalType: "int24" },
1795
+ { name: "hooks", type: "address", internalType: "address" }
1796
+ ]
1797
+ },
1798
+ { name: "count", type: "uint256", internalType: "uint256" }
1799
+ ],
1800
+ stateMutability: "view"
1801
+ }
1802
+ ];
1803
+
1804
+ // src/abis/multi-version-uniswap-pool-info-retriever.json
1805
+ var multi_version_uniswap_pool_info_retriever_default = [
1806
+ {
1807
+ type: "function",
1808
+ name: "V4_POOL_MANAGER",
1809
+ inputs: [],
1810
+ outputs: [{ name: "", type: "address", internalType: "address" }],
1811
+ stateMutability: "view"
1812
+ },
1813
+ {
1814
+ type: "function",
1815
+ name: "_getV4Slot0",
1816
+ inputs: [
1817
+ {
1818
+ name: "poolKey",
1819
+ type: "tuple",
1820
+ internalType: "struct PoolKey",
1821
+ components: [
1822
+ {
1823
+ name: "currency0",
1824
+ type: "address",
1825
+ internalType: "Currency"
1826
+ },
1827
+ {
1828
+ name: "currency1",
1829
+ type: "address",
1830
+ internalType: "Currency"
1831
+ },
1832
+ { name: "fee", type: "uint24", internalType: "uint24" },
1833
+ { name: "tickSpacing", type: "int24", internalType: "int24" },
1834
+ {
1835
+ name: "hooks",
1836
+ type: "address",
1837
+ internalType: "contract IHooks"
1838
+ }
1839
+ ]
1840
+ }
1841
+ ],
1842
+ outputs: [
1843
+ { name: "sqrtPriceX96", type: "uint160", internalType: "uint160" }
1844
+ ],
1845
+ stateMutability: "view"
1846
+ },
1847
+ {
1848
+ type: "function",
1849
+ name: "getPoolsFullInfoMultiVersion",
1850
+ inputs: [
1851
+ {
1852
+ name: "v2PoolAddresses",
1853
+ type: "address[]",
1854
+ internalType: "address[]"
1855
+ },
1856
+ {
1857
+ name: "v3PoolAddresses",
1858
+ type: "address[]",
1859
+ internalType: "address[]"
1860
+ },
1861
+ {
1862
+ name: "v4PoolKeys",
1863
+ type: "tuple[]",
1864
+ internalType: "struct PoolKey[]",
1865
+ components: [
1866
+ {
1867
+ name: "currency0",
1868
+ type: "address",
1869
+ internalType: "Currency"
1870
+ },
1871
+ {
1872
+ name: "currency1",
1873
+ type: "address",
1874
+ internalType: "Currency"
1875
+ },
1876
+ { name: "fee", type: "uint24", internalType: "uint24" },
1877
+ { name: "tickSpacing", type: "int24", internalType: "int24" },
1878
+ {
1879
+ name: "hooks",
1880
+ type: "address",
1881
+ internalType: "contract IHooks"
1882
+ }
1883
+ ]
1884
+ },
1885
+ { name: "baseToken", type: "address", internalType: "address" }
1886
+ ],
1887
+ outputs: [
1888
+ {
1889
+ name: "",
1890
+ type: "tuple[]",
1891
+ internalType: "struct MultiVersionPoolInfoRetriever.PoolFullInfo[]",
1892
+ components: [
1893
+ {
1894
+ name: "poolAddress",
1895
+ type: "address",
1896
+ internalType: "address"
1897
+ },
1898
+ { name: "token0", type: "address", internalType: "address" },
1899
+ { name: "token1", type: "address", internalType: "address" },
1900
+ {
1901
+ name: "token0Decimals",
1902
+ type: "uint8",
1903
+ internalType: "uint8"
1904
+ },
1905
+ {
1906
+ name: "token1Decimals",
1907
+ type: "uint8",
1908
+ internalType: "uint8"
1909
+ },
1910
+ {
1911
+ name: "sqrtPriceX96",
1912
+ type: "uint256",
1913
+ internalType: "uint256"
1914
+ },
1915
+ {
1916
+ name: "baseTokenBalance",
1917
+ type: "uint256",
1918
+ internalType: "uint256"
1919
+ },
1920
+ {
1921
+ name: "token0Balance",
1922
+ type: "uint256",
1923
+ internalType: "uint256"
1924
+ },
1925
+ {
1926
+ name: "token1Balance",
1927
+ type: "uint256",
1928
+ internalType: "uint256"
1929
+ }
1930
+ ]
1931
+ }
1932
+ ],
1933
+ stateMutability: "view"
1934
+ }
1935
+ ];
1936
+
1660
1937
  // src/constants.ts
1661
1938
  var SCORE_CONTRACT = {
1662
1939
  address: "0x0000000fa09b022e5616e5a173b4b67fa2fbcf28",
@@ -1690,6 +1967,17 @@ var ALL_STRATEGY_ADDRESSES = [
1690
1967
  var LEGACY_UPVOTE_V1_ADDRESS = "0x0ada882dbbdc12388a1f9ca85d2d847088f747df";
1691
1968
  var LEGACY_UPVOTE_V2_ADDRESS = "0x9027dcad0a3dca5835895e14fbc022a1e5ea909b";
1692
1969
  var SUPPORTED_SCORE_CHAINS = [8453];
1970
+ var MULTI_VERSION_UNISWAP_BULK_POOL_FINDER = {
1971
+ address: "0xbc237dac4c74c170780fc12f353a258bdd31a8cf",
1972
+ abi: multi_version_uniswap_bulk_pool_finder_default
1973
+ };
1974
+ var MULTI_VERSION_UNISWAP_POOL_INFO_RETRIEVER = {
1975
+ address: "0x7A9EF0AC6F6a254cd570B05D62D094D3aa5067f1",
1976
+ abi: multi_version_uniswap_pool_info_retriever_default
1977
+ };
1978
+ var WETH_ADDRESS = "0x4200000000000000000000000000000000000006";
1979
+ var NULL_ADDRESS = "0x0000000000000000000000000000000000000000";
1980
+ var UPVOTE_PRICE_ETH = 25e-6;
1693
1981
  var encodeUpvoteKey = (tokenAddress) => {
1694
1982
  return `0x${BigInt(`0x${tokenAddress.slice(2)}`).toString(16).padStart(64, "0")}`;
1695
1983
  };
@@ -2116,21 +2404,400 @@ var encodePoolKey = (poolKey) => {
2116
2404
  function isValidPoolKey2(poolKey) {
2117
2405
  return poolKey.fee !== void 0 || poolKey.tickSpacing !== void 0 || poolKey.currency0 !== void 0;
2118
2406
  }
2407
+ var V3_V4_FEE_TIERS = [500, 3e3, 1e4, 12e3, 8388608];
2408
+ var V4_TICK_SPACINGS = [200];
2409
+ var V4_HOOKS = [
2410
+ NULL_ADDRESS,
2411
+ "0xDd5EeaFf7BD481AD55Db083062b13a3cdf0A68CC",
2412
+ "0x34a45c6B61876d739400Bd71228CbcbD4F53E8cC",
2413
+ "0xb429d62f8f3bFFb98CdB9569533eA23bF0Ba28CC",
2414
+ "0xd60D6B218116cFd801E28F78d011a203D2b068Cc",
2415
+ "0x3e342a06f9592459D75721d6956B570F02eF2Dc0",
2416
+ "0xbB7784A4d481184283Ed89619A3e3ed143e1Adc0"
2417
+ ];
2418
+ var LIQUIDITY_THRESHOLD_TO_PREFER_V2_V3_POOLS = 0.1 * 1e18;
2419
+ var LIQUIDITY_THRESHOLD_TO_CONSIDER_V2_V3_POOLS = 0.01 * 1e18;
2420
+ function normalizeTokenPairs(pairs) {
2421
+ return pairs.map((pair) => {
2422
+ const tokenA = pair.tokenAddress;
2423
+ const tokenB = pair.baseTokenAddress || WETH_ADDRESS;
2424
+ return {
2425
+ originalPair: pair,
2426
+ tokenA: tokenA.toLowerCase() < tokenB.toLowerCase() ? tokenA : tokenB,
2427
+ tokenB: tokenA.toLowerCase() < tokenB.toLowerCase() ? tokenB : tokenA
2428
+ };
2429
+ });
2430
+ }
2431
+ function buildDiscoveryArgs(normalizedPairs) {
2432
+ return {
2433
+ tokenAs: normalizedPairs.map((p) => p.tokenA),
2434
+ tokenBs: normalizedPairs.map((p) => p.tokenB),
2435
+ fees: V3_V4_FEE_TIERS,
2436
+ v4TickSpacings: V4_TICK_SPACINGS,
2437
+ v4Hooks: V4_HOOKS
2438
+ };
2439
+ }
2440
+ function parsePoolDiscoveries(poolResults, pairs) {
2441
+ if (!poolResults) {
2442
+ return {
2443
+ v2PoolAddresses: [],
2444
+ v3PoolAddresses: [],
2445
+ v4PoolKeys: [],
2446
+ v2PoolAddressToPair: {},
2447
+ v3PoolAddressToPair: {},
2448
+ v4PoolKeyToPair: {}
2449
+ };
2450
+ }
2451
+ const [discoveries, countRaw] = poolResults;
2452
+ const countNum = typeof countRaw === "bigint" ? Number(countRaw) : Number(countRaw || 0);
2453
+ const v2PoolAddresses = [];
2454
+ const v3PoolAddresses = [];
2455
+ const v4PoolKeys = [];
2456
+ const seenV2V3Addresses = /* @__PURE__ */ new Set();
2457
+ const seenV4Keys = /* @__PURE__ */ new Set();
2458
+ const v2PoolAddressToPair = {};
2459
+ const v3PoolAddressToPair = {};
2460
+ const v4PoolKeyToPair = {};
2461
+ for (let i = 0; i < Math.min(countNum, discoveries.length); i++) {
2462
+ const discovery = discoveries[i];
2463
+ const version = Number(discovery?.version ?? 0);
2464
+ const poolAddressValue = discovery?.poolAddress;
2465
+ const pairIndex = Number(discovery?.pairIndex ?? 0);
2466
+ const feeNum = Number(discovery?.fee ?? 0);
2467
+ const poolKey = discovery?.poolKey;
2468
+ const pair = pairs[pairIndex];
2469
+ if (!pair) continue;
2470
+ if (version === 2 && poolAddressValue && poolAddressValue !== NULL_ADDRESS) {
2471
+ const poolAddress = poolAddressValue.toLowerCase();
2472
+ if (!seenV2V3Addresses.has(poolAddress)) {
2473
+ seenV2V3Addresses.add(poolAddress);
2474
+ v2PoolAddresses.push(poolAddressValue);
2475
+ v2PoolAddressToPair[poolAddress] = {
2476
+ tokenAddress: pair.tokenAddress,
2477
+ baseTokenAddress: pair.baseTokenAddress || WETH_ADDRESS,
2478
+ fee: feeNum
2479
+ };
2480
+ }
2481
+ } else if (version === 3 && poolAddressValue && poolAddressValue !== NULL_ADDRESS) {
2482
+ const poolAddress = poolAddressValue.toLowerCase();
2483
+ if (!seenV2V3Addresses.has(poolAddress)) {
2484
+ seenV2V3Addresses.add(poolAddress);
2485
+ v3PoolAddresses.push(poolAddressValue);
2486
+ v3PoolAddressToPair[poolAddress] = {
2487
+ tokenAddress: pair.tokenAddress,
2488
+ baseTokenAddress: pair.baseTokenAddress || WETH_ADDRESS,
2489
+ fee: feeNum
2490
+ };
2491
+ }
2492
+ } else if (version === 4 && poolKey) {
2493
+ const poolKeyString = JSON.stringify(poolKey);
2494
+ if (!seenV4Keys.has(poolKeyString)) {
2495
+ seenV4Keys.add(poolKeyString);
2496
+ v4PoolKeys.push(poolKey);
2497
+ v4PoolKeyToPair[poolKeyString] = {
2498
+ tokenAddress: pair.tokenAddress,
2499
+ baseTokenAddress: pair.baseTokenAddress || WETH_ADDRESS,
2500
+ fee: feeNum
2501
+ };
2502
+ }
2503
+ }
2504
+ }
2505
+ return {
2506
+ v2PoolAddresses,
2507
+ v3PoolAddresses,
2508
+ v4PoolKeys,
2509
+ v2PoolAddressToPair,
2510
+ v3PoolAddressToPair,
2511
+ v4PoolKeyToPair
2512
+ };
2513
+ }
2514
+ function determinePoolVersion(discoveries, index) {
2515
+ const {
2516
+ v2PoolAddresses,
2517
+ v3PoolAddresses,
2518
+ v4PoolKeys,
2519
+ v2PoolAddressToPair,
2520
+ v3PoolAddressToPair,
2521
+ v4PoolKeyToPair
2522
+ } = discoveries;
2523
+ if (index < v2PoolAddresses.length) {
2524
+ const poolAddress = v2PoolAddresses[index].toLowerCase();
2525
+ return {
2526
+ version: 2,
2527
+ pair: v2PoolAddressToPair[poolAddress],
2528
+ fee: 0,
2529
+ v4PoolKey: void 0
2530
+ };
2531
+ } else if (index < v2PoolAddresses.length + v3PoolAddresses.length) {
2532
+ const v3Index = index - v2PoolAddresses.length;
2533
+ const poolAddress = v3PoolAddresses[v3Index].toLowerCase();
2534
+ return {
2535
+ version: 3,
2536
+ pair: v3PoolAddressToPair[poolAddress],
2537
+ fee: v3PoolAddressToPair[poolAddress]?.fee || 0,
2538
+ v4PoolKey: void 0
2539
+ };
2540
+ } else {
2541
+ const v4Index = index - v2PoolAddresses.length - v3PoolAddresses.length;
2542
+ const poolKey = v4PoolKeys[v4Index];
2543
+ const poolKeyString = JSON.stringify(poolKey);
2544
+ return {
2545
+ version: 4,
2546
+ pair: v4PoolKeyToPair[poolKeyString],
2547
+ fee: v4PoolKeyToPair[poolKeyString]?.fee || 0,
2548
+ v4PoolKey: poolKey
2549
+ };
2550
+ }
2551
+ }
2552
+ function calculatePriceFromSqrtPriceX96(sqrtPriceX96, token0Decimals, token1Decimals, isToken0) {
2553
+ const sqrtPrice = Number(sqrtPriceX96);
2554
+ if (sqrtPrice === 0) return 0;
2555
+ const priceX96 = (sqrtPrice / 2 ** 96) ** 2;
2556
+ if (isToken0) {
2557
+ return priceX96 * 10 ** (token0Decimals - token1Decimals);
2558
+ } else {
2559
+ return 1 / priceX96 * 10 ** (token1Decimals - token0Decimals);
2560
+ }
2561
+ }
2562
+ function calculatePoolPrice(info, pair, version) {
2563
+ try {
2564
+ const sqrtPriceX96 = Number(info.sqrtPriceX96);
2565
+ const token0Decimals = Number(info.token0Decimals);
2566
+ const token1Decimals = Number(info.token1Decimals);
2567
+ const isToken0 = info.token0.toLowerCase() === pair.tokenAddress.toLowerCase();
2568
+ if (version === 2) {
2569
+ const token0Balance = Number(info.token0Balance) / 10 ** token0Decimals;
2570
+ const token1Balance = Number(info.token1Balance) / 10 ** token1Decimals;
2571
+ if (token0Balance === 0 || token1Balance === 0) return null;
2572
+ if (isToken0) {
2573
+ return token1Balance / token0Balance;
2574
+ } else {
2575
+ return token0Balance / token1Balance;
2576
+ }
2577
+ } else {
2578
+ if (sqrtPriceX96 === 0) return null;
2579
+ if (isToken0) {
2580
+ return (sqrtPriceX96 / 2 ** 96) ** 2 * 10 ** (token0Decimals - token1Decimals);
2581
+ } else {
2582
+ const priceX96 = (sqrtPriceX96 / 2 ** 96) ** 2;
2583
+ return 1 / priceX96 * 10 ** (token1Decimals - token0Decimals);
2584
+ }
2585
+ }
2586
+ } catch {
2587
+ return null;
2588
+ }
2589
+ }
2590
+ function constructPoolKey(info, pair, version, v4PoolKey) {
2591
+ try {
2592
+ if (!info.token0 || !info.token1 || typeof pair.fee !== "number") {
2593
+ return void 0;
2594
+ }
2595
+ if (!info.token0.startsWith("0x") || !info.token1.startsWith("0x")) {
2596
+ return void 0;
2597
+ }
2598
+ const currency0 = info.token0.toLowerCase() < info.token1.toLowerCase() ? info.token0 : info.token1;
2599
+ const currency1 = info.token0.toLowerCase() < info.token1.toLowerCase() ? info.token1 : info.token0;
2600
+ if (version === 2) {
2601
+ return {
2602
+ currency0,
2603
+ currency1,
2604
+ fee: 0,
2605
+ tickSpacing: 0,
2606
+ hooks: NULL_ADDRESS
2607
+ };
2608
+ } else if (version === 3) {
2609
+ return {
2610
+ currency0,
2611
+ currency1,
2612
+ fee: pair.fee,
2613
+ tickSpacing: 0,
2614
+ hooks: NULL_ADDRESS
2615
+ };
2616
+ } else {
2617
+ if (!v4PoolKey || !v4PoolKey.currency0 || !v4PoolKey.currency1) {
2618
+ return void 0;
2619
+ }
2620
+ return v4PoolKey;
2621
+ }
2622
+ } catch {
2623
+ return void 0;
2624
+ }
2625
+ }
2626
+ function getWethBalanceWei(pool) {
2627
+ if (pool.token0?.toLowerCase() === WETH_ADDRESS.toLowerCase()) {
2628
+ return Number(pool.token0Balance);
2629
+ } else if (pool.token1?.toLowerCase() === WETH_ADDRESS.toLowerCase()) {
2630
+ return Number(pool.token1Balance);
2631
+ } else {
2632
+ return Number(pool.baseTokenBalance);
2633
+ }
2634
+ }
2635
+ function filterV2V3PoolsByLiquidity(pools, threshold) {
2636
+ return pools.filter((pool) => {
2637
+ if (!pool.poolAddress) return false;
2638
+ const wethBalanceWei = getWethBalanceWei(pool);
2639
+ return wethBalanceWei >= threshold;
2640
+ });
2641
+ }
2642
+ function selectBestV2V3Pool(pools) {
2643
+ return pools.reduce((a, b) => {
2644
+ const aIsV3 = a.fee > 0;
2645
+ const bIsV3 = b.fee > 0;
2646
+ if (aIsV3 && !bIsV3) return a;
2647
+ if (!aIsV3 && bIsV3) return b;
2648
+ return Number(a.baseTokenBalance) > Number(b.baseTokenBalance) ? a : b;
2649
+ });
2650
+ }
2651
+ function selectBestV4Pool(pools) {
2652
+ return pools.reduce((a, b) => {
2653
+ return a.fee < b.fee ? a : b;
2654
+ });
2655
+ }
2656
+ function selectBestV2V3PoolByFee(pools) {
2657
+ return pools.reduce((a, b) => {
2658
+ return a.fee < b.fee ? a : b;
2659
+ });
2660
+ }
2661
+ function selectBestPoolPerPair(allPools) {
2662
+ const poolsByPair = {};
2663
+ for (const pool of allPools) {
2664
+ const key = pool.tokenAddress.toLowerCase() + "_" + pool.baseTokenAddress.toLowerCase();
2665
+ if (!poolsByPair[key]) poolsByPair[key] = [];
2666
+ poolsByPair[key].push(pool);
2667
+ }
2668
+ const bestPools = [];
2669
+ for (const [, group] of Object.entries(poolsByPair)) {
2670
+ let best;
2671
+ if (group.length === 1) {
2672
+ best = group[0];
2673
+ } else {
2674
+ const v2v3PoolsWithPreferredLiquidity = filterV2V3PoolsByLiquidity(
2675
+ group,
2676
+ LIQUIDITY_THRESHOLD_TO_PREFER_V2_V3_POOLS
2677
+ );
2678
+ if (v2v3PoolsWithPreferredLiquidity.length > 0) {
2679
+ best = selectBestV2V3Pool(v2v3PoolsWithPreferredLiquidity);
2680
+ } else {
2681
+ const v4Pools = group.filter((pool) => !pool.poolAddress);
2682
+ if (v4Pools.length > 0) {
2683
+ best = selectBestV4Pool(v4Pools);
2684
+ } else {
2685
+ const v2v3PoolsWithAcceptableLiquidity = filterV2V3PoolsByLiquidity(
2686
+ group,
2687
+ LIQUIDITY_THRESHOLD_TO_CONSIDER_V2_V3_POOLS
2688
+ );
2689
+ if (v2v3PoolsWithAcceptableLiquidity.length > 0) {
2690
+ best = selectBestV2V3PoolByFee(v2v3PoolsWithAcceptableLiquidity);
2691
+ }
2692
+ }
2693
+ }
2694
+ }
2695
+ if (best) {
2696
+ bestPools.push(best);
2697
+ }
2698
+ }
2699
+ return bestPools;
2700
+ }
2701
+ async function discoverPools({
2702
+ publicClient,
2703
+ pairs
2704
+ }) {
2705
+ if (pairs.length === 0) return [];
2706
+ const normalizedPairs = normalizeTokenPairs(pairs);
2707
+ const discoveryArgs = buildDiscoveryArgs(normalizedPairs);
2708
+ const poolResults = await actions.readContract(publicClient, {
2709
+ address: MULTI_VERSION_UNISWAP_BULK_POOL_FINDER.address,
2710
+ abi: MULTI_VERSION_UNISWAP_BULK_POOL_FINDER.abi,
2711
+ functionName: "getPoolsMultiVersion",
2712
+ args: [discoveryArgs]
2713
+ });
2714
+ const discoveries = parsePoolDiscoveries(poolResults, pairs);
2715
+ const totalPools = discoveries.v2PoolAddresses.length + discoveries.v3PoolAddresses.length + discoveries.v4PoolKeys.length;
2716
+ if (totalPools === 0) return [];
2717
+ const poolInfos = await actions.readContract(publicClient, {
2718
+ address: MULTI_VERSION_UNISWAP_POOL_INFO_RETRIEVER.address,
2719
+ abi: MULTI_VERSION_UNISWAP_POOL_INFO_RETRIEVER.abi,
2720
+ functionName: "getPoolsFullInfoMultiVersion",
2721
+ args: [
2722
+ discoveries.v2PoolAddresses,
2723
+ discoveries.v3PoolAddresses,
2724
+ discoveries.v4PoolKeys,
2725
+ WETH_ADDRESS
2726
+ ]
2727
+ });
2728
+ if (!Array.isArray(poolInfos) || poolInfos.length === 0) return [];
2729
+ const allPools = poolInfos.map((info, index) => {
2730
+ const poolData = determinePoolVersion(discoveries, index);
2731
+ if (!poolData || !poolData.pair) return null;
2732
+ return {
2733
+ tokenAddress: poolData.pair.tokenAddress,
2734
+ baseTokenAddress: poolData.pair.baseTokenAddress || WETH_ADDRESS,
2735
+ poolAddress: poolData.version === 4 ? null : info.poolAddress,
2736
+ price: calculatePoolPrice(info, poolData.pair, poolData.version),
2737
+ baseTokenBalance: String(info.baseTokenBalance || 0),
2738
+ token0: info.token0,
2739
+ token1: info.token1,
2740
+ token0Balance: String(info.token0Balance || 0),
2741
+ token1Balance: String(info.token1Balance || 0),
2742
+ fee: poolData.fee,
2743
+ poolKey: constructPoolKey(
2744
+ info,
2745
+ poolData.pair,
2746
+ poolData.version,
2747
+ poolData.v4PoolKey
2748
+ )
2749
+ };
2750
+ }).filter((p) => p !== null);
2751
+ const bestPools = selectBestPoolPerPair(allPools);
2752
+ return bestPools.map(
2753
+ (pool) => ({
2754
+ tokenAddress: pool.tokenAddress,
2755
+ baseTokenAddress: pool.baseTokenAddress,
2756
+ poolAddress: pool.poolAddress,
2757
+ price: pool.price,
2758
+ fee: pool.fee,
2759
+ poolKey: pool.poolKey,
2760
+ balances: {
2761
+ baseTokenBalance: pool.baseTokenBalance,
2762
+ token0Balance: pool.token0Balance,
2763
+ token1Balance: pool.token1Balance
2764
+ }
2765
+ })
2766
+ );
2767
+ }
2768
+ async function discoverTokenPool({
2769
+ publicClient,
2770
+ tokenAddress
2771
+ }) {
2772
+ const results = await discoverPools({
2773
+ publicClient,
2774
+ pairs: [{ tokenAddress }]
2775
+ });
2776
+ return results[0] ?? null;
2777
+ }
2119
2778
 
2120
2779
  exports.ALL_STRATEGY_ADDRESSES = ALL_STRATEGY_ADDRESSES;
2121
2780
  exports.DYNAMIC_SPLIT_STRATEGY = DYNAMIC_SPLIT_STRATEGY;
2122
2781
  exports.LEGACY_UPVOTE_V1_ADDRESS = LEGACY_UPVOTE_V1_ADDRESS;
2123
2782
  exports.LEGACY_UPVOTE_V2_ADDRESS = LEGACY_UPVOTE_V2_ADDRESS;
2783
+ exports.MULTI_VERSION_UNISWAP_BULK_POOL_FINDER = MULTI_VERSION_UNISWAP_BULK_POOL_FINDER;
2784
+ exports.MULTI_VERSION_UNISWAP_POOL_INFO_RETRIEVER = MULTI_VERSION_UNISWAP_POOL_INFO_RETRIEVER;
2785
+ exports.NULL_ADDRESS = NULL_ADDRESS;
2124
2786
  exports.PURE_ALPHA_STRATEGY = PURE_ALPHA_STRATEGY;
2125
2787
  exports.SCORE_CONTRACT = SCORE_CONTRACT;
2126
2788
  exports.SUPPORTED_SCORE_CHAINS = SUPPORTED_SCORE_CHAINS;
2127
2789
  exports.ScoreClient = ScoreClient;
2128
2790
  exports.UNIV234_POOLS_STRATEGY = UNIV234_POOLS_STRATEGY;
2129
2791
  exports.UPVOTE_APP = UPVOTE_APP;
2792
+ exports.UPVOTE_PRICE_ETH = UPVOTE_PRICE_ETH;
2130
2793
  exports.UPVOTE_STORAGE_APP = UPVOTE_STORAGE_APP;
2794
+ exports.WETH_ADDRESS = WETH_ADDRESS;
2795
+ exports.calculatePriceFromSqrtPriceX96 = calculatePriceFromSqrtPriceX96;
2131
2796
  exports.decodeStrategyMetadata = decodeStrategyMetadata;
2132
2797
  exports.decodeUpvoteMessage = decodeUpvoteMessage;
2133
2798
  exports.decodeUpvoteStorageBlob = decodeUpvoteStorageBlob;
2799
+ exports.discoverPools = discoverPools;
2800
+ exports.discoverTokenPool = discoverTokenPool;
2134
2801
  exports.encodePoolKey = encodePoolKey;
2135
2802
  exports.encodeUpvoteKey = encodeUpvoteKey;
2136
2803
  exports.extractStrategyAddress = extractStrategyAddress;