Skip to content

RyanMercier/OpenTaoAPI

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OpenTaoAPI

Open-source, self-hostable Bittensor network explorer and API. A drop-in alternative to TaoStats and TaoMarketCap.

No API-level rate limits unlike TaoStats (5 req/min free tier), your self-hosted instance has no request caps. The underlying subtensor RPC nodes (e.g. public Finney endpoints) do have their own connection limits. For heavy usage or production deployments, point OpenTaoAPI at your own subtensor node:

SUBTENSOR_ENDPOINT=ws://your-node:9944

Web UI at http://localhost:8000 | Swagger docs at http://localhost:8000/docs

Features

  • REST API with full subnet, neuron, emission, and portfolio data
  • TaoStats-compatible /miner/ endpoint for drop-in replacement
  • Web dashboard: portfolio viewer, subnets overview, miners/validators tables
  • Direct chain queries via Bittensor SDK (no third-party APIs except MEXC for price)
  • Historical data: SQLite storage with epoch-resolution snapshots via public archive node, live polling
  • Backfill script pulls directly from chain — no third-party API needed
  • In-memory caching with configurable TTLs
  • Self-hostable with Docker or conda

Quick Start

With conda

conda create -n tao python=3.11 -y
conda activate tao
pip install -r requirements.txt
uvicorn api.main:app --host 0.0.0.0 --port 8000

First startup takes ~15-20s for the initial metagraph sync. Subsequent requests are instant from cache.

With Docker

docker-compose up -d

Web UI

Page URL Description
Subnets /subnets All subnets ranked by market cap with emission %, price, volume
Miners /subnet/{netuid}/miners Miner table with incentive, stake, daily emission (alpha + USD)
Validators /subnet/{netuid}/miners then Validators tab Validator table with stake, VTrust, dividends, dominance, daily emission
Portfolio / Coldkey lookup showing total balance, per-subnet breakdown, daily yield

API Endpoints

Price

GET /api/v1/price/tao

Current TAO/USDT from MEXC. Cached 30s.

Portfolio

GET /api/v1/portfolio/{coldkey}

Cross-subnet portfolio for a coldkey. Returns total balance (TAO + USD), free balance, staked balance, and per-subnet breakdown with alpha balance, TAO equivalent, price, daily yield.

Miner (TaoStats-compatible)

GET /api/v1/miner/{coldkey}/{netuid}

Response format matches the TaoStats /api/miner/ endpoint. Includes coldkey balance, alpha balances across all subnets, hotkey details with emission data, registration status, and mining rank.

Subnets

GET /api/v1/subnets                          # All subnets with market cap, emission %, price, volume
GET /api/v1/subnet/{netuid}/info             # Subnet hyperparams and pool data
GET /api/v1/subnet/{netuid}/neurons          # Paginated neuron list (?page=1&per_page=50)
GET /api/v1/subnet/{netuid}/metagraph        # Full metagraph (?refresh=true to bypass cache)
GET /api/v1/subnet/{netuid}/miners           # Miners with daily emission (?sort=incentive&order=desc)
GET /api/v1/subnet/{netuid}/validators       # Validators with stake, dividends, daily emission

Neurons

GET /api/v1/neuron/{netuid}/{uid}             # Single neuron by UID
GET /api/v1/neuron/coldkey/{coldkey}          # All neurons for a coldkey
GET /api/v1/neuron/hotkey/{hotkey}            # Neuron by hotkey

Emissions

GET /api/v1/emissions/{netuid}/{uid}

Emission breakdown: alpha per epoch, alpha per block, TAO per block, daily/monthly estimates in alpha, TAO, and USD.

Historical Data

GET /api/v1/history/{netuid}/price?hours=720      # Alpha price history (last 30 days)
GET /api/v1/history/{netuid}/snapshots?hours=168   # Full snapshots (last 7 days)
GET /api/v1/history/{netuid}/stats                 # Data coverage stats

Historical data is stored in SQLite. The backfill script queries the public archive node (wss://archive.chain.opentensor.ai) at epoch-level resolution (~30 min intervals). The live poller adds new snapshots every 30 minutes going forward.

# Backfill last 30 days at epoch resolution (~600 snapshots per subnet)
python -m scripts.backfill --netuid 51 --days 30

# Backfill from a specific block
python -m scripts.backfill --netuid 51 --start-block 5000000

# Resume from where you left off
python -m scripts.backfill --netuid 51 --resume

# Include metagraph data (stake, emissions, neuron count — slower)
python -m scripts.backfill --netuid 51 --days 7 --full

Usage Examples

curl

# TAO price
curl http://localhost:8000/api/v1/price/tao

# Portfolio for a coldkey
curl http://localhost:8000/api/v1/portfolio/5EhrSbeGeiLgsXcJTXXaBCcqrrMubvWcykSwk4Ho6KUd5sQG

# All subnets ranked by market cap
curl http://localhost:8000/api/v1/subnets

# Subnet 51 miners sorted by incentive
curl "http://localhost:8000/api/v1/subnet/51/miners?sort=incentive&order=desc"

# Subnet 51 validators sorted by stake
curl "http://localhost:8000/api/v1/subnet/51/validators?sort=stake&order=desc"

# Miner info (TaoStats-compatible format)
curl http://localhost:8000/api/v1/miner/5GEP69yPWi3qB2tLQdsbv3Fa2JA6wH6szFNP77EqXizEufvM/51

# Emission breakdown for subnet 51, UID 40
curl http://localhost:8000/api/v1/emissions/51/40

# Historical alpha price for subnet 51 (last 30 days)
curl "http://localhost:8000/api/v1/history/51/price?hours=720"

# Historical data coverage stats
curl http://localhost:8000/api/v1/history/51/stats

Python

import httpx

BASE = "http://localhost:8000/api/v1"

# Portfolio
r = httpx.get(f"{BASE}/portfolio/5EhrSbeGeiLgsXcJTXXaBCcqrrMubvWcykSwk4Ho6KUd5sQG")
p = r.json()
print(f"Balance: {p['total_balance_tao']:.4f} TAO (${p['total_balance_usd']:.2f})")
for sn in p["subnets"]:
    print(f"  SN{sn['netuid']} {sn['name']}: {sn['balance_tao']:.4f} TAO  yield {sn['daily_yield_tao']:.4f}/day")

# Miner data (TaoStats-compatible)
r = httpx.get(f"{BASE}/miner/5GEP69yPWi3qB2tLQdsbv3Fa2JA6wH6szFNP77EqXizEufvM/51")
data = r.json()["data"][0]
print(f"Total balance: {int(data['total_balance']) / 1e9:.4f} TAO")
for hk in data["hotkeys"]:
    print(f"  UID {hk['uid']} rank #{hk['miner_rank']} emission {int(hk['emission']) / 1e9:.4f} alpha/epoch")

# Emissions
r = httpx.get(f"{BASE}/emissions/51/40")
em = r.json()
print(f"Daily: {em['daily_tao']:.4f} TAO (${em['daily_usd']:.2f})")

Configuration

All settings via environment variables (or .env file):

Variable Default Description
BITTENSOR_NETWORK finney Network: finney, testnet, local
SUBTENSOR_ENDPOINT (empty) Custom subtensor websocket URL (e.g. ws://localhost:9944). Overrides BITTENSOR_NETWORK when set. Use this to connect to your own node and avoid public RPC rate limits.
CACHE_TTL_METAGRAPH 300 Metagraph cache seconds
CACHE_TTL_PRICE 30 Price cache seconds
CACHE_TTL_DYNAMIC_INFO 120 Subnet pool data cache seconds
CACHE_TTL_BALANCE 60 Balance/stake cache seconds
ARCHIVE_ENDPOINT wss://archive.chain.opentensor.ai:443/ Archive node for historical backfill
DATABASE_PATH data/opentao.db SQLite database path for historical data
HISTORY_POLL_INTERVAL 1800 Seconds between live snapshots (0 to disable)
HISTORY_POLL_NETUIDS (empty) Comma-separated netuids to poll (empty = all active)
API_HOST 0.0.0.0 Bind address
API_PORT 8000 Port

Project Structure

OpenTaoAPI/
├── api/
│   ├── main.py                 # FastAPI app, routes, static file serving
│   ├── config.py               # Settings from environment
│   ├── routes/
│   │   ├── price.py            # TAO price from MEXC
│   │   ├── miner.py            # TaoStats-compatible miner endpoint
│   │   ├── neuron.py           # Neuron lookup by UID/hotkey/coldkey
│   │   ├── subnet.py           # Subnet info, metagraph, miners, validators
│   │   ├── emissions.py        # Emission breakdown
│   │   ├── portfolio.py        # Cross-subnet portfolio
│   │   └── history.py          # Historical data endpoints
│   ├── services/
│   │   ├── chain_client.py     # Bittensor SDK wrapper (AsyncSubtensor)
│   │   ├── price_client.py     # MEXC price feed
│   │   ├── cache.py            # In-memory TTL cache
│   │   ├── database.py         # SQLite storage for historical data
│   │   ├── metagraph_compat.py # SDK version compatibility layer
│   │   └── calculations.py     # Emission math
│   └── models/
│       └── schemas.py          # Pydantic response models
├── scripts/
│   ├── backfill.py             # Historical scraper (chain-direct)
│   └── backfill_taostats.py    # Historical scraper (TaoStats API)
├── data/
│   └── opentao.db              # SQLite database (created on first run)
├── frontend/
│   ├── index.html              # Portfolio dashboard
│   ├── subnets.html            # Subnets overview
│   └── miners.html             # Miners/validators table
├── docker-compose.yml
├── Dockerfile
├── requirements.txt
└── .env.example

How It Works

Data sources:

  • Bittensor chain via AsyncSubtensor for metagraph, balances, stake info, subnet data
  • MEXC public API for TAO/USDT price (no auth required, 500 req/10s limit)

Emission calculation:

alpha_per_day = meta.E[uid] / tempo * 7200
tao_per_day   = alpha_per_day * (pool.tao_in / pool.alpha_in)
usd_per_day   = tao_per_day * tao_price

Where meta.E[uid] is alpha per epoch, tempo is blocks per epoch (usually 360), and 7200 is blocks per day.

Validator yield is proportional to stake share: yield = emission * (my_stake / total_stake_on_hotkey).

Caching: metagraph syncs are expensive (~10-20s cold). All queries are cached in-memory with configurable TTLs. Use ?refresh=true on metagraph endpoints to force a fresh sync.

Comparison to TaoStats

Feature TaoStats OpenTaoAPI
Rate limit 5 req/min (free) None on API; RPC-limited by subtensor node (use your own node for unlimited)
API key required Yes No
Source code Closed MIT open source
Self-hostable No Yes
Miner endpoint /api/miner/{coldkey}/{netuid} /api/v1/miner/{coldkey}/{netuid} (compatible format)
Web UI Full explorer Portfolio, subnets, miners/validators
Historical data Yes Yes (SQLite, epoch-resolution via archive node)
Price source Multiple MEXC

Support

If this project is useful to you, consider supporting development:

TAO: 5EhrSbeGeiLgsXcJTXXaBCcqrrMubvWcykSwk4Ho6KUd5sQG

License

MIT

About

Open-source Bittensor network explorer API, self-hostable alternative to TaoStats and TaoMarketCap with no API-level rate limits

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors