@net-protocol/score 0.1.7 → 0.1.9

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.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { readContract } from 'viem/actions';
2
- import { getPublicClient, getBaseDataSuffix } from '@net-protocol/core';
2
+ import { getPublicClient, getBaseDataSuffix, NetClient } from '@net-protocol/core';
3
3
  import { decodeAbiParameters, keccak256, encodePacked, getAddress, encodeAbiParameters, isAddressEqual } from 'viem';
4
- import { getStorageKeyBytes } from '@net-protocol/storage';
4
+ import { getStorageKeyBytes, STORAGE_CONTRACT } from '@net-protocol/storage';
5
5
 
6
6
  // src/client/ScoreClient.ts
7
7
 
@@ -2482,6 +2482,44 @@ var user_upvote_default = [
2482
2482
  { type: "error", name: "ZeroUpvotes", inputs: [] }
2483
2483
  ];
2484
2484
 
2485
+ // src/abis/erc20-bulk-info-helper.json
2486
+ var erc20_bulk_info_helper_default = [
2487
+ {
2488
+ type: "function",
2489
+ name: "getTokenInfo",
2490
+ inputs: [
2491
+ {
2492
+ name: "tokenAddresses",
2493
+ type: "address[]",
2494
+ internalType: "address[]"
2495
+ }
2496
+ ],
2497
+ outputs: [
2498
+ {
2499
+ name: "tokenInfos",
2500
+ type: "tuple[]",
2501
+ internalType: "struct ERC20BulkInfoHelper.TokenInfo[]",
2502
+ components: [
2503
+ { name: "name", type: "string", internalType: "string" },
2504
+ { name: "symbol", type: "string", internalType: "string" },
2505
+ { name: "decimals", type: "uint8", internalType: "uint8" },
2506
+ {
2507
+ name: "totalSupply",
2508
+ type: "uint256",
2509
+ internalType: "uint256"
2510
+ },
2511
+ {
2512
+ name: "burnedTokens",
2513
+ type: "uint256",
2514
+ internalType: "uint256"
2515
+ }
2516
+ ]
2517
+ }
2518
+ ],
2519
+ stateMutability: "view"
2520
+ }
2521
+ ];
2522
+
2485
2523
  // src/constants.ts
2486
2524
  var SCORE_CONTRACT = {
2487
2525
  address: "0x0000000fa09b022e5616e5a173b4b67fa2fbcf28",
@@ -2542,6 +2580,10 @@ var USER_UPVOTE_CONTRACT = {
2542
2580
  address: "0xa4bc2c63dd0157692fd5f409389e5032e37d8895",
2543
2581
  abi: user_upvote_default
2544
2582
  };
2583
+ var ERC20_BULK_INFO_HELPER_CONTRACT = {
2584
+ address: "0x00000051809cbfacdf7d08ada813836822b880a2",
2585
+ abi: erc20_bulk_info_helper_default
2586
+ };
2545
2587
  var encodeUpvoteKey = (tokenAddress) => {
2546
2588
  return `0x${BigInt(`0x${tokenAddress.slice(2)}`).toString(16).padStart(64, "0")}`;
2547
2589
  };
@@ -3207,41 +3249,6 @@ var UserUpvoteClient = class {
3207
3249
  return hash;
3208
3250
  }
3209
3251
  };
3210
- var encodePoolKey = (poolKey) => {
3211
- if (!poolKey || !isValidPoolKey2(poolKey)) {
3212
- return "0x";
3213
- }
3214
- try {
3215
- return encodeAbiParameters(
3216
- [
3217
- {
3218
- type: "tuple",
3219
- components: [
3220
- { name: "currency0", type: "address" },
3221
- { name: "currency1", type: "address" },
3222
- { name: "fee", type: "uint24" },
3223
- { name: "tickSpacing", type: "int24" },
3224
- { name: "hooks", type: "address" }
3225
- ]
3226
- }
3227
- ],
3228
- [
3229
- {
3230
- currency0: poolKey.currency0,
3231
- currency1: poolKey.currency1,
3232
- fee: poolKey.fee,
3233
- tickSpacing: poolKey.tickSpacing,
3234
- hooks: poolKey.hooks
3235
- }
3236
- ]
3237
- );
3238
- } catch {
3239
- return "0x";
3240
- }
3241
- };
3242
- function isValidPoolKey2(poolKey) {
3243
- return poolKey.fee !== void 0 || poolKey.tickSpacing !== void 0 || poolKey.currency0 !== void 0;
3244
- }
3245
3252
  var V3_V4_FEE_TIERS = [500, 3e3, 1e4, 12e3, 8388608];
3246
3253
  var V4_TICK_SPACINGS = [200];
3247
3254
  var V4_HOOKS = [
@@ -3595,6 +3602,433 @@ async function discoverTokenPool({
3595
3602
  return results[0] ?? null;
3596
3603
  }
3597
3604
 
3598
- export { ALL_STRATEGY_ADDRESSES, DYNAMIC_SPLIT_STRATEGY, LEGACY_UPVOTE_V1_ADDRESS, LEGACY_UPVOTE_V2_ADDRESS, MULTI_VERSION_UNISWAP_BULK_POOL_FINDER, MULTI_VERSION_UNISWAP_POOL_INFO_RETRIEVER, NULL_ADDRESS, PURE_ALPHA_STRATEGY, SCORE_CONTRACT, SUPPORTED_SCORE_CHAINS, ScoreClient, UNIV234_POOLS_STRATEGY, UPVOTE_APP, UPVOTE_PRICE_ETH, UPVOTE_STORAGE_APP, USER_UPVOTE_CONTRACT, UserUpvoteClient, buildUserUpvote, buildUserUpvoteReceived, calculatePriceFromSqrtPriceX96, calculatePriceInUsdc, calculateUpvoteCost, calculateUserTokenBalance, decodeStrategyMetadata, decodeUpvoteMessage, decodeUpvoteStorageBlob, discoverPools, discoverTokenPool, encodePoolKey, encodeUpvoteKey, extractStrategyAddress, extractTokenAddressFromScoreKey, extractTokenAddressesFromMessages, getFeedContentKey, getScoreKey, getStorageScoreKey, getStorageUpvoteContext, getTokenScoreKey, getWethAddress, isDynamicSplitStrategy, isPureAlphaStrategy, isStrategyMessage, isTokenScoreKey, isUniv234PoolsStrategy, isUserUpvoteMessage, parseUserUpvoteMessage, selectStrategy, tokenAddressToUpvoteKeyString, validateUpvoteParams, validateUserUpvoteMessage };
3605
+ // src/ranking/getTokenRankings.ts
3606
+ var DEFAULT_MESSAGE_SCAN_WINDOW = 150;
3607
+ var DEFAULT_MAX_TOKENS = 50;
3608
+ var DEFAULT_MIN_UPVOTES = 500;
3609
+ var DEFAULT_MIN_MARKET_CAP = 4e4;
3610
+ var DEFAULT_RECENCY_HOURS = 48;
3611
+ var USDC_ADDRESS_BY_CHAIN = {
3612
+ 8453: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
3613
+ };
3614
+ var ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
3615
+ async function getTokenRankings(options) {
3616
+ const {
3617
+ chainId,
3618
+ sort = "trending",
3619
+ maxTokens = DEFAULT_MAX_TOKENS,
3620
+ messageScanWindow = DEFAULT_MESSAGE_SCAN_WINDOW,
3621
+ rpcUrl
3622
+ } = options;
3623
+ validateChainSupported(chainId);
3624
+ const minUpvotes = options.thresholds?.minUpvotes ?? DEFAULT_MIN_UPVOTES;
3625
+ const minMarketCap = options.thresholds?.minMarketCap ?? DEFAULT_MIN_MARKET_CAP;
3626
+ const recencyHours = options.thresholds?.recencyHours ?? DEFAULT_RECENCY_HOURS;
3627
+ const nowSec = Date.now() / 1e3;
3628
+ const rpcOverride = rpcUrl ? { rpcUrls: Array.isArray(rpcUrl) ? rpcUrl : [rpcUrl] } : void 0;
3629
+ const publicClient = getPublicClient({ chainId, rpcUrl });
3630
+ const netClient = new NetClient({ chainId, overrides: rpcOverride });
3631
+ const messageGroups = await fetchUpvoteMessages({
3632
+ netClient,
3633
+ messageScanWindow
3634
+ });
3635
+ const storageBlobByKey = await fetchStrategyStorage({
3636
+ publicClient,
3637
+ messageGroups
3638
+ });
3639
+ const wethAddress = getWethAddress(chainId);
3640
+ const { tokenAddresses, latestUpvoteTimestamps } = aggregateAndRank({
3641
+ messageGroups,
3642
+ storageBlobByKey,
3643
+ sort,
3644
+ maxTokens,
3645
+ excludeAddresses: [wethAddress.toLowerCase()],
3646
+ nowSec
3647
+ });
3648
+ if (tokenAddresses.length === 0) return [];
3649
+ const usdcAddress = USDC_ADDRESS_BY_CHAIN[chainId];
3650
+ const pairs = [
3651
+ ...tokenAddresses.map((tokenAddress) => ({
3652
+ tokenAddress,
3653
+ baseTokenAddress: wethAddress
3654
+ })),
3655
+ ...usdcAddress ? [{ tokenAddress: wethAddress, baseTokenAddress: usdcAddress }] : []
3656
+ ];
3657
+ const [tokenInfos, pools, upvoteCounts] = await Promise.all([
3658
+ fetchBulkErc20Info({ publicClient, addresses: tokenAddresses }),
3659
+ discoverPools({ publicClient, pairs, chainId }),
3660
+ fetchAggregateUpvotes({ publicClient, tokenAddresses })
3661
+ ]);
3662
+ if (tokenInfos.length !== tokenAddresses.length) {
3663
+ throw new Error(
3664
+ `ERC20 bulk info returned ${tokenInfos.length} entries for ${tokenAddresses.length} addresses`
3665
+ );
3666
+ }
3667
+ if (upvoteCounts.length !== tokenAddresses.length) {
3668
+ throw new Error(
3669
+ `getUpvotesWithLegacy returned ${upvoteCounts.length} entries for ${tokenAddresses.length} addresses`
3670
+ );
3671
+ }
3672
+ return composeAndFilter({
3673
+ tokenAddresses,
3674
+ tokenInfos,
3675
+ pools,
3676
+ upvoteCounts,
3677
+ latestUpvoteTimestamps,
3678
+ wethAddress,
3679
+ usdcAddress,
3680
+ sort,
3681
+ maxTokens,
3682
+ minUpvotes,
3683
+ minMarketCap,
3684
+ recencyHours,
3685
+ nowSec
3686
+ });
3687
+ }
3688
+ function validateChainSupported(chainId) {
3689
+ if (!SUPPORTED_SCORE_CHAINS.includes(chainId)) {
3690
+ throw new Error(
3691
+ `getTokenRankings: chainId ${chainId} is not supported. Supported chains: ${SUPPORTED_SCORE_CHAINS.join(", ")}`
3692
+ );
3693
+ }
3694
+ }
3695
+ async function fetchUpvoteMessages({
3696
+ netClient,
3697
+ messageScanWindow
3698
+ }) {
3699
+ const legacyFilter = {
3700
+ appAddress: LEGACY_UPVOTE_V1_ADDRESS,
3701
+ topic: "t"
3702
+ };
3703
+ const strategyFilters = [
3704
+ UNIV234_POOLS_STRATEGY.address,
3705
+ PURE_ALPHA_STRATEGY.address,
3706
+ DYNAMIC_SPLIT_STRATEGY.address
3707
+ ].map((stratAddr) => ({
3708
+ appAddress: SCORE_CONTRACT.address,
3709
+ topic: `t${stratAddr.toLowerCase()}`
3710
+ }));
3711
+ const [legacyCount, ...strategyCounts] = await Promise.all([
3712
+ netClient.getMessageCount({ filter: legacyFilter }),
3713
+ ...strategyFilters.map((filter) => netClient.getMessageCount({ filter }))
3714
+ ]);
3715
+ const sliceRange = (count) => ({
3716
+ startIndex: Math.max(0, count - messageScanWindow),
3717
+ endIndex: count
3718
+ });
3719
+ const [legacy, strategy1, strategy2, strategy3] = await Promise.all([
3720
+ legacyCount > 0 ? netClient.getMessagesBatch({
3721
+ filter: legacyFilter,
3722
+ ...sliceRange(legacyCount)
3723
+ }) : Promise.resolve([]),
3724
+ ...strategyFilters.map(
3725
+ (filter, i) => strategyCounts[i] > 0 ? netClient.getMessagesBatch({
3726
+ filter,
3727
+ ...sliceRange(strategyCounts[i])
3728
+ }) : Promise.resolve([])
3729
+ )
3730
+ ]);
3731
+ return { legacy, strategy1, strategy2, strategy3 };
3732
+ }
3733
+ async function fetchStrategyStorage({
3734
+ publicClient,
3735
+ messageGroups
3736
+ }) {
3737
+ const seen = /* @__PURE__ */ new Set();
3738
+ const keys = [];
3739
+ for (const msg of [
3740
+ ...messageGroups.strategy1,
3741
+ ...messageGroups.strategy2,
3742
+ ...messageGroups.strategy3
3743
+ ]) {
3744
+ if (!msg.data || !msg.data.startsWith("0x")) continue;
3745
+ const key = msg.data;
3746
+ if (seen.has(key)) continue;
3747
+ seen.add(key);
3748
+ keys.push({ key, operator: SCORE_CONTRACT.address });
3749
+ }
3750
+ if (keys.length === 0) return /* @__PURE__ */ new Map();
3751
+ const results = await readContract(publicClient, {
3752
+ address: STORAGE_CONTRACT.address,
3753
+ abi: STORAGE_CONTRACT.abi,
3754
+ functionName: "bulkGet",
3755
+ args: [keys]
3756
+ });
3757
+ return buildStorageMapFromBulkGetResults(results, keys);
3758
+ }
3759
+ function buildStorageMapFromBulkGetResults(results, keys) {
3760
+ if (results.length !== keys.length) {
3761
+ throw new Error(
3762
+ `bulkGet returned ${results.length} entries for ${keys.length} keys`
3763
+ );
3764
+ }
3765
+ const map = /* @__PURE__ */ new Map();
3766
+ results.forEach((item, idx) => {
3767
+ const value = item?.value;
3768
+ if (value && value !== "0x") {
3769
+ map.set(keys[idx].key, value);
3770
+ }
3771
+ });
3772
+ return map;
3773
+ }
3774
+ function aggregateAndRank({
3775
+ messageGroups,
3776
+ storageBlobByKey,
3777
+ sort,
3778
+ maxTokens,
3779
+ excludeAddresses = [],
3780
+ nowSec
3781
+ }) {
3782
+ const tokenUpvoteEvents = /* @__PURE__ */ new Map();
3783
+ const excludeSet = new Set(excludeAddresses.map((a) => a.toLowerCase()));
3784
+ const addEvent = (tokenAddress, timestamp, count) => {
3785
+ if (!ADDRESS_RE.test(tokenAddress)) return;
3786
+ const lower = tokenAddress.toLowerCase();
3787
+ if (lower === NULL_ADDRESS || excludeSet.has(lower)) return;
3788
+ if (!Number.isFinite(timestamp) || !Number.isFinite(count)) return;
3789
+ const events = tokenUpvoteEvents.get(lower) ?? [];
3790
+ events.push({ timestamp, count });
3791
+ tokenUpvoteEvents.set(lower, events);
3792
+ };
3793
+ for (const msg of messageGroups.legacy) {
3794
+ if (msg.topic !== "t" || !msg.text) continue;
3795
+ let count = 1;
3796
+ if (msg.data && msg.data.startsWith("0x")) {
3797
+ try {
3798
+ const [votes] = decodeAbiParameters(
3799
+ [{ type: "uint256" }],
3800
+ msg.data
3801
+ );
3802
+ count = Number(votes);
3803
+ } catch {
3804
+ count = 1;
3805
+ }
3806
+ }
3807
+ addEvent(msg.text, Number(msg.timestamp), count);
3808
+ }
3809
+ for (const msg of [
3810
+ ...messageGroups.strategy1,
3811
+ ...messageGroups.strategy2,
3812
+ ...messageGroups.strategy3
3813
+ ]) {
3814
+ if (!msg.topic.startsWith("t") || !msg.data || !msg.data.startsWith("0x")) {
3815
+ continue;
3816
+ }
3817
+ const blob = storageBlobByKey.get(msg.data);
3818
+ if (!blob) continue;
3819
+ const decoded = decodeUpvoteStorageBlob(blob);
3820
+ if (!decoded || !decoded.scoreKey) continue;
3821
+ const tokenAddress = extractTokenAddressFromScoreKey(decoded.scoreKey);
3822
+ if (!tokenAddress) continue;
3823
+ addEvent(tokenAddress, Number(msg.timestamp), decoded.scoreDelta);
3824
+ }
3825
+ const timeWeight = (ts) => Math.exp(-0.1 * ((nowSec - ts) / 3600));
3826
+ const latestUpvoteTimestamps = /* @__PURE__ */ new Map();
3827
+ for (const [addr, events] of tokenUpvoteEvents) {
3828
+ let latest = events[0].timestamp;
3829
+ for (const e of events) if (e.timestamp > latest) latest = e.timestamp;
3830
+ latestUpvoteTimestamps.set(addr, latest);
3831
+ }
3832
+ let ordered;
3833
+ if (sort === "top") {
3834
+ ordered = Array.from(tokenUpvoteEvents.keys());
3835
+ } else {
3836
+ const scores = /* @__PURE__ */ new Map();
3837
+ for (const [addr, events] of tokenUpvoteEvents) {
3838
+ if (sort === "recent") {
3839
+ scores.set(addr, latestUpvoteTimestamps.get(addr) ?? 0);
3840
+ } else {
3841
+ const score = events.reduce(
3842
+ (total, e) => total + e.count * timeWeight(e.timestamp),
3843
+ 0
3844
+ );
3845
+ scores.set(addr, score);
3846
+ }
3847
+ }
3848
+ ordered = Array.from(scores.entries()).sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([address]) => address);
3849
+ }
3850
+ const fetchLimit = Math.max(maxTokens * 3, 30);
3851
+ return {
3852
+ tokenAddresses: ordered.slice(0, fetchLimit),
3853
+ latestUpvoteTimestamps
3854
+ };
3855
+ }
3856
+ async function fetchBulkErc20Info({
3857
+ publicClient,
3858
+ addresses
3859
+ }) {
3860
+ if (addresses.length === 0) return [];
3861
+ try {
3862
+ const data = await readContract(publicClient, {
3863
+ address: ERC20_BULK_INFO_HELPER_CONTRACT.address,
3864
+ abi: ERC20_BULK_INFO_HELPER_CONTRACT.abi,
3865
+ functionName: "getTokenInfo",
3866
+ args: [addresses]
3867
+ });
3868
+ if (Array.isArray(data) && data.length === addresses.length) return data;
3869
+ } catch {
3870
+ }
3871
+ const results = await Promise.all(
3872
+ addresses.map(async (addr) => {
3873
+ try {
3874
+ const data = await readContract(publicClient, {
3875
+ address: ERC20_BULK_INFO_HELPER_CONTRACT.address,
3876
+ abi: ERC20_BULK_INFO_HELPER_CONTRACT.abi,
3877
+ functionName: "getTokenInfo",
3878
+ args: [[addr]]
3879
+ });
3880
+ if (Array.isArray(data) && data[0]) return data[0];
3881
+ } catch {
3882
+ }
3883
+ return {
3884
+ name: "",
3885
+ symbol: "",
3886
+ decimals: 0,
3887
+ totalSupply: 0n,
3888
+ burnedTokens: 0n
3889
+ };
3890
+ })
3891
+ );
3892
+ return results;
3893
+ }
3894
+ async function fetchAggregateUpvotes({
3895
+ publicClient,
3896
+ tokenAddresses
3897
+ }) {
3898
+ if (tokenAddresses.length === 0) return [];
3899
+ const data = await readContract(publicClient, {
3900
+ address: UPVOTE_APP.address,
3901
+ abi: UPVOTE_APP.abi,
3902
+ functionName: "getUpvotesWithLegacy",
3903
+ args: [
3904
+ tokenAddresses.map((addr) => encodeUpvoteKey(addr)),
3905
+ ALL_STRATEGY_ADDRESSES
3906
+ ]
3907
+ });
3908
+ if (!Array.isArray(data)) {
3909
+ throw new Error(
3910
+ "getUpvotesWithLegacy returned non-array; contract or RPC misbehaving"
3911
+ );
3912
+ }
3913
+ return data.map(Number);
3914
+ }
3915
+ function composeAndFilter({
3916
+ tokenAddresses,
3917
+ tokenInfos,
3918
+ pools,
3919
+ upvoteCounts,
3920
+ latestUpvoteTimestamps,
3921
+ wethAddress,
3922
+ usdcAddress,
3923
+ sort,
3924
+ maxTokens,
3925
+ minUpvotes,
3926
+ minMarketCap,
3927
+ recencyHours,
3928
+ nowSec
3929
+ }) {
3930
+ const wethLower = wethAddress.toLowerCase();
3931
+ const usdcLower = usdcAddress?.toLowerCase();
3932
+ let ethPriceInUsdc;
3933
+ if (usdcLower) {
3934
+ const wethUsdcPool = pools.find(
3935
+ (p) => p.tokenAddress.toLowerCase() === wethLower && p.baseTokenAddress.toLowerCase() === usdcLower
3936
+ );
3937
+ const usdcWethPool = pools.find(
3938
+ (p) => p.tokenAddress.toLowerCase() === usdcLower && p.baseTokenAddress.toLowerCase() === wethLower
3939
+ );
3940
+ if (wethUsdcPool?.price) {
3941
+ ethPriceInUsdc = wethUsdcPool.price;
3942
+ } else if (usdcWethPool?.price) {
3943
+ ethPriceInUsdc = 1 / usdcWethPool.price;
3944
+ }
3945
+ }
3946
+ const tokenAddressToPool = /* @__PURE__ */ new Map();
3947
+ for (const pool of pools) {
3948
+ if (pool.baseTokenAddress.toLowerCase() === wethLower) {
3949
+ tokenAddressToPool.set(pool.tokenAddress.toLowerCase(), pool);
3950
+ }
3951
+ }
3952
+ const composed = tokenAddresses.map((address, i) => {
3953
+ const info = tokenInfos[i];
3954
+ const pool = tokenAddressToPool.get(address.toLowerCase());
3955
+ const priceInUsdc = pool?.price && ethPriceInUsdc ? pool.price * ethPriceInUsdc : void 0;
3956
+ let circulating;
3957
+ if (info?.totalSupply) {
3958
+ const burned = info.burnedTokens ?? 0n;
3959
+ const c = info.totalSupply - burned;
3960
+ circulating = c > 0n ? c : 0n;
3961
+ }
3962
+ const decimals = info?.decimals || void 0;
3963
+ const fdv = circulating != null && decimals != null && priceInUsdc != null ? Number(circulating) / 10 ** decimals * priceInUsdc : void 0;
3964
+ return {
3965
+ address,
3966
+ name: info?.name || void 0,
3967
+ symbol: info?.symbol || void 0,
3968
+ decimals,
3969
+ fdv,
3970
+ priceInUsdc,
3971
+ upvotes: upvoteCounts[i] ?? 0,
3972
+ latestUpvoteTimestamp: latestUpvoteTimestamps.get(address.toLowerCase()) ?? 0
3973
+ };
3974
+ });
3975
+ const valid = composed.filter((t) => {
3976
+ if (!t.name?.trim() || !t.symbol?.trim()) return false;
3977
+ const belowFloor = t.fdv == null || t.fdv < minMarketCap;
3978
+ if (belowFloor) {
3979
+ const hoursSince = (nowSec - t.latestUpvoteTimestamp) / 3600;
3980
+ if (hoursSince > recencyHours) return false;
3981
+ }
3982
+ return true;
3983
+ });
3984
+ let sorted;
3985
+ if (sort === "top") {
3986
+ sorted = [...valid].sort((a, b) => b.upvotes - a.upvotes);
3987
+ } else {
3988
+ const byAddr = new Map(valid.map((t) => [t.address.toLowerCase(), t]));
3989
+ sorted = tokenAddresses.map((addr) => byAddr.get(addr.toLowerCase())).filter((t) => t != null);
3990
+ }
3991
+ const qualifies = (t) => t.upvotes >= minUpvotes || t.fdv != null && t.fdv >= minMarketCap;
3992
+ const top = sorted.filter(qualifies);
3993
+ const rest = sorted.filter((t) => !qualifies(t));
3994
+ return [...top, ...rest].slice(0, maxTokens);
3995
+ }
3996
+ var encodePoolKey = (poolKey) => {
3997
+ if (!poolKey || !isValidPoolKey2(poolKey)) {
3998
+ return "0x";
3999
+ }
4000
+ try {
4001
+ return encodeAbiParameters(
4002
+ [
4003
+ {
4004
+ type: "tuple",
4005
+ components: [
4006
+ { name: "currency0", type: "address" },
4007
+ { name: "currency1", type: "address" },
4008
+ { name: "fee", type: "uint24" },
4009
+ { name: "tickSpacing", type: "int24" },
4010
+ { name: "hooks", type: "address" }
4011
+ ]
4012
+ }
4013
+ ],
4014
+ [
4015
+ {
4016
+ currency0: poolKey.currency0,
4017
+ currency1: poolKey.currency1,
4018
+ fee: poolKey.fee,
4019
+ tickSpacing: poolKey.tickSpacing,
4020
+ hooks: poolKey.hooks
4021
+ }
4022
+ ]
4023
+ );
4024
+ } catch {
4025
+ return "0x";
4026
+ }
4027
+ };
4028
+ function isValidPoolKey2(poolKey) {
4029
+ return poolKey.fee !== void 0 || poolKey.tickSpacing !== void 0 || poolKey.currency0 !== void 0;
4030
+ }
4031
+
4032
+ export { ALL_STRATEGY_ADDRESSES, DYNAMIC_SPLIT_STRATEGY, ERC20_BULK_INFO_HELPER_CONTRACT, LEGACY_UPVOTE_V1_ADDRESS, LEGACY_UPVOTE_V2_ADDRESS, MULTI_VERSION_UNISWAP_BULK_POOL_FINDER, MULTI_VERSION_UNISWAP_POOL_INFO_RETRIEVER, NULL_ADDRESS, PURE_ALPHA_STRATEGY, SCORE_CONTRACT, SUPPORTED_SCORE_CHAINS, ScoreClient, UNIV234_POOLS_STRATEGY, UPVOTE_APP, UPVOTE_PRICE_ETH, UPVOTE_STORAGE_APP, USER_UPVOTE_CONTRACT, UserUpvoteClient, buildUserUpvote, buildUserUpvoteReceived, calculatePriceFromSqrtPriceX96, calculatePriceInUsdc, calculateUpvoteCost, calculateUserTokenBalance, decodeStrategyMetadata, decodeUpvoteMessage, decodeUpvoteStorageBlob, discoverPools, discoverTokenPool, encodePoolKey, encodeUpvoteKey, extractStrategyAddress, extractTokenAddressFromScoreKey, extractTokenAddressesFromMessages, getFeedContentKey, getScoreKey, getStorageScoreKey, getStorageUpvoteContext, getTokenRankings, getTokenScoreKey, getWethAddress, isDynamicSplitStrategy, isPureAlphaStrategy, isStrategyMessage, isTokenScoreKey, isUniv234PoolsStrategy, isUserUpvoteMessage, parseUserUpvoteMessage, selectStrategy, tokenAddressToUpvoteKeyString, validateUpvoteParams, validateUserUpvoteMessage };
3599
4033
  //# sourceMappingURL=index.mjs.map
3600
4034
  //# sourceMappingURL=index.mjs.map