Taostats App Architecture
Always visible (header)
- price (+/- % change), mcap, volume
- universal search for address, hash, extrinc, block hash etc.
- delegate app launched (will be replaced with full wallet launcher)
- buy tao (multiple sub links)
- corcel
- timezone (set EVERYTHING to UTC and then let user set local timezone if they chose)
core landing
- stats: price, mc, 24h vol, circ. supply, tot. supply, vali apr, stake apr, finalised blocks, signed extrinsics, total accounts, transfers
- charts: historical price/vol (+trading view), historical total/active accounts, historical staked/free issuance
Following sections are core, but i feel need to be sumarised in easy to digest block on the homepage, with links through to full page section. Will give fill details for each below.
==================
Subnets & Emissions
Summary: top 5 subnets with name and emissions, tao recycled in 24h
Emissions
- chart: emissions breakdown by subnet (historical + indicator of subnet dereg/reg)
- emissions assignment by validator (current! this might change in modification of emissions assignment by foundation. we build for now, plan for future). This is actually a complex set of data to show neatly, we can discuss options, current implementatino is on the front page of taostats.
Subnets
Single Subnet
- subnet specs: name, reg date, reg history, emissions %, emissions (t/24), emissions (total t)
- subnet info: github link, dev, discord, additional links, description, hardware reqs (miner/validator)
- metagraph
- reg data: reg price chart (7 days), reg cost, blocks until next reg, regs per interval, last regs table
- dereg data: last dereg incentive, historical dereg incentive/emissions
- distributions: miner incentive distribution chart (include uid for each data point), coldkey distribution, ip distribution.
- recycle data: recycled tao/24, total recycled tao, historical graph.
- historical vtrust: all valid, + network mean
- historical incenitve: high, low, mean (keys not in immunity only)
==================
Validators
Validators Main
- performance over last 7 days (nom/24h/Kt) or all validators (top 10 by default, interactive toggles)
- full vali list of those in sn0 with >=1024 stake: name, stake (24h change), nominators (24h change), nom/24h/Kt, val/24h, network %, logo, hotkey, short desc.
- sync names with delegates.json --> https://github.com/opentensor/bittensor-delegates --> https://github.com/opentensor/bittensor-delegates/blob/main/public/delegates.json
Single Validator
Combination of:
- https://x.taostats.io/validator/5Hddm3iBFD2GLT5ik7LZnT3XJUnRnN8PoeCFgGQgawUVKNm8
- https://taostats.io/validators/taostats/ So
- all the blockchain elements from x
- from taostats we need a by subnet view for an overview which is visible in a single page for: updated, vtrust, and then expandable for performance metrics of historical: updated, emissions, vtrust
==================
Accounts
Accounts Main
- table list: address, rank, free, delegated, total (don't think we need last updated as they should all be up to date).
- filters: pagination (10,25,50,100), Balance (100,500,1k,5k,10k,50k,100k,)
Accounts Single
==================
Transfers
Most recent transfers, and link to full transfers list. Number of transfers in last 24h/7d/30d/
Transfers Main
Transfers Single
==================
Extrinsics
(does this need to be on front page, i think not) Most recent extrinsics Number of extrinsics in last 24h/7d/30d
Extrinsics Main
Extrinsics Single
==================
Blocks
Blocks Main
Blocks Single
==================
Delegation
The purpose of the delegation summary is to see the general movement of tao in and out of nominees, allowing a user to easily see if there is more of a flow towards delegating or undelgating in the previous 24h/7d/30d which allows a guage of the sentiment of holders of tao.
Delegation Main
Delegation actions are listed with filters that allow easy separation of large single movements of tao 100,500,1k,10k,50k. You can also filter by nominee/validator and/or search by a given address to isolate all delegation for that account.
Delegation Single
A single delegation even is similar to a transaction and I am not sure we need a stand alone page for this - but it is useful to have as a direct link as a delegation proof of action from our (or 3rd party) delegation app.
==================
User Dashboard (mystats)
- you can enter any key into this to use it in a non-identifiable way. Else user encouraged to create account and login to add accounts for long term monitoring. Gatekeep some features for logged in users to encourage singup. You can used the dahsboard as a logged in user by entering your addresses, but you DO NOT have to connect the wallets in any way, there is no interaction, you are simply entering addresses to follow in your dash.
For User
- single multiple account balance, stake, growth from delegation in 24h/7d/30d, change from transfers in 24h/7d/30d
- downloadable CSV for the above data + link to API for more complex interactions
- for multiple accounts you need to sign up
For Validator
- if the key entered above is a validator hotkey from the delegates json, then validator params are shown (this means ANYONE can monitor their chosen validator or any other validaotrs if they choose) - you can also select the validator from a dropdown of validators in delegates.json.
For Miner
- enter coldkey to map out all assocated hotkeys across all subnets
- detailed statistics for performance and earning under that coldkey
- historcal registrations for ALL hotkeys (including no longer regsitered) under that coldkey, including tao recycle costs
- current performance of keys in subnets, earning, incentive, position, alerts for bottom percentile (colour coding for health)
- filter by subnet
==================
Tokenomics
- emissions schedule
- halvening schedule
- dynamic next havlvening date countdown
- halvening delay from last 24h/7d/30d recycle
- current issuance
- confirmation of no pre-mine with proof of first blocks of Kusangi
==================
Network Statistics
- wallet size breakdown
- holder rank/size chart
- NVL/NPL chart
- transaction volume
==================
Infrastructure
-
CLoudflare tunnels for exposing and securing all the services behind taost.at domain.
-
Cloudflare R2 for all archive / files:
-
Sentry
https://sentry.io/organizations/taostats/projects/: Centralized errors agregator where we can monitor and get alerted for indexer and other services. -
Services Monitoring
https://monitoring.taost.at/status/taostats: Monitoring of all the services related to TaoStats like RPC node, endpoints, ... -
GitHub Org
https://github.com/TaoStat -
Internal Doc
https://internal-doc.taost.at: Hosted on Cloudflare and password protected, request to add email for new participants.
GCP
- GKE ( hosted in BE region )
- Cloudflare Worker
- Bitternsor archive node
- Monitoring deployment
The K8S deployments are available in the private Github
Subscriptions
- Sentry ( Free 15 days)
- Cloudflare ( Free )
- GCP ( metered )
Archives Nodes Deployment
Current public endpoints:
- Finney: wss://finney.taost.at
- Kusanagi: wss://kusanagi.taost.at
- Nakamoto: wss://nakamoto.taost.at
Nakamoto:
- Download and extract the archive from cloudflare R2 inside /data
- Run the k8s deployment for nakamoto link
Kusanagi
- Deploy to kubernetes from the pre-made deployment link
- When done downloading the archive, run the cleanup job
Finney:
- Deploy to kubernetes from the pre-made deployment link
API Endpoints (WIP)
Overview
This document provides a list of API endpoints for a blockchain explorer. These endpoints allow users to query information about blocks, transactions, addresses, and other blockchain-related data.
API Endpoints
Blocks
-
GET /blocks- Description: Retrieve a list of recent blocks. - Parameters: -limit(optional, number of blocks to return) -
GET /blocks/{blockHash}- Description: Retrieve details of a specific block by its hash. - Parameters: -blockHash(hash of the block) -
GET /blocks/height/{blockHeight}- Description: Retrieve details of a block by its height. - Parameters: -blockHeight(height of the block)
Transactions
-
GET /extrinsic/{extrinsicHAsh}- Description: Retrieve an extrinsic associated with a specific hash. It contain all the events included and the state of them.
-
GET /extrinsics?startbloc=1234&endblock=345&limit=50- Description: Retrieve a list of extrinsic in the block range, if not defined it return the last 50 extrinsic. This need pagination
- Parameters:
startbloc(the end block we want the transactions to be included not required)endblock(the end block we want the transactions to be included not required )limit(the maximum number of events we want to return, if not set we return 50)
- Parameters:
- Description: Retrieve a list of extrinsic in the block range, if not defined it return the last 50 extrinsic. This need pagination
-
GET /extrinsics/{palletName}/{extrinsicName}?startbloc=1234&endblock=345&limit=50- Description: Retrieve a list of extrinsic in the block range, if not defined it return the last 50 extrinsic. This need pagination
- Parameters:
palletName(the pallet name we want the extrinsic from, required )extrinsicName(the extrinsic name we want to retrieve, required)startbloc(the end block we want the transactions to be included not required)endblock(the end block we want the transactions to be included not required )limit(the maximum number of events we want to return, if not set we return 50)
- Parameters:
- Description: Retrieve a list of extrinsic in the block range, if not defined it return the last 50 extrinsic. This need pagination
Addresses
-
GET /addresses- Description: the list of all the chain address balance paginated.
-
GET /address/{address}- Description: Retrieve information about a specific address, including balance and transaction history.
- Parameters:
address(the blockchain address)
-
GET /address/{address}/balance- Description: Retrieve the balance of a specific address in realtime using the blockchain.
- Parameters:
address(the blockchain address)
- Parameters:
- Description: Retrieve the balance of a specific address in realtime using the blockchain.
-
GET /address/{address}/transactions?startbloc=1234&endblock=345&limit=50- Description: Retrieve transactions associated with a specific address. If start and end block is not set we pass the last 50 transaction. This need pagination
- Parameters:
address(the blockchain address)start(the end block we want the transactions to be included not required)endblock(the end block we want the transactions to be included not required )limit(the maximum number of events we want to return, if not set we return 50)
- Parameters:
- Description: Retrieve transactions associated with a specific address. If start and end block is not set we pass the last 50 transaction. This need pagination
Pallets Information
-
GET /{palletId}/consts?block=123- Description: Return a list of const item metadata for constant items of the specified palletId.
- Parameters:
block(the block we want the const to be included not required if not set we return the last record know)
-
GET /{palletId}/events?block=123&limit=50- Description: Returns a list of event item metadata for event items of the specified palletId.
- Parameters:
block(the block we want the event to be included not required if not set we return the last record know)limit(the maximum number of events we want to return, if not set we return 50)
-
GET /{palletId}/events/{eventId}- Description: Returns an event item of the specified palletId.
- Parameters:
eventId(the id of the event)
-
GET /{palletId}/events?block=123&limit=50- Description: Returns a list of event item metadata for event items of the specified palletId.
- Parameters:
block(the block we want the event to be included not required if not set we return the last record know)limit(the maximum number of events we want to return, if not set we return 50)
Subnets Information
-
GET /subnets?block=123- Description: Return a list of all the subnets at the latest block with basic informations ( Active Keys, Active Validators, Active Dual Miners / Validators, Active Miners, Registration Cost)
- Parameters:
block(the block we want the const to be included not required if not set we return the last record know)
- Parameters:
- Description: Return a list of all the subnets at the latest block with basic informations ( Active Keys, Active Validators, Active Dual Miners / Validators, Active Miners, Registration Cost)
-
GET /{subnets}/{subnetId}/miners?block=123- Description: Return a list of all miners active in the subnet at a defined block.- Parameters:
subnetId(the id of the subnet we want to query)block(the block we want the const to be included not required if not set we return the last record know)
- Parameters:
-
GET /{subnets}/{subnetId}/infos?block=123- Description: Return a list of all miners active in the subnet at a defined block.-
Parameters:
subnetId(the id of the subnet we want to query)block(the block we want the const to be included not required if not set we return the last record know)
-
Data Returned:
- subnet specs:
- name
- reg date
- emissions %
- emissions (t/24)
- emissions (total t)
- subnet info:
- github link
- dev
- discord
- additional links ( exchanges )
- description
- hardware reqs (miner/validator)
- metagraph
- reg data:
- reg price chart (7 days)
- reg cost
- blocks until next reg
- regs per block
- last regs table
- dereg data:
- last dereg incentive
- historical dereg incentive/emissions
- distributions:
- miner incentive distribution chart (include uid for each data point)
- coldkey distribution
- ip distribution.
- recycle data: recycled tao/24, total recycled tao, historical graph.
- historical vtrust: all valid, + network mean
- historical incenitve: high, low, mean (keys not in immunity only)
{ "subnet_specs": { "name": "", "reg_date": "", "emissions_percentage": 0, "emissions_per_day": 0, "total_emissions": 0 }, "subnet_info": { "github_link": "", "developer": [], "discord": "", "additional_links": { "exchanges": "" }, "description": "", "hardware_requirements": { "miner": "", "validator": "" } }, "metagraph": {}, "registration_data": { "reg_price_chart_7_days": [], "reg_cost": 0, "blocks_until_next_reg": 0, "regs_per_block": 0, "last_regs_table": "" }, "deregistration_data": { "last_dereg_incentive": 0, "historical_dereg_incentive_emissions": "" }, "distributions": { "miner_incentive_distribution_chart": { "uid": "" }, "coldkey_distribution": "", "ip_distribution": "" }, "recycle_data": { "recycled_tao_per_day": 0, "total_recycled_tao": 0, "historical_graph": [] }, "historical_vtrust": { "all_valid": "", "network_mean": 0 }, "historical_incentive": { "high": 0, "low": 0, "mean": 0 } } - subnet specs:
-
-
GET /miners?block=123- Description: Return a list of all miners active at a defined block.- Parameters:
block(the block we want the const to be included not required if not set we return the last record know)
- Parameters:
-
GET /miner/{minerId}?block=123- Description: Return a list of all miners active at a defined block.- Parameters:
minerId(the the miner id we want to return the infos from)block(the block we want the const to be included not required if not set we return the last record know)
- Parameters:
Validators Information
GET /validators?block=123
- Description: Return a list of all validators active at a defined block.
- Parameters:
- block (the block we want the const to be included not required if not set we return the last record know)
-
GET /validator?validatorId=5F4tQyWrhfGVcNhoqeiNsR6&block=123
- Description: Return a single validator active at a defined block.
- Parameters:
- validatorId ( the id of the validator we want the informations )
- block (the block we want the const to be included not required if not set we return the last record know)
Network Statistics
-
GET /stats- Description: Retrieve blockchain network statistics, such as total number of transactions, average block time, price, total supply, Market Cap, Circulating Supply, 24h Volume, Finalised blocks, Validating APY, Signed extrinsic, Staking APY, Total Accounts, Active accounts ( account that are active the last X days it will give a chain health), Staked Supply, Total transfers. -
GET /totalsupply- Description: just give the supply for CMC as a simple number, no formatting
Node Information
GET /node/info- Description: Retrieve information about the blockchain node, such as software version, connection count, etc.
Search
GET /search- Description: General search endpoint to find blocks, transactions, or addresses. - Parameters:query(search query, could be block hash, transaction hash, or address)
Miscellaneous
GET /price- Description: Retrieve current price and historical price data for the blockchain's native cryptocurrency.
Notes
- All endpoints return data in JSON format.
- Parameters should be passed as query parameters in the URL.
Errors
- Standard HTTP response codes are used for errors.
400 Bad Requestfor invalid requests.404 Not Foundfor non-existent resources.500 Internal Server Errorfor server errors.
Explorer
Frontend
Backend
It’s a custom solution based on the subsquid libraries. That solution gives us the full control over the data we want to store in the database, which means it would be possible to add new fields/tables if needed or upgrade to the new and more efficient libraries in the future (if they arrive). The repo si hosted here: https://github.com/taostat/indexer
Ongoing
Frontend:
- Preferd tech Stack:
- React
- Next.js
- Jotai ( state management )
Backend:
- API:
- Tech Stack: Rust see discussion
- Axum ( using Loco for flexibility and all the auth, could be a good fit to make one API for all the planned apps / miner monitoring )
- Open API Schema
- Swagger Explorer for testing to be deployed on the same domain
- Do we need to compile and create various SDK for integration ?
- Should we create a path like /accounting or /reports inside the API so we can request reports for various thing like exporting the account data, transactions, historical of validators, ... OR we want to let user create it using the API?
- Add a system for notifications, maybe only in the app so user are a bit "forced" to download / register ( email ? ) to it and enter the system. A system for the user to be able to create their own alerts for example if a specific validator is offline for a long time, if miner perform bellow the average, ...
- DB:
- Undefined yet, testing:
- BigQuery ( GCP but need to check the costs we should try to stay away from it as cost can rise fast )
- Mariadb
- Postgresql
- Undefined yet, testing:
- Caching for the API via something like Redis
- Rate Limit
Idea to get more data:
- A mining monitoring module that miners can install and have more in dept data directly in the app/mobile app. It will also help getting data for the explorer.