Docs

chain_getFinalizedHead - Moonbeam RPC Method

Get the finalized block hash on Moonbeam. Essential for confirmed state queries, exchange integrations, and applications requiring irreversible finality on the cross-chain connected EVM platform on Polkadot with $65M+ TVL and 100+ projects.

Returns the hash of the last finalized block on Moonbeam. Finalized blocks have been confirmed by the GRANDPA finality gadget and are guaranteed to never be reverted.

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_getFinalizedHead is critical for cross-chain dApp developers, Polkadot builders, and teams requiring multi-chain interoperability:

  • Exchange Deposits — Only credit user funds after the block has been finalized on Moonbeam
  • Transaction Confirmation — Verify transactions have achieved irreversible finality for cross-chain DeFi, multi-chain dApps, and Ethereum-to-Polkadot bridging via XCM, Axelar, LayerZero, and Wormhole
  • Safe Checkpoints — Use finalized blocks as safe anchors for indexing and state queries
  • Bridge Operations — Confirm source-chain finality before executing cross-chain transfers

Code Examples

Common Use Cases

1. Exchange Deposit Confirmation

Wait for finality before crediting deposits on Moonbeam:

JavaScript
async function waitForFinality(api, txBlockHash) {
  return new Promise((resolve) => {
    const unsub = api.rpc.chain.subscribeFinalizedHeads(async (header) => {
      const finalizedHash = await api.rpc.chain.getBlockHash(header.number);

      // Check if the transaction block has been finalized
      const finalizedNumber = header.number.toNumber();
      const txBlock = await api.rpc.chain.getBlock(txBlockHash);
      const txNumber = txBlock.block.header.number.toNumber();

      if (finalizedNumber >= txNumber) {
        console.log(`Transaction finalized at block #${txNumber}`);
        unsub();
        resolve(txBlockHash);
      }
    });
  });
}

2. Safe State Queries

Query chain state at the finalized block to avoid reading data that could be reverted:

JavaScript
async function getSafeBalance(api, address) {
  const finalizedHash = await api.rpc.chain.getFinalizedHead();
  const apiAt = await api.at(finalizedHash);
  const account = await apiAt.query.system.account(address);

  return {
    free: account.data.free.toString(),
    reserved: account.data.reserved.toString(),
    finalizedAt: finalizedHash.toHex()
  };
}

3. Finality Lag Monitor

Track the gap between best and finalized blocks for health monitoring:

JavaScript
async function monitorFinalityLag(api, threshold = 10) {
  const bestHeader = await api.rpc.chain.getHeader();
  const finalizedHash = await api.rpc.chain.getFinalizedHead();
  const finalizedHeader = await api.rpc.chain.getHeader(finalizedHash);

  const lag = bestHeader.number.toNumber() - finalizedHeader.number.toNumber();
  console.log(`Finality lag: ${lag} blocks`);

  if (lag > threshold) {
    console.warn(`WARNING: Finality lag (${lag}) exceeds threshold (${threshold})`);
  }

  return lag;
}

Error Handling

Error CodeDescriptionSolution
-32603Internal errorNode may be syncing or GRANDPA not running — retry with backoff
-32601Method not foundVerify the node supports this RPC method
-32005Rate limit exceededImplement client-side rate limiting