nominators functionality added
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
This commit is contained in:
		
							parent
							
								
									9e7cdffd29
								
							
						
					
					
						commit
						0af68ca624
					
				@ -2,7 +2,7 @@
 | 
				
			|||||||
name = "ghost-eye"
 | 
					name = "ghost-eye"
 | 
				
			||||||
authors = ["str3tch <stretch@ghostchain.io>"]
 | 
					authors = ["str3tch <stretch@ghostchain.io>"]
 | 
				
			||||||
description = "Application for interacting with Casper/Ghost nodes that are exposing RPC only to the localhost"
 | 
					description = "Application for interacting with Casper/Ghost nodes that are exposing RPC only to the localhost"
 | 
				
			||||||
version = "0.3.52"
 | 
					version = "0.3.53"
 | 
				
			||||||
edition = "2021"
 | 
					edition = "2021"
 | 
				
			||||||
homepage = "https://git.ghostchain.io/ghostchain"
 | 
					homepage = "https://git.ghostchain.io/ghostchain"
 | 
				
			||||||
repository = "https://git.ghostchain.io/ghostchain/ghost-eye"
 | 
					repository = "https://git.ghostchain.io/ghostchain/ghost-eye"
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@ use subxt::config::substrate::DigestItem;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use crate::types::{
 | 
					use crate::types::{
 | 
				
			||||||
    ActionLevel, ActionTarget, CasperExtrinsicDetails, EraInfo, EraRewardPoints, 
 | 
					    ActionLevel, ActionTarget, CasperExtrinsicDetails, EraInfo, EraRewardPoints, 
 | 
				
			||||||
    Nominator, PeerInformation, SessionKeyInfo, UnlockChunk, SystemAccount,
 | 
					    Nominator, Nominations, PeerInformation, SessionKeyInfo, UnlockChunk, SystemAccount,
 | 
				
			||||||
    RewardDestination,
 | 
					    RewardDestination,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -63,6 +63,7 @@ pub enum Action {
 | 
				
			|||||||
    UnbondFrom([u8; 32], u128),
 | 
					    UnbondFrom([u8; 32], u128),
 | 
				
			||||||
    RebondFrom([u8; 32], u128),
 | 
					    RebondFrom([u8; 32], u128),
 | 
				
			||||||
    WithdrawUnbondedFrom([u8; 32], u32),
 | 
					    WithdrawUnbondedFrom([u8; 32], u32),
 | 
				
			||||||
 | 
					    NominateTargets([u8; 32], Vec<[u8; 32]>),
 | 
				
			||||||
    EventLog(String, ActionLevel, ActionTarget),
 | 
					    EventLog(String, ActionLevel, ActionTarget),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    NewBestBlock(u32),
 | 
					    NewBestBlock(u32),
 | 
				
			||||||
@ -100,6 +101,7 @@ pub enum Action {
 | 
				
			|||||||
    GetNominatorsNumber,
 | 
					    GetNominatorsNumber,
 | 
				
			||||||
    GetInflation,
 | 
					    GetInflation,
 | 
				
			||||||
    GetNominatorsByValidator([u8; 32], bool),
 | 
					    GetNominatorsByValidator([u8; 32], bool),
 | 
				
			||||||
 | 
					    GetNominatorsByAccount([u8; 32], bool),
 | 
				
			||||||
    GetValidatorAllRewards([u8; 32], bool),
 | 
					    GetValidatorAllRewards([u8; 32], bool),
 | 
				
			||||||
    GetValidatorLedger([u8; 32], bool),
 | 
					    GetValidatorLedger([u8; 32], bool),
 | 
				
			||||||
    GetIsStashBonded([u8; 32], bool),
 | 
					    GetIsStashBonded([u8; 32], bool),
 | 
				
			||||||
@ -133,6 +135,7 @@ pub enum Action {
 | 
				
			|||||||
    SetListenAddresses(Vec<String>),
 | 
					    SetListenAddresses(Vec<String>),
 | 
				
			||||||
    SetLocalIdentity(String),
 | 
					    SetLocalIdentity(String),
 | 
				
			||||||
    SetNominatorsByValidator(Vec<Nominator>, [u8; 32]),
 | 
					    SetNominatorsByValidator(Vec<Nominator>, [u8; 32]),
 | 
				
			||||||
 | 
					    SetNominatorsByAccount(Nominations, [u8; 32]),
 | 
				
			||||||
    SetValidatorEraReward(u32, u128),
 | 
					    SetValidatorEraReward(u32, u128),
 | 
				
			||||||
    SetValidatorEraClaimed(u32, bool),
 | 
					    SetValidatorEraClaimed(u32, bool),
 | 
				
			||||||
    SetValidatorEraSlash(u32, u128),
 | 
					    SetValidatorEraSlash(u32, u128),
 | 
				
			||||||
 | 
				
			|||||||
@ -54,9 +54,8 @@ impl NominatorsByValidator {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fn update_nominators(&mut self, nominators: Vec<Nominator>) {
 | 
					    fn update_nominators(&mut self, nominators: Vec<Nominator>) {
 | 
				
			||||||
        if self.nominators.len() > nominators.len() {
 | 
					        if self.nominators.len() > nominators.len() {
 | 
				
			||||||
            if let Some(_) = self.table_state.selected() {
 | 
					            self.table_state.select(None);
 | 
				
			||||||
                self.last_row();
 | 
					            self.scroll_state = self.scroll_state.position(0);
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        self.nominators = nominators;
 | 
					        self.nominators = nominators;
 | 
				
			||||||
        self.scroll_state = self.scroll_state.content_length(self.nominators.len());
 | 
					        self.scroll_state = self.scroll_state.content_length(self.nominators.len());
 | 
				
			||||||
@ -178,7 +177,7 @@ impl Component for NominatorsByValidator {
 | 
				
			|||||||
                .iter()
 | 
					                .iter()
 | 
				
			||||||
                .map(|info| {
 | 
					                .map(|info| {
 | 
				
			||||||
                    Row::new(vec![
 | 
					                    Row::new(vec![
 | 
				
			||||||
                        Cell::from(Text::from(info.who.clone()).alignment(Alignment::Left)),
 | 
					                        Cell::from(Text::from(info.address.clone()).alignment(Alignment::Left)),
 | 
				
			||||||
                        Cell::from(Text::from(self.prepare_u128(info.value)).alignment(Alignment::Right)), 
 | 
					                        Cell::from(Text::from(self.prepare_u128(info.value)).alignment(Alignment::Right)), 
 | 
				
			||||||
                    ])
 | 
					                    ])
 | 
				
			||||||
                }),
 | 
					                }),
 | 
				
			||||||
 | 
				
			|||||||
@ -94,6 +94,11 @@ impl Accounts {
 | 
				
			|||||||
                    account_id, 
 | 
					                    account_id, 
 | 
				
			||||||
                    used_seed.clone()));
 | 
					                    used_seed.clone()));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        if let Some(network_tx) = &self.network_tx {
 | 
				
			||||||
 | 
					            let _ = network_tx.send(Action::GetNominatorsByAccount(
 | 
				
			||||||
 | 
					                    account_id,
 | 
				
			||||||
 | 
					                    false));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        self.set_sender_nonce(index);
 | 
					        self.set_sender_nonce(index);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -311,10 +316,8 @@ impl Accounts {
 | 
				
			|||||||
                });
 | 
					                });
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        self.table_state.select(Some(0));
 | 
					 | 
				
			||||||
        self.scroll_state = self.scroll_state.content_length(self.wallet_keys.len());
 | 
					        self.scroll_state = self.scroll_state.content_length(self.wallet_keys.len());
 | 
				
			||||||
        self.set_balance_active(0);
 | 
					        self.first_row();
 | 
				
			||||||
        self.set_used_account(0);
 | 
					 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2,13 +2,15 @@ use std::fs::File;
 | 
				
			|||||||
use std::path::PathBuf;
 | 
					use std::path::PathBuf;
 | 
				
			||||||
use std::io::{Write, BufRead, BufReader};
 | 
					use std::io::{Write, BufRead, BufReader};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use subxt::ext::sp_core::crypto::{AccountId32, Ss58AddressFormat, Ss58Codec};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use color_eyre::Result;
 | 
					use color_eyre::Result;
 | 
				
			||||||
use crossterm::event::{KeyCode, KeyEvent};
 | 
					use crossterm::event::{KeyCode, KeyEvent};
 | 
				
			||||||
use ratatui::layout::{Constraint, Margin};
 | 
					use ratatui::layout::{Constraint, Margin};
 | 
				
			||||||
use ratatui::style::{Stylize, Modifier};
 | 
					use ratatui::style::{Stylize, Modifier};
 | 
				
			||||||
use ratatui::widgets::Clear;
 | 
					use ratatui::widgets::Clear;
 | 
				
			||||||
use ratatui::{
 | 
					use ratatui::{
 | 
				
			||||||
    text::Text,
 | 
					    text::{Line, Text},
 | 
				
			||||||
    layout::{Alignment, Rect}, 
 | 
					    layout::{Alignment, Rect}, 
 | 
				
			||||||
    widgets::{
 | 
					    widgets::{
 | 
				
			||||||
        Block, Cell, Row, Table, TableState, Scrollbar, Padding,
 | 
					        Block, Cell, Row, Table, TableState, Scrollbar, Padding,
 | 
				
			||||||
@ -17,9 +19,10 @@ use ratatui::{
 | 
				
			|||||||
    Frame
 | 
					    Frame
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use tokio::sync::mpsc::UnboundedSender;
 | 
					use tokio::sync::mpsc::UnboundedSender;
 | 
				
			||||||
 | 
					use std::sync::mpsc::Sender;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use super::{PartialComponent, Component, CurrentTab};
 | 
					use super::{PartialComponent, Component, CurrentTab};
 | 
				
			||||||
use crate::types::EraRewardPoints;
 | 
					use crate::types::{ActionLevel, Nominations, ActionTarget, EraRewardPoints};
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    action::Action, 
 | 
					    action::Action, 
 | 
				
			||||||
    config::Config, 
 | 
					    config::Config, 
 | 
				
			||||||
@ -28,12 +31,14 @@ use crate::{
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
pub struct CurrentValidators {
 | 
					pub struct CurrentValidators {
 | 
				
			||||||
    is_active: bool,
 | 
					    is_active: bool,
 | 
				
			||||||
 | 
					    network_tx: Option<Sender<Action>>,
 | 
				
			||||||
    action_tx: Option<UnboundedSender<Action>>,
 | 
					    action_tx: Option<UnboundedSender<Action>>,
 | 
				
			||||||
    known_validators_file: PathBuf,
 | 
					    known_validators_file: PathBuf,
 | 
				
			||||||
    palette: StylePalette,
 | 
					    palette: StylePalette,
 | 
				
			||||||
    scroll_state: ScrollbarState,
 | 
					    scroll_state: ScrollbarState,
 | 
				
			||||||
    table_state: TableState,
 | 
					    table_state: TableState,
 | 
				
			||||||
    individual: Vec<EraRewardPoints>,
 | 
					    individual: Vec<EraRewardPoints>,
 | 
				
			||||||
 | 
					    not_active_nominations: Vec<EraRewardPoints>,
 | 
				
			||||||
    known_validators: std::collections::HashMap<[u8; 32], String>,
 | 
					    known_validators: std::collections::HashMap<[u8; 32], String>,
 | 
				
			||||||
    checked_validators: std::collections::HashSet<[u8; 32]>,
 | 
					    checked_validators: std::collections::HashSet<[u8; 32]>,
 | 
				
			||||||
    total_points: u32,
 | 
					    total_points: u32,
 | 
				
			||||||
@ -41,6 +46,8 @@ pub struct CurrentValidators {
 | 
				
			|||||||
    my_stash_id: Option<[u8; 32]>,
 | 
					    my_stash_id: Option<[u8; 32]>,
 | 
				
			||||||
    account_id: [u8; 32],
 | 
					    account_id: [u8; 32],
 | 
				
			||||||
    account_secret_seed: [u8; 32],
 | 
					    account_secret_seed: [u8; 32],
 | 
				
			||||||
 | 
					    my_nominations: std::collections::HashMap<[u8; 32], Nominations>,
 | 
				
			||||||
 | 
					    filtered_vector: Vec<EraRewardPoints>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Default for CurrentValidators {
 | 
					impl Default for CurrentValidators {
 | 
				
			||||||
@ -55,6 +62,7 @@ impl CurrentValidators {
 | 
				
			|||||||
    pub fn new() -> Self {
 | 
					    pub fn new() -> Self {
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            is_active: false,
 | 
					            is_active: false,
 | 
				
			||||||
 | 
					            network_tx: None,
 | 
				
			||||||
            action_tx: None,
 | 
					            action_tx: None,
 | 
				
			||||||
            known_validators_file: Default::default(),
 | 
					            known_validators_file: Default::default(),
 | 
				
			||||||
            scroll_state: ScrollbarState::new(0),
 | 
					            scroll_state: ScrollbarState::new(0),
 | 
				
			||||||
@ -68,6 +76,9 @@ impl CurrentValidators {
 | 
				
			|||||||
            account_id: [0u8; 32],
 | 
					            account_id: [0u8; 32],
 | 
				
			||||||
            account_secret_seed: [0u8; 32],
 | 
					            account_secret_seed: [0u8; 32],
 | 
				
			||||||
            palette: StylePalette::default(),
 | 
					            palette: StylePalette::default(),
 | 
				
			||||||
 | 
					            my_nominations: Default::default(),
 | 
				
			||||||
 | 
					            not_active_nominations: Default::default(),
 | 
				
			||||||
 | 
					            filtered_vector: Default::default(),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -79,7 +90,7 @@ impl CurrentValidators {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn move_selected(&mut self, index: usize) {
 | 
					    fn move_selected(&mut self, index: usize) {
 | 
				
			||||||
        if self.individual.len() > 0 {
 | 
					        if self.filtered_vector.len() > 0 {
 | 
				
			||||||
            self.table_state.select(Some(index));
 | 
					            self.table_state.select(Some(index));
 | 
				
			||||||
            self.scroll_state = self.scroll_state.position(index);
 | 
					            self.scroll_state = self.scroll_state.position(index);
 | 
				
			||||||
            self.update_choosen_details(index);
 | 
					            self.update_choosen_details(index);
 | 
				
			||||||
@ -96,9 +107,27 @@ impl CurrentValidators {
 | 
				
			|||||||
        self.account_secret_seed = secret_seed;
 | 
					        self.account_secret_seed = secret_seed;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn store_nominators(&mut self, nominations: Nominations, account_id: [u8; 32]) {
 | 
				
			||||||
 | 
					        if self.account_id == account_id {
 | 
				
			||||||
 | 
					            self.not_active_nominations.clear();
 | 
				
			||||||
 | 
					            for account in nominations.targets.iter() {
 | 
				
			||||||
 | 
					                if !self.individual.iter().any(|r| r.account_id == *account) {
 | 
				
			||||||
 | 
					                    self.not_active_nominations.push(EraRewardPoints {
 | 
				
			||||||
 | 
					                        account_id: *account,
 | 
				
			||||||
 | 
					                        address: AccountId32::from(*account)
 | 
				
			||||||
 | 
					                            .to_ss58check_with_version(Ss58AddressFormat::custom(1996)),
 | 
				
			||||||
 | 
					                            points: 0,
 | 
				
			||||||
 | 
					                            disabled: true,
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        self.my_nominations.insert(account_id, nominations);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn update_choosen_details(&self, index: usize) {
 | 
					    fn update_choosen_details(&self, index: usize) {
 | 
				
			||||||
        if let Some(action_tx) = &self.action_tx {
 | 
					        if let Some(action_tx) = &self.action_tx {
 | 
				
			||||||
            let (selected_account_id, selected_points) = self.individual
 | 
					            let (selected_account_id, selected_points) = self.filtered_vector
 | 
				
			||||||
                .get(index)
 | 
					                .get(index)
 | 
				
			||||||
                .map(|data| (data.account_id, data.points))
 | 
					                .map(|data| (data.account_id, data.points))
 | 
				
			||||||
                .unwrap_or_default();
 | 
					                .unwrap_or_default();
 | 
				
			||||||
@ -114,9 +143,41 @@ impl CurrentValidators {
 | 
				
			|||||||
        self.checked_validators.clear();
 | 
					        self.checked_validators.clear();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn choose_current_nominated(&mut self) {
 | 
				
			||||||
 | 
					        self.clear_choosen();
 | 
				
			||||||
 | 
					        self.checked_validators.extend(self.my_nominations
 | 
				
			||||||
 | 
					            .get(&self.account_id)
 | 
				
			||||||
 | 
					            .map(|nom| nom.targets.clone())
 | 
				
			||||||
 | 
					            .unwrap_or_default());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn choose_all_validators(&mut self) {
 | 
				
			||||||
 | 
					        self.clear_choosen();
 | 
				
			||||||
 | 
					        self.checked_validators.extend(self.individual
 | 
				
			||||||
 | 
					            .iter().map(|ind| ind.account_id));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn swap_choosen_filter(&mut self) {
 | 
				
			||||||
 | 
					        let is_individual = self.filtered_vector.len() == self.individual.len();
 | 
				
			||||||
 | 
					        self.filtered_vector = self.individual
 | 
				
			||||||
 | 
					            .iter()
 | 
				
			||||||
 | 
					            .filter_map(|data| {
 | 
				
			||||||
 | 
					                let is_good = !is_individual || self.checked_validators.contains(&data.account_id);
 | 
				
			||||||
 | 
					                is_good.then(|| data.clone())
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .collect::<Vec<_>>();
 | 
				
			||||||
 | 
					        self.scroll_state = self.scroll_state.content_length(self.filtered_vector.len());
 | 
				
			||||||
 | 
					        if self.filtered_vector.len() == 0 {
 | 
				
			||||||
 | 
					            self.table_state.select(None);
 | 
				
			||||||
 | 
					            self.scroll_state = self.scroll_state.position(0);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            self.first_row();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn flip_validator_check(&mut self) {
 | 
					    fn flip_validator_check(&mut self) {
 | 
				
			||||||
        if let Some(index) = self.table_state.selected() {
 | 
					        if let Some(index) = self.table_state.selected() {
 | 
				
			||||||
            if let Some(indiv) = self.individual.get(index) {
 | 
					            if let Some(indiv) = self.filtered_vector.get(index) {
 | 
				
			||||||
                let current_account_id = indiv.account_id;
 | 
					                let current_account_id = indiv.account_id;
 | 
				
			||||||
                if self.checked_validators.contains(¤t_account_id) {
 | 
					                if self.checked_validators.contains(¤t_account_id) {
 | 
				
			||||||
                    self.checked_validators.remove(¤t_account_id);
 | 
					                    self.checked_validators.remove(¤t_account_id);
 | 
				
			||||||
@ -129,7 +190,7 @@ impl CurrentValidators {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fn save_validator_name(&mut self, new_name: String) {
 | 
					    fn save_validator_name(&mut self, new_name: String) {
 | 
				
			||||||
        if let Some(index) = self.table_state.selected() {
 | 
					        if let Some(index) = self.table_state.selected() {
 | 
				
			||||||
            let account_id = self.individual[index].account_id;
 | 
					            let account_id = self.filtered_vector[index].account_id;
 | 
				
			||||||
            let _ = self.known_validators.insert(account_id, new_name);
 | 
					            let _ = self.known_validators.insert(account_id, new_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let mut file = File::create(&self.known_validators_file)
 | 
					            let mut file = File::create(&self.known_validators_file)
 | 
				
			||||||
@ -172,7 +233,7 @@ impl CurrentValidators {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn first_row(&mut self) {
 | 
					    fn first_row(&mut self) {
 | 
				
			||||||
        if self.individual.len() > 0 {
 | 
					        if self.filtered_vector.len() > 0 {
 | 
				
			||||||
            self.move_selected(0);
 | 
					            self.move_selected(0);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -180,7 +241,7 @@ impl CurrentValidators {
 | 
				
			|||||||
    fn next_row(&mut self) {
 | 
					    fn next_row(&mut self) {
 | 
				
			||||||
        let i = match self.table_state.selected() {
 | 
					        let i = match self.table_state.selected() {
 | 
				
			||||||
            Some(i) => {
 | 
					            Some(i) => {
 | 
				
			||||||
                if i >= self.individual.len() - 1 {
 | 
					                if i >= self.filtered_vector.len() - 1 {
 | 
				
			||||||
                    i
 | 
					                    i
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    i + 1
 | 
					                    i + 1
 | 
				
			||||||
@ -192,8 +253,8 @@ impl CurrentValidators {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn last_row(&mut self) {
 | 
					    fn last_row(&mut self) {
 | 
				
			||||||
        if self.individual.len() > 0 {
 | 
					        if self.filtered_vector.len() > 0 {
 | 
				
			||||||
            let last = self.individual.len() - 1;
 | 
					            let last = self.filtered_vector.len() - 1;
 | 
				
			||||||
            self.move_selected(last);
 | 
					            self.move_selected(last);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -218,21 +279,67 @@ impl CurrentValidators {
 | 
				
			|||||||
        total_points: u32,
 | 
					        total_points: u32,
 | 
				
			||||||
        individual: &Vec<EraRewardPoints>,
 | 
					        individual: &Vec<EraRewardPoints>,
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
 | 
					        let previous_length = self.individual.len();
 | 
				
			||||||
        self.individual = individual.to_vec();
 | 
					        self.individual = individual.to_vec();
 | 
				
			||||||
        self.total_points = total_points;
 | 
					        self.total_points = total_points;
 | 
				
			||||||
        self.era_index = era_index;
 | 
					        self.era_index = era_index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if individual.len() > 0 {
 | 
				
			||||||
            if let Some(account_id) = self.my_stash_id {
 | 
					            if let Some(account_id) = self.my_stash_id {
 | 
				
			||||||
            if self.individual.len() > 1 {
 | 
					 | 
				
			||||||
                if let Some(index) = self.individual
 | 
					                if let Some(index) = self.individual
 | 
				
			||||||
                    .iter()
 | 
					                    .iter()
 | 
				
			||||||
                    .position(|item| item.account_id == account_id) {
 | 
					                    .position(|item| item.account_id == account_id) {
 | 
				
			||||||
                        self.individual.swap(0, index);
 | 
					                        self.individual.swap(0, index);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            if previous_length == 0 {
 | 
				
			||||||
 | 
					                self.filtered_vector = self.individual.clone();
 | 
				
			||||||
 | 
					                self.scroll_state = self.scroll_state.content_length(self.individual.len());
 | 
				
			||||||
 | 
					                self.first_row();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.scroll_state = self.scroll_state.content_length(self.individual.len());
 | 
					    fn nominate_choosen(&mut self) {
 | 
				
			||||||
 | 
					        if self.my_stash_id.map(|acc| acc == self.account_id).unwrap_or_default() {
 | 
				
			||||||
 | 
					            if let Some(action_tx) = &self.action_tx {
 | 
				
			||||||
 | 
					                let _ = action_tx.send(Action::EventLog(
 | 
				
			||||||
 | 
					                        "nomination from stash account will stop node validation, use another account for nomination".to_string(), 
 | 
				
			||||||
 | 
					                        ActionLevel::Error, 
 | 
				
			||||||
 | 
					                        ActionTarget::WalletLog));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            if let Some(network_tx) = &self.network_tx {
 | 
				
			||||||
 | 
					                let nominate_targets: Vec<[u8; 32]> = self.checked_validators
 | 
				
			||||||
 | 
					                    .clone()
 | 
				
			||||||
 | 
					                    .into_iter()
 | 
				
			||||||
 | 
					                    .collect::<Vec<_>>();
 | 
				
			||||||
 | 
					                let _ = network_tx.send(Action::NominateTargets(
 | 
				
			||||||
 | 
					                        self.account_secret_seed, nominate_targets));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        self.close_popup();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn prepare_nomination_line(&self) -> String {
 | 
				
			||||||
 | 
					        let empty_nominations = Nominations::default();
 | 
				
			||||||
 | 
					        let nominations = self.my_nominations
 | 
				
			||||||
 | 
					            .get(&self.account_id)
 | 
				
			||||||
 | 
					            .unwrap_or(&empty_nominations);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if nominations.targets.len() == 0 {
 | 
				
			||||||
 | 
					            "No nominations found".to_string()
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            let status = if nominations.suppressed {
 | 
				
			||||||
 | 
					                "Suppressed"
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                "Active"
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            format!("Submitted at era #{} | {} ", 
 | 
				
			||||||
 | 
					                nominations.submitted_in,
 | 
				
			||||||
 | 
					                status,
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -251,6 +358,11 @@ impl Component for CurrentValidators {
 | 
				
			|||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn register_network_handler(&mut self, tx: Sender<Action>) -> Result<()> {
 | 
				
			||||||
 | 
					        self.network_tx = Some(tx);
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn register_config_handler(&mut self, config: Config) -> Result<()> {
 | 
					    fn register_config_handler(&mut self, config: Config) -> Result<()> {
 | 
				
			||||||
        if let Some(style) = config.styles.get(&crate::app::Mode::Wallet) {
 | 
					        if let Some(style) = config.styles.get(&crate::app::Mode::Wallet) {
 | 
				
			||||||
            self.palette.with_normal_style(style.get("normal_style").copied());
 | 
					            self.palette.with_normal_style(style.get("normal_style").copied());
 | 
				
			||||||
@ -273,6 +385,7 @@ impl Component for CurrentValidators {
 | 
				
			|||||||
        match action {
 | 
					        match action {
 | 
				
			||||||
            Action::UpdateKnownValidator(validator_name) => self.save_validator_name(validator_name),
 | 
					            Action::UpdateKnownValidator(validator_name) => self.save_validator_name(validator_name),
 | 
				
			||||||
            Action::UsedAccount(account_id, secret_seed) => self.update_used_account(account_id, secret_seed),
 | 
					            Action::UsedAccount(account_id, secret_seed) => self.update_used_account(account_id, secret_seed),
 | 
				
			||||||
 | 
					            Action::SetNominatorsByAccount(nominations, account_id) => self.store_nominators(nominations, account_id),
 | 
				
			||||||
            Action::SetStashAccount(account_id) => self.my_stash_id = Some(account_id),
 | 
					            Action::SetStashAccount(account_id) => self.my_stash_id = Some(account_id),
 | 
				
			||||||
            Action::SetCurrentValidatorEraRewards(era_index, total_points, individual) => 
 | 
					            Action::SetCurrentValidatorEraRewards(era_index, total_points, individual) => 
 | 
				
			||||||
                self.update_era_rewards(era_index, total_points, &individual),
 | 
					                self.update_era_rewards(era_index, total_points, &individual),
 | 
				
			||||||
@ -289,7 +402,13 @@ impl Component for CurrentValidators {
 | 
				
			|||||||
                KeyCode::Char('g') => self.first_row(),
 | 
					                KeyCode::Char('g') => self.first_row(),
 | 
				
			||||||
                KeyCode::Char('G') => self.last_row(),
 | 
					                KeyCode::Char('G') => self.last_row(),
 | 
				
			||||||
                KeyCode::Char('R') => self.update_known_validator_record(),
 | 
					                KeyCode::Char('R') => self.update_known_validator_record(),
 | 
				
			||||||
                KeyCode::Char('C') => self.clear_choosen(),
 | 
					
 | 
				
			||||||
 | 
					                KeyCode::Char('c') => self.clear_choosen(),
 | 
				
			||||||
 | 
					                KeyCode::Char('m') => self.choose_current_nominated(),
 | 
				
			||||||
 | 
					                KeyCode::Char('a') => self.choose_all_validators(),
 | 
				
			||||||
 | 
					                KeyCode::Char('f') => self.swap_choosen_filter(),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                KeyCode::Char('N') => self.nominate_choosen(),
 | 
				
			||||||
                KeyCode::Enter => self.flip_validator_check(),
 | 
					                KeyCode::Enter => self.flip_validator_check(),
 | 
				
			||||||
                KeyCode::Esc => self.close_popup(),
 | 
					                KeyCode::Esc => self.close_popup(),
 | 
				
			||||||
                _ => {},
 | 
					                _ => {},
 | 
				
			||||||
@ -302,17 +421,33 @@ impl Component for CurrentValidators {
 | 
				
			|||||||
        if self.is_active {
 | 
					        if self.is_active {
 | 
				
			||||||
            let (border_style, border_type) = self.palette.create_border_style(self.is_active);
 | 
					            let (border_style, border_type) = self.palette.create_border_style(self.is_active);
 | 
				
			||||||
            let [place, _] = super::nominator_layout(area);
 | 
					            let [place, _] = super::nominator_layout(area);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let top_title = format!("Validators {} | Total points: {}", self.individual.len(), self.total_points);
 | 
				
			||||||
 | 
					            let bottom_title = self.prepare_nomination_line();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let table = Table::new(
 | 
					            let table = Table::new(
 | 
				
			||||||
                self.individual
 | 
					                self.filtered_vector
 | 
				
			||||||
                    .iter()
 | 
					                    .iter()
 | 
				
			||||||
 | 
					                    .chain(&self.not_active_nominations)
 | 
				
			||||||
                    .enumerate()
 | 
					                    .enumerate()
 | 
				
			||||||
                    .map(|(index, info)| {
 | 
					                    .map(|(index, info)| {
 | 
				
			||||||
 | 
					                        let is_validator_choosen = self.checked_validators.contains(&info.account_id);
 | 
				
			||||||
 | 
					                        let is_current_nomination = self.my_nominations
 | 
				
			||||||
 | 
					                            .get(&self.account_id)
 | 
				
			||||||
 | 
					                            .map(|x| x.targets.contains(&info.account_id))
 | 
				
			||||||
 | 
					                            .unwrap_or_default();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        let mut address_text = Text::from(info.address.clone()).alignment(Alignment::Center);
 | 
					                        let mut address_text = Text::from(info.address.clone()).alignment(Alignment::Center);
 | 
				
			||||||
                        let mut points_text = Text::from(info.points.to_string()).alignment(Alignment::Right);
 | 
					                        let mut points_text = Text::from(info.points.to_string()).alignment(Alignment::Right);
 | 
				
			||||||
                    let is_choosen_text = if self.checked_validators.contains(&info.account_id) {
 | 
					
 | 
				
			||||||
                        ">"
 | 
					                        let (row_style, is_choosen_text) = if is_validator_choosen {
 | 
				
			||||||
 | 
					                            address_text = address_text.add_modifier(Modifier::ITALIC);
 | 
				
			||||||
 | 
					                            points_text = points_text.add_modifier(Modifier::ITALIC);
 | 
				
			||||||
 | 
					                            (self.palette.create_highlight_style(), ">")
 | 
				
			||||||
 | 
					                        } else if is_current_nomination {
 | 
				
			||||||
 | 
					                            (Default::default(), "*")
 | 
				
			||||||
                        } else {
 | 
					                        } else {
 | 
				
			||||||
                        ""
 | 
					                            (Default::default(), "")
 | 
				
			||||||
                        };
 | 
					                        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if info.disabled {
 | 
					                        if info.disabled {
 | 
				
			||||||
@ -320,36 +455,25 @@ impl Component for CurrentValidators {
 | 
				
			|||||||
                            points_text = points_text.add_modifier(Modifier::CROSSED_OUT);
 | 
					                            points_text = points_text.add_modifier(Modifier::CROSSED_OUT);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    let mut current_validator_is_my_stash = false;
 | 
					                        let default_name = if index == 0 && self.my_stash_id
 | 
				
			||||||
                    if index == 0 {
 | 
					                            .map(|account_id| account_id == info.account_id)
 | 
				
			||||||
                        if let Some(account_id) = self.my_stash_id {
 | 
					                            .unwrap_or_default() == true {
 | 
				
			||||||
                            current_validator_is_my_stash = account_id == info.account_id;
 | 
					                                "My stash"
 | 
				
			||||||
                        }
 | 
					                            } else {
 | 
				
			||||||
 | 
					                                "Ghostie"
 | 
				
			||||||
                            };
 | 
					                            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if current_validator_is_my_stash {
 | 
					 | 
				
			||||||
                        let name = self.known_validators
 | 
					                        let name = self.known_validators
 | 
				
			||||||
                            .get(&info.account_id)
 | 
					                            .get(&info.account_id)
 | 
				
			||||||
                            .cloned()
 | 
					                            .cloned()
 | 
				
			||||||
                            .unwrap_or("My stash".to_string());
 | 
					                            .unwrap_or(default_name.to_string());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        Row::new(vec![
 | 
					                        Row::new(vec![
 | 
				
			||||||
                            Cell::from(Text::from(is_choosen_text).alignment(Alignment::Left)),
 | 
					                            Cell::from(Text::from(is_choosen_text).alignment(Alignment::Left)),
 | 
				
			||||||
                            Cell::from(Text::from(name).alignment(Alignment::Left)),
 | 
					                            Cell::from(Text::from(name).alignment(Alignment::Left)),
 | 
				
			||||||
                            Cell::from(address_text),
 | 
					                            Cell::from(address_text),
 | 
				
			||||||
                            Cell::from(points_text), 
 | 
					                            Cell::from(points_text), 
 | 
				
			||||||
                        ]).style(self.palette.create_highlight_style())
 | 
					                        ]).style(row_style)
 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        let name = self.known_validators
 | 
					 | 
				
			||||||
                            .get(&info.account_id)
 | 
					 | 
				
			||||||
                            .cloned()
 | 
					 | 
				
			||||||
                            .unwrap_or("Ghostie".to_string());
 | 
					 | 
				
			||||||
                        Row::new(vec![
 | 
					 | 
				
			||||||
                            Cell::from(Text::from(is_choosen_text).alignment(Alignment::Left)),
 | 
					 | 
				
			||||||
                            Cell::from(Text::from(name).alignment(Alignment::Left)),
 | 
					 | 
				
			||||||
                            Cell::from(address_text),
 | 
					 | 
				
			||||||
                            Cell::from(points_text), 
 | 
					 | 
				
			||||||
                        ])
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    }),
 | 
					                    }),
 | 
				
			||||||
                [
 | 
					                [
 | 
				
			||||||
                    Constraint::Length(1),
 | 
					                    Constraint::Length(1),
 | 
				
			||||||
@ -365,9 +489,9 @@ impl Component for CurrentValidators {
 | 
				
			|||||||
                    .border_style(border_style)
 | 
					                    .border_style(border_style)
 | 
				
			||||||
                    .border_type(border_type)
 | 
					                    .border_type(border_type)
 | 
				
			||||||
                    .padding(Padding::right(2))
 | 
					                    .padding(Padding::right(2))
 | 
				
			||||||
                    .title_alignment(Alignment::Right)
 | 
					 | 
				
			||||||
                    .title_style(self.palette.create_title_style(false))
 | 
					                    .title_style(self.palette.create_title_style(false))
 | 
				
			||||||
                    .title(format!("Validators {} | Total points: {}", self.individual.len(), self.total_points)));
 | 
					                    .title_bottom(Line::from(bottom_title).left_aligned())
 | 
				
			||||||
 | 
					                    .title_top(Line::from(top_title).right_aligned()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let scrollbar = Scrollbar::default()
 | 
					            let scrollbar = Scrollbar::default()
 | 
				
			||||||
                .orientation(ScrollbarOrientation::VerticalRight)
 | 
					                .orientation(ScrollbarOrientation::VerticalRight)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,7 @@
 | 
				
			|||||||
use tokio::sync::mpsc::UnboundedSender;
 | 
					use tokio::sync::mpsc::UnboundedSender;
 | 
				
			||||||
use color_eyre::Result;
 | 
					use color_eyre::Result;
 | 
				
			||||||
use subxt::{
 | 
					use subxt::{
 | 
				
			||||||
    backend::rpc::RpcClient,
 | 
					    backend::rpc::RpcClient, tx::{TxProgress, TxStatus}, utils::H256, OnlineClient
 | 
				
			||||||
    tx::{TxProgress, TxStatus}, 
 | 
					 | 
				
			||||||
    utils::H256, 
 | 
					 | 
				
			||||||
    OnlineClient,
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod legacy_rpc_calls;
 | 
					mod legacy_rpc_calls;
 | 
				
			||||||
@ -132,7 +129,9 @@ impl Network {
 | 
				
			|||||||
                    predefined_calls::get_account_payee(&self.action_tx, &self.online_client_api, &validator_details_to_watch).await?;
 | 
					                    predefined_calls::get_account_payee(&self.action_tx, &self.online_client_api, &validator_details_to_watch).await?;
 | 
				
			||||||
                    predefined_calls::get_validators_ledger(&self.action_tx, &self.online_client_api, &validator_details_to_watch).await?;
 | 
					                    predefined_calls::get_validators_ledger(&self.action_tx, &self.online_client_api, &validator_details_to_watch).await?;
 | 
				
			||||||
                    predefined_calls::get_is_stash_bonded(&self.action_tx, &self.online_client_api, &validator_details_to_watch).await?;
 | 
					                    predefined_calls::get_is_stash_bonded(&self.action_tx, &self.online_client_api, &validator_details_to_watch).await?;
 | 
				
			||||||
 | 
					                    predefined_calls::get_nominators_by_account(&self.action_tx, &self.online_client_api, &validator_details_to_watch).await?;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                for account_id in self.accounts_to_watch.iter() {
 | 
					                for account_id in self.accounts_to_watch.iter() {
 | 
				
			||||||
                    predefined_calls::get_balance(&self.action_tx, &self.online_client_api, &account_id).await?;
 | 
					                    predefined_calls::get_balance(&self.action_tx, &self.online_client_api, &account_id).await?;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -242,6 +241,10 @@ impl Network {
 | 
				
			|||||||
                self.store_stash_or_validator_if_possible(account_id, is_stash);
 | 
					                self.store_stash_or_validator_if_possible(account_id, is_stash);
 | 
				
			||||||
                predefined_calls::get_nominators_by_validator(&self.action_tx, &self.online_client_api, &account_id).await
 | 
					                predefined_calls::get_nominators_by_validator(&self.action_tx, &self.online_client_api, &account_id).await
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
 | 
					            Action::GetNominatorsByAccount(account_id, is_stash) => {
 | 
				
			||||||
 | 
					                self.store_stash_or_validator_if_possible(account_id, is_stash);
 | 
				
			||||||
 | 
					                predefined_calls::get_nominators_by_account(&self.action_tx, &self.online_client_api, &account_id).await
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
            Action::GetValidatorAllRewards(account_id, is_stash) => {
 | 
					            Action::GetValidatorAllRewards(account_id, is_stash) => {
 | 
				
			||||||
                self.store_stash_or_validator_if_possible(account_id, is_stash);
 | 
					                self.store_stash_or_validator_if_possible(account_id, is_stash);
 | 
				
			||||||
                predefined_calls::get_validator_staking_results(&self.action_tx, &self.online_client_api, &account_id).await
 | 
					                predefined_calls::get_validator_staking_results(&self.action_tx, &self.online_client_api, &account_id).await
 | 
				
			||||||
@ -474,6 +477,24 @@ impl Network {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                Ok(())
 | 
					                Ok(())
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            Action::NominateTargets(sender, nomination_targets) => {
 | 
				
			||||||
 | 
					                let sender_str = hex::encode(sender);
 | 
				
			||||||
 | 
					                let maybe_nonce = self.senders.get_mut(&sender_str);
 | 
				
			||||||
 | 
					                if let Ok(tx_progress) = predefined_txs::nominate(
 | 
				
			||||||
 | 
					                    &self.action_tx,
 | 
				
			||||||
 | 
					                    &self.online_client_api,
 | 
				
			||||||
 | 
					                    &sender,
 | 
				
			||||||
 | 
					                    &nomination_targets,
 | 
				
			||||||
 | 
					                    maybe_nonce,
 | 
				
			||||||
 | 
					                ).await {
 | 
				
			||||||
 | 
					                    self.transactions_to_watch.push(TxToWatch {
 | 
				
			||||||
 | 
					                        tx_progress,
 | 
				
			||||||
 | 
					                        sender: sender_str,
 | 
				
			||||||
 | 
					                        target: ActionTarget::WalletLog,
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Ok(())
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            _ => Ok(())
 | 
					            _ => Ok(())
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,7 @@ use subxt::{
 | 
				
			|||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    action::Action, 
 | 
					    action::Action, 
 | 
				
			||||||
    casper_network::runtime_types::{pallet_staking::RewardDestination, sp_consensus_slots}, 
 | 
					    casper_network::runtime_types::{pallet_staking::RewardDestination, sp_consensus_slots}, 
 | 
				
			||||||
    types::{EraInfo, EraRewardPoints, Nominator, SessionKeyInfo, SystemAccount, UnlockChunk}, 
 | 
					    types::{EraInfo, EraRewardPoints, Nominator, Nominations, SessionKeyInfo, SystemAccount, UnlockChunk}, 
 | 
				
			||||||
    CasperAccountId, CasperConfig
 | 
					    CasperAccountId, CasperConfig
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -448,6 +448,27 @@ pub async fn get_validators_ledger(
 | 
				
			|||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub async fn get_nominators_by_account(
 | 
				
			||||||
 | 
					    action_tx: &UnboundedSender<Action>,
 | 
				
			||||||
 | 
					    api: &OnlineClient<CasperConfig>,
 | 
				
			||||||
 | 
					    account_id: &[u8; 32],
 | 
				
			||||||
 | 
					) -> Result<()> {
 | 
				
			||||||
 | 
					    let nominators = super::raw_calls::staking::nominators(api, None, account_id)
 | 
				
			||||||
 | 
					        .await?
 | 
				
			||||||
 | 
					        .map(|n| Nominations {
 | 
				
			||||||
 | 
					            targets: n.targets
 | 
				
			||||||
 | 
					                .0
 | 
				
			||||||
 | 
					                .into_iter()
 | 
				
			||||||
 | 
					                .map(|account_id_32| account_id_32.0)
 | 
				
			||||||
 | 
					                .collect::<Vec<_>>(),
 | 
				
			||||||
 | 
					            submitted_in: n.submitted_in,
 | 
				
			||||||
 | 
					            suppressed: n.suppressed,
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .unwrap_or_default();
 | 
				
			||||||
 | 
					    action_tx.send(Action::SetNominatorsByAccount(nominators, *account_id))?;
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
pub async fn get_nominators_by_validator(
 | 
					pub async fn get_nominators_by_validator(
 | 
				
			||||||
    action_tx: &UnboundedSender<Action>,
 | 
					    action_tx: &UnboundedSender<Action>,
 | 
				
			||||||
    api: &OnlineClient<CasperConfig>,
 | 
					    api: &OnlineClient<CasperConfig>,
 | 
				
			||||||
@ -458,21 +479,32 @@ pub async fn get_nominators_by_validator(
 | 
				
			|||||||
        .map(|era_info| era_info.index)
 | 
					        .map(|era_info| era_info.index)
 | 
				
			||||||
        .unwrap_or_default();
 | 
					        .unwrap_or_default();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let maybe_eras_stakers = super::raw_calls::staking::eras_stakers(api, None, active_era_index, account_id)
 | 
					    let maybe_eras_stakers_overview = super::raw_calls::staking::eras_stakers_overview(api, None, active_era_index, account_id)
 | 
				
			||||||
        .await?;
 | 
					        .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let nominators = match maybe_eras_stakers {
 | 
					    let nominators = match maybe_eras_stakers_overview {
 | 
				
			||||||
        Some(eras_stakers) => eras_stakers
 | 
					        Some(overview) => {
 | 
				
			||||||
            .others
 | 
					            let mut others = Vec::with_capacity(overview.nominator_count as usize);
 | 
				
			||||||
 | 
					            for page in 0..overview.page_count {
 | 
				
			||||||
 | 
					                let page_index = page as u32;
 | 
				
			||||||
 | 
					                let nominators = super::raw_calls::staking::eras_stakers_paged(api, None, active_era_index, page_index, account_id)
 | 
				
			||||||
 | 
					                    .await?;
 | 
				
			||||||
 | 
					                others.append(&mut nominators
 | 
				
			||||||
 | 
					                    .map(|n| n.others
 | 
				
			||||||
                        .iter()
 | 
					                        .iter()
 | 
				
			||||||
            .map(|info| {
 | 
					                        .map(|info| Nominator {
 | 
				
			||||||
                Nominator { 
 | 
					                            account_id: info.who.0,
 | 
				
			||||||
                    who: AccountId32::from(info.who.0)
 | 
					                            address: AccountId32::from(info.who.0)
 | 
				
			||||||
                                .to_ss58check_with_version(Ss58AddressFormat::custom(1996)),
 | 
					                                .to_ss58check_with_version(Ss58AddressFormat::custom(1996)),
 | 
				
			||||||
                            value: info.value,
 | 
					                            value: info.value,
 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                        })
 | 
					                        })
 | 
				
			||||||
            .collect::<Vec<_>>(),
 | 
					                        .collect::<Vec<_>>()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .unwrap_or_default()
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            others
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        None => Vec::new(),
 | 
					        None => Vec::new(),
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -261,6 +261,29 @@ pub async fn set_payee(
 | 
				
			|||||||
    ).await
 | 
					    ).await
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub async fn nominate(
 | 
				
			||||||
 | 
					    action_tx: &UnboundedSender<Action>,
 | 
				
			||||||
 | 
					    api: &OnlineClient<CasperConfig>,
 | 
				
			||||||
 | 
					    sender: &[u8; 32],
 | 
				
			||||||
 | 
					    nomination_targets: &Vec<[u8; 32]>,
 | 
				
			||||||
 | 
					    maybe_nonce: Option<&mut u32>,
 | 
				
			||||||
 | 
					) -> Result<TxProgress<CasperConfig, OnlineClient<CasperConfig>>> {
 | 
				
			||||||
 | 
					    let targets = nomination_targets
 | 
				
			||||||
 | 
					        .iter()
 | 
				
			||||||
 | 
					        .map(|acc| subxt::utils::MultiAddress::Id(subxt::utils::AccountId32::from(*acc)))
 | 
				
			||||||
 | 
					        .collect::<Vec<_>>();
 | 
				
			||||||
 | 
					    let nominate_tx = casper_network::tx().staking().nominate(targets);
 | 
				
			||||||
 | 
					    inner_sign_and_submit_then_watch(
 | 
				
			||||||
 | 
					        action_tx, 
 | 
				
			||||||
 | 
					        api, 
 | 
				
			||||||
 | 
					        sender, 
 | 
				
			||||||
 | 
					        maybe_nonce, 
 | 
				
			||||||
 | 
					        Box::new(nominate_tx), 
 | 
				
			||||||
 | 
					        "nominate", 
 | 
				
			||||||
 | 
					        ActionTarget::WalletLog,
 | 
				
			||||||
 | 
					    ).await
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async fn inner_sign_and_submit_then_watch(
 | 
					async fn inner_sign_and_submit_then_watch(
 | 
				
			||||||
    action_tx: &UnboundedSender<Action>,
 | 
					    action_tx: &UnboundedSender<Action>,
 | 
				
			||||||
    api: &OnlineClient<CasperConfig>,
 | 
					    api: &OnlineClient<CasperConfig>,
 | 
				
			||||||
 | 
				
			|||||||
@ -9,10 +9,11 @@ use crate::{
 | 
				
			|||||||
        self, 
 | 
					        self, 
 | 
				
			||||||
        runtime_types::{
 | 
					        runtime_types::{
 | 
				
			||||||
            pallet_staking::{
 | 
					            pallet_staking::{
 | 
				
			||||||
                slashing::SlashingSpans, ActiveEraInfo, EraRewardPoints, RewardDestination, StakingLedger, ValidatorPrefs
 | 
					                slashing::SlashingSpans, ActiveEraInfo, EraRewardPoints, 
 | 
				
			||||||
 | 
					                RewardDestination, StakingLedger, ValidatorPrefs, Nominations,
 | 
				
			||||||
            }, 
 | 
					            }, 
 | 
				
			||||||
            sp_arithmetic::per_things::Perbill, 
 | 
					            sp_arithmetic::per_things::Perbill, 
 | 
				
			||||||
            sp_staking::{Exposure, PagedExposureMetadata},
 | 
					            sp_staking::{ExposurePage, PagedExposureMetadata},
 | 
				
			||||||
        }, 
 | 
					        }, 
 | 
				
			||||||
    }, 
 | 
					    }, 
 | 
				
			||||||
    CasperConfig,
 | 
					    CasperConfig,
 | 
				
			||||||
@ -54,6 +55,17 @@ pub async fn counter_for_nominators(
 | 
				
			|||||||
    Ok(maybe_counter_for_nominators)
 | 
					    Ok(maybe_counter_for_nominators)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub async fn nominators(
 | 
				
			||||||
 | 
					    online_client: &OnlineClient<CasperConfig>,
 | 
				
			||||||
 | 
					    at_hash: Option<&H256>,
 | 
				
			||||||
 | 
					    account: &[u8; 32],
 | 
				
			||||||
 | 
					) -> Result<Option<Nominations>> {
 | 
				
			||||||
 | 
					    let account_id = super::convert_array_to_account_id(account);
 | 
				
			||||||
 | 
					    let storage_key = casper_network::storage().staking().nominators(account_id);
 | 
				
			||||||
 | 
					    let maybe_nominators = super::do_storage_call(online_client, &storage_key, at_hash).await.unwrap();
 | 
				
			||||||
 | 
					    Ok(maybe_nominators)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn eras_total_stake(
 | 
					pub async fn eras_total_stake(
 | 
				
			||||||
    online_client: &OnlineClient<CasperConfig>,
 | 
					    online_client: &OnlineClient<CasperConfig>,
 | 
				
			||||||
    at_hash: Option<&H256>,
 | 
					    at_hash: Option<&H256>,
 | 
				
			||||||
@ -119,16 +131,17 @@ pub async fn ledger(
 | 
				
			|||||||
    Ok(maybe_ledger)
 | 
					    Ok(maybe_ledger)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn eras_stakers(
 | 
					pub async fn eras_stakers_paged(
 | 
				
			||||||
    online_client: &OnlineClient<CasperConfig>,
 | 
					    online_client: &OnlineClient<CasperConfig>,
 | 
				
			||||||
    at_hash: Option<&H256>,
 | 
					    at_hash: Option<&H256>,
 | 
				
			||||||
    era_index: u32,
 | 
					    era_index: u32,
 | 
				
			||||||
 | 
					    page_index: u32,
 | 
				
			||||||
    account: &[u8; 32],
 | 
					    account: &[u8; 32],
 | 
				
			||||||
) -> Result<Option<Exposure<AccountId32, u128>>> {
 | 
					) -> Result<Option<ExposurePage<AccountId32, u128>>> {
 | 
				
			||||||
    let account_id = super::convert_array_to_account_id(account);
 | 
					    let account_id = super::convert_array_to_account_id(account);
 | 
				
			||||||
    let storage_key = casper_network::storage().staking().eras_stakers(era_index, account_id);
 | 
					    let storage_key = casper_network::storage().staking().eras_stakers_paged(era_index, account_id, page_index);
 | 
				
			||||||
    let maybe_eras_stakers = super::do_storage_call(online_client, &storage_key, at_hash).await?;
 | 
					    let maybe_eras_stakers_paged = super::do_storage_call(online_client, &storage_key, at_hash).await?;
 | 
				
			||||||
    Ok(maybe_eras_stakers)
 | 
					    Ok(maybe_eras_stakers_paged)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn bonded(
 | 
					pub async fn bonded(
 | 
				
			||||||
 | 
				
			|||||||
@ -15,5 +15,6 @@ pub use account::SystemAccount;
 | 
				
			|||||||
pub use peer::PeerInformation;
 | 
					pub use peer::PeerInformation;
 | 
				
			||||||
pub use session::SessionKeyInfo;
 | 
					pub use session::SessionKeyInfo;
 | 
				
			||||||
pub use nominator::Nominator;
 | 
					pub use nominator::Nominator;
 | 
				
			||||||
 | 
					pub use nominator::Nominations;
 | 
				
			||||||
pub use staking::UnlockChunk;
 | 
					pub use staking::UnlockChunk;
 | 
				
			||||||
pub use staking::RewardDestination;
 | 
					pub use staking::RewardDestination;
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,14 @@ use serde::{Serialize, Deserialize};
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Decode)]
 | 
					#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Decode)]
 | 
				
			||||||
pub struct Nominator {
 | 
					pub struct Nominator {
 | 
				
			||||||
    pub who: String,
 | 
					    pub account_id: [u8; 32],
 | 
				
			||||||
 | 
					    pub address: String,
 | 
				
			||||||
    pub value: u128,
 | 
					    pub value: u128,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Decode)]
 | 
				
			||||||
 | 
					pub struct Nominations {
 | 
				
			||||||
 | 
					    pub targets: Vec<[u8; 32]>,
 | 
				
			||||||
 | 
					    pub submitted_in: u32,
 | 
				
			||||||
 | 
					    pub suppressed: bool,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user