bittensor_rs/queries/
neuron.rs

1//! # Neuron Queries
2//!
3//! Query individual neuron information from the Bittensor network.
4
5use crate::api::api;
6use crate::error::BittensorError;
7use crate::AccountId;
8use std::str::FromStr;
9use subxt::OnlineClient;
10use subxt::PolkadotConfig;
11
12/// NeuronInfo type with AccountId
13pub type NeuronInfo =
14    crate::api::api::runtime_types::pallet_subtensor::rpc_info::neuron_info::NeuronInfo<AccountId>;
15
16/// NeuronInfoLite type with AccountId
17pub type NeuronInfoLite =
18    crate::api::api::runtime_types::pallet_subtensor::rpc_info::neuron_info::NeuronInfoLite<
19        AccountId,
20    >;
21
22/// Get full neuron information by UID
23///
24/// # Arguments
25///
26/// * `client` - The subxt client
27/// * `netuid` - The subnet netuid
28/// * `uid` - The neuron UID
29///
30/// # Returns
31///
32/// Full neuron information including hotkey, coldkey, stake, etc.
33pub async fn get_neuron(
34    client: &OnlineClient<PolkadotConfig>,
35    netuid: u16,
36    uid: u16,
37) -> Result<NeuronInfo, BittensorError> {
38    let runtime_api =
39        client
40            .runtime_api()
41            .at_latest()
42            .await
43            .map_err(|e| BittensorError::RpcError {
44                message: format!("Failed to get runtime API: {}", e),
45            })?;
46
47    let neuron = runtime_api
48        .call(
49            api::runtime_apis::neuron_info_runtime_api::NeuronInfoRuntimeApi
50                .get_neuron(netuid, uid),
51        )
52        .await
53        .map_err(|e| BittensorError::RpcMethodError {
54            method: "get_neuron".to_string(),
55            message: e.to_string(),
56        })?
57        .ok_or(BittensorError::NeuronNotFound { uid, netuid })?;
58
59    Ok(neuron)
60}
61
62/// Get lite neuron information by UID
63///
64/// This is more efficient than `get_neuron` if you don't need all fields.
65pub async fn get_neuron_lite(
66    client: &OnlineClient<PolkadotConfig>,
67    netuid: u16,
68    uid: u16,
69) -> Result<NeuronInfoLite, BittensorError> {
70    let runtime_api =
71        client
72            .runtime_api()
73            .at_latest()
74            .await
75            .map_err(|e| BittensorError::RpcError {
76                message: format!("Failed to get runtime API: {}", e),
77            })?;
78
79    let neuron = runtime_api
80        .call(
81            api::runtime_apis::neuron_info_runtime_api::NeuronInfoRuntimeApi
82                .get_neuron_lite(netuid, uid),
83        )
84        .await
85        .map_err(|e| BittensorError::RpcMethodError {
86            method: "get_neuron_lite".to_string(),
87            message: e.to_string(),
88        })?
89        .ok_or(BittensorError::NeuronNotFound { uid, netuid })?;
90
91    Ok(neuron)
92}
93
94/// Get the UID for a hotkey on a subnet
95///
96/// # Arguments
97///
98/// * `client` - The subxt client
99/// * `netuid` - The subnet netuid
100/// * `hotkey` - The hotkey SS58 address
101///
102/// # Returns
103///
104/// The UID of the neuron, or an error if not registered
105pub async fn get_uid_for_hotkey(
106    client: &OnlineClient<PolkadotConfig>,
107    netuid: u16,
108    hotkey: &str,
109) -> Result<u16, BittensorError> {
110    let hotkey_id = AccountId::from_str(hotkey).map_err(|_| BittensorError::InvalidHotkey {
111        hotkey: hotkey.to_string(),
112    })?;
113
114    let storage = api::storage().subtensor_module().uids(netuid, hotkey_id);
115
116    let uid = client
117        .storage()
118        .at_latest()
119        .await
120        .map_err(|e| BittensorError::RpcError {
121            message: format!("Failed to get storage: {}", e),
122        })?
123        .fetch(&storage)
124        .await
125        .map_err(|e| BittensorError::StorageQueryError {
126            key: "uids".to_string(),
127            message: format!("Failed to fetch uid: {}", e),
128        })?;
129
130    uid.ok_or_else(|| BittensorError::HotkeyNotRegistered {
131        hotkey: hotkey.to_string(),
132        netuid,
133    })
134}
135
136#[cfg(test)]
137mod tests {
138    #[test]
139    fn test_neuron_query_types() {
140        let _uid: u16 = 0;
141        let _netuid: u16 = 1;
142    }
143}