Docs

chain_subscribeFinalizedHeads - Moonbeam RPC Method

Subscribe to finalized block headers on Moonbeam. Real-time WebSocket notifications for blocks that have achieved GRANDPA finality — essential for exchanges, bridges, and applications requiring irreversibility on the cross-chain connected EVM platform on Polkadot with $65M+ TVL and 100+ projects.

Subscribe to receive notifications when blocks are finalized on Moonbeam. Finalized blocks are guaranteed to never be reverted by the GRANDPA finality gadget, making this the safest way to track confirmed state changes.

Why Moonbeam? Build on the cross-chain connected EVM platform on Polkadot with $65M+ TVL and 100+ projects with full EVM compatibility on Polkadot, native XCM cross-chain messaging, 10K+ TPS, 24% staking APR, and $0.015 transaction costs.

When to Use This Method

chain_subscribeFinalizedHeads is critical for cross-chain dApp developers, Polkadot builders, and teams requiring multi-chain interoperability:

  • Exchange Deposits — Only credit funds after finalization for cross-chain DeFi, multi-chain dApps, and Ethereum-to-Polkadot bridging via XCM, Axelar, LayerZero, and Wormhole
  • Bridge Operations — Wait for finality before executing cross-chain transfers
  • Critical State Changes — Ensure irreversibility before acting on important transactions
  • Compliance Workflows — Record-keeping that requires provably irreversible state

Code Examples

Bash
# WebSocket subscription (requires wscat or similar tool)
wscat -c wss://api-moonbeam.n.dwellir.com/YOUR_API_KEY -x '{
  "jsonrpc": "2.0",
  "method": "chain_subscribeFinalizedHeads",
  "params": [],
  "id": 1
}'

Common Use Cases

1. Exchange Deposit Watcher

Watch for finalized transfers and credit user accounts on Moonbeam:

JavaScript
async function watchDeposits(api, depositAddresses) {
  const unsub = await api.rpc.chain.subscribeFinalizedHeads(async (header) => {
    const blockHash = header.hash;
    const block = await api.rpc.chain.getBlock(blockHash);
    const apiAt = await api.at(blockHash);
    const events = await apiAt.query.system.events();

    // Check for transfer events in the finalized block
    events.forEach((record) => {
      const { event } = record;
      if (event.section === 'balances' && event.method === 'Transfer') {
        const [from, to, amount] = event.data;
        if (depositAddresses.includes(to.toString())) {
          console.log(`Finalized deposit: ${amount} from ${from} to ${to}`);
          // Credit user account — this block will never be reverted
        }
      }
    });
  });

  return unsub;
}

2. Finality Lag Tracker

Monitor the gap between best and finalized blocks:

JavaScript
async function trackFinalityLag(api) {
  let bestNumber = 0;

  api.rpc.chain.subscribeNewHeads((header) => {
    bestNumber = header.number.toNumber();
  });

  api.rpc.chain.subscribeFinalizedHeads((header) => {
    const finalizedNumber = header.number.toNumber();
    const lag = bestNumber - finalizedNumber;

    console.log(`Best: #${bestNumber} | Finalized: #${finalizedNumber} | Lag: ${lag} blocks`);

    if (lag > 10) {
      console.warn('WARNING: High finality lag detected — GRANDPA may be stalling');
    }
  });
}

3. Cross-Chain Bridge Relay

Relay finalized headers to a bridge contract:

JavaScript
async function relayFinalizedHeaders(api, bridgeContract) {
  const unsub = await api.rpc.chain.subscribeFinalizedHeads(async (header) => {
    const headerData = {
      number: header.number.toNumber(),
      stateRoot: header.stateRoot.toHex(),
      extrinsicsRoot: header.extrinsicsRoot.toHex(),
      parentHash: header.parentHash.toHex()
    };

    console.log(`Relaying finalized header #${headerData.number}`);
    await bridgeContract.submitHeader(headerData);
  });

  return unsub;
}

Finality Lag

Finalized blocks typically lag behind the best block by a few blocks due to GRANDPA consensus requirements. This lag is normal and ensures Byzantine fault tolerance. The typical lag is 2-3 blocks under healthy network conditions.

Error Handling

Error CodeDescriptionSolution
-32603Internal errorNode may be syncing or GRANDPA not running — retry connection
-32601Method not foundVerify the node supports WebSocket subscriptions
-32005Rate limit exceededReduce subscription count per connection
Connection closedWebSocket disconnectedImplement automatic reconnection with backoff