bittensor_rs/extrinsics/
children.rs1use crate::api::api;
8use crate::error::BittensorError;
9use crate::extrinsics::ExtrinsicResponse;
10use crate::AccountId;
11use subxt::OnlineClient;
12use subxt::PolkadotConfig;
13
14#[derive(Debug, Clone)]
16pub struct ChildKey {
17 pub proportion: u64,
19 pub child: AccountId,
21}
22
23impl ChildKey {
24 pub fn new(child: AccountId, proportion: f64) -> Self {
41 let proportion = (proportion.clamp(0.0, 1.0) * u64::MAX as f64) as u64;
42 Self { proportion, child }
43 }
44
45 pub fn new_raw(child: AccountId, proportion: u64) -> Self {
47 Self { proportion, child }
48 }
49}
50
51#[derive(Debug, Clone)]
53pub struct SetChildrenParams {
54 pub netuid: u16,
56 pub children: Vec<ChildKey>,
58}
59
60impl SetChildrenParams {
61 pub fn new(netuid: u16) -> Self {
63 Self {
64 netuid,
65 children: Vec::new(),
66 }
67 }
68
69 pub fn with_child(mut self, child: AccountId, proportion: f64) -> Self {
71 self.children.push(ChildKey::new(child, proportion));
72 self
73 }
74
75 pub fn with_children(mut self, children: Vec<ChildKey>) -> Self {
77 self.children.extend(children);
78 self
79 }
80}
81
82pub async fn set_children<S>(
94 client: &OnlineClient<PolkadotConfig>,
95 signer: &S,
96 hotkey: AccountId,
97 params: SetChildrenParams,
98) -> Result<ExtrinsicResponse<()>, BittensorError>
99where
100 S: subxt::tx::Signer<PolkadotConfig>,
101{
102 let children: Vec<(u64, AccountId)> = params
103 .children
104 .into_iter()
105 .map(|c| (c.proportion, c.child))
106 .collect();
107
108 let call = api::tx()
109 .subtensor_module()
110 .set_children(hotkey, params.netuid, children);
111
112 let tx_hash = client
113 .tx()
114 .sign_and_submit_default(&call, signer)
115 .await
116 .map_err(|e| BittensorError::TxSubmissionError {
117 message: format!("Failed to set children: {}", e),
118 })?;
119
120 Ok(ExtrinsicResponse::success()
121 .with_message("Children set successfully")
122 .with_extrinsic_hash(&format!("{:?}", tx_hash))
123 .with_data(()))
124}
125
126pub async fn set_childkey_take<S>(
138 client: &OnlineClient<PolkadotConfig>,
139 signer: &S,
140 hotkey: AccountId,
141 netuid: u16,
142 take: f64,
143) -> Result<ExtrinsicResponse<()>, BittensorError>
144where
145 S: subxt::tx::Signer<PolkadotConfig>,
146{
147 let take_u16 = (take.clamp(0.0, 1.0) * u16::MAX as f64) as u16;
149
150 let call = api::tx()
151 .subtensor_module()
152 .set_childkey_take(hotkey, netuid, take_u16);
153
154 let tx_hash = client
155 .tx()
156 .sign_and_submit_default(&call, signer)
157 .await
158 .map_err(|e| BittensorError::TxSubmissionError {
159 message: format!("Failed to set childkey take: {}", e),
160 })?;
161
162 Ok(ExtrinsicResponse::success()
163 .with_message("Childkey take set successfully")
164 .with_extrinsic_hash(&format!("{:?}", tx_hash))
165 .with_data(()))
166}
167
168pub async fn revoke_children<S>(
172 client: &OnlineClient<PolkadotConfig>,
173 signer: &S,
174 hotkey: AccountId,
175 netuid: u16,
176) -> Result<ExtrinsicResponse<()>, BittensorError>
177where
178 S: subxt::tx::Signer<PolkadotConfig>,
179{
180 let children: Vec<(u64, AccountId)> = Vec::new();
181
182 let call = api::tx()
183 .subtensor_module()
184 .set_children(hotkey, netuid, children);
185
186 let tx_hash = client
187 .tx()
188 .sign_and_submit_default(&call, signer)
189 .await
190 .map_err(|e| BittensorError::TxSubmissionError {
191 message: format!("Failed to revoke children: {}", e),
192 })?;
193
194 Ok(ExtrinsicResponse::success()
195 .with_message("Children revoked successfully")
196 .with_extrinsic_hash(&format!("{:?}", tx_hash))
197 .with_data(()))
198}
199
200#[cfg(test)]
201mod tests {
202 use super::*;
203 use subxt::utils::AccountId32;
204
205 #[test]
206 fn test_child_key_new() {
207 let child = AccountId32::from([1u8; 32]);
208 let key = ChildKey::new(child.clone(), 0.5);
209 assert_eq!(key.child, child);
210 let third = u64::MAX / 3;
212 let two_thirds = u64::MAX / 3 * 2;
213 assert!(key.proportion > third);
214 assert!(key.proportion < two_thirds);
215 }
216
217 #[test]
218 fn test_child_key_clamping() {
219 let child = AccountId32::from([1u8; 32]);
220
221 let key = ChildKey::new(child.clone(), -0.5);
223 assert_eq!(key.proportion, 0);
224
225 let key = ChildKey::new(child, 1.5);
227 assert_eq!(key.proportion, u64::MAX);
228 }
229
230 #[test]
231 fn test_child_key_raw() {
232 let child = AccountId32::from([1u8; 32]);
233 let key = ChildKey::new_raw(child.clone(), 12345);
234 assert_eq!(key.proportion, 12345);
235 }
236
237 #[test]
238 fn test_set_children_params() {
239 let child1 = AccountId32::from([1u8; 32]);
240 let child2 = AccountId32::from([2u8; 32]);
241
242 let params = SetChildrenParams::new(1)
243 .with_child(child1.clone(), 0.3)
244 .with_child(child2.clone(), 0.2);
245
246 assert_eq!(params.netuid, 1);
247 assert_eq!(params.children.len(), 2);
248 }
249
250 #[test]
251 fn test_set_children_params_with_children() {
252 let child1 = AccountId32::from([1u8; 32]);
253 let child2 = AccountId32::from([2u8; 32]);
254
255 let children = vec![ChildKey::new(child1, 0.5), ChildKey::new(child2, 0.5)];
256
257 let params = SetChildrenParams::new(1).with_children(children);
258 assert_eq!(params.children.len(), 2);
259 }
260
261 #[test]
262 fn test_child_key_clone() {
263 let child = AccountId32::from([1u8; 32]);
264 let key = ChildKey::new(child, 0.5);
265 let cloned = key.clone();
266 assert_eq!(key.proportion, cloned.proportion);
267 assert_eq!(key.child, cloned.child);
268 }
269
270 #[test]
271 fn test_child_key_debug() {
272 let child = AccountId32::from([1u8; 32]);
273 let key = ChildKey::new(child, 0.5);
274 let debug = format!("{:?}", key);
275 assert!(debug.contains("ChildKey"));
276 }
277}