- 网络检测错误:BSC 地址被错误识别为 Ethereum
- API 调用失败:GeckoTerminal API 返回 404 错误
- 搜索结果不显示:即使获取到数据也无法在 UI 中显示
BSC 和 Ethereum 都使用相同的地址格式 0x[a-fA-F0-9]{40},无法通过地址格式直接区分:
// 问题代码
function detectTokenNetwork(address: string): string | null {
for (const [networkKey, network] of Object.entries(SUPPORTED_NETWORKS)) {
if (network.address_pattern.test(address)) {
return networkKey; // 总是返回第一个匹配的(ethereum)
}
}
return null;
}- 某些代币在 GeckoTerminal 上可能没有数据
- API 端点可能不稳定
- 需要准确的网络识别
只依赖 GeckoTerminal API,没有备用方案。
function detectTokenNetwork(address: string): string | null {
// Solana 地址有独特的格式,可以直接识别
if (SUPPORTED_NETWORKS.solana.address_pattern.test(address)) {
return 'solana';
}
// EVM 地址格式相同,无法直接区分 BSC 和 Ethereum
// 返回 'evm' 表示需要进一步检测
if (/^0x[a-fA-F0-9]{40}$/.test(address)) {
return 'evm';
}
return null;
}async function getTokenFromDexScreener(tokenAddress: string): Promise<CryptoCurrency | null> {
try {
const url = `https://api.dexscreener.com/latest/dex/tokens/${tokenAddress}`;
const response = await fetch(url, {
headers: {
'Accept': 'application/json',
'User-Agent': 'CryptoTrack/1.0'
}
});
if (!response.ok) return null;
const data = await response.json();
if (!data.pairs || data.pairs.length === 0) return null;
// 选择流动性最高的交易对
const bestPair = data.pairs.reduce((best: any, current: any) => {
const bestLiquidity = parseFloat(best.liquidity?.usd || '0');
const currentLiquidity = parseFloat(current.liquidity?.usd || '0');
return currentLiquidity > bestLiquidity ? current : best;
});
// DexScreener 自动识别具体的链
const tokenInfo = bestPair.baseToken.address.toLowerCase() === tokenAddress.toLowerCase()
? bestPair.baseToken
: bestPair.quoteToken;
return {
id: `dex-${bestPair.chainId}-${tokenAddress.toLowerCase()}`,
symbol: tokenInfo.symbol?.toUpperCase() || 'UNKNOWN',
name: tokenInfo.name || tokenInfo.symbol?.toUpperCase() || 'Unknown Token',
current_price: parseFloat(bestPair.priceUsd) || 0,
price_change_percentage_24h: parseFloat(bestPair.priceChange?.h24) || 0,
market_cap: parseFloat(bestPair.marketCap) || 0,
total_volume: parseFloat(bestPair.volume?.h24) || 0,
// ... 其他字段
dexscreener_data: {
chainId: bestPair.chainId,
pairAddress: bestPair.pairAddress,
dexId: bestPair.dexId,
// ...
}
};
} catch (error) {
console.error('DexScreener API 调用失败:', error);
return null;
}
}// 新的搜索逻辑
if (detectedNetwork === 'evm') {
console.log(`🔍 检测到 EVM 代币地址: ${input}`);
// 1. 优先使用 DexScreener API(自动识别链)
const priceData = await getTokenFromDexScreener(input);
if (priceData) return priceData;
// 2. 备用方案:尝试 GeckoTerminal BSC
let geckoData = await getTokenPriceFromGeckoTerminal(input, 'bsc');
if (geckoData) return geckoData;
// 3. 最后尝试 GeckoTerminal Ethereum
geckoData = await getTokenPriceFromGeckoTerminal(input, 'ethereum');
if (geckoData) return geckoData;
}- 无需预先知道代币在哪条链上
- 返回数据中包含
chainId字段 - 支持多链查询
- 实时价格数据
- 24h 价格变化
- 流动性信息
- 交易量数据
- 市值信息
- 专业的 DEX 数据聚合器
- 稳定的 API 服务
- 广泛的代币覆盖
- 免费使用
- 无请求限制(合理使用)
- 第630-644行: 修改
detectTokenNetwork函数 - 第646-744行: 添加
getTokenFromDexScreener函数 - 第946-995行: 更新
searchAndGetTokenPrice函数逻辑
- 更新地址检测逻辑
- 添加 DexScreener API 测试
- 更新完整流程测试
- ASTER (BSC):
0x000ae314e2a2172a039b26378814c252734f556a - USDT (BSC):
0x55d398326f99059fF775485246999027B3197955 - USDC (Ethereum):
0xA0b86a33E6441b8C4505B8C4505B8C4505B8C4505
- ✅ 正确识别为 EVM 地址
- ✅ DexScreener API 返回正确的链信息
- ✅ 显示准确的代币数据
- ✅ 在搜索结果中正确显示
- 用户输入 → EVM 地址
- 地址检测 → 识别为
evm类型 - API 调用 → DexScreener API
- 链识别 → 自动识别为 BSC/Ethereum
- 数据获取 → 完整的代币信息
- 搜索显示 → 正确的链标识和代币信息
- ❌ BSC 地址被错误识别为 Ethereum
- ❌ GeckoTerminal API 调用失败
- ❌ 搜索结果不显示
- ✅ 自动识别正确的链(BSC/Ethereum)
- ✅ DexScreener API 稳定可用
- ✅ 搜索结果正确显示
- ✅ 支持多个数据源备用
- 缓存 DexScreener 响应
- 减少重复 API 调用
- 更友好的错误提示
- API 降级策略
- 并行 API 调用
- 请求去重
- 获取代币图标
- 更多时间段的价格数据
通过集成 DexScreener API,我们解决了:
- EVM 地址链识别问题
- API 可用性问题
- 数据完整性问题
现在用户可以:
- 输入任何 EVM 地址(BSC/Ethereum)
- 自动获取正确的链信息
- 看到完整的代币数据
- 享受稳定的搜索体验