@@ -224,6 +224,25 @@ pub async fn neurons(
224224 }
225225
226226 neurons. sort_by_key ( |n| n. uid ) ;
227+
228+ // Step 6: Fetch correct stake values from runtime API (includes parent inheritance)
229+ // This overwrites the storage-based stakes with the actual consensus values
230+ if let Ok ( ( alpha_stakes, _tao_stakes, total_stakes) ) = get_stake_weights_for_subnet ( client, netuid) . await {
231+ for neuron in & mut neurons {
232+ let idx = neuron. uid as usize ;
233+ if let Some ( & alpha) = alpha_stakes. get ( idx) {
234+ // Update stake and total_stake with the correct value including inheritance
235+ neuron. stake = alpha;
236+ neuron. total_stake = alpha;
237+ }
238+ if let Some ( & total) = total_stakes. get ( idx) {
239+ // total_stake from runtime includes alpha + (tao * tao_weight)
240+ // We store this for reference but primary stake field is alpha_stake
241+ neuron. total_stake = total;
242+ }
243+ }
244+ }
245+
227246 Ok ( neurons)
228247}
229248
@@ -778,3 +797,84 @@ fn extract_last_u64_from_str(s: &str) -> Option<u64> {
778797 None
779798 }
780799}
800+
801+ /// Get stake weights for all neurons in a subnet using runtime API
802+ /// Returns (alpha_stake, tao_stake, total_stake) vectors indexed by UID
803+ /// These values include parent inheritance and are the actual values used in consensus
804+ pub async fn get_stake_weights_for_subnet (
805+ client : & BittensorClient ,
806+ netuid : u16 ,
807+ ) -> Result < ( Vec < u128 > , Vec < u128 > , Vec < u128 > ) > {
808+ // Call SubnetInfoRuntimeApi.get_subnet_state to get correct stakes
809+ let params = vec ! [ Value :: u128 ( netuid as u128 ) ] ;
810+
811+ if let Some ( val) = client
812+ . runtime_api ( "SubnetInfoRuntimeApi" , "get_subnet_state" , params)
813+ . await ?
814+ {
815+ // Parse using debug string representation (same approach as other decoders)
816+ let s = format ! ( "{:?}" , val) ;
817+
818+ // Extract alpha_stake, tao_stake, total_stake arrays from the debug string
819+ let alpha_stake = extract_stake_array ( & s, "alpha_stake" ) ;
820+ let tao_stake = extract_stake_array ( & s, "tao_stake" ) ;
821+ let total_stake = extract_stake_array ( & s, "total_stake" ) ;
822+
823+ if !alpha_stake. is_empty ( ) {
824+ return Ok ( ( alpha_stake, tao_stake, total_stake) ) ;
825+ }
826+ }
827+
828+ // Fallback: return empty vectors if runtime API fails
829+ Ok ( ( Vec :: new ( ) , Vec :: new ( ) , Vec :: new ( ) ) )
830+ }
831+
832+ /// Extract a stake array from the debug string representation of SubnetState
833+ /// The format is: ("alpha_stake", Value { value: Composite(Unnamed([Value { value: Primitive(U128(123)), ...
834+ fn extract_stake_array ( s : & str , field_name : & str ) -> Vec < u128 > {
835+ let mut result = Vec :: new ( ) ;
836+
837+ // Find the field pattern: ("field_name", Value { value: Composite(Unnamed([
838+ let field_pattern = format ! ( "(\" {}\" , Value {{ value: Composite(Unnamed([" , field_name) ;
839+ if let Some ( start_idx) = s. find ( & field_pattern) {
840+ let after_field = & s[ start_idx + field_pattern. len ( ) ..] ;
841+
842+ // Find where this array ends - look for ])), which closes Unnamed([...]))
843+ // We need to find the matching close
844+ let mut depth = 1 ;
845+ let mut end_idx = 0 ;
846+ let mut i = 0 ;
847+ let chars: Vec < char > = after_field. chars ( ) . collect ( ) ;
848+ while i < chars. len ( ) {
849+ match chars[ i] {
850+ '[' => depth += 1 ,
851+ ']' => {
852+ depth -= 1 ;
853+ if depth == 0 {
854+ end_idx = i;
855+ break ;
856+ }
857+ }
858+ _ => { }
859+ }
860+ i += 1 ;
861+ }
862+
863+ if end_idx > 0 {
864+ let array_content = & after_field[ ..end_idx] ;
865+
866+ // Extract all Primitive(U128(N)) values
867+ // Format: Value { value: Primitive(U128(38121433580446)), context: () }
868+ let re = regex:: Regex :: new ( r"Primitive\(U128\((\d+)\)\)" ) . unwrap ( ) ;
869+ for cap in re. captures_iter ( array_content) {
870+ if let Some ( num_str) = cap. get ( 1 ) {
871+ if let Ok ( num) = num_str. as_str ( ) . parse :: < u128 > ( ) {
872+ result. push ( num) ;
873+ }
874+ }
875+ }
876+ }
877+ }
878+
879+ result
880+ }
0 commit comments