fix: read validators from overview to capture all active stakers

Validators with only self-stake (no nominator pages) were missing.
Now reads erasStakersOverview for complete validator list.
This commit is contained in:
Kurdistan Tech Ministry committed 2026-02-18 04:50:18 +03:00
1 parent 3dc7a19dee
commit 81c6c89bfb
1 file changed
+9 -4
+9 -4
View File
@@ -41,7 +41,14 @@ export async function handleRelayBlock(block: SubstrateBlock): Promise<void> {
const activeNominators = new Set<string>(); const activeNominators = new Set<string>();
const activeValidators = new Set<string>(); const activeValidators = new Set<string>();
// Read all paged exposure entries for current era // Read all validators from overview (includes validators with only self-stake)
const overviews = await api.query.staking.erasStakersOverview.entries(currentEra);
for (const [key, ov] of overviews) {
const [, validatorId] = key.args;
activeValidators.add(validatorId.toString());
}
// Read all paged exposure entries for current era (contains nominators)
const pages = await api.query.staking.erasStakersPaged.entries(currentEra); const pages = await api.query.staking.erasStakersPaged.entries(currentEra);
for (const [key, exp] of pages) { for (const [key, exp] of pages) {
const [, validatorId] = key.args; const [, validatorId] = key.args;
@@ -49,12 +56,10 @@ export async function handleRelayBlock(block: SubstrateBlock): Promise<void> {
let exposure: any; let exposure: any;
try { try {
// Try as Option first (some runtimes wrap it)
const asOpt = exp as Option<any>; const asOpt = exp as Option<any>;
if (asOpt.isNone) continue; if (asOpt.isNone) continue;
exposure = asOpt.unwrap(); exposure = asOpt.unwrap();
} catch { } catch {
// Direct value (not wrapped in Option)
exposure = exp as any; exposure = exp as any;
} }
@@ -65,7 +70,7 @@ export async function handleRelayBlock(block: SubstrateBlock): Promise<void> {
} }
} }
// If paged API had no results, try legacy erasStakersClipped // Fallback: if overview had no results, try legacy erasStakersClipped
if (activeValidators.size === 0) { if (activeValidators.size === 0) {
const clipped = await api.query.staking.erasStakersClipped.entries(currentEra); const clipped = await api.query.staking.erasStakersClipped.entries(currentEra);
for (const [key, exposure] of clipped) { for (const [key, exposure] of clipped) {