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