摘要
Solana 的 RPC API 是您的应用用来读取账户、提交交易和订阅链上事件的 JSON-RPC 接口。本参考文档将介绍端点结构、您实际会调用的方法组,以及如何调试生产环境中出现的错误。
它还涵盖了何时公共端点就足够,以及何时使用 OnFinality 的专用 Solana 节点更适合获得一致的吞吐量、WebSocket 订阅和更重的读取工作负载。
Solana 不提供用于链数据的 REST API。您的应用读取或写入的所有内容都通过一个 JSON-RPC 端点进行,这意味着您选择的端点以及调用的方法决定了您的延迟、错误率和账单。本页面是该接口的实用参考:请求如何构造、哪些方法重要、订阅如何工作,以及当真实流量到来时如何调试您将遇到的故障。
您应该连接到哪个 Solana 端点?
首先将端点与任务匹配。快速脚本、黑客松演示或只读仪表板通常可以针对公共端点运行。钱包、交易机器人、索引器或任何需要大量并发读取的应用几乎会立即感受到共享容量与专用容量之间的差异。
| 您的情况 | 合理的起点 | 原因 |
|---|---|---|
| 原型设计、一次性脚本、学习 API | 公共 Solana 端点 | 无需设置,适合低请求量 |
| 在主网之前测试程序逻辑 | Solana Devnet RPC | 从水龙头免费获取 SOL,可以安全地破坏东西 |
| 具有稳定用户流量的钱包或 dApp | 托管 Solana RPC | 可预测的容量,无需运行验证器 |
| 索引器、机器人或高读取扇出 | 专用 Solana 节点 | 隔离的吞吐量和您自己的 WebSocket 容量 |
| 需要历史账户或交易状态 | 支持归档的节点 | 标准节点会修剪较旧的账本数据 |
OnFinality 通过 HTTP 和 WebSocket 运行 Solana 主网 RPC,因此您可以将单个提供商同时指向您的请求/响应调用和订阅调用。如果您仍在权衡提供商,RPC 提供商选择指南更深入地介绍了评估标准。
端点结构和第一个请求
Solana RPC 端点是一个单一的 URL,接受带有 JSON 正文的 HTTP POST 请求。没有针对每个方法的路径;方法名称位于正文中。公共 OnFinality Solana 端点是:
https://solana.api.onfinality.io/public
获取当前 slot 的最小调用如下所示:
curl https://solana.api.onfinality.io/public \
-X POST \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getSlot",
"params": []
}'
响应遵循 JSON-RPC 2.0 信封:一个 jsonrpc 字段、一个回显您请求的 id,以及一个 result 或 error 对象。每个 Solana 方法都使用相同的信封,因此一旦您的客户端正确处理它,您就可以调用任何方法而无需更改传输代码。
您实际会调用的方法组
Solana 的方法列表很长,但生产应用集中在少数几个组上。知道一个方法属于哪个组可以告诉您它的开销有多大以及它如何失败。
| 组 | 代表性方法 | 典型用途 | 成本概况 |
|---|---|---|---|
| 账户读取 | getAccountInfo、getMultipleAccounts、getProgramAccounts | 余额、代币账户、程序状态 | 每次调用便宜,但 getProgramAccounts 可能很重 |
| 区块和 slot 数据 | getSlot、getBlock、getBlockHeight、getLatestBlockhash | 确认、交易构建 | 中等;getBlock 返回大负载 |
| 交易提交 | sendTransaction、simulateTransaction | 发送已签名交易 | 对负载敏感;先模拟 |
| 代币和 SPL 辅助 | getTokenAccountsByOwner、getTokenAccountBalance | 钱包余额和代币列表 | 每个用户中等扇出 |
| 费用和优先级 | getRecentPrioritizationFees、getFeeForMessage | 设置计算单元价格 | 便宜,但要新鲜调用 |
| 订阅(WebSocket) | accountSubscribe、logsSubscribe、slotSubscribe | 无需轮询的实时更新 | 长连接 |
两个实用说明。首先,getProgramAccounts 是最有可能在共享端点上超时的方法,因为它可能扫描大量账户集;尽可能使用过滤器和 dataSlice 来限定范围。其次,getLatestBlockhash 结果会过期,因此在签名时获取新鲜的 blockhash,而不是缓存几分钟。
使用 JSON-RPC API 构建交易
大多数团队使用 @solana/web3.js 或类似的客户端,而不是手工编写 JSON。客户端在底层仍然使用相同的 RPC 方法,因此将其指向您的端点只需更改一行:
import { Connection, PublicKey, LAMPORTS_PER_SOL } from "@solana/web3.js";
const connection = new Connection(
"https://solana.api.onfinality.io/public",
{ commitment: "confirmed" }
);
const balance = await connection.getBalance(
new PublicKey("11111111111111111111111111111111")
);
console.log("lamports:", balance, "SOL:", balance / LAMPORTS_PER_SOL);
您传递的 commitment 级别很重要。processed 最快但可能回滚;confirmed 是面向用户余额的常用默认值;finalized 对于结算逻辑最安全。有意识地选择一个并在读取中保持一致,因为混合 commitment 级别是导致 UI 状态混乱的常见原因。
WebSocket 订阅以及何时使用它们
在循环中轮询 getSlot 或 getAccountInfo 会消耗请求,而且仍然感觉延迟。Solana 的 WebSocket 接口改为推送更新。公共 OnFinality WebSocket 端点是:
wss://solana.api.onfinality.io/public-ws
订阅请求使用相同的 JSON-RPC 信封,通过 socket 发送:
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: ["YourProgramPublicKeyHere"] },
{ commitment: "confirmed" }
]
}));
};
ws.onmessage = (event) => {
const payload = JSON.parse(event.data);
if (payload.method === "logsNotification") {
console.log("program log:", payload.params.result.value.logs);
}
};
订阅是长寿命的,因此要计划重新连接。共享端点可能会关闭空闲或过载的 socket,而您的应用未注意到的断开 socket 看起来就像链停滞一样。添加心跳、使用退避重新连接,并在重新连接时重新订阅。如果您的工作负载依赖于许多并发订阅,这是一个强烈的信号,表明您应该迁移到专用节点,在那里连接预算属于您。
常见 Solana RPC 错误的调试路径
当出现问题时,错误文本通常指向某一层。使用此表来路由修复。
| 症状 | 可能原因 | 下一步 |
|---|---|---|
429 或速率限制响应 | 共享端点负载过高 | 退避、批量读取或迁移到专用容量 |
Blockhash not found | 过时或过期的 blockhash | 在签名前立即获取新的 blockhash |
| 交易确认后消失 | Commitment 级别不匹配 | 将读取和确认逻辑对齐到 confirmed 或 finalized |
getProgramAccounts 超时 | 未过滤的账户扫描 | 添加 filters 和 dataSlice,或使用专用节点 |
| WebSocket 停止更新 | Socket 静默关闭 | 添加心跳、重新连接并重新订阅 |
-32002 交易模拟失败 | 程序逻辑拒绝了交易 | 运行 simulateTransaction 并在重新发送前读取日志 |
一个有用的习惯是记录原始 JSON-RPC error 对象,而不仅仅是友好的消息。Solana 返回结构化错误数据,包括模拟失败的日志,这些细节通常足以识别失败的指令。
生产就绪检查清单
在将真实用户指向端点之前,确认以下事项:
- Commitment 级别是明确的,贯穿每个读取和确认路径。
- 重试使用退避,而不是紧密循环,这样慢时刻不会变成自我造成的峰值。
- Blockhash 新鲜度在签名时处理,而不是缓存。
- WebSocket 重新连接已实现并通过故意杀死 socket 进行测试。
- 重读取被限定范围,使用过滤器、
dataSlice和 API 允许的批处理。 - 配置了回退端点,这样单个提供商问题不会导致应用宕机。
- 测量请求量,以便判断共享容量是否仍然足够。
如果在共享端点上难以满足其中几项,那就是查看专用节点或查看 RPC 定价以比较选项的时候。
Devnet、主网以及在它们之间迁移
Devnet 镜像主网 API 表面,因此针对主网工作的代码通常可以通过不同的 URL 和水龙头资助的密钥对针对 Solana Devnet RPC 工作。将端点保留在配置中而不是硬编码,并为每个环境保留单独的密钥对。最常见的迁移错误是在一个环境中更新了程序 ID 或代币铸造,但在另一个环境中没有更新。
OnFinality 将 Solana 主网和 devnet 作为单独的网络条目公开,因此您可以注册两者并通过配置切换。请参阅 Solana 网络页面了解当前端点详细信息和传输支持,以及支持的 RPC 网络获取完整列表。
关键要点
- Solana 为读取、写入和订阅公开一个 JSON-RPC 接口;方法名称位于请求正文中,而不是 URL 中。
- 将端点与工作负载匹配:公共用于原型,托管用于稳定流量,专用用于高扇出或订阅密集型应用。
getProgramAccounts和长寿命 WebSocket 是最有可能将您推出共享端点的两个领域。- 大多数生产错误可追溯到 commitment 级别、过时的 blockhash 或未被注意的 socket 断开,而不是 API 本身。
- OnFinality 通过 HTTP 和 WebSocket 提供 Solana RPC,并在共享容量不足时提供专用节点选项。
常见问题
Solana RPC API 与 Solana JSON-RPC API 相同吗?
是的。当人们说“Solana RPC API”时,他们指的是通过 HTTP 和 WebSocket 提供的 JSON-RPC 2.0 接口。没有单独的用于链数据的 REST API。
调用 Solana RPC 端点需要 API 密钥吗?
公共端点通常无需密钥即可工作,这对于低容量使用来说没问题。托管和专用端点使用密钥或私有 URL,以便您的流量被隔离和可测量。
为什么我的交易失败并显示“Blockhash not found”?
您签名的 blockhash 在交易落地之前过期了。在签名前立即获取新的 blockhash,并使用退避重试。
我应该轮询还是使用 WebSocket 订阅?
对于任何需要对链上事件做出反应的内容,使用订阅,并将轮询保留用于偶尔的检查。订阅减少请求量,通常感觉更快,但它们需要重新连接处理。
什么时候应该从公共端点迁移到专用节点?
当您看到速率限制时,当 getProgramAccounts 或类似的重读取超时时,当您需要许多并发 WebSocket 订阅时,或者当您需要标准节点修剪的历史状态时。专用节点为这些情况提供隔离的容量。