摘要
Solana HTTP API 是您的应用通过标准 HTTPS 读取账户、提交交易和查询集群所使用的 JSON-RPC 接口。您向 RPC 端点发送带有 JSON 正文的 POST 请求,节点返回 JSON 结果或错误对象。本文涵盖请求结构、最常用的方法,以及如何调试实际 Solana 应用中出现的故障。它还解释了何时共享公共端点足够,以及何时专用 Solana 节点更适合生产流量。
Solana HTTP API 是您的应用程序通过 HTTPS 与 Solana 节点通信所使用的 JSON-RPC 接口。每次钱包余额查询、账户读取、交易提交和区块查询都通过向 RPC 端点发送 POST 请求来完成。如果您在 Solana 上构建,这是您最常调试的层。
本页侧重于实践方面:请求结构、您实际会调用的方法、承诺级别如何改变结果,以及如何解读返回的错误。它还能帮助您决定共享端点是否足够,或者您的工作负载是否需要专用 Solana 节点。
您应该从哪个端点开始?
从 Solana 主网的官方 OnFinality 公共端点开始:
https://solana.api.onfinality.io/public
该端点适用于本地开发、脚本和低流量读取。当您遇到以下任何信号时,请迁移到专用或私有端点:
- 您以稳定速率提交交易并看到间歇性的 429 响应。
- 您需要一致地访问历史账户状态或大型
getProgramAccounts扫描。 - 您运行索引器、机器人或后端,每隔几秒轮询相同的账户。
- 您需要 WebSocket 订阅以获取账户或 slot 变化,同时进行 HTTP 调用。
如果您的工作负载是读取密集型和突发性的,共享 RPC 计划通常可以满足。如果您的工作负载是持续且延迟敏感的,专用 Solana 节点可为您提供隔离的容量。您可以在 RPC 定价 页面比较选项,并查看 支持的 RPC 网络 的完整列表。
请求结构
每个 Solana HTTP API 调用都是一个 JSON-RPC 2.0 POST。正文包含四个字段:jsonrpc、id、method 和 params。
curl https://solana.api.onfinality.io/public \
-X POST \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getBalance",
"params": [
"83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri"
]
}'
成功时响应返回 result 对象,失败时返回带有 code 和 message 的 error 对象。您发送的 id 会被回显,这在批量请求时很重要。
一些容易让人困惑的地方:
params始终是一个数组,即使只有一个参数。- 某些方法将选项对象作为第二个元素,例如
{"commitment": "confirmed"}。 Content-Type头必须是application/json。
您最常调用的方法
您不需要记住完整的方法列表。大多数 Solana 应用重复使用一小部分方法。
| 方法 | 作用 | 典型调用者 |
|---|---|---|
getBalance | 返回账户的 lamport 余额 | 钱包、仪表盘 |
getAccountInfo | 返回账户的数据和所有者 | 程序、索引器 |
getLatestBlockhash | 返回用于构建交易的最近 blockhash | 任何交易发送者 |
sendTransaction | 提交已签名的交易 | 钱包、机器人、后端 |
getSignatureStatuses | 检查签名的确认状态 | 交易发送者 |
getTransaction | 通过签名返回已确认的交易 | 浏览器、支持工具 |
getProgramAccounts | 返回程序拥有的账户 | 索引器、分析 |
getSlot | 返回当前 slot | 健康检查、监控 |
getProgramAccounts 值得警告。在大型程序上它可能开销很大,并且通常是共享端点上第一个超时或被限流的调用。如果您依赖它,请计划使用专用节点或索引数据源。
承诺级别改变返回结果
Solana 没有单一的“已确认”状态。您为每个请求选择承诺级别,它同时改变结果和延迟。
| 承诺级别 | 含义 | 权衡 |
|---|---|---|
processed | 节点已看到该 slot | 最快,可能回滚 |
confirmed | 绝大多数质押已投票 | 大多数应用的平衡默认值 |
finalized | 已根化,无法回滚 | 最慢,结算最安全 |
对于显示余额的钱包,confirmed 通常是正确的。对于任何转移资金或触发不可逆业务逻辑的操作,请等待 finalized。如果您在不同调用中混合承诺级别,可能会得到不一致的读取,例如余额在改变它的交易之前出现。
解读错误而非猜测
当 Solana HTTP API 调用失败时,错误对象会告诉您从哪里查找。下表将常见症状映射到可能的原因和下一步。
| 症状 | 可能原因 | 下一步 |
|---|---|---|
| HTTP 429 | 共享端点上的速率限制 | 退避、批量读取或迁移到专用节点 |
-32602 无效参数 | 参数结构错误或缺少选项对象 | 检查方法签名和数组顺序 |
-32002 交易模拟失败 | 交易将在链上失败 | 运行 simulateTransaction 并读取日志 |
Blockhash not found | blockhash 在提交前过期 | 在发送前立即获取新的 blockhash |
getTransaction 返回空 result | 尚未确认或承诺级别错误 | 使用 confirmed 或 finalized 重试 |
getProgramAccounts 超时 | 结果集太大 | 添加过滤器或使用专用节点 |
一个有用的习惯是记录完整的错误对象,而不仅仅是消息。data 字段通常包含失败交易的日志,这通常直接指向程序错误。
构建和发送交易
HTTP API 不会为您签名交易。您在本地构建并签名,然后提交已签名的字节。一个最小的 JavaScript 流程如下:
import { Connection, PublicKey, Transaction, SystemProgram } from "@solana/web3.js";
const connection = new Connection("https://solana.api.onfinality.io/public", "confirmed");
const from = new PublicKey("<YOUR_WALLET_PUBLIC_KEY>");
const to = new PublicKey("<RECIPIENT_PUBLIC_KEY>");
const { blockhash } = await connection.getLatestBlockhash("confirmed");
const tx = new Transaction().add(
SystemProgram.transfer({ fromPubkey: from, toPubkey: to, lamports: 1_000_000 })
);
tx.recentBlockhash = blockhash;
tx.feePayer = from;
// Sign with your wallet adapter or keypair, then:
const signature = await connection.sendRawTransaction(tx.serialize());
await connection.confirmTransaction(signature, "confirmed");
这里有两个细节很重要。首先,始终在发送前立即获取新的 blockhash,因为 blockhash 会过期。其次,确认签名,而不是假设提交就等于成功。
HTTP 与 WebSocket
HTTP 是请求-响应。WebSocket 是持久连接,推送更新。使用 HTTP 进行读取和交易提交。当您需要无需轮询即可响应变化时,使用 WebSocket。
const subId = connection.onAccountChange(
new PublicKey("<ACCOUNT_PUBLIC_KEY>"),
(accountInfo) => {
console.log("Account changed:", accountInfo.lamports);
},
"confirmed"
);
OnFinality 为 Solana 提供 WebSocket 传输以及 HTTP,因此您可以在同一提供商上保留两者。如果您的应用每隔几秒轮询同一账户,切换到订阅通常可以减少负载并改善响应时间。
何时从公共端点迁移
公共端点是起点,不是生产计划。决策通常归结为三个问题:
- 您的流量是连续的还是偶尔的?连续流量需要隔离的容量。
- 您是否依赖像
getProgramAccounts或历史读取这样的昂贵调用?这些需要余量。 - 您是否需要在负载下可预测的行为?共享端点本质上是尽力而为的。
如果您对多个问题回答“是”,请查看 专用节点。专用基础设施为您的应用提供自己的容量,这消除了吵闹邻居问题并使速率限制行为可预测。OnFinality 同时提供 RPC API 访问和专用节点选项,因此您可以从共享开始并升级,而无需更改集成。
对于 devnet 和测试,请使用 Solana Devnet RPC 页面设置单独的端点,以便测试流量永远不会与生产竞争。
上线前的操作检查
在将真实用户指向您的 Solana HTTP API 设置之前,请确认以下基本事项:
- 您的端点可通过环境变量配置,而不是硬编码。
- 您有备用端点或提供商用于故障转移。
- 您记录请求 ID 和错误代码以供支持。
- 您定期监控
getSlot或getHealth以尽早发现停滞。 - 您批量处理独立读取,而不是一次一个地触发。
- 您使用指数退避处理 429 响应。
一个简单的健康探测如下所示:
curl -s https://solana.api.onfinality.io/public \
-X POST -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"getHealth"}'
如果 getHealth 返回 "ok",则节点正在响应。将其与 slot 检查配对,以确认节点确实在推进。
关键要点
- Solana HTTP API 是基于 HTTPS 的 JSON-RPC:POST JSON 正文,获取 JSON 结果或错误。
params始终是一个数组,像 commitment 这样的选项放在第二个元素中。- 承诺级别同时改变延迟和安全性;对于不可逆操作使用
finalized。 - 像
getProgramAccounts这样的昂贵调用是共享端点上最先失败的。 - 使用 HTTP 进行读取和提交,使用 WebSocket 进行订阅。
- 当流量连续或延迟敏感时,迁移到专用节点。
常见问题
Solana HTTP API 和 JSON-RPC 是一样的吗?
是的。当人们说 Solana HTTP API 时,他们指的是通过 HTTPS 提供的 JSON-RPC 接口。传输是 HTTP,负载格式是 JSON-RPC 2.0。
默认承诺级别是什么?
如果您不传递 commitment 选项,大多数方法默认为 finalized。许多应用显式设置 confirmed 以获得更快的读取。
为什么我会收到 429 响应?
429 表示您触发了速率限制,这在共享公共端点上很常见。减少请求量、批量读取或迁移到专用节点。
我可以对主网和 devnet 使用同一个端点吗?
不可以。主网和 devnet 是独立的集群,具有独立的端点。将它们保存在单独的配置中,以便测试流量永远不会触及生产。
如果我已经使用 HTTP,还需要 WebSocket 吗?
仅当您需要推送更新时。如果您重复轮询同一账户,WebSocket 订阅通常更高效。
如何调试失败的交易?
运行 simulateTransaction 并读取错误 data 字段中的日志。程序错误代码通常能识别原因。
下一步
如果您仍在评估,请从上面的公共端点开始,并测量一周的请求模式。如果您看到速率限制、大型查询超时或需要 WebSocket 订阅,请查看 RPC 定价 和 Solana 网络页面 以选择适合您工作负载的计划。对于运行连续流量的团队,专用节点 消除了共享容量上限,并保持您的 Solana HTTP API 调用可预测。