参数
获取包含此 slot 的 epoch 的领导者计划
响应
代码示例
基本请求
复制
curl https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY -X POST -H "Content-Type: application/json" -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getLeaderSchedule"
}'
请求特定验证者
复制
curl https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY -X POST -H "Content-Type: application/json" -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getLeaderSchedule",
"params": [{
"identity": "VALIDATOR_IDENTITY"
}]
}'
使用 web3.js
复制
import { Connection } from '@solana/web3.js';
const connection = new Connection('https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY');
// Get leader schedule
const leaderSchedule = await connection.getLeaderSchedule();
console.log('Leader schedule:', leaderSchedule.value);
// Get validator's leader slots
async function getValidatorLeaderSlots(validatorIdentity: string) {
const schedule = await connection.getLeaderSchedule({
identity: validatorIdentity
});
if (!schedule.value) {
return {
hasSlots: false,
slots: []
};
}
const slots = schedule.value[validatorIdentity] || [];
return {
hasSlots: slots.length > 0,
slots,
totalSlots: slots.length,
context: schedule.context
};
}
注意事项
- 返回当前或指定 epoch 的领导者计划
- 可以过滤仅显示特定验证者的 slot
- 领导者 slot 根据质押权重分配给验证者
- 计划在 epoch 期间是固定的
- 响应包含处理请求时的 slot
最佳实践
- 根据需求使用适当的 commitment 级别
- 当只关心特定验证者时按验证者身份过滤
- 在适当时缓存结果以减少 RPC 负载
- 监控领导者计划的变化
- 结合其他验证者相关方法使用
常见错误
| 错误码 | 消息 | 解决方案 |
|---|---|---|
| -32601 | Method not found | 验证是否连接到 Solana RPC 节点 |
| -32602 | Invalid params | 检查 slot 和 identity 参数 |
| -32007 | Schedule information unavailable | 节点可能正在启动或同步中 |
用例
-
验证者分析
复制
interface ValidatorMetrics { identity: string; totalSlots: number; slotDistribution: number[]; averageGap: number; maxGap: number; minGap: number; } async function analyzeValidatorSlots( validatorIdentity: string ): Promise<ValidatorMetrics> { const schedule = await connection.getLeaderSchedule({ identity: validatorIdentity }); if (!schedule.value || !schedule.value[validatorIdentity]) { throw new Error('No leader slots found for validator'); } const slots = schedule.value[validatorIdentity].sort((a, b) => a - b); const gaps = []; for (let i = 1; i < slots.length; i++) { gaps.push(slots[i] - slots[i - 1]); } return { identity: validatorIdentity, totalSlots: slots.length, slotDistribution: slots, averageGap: gaps.reduce((sum, gap) => sum + gap, 0) / gaps.length, maxGap: Math.max(...gaps), minGap: Math.min(...gaps) }; } -
领导者计划监控
复制
interface ScheduleAlert { type: 'change' | 'gap' | 'distribution'; message: string; validator: string; details: any; } class ScheduleMonitor { private previousSchedule: Map<string, number[]> = new Map(); async monitorSchedule( maxGap: number = 100, minSlots: number = 10 ): Promise<ScheduleAlert[]> { const schedule = await connection.getLeaderSchedule(); const alerts: ScheduleAlert[] = []; for (const [validator, slots] of Object.entries(schedule.value)) { const previousSlots = this.previousSchedule.get(validator) || []; // Check for significant changes if (previousSlots.length > 0) { const change = Math.abs(slots.length - previousSlots.length); if (change > minSlots) { alerts.push({ type: 'change', message: `Validator ${validator} slot count changed by ${change}`, validator, details: { previous: previousSlots.length, current: slots.length } }); } } // Check for large gaps const sortedSlots = [...slots].sort((a, b) => a - b); for (let i = 1; i < sortedSlots.length; i++) { const gap = sortedSlots[i] - sortedSlots[i - 1]; if (gap > maxGap) { alerts.push({ type: 'gap', message: `Large gap of ${gap} slots found for validator ${validator}`, validator, details: { gap, slot1: sortedSlots[i - 1], slot2: sortedSlots[i] } }); } } this.previousSchedule.set(validator, slots); } return alerts; } } -
Epoch 规划
复制
interface EpochPlan { currentEpoch: number; nextEpoch: number; slotsPerEpoch: number; validatorSlots: Map<string, number>; slotDistribution: Map<number, string[]>; } async function planEpoch(): Promise<EpochPlan> { const schedule = await connection.getLeaderSchedule(); const epochInfo = await connection.getEpochInfo(); const validatorSlots = new Map<string, number>(); const slotDistribution = new Map<number, string[]>(); for (const [validator, slots] of Object.entries(schedule.value)) { validatorSlots.set(validator, slots.length); for (const slot of slots) { if (!slotDistribution.has(slot)) { slotDistribution.set(slot, []); } slotDistribution.get(slot)!.push(validator); } } return { currentEpoch: epochInfo.epoch, nextEpoch: epochInfo.epoch + 1, slotsPerEpoch: epochInfo.slotsInEpoch, validatorSlots, slotDistribution }; }