Bittensor Data: Index TAO Staking, Subnets, and Weight Commits
Index Bittensor's staking calls, subnet activity, weight commits, and TAO transfers as extrinsics, delivered to your own database. Real-time and complete historical data, no node to run.
Bittensor is an open network where independent subnets produce digital commodities such as compute, inference, storage, and prediction, and the chain pays participants in TAO in proportion to the value they contribute. Miners produce the commodity, validators score the miners, subnet creators define the incentive mechanism, and stakers back validators with TAO. You can read how the project frames it at bittensor.com and in the Bittensor docs.
The chain itself is built on Substrate, so all of that shows up as extrinsics, not EVM logs: subtensorModule.addStakeLimit and subtensorModule.removeStake for staking, subtensorModule.commitTimelockedWeights for validator weights, commitments.setCommitment for per-subnet commitments, plus EVM transactions carried as ethereum.transact. Indexing Co covers Bittensor in a single pipeline, lets you shape those extrinsics into rows keyed by subnet, and delivers them to your own PostgreSQL, warehouse, or webhook. Real-time and full history, with no node to operate.
Why Bittensor data is hard
netuid, signed by the staker's coldkey, with amounts and limit prices as positional arguments. Building a view of who backs which validator on which subnet means parsing every addStake, addStakeLimit, removeStake, and removeStakeFullLimit variant correctly.
commitments.setCommitment, commitTimelockedWeights, and commitTimelockedMechanismWeights calls can fill a block. Keeping up with the head while filtering that traffic down to what you need is a real throughput problem.
mevShield.submitEncrypted with an opaque ciphertext payload, and other calls are wrapped in utility.batchAll or utility.forceBatch. A naive counter of top-level methods misreads what users did.
ethereum.transact extrinsics with an EIP1559 envelope. Native subtensor calls and EVM activity sit side by side in the same block and need different handling.
What Indexing Co delivers for Bittensor
Stand up and maintain the Subtensor stack yourself.
- Run a Bittensor archive node or rent a Substrate RPC.
- Decode extrinsics against runtime metadata across runtime upgrades.
- Map positional args for every staking and weights call variant.
- Build backfill, head-following, and delivery from scratch.
One pipeline sources, decodes, and delivers Bittensor to your store.
- Every extrinsic with method, signer, nonce, hash, and decoded args.
- Shaped by your JavaScript transform: stake flows by hotkey and netuid.
- Lands in your PostgreSQL, BigQuery, warehouse, or webhook.
- Real-time delivery plus complete backfilled history. No node, no RPC babysitting.
What you can index
| Bittensor extrinsic data | For example |
|---|---|
| TAO staking | subtensorModule.addStakeLimit, removeStake, removeStakeFullLimit by hotkey and netuid |
| Validator weights | subtensorModule.commitTimelockedWeights, commitTimelockedMechanismWeights |
| Subnet commitments | commitments.setCommitment per netuid |
| TAO transfers | balances.transferKeepAlive |
| EVM transactions | ethereum.transact envelopes with target, value, and calldata |
A transform, not a subgraph
You write the transform in JavaScript, not AssemblyScript, and change it without re-indexing from block zero. Indexing Co runs your function over each block server-side: pick the extrinsics you care about and return rows for your destination.
// Indexing Co transform: TAO staking per subnet on Bittensor
function transform(block) {
const results = [];
const stakeCalls = ['addStake', 'addStakeLimit', 'removeStake', 'removeStakeLimit', 'removeStakeFullLimit'];
for (const ext of block.extrinsics || []) {
const [pallet, call] = ext.method.split('.');
if (pallet !== 'subtensorModule' || !stakeCalls.includes(call)) continue;
const [hotkey, netuid] = ext.args;
results.push({
chain: block._network,
block: block.blockNumber,
extrinsic_hash: ext.hash,
call,
coldkey: ext.signer,
hotkey,
netuid: Number(netuid),
args: ext.args,
});
}
return results;
}
Bittensor with Indexing Co
You want full control of infrastructure and have the team to operate a Bittensor archive node, track runtime upgrades to the subtensor pallet, and build backfill and delivery in-house.
You want Bittensor staking, weight commits, and transfers delivered to your own database as clean rows keyed by subnet, with real-time plus complete history and no node to run.
Related Reading
- AI and Data Science Infrastructure
- DePIN Data Infrastructure
- Polkadot Hub Data
- Indexing Co vs SubQuery
FAQ
Can I track stake flows per subnet?
Yes. Staking extrinsics carry the hotkey and subnet netuid as arguments and the coldkey as signer. The transform above turns each addStakeLimit, removeStake, and similar call into a row you can aggregate by subnet or validator.
What is in each Bittensor block?
The block number, block hash, and header, plus an array of extrinsics. Each extrinsic carries its index, hash, signer, nonce, method in pallet.call form, and its decoded arguments.
What about MEV Shield encrypted submissions?
They arrive as mevShield.submitEncrypted extrinsics with the ciphertext as the argument, so the payload itself is unreadable. The block author decrypts it and includes the inner call as its own extrinsic, which your transform sees like any other call.
Do I need to run a Bittensor node?
No. Indexing Co sources Bittensor blocks for you, including full history, so you never operate an archive node or chase runtime metadata changes yourself.
Where does the Bittensor data go?
Into your own destination: PostgreSQL, BigQuery, a warehouse, or a webhook. You define the output schema and own the storage.
Get Started
Index Bittensor in minutes. Set up your first staking or subnet pipeline without running a node.