Skip to main content

state_getMetadata

Description​

Retrieves the runtime metadata for the Polkadot blockchain. Metadata contains essential information about the runtime's pallets, storage items, calls, events, errors, and types. This information is crucial for properly encoding transactions and decoding storage values.

Parameters​

ParameterTypeRequiredDescription
blockHashstringNoHex-encoded block hash to query metadata at specific block. If omitted, uses the latest block

Returns​

FieldTypeDescription
resultstringHex-encoded SCALE-encoded metadata

Request Example​

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

Response Example​

{
"jsonrpc": "2.0",
"result": "0x6d6574610e7c1853797374656d1853797374656d04...",
"id": 1
}

Code Examples​

cURL​

# Get current metadata
curl https://api-polkadot.n.dwellir.com \
-X POST \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "state_getMetadata",
"params": [],
"id": 1
}'

# Get metadata at specific block
curl https://api-polkadot.n.dwellir.com \
-X POST \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "state_getMetadata",
"params": ["0x5d83e66b61701da7b6e3e8c9d8e2e57e1391e3e58e677b30e1f391d568c9ca24"],
"id": 1
}'

JavaScript (fetch)​

const getMetadata = async (blockHash = null) => {
const params = blockHash ? [blockHash] : [];

const response = await fetch('https://api-polkadot.n.dwellir.com', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
jsonrpc: '2.0',
method: 'state_getMetadata',
params: params,
id: 1
})
});

const data = await response.json();
return data.result;
};

// Get and decode metadata (requires @polkadot/types)
import { Metadata } from '@polkadot/types';
import { TypeRegistry } from '@polkadot/types';

const metadataHex = await getMetadata();
const registry = new TypeRegistry();
const metadata = new Metadata(registry, metadataHex);

console.log('Runtime version:', metadata.version);
console.log('Pallets:', metadata.pallets.map(p => p.name.toString()));

Python (requests)​

import requests
import json
from scalecodec import ScaleBytes, ScaleDecoder
from substrateinterface import SubstrateInterface

def get_metadata(block_hash=None):
url = "https://api-polkadot.n.dwellir.com"
headers = {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
}

params = [block_hash] if block_hash else []

payload = {
"jsonrpc": "2.0",
"method": "state_getMetadata",
"params": params,
"id": 1
}

response = requests.post(url, headers=headers, data=json.dumps(payload))
data = response.json()

if "error" in data:
raise Exception(f"RPC Error: {data['error']}")

return data["result"]

# Using substrate-interface for decoding
substrate = SubstrateInterface(
url="https://api-polkadot.n.dwellir.com",
extra_headers={"Authorization": "Bearer YOUR_API_KEY"}
)

# Access metadata
metadata = substrate.get_metadata()
print(f"Metadata version: {metadata.version}")
print(f"Number of pallets: {len(metadata.pallets)}")

# List all pallets
for pallet in metadata.pallets:
print(f"Pallet: {pallet.name}")
print(f" - Calls: {len(pallet.calls or [])}")
print(f" - Events: {len(pallet.events or [])}")
print(f" - Storage: {len(pallet.storage or [])}")

TypeScript (@polkadot/api)​

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

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

// Access metadata directly
const metadata = await api.rpc.state.getMetadata();

console.log('Metadata:', {
version: metadata.version,
pallets: metadata.pallets.map(p => p.name.toString())
});

// Access specific pallet metadata
const systemPallet = metadata.pallets.find(
p => p.name.toString() === 'System'
);

if (systemPallet) {
console.log('System pallet:', {
index: systemPallet.index.toNumber(),
calls: systemPallet.calls.isSome ?
systemPallet.calls.unwrap().map(c => c.name.toString()) : [],
events: systemPallet.events.isSome ?
systemPallet.events.unwrap().map(e => e.name.toString()) : [],
storage: systemPallet.storage.isSome ?
systemPallet.storage.unwrap().items.map(s => s.name.toString()) : []
});
}

// Use metadata for transaction construction
const tx = api.tx.balances.transfer(
'RECIPIENT_ADDRESS',
1000000000000
);

console.log('Transaction metadata:', {
section: tx.meta.section,
method: tx.meta.method,
args: tx.meta.args.map(a => a.name.toString())
});

await api.disconnect();
}

Metadata Structure​

Key Components​

  1. Pallets: Modules that compose the runtime

    • Storage items
    • Callable functions (extrinsics)
    • Events
    • Errors
    • Constants
  2. Types Registry: Type definitions for encoding/decoding

  3. Extrinsic Format: Structure of transactions

  4. Runtime Version: Specification version and APIs

Common Pallets​

PalletDescription
SystemCore blockchain functionality
BalancesNative token management
StakingValidator and nominator operations
DemocracyGovernance proposals and voting
IdentityOn-chain identity management
ProxyProxy account management
MultisigMulti-signature operations

Use Cases​

  1. Transaction Construction: Encode calls with proper types
  2. Storage Decoding: Interpret storage query results
  3. Event Parsing: Decode events from blocks
  4. UI Generation: Build dynamic interfaces based on available calls
  5. Chain Analysis: Understand runtime capabilities and constraints

Working with Metadata​

Decoding Metadata​

// Using @polkadot/api
const api = await ApiPromise.create({ provider });

// Metadata is automatically handled
const pallets = api.runtimeMetadata.pallets;
pallets.forEach(pallet => {
console.log(`Pallet ${pallet.name}:`, {
storage: pallet.storage?.items.length || 0,
calls: pallet.calls?.length || 0,
events: pallet.events?.length || 0
});
});

Version Compatibility​

// Check metadata version
const metadata = await api.rpc.state.getMetadata();
const version = metadata.version;

if (version < 14) {
console.warn('Metadata version outdated, some features may not work');
}

Notes​

  • Metadata is SCALE-encoded and requires proper decoding
  • Metadata changes with runtime upgrades
  • Cache metadata for performance - it's large (typically 500KB+)
  • Different metadata versions have different structures
  • Always use matching metadata version for encoding/decoding