Skip to main content
orbitflare-apex-go 是 Apex 的 Go 客户端。它为每个 Apex 端点保持一个持久 QUIC 连接,使用由您的 API 密钥派生的客户端证书进行身份验证,每个流发送一笔序列化后的交易,并在连接断开时以 0-RTT 重连。它的功能与 Rust 客户端相同,其客户端证书与 Rust 客户端的逐字节一致。

安装

该模块为 github.com/orbitflare/orbitflare-apex-go;源码托管在 GitHub:
该模块包含两个包: 交易使用 solana-go 构建,它支持 legacy、v0 和 v1 消息。QUIC 路径不依赖 rpc 包。 该模块需要 Go 1.26 或更高版本。

快速开始

一个完整的程序。它构建一笔带有计算预算和小费的 memo 交易,通过 QUIC 发送,并等待确认。它读取与快速入门相同的环境变量:APEX_API_KEY、KEYPAIR_PATH 和 SOLANA_RPC_URL。
main.go
SendTransaction 在交易写入流后立即返回,耗时仅几微秒,不等待任何确认。下面的代码片段可直接放入该程序中:它们复用其中的 ctx、client、apiKey、payer、tipAccount、blockhash、solanaRPC 和 tx。请添加代码片段用到的标准库导入,例如 errors、encoding/base64 或 sync。

带应答发送

双向流会在返回前读取 Apex 的应答:交易被接受时返回签名,被拒绝时返回带有准入码和消息的 *apex.RejectedError。它多花费一次往返,因此请在集成阶段使用,或在您需要直接获得原因时使用。
SendWithResponse(ctx, wire) 对您已持有的字节执行相同操作,并返回原始的 apex.Admission(Accepted、Signature、Code、Message)。

v1 交易

v1 交易最大可达 4096 字节。计算预算位于消息的 solana.TransactionConfig 中,而不是 ComputeBudget 指令中,并且每个未设置的限制都为 0,因此请设置计算单元上限、已加载账户数据大小上限,以及用于优先级的费用。参见 Transaction v1。

原始字节

如果您的交易已经序列化(来自其他签名者、其他进程或文件),请按原样发送这些字节。不会对其重新编码。
apex.EncodePacket(wire, mevProtect, maxRetries) 返回客户端写入流的精确数据包:8 字节长度、交易本身,以及 3 字节的尾部。它可作为其他语言的参考。

HTTP

rpc 包覆盖了 Apex 端点上的每一条 HTTP 路由。它通过 x-api-key 请求头发送密钥。
SendTransaction 即 JSON-RPC sendTransaction,可直接替换现有代码。SendTransactionBinary 将原始字节提交到 /send-bin,这是开销最低的 HTTP 路径。最后两个参数是 mevProtect 和 maxRetries;传入 nil 则沿用端点默认的重试预算。

批量发送

SendBatch 在一个请求中最多发送 16 笔交易。每笔交易独立准入,结果会说明哪些被接受。

捆绑包

SendBundle 发送一到四笔按顺序上链的交易,要么全部上链,要么全部不上链,其中恰好一笔带小费。轮询 BundleStatuses,直到捆绑包上链或失败。参见捆绑包。

并发发送

*apex.Client 可安全地并发使用,每次发送都会在同一个连接上获得自己的流。只需创建一次客户端,然后可以从任意数量的 goroutine 中发送。

区域

每个 Apex 端点都是一个 apex.Region 常量。apex.ParseRegion 接受代码或城市名称,apex.AllRegions 列出全部区域。
QUICEndpoint() 返回 <code>.apex.orbitflare.com:7001,RPCURL() 返回 http://<code>.apex.orbitflare.com。参见端点与区域。

传输方式

传输方式不会改变优先级或路由。起作用的是小费。

API

每个涉及网络的调用都接受一个 context.Context,因此您可以取消一次发送或为其设置截止时间。用完后请调用 Close;它会停止后台重连并关闭套接字。

选项

每个字段的零值即为默认值,因此只需设置您需要的字段:

保活与重连

连接通过每秒一次的 QUIC PING 保持打开,而 Apex 端点的空闲超时为 30 秒。在预热的连接上,一次发送就是打开一个流并写入一次。 如果连接断开:
  • 后台 goroutine 会发现并立即重新握手,因此下一次发送通常能找到一个可用的连接。如果是端点本身关闭了连接(未知密钥、连接数过多),该 goroutine 每次尝试后都会将等待时间加倍,最长 30 秒,而不是反复强行重试。
  • 重连会使用缓存的会话票据,并在握手的首批数据包中发送等待中的交易(0-RTT)。如果端点拒绝早期数据,客户端会在握手完成后重新发送。
  • 因连接已断开而失败的发送会重新连接并重试一次。设置 DisableAutoReconnect 可自行处理这种情况。
  • 每次重连都会重新解析主机名,因此使用 apex.Global 的客户端在自己所连的端点宕机时,会跟随负载均衡器切换到下一个最近的端点,无需重启。解析发生在后台重连中,而不是在发送时;如果解析失败或耗时超过两秒,客户端会保留原有地址。IP 地址形式的端点永远不会被解析。
将连接状态导出到您的指标中:

错误

错误会包装一个哨兵错误,因此 errors.Is 可以告诉您失败发生在哪个阶段,而 errors.As 可以取得带类型的错误。
rpc 包在 JSON-RPC 或普通 HTTP 拒绝时返回带有代码和消息的 *rpc.Error,在无法解析响应时返回 rpc.ErrBadResponse。普通 HTTP 拒绝的代码为 0,消息为 label: message,其中的标签列于错误与速率限制。

检查您的密钥

打印您的 API 密钥派生出的证书密钥。它必须与控制台上该密钥旁显示的客户端公钥一致;如果不一致,说明密钥复制有误。

仓库中的示例

所有示例都读取 APEX_API_KEY、KEYPAIR_PATH(默认 payer.json)、SOLANA_RPC_URL,以及可选的 APEX_REGION、APEX_QUIC、APEX_RPC、TIP_LAMPORTS、APEX_TX_VERSION(legacy 或 v1)、APEX_MEMO_BYTES 和 APEX_CU_LIMIT。每个示例都会发送一笔带小费的 memo 交易,并报告其上链的 slot。

客户端不做的事

  • 构建或签名交易,或为您选择优先费。
  • 模拟或运行预检。在您和领导者之间,没有任何环节会这样做。