This repository was archived by the owner on Apr 26, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathIndexTopChainsResource.ts
More file actions
161 lines (145 loc) · 6.02 KB
/
IndexTopChainsResource.ts
File metadata and controls
161 lines (145 loc) · 6.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import { sql, gt } from "drizzle-orm";
import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
import * as JsinfoProviderAgrSchema from '@jsinfo/schemas/jsinfoSchema/providerRelayPaymentsAgregation';
import { RedisResourceBase } from '@jsinfo/redis/classes/RedisResourceBase';
import { queryJsinfo } from '@jsinfo/utils/db';
export interface IndexTopChainsData {
allSpecs: {
chainId: string;
relaySum30Days: number;
cuSum30Days: number;
relaySum: number;
cuSum: number;
}[];
}
export class IndexTopChainsResource extends RedisResourceBase<IndexTopChainsData, {}> {
protected readonly redisKey = 'index:top:chains';
protected readonly cacheExpirySeconds = 600; // 10 minutes cache
protected async fetchFromSource(): Promise<IndexTopChainsData> {
// Get 30 days stats
const thirtyDaysStats = await queryJsinfo(
async (db: PostgresJsDatabase) => db.select({
chainId: JsinfoProviderAgrSchema.aggDailyRelayPayments.specId,
relaySum: sql<number>`SUM(${JsinfoProviderAgrSchema.aggDailyRelayPayments.relaySum})`,
cuSum: sql<number>`SUM(${JsinfoProviderAgrSchema.aggDailyRelayPayments.cuSum})`,
})
.from(JsinfoProviderAgrSchema.aggDailyRelayPayments)
.where(gt(JsinfoProviderAgrSchema.aggDailyRelayPayments.dateday, sql<Date>`now() - interval '30 day'`))
.groupBy(JsinfoProviderAgrSchema.aggDailyRelayPayments.specId),
'IndexTopChainsResource_fetchFromSource_30days'
);
console.log("thirtyDaysStats",thirtyDaysStats);
// Get all time stats
const allTimeStats = await queryJsinfo(
async (db: PostgresJsDatabase) => db.select({
chainId: JsinfoProviderAgrSchema.aggDailyRelayPayments.specId,
relaySum: sql<number>`SUM(${JsinfoProviderAgrSchema.aggDailyRelayPayments.relaySum})`,
cuSum: sql<number>`SUM(${JsinfoProviderAgrSchema.aggDailyRelayPayments.cuSum})`,
})
.from(JsinfoProviderAgrSchema.aggDailyRelayPayments)
.groupBy(JsinfoProviderAgrSchema.aggDailyRelayPayments.specId),
'IndexTopChainsResource_fetchFromSource_alltime'
);
// Combine results
const statsMap = new Map<string, {
chainId: string;
relaySum30Days: number;
cuSum30Days: number;
relaySum: number;
cuSum: number;
}>();
// add here custom logic to remove these chains:
const mainnetChains = [
"FVM",
"FVMT",
"STRK",
"STRKS",
"AXELAR",
"AXELART",
"ARBITRUM",
"ARBITRUMS",
"MOVEMENT",
"MOVEMENTT",
"NEAR",
"NEART",
"COSMOSHUB",
"COSMOSHUBT",
"LAVA",
"ETH1",
"Sep1",
"HOL1",
"BASE",
"BASES",
"OPTM",
"OPTMS",
"BSC",
"BSCT",
"POLYGON",
"POLYGONA",
"SOLANA",
"SOLANAT",
"HYPERLIQUID",
"HYPERLIQUIDT",
"HEDERA",
"HEDERAT",
"XLM",
"XLMT",
"SONIC",
"UNION",
"UNIONT",
"BTC",
"BTCT",
"BCH",
"BCHT",
"AVAX",
"AVAXT"
].map(chain => chain.toLowerCase().trim());
const testnetChains = [
"LAV1",
"APT1",
"ETH1",
"SOLANA",
"NEAR"
].map(chain => chain.toLowerCase().trim());
// Initialize with 30-day stats instead of all-time stats
const filteredStats = thirtyDaysStats
.filter((stat): stat is { chainId: string; relaySum: number; cuSum: number; } =>
stat.chainId !== null && (mainnetChains.includes(stat.chainId.toLowerCase().trim()) || testnetChains.includes(stat.chainId.toLowerCase().trim())));
// Log what got filtered out
const allChainIds = thirtyDaysStats
.filter((stat): stat is { chainId: string; relaySum: number; cuSum: number; } => stat.chainId !== null)
.map(stat => stat.chainId);
const filteredOutChains = allChainIds.filter(chainId =>
!mainnetChains.includes(chainId.toLowerCase().trim()) && !testnetChains.includes(chainId.toLowerCase().trim())
);
// // Debug: Check if hedera is in the raw data
// const hederaInRawData = allChainIds.some(chainId => chainId.toLowerCase() === 'hedera');
// console.log(`IndexTopChainsResource: HEDERA in raw 30-day data: ${hederaInRawData}`);
// console.log(`IndexTopChainsResource: All chain IDs from 30-day query: ${allChainIds.join(', ')}`);
if (filteredOutChains.length > 0) {
console.log(`IndexTopChainsResource: Filtered out chains: ${filteredOutChains.join(', ')}`);
}
filteredStats.forEach(stat => {
statsMap.set(stat.chainId, {
chainId: stat.chainId,
relaySum30Days: Number(stat.relaySum) || 0,
cuSum30Days: Number(stat.cuSum) || 0,
relaySum: 0, // Will be updated with all-time stats
cuSum: 0
});
});
// Add all-time stats only for chains that exist in 30-day window
allTimeStats
.filter((stat): stat is { chainId: string; relaySum: number; cuSum: number; } =>
stat.chainId !== null && statsMap.has(stat.chainId))
.forEach(stat => {
const existing = statsMap.get(stat.chainId)!;
existing.relaySum = Number(stat.relaySum) || 0;
existing.cuSum = Number(stat.cuSum) || 0;
});
return {
allSpecs: Array.from(statsMap.values())
.sort((a, b) => b.relaySum30Days - a.relaySum30Days) // Sort by 30-day relays
};
}
}