{"message":"Welcome to the API. See available endpoints below:","endpoints":[{"path":"/updateVotes","method":"POST","description":"Updates or registers votes for a given coldkey address. The coldkey must hold alpha tokens. Includes vote cooldown management to prevent gaming of the incentive mechanism.","inputs":{"body":{"signature":"string (Polkadot/Substrate signature of the message)","message":"string (formatted as 'poolsStr|blockNumStr')","address":"string (coldkey address of the voter)"},"message_format_details":{"poolsStr":"string (formatted as 'poolAddress1,weight1;poolAddress2,weight2;...') - max 10 pools","blockNumStr":"string (current Bittensor block number)"}},"outputs":{"success":"boolean","message":"string (e.g., 'Votes updated')","pools":"Array<{ address: string, weight: number }> (normalized pools if successful)","error":"string (description of error if success is false)"},"cooldown_features":{"base_cooldown":"72 minutes after vote changes","progressive_system":"Cooldown doubles for frequent changes (72m → 144m → 288m → 576m)","max_cooldown":"8 hours maximum cooldown cap","cooldown_reset":"24 hours of inactivity resets change count back to 72m","enhanced_errors":"Detailed error messages show remaining cooldown time and exact unlock time","first_time_voting":"No cooldown for new voters"}},{"path":"/claimAddress","method":"POST","description":"Claims an Ethereum address for a hotkey address. The hotkey must be registered in the subnet and hold alpha tokens.","inputs":{"body":{"signature":"string (Polkadot/Substrate signature of the message)","message":"string (formatted as 'ethSig|ethAddrPayload|hotkeyPayload|blockNumStr|ethSigner')","address":"string (hotkey address)"},"message_format_details":{"ethSig":"string (Ethereum signature of 'ethAddrPayload|hotkeyPayload|blockNumStr')","ethAddrPayload":"string (Ethereum address being claimed)","hotkeyPayload":"string (hotkey address performing the claim)","blockNumStr":"string (current Bittensor block number)","ethSigner":"string (Ethereum address that signed the ethMessage)"}},"outputs":{"success":"boolean","message":"string (e.g., 'Address mapping created' or 'Mapping already exists')","error":"string (description of error if success is false)"}},{"path":"/userVotes/:address","method":"GET","description":"Retrieves the votes for a specific coldkey address.","inputs":{"params":{"address":"string (coldkey address)"}},"outputs":{"success":"boolean","userVotes":"object (contains user's vote data) or null if no votes found","message":"string (e.g., 'No votes found')","error":"string (description of error if success is false)"}},{"path":"/allVotes","method":"GET","description":"Retrieves all stored user votes with token-based weight multipliers. Only includes voters who hold alpha tokens (filters out users with zero alpha balance). Results are cached for 30 seconds.","inputs":"None","outputs":{"success":"boolean","votes":"Array<object> (list of all votes from alpha token holders, each containing: coldkey address, pools, total_weight, block_number, alphaBalance, weightMultiplier)","totalAlphaTokens":"number (total alpha tokens held by all valid voters)","cached":"boolean (true if the response is from cache)","error":"string (description of error if success is false)"},"filtering":{"alpha_holders_only":"Only voters who hold alpha tokens are included in the response","zero_balance_excluded":"Users with zero alpha token balance are automatically filtered out"},"weight_calculation":{"single_voter":"If only one valid voter exists, they receive full weight (weightMultiplier = 1)","multiple_voters":"Weight multiplier is calculated as: voter's_alpha_tokens / total_alpha_tokens"}},{"path":"/allHolders","method":"GET","description":"Retrieves all token holders and their balances directly from the Bittensor chain. Results are cached and periodically refreshed.","inputs":"None","outputs":{"success":"boolean","holders":"object (mapping of coldkey address to balance)","cached":"boolean (always true as data is served from an in-memory cache)","error":"string (description of error if success is false)"}},{"path":"/allAddresses","method":"GET","description":"Retrieves all addresses associated with the token holders.","inputs":"None","outputs":{"success":"boolean","addresses":"Array<{ hotkeyAddress: string, ethereumAddress: string }> (linked addresses registered to subnet)","error":"string (description of error if success is false)"}},{"path":"/allMiners","method":"GET","description":"Retrieves all miners on the subnet along with their linked Ethereum addresses (if any).","inputs":"None","outputs":{"success":"boolean","miners":"Array<{ hotkeyAddress: string, ethereumAddress: string | null }> (all subnet miners with optional Ethereum addresses)","totalMiners":"number (total number of miners on the subnet)","linkedMiners":"number (number of miners with linked Ethereum addresses)","error":"string (description of error if success is false)"}},{"path":"/pools","method":"GET","description":"Retrieves all incentivized pools with voting information and alpha token holdings for each voter. Only shows pools that have at least one active voter (voter holding alpha tokens).","inputs":"None","outputs":{"success":"boolean","pools":"Array<{ address: string, totalWeight: number, token0: string, token1: string, token0Symbol: string, token1Symbol: string, fee: number, voters: Array<{ address: string, weight: number, alphaBalance: number, weightMultiplier: number }> }> (all pools being voted for with voter details and pool information)","totalPools":"number (total number of unique pools being voted for)","totalVoters":"number (total number of unique voters with alpha tokens)","totalAlphaTokens":"number (total alpha tokens held by all valid voters)","cached":"boolean (true if the response is from cache)","error":"string (description of error if success is false)"},"filtering":{"active_voters_only":"Only pools with at least one voter holding alpha tokens are included","inactive_pools":"Pools where all voters have 0 alpha tokens are filtered out"}},{"path":"/pools","method":"GET","description":"Retrieves all incentivized pools with voting information and alpha token holdings for each voter. Only shows pools that have at least one active voter (voter holding alpha tokens).","inputs":"None","outputs":{"success":"boolean","pools":"Array<{ address: string, totalWeight: number, token0: string, token1: string, token0Symbol: string, token1Symbol: string, fee: number, voters: Array<{ address: string, weight: number, alphaBalance: number, weightMultiplier: number }> }> (all pools being voted for with voter details and pool information)","totalPools":"number (total number of unique pools being voted for)","totalVoters":"number (total number of unique voters with alpha tokens)","totalAlphaTokens":"number (total alpha tokens held by all valid voters)","cached":"boolean (true if the response is from cache)","error":"string (description of error if success is false)"},"filtering":{"active_voters_only":"Only pools with at least one voter holding alpha tokens are included","inactive_pools":"Pools where all voters have 0 alpha tokens are filtered out"}},{"path":"/positions","method":"GET","description":"Retrieves all active Uniswap v3 liquidity positions for all miners with a linked Ethereum address. Results are cached for 5 minutes. Can be filtered by `hotkey` and/or `pool`. Inactive liquidity positions (positions where current tick is outside the position's bounds) are automatically filtered out. Includes current token amounts (token0Amount, token1Amount) and USD values for each position calculated using CoinGecko price data.","inputs":{"query":{"hotkey":"string (optional miner hotkey to filter by)","pool":"string (optional pool address to filter by)"}},"outputs":{"success":"boolean","positions":"Record<string, (LiquidityPosition & { emission: number, token0Amount?: string, token1Amount?: string, usdValue?: { token0Value: number, token1Value: number, totalValue: number, token0Price: number, token1Price: number } })[]> (map of miner hotkey to their liquidity positions with emission, current token amounts, and USD values)","cached":"boolean (true if the response is from cache)","error":"string (description of error if success is false)"}},{"path":"/positions/:minerHotkey","method":"GET","description":"Retrieves all active Uniswap v3 liquidity positions for a specific miner with a linked Ethereum address. Results are cached for 5 minutes. Inactive liquidity positions (positions where current tick is outside the position's bounds) are automatically filtered out. Includes current token amounts (token0Amount, token1Amount) and USD values for each position calculated using CoinGecko price data.","inputs":{"params":{"minerHotkey":"string (miner hotkey to filter by)"}},"outputs":{"success":"boolean","positions":"(LiquidityPosition & { emission: number, token0Amount?: string, token1Amount?: string, usdValue?: { token0Value: number, token1Value: number, totalValue: number, token0Price: number, token1Price: number } })[] (array of liquidity positions with emission, current token amounts, and USD values)","cached":"boolean (true if the response is from cache)","error":"string (description of error if success is false)"}},{"path":"/weights","method":"GET","description":"Retrieves the final calculated weight for each miner, which should directly correspond to the votes cast and the liquidity provided. Inactive liquidity positions (positions where current tick is outside the position's bounds) are automatically excluded from weight calculations.","inputs":"None","outputs":{"success":"boolean","weights":"Record<string, number> (map of miner hotkey to their final weight)","cached":"boolean (true if the response is from cache)","error":"string (description of error if success is false)"}},{"path":"/ping","method":"POST","description":"Validates a validator hotkey signature and checks version compatibility. Used for health checks and version validation.","inputs":{"body":{"signature":"string (Polkadot/Substrate signature of the message)","message":"string (formatted as 'blockNumStr|versionStr')","address":"string (validator hotkey address)"},"message_format_details":{"blockNumStr":"string (recent Bittensor block number within past 10 blocks)","versionStr":"string (client version in format 'major.minor.patch')"}},"outputs":{"success":"boolean","message":"string (e.g., 'Ping successful')","serverVersion":"string (current server version)","clientVersion":"string (client version from request)","versionCompatible":"boolean (true if versions are compatible)","versionMessage":"string (version message if client is running a different branch)","error":"string (description of error if success is false)"},"version_compatibility":{"major_minor_match":"Major and minor versions must match exactly","patch_behind_ok":"Client patch version can be behind server patch version","update_required":"If major or minor versions don't match, client must update"}},{"path":"/voteCooldown/:address","method":"GET","description":"Retrieves the current cooldown status for a specific address's voting ability. Provides detailed timing information including remaining time and exact unlock timestamp.","inputs":{"params":{"address":"string (coldkey address)"}},"outputs":{"success":"boolean","cooldownStatus":"object (contains cooldown information) or null if no cooldown active","message":"string (e.g., 'No active cooldown' or 'Cooldown active for 1h 12m')","error":"string (description of error if success is false)"},"cooldown_status_details":{"active":"boolean indicating if cooldown is currently active","remainingTime":"milliseconds until cooldown expires","remainingMinutes":"total minutes remaining","timeDisplay":"human-readable format (e.g., '1h 12m' or '45m')","cooldownUntil":"ISO timestamp when cooldown expires","changeCount":"number of vote changes made by this address","nextCooldownDuration":"what the next cooldown duration would be (e.g., '72m', '2h 24m')"}},{"path":"/voteHistory/:address","method":"GET","description":"Retrieves the complete vote change history and current active vote for a specific address. Tracks all vote modifications with detailed cooldown information for transparency and audit purposes.","inputs":{"params":{"address":"string (coldkey address)"}},"outputs":{"success":"boolean","voteHistory":"Array<object> (list of vote changes with timestamps and cooldown information)","currentVote":"object | null (current active vote if exists)","message":"string (e.g., 'Vote history retrieved')","error":"string (description of error if success is false)"},"vote_history_details":{"oldPools":"previous pool configuration before the change","newPools":"new pool configuration after the change","changeTimestamp":"when the vote change occurred","cooldownUntil":"when the cooldown period expired/expires","changeCount":"sequential change counter for tracking vote modifications"},"current_vote_details":{"pools":"current pool configuration","totalWeight":"total weight of current vote","blockNumber":"block number when vote was submitted","isActive":"always true for current vote"}}]}