摘要
Solana 提供了一套 JSON-RPC 接口,包含大量用于读取账户、提交交易和订阅实时更新的方法。你需要启用哪些方法取决于你的工作负载:钱包需要 blockhash 和 sendTransaction,索引器需要 getProgramAccounts 和 getSignaturesForAddress,而交易系统则依赖 WebSocket 订阅和优先费用估算。本参考将常见的 Solana RPC 方法映射到实际用例,展示请求示例,并解释影响生产架构的限制。它还涵盖了如何选择端点、何时共享公共 RPC 就足够,以及何时 OnFinality 的专用 Solana 节点更适合持续或高流量场景。
Solana 的 JSON-RPC API 是应用程序读取状态和提交交易的主要方式。与 EVM 链不同,EVM 链上少量方法就能覆盖大多数用例,而 Solana 暴露了更广泛的接口:账户查询、程序派生查找、blockhash 获取、交易模拟和 WebSocket 订阅。你调用的方法以及调用频率,决定了共享端点是否足够,还是需要专用基础设施。
从这里开始:将你的工作负载匹配到方法集
在优化任何东西之前,先确定你的应用属于哪一类。下表将常见的 Solana 工作负载映射到它们依赖的方法以及最重要的端点特性。
| 工作负载 | 核心方法 | 需要优先考虑的端点特性 |
|---|---|---|
| 钱包或 dapp 前端 | getLatestBlockhash, getBalance, sendTransaction, getSignatureStatuses | 低延迟 HTTP,可靠的交易转发 |
| 索引器或分析 | getProgramAccounts, getSignaturesForAddress, getTransaction | 高请求吞吐量,归档深度,稳定的分页 |
| 交易或机器人 | onAccountChange, onLogs, getRecentPrioritizationFees, sendTransaction | WebSocket 稳定性,低延迟,突发容量 |
| NFT 或代币工具 | getTokenAccountsByOwner, getAccountInfo, getProgramAccounts | 一致的响应时间,过滤支持 |
如果你的工作负载主要是读密集型且偶尔写入,像 OnFinality 的 Solana 公共端点这样的共享 RPC 端点可以覆盖早期开发。如果你运行持续的订阅、大规模的 getProgramAccounts 扫描或高交易量,专用节点可以消除吵闹邻居效应并提供可预测的容量。你可以查看 RPC 定价 和 支持的 RPC 网络 来比较选项。
读取账户和余额
最常见的 Solana RPC 方法用于检索账户状态。这些是带有 JSON 正文的 HTTP POST 调用。
curl https://solana.api.onfinality.io/public \
-X POST -H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getBalance",
"params": ["<PUBKEY>"]
}'
该组中的关键方法:
- getBalance 返回公钥的 lamport 余额。
- getAccountInfo 返回账户的数据、所有者、lamports 和可执行标志。
- getTokenAccountsByOwner 列出钱包的 SPL 代币账户,并可选按 mint 过滤。
- getProgramAccounts 返回程序拥有的所有账户。这很强大但开销大;始终使用过滤器(dataSize、memcmp)来缩小结果范围。
getProgramAccounts 是最容易触及提供商限制的方法。没有过滤器时,它可能扫描数百万个账户。如果你严重依赖它,请确认你的提供商支持你所需的规模,并考虑使用你可以控制配置的专用节点。
提交和跟踪交易
向 Solana 写入涉及一个特定序列:获取最近的 blockhash,构建并签名交易,发送它,然后确认它。
// 使用 fetch 针对 Solana RPC 端点的最小发送流程
const endpoint = "https://solana.api.onfinality.io/public";
async function rpc(method, params) {
const res = await fetch(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
});
return res.json();
}
const { result } = await rpc("getLatestBlockhash", [{ commitment: "confirmed" }]);
// 使用 result.value.blockhash 构建并签名交易
// 然后:
// await rpc("sendTransaction", [signedTxBase64, { encoding: "base64" }]);
需要了解的方法:
- getLatestBlockhash 返回一个 blockhash 及其有效窗口。Blockhash 会过期,因此在发送时间附近获取新的。
- sendTransaction 提交已签名的交易。谨慎设置
skipPreflight;预检会捕获许多错误但会增加延迟。 - simulateTransaction 在不提交的情况下运行交易,用于估算计算单元和捕获失败。
- getSignatureStatuses 和 getTransaction 让你确认交易是否落地。
- getRecentPrioritizationFees 帮助你在拥堵期间设置有竞争力的优先费用。
一个常见的陷阱是缓存 blockhash 太久。如果 blockhash 在交易落地前过期,网络会拒绝它。每次尝试都获取新的 blockhash,并使用退避重试。
WebSocket 订阅及其限制
Solana 支持 WebSocket 订阅以实现实时更新。OnFinality 的 Solana 端点在 wss://solana.api.onfinality.io/public-ws 暴露了 WebSocket 传输。
常见的订阅方法:
- accountSubscribe 监视单个账户的变化。
- logsSubscribe 流式传输程序或账户的日志。
- signatureSubscribe 在特定交易确认时通知。
- slotSubscribe 和 rootSubscribe 跟踪 slot 进展。
const ws = new WebSocket("wss://solana.api.onfinality.io/public-ws");
ws.onopen = () => {
ws.send(JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "logsSubscribe",
params: [{ mentions: ["<PROGRAM_ID>"] }, { commitment: "confirmed" }],
}));
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
// 处理日志通知
};
WebSocket 连接是有状态的,可能会断开。生产客户端应实现重连逻辑,在重连时重新订阅,并将流视为最终一致。如果你维护许多并发订阅,连接限制和服务器端空闲超时就会变得相关;这正是专用节点有帮助的地方,因为你不需要与其他租户共享订阅容量。
生产就绪检查清单
在将 Solana 集成移至生产环境之前,请使用此检查清单。
| 检查项 | 为什么重要 |
|---|---|
| Blockhash 新鲜度 | 过期的 blockhash 会导致发送失败 |
| 承诺级别 | processed 快但可能回滚;confirmed 和 finalized 以速度换安全 |
| 重试策略 | 网络拥堵和丢弃的交易需要幂等重试 |
| getProgramAccounts 过滤器 | 未过滤的扫描很慢且可能被限流 |
| WebSocket 重连 | 断开的订阅会静默停止更新 |
| 故障转移端点 | 单个端点是单点故障 |
| 优先费用逻辑 | 静态费用在拥堵期间表现不佳 |
如果其中几项在共享端点上难以管理,那就是评估专用 Solana 节点的信号。OnFinality 在 支持的网络 上提供 RPC API 访问和专用节点基础设施,包括 Solana,因此你可以在不自己运行验证器的情况下扩展容量。
承诺级别及其为何改变结果
每个读取方法都接受一个承诺参数。你最常使用的三个:
- processed 反映最新的 slot,但可能回滚。
- confirmed 由绝对多数投票,是面向用户余额的常用选择。
- finalized 不可逆,最适合结算逻辑。
在调用中混合承诺级别会导致令人困惑的错误,例如余额出现后又消失。为每个功能选择一个级别并一致应用。对于交易确认,confirmed 是合理的默认值;对于金融结算,使用 finalized。
调试常见的 Solana RPC 故障
| 症状 | 可能原因 | 下一步 |
|---|---|---|
| 交易未确认 | Blockhash 过期或优先费用低 | 重新获取 blockhash,提高优先费用,重新发送 |
getProgramAccounts 超时 | 缺少过滤器或结果过大 | 添加 dataSize/memcmp 过滤器,分页 |
| WebSocket 停止更新 | 连接断开 | 重连并重新订阅 |
| 余额不一致 | 混合承诺级别 | 为每个功能标准化承诺级别 |
| 429 响应 | 请求速率超限 | 批量请求,缓存读取,或迁移到专用容量 |
当你看到 429 或延迟峰值时,捕获方法名和负载大小。大型 getProgramAccounts 调用和未过滤的日志订阅是常见的罪魁祸首。减少负载大小通常无需更换提供商即可解决问题。
在共享和专用 Solana RPC 之间选择
共享端点对于开发、低流量 dapp 和读密集型仪表板具有成本效益。当你需要一致的吞吐量、大量订阅、大型账户扫描或与其他租户流量隔离时,专用节点就有意义。OnFinality 提供两种模式,因此你可以从共享端点开始,随着使用量增长迁移到专用节点。查看 RPC 定价 了解当前选项,以及 如何选择 RPC 提供商 了解评估标准。
关键要点
- Solana RPC 方法分为读取(getAccountInfo, getBalance, getProgramAccounts)、写入(sendTransaction)和订阅(logsSubscribe, accountSubscribe)。
- 发送前始终获取新的 blockhash;过期的 blockhash 是交易失败的主要原因。
- 一致地使用承诺级别;混合它们会造成难以调试的不一致。
- 积极过滤 getProgramAccounts 以避免超时和速率限制。
- WebSocket 客户端必须处理重连和重新订阅。
- 共享端点适合低流量应用;专用节点适合持续、高流量或订阅密集型工作负载。
常见问题解答
最常用的 Solana RPC 方法是什么? 对于钱包和 dapp,getLatestBlockhash、getBalance 和 sendTransaction 是最常见的。索引器更依赖 getProgramAccounts 和 getSignaturesForAddress。
OnFinality 支持 Solana WebSocket 订阅吗? 是的。Solana 端点同时暴露 HTTP 和 WebSocket 传输。详情请参阅 Solana 网络页面。
为什么 getProgramAccounts 会失败或超时? 通常是因为查询缺少过滤器并返回太多数据。添加 dataSize 或 memcmp 过滤器并对结果分页。
我应该使用公共还是专用的 Solana RPC 端点? 开发和低流量时从公共端点开始。当你需要可预测的吞吐量、大量订阅或与共享流量隔离时,迁移到专用节点。
如何设置优先费用? 调用 getRecentPrioritizationFees,然后设置反映当前拥堵情况的费用。静态费用在繁忙时段通常表现不佳。