diff --git a/pallets/subtensor/rpc/src/lib.rs b/pallets/subtensor/rpc/src/lib.rs index e460c5c382..5bb0f2014d 100644 --- a/pallets/subtensor/rpc/src/lib.rs +++ b/pallets/subtensor/rpc/src/lib.rs @@ -25,6 +25,8 @@ pub trait SubtensorCustomApi { fn get_delegates(&self, at: Option) -> RpcResult>; #[method(name = "delegateInfo_getDelegate")] fn get_delegate(&self, delegate_account_vec: Vec, at: Option) -> RpcResult>; + #[method(name = "delegateInfo_getDelegated")] + fn get_delegated(&self, delegatee_account_vec: Vec, at: Option) -> RpcResult>; #[method(name = "neuronInfo_getNeurons")] fn get_neurons(&self, netuid: u16, at: Option) -> RpcResult>; @@ -105,6 +107,23 @@ where }) } + fn get_delegated( + &self, + delegatee_account_vec: Vec, + at: Option<::Hash> + ) -> RpcResult> { + let api = self.client.runtime_api(); + let at = at.unwrap_or_else(|| self.client.info().best_hash); + + api.get_delegated(at, delegatee_account_vec).map_err(|e| { + CallError::Custom(ErrorObject::owned( + Error::RuntimeError.into(), + "Unable to get delegated info.", + Some(e.to_string()), + )).into() + }) + } + fn get_neurons( &self, netuid: u16, diff --git a/pallets/subtensor/runtime-api/src/lib.rs b/pallets/subtensor/runtime-api/src/lib.rs index ec7020c9ae..73a4a3a2b6 100644 --- a/pallets/subtensor/runtime-api/src/lib.rs +++ b/pallets/subtensor/runtime-api/src/lib.rs @@ -8,6 +8,7 @@ sp_api::decl_runtime_apis! { pub trait DelegateInfoRuntimeApi { fn get_delegates() -> Vec; fn get_delegate( delegate_account_vec: Vec ) -> Vec; + fn get_delegated( delegatee_account_vec: Vec ) -> Vec; } pub trait NeuronInfoRuntimeApi { diff --git a/pallets/subtensor/src/delegate_info.rs b/pallets/subtensor/src/delegate_info.rs index 7d23c0545d..508dc1072b 100644 --- a/pallets/subtensor/src/delegate_info.rs +++ b/pallets/subtensor/src/delegate_info.rs @@ -95,5 +95,27 @@ impl Pallet { return delegates; } + + pub fn get_delegated(delegatee_account_vec: Vec) -> Vec<(DelegateInfo, Compact)> { + if delegatee_account_vec.len() != 32 { + return Vec::new(); // No delegates for invalid account + } + + let delegatee: AccountIdOf = T::AccountId::decode( &mut delegatee_account_vec.as_bytes_ref() ).unwrap(); + + + let mut delegates: Vec<(DelegateInfo, Compact)> = Vec::new(); + for delegate in < Delegates as IterableStorageMap >::iter_keys().into_iter() { + let staked_to_this_delegatee = Self::get_stake_for_coldkey_and_hotkey( &delegatee.clone(), &delegate.clone() ); + if staked_to_this_delegatee == 0 { + continue; // No stake to this delegate + } + // Staked to this delegate, so add to list + let delegate_info = Self::get_delegate_by_existing_account( delegate.clone() ); + delegates.push( (delegate_info, staked_to_this_delegatee.into()) ); + } + + return delegates; + } } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 7be758dde1..e23ef929d2 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -698,6 +698,11 @@ impl_runtime_apis! { vec![] } } + + fn get_delegated(delegatee_account_vec: Vec) -> Vec { + let result = SubtensorModule::get_delegated(delegatee_account_vec); + result.encode() + } } impl subtensor_custom_rpc_runtime_api::NeuronInfoRuntimeApi for Runtime {