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​
Parameter | Type | Required | Description |
---|---|---|---|
blockHash | string | No | Hex-encoded block hash to query metadata at specific block. If omitted, uses the latest block |
Returns​
Field | Type | Description |
---|---|---|
result | string | Hex-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​
-
Pallets: Modules that compose the runtime
- Storage items
- Callable functions (extrinsics)
- Events
- Errors
- Constants
-
Types Registry: Type definitions for encoding/decoding
-
Extrinsic Format: Structure of transactions
-
Runtime Version: Specification version and APIs
Common Pallets​
Pallet | Description |
---|---|
System | Core blockchain functionality |
Balances | Native token management |
Staking | Validator and nominator operations |
Democracy | Governance proposals and voting |
Identity | On-chain identity management |
Proxy | Proxy account management |
Multisig | Multi-signature operations |
Use Cases​
- Transaction Construction: Encode calls with proper types
- Storage Decoding: Interpret storage query results
- Event Parsing: Decode events from blocks
- UI Generation: Build dynamic interfaces based on available calls
- 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');
}
Related Methods​
state_getStorage
- Query storage with metadatachain_getBlock
- Get block datasystem_health
- Check node statusauthor_submitExtrinsic
- Submit transactions
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