Parameters
Fetch the leader schedule for the epoch containing this slot
Commitment level (processed, confirmed, finalized)
Only return results for this validator identity (base-58 encoded)
Response
Slot at which the request was processed
Dictionary of validator identities to their assigned leader slots
Code Examples
Basic Request
curl https://rpc.orbitflare.com -X POST -H "Content-Type: application/json" -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getLeaderSchedule"
}'
Request for Specific Validator
curl https://rpc.orbitflare.com -X POST -H "Content-Type: application/json" -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getLeaderSchedule",
"params": [{
"identity": "VALIDATOR_IDENTITY"
}]
}'
Using web3.js
import { Connection } from '@solana/web3.js';
const connection = new Connection('https://rpc.orbitflare.com');
// 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
};
}
Notes
- Returns the leader schedule for the current or specified epoch
- Can filter to show only a specific validator’s slots
- Leader slots are assigned to validators based on stake weight
- The schedule is fixed for the duration of an epoch
- Response includes the slot at which the request was processed
Best Practices
- Use appropriate commitment level based on your needs
- Filter by validator identity when only interested in specific validators
- Cache results when appropriate to reduce RPC load
- Monitor for changes in leader schedule
- Use in conjunction with other validator-related methods
Common Errors
Code | Message | Solution |
---|
-32601 | Method not found | Verify you’re connected to a Solana RPC node |
-32602 | Invalid params | Check slot and identity parameters |
-32007 | Schedule information unavailable | Node may be bootstrapping or syncing |
Use Cases
-
Validator Analysis
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)
};
}
-
Leader Schedule Monitoring
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 Planning
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
};
}