Electron(Node.js 18)应用中Casper(CSPR)余额查询端点测试失败的问题排查及可靠方案咨询
问题描述
我正在构建一个Electron应用(Node.js 18)来查询加密货币余额,其中包括Casper(CSPR)。但在尝试查询CSPR余额时,一直收到**"No working endpoints found"**错误。
错误信息
Testing available endpoints... Testing endpoint: https://rpc.mainnet.casperlabs.io Testing endpoint: https://casper-node.services.dev.z7x.org // ... more endpoints ... Endpoint https://casper-node.services.dev.z7x.org failed: getaddrinfo ENOTFOUND Found 0 working endpoints CSPR balance check failed: Error: No working endpoints found
相关代码
端点测试函数
async function testEndpoint(url) { try { console.log(`Testing endpoint: ${url}`); const response = await axios.post(`${url}/rpc`, { jsonrpc: "2.0", id: "0", method: "info_get_status", params: [] }, { timeout: 10000, headers: { 'Content-Type': 'application/json' }, validateStatus: status => status < 500, httpsAgent: new require('https').Agent({ rejectUnauthorized: false, timeout: 10000 }) }); if (response.data && !response.data.error) { console.log(`Endpoint ${url} is working`); return true; } console.log(`Endpoint ${url} returned invalid data:`, response.data); return false; } catch (error) { console.log(`Endpoint ${url} failed:`, error.message); return false; } }
余额查询函数
async function getCSPRBalance(key) { try { const formattedKey = normalizePublicKey(key); const endpoints = Array.isArray(config.casper.apiUrl) ? config.casper.apiUrl : [config.casper.apiUrl]; // Test endpoints in parallel const endpointTests = endpoints.map(endpoint => testEndpoint(endpoint)); const results = await Promise.allSettled(endpointTests); const workingEndpoints = endpoints.filter((endpoint, index) => results[index].status === 'fulfilled' && results[index].value === true ); if (workingEndpoints.length === 0) { throw new Error('No working endpoints found'); } // Try each working endpoint for (const baseUrl of workingEndpoints) { try { const url = `${baseUrl}/rpc`; const rpcKey = `01${formattedKey}`; const accountResponse = await axios.post(url, { jsonrpc: "2.0", id: "1", method: "state_get_account_info", params: { public_key: rpcKey } }); // ... rest of balance checking logic ... } catch (endpointError) { // Continue to next endpoint } } } catch (error) { return { success: false, error: error.message || 'Failed to check CSPR balance', address: key }; } }
使用的端点列表
const endpoints = [ 'https://rpc.mainnet.casperlabs.io', 'https://casper-node.services.dev.z7x.org', 'https://casper-proxy.liquidstaking.com', 'https://casper-node-proxy.dev.z7x.org', 'https://node.casper.network.dev.z7x.org' ];
已尝试的解决方法
- 使用不同的Casper RPC端点
- 添加SSL/TLS错误处理
- 实现超时和重试机制
- 为测试禁用SSL验证
测试用公钥
0203d9f49b0d76a3f14482ab11926f0d5f792e933f3df824dc1e0b07104474c4c3b3
核心问题
- 有没有更可靠的Casper RPC端点可以使用?
- 我的端点测试方法是否存在问题?
- 从Electron应用向Casper节点发起RPC调用有什么需要特别注意的地方?
环境
- Electron
- Node.js 18
- axios 用于HTTP请求
- casper-js-sdk 用于密钥处理
问题排查与解决方案
一、更可靠的Casper主网RPC端点
给你几个目前验证过的稳定主网端点,优先推荐官方维护的:
https://mainnet.casperlabs.io(官方主节点,稳定性最高)https://api.casperholders.com(社区维护的高可用端点)https://casper-mainnet.public.blastapi.io(第三方提供的分布式节点)https://rpc.casper.network(官方备用节点)
建议把官方端点放在列表最前面,社区端点作为备用。
二、你的端点测试方法的潜在问题
路径拼接的兼容性问题
你给每个端点都拼接了/rpc路径,但有些官方端点本身已经包含/rpc后缀(比如https://mainnet.casperlabs.io/rpc),会导致拼接后变成xxx/rpc/rpc,触发404错误。
建议统一端点格式:要么都使用不带/rpc的基础URL,要么在测试前自动处理路径:let rpcUrl = new URL(url); if (!rpcUrl.pathname.endsWith('/rpc')) { rpcUrl.pathname = rpcUrl.pathname.replace(/\/?$/, '/rpc'); } const fullRpcUrl = rpcUrl.toString();Promise.allSettled的逻辑优化
你的过滤逻辑没问题,但可以简化为直接判断result.value(因为testEndpoint返回的是布尔值):const workingEndpoints = endpoints.filter((endpoint, index) => { const result = results[index]; return result.status === 'fulfilled' && result.value; });SSL验证的风险与必要性
测试时禁用rejectUnauthorized可以临时解决证书问题,但生产环境绝对不建议这么做——这会让请求暴露在中间人攻击的风险下。如果遇到证书错误,优先更换端点,而不是禁用验证。重复超时设置的冗余
你同时在axios配置和httpsAgent里设置了timeout,axios的全局timeout已经足够覆盖请求周期,不需要在Agent里重复设置,避免逻辑混乱。
三、Electron应用调用Casper RPC的特殊注意事项
网络权限配置
在Electron的package.json里确保配置了正确的网络权限:"permissions": ["network", "https://*/*"]另外,如果启用了
contextIsolation(Electron 12+默认开启),建议把RPC请求放在主进程中处理,通过IPC和渲染进程通信——渲染进程直接发起请求可能会遇到CORS或权限问题。系统代理的干扰
Electron会自动继承系统代理设置,如果用户的代理配置有问题,会导致端点连接失败。可以在axios中显式跳过代理:{ proxy: false }Electron网络栈的差异
Electron的网络栈和Node.js原生有细微差异,比如证书验证逻辑。如果在主进程中请求正常,渲染进程中异常,大概率是CORS或权限问题,建议统一把网络请求放在主进程。
四、优化后的端点测试函数示例
const https = require('https'); const axios = require('axios'); async function testEndpoint(url, retryCount = 1) { try { // 统一处理RPC路径 let rpcUrl = new URL(url); if (!rpcUrl.pathname.endsWith('/rpc')) { rpcUrl.pathname = rpcUrl.pathname.replace(/\/?$/, '/rpc'); } const fullRpcUrl = rpcUrl.toString(); console.log(`Testing endpoint: ${fullRpcUrl}`); const response = await axios.post(fullRpcUrl, { jsonrpc: "2.0", id: "0", method: "info_get_status", params: [] }, { timeout: 10000, headers: { 'Content-Type': 'application/json' }, validateStatus: status => status < 500, proxy: false, httpsAgent: new https.Agent({ rejectUnauthorized: true, // 生产环境启用 timeout: 10000 }) }); // 严格验证RPC响应格式 if (response.data?.jsonrpc === "2.0" && !response.data.error) { console.log(`Endpoint ${url} is working`); return true; } console.log(`Endpoint ${url} returned invalid data:`, response.data); return false; } catch (error) { console.log(`Endpoint ${url} failed:`, error.message); // 临时错误重试(超时、DNS解析失败) if ((error.code === 'ETIMEDOUT' || error.code === 'ENOTFOUND') && retryCount > 0) { console.log(`Retrying endpoint: ${url}`); return await testEndpoint(url, retryCount - 1); } return false; } }
五、额外建议
- 添加端点优先级:把官方稳定端点放在列表最前面,优先测试
- 缓存工作端点:如果某个端点测试通过,缓存下来,下次启动直接使用,减少重复测试
- 完善日志:记录每个端点的测试耗时、错误类型,方便后续排查
备注:内容来源于stack exchange,提问作者Jintor




