Skip to main content

chain_subscribeNewHeads - JSON-RPC Method

Description​

Creates a subscription to receive notifications about new block headers as they are produced. This JSON-RPC method is only available via WebSocket connections and provides real-time updates about the blockchain state.

Parameters​

This method does not require any parameters.

Returns​

FieldTypeDescription
subscriptionstringSubscription ID for managing the subscription

Subscription Updates​

Each notification contains a block header with:

FieldTypeDescription
parentHashstringHash of the parent block
numberstringBlock number (hex-encoded)
stateRootstringRoot of the state trie
extrinsicsRootstringRoot of the extrinsics trie
digestobjectDigest items including consensus messages

Request Example​

{
"jsonrpc": "2.0",
"method": "chain_subscribeNewHeads",
"params": [],
"id": 1
}

Response Example​

{
"jsonrpc": "2.0",
"result": "0x1234567890abcdef",
"id": 1
}

Subscription Update Example​

{
"jsonrpc": "2.0",
"method": "chain_newHead",
"params": {
"subscription": "0x1234567890abcdef",
"result": {
"parentHash": "0x4a84d1c5fc5c725b26a3c8e126d8f65e1c2d2dc5b3fcbc91e67e7637fa136789",
"number": "0x123456",
"stateRoot": "0x8f7a82e2e0f3e73f5e232e68de18144f6e7a52a6db39bb5e5e3d9ca6e1f72845",
"extrinsicsRoot": "0x2e6f9a7d2c4b3e1a8f5c6d9e4b1a7c3f8e5d2a9b6c4e1f8a5d3c2b9e7f6a4d38",
"digest": {
"logs": [
"0x0642414245b501013c0000009d2ef70f00000000"
]
}
}
}
}

Code Examples​

JavaScript (WebSocket)​

const WebSocket = require('ws');

const subscribeToNewHeads = () => {
const ws = new WebSocket('wss://api-polkadot.n.dwellir.com');

ws.on('open', () => {
// Subscribe to new heads
ws.send(JSON.stringify({
jsonrpc: '2.0',
method: 'chain_subscribeNewHeads',
params: [],
id: 1
}));
});

ws.on('message', (data) => {
const response = JSON.parse(data);

// Handle subscription confirmation
if (response.id === 1) {
console.log('Subscribed with ID:', response.result);
}

// Handle new block headers
if (response.method === 'chain_newHead') {
const header = response.params.result;
const blockNumber = parseInt(header.number, 16);
console.log(`New block #${blockNumber}:`, header.parentHash);

// Process block header
processNewBlock(header);
}
});

// Clean up subscription on disconnect
ws.on('close', () => {
console.log('WebSocket connection closed');
});

return ws;
};

const processNewBlock = (header) => {
// Implement your block processing logic
const blockNumber = parseInt(header.number, 16);
console.log(`Processing block ${blockNumber}`);

// Example: Check for specific events in digest
if (header.digest && header.digest.logs) {
header.digest.logs.forEach(log => {
// Process consensus messages
console.log('Digest log:', log);
});
}
};

Python (websockets)​

import asyncio
import json
import websockets

async def subscribe_new_heads():
uri = "wss://api-polkadot.n.dwellir.com"

async with websockets.connect(uri) as websocket:
# Subscribe to new heads
subscribe_msg = json.dumps({
"jsonrpc": "2.0",
"method": "chain_subscribeNewHeads",
"params": [],
"id": 1
})
await websocket.send(subscribe_msg)

subscription_id = None

async for message in websocket:
data = json.loads(message)

# Handle subscription confirmation
if data.get("id") == 1:
subscription_id = data["result"]
print(f"Subscribed with ID: {subscription_id}")

# Handle new block headers
elif data.get("method") == "chain_newHead":
header = data["params"]["result"]
block_number = int(header["number"], 16)
print(f"New block #{block_number}")

await process_block(header)

async def process_block(header):
"""Process new block header"""
block_number = int(header["number"], 16)

# Example: Track block production rate
print(f"Block {block_number} parent: {header['parentHash']}")
print(f"State root: {header['stateRoot']}")

# Monitor for reorganizations
# Store parent hash and detect if chain reorgs

# Run the subscription
asyncio.run(subscribe_new_heads())

TypeScript (@polkadot/api)​

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

async function subscribeToHeads() {
const provider = new WsProvider('wss://api-polkadot.n.dwellir.com');
const api = await ApiPromise.create({ provider });

// Subscribe to new headers
const unsubscribe = await api.rpc.chain.subscribeNewHeads((header) => {
console.log(`New block #${header.number.toNumber()}`);
console.log(` Parent: ${header.parentHash.toHex()}`);
console.log(` State Root: ${header.stateRoot.toHex()}`);
console.log(` Extrinsics Root: ${header.extrinsicsRoot.toHex()}`);

// Process digest items
header.digest.logs.forEach((log, index) => {
console.log(` Digest[${index}]: ${log.toHex()}`);
});

// Example: Monitor block production time
const blockTime = new Date();
console.log(` Received at: ${blockTime.toISOString()}`);
});

// Unsubscribe after some time
setTimeout(async () => {
unsubscribe();
await api.disconnect();
}, 60000); // 1 minute
}

subscribeToHeads().catch(console.error);

Block Production Monitoring​

class BlockMonitor {
constructor(wsUrl) {
this.wsUrl = wsUrl;
this.lastBlock = null;
this.blockTimes = [];
}

async start() {
const ws = new WebSocket(this.wsUrl);

ws.on('open', () => {
ws.send(JSON.stringify({
jsonrpc: '2.0',
method: 'chain_subscribeNewHeads',
params: [],
id: 1
}));
});

ws.on('message', (data) => {
const response = JSON.parse(data);

if (response.method === 'chain_newHead') {
const header = response.params.result;
const blockNumber = parseInt(header.number, 16);
const now = Date.now();

if (this.lastBlock) {
const timeDiff = now - this.lastBlock.timestamp;
this.blockTimes.push(timeDiff);

// Calculate average block time
const avgTime = this.blockTimes.reduce((a, b) => a + b, 0) / this.blockTimes.length;
console.log(`Block ${blockNumber} - Time since last: ${timeDiff}ms, Avg: ${avgTime.toFixed(0)}ms`);
}

this.lastBlock = {
number: blockNumber,
timestamp: now,
hash: header.parentHash
};
}
});
}
}

Use Cases​

  1. Block Explorer: Display real-time blockchain updates
  2. Transaction Monitoring: Watch for transaction inclusion
  3. Network Health: Monitor block production rate
  4. Reorganization Detection: Detect and handle chain reorgs
  5. Event Listening: Watch for specific on-chain events

Notes​

  • WebSocket connection required (not available over HTTP)
  • Headers are sent for all blocks, not just finalized ones
  • Use chain_subscribeFinalizedHeads for finalized blocks only
  • Remember to handle reconnection logic for production systems
  • Unsubscribe when no longer needed to free resources