跳转到主要内容

参数

slot
number
获取包含此 slot 的 epoch 的领导者计划
config
object

响应

result
object

代码示例

基本请求

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
  };
}

注意事项

  1. 返回当前或指定 epoch 的领导者计划
  2. 可以过滤仅显示特定验证者的 slot
  3. 领导者 slot 根据质押权重分配给验证者
  4. 计划在 epoch 期间是固定的
  5. 响应包含处理请求时的 slot

最佳实践

  1. 根据需求使用适当的 commitment 级别
  2. 当只关心特定验证者时按验证者身份过滤
  3. 在适当时缓存结果以减少 RPC 负载
  4. 监控领导者计划的变化
  5. 结合其他验证者相关方法使用

常见错误

错误码消息解决方案
-32601Method not found验证是否连接到 Solana RPC 节点
-32602Invalid params检查 slot 和 identity 参数
-32007Schedule information unavailable节点可能正在启动或同步中

用例

  1. 验证者分析
    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)
      };
    }
    
  2. 领导者计划监控
    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;
      }
    }
    
  3. 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
      };
    }