Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

索引验证器数据

验证器数据存储在链上,可通过标准 EVM JSON-RPC 读取。您可以通过质押、惩罚和治理预编译查询当前状态,并从其事件日志中重建历史。这意味着索引器或分析平台可以通过 eth_calleth_getLogs 读取所需的一切,而无需访问节点的 stabled CLI 或 Cosmos REST。

每个数据点的来源

数据点来源如何读取
验证器名称、身份、网站质押预编译 validators()description.moniker 和相关字段
质押(绑定代币)质押预编译 validators()tokens 字段
佣金质押预编译 validators()commission 字段
质押随时间变化质押预编译事件Delegate, Unbond, Redelegate 日志
加入日期质押预编译事件CreateValidator 日志 → 块时间戳
正常运行时间惩罚预编译 getSigningInfos()(signedBlocksWindow − missedBlocksCounter) / signedBlocksWindow
投票历史(聚合)治理预编译 getTallyResult()每一项提案的计票结果
投票历史(按验证器)治理预编译事件Vote, VoteWeighted 日志,投票者 = 运营者地址

预编译地址

模块地址用途
质押0x0000000000000000000000000000000000000800验证器集合、质押、佣金、委托事件
分发0x0000000000000000000000000000000000000801奖励和佣金提款
治理0x0000000000000000000000000000000000000805提案、计票和投票日志
惩罚0x0000000000000000000000000000000000000806签名信息和正常运行时间

连接到主网(链 ID 988),地址为 https://rpc.stable.xyz。有关端点和限制,请参阅主网信息

验证器名称、质押和佣金

调用质押预编译上的 validators() 来读取当前验证器集。传入绑定状态进行过滤(例如 BOND_STATUS_BONDED)。每个条目都显示验证器的 description(包括 moniker)、tokens(绑定的质押)和 commission

// validators.ts
import { createPublicClient, http } from "viem";
 
const STAKING_PRECOMPILE = "0x0000000000000000000000000000000000000800";
 
const client = createPublicClient({
  transport: http("https://rpc.stable.xyz"),
});
 
// See the staking precompile reference for the full validators() ABI and structs.
const validators = await client.readContract({
  address: STAKING_PRECOMPILE,
  abi: stakingAbi,
  functionName: "validators",
  args: ["BOND_STATUS_BONDED", { key: "0x", offset: 0n, limit: 100n, countTotal: true, reverse: false }],
});
 
for (const v of validators[0]) {
  console.log(v.description.moniker, v.tokens.toString(), v.commission.toString());
}
StableNode-01 4500000000000000000000000 50000000000000000
StableNode-02 3900000000000000000000000 100000000000000000

tokenscommission 的值按 18 位小数进行缩放。将 commission 除以 1e18 可获得费率分数(例如 0.05 为 5%)。有关完整的 Validator 结构和 BOND_STATUS_* 值,请参阅质押预编译参考

质押随时间变化

validators() 返回一个快照。要跟踪质押的变化,请索引质押预编译的委托事件。DelegateUnbondRedelegate 带有索引的 validatorAddramount,因此您可以将每个质押变化归因于验证器和区块。

// stakeChanges.ts
import { parseAbiItem } from "viem";
 
const logs = await client.getLogs({
  address: STAKING_PRECOMPILE,
  event: parseAbiItem(
    "event Delegate(address indexed delegatorAddr, string indexed validatorAddr, uint256 amount, uint256 newShares)"
  ),
  fromBlock: 0n,
  toBlock: "latest",
});
 
console.log(`${logs.length} delegations indexed`);
1842 delegations indexed

UnbondRedelegate 遵循相同的结构,并且额外带有 completionTime。有关确切的签名,请参阅质押参考的事件部分

加入日期

验证器的加入日期是其 CreateValidator 事件的区块时间戳。该事件按验证器地址索引,因此您可以筛选单个验证器或扫描完整集合,然后使用 eth_getBlockByNumber 将每个日志的 blockNumber 解析为时间戳。

// joinDate.ts
import { parseAbiItem } from "viem";
 
const logs = await client.getLogs({
  address: STAKING_PRECOMPILE,
  event: parseAbiItem("event CreateValidator(address indexed valiAddr, uint256 value)"),
  fromBlock: 0n,
  toBlock: "latest",
});
 
for (const log of logs) {
  const block = await client.getBlock({ blockNumber: log.blockNumber });
  console.log(log.args.valiAddr, new Date(Number(block.timestamp) * 1000).toISOString());
}
0xAbc...123 2025-11-04T09:12:44.000Z
0xDef...456 2025-12-18T17:03:01.000Z

正常运行时间

使用 getSigningInfos() 从惩罚预编译 (0x...806) 读取签名信息。每条记录报告 signedBlocksWindow(滑动窗口的大小)和 missedBlocksCounter(窗口内错过的区块)。计算正常运行时间为:

正常运行时间 = (signedBlocksWindow − missedBlocksCounter) / signedBlocksWindow

一个 signedBlocksWindow10000missedBlocksCounter25 的验证器在窗口内的正常运行时间为 99.75%。这是一个滚动数字,而不是生命周期正常运行时间。要跟踪正常运行时间历史记录,请按固定间隔对计数器进行快照并存储每次读取。

投票历史

治理数据分为两层。对于提案的聚合结果,在治理预编译 (0x...805) 上调用 getTallyResult()。对于谁投了什么票,索引 VoteVoteWeighted 事件日志。这些日志中的投票者地址是验证器的运营者地址,因此您可以直接将投票与验证器关联起来。

// votes.ts
import { parseAbiItem } from "viem";
 
const GOV_PRECOMPILE = "0x0000000000000000000000000000000000000805";
 
const logs = await client.getLogs({
  address: GOV_PRECOMPILE,
  event: parseAbiItem(
    "event Vote(uint64 indexed proposalId, address indexed voter, uint8 option, uint256 weight)"
  ),
  fromBlock: 0n,
  toBlock: "latest",
});
 
console.log(`${logs.length} votes indexed across all proposals`);
38 votes indexed across all proposals

实时投票日志确认了迄今为止的所有提案(提案 #1 到 #7)。当您只需要每项提案的最终计票结果时,请使用 getTallyResult(),当您需要每个验证器的记录时,请使用事件日志。

接下来推荐

  • 质押预编译参考:查找完整的 validators()、委托方法和事件签名。
  • 创建验证器:将同步节点注册为验证器,以便它出现在上述数据中。
  • 索引器和分析:浏览已经提供标准化 Stable 数据的索引提供商。
  • 主网信息:在开始索引之前获取链 ID、RPC 端点和费率限制。