Logo
新用户订阅 RPC,首月享 6.5 折优惠查看优惠
OnFinality Learn
集成与开发阅读约 14 分钟

通过 Info API 查询 Hyperliquid 订单状态与用户成交

通过无需认证的 /info 端点读取 Hyperliquid 订单与成交状态,并将 userFills、historicalOrders 和 orderStatus 整合为统一的订单生命周期视图。

TL;DR

Hyperliquid 的 /info 端点是一个无需认证的只读 POST 接口,无需私钥即可查询订单与成交状态。三个读取请求各自拥有不同的权威范围:userFills 是成交历史,historicalOrders 是带状态的账户订单历史,frontendOpenOrders 列出当前挂单。orderStatus(oid|cloid) 是单点查询,返回一个可辨识联合类型(order、status、fill、rejected、unknownOid),是单个订单的权威来源。由于索引延迟,userFills 与 historicalOrders 可能短暂不一致,因此应通过 oid 进行关联对账,并将 orderStatus 视为每个订单的最终事实来源。本文展示请求结构、可运行的 Node.js 读取路径、用于对照自己账户填写的结果表,以及会破坏集成的常见故障模式。

只读的 /info 接口,以及为什么观察订单无需私钥

Hyperliquid 将其 HTTP API 分为两个接口面:/info 用于读取,/exchange 用于签名写入。/info 端点是一个无需认证的 POST 请求,接受带有 type 字段和请求特定参数的 JSON 请求体,并返回所请求的状态。由于它是只读的,观察订单和成交从不需要私钥,这意味着监控可以运行在独立进程、仪表盘或只读服务账户中,而无需暴露签名材料。

这与 JSON-RPC 提供商端点不同,后者同样基于 POST,但遵循 JSON-RPC 2.0 信封格式,包含 jsonrpc、method、params 和 id 字段。/info 接口是普通的应用层 POST,而不是 JSON-RPC 方法调用,因此不应将其请求体包装在 JSON-RPC 信封中。Hyperliquid API 文档是确切的请求与响应结构的权威来源。

对于生产环境读取,请将客户端指向可靠的端点。OnFinality 提供 Hyperliquid RPC 端点以及可代理 /info 接口的 API 服务Hyperliquid 网络页面列出了可用的访问路径。

  • /info:无需认证的只读 POST,请求体是带有 type 字段的 JSON 对象。
  • /exchange:用于提交和取消订单的签名写入路径。
  • 读取 userFills、historicalOrders、frontendOpenOrders 或 orderStatus 无需私钥。
  • 不要将 /info 请求体包装在 JSON-RPC 2.0 信封中;它不是 JSON-RPC 方法。

三个读取请求及其各自的权威范围

userFills 返回账户的成交历史。每笔成交包含 px、sz、side、time、fee、closedPnl、oid 和 tid,请求接受可选的 aggregateByTime 标志。这是聚合成交的权威来源:如果你想了解实际成交了多少以及成交价格,userFills 就是来源。Hyperliquid API 文档定义了确切的字段集和聚合语义。

historicalOrders 返回账户带状态的订单历史,是订单级状态转换的权威来源。frontendOpenOrders 返回当前挂单,是当前实时状态的权威来源。orderStatus(oid|cloid) 是单个订单的单点查询,是该订单当前状态的权威来源。Hyperliquid Python SDK展示了这些调用的参考客户端实现。

一个实用的读取路径会调用 frontendOpenOrders 获取实时订单簿、historicalOrders 获取近期订单日志、userFills 获取成交,然后按 oid 关联。Hyperliquid 历史数据与市场数据 API页面涵盖了市场数据部分,它与你的订单状态是分开的。

  • userFills:成交历史;聚合成交和手续费的权威来源。
  • historicalOrders:带状态的订单历史;订单级状态转换的权威来源。
  • frontendOpenOrders:当前挂单;实时敞口的权威来源。
  • orderStatus(oid|cloid):单点查询;单个订单的权威来源。

orderStatus 可辨识联合类型与安全分支

orderStatus 以 oid 或 cloid 为键,返回一个可辨识联合类型。文档记录的结果包括 order、status、fill、rejected 和 unknownOid。每种结果的形状不同,因此必须先根据判别字段进行分支,再读取字段。将响应当作单一扁平对象处理是最常见的集成错误。

order 结果描述挂单,status 描述状态转换,fill 描述成交,rejected 描述被拒绝的订单,unknownOid 表示未找到该标识符。当你生成自己的客户端订单 ID 时,cloid 路径允许你在还没有 oid 时查询订单,这对幂等提交流程很有用。Hyperliquid 文档是订单如何从提交过渡到成交、以及为什么 orderStatus 以 oid 或 cloid 为键的权威来源。

安全分支意味着先检查判别字段,然后验证该分支所需的字段是否存在。绝不要假设 order 结果中存在 fill 字段,也绝不要假设 unknownOid 结果中存在 oid。

  • order:挂单详情。
  • status:状态转换详情。
  • fill:成交详情。
  • rejected:订单被拒绝;读取原因。
  • unknownOid:未找到标识符;检查 cloid 生成和提交。

为什么 userFills 与 historicalOrders 可能短暂不一致

userFills 和 historicalOrders 由不同的读取路径提供,由于索引延迟,可能在短时间内不一致。一笔成交可能先出现在 userFills 中,而 historicalOrders 中对应订单状态稍后才更新,反之亦然。这是正常现象,并不表示数据丢失。

对账规则是将 orderStatus 视为单个订单的权威来源,将 userFills 视为聚合成交的权威来源。当两者不一致时,针对特定 oid 重新查询 orderStatus,并用该结果来确定订单状态。对于聚合成交量、手续费和 closedPnl,请信任 userFills。Hyperliquid API 错误处理页面涵盖了提交时的拒绝解码,这与本文提交后的读取路径属于不同阶段。

如果你需要一致的快照,请轮询两个接口并按 oid 关联,然后在告警前应用一个短暂的等待重试窗口。不要将瞬时不一致视为故障。

  • 索引延迟可能导致 userFills 与 historicalOrders 暂时不一致。
  • orderStatus 是单个订单的权威来源;userFills 是聚合的权威来源。
  • 按 oid 关联,并在告警前重试。

可运行的 Node.js 读取路径:挂单、历史与成交

以下 Node.js 示例使用正确的请求体结构 POST 到 /info 端点,读取挂单、历史订单和近期用户成交,并打印一张按 oid 关联成交与状态的对账表。它使用现代 Node.js 内置的 fetch,无需私钥。

将端点 URL 替换为你的提供商的 /info URL,并设置用户地址。该示例假设响应结构符合 Hyperliquid 文档;如果你的提供商返回包装层,请相应调整解析逻辑。

const INFO_URL = 'https://api.hyperliquid.xyz/info';
const USER = '0xYourAccountAddress';

async function info(body) {
  const res = await fetch(INFO_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body)
  });
  if (!res.ok) throw new Error('info HTTP ' + res.status);
  return res.json();
}

async function main() {
  const open = await info({ type: 'frontendOpenOrders', user: USER });
  const history = await info({ type: 'historicalOrders', user: USER });
  const fills = await info({ type: 'userFills', user: USER, aggregateByTime: false });

  const byOid = new Map();
  for (const o of history) {
    const oid = o.order && o.order.oid;
    if (oid == null) continue;
    byOid.set(oid, { oid, status: o.status, fills: [] });
  }
  for (const f of fills) {
    const oid = f.oid;
    if (oid == null) continue;
    if (!byOid.has(oid)) byOid.set(oid, { oid, status: 'unknown', fills: [] });
    byOid.get(oid).fills.push(f);
  }
  for (const o of open) {
    const oid = o.oid;
    if (oid == null) continue;
    if (!byOid.has(oid)) byOid.set(oid, { oid, status: 'open', fills: [] });
  }

  console.log('oid | status | fills | filledSz | avgPx');
  for (const row of byOid.values()) {
    let filledSz = 0;
    let notional = 0;
    for (const f of row.fills) {
      const sz = Number(f.sz);
      const px = Number(f.px);
      filledSz += sz;
      notional += sz * px;
    }
    const avgPx = filledSz > 0 ? (notional / filledSz).toFixed(4) : '-';
    console.log(row.oid + ' | ' + row.status + ' | ' + row.fills.length + ' | ' + filledSz + ' | ' + avgPx);
  }
}

main().catch((e) => { console.error(e); process.exit(1); });

使用 orderStatus 对单个订单进行单点查询

当你需要查询单个订单的状态时,orderStatus 比扫描历史更经济、更精确。在请求体中传入 oid 或 cloid。响应是前面描述的可辨识联合类型,因此请先根据判别字段分支,再读取字段。

以下 curl 示例展示了 oid 查询的请求结构。将 oid 替换为你账户中的真实值。如果你生成自己的客户端订单 ID,请改用 cloid 形式。

curl -s -X POST https://api.hyperliquid.xyz/info \
  -H 'Content-Type: application/json' \
  -d '{"type":"orderStatus","user":"0xYourAccountAddress","oid":123456789}'

# cloid form
curl -s -X POST https://api.hyperliquid.xyz/info \
  -H 'Content-Type: application/json' \
  -d '{"type":"orderStatus","user":"0xYourAccountAddress","cloid":"0x..."}'

用于对照自己账户填写的结果表

使用下表记录你的端点对某个已知订单返回的内容。运行 Node.js 示例,选择一个 oid,并填写每一列。这可以验证你的提供商是否返回文档所述的结构,以及你的对账逻辑是否正确关联。

如果某一列为空或不符合预期,请先重新检查请求体和判别分支,再假设是提供商问题。如果需要不同的端点,Hyperliquid RPC 端点页面列出了可用的访问选项。

  • oid:你查询的订单标识符。
  • orderStatus 判别字段:order、status、fill、rejected 或 unknownOid。
  • historicalOrders 状态:该 oid 返回的状态字符串。
  • userFills 数量:关联到该 oid 的成交笔数。
  • filledSz:关联成交的 sz 之和。
  • avgPx:名义价值除以 filledSz。
  • fee 总计:关联成交的 fee 之和。
  • closedPnl 总计:关联成交的 closedPnl 之和。

故障模式:unknownOid、部分成交、聚合与时间单位

当 cloid 从未被接受或 oid 不存在时,会出现 unknownOid。如果你生成客户端订单 ID,请验证查询的 cloid 与提交的 cloid 一致,包括大小写和前缀。在提交时被拒绝的 cloid 之后不会解析成功。

如果你只读取最新一笔成交,部分成交看起来会像一笔更小的订单。请始终对关联到该 oid 的所有成交的 sz 求和,并与原始订单大小比较。aggregateByTime 会将多笔成交合并为一行,这对报告很有用,但会隐藏每笔成交的细节;当你需要执行级粒度时,请将其设为 false。

时间字段基于纪元时间。请确认你的提供商返回的是秒还是毫秒,并在比较前进行归一化。info 接口的速率限制行为因提供商而异;请查阅提供商的速率限制文档,并在收到 429 响应时退避。Hyperliquid 资金费率机制页面展示了针对不同数据类型的类似读取路径模式。

  • unknownOid:cloid 从未被接受或 oid 不存在。
  • 部分成交:对所有成交的 sz 求和,不要只读取最新一笔。
  • aggregateByTime:合并成交;需要执行细节时设为 false。
  • 时间单位:比较前归一化秒与毫秒。
  • 速率限制:收到 429 时退避;行为因提供商而异。

只读 info 接口的局限与权衡

由于 /info 无需认证,它无法对写入进行对账。你不能用它确认签名操作是否被接受;这需要 /exchange 路径及其响应。请将 /info 视为观察接口,而非写入确认接口。

提供商缓存可能引入陈旧数据。一些提供商会在短时间内缓存 /info 响应,因此刚下的订单可能不会立即出现。经销商覆盖缺口是另一个权衡:经销商可能不会暴露所有 /info 请求类型,因此在基于其构建之前请验证覆盖范围。Hyperliquid clearinghouseState页面涵盖了保证金和仓位状态,这是与订单状态不同的读取路径。

对于生产监控,请将 /info 读取与你自己的提交日志和重试窗口结合使用。不要假设单次读取就是一致的快照。

  • 无认证意味着无法进行写入对账;请使用 /exchange。
  • 提供商缓存可能延迟新订单的可见性。
  • 经销商对 /info 请求类型的覆盖范围各不相同。
  • 将读取与提交日志和重试窗口结合使用。

订单与成交读取的故障排查清单

当读取结果看起来不对时,请按顺序逐项检查清单。首先确认请求体的 type 和参数与文档结构一致。其次,确认你正在根据 orderStatus 判别字段进行分支。第三,确认你按 oid 关联成交并对 sz 求和,而不是只读取单笔成交。

如果不一致持续存在,请比较同一 oid 的 userFills 和 historicalOrders,并重新查询 orderStatus。瞬时不一致是预期内的;持续不一致则表明存在请求或解析错误。如果轮询对你的用例来说太慢,Hyperliquid WebSocket 订阅页面涵盖了流式替代方案。

最后,检查端点本身。如果你的提供商返回错误或截断数据,请切换到已知良好的端点并重新运行结果表。

  • 验证请求体 type 和参数。
  • 根据 orderStatus 判别字段进行分支。
  • 按 oid 关联成交并对 sz 求和。
  • 重新查询 orderStatus 以解决瞬时不一致。
  • 如果错误持续存在,请切换端点。

生产环境订单与成交监控的后续步骤

构建一个小型对账服务,按计划轮询 frontendOpenOrders、historicalOrders 和 userFills,按 oid 关联,并暴露每个订单的视图。为需要立即解决的订单添加 orderStatus 查询。将读取路径与签名路径分开,这样监控中断就不会影响交易。

关于端点选择和定价,请参阅 RPC 定价以及 OnFinality Learn 中心获取相关指南。如果你需要更低延迟的更新,请评估 WebSocket 路径与轮询读取路径的配合使用。

记录你自己的结果表和重试策略,并在更换提供商时重新审视。读取路径是稳定的,但提供商在缓存和速率限制方面的行为并非如此。

  • 将读取路径与签名路径分开。
  • 轮询并按 oid 关联;为紧急查询添加 orderStatus。
  • 查看 RPC 定价和 Learn 中心获取相关指南。
  • 更换提供商时重新验证结果表。

永远不用担心基础设施

OnFinality 消除了 DevOps 的繁重工作,让您能够更聪明、更快地构建。

开始