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

通过 Info API 读取 Hyperliquid 金库权益

通过 info API 读取 Hyperliquid 金库状态和账户金库持仓,将份额与总价值对账,并推导份额价格表现,而非直接使用原始权益。

TL;DR

Hyperliquid 金库是一个资金池账户:存款人获得份额,其经济头寸等于份额乘以份额价格,而不是存储的美元余额。info API 通过两条不同的读取路径暴露这一点:账户范围的读取返回用户的份额数量和可归属权益,金库范围的读取返回金库的聚合状态,包括总价值和存款人集合。由于存款、取款和交易盈亏都会同时改变总价值和流通份额,仅用原始权益计算的表现指标会将现金流与收益混为一谈;唯一能隔离管理者表现的方法是份额价格变化。本文展示如何读取这两条路径,将份额与总份额对账,推导每份价值,随时间进行快照,并区分导致空结果、缺失行或内部不一致响应的故障类别。

金库机制与份额会计模型

Hyperliquid 金库是一个资金池账户,其他用户通过存入资金来换取份额。存款人的经济头寸是份额乘以份额价格,而不是存储的美元余额,因此账户侧的读取返回的是份额数量和权益数字,必须与金库自身的总额进行对账,而不能当作独立数字处理。Hyperliquid 金库的 Hyperliquid 金库文档 描述了这种份额模型以及由此产生的存款人会计。

这一点很重要,因为对账户金库行的简单读取看起来像余额,但实际上是一个派生量。如果你将返回的权益视为存储值,并将其与永续合约或现货权益相加,就会重复计算抵押品。正确的心智模型是:金库持有抵押品,存款人持有对其一部分的索取权。

  • 金库 = 资金池账户;存款人 = 份额持有人。
  • 存款人权益 = 份额 × 份额价格,而不是存储余额。
  • 金库总价值和流通份额都会随存款、取款和交易盈亏变动。
  • 字段名称和附加字段以文档为准 / 因 API 版本而异;请对照实时响应进行验证。

两条读取路径:账户范围与金库范围

info 端点暴露了两条不同的读取路径,回答不同的问题。账户范围的读取返回调用者或被监视地址在金库中的持仓,包括该地址的份额数量和可归属权益。金库范围的读取返回金库的聚合状态,包括总价值和存款人集合。想要了解“这个金库表现如何”的调用者和想要了解“这个用户的风险敞口是什么”的调用者不能使用同一个请求。

Hyperliquid info 端点的 Hyperliquid info 端点文档 列出了请求类型及其参数。请将确切的请求名称和响应字段视为以文档为准 / 因 API 版本而异,并在硬编码之前对照实时响应进行确认。Hyperliquid RPC 端点(RPC Assistant) 页面是选择端点的有用起点,而 Hyperliquid clearinghouseState:保证金与清算 一文涵盖了常与金库权益混淆的永续合约侧读取。

  • 账户范围读取:用户的资金库持仓、份额数量、可归属权益。
  • 金库范围读取:金库聚合状态、总价值、存款人集合。
  • 不要用一个请求回答两个问题。
  • 对照实时响应确认请求名称和字段。

金库权益与现货、永续账户权益

clearinghouseState 报告永续账户价值和保证金,现货余额是另一个独立界面,而金库持仓又是第三种东西。在不进行抵押品去重的情况下将它们相加会导致重复计算并产生错误的总数,这是金库仪表盘中最常见的错误。金库的抵押品已经反映在金库的总价值中;存款人的索取权是其中的一部分,而不是额外的余额。

如果你需要合并视图,请明确决定你是要报告金库总价值、存款人可归属权益,还是两者并列。只要分别标注且从不相加,同时报告两者是可以的。Hyperliquid 资金费率机制Hyperliquid 预言机价格与构建者拍卖信息 文章涵盖了同样容易与金库状态混淆的相邻读取。

  • clearinghouseState = 永续账户价值和保证金。
  • 现货余额 = 独立界面。
  • 金库持仓 = 第三个界面;不去重不要相加。
  • 分别标注金库总价值和存款人可归属权益。

推导份额价格并隔离管理者表现

金库的每份价值等于金库总价值除以流通份额。由于这两个数量都会随存款、取款和交易盈亏变动,仅用原始权益计算的表现指标会将存款与收益混为一谈。读取者必须计算份额价格变化,而不是权益变化,这是唯一能将管理者表现与现金流隔离的指标。

存款会同时增加总价值和流通份额,因此存款时份额价格不变。交易收益会增加总价值而不改变份额,因此份额价格上升。这就是为什么份额价格变化是有意义的表现信号,而权益变化不是。Hyperliquid 金库的 Hyperliquid 金库文档 描述了使这一点成立的份额模型。

  • 份额价格 = 金库总价值 / 流通份额。
  • 存款:总价值和份额都上升;份额价格不变。
  • 交易收益:总价值上升,份额不变;份额价格上升。
  • 表现 = 份额价格变化,而不是权益变化。

在 Node.js 中读取金库聚合状态和账户持仓

下面的脚本通过 info 端点读取金库的聚合状态和账户的金库持仓,将份额数量与总份额对账,推导每份价值,进行快照,并打印表格。每个请求使用一次 POST,并将两次读取分开,使对账过程明确。请将端点和请求名称替换为你的 API 版本所记录的值。

由于 info 端点回答的是当前状态,脚本的快照存储就是历史记录器。按计划运行它,并将每次读取追加到文件或数据库;单次读取不是表现测量。

// Node.js 18+ (global fetch). Replace endpoint and request names with your API version.
const ENDPOINT = process.env.HL_INFO_ENDPOINT || 'https://api.hyperliquid.xyz/info';
const VAULT = process.env.HL_VAULT_ADDRESS || '0xVaultAddress';
const ACCOUNT = process.env.HL_ACCOUNT_ADDRESS || '0xAccountAddress';

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

function num(x) {
  const n = Number(x);
  return Number.isFinite(n) ? n : null;
}

async function main() {
  // Vault-scoped read: aggregate state. Request name varies by API version.
  const vaultState = await info({ type: 'vaultDetails', vaultAddress: VAULT });
  // Account-scoped read: this address's vault positions.
  const accountState = await info({ type: 'userVaultEquities', user: ACCOUNT });

  const totalValue = num(vaultState?.totalValue ?? vaultState?.value);
  const totalShares = num(vaultState?.totalShares ?? vaultState?.shares);
  const sharePrice = (totalValue !== null && totalShares) ? totalValue / totalShares : null;

  const rows = Array.isArray(accountState) ? accountState : (accountState?.vaultEquities || []);
  const row = rows.find(r => (r.vaultAddress || r.vault || '').toLowerCase() === VAULT.toLowerCase());
  const accountShares = row ? num(row.shares ?? row.vaultShares) : null;
  const accountEquity = row ? num(row.equity ?? row.vaultEquity) : null;

  const reconciledEquity = (accountShares !== null && sharePrice !== null)
    ? accountShares * sharePrice : null;

  const snapshot = {
    ts: new Date().toISOString(),
    vault: VAULT,
    totalValue, totalShares, sharePrice,
    accountShares, accountEquity, reconciledEquity
  };

  console.log('vault | totalValue | totalShares | sharePrice | accountShares | accountEquity | reconciledEquity');
  console.log([
    snapshot.vault, snapshot.totalValue, snapshot.totalShares,
    snapshot.sharePrice, snapshot.accountShares,
    snapshot.accountEquity, snapshot.reconciledEquity
  ].join(' | '));

  // Append to your own snapshot store; this is the historian.
  const fs = require('fs');
  fs.appendFileSync('vault-snapshots.ndjson', JSON.stringify(snapshot) + '\n');
}

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

将份额数量与总份额对账

对账步骤是大多数仪表盘出错的地方。账户范围的读取返回份额数量和权益数字;金库范围的读取返回总价值和总份额。如果 accountShares × sharePrice 与 accountEquity 不近似相等,要么两次读取跨越了状态转换,要么字段名称与文档不同。将不匹配视为重新读取的信号,而不是取平均值的数字。

由于 info 端点回答的是当前状态,单次快照应尽可能接近原子性地获取。如果你的客户端可以在没有其他工作的情况下连续发出两次读取,请这样做;如果不能,请记录时间戳,并丢弃间隔大到对你的用例有影响的快照。

  • accountShares × sharePrice 应近似等于 accountEquity。
  • 不匹配 = 重新读取,而不是取平均值。
  • 尽可能接近原子性地进行两次读取。
  • 记录时间戳,并丢弃间隔过大的快照。

构建时间序列并衡量表现

单次份额价格读取不是表现测量。读取者必须采样并存储读数,并且由于 info 端点回答的是当前状态,读取者自己的快照存储就是历史记录器。测量方法是可复现的:以固定频率采样,存储每个快照,并计算窗口内的份额价格变化。

下表是一个模板,请用你自己端点的结果填充。不要将你的数字与任何其他人的数字进行比较;推导出的表现取决于你的采样频率,并且在不同实现之间不可比较。

  • 以固定频率采样(例如每 5 分钟)。
  • 存储每个快照及其时间戳。
  • 计算窗口内的份额价格变化。
  • 在报告结果的同时报告采样频率。
Results Table (fill with your own endpoint's readings)

| Timestamp (UTC) | Vault | Total Value | Total Shares | Share Price | Account Shares | Account Equity | Reconciled Equity |
|-----------------|-------|-------------|--------------|-------------|----------------|----------------|-------------------|
|                 |       |             |              |             |                |                |                   |
|                 |       |             |              |             |                |                |                   |
|                 |       |             |              |             |                |                |                   |

Derived performance over the window:
  sharePriceChange = (lastSharePrice - firstSharePrice) / firstSharePrice
  cadence = <your sampling interval>
  note = not comparable across implementations

故障类别与故障排除

在调试之前先区分故障类别。不存在的金库标识符返回空结果而不是错误。在某个金库中没有持仓的账户返回缺失行而不是零。字段名称与文档不同的 API 版本返回可解析但产生 null 的响应。内部不一致的响应是在状态转换期间跨越两次调用读取的,这就是为什么单次快照应尽可能接近原子性地获取。

对于订单级别的故障,Hyperliquid API 错误处理与订单拒绝 一文涵盖了拒绝面。关于端点选择和连接性,请参阅 Hyperliquid RPC 端点(RPC Assistant)Hyperliquid 网络页面

  • 空结果:金库标识符不存在。
  • 缺失行:账户在该金库中没有持仓。
  • 解析后为 null:字段名称与文档不同。
  • 响应不一致:读取跨越了状态转换。
  • 对账失败时重新读取,而不是取平均值。

局限性与权衡

本文不构成投资建议。推导出的表现取决于读取者自己的采样频率,因此在不同实现之间不可比较。金库费用和管理者份额条款必须从金库自身的配置中读取,而不能从权益或份额价格变动中推断。字段可用性取决于提供商和版本,因此此处显示的请求名称和响应字段以文档为准 / 因 API 版本而异,必须对照实时响应进行验证。

info 端点回答的是当前状态,因此任何历史视图都是读取者自己的构建。这种构建的质量取决于其采样频率和对缺口的处理。如果你需要合并的投资组合视图,请明确决定如何避免在永续、现货和金库界面之间重复计算抵押品。

  • 不构成投资建议。
  • 推导出的表现取决于采样频率,在不同实现之间不可比较。
  • 金库费用和管理者份额条款来自金库自身的配置。
  • 字段可用性取决于提供商和版本。
  • 历史视图是读取者自己的构建。

集成后续步骤

首先对照你的 API 版本的实时响应确认请求名称和响应字段。然后将两条读取路径接入你的客户端,添加对账检查,并开始以固定频率采样。一旦你有了几天的快照,计算窗口内的份额价格变化,并在报告结果的同时报告采样频率。

对于生产访问,请查看 RPC 定价API 服务 页面,并浏览 OnFinality Learn 中心 以获取相邻的 Hyperliquid 读取内容。Hyperliquid 网络页面 列出了你需要的端点和网络详情。

  • 对照实时响应确认请求名称和字段。
  • 接入两条读取路径并添加对账检查。
  • 以固定频率采样并存储快照。
  • 计算份额价格变化并报告采样频率。
  • 查看定价和 API 服务页面以获取生产访问。

永远不用担心基础设施

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

开始