如何提升从Solana Raydium获取PoolKeys的速度?
优化Raydium PoolKeys查询效率的方案
你的问题核心在于每次调用getPoolKeys都重新拉取整个大体积的流动性JSON文件,再做O(n)的遍历查找,这会导致重复请求和低效匹配。以下是几个关键优化方向:
1. 全局缓存流动性数据
避免每次查询都重新请求API,把数据缓存到内存(或持久化存储)中,仅在首次调用或缓存过期时重新加载。
2. 预构建哈希索引
将所有代币对映射为唯一键,把查找复杂度从O(n)降到O(1)。由于代币对是无序的(A-B和B-A是同一个池),可以通过排序代币地址生成统一键。
优化后的代码实现
// 全局缓存:存储流动性数据和预构建的索引 let liquidityCache = null; let tokenPairPoolMap = null; // 预加载流动性数据并构建索引 const initLiquidityData = async () => { if (liquidityCache) return; // 已缓存则直接返回 const resp = await fetch('https://api.raydium.io/v2/sdk/liquidity/mainnet.json'); if (!resp.ok) { console.error('加载流动性数据失败'); return; } liquidityCache = await resp.json(); // 构建代币对到Pool的映射索引 tokenPairPoolMap = new Map(); const allPools = [...(liquidityCache.official ?? []), ...(liquidityCache.unOfficial ?? [])]; allPools.forEach(pool => { // 对两个代币地址排序,生成统一的键(避免A-B和B-A视为不同键) const sortedMints = [pool.baseMint, pool.quoteMint].sort(); const pairKey = `${sortedMints[0]}|${sortedMints[1]}`; // 若同一代币对存在多个池,可根据需求选择(比如保留TVL最高的,这里默认取第一个) if (!tokenPairPoolMap.has(pairKey)) { tokenPairPoolMap.set(pairKey, pool); } }); }; // 优化后的PoolKeys查询函数 const getPoolKeys = async (tokenA, tokenB) => { // 确保数据已初始化 await initLiquidityData(); if (!tokenPairPoolMap) return null; // 生成统一查询键 const sortedMints = [tokenA, tokenB].sort(); const pairKey = `${sortedMints[0]}|${sortedMints[1]}`; const poolData = tokenPairPoolMap.get(pairKey); return poolData ? jsonInfo2PoolKeys(poolData) : null; };
额外优化建议
- 缓存过期机制:如果担心数据过时,可以添加缓存过期逻辑,比如每隔2小时重新调用
initLiquidityData刷新缓存。 - 前端持久化缓存:在浏览器环境中,可以用
localStorage存储序列化后的liquidityCache和tokenPairPoolMap,页面刷新后无需重新请求API。 - 错误重试:给
fetch添加重试逻辑,避免单次请求失败导致功能不可用。
内容的提问来源于stack exchange,提问作者Shahria Emon
相关产品推荐
相关产品推荐

