@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.d.mts +107 -28
- package/dist/index.d.ts +107 -28
- package/dist/index.js +471 -35
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +472 -38
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js.map +1 -1
- package/dist/react.mjs.map +1 -1
- package/dist/{scoreKeyUtils-BjMpyhyX.d.mts → scoreKeyUtils-BQl5oCSc.d.mts} +1 -1
- package/dist/{scoreKeyUtils-BjMpyhyX.d.ts → scoreKeyUtils-BQl5oCSc.d.ts} +1 -1
- package/package.json +2 -2
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;
|