subnetInfo_getMetagraph - Bittensor RPC Method
Retrieve the SCALE-encoded metagraph for a specific Bittensor subnet. The metagraph is the core network topology data structure containing all validators, miners, stakes, and weights.
Overview
The subnetInfo_getMetagraph method returns the SCALE-encoded metagraph for a specific Bittensor subnet identified by its netuid. The metagraph is the most important data structure in the Bittensor network -- it represents the complete topology of a subnet, including every registered neuron (validator or miner), their stakes, trust scores, incentive values, emission distributions, and weight matrices.
The metagraph is the foundation for:
- Understanding how a subnet's consensus is operating
- Monitoring validator and miner performance
- Analyzing emission flows and incentive distributions
- Building subnet explorer dashboards and analytics tools
Each subnet in Bittensor has its own metagraph. The root network (netuid 0) coordinates emissions across all subnets, while application subnets (netuid 1+) each run specialized AI/ML tasks.
Parameters
| Position | Name | Type | Required | Description |
|---|---|---|---|---|
| 0 | netuid | u16 | Yes | The subnet identifier. Use 0 for the root network, 1 for the first application subnet, etc. |
| 1 | at | BlockHash | No | Optional block hash to query at a specific block. Pass null for the latest state |
Response
The result is a JSON array of SCALE bytes. When decoded using Bittensor runtime type definitions, the metagraph contains:
| Field | Type | Description |
|---|---|---|
netuid | u16 | The subnet identifier |
n | u16 | Number of neurons currently registered in the subnet |
block | u64 | Block number this metagraph was captured at |
hotkeys | Vec<AccountId32> | Hotkey addresses for every neuron, indexed by UID |
coldkeys | Vec<AccountId32> | Coldkey (owner) addresses for every neuron |
uids | Vec<u16> | Neuron UIDs |
stake | Vec<u64> | Total stake (RAO) for each neuron. Divide by 1e9 for TAO |
trust | Vec<u16> | Trust scores (0--65535 scaled, divide by 65535 for float) |
consensus | Vec<u16> | Consensus scores (0--65535 scaled) |
incentive | Vec<u16> | Incentive scores (0--65535 scaled). Higher = better-performing miner |
dividends | Vec<u16> | Dividend scores (0--65535 scaled). Higher = more validator rewards |
emission | Vec<u64> | Emissions per neuron (RAO per tempo) |
validator_trust | Vec<u16> | Validator-specific trust scores (how much other validators trust this one) |
validator_permit | Vec<bool> | Whether each neuron has a validator permit |
active | Vec<bool> | Whether each neuron is currently active |
last_update | Vec<u64> | Last block each neuron set weights |
rank | Vec<u16> | Rank scores (0--65535 scaled) |
weights | Vec<Vec<(u16, u16)>> | Weight matrix: each neuron's weight assignments to other neurons (uid, weight) |
bonds | Vec<Vec<(u16, u16)>> | Bond matrix: validator bonds to miners (uid, bond) |
axons | Vec<AxonInfo> | Network endpoint info (IP, port, protocol) for each neuron |
SCALE Decoding
The metagraph is one of the largest SCALE-encoded structures in Bittensor. Understanding the decoding process is important for working with it correctly.
Using @polkadot/api: Register the Bittensor type definitions including MetagraphInfo, AxonInfo, and related types. The AxonInfo struct typically contains: version (u32), ip (u128), port (u16), ip_type (u8), protocol (u8), placeholder1 (u8), placeholder2 (u8). IP addresses are stored as u128 and need conversion -- for IPv4, the value fits in 4 bytes.
Using bittensor Python SDK: The recommended approach is bt.subtensor(network='finney').metagraph(netuid=N), which returns a Metagraph object with NumPy arrays for all vector fields (e.g., meta.S for stake, meta.I for incentive, meta.E for emission).
Score normalization: All u16 score fields (trust, consensus, incentive, dividends, rank, validator_trust) are scaled to the range 0--65535. Divide by 65535 to get float values between 0.0 and 1.0. The bittensor SDK does this conversion automatically.
Weight matrix format: Each entry in weights is a sparse vector of (target_uid, weight) pairs. The weight values are u16 (0--65535). This represents how validators evaluate miners -- a higher weight means the validator considers that miner to be performing better.
Code Examples
Using SubstrateExamples
Decode with Python (bittensor SDK)
import requests
import json
url = 'https://api-bittensor-mainnet.n.dwellir.com/YOUR_API_KEY'
# Fetch metagraph for subnet 1
payload = {
'jsonrpc': '2.0',
'method': 'subnetInfo_getMetagraph',
'params': [1, None],
'id': 1
}
response = requests.post(url, json=payload)
result = response.json()
if result.get('result'):
scale_bytes = result['result']
print(f'Metagraph SCALE data size: {len(scale_bytes)} bytes')
else:
print('No metagraph found for this subnet')
# To decode with bittensor SDK:
# import bittensor as bt
# sub = bt.subtensor(network='finney')
# meta = sub.metagraph(netuid=1)
# print(f"Subnet 1: {meta.n} neurons")
# print(f"Top validator stake: {meta.S[meta.S.argmax()]:.2f} TAO")
# print(f"Total emissions: {meta.E.sum():.4f} TAO/tempo")Full Python metagraph analysis
import bittensor as bt
import numpy as np
sub = bt.subtensor(network='finney')
meta = sub.metagraph(netuid=1)
print(f"=== Subnet 1 Metagraph (block {meta.block}) ===")
print(f"Neurons: {meta.n}")
print(f"Total stake: {meta.S.sum():,.2f} TAO")
print(f"Total emissions: {meta.E.sum():,.6f} TAO/tempo")
# Identify validators (those with validator permits)
validator_mask = np.array(meta.validator_permit)
validator_uids = np.where(validator_mask)[0]
miner_uids = np.where(~validator_mask)[0]
print(f"Validators: {len(validator_uids)}, Miners: {len(miner_uids)}")
# Top 5 validators by stake
top_validators = np.argsort(meta.S[validator_mask])[::-1][:5]
print("\nTop 5 validators by stake:")
for idx in top_validators:
uid = validator_uids[idx]
print(f" UID {uid}: stake={meta.S[uid]:,.2f} TAO, "
f"vtrust={meta.Tv[uid]:.4f}, dividends={meta.D[uid]:.4f}")
# Top 5 miners by incentive
top_miners = np.argsort(meta.I[~validator_mask])[::-1][:5]
print("\nTop 5 miners by incentive:")
for idx in top_miners:
uid = miner_uids[idx]
print(f" UID {uid}: incentive={meta.I[uid]:.4f}, "
f"trust={meta.T[uid]:.4f}, emission={meta.E[uid]:.6f} TAO")
# Weight analysis: how concentrated are validator weights?
for uid in validator_uids[:3]:
weights = meta.W[uid]
non_zero = weights[weights > 0]
if len(non_zero) > 0:
print(f"\nValidator UID {uid}: sets weights on {len(non_zero)} miners")
print(f" Max weight: {non_zero.max():.4f}, Mean: {non_zero.mean():.4f}")Decode with JavaScript
import { ApiPromise, WsProvider } from '@polkadot/api';
const provider = new WsProvider('wss://api-bittensor-mainnet.n.dwellir.com/YOUR_API_KEY');
const api = await ApiPromise.create({ provider });
// Fetch metagraph for subnet 1
const metagraph = await api.rpc.subnetInfo.getMetagraph(1);
console.log('Raw metagraph size:', metagraph.toHex().length, 'bytes');
// With proper Bittensor type definitions registered,
// the result auto-decodes to structured fields:
// console.log('Neurons:', metagraph.n.toNumber());
// console.log('Hotkeys:', metagraph.hotkeys.map(h => h.toHuman()));
await api.disconnect();Query with cURL
curl -X POST https://api-bittensor-mainnet.n.dwellir.com/YOUR_API_KEY \
-H 'Content-Type: application/json' \
-d '{
"jsonrpc": "2.0",
"method": "subnetInfo_getMetagraph",
"params": [1, null],
"id": 1
}'Error Handling
| Error Scenario | Behavior | Recommended Action |
|---|---|---|
| Invalid netuid | Returns null or empty result | Use subnetInfo_getSubnetsInfo to list valid netuids first |
| Netuid 0 (root network) | Returns the root metagraph (different structure) | Root metagraph has validators but no traditional miners |
| Very large subnet | Response may be several MB | Increase HTTP timeout; consider getSelectiveMetagraph for targeted queries |
| Invalid block hash | Returns JSON-RPC error | Verify the block hash exists on chain |
| Node not fully synced | May return incomplete or stale metagraph | Check system_health before querying |
Performance considerations: Metagraphs for large subnets (256+ neurons) can exceed 1 MB in SCALE-encoded form. If you only need data for specific neurons, use subnetInfo_getSelectiveMetagraph to reduce payload size. Cache metagraph data and refresh once per tempo for most use cases.
Common Use Cases
- Subnet analytics — Build dashboards showing neuron counts, emission distributions, stake concentrations, and consensus health for each subnet.
- Validator monitoring — Track validator trust, consensus scores, and weight-setting patterns to detect anomalies or poor performance.
- Miner monitoring — Monitor miner incentive scores, rank changes, and emission earnings over time.
- Weight analysis — Analyze the weight matrix to understand how validators evaluate miners and detect potential gaming or collusion.
- Staking decisions — Use metagraph data to identify high-performing validators before delegating TAO.
- Research — Study incentive dynamics, consensus convergence, and network topology evolution across subnets.
- Axon discovery — Find miner/validator endpoints for direct network communication.
Related Methods
subnetInfo_getAllMetagraphs— Get metagraphs for all subnets in one callsubnetInfo_getSelectiveMetagraph— Get metagraph data filtered by specific neuron UIDssubnetInfo_getMechagraph— Get mechagraph for a subnet (mechanism-level view)subnetInfo_getSubnetsInfo— Get subnet configuration infosubnetInfo_getDynamicInfo— Get dynamic subnet info (emissions, registration costs)neuronInfo_getNeuron— Get detailed info for a specific neuron by UID
subnetInfo_getMechagraph - Bittensor RPC Method
Retrieve the SCALE-encoded mechagraph for a specific subnet and mechanism ID on Bittensor. Used for advanced subnet analytics and mechanism-level performance monitoring.
subnetInfo_getSelectiveMechagraph - Bittensor RPC Method
Retrieve SCALE-encoded mechagraph data filtered by specific neuron UIDs for a Bittensor subnet. Enables targeted mechanism queries without fetching the full mechagraph.