Docs

grandpa_roundState - Hydration RPC Method

Get the current GRANDPA finality round state on Hydration. Monitor consensus progress, validator voting participation, and finality health across the Polkadot's leading DEX with $200M+ TVL, Omnipool AMM, and native HOLLAR stablecoin network.

Returns the state of the current GRANDPA finality round on Hydration when the endpoint exposes validator-round internals. GRANDPA (GHOST-based Recursive ANcestor Deriving Prefix Agreement) is the finality gadget used by many Substrate-based chains to provide deterministic finality, but some public endpoints do not surface grandpa_roundState and instead return a method-not-found style error.

Why Hydration? Build on Polkadot's leading DEX with $200M+ TVL, Omnipool AMM, and native HOLLAR stablecoin with Omnipool with reduced slippage, permissioned listings, 3M DOT DAO allocation, and 200%+ APR farm yields.

When to Use This Method

grandpa_roundState is essential for DeFi developers, liquidity providers, and DAOs requiring capital-efficient trading:

  • Finality Monitoring -- Track whether GRANDPA rounds are progressing normally or stalling on Hydration, critical for single-sided liquidity provision, cross-chain trading (SOL, KSM, tBTC), and HOLLAR decentralized stablecoin
  • Consensus Health Checks -- Detect finality delays by comparing prevote/precommit counts against the supermajority threshold weight
  • Validator Participation Analysis -- Monitor which validators are actively voting and whether the authority set has sufficient online weight
  • Authority Set Tracking -- Observe setId changes after validator set rotations to verify smooth authority transitions
  • Capability Detection -- Confirm whether the shared endpoint exposes GRANDPA round internals before you build monitoring around them

Code Examples

Bash
curl -X POST https://api-hydradx.dwellir.com/YOUR_API_KEY \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "grandpa_roundState",
    "params": [],
    "id": 1
  }'

Common Use Cases

1. Finality Health Monitoring

Periodically check whether GRANDPA rounds are progressing and alert on stalls:

JavaScript
import { ApiPromise, WsProvider } from '@polkadot/api';

async function monitorFinality(api, intervalMs = 10000) {
  let lastRound = 0;
  let lastSetId = 0;
  let stallCount = 0;

  setInterval(async () => {
    const state = await api.rpc.grandpa.roundState();
    const best = state.best;
    const round = best.round.toNumber();
    const setId = state.setId.toNumber();
    const prevoteProgress = best.prevotes.currentWeight.toNumber();
    const precommitProgress = best.precommits.currentWeight.toNumber();
    const threshold = best.thresholdWeight.toNumber();

    if (setId !== lastSetId) {
      console.log(`Authority set changed: ${lastSetId} -> ${setId}`);
      lastSetId = setId;
    }

    if (round === lastRound) {
      stallCount++;
      if (stallCount >= 3) {
        console.warn(`GRANDPA round ${round} stalled for ${stallCount} checks`);
        console.warn(`  Prevotes: ${prevoteProgress}/${threshold}`);
        console.warn(`  Precommits: ${precommitProgress}/${threshold}`);
        console.warn(`  Missing voters: ${best.precommits.missing.length}`);
      }
    } else {
      stallCount = 0;
      console.log(`Round ${round} | prevotes=${prevoteProgress}/${threshold} precommits=${precommitProgress}/${threshold}`);
    }

    lastRound = round;
  }, intervalMs);
}

2. Validator Participation Report

Generate a report of which validators are consistently missing votes:

JavaScript
async function trackMissingVoters(api, samples = 20, delayMs = 6000) {
  const missingCounts = {};

  for (let i = 0; i < samples; i++) {
    const state = await api.rpc.grandpa.roundState();
    const missing = state.best.precommits.missing;

    missing.forEach((authority) => {
      const key = authority.toString();
      missingCounts[key] = (missingCounts[key] || 0) + 1;
    });

    await new Promise((resolve) => setTimeout(resolve, delayMs));
  }

  // Sort by most frequently missing
  const sorted = Object.entries(missingCounts)
    .sort(([, a], [, b]) => b - a);

  console.log('Validator participation report:');
  sorted.forEach(([authority, count]) => {
    const missRate = ((count / samples) * 100).toFixed(1);
    console.log(`  ${authority}: missed ${count}/${samples} (${missRate}%)`);
  });

  return sorted;
}

3. Supported-Fallback Check

If the endpoint does not expose GRANDPA round internals, fall back to finalized-head tracking:

JavaScript
async function getFinalitySignal(api) {
  try {
    return { supported: true, roundState: await api.rpc.grandpa.roundState() };
  } catch (error) {
    return {
      supported: false,
      finalizedHead: (await api.rpc.chain.getFinalizedHead()).toHex(),
      message: error.message
    };
  }
}

3. Finality Lag Detection

Compare the finalized head with the best block to measure finality lag:

JavaScript
async function getFinalityLag(api) {
  const [roundState, finalizedHash, bestHeader] = await Promise.all([
    api.rpc.grandpa.roundState(),
    api.rpc.chain.getFinalizedHead(),
    api.rpc.chain.getHeader()
  ]);

  const finalizedHeader = await api.rpc.chain.getHeader(finalizedHash);
  const bestNumber = bestHeader.number.toNumber();
  const finalizedNumber = finalizedHeader.number.toNumber();
  const lag = bestNumber - finalizedNumber;

  return {
    bestBlock: bestNumber,
    finalizedBlock: finalizedNumber,
    lagBlocks: lag,
    grandpaRound: roundState.best.round.toNumber(),
    setId: roundState.setId.toNumber(),
    prevoteReached: roundState.best.prevotes.currentWeight.toNumber() >= roundState.best.thresholdWeight.toNumber(),
    precommitReached: roundState.best.precommits.currentWeight.toNumber() >= roundState.best.thresholdWeight.toNumber()
  };
}

Understanding GRANDPA Rounds

GRANDPA achieves finality through a two-phase voting protocol:

  1. Prevote Phase -- Each authority broadcasts a prevote for the highest block they consider best. Once prevotes reach the thresholdWeight (supermajority), the protocol derives the highest block that is an ancestor of all supermajority prevotes.

  2. Precommit Phase -- Authorities that observe a supermajority of prevotes issue precommits for the block derived in the prevote phase. When precommits reach the threshold, that block and all its ancestors are finalized.

  3. Authority Sets -- The setId increments each time the authority set changes (e.g., after a session rotation). A new authority set starts a new round sequence from round 1.

ConceptDescription
totalWeightSum of all authority weights in the current set
thresholdWeight⌊totalWeight × 2/3⌋ + 1 -- minimum for supermajority
Healthy roundprevotes.currentWeight >= thresholdWeight AND precommits.currentWeight >= thresholdWeight
Stalled roundNeither prevotes nor precommits reach threshold for an extended period

Error Handling

Common errors and solutions:

Error CodeDescriptionSolution
-32603Internal errorThe node may not be running the GRANDPA protocol (e.g., light client or parachain collator) -- verify node type
-32601Method not foundGRANDPA RPC is not enabled on this node -- check the node's --rpc-methods configuration
-32005Rate limit exceededReduce polling frequency or implement client-side rate limiting
Empty responseNo round dataNode may still be syncing or the GRANDPA voter has not started -- wait for sync completion