From 2afc38068a7b773bbf002d642901a27cc4af0f6a Mon Sep 17 00:00:00 2001 From: Uncle Stretch Date: Sun, 16 Feb 2025 16:23:00 +0300 Subject: [PATCH] additional validator info in nominator tab Signed-off-by: Uncle Stretch --- Cargo.toml | 2 +- src/action.rs | 6 +-- .../nominator/current_validator_details.rs | 54 ++++++++++++++++++- src/components/validator/reward_details.rs | 2 +- src/components/validator/stash_details.rs | 2 +- src/components/validator/withdraw_popup.rs | 9 +++- src/network/predefined_calls.rs | 15 +++--- 7 files changed, 72 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b500431..5ce1e1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "ghost-eye" authors = ["str3tch "] description = "Application for interacting with Casper/Ghost nodes that are exposing RPC only to the localhost" -version = "0.3.26" +version = "0.3.27" edition = "2021" [dependencies] diff --git a/src/action.rs b/src/action.rs index f77686d..dd894eb 100644 --- a/src/action.rs +++ b/src/action.rs @@ -114,7 +114,7 @@ pub enum Action { SetStashAccount([u8; 32]), SetStashSecret([u8; 32]), SetChoosenValidator([u8; 32], u32, u32), - SetSlashingSpansLength(usize), + SetSlashingSpansLength(usize, [u8; 32]), SetUnlockingIsEmpty(bool), BestBlockInformation(H256, u32), @@ -134,9 +134,9 @@ pub enum Action { SetValidatorEraSlash(u32, u128), SetValidatorEraUnlocking(u32, u128), SetIsBonded(bool), - SetStakedAmountRatio(u128, u128), + SetStakedAmountRatio(u128, u128, [u8; 32]), SetStakedRatio(u128, u128, [u8; 32]), - SetValidatorPrefs(u32, bool, [u8; 32]), + SetValidatorPrefs(Option, bool, [u8; 32]), SetCurrentValidatorEraRewards(u32, u32, Vec), GetTotalIssuance, diff --git a/src/components/nominator/current_validator_details.rs b/src/components/nominator/current_validator_details.rs index 16f5cb6..eb4ac0c 100644 --- a/src/components/nominator/current_validator_details.rs +++ b/src/components/nominator/current_validator_details.rs @@ -19,9 +19,12 @@ pub struct CurrentValidatorDetails { choosen: [u8; 32], total_balance: u128, own_balance: u128, + active_stake: u128, others_len: usize, commission: f64, points_ratio: f64, + is_active_validator: bool, + is_nomination_disabled: bool, } impl Default for CurrentValidatorDetails { @@ -41,10 +44,13 @@ impl CurrentValidatorDetails { choosen: [0u8; 32], total_balance: 0, own_balance: 0, + active_stake: 0, others_len: 0, commission: 0.0, points_ratio: 0.0, palette: Default::default(), + is_active_validator: false, + is_nomination_disabled: false, } } @@ -54,6 +60,37 @@ impl CurrentValidatorDetails { format!("{:.after$}{}", value, Self::TICKER) } + fn prepare_stake_imbalance(&self) -> String { + let (value, prefix) = if self.own_balance <= self.active_stake { + (self.active_stake.saturating_sub(self.own_balance), "+") + } else { + (self.own_balance.saturating_sub(self.active_stake), "-") + }; + format!("{}{}", prefix, self.prepare_u128(value)) + } + + fn prepare_state_string(&self) -> String { + if self.is_active_validator { + "active staking".to_string() + } else { + "stop staking".to_string() + } + } + + fn update_commission(&mut self, maybe_commission: Option, is_disabled: bool) { + self.is_nomination_disabled = is_disabled; + match maybe_commission { + Some(commission) => { + self.commission = commission as f64 / 1_000_000_000.0; + self.is_active_validator = true; + }, + None => { + self.commission = 0.0; + self.is_active_validator = false; + }, + } + } + fn update_choosen_validator(&mut self, account_id: [u8; 32], individual: u32, total: u32) { self.choosen = account_id; self.points_ratio = match total { @@ -64,6 +101,7 @@ impl CurrentValidatorDetails { let _ = network_tx.send(Action::GetErasStakersOverview(account_id, false)); let _ = network_tx.send(Action::GetNominatorsByValidator(account_id, false)); let _ = network_tx.send(Action::GetValidatorPrefs(account_id, false)); + let _ = network_tx.send(Action::GetValidatorLedger(account_id, false)); } } } @@ -95,9 +133,9 @@ impl Component for CurrentValidatorDetails { fn update(&mut self, action: Action) -> Result> { match action { Action::SetChoosenValidator(account_id, individual, total) => self.update_choosen_validator(account_id, individual, total), + Action::SetValidatorPrefs(commission, is_disabled, account_id) if self.choosen == account_id => self.update_commission(commission, is_disabled), Action::SetNominatorsByValidator(noms, account_id) if self.choosen == account_id => self.others_len = noms.len(), - Action::SetValidatorPrefs(commission, _, account_id) if self.choosen == account_id => - self.commission = commission as f64 / 1_000_000_000.0, + Action::SetStakedAmountRatio(_, active_stake, account_id) if self.choosen == account_id => self.active_stake = active_stake, Action::SetStakedRatio(total, own, account_id) if self.choosen == account_id => { self.total_balance = total; self.own_balance = own; @@ -113,6 +151,10 @@ impl Component for CurrentValidatorDetails { let table = Table::new( vec![ + Row::new(vec![ + Cell::from(Text::from("Forbidden".to_string()).alignment(Alignment::Left)), + Cell::from(Text::from(self.is_nomination_disabled.to_string()).alignment(Alignment::Right)), + ]), Row::new(vec![ Cell::from(Text::from("Total staked".to_string()).alignment(Alignment::Left)), Cell::from(Text::from(self.prepare_u128(self.total_balance)).alignment(Alignment::Right)), @@ -133,6 +175,14 @@ impl Component for CurrentValidatorDetails { Cell::from(Text::from("Points ratio".to_string()).alignment(Alignment::Left)), Cell::from(Text::from(format!("{:.4}%", self.points_ratio)).alignment(Alignment::Right)), ]), + Row::new(vec![ + Cell::from(Text::from("In next era".to_string()).alignment(Alignment::Left)), + Cell::from(Text::from(self.prepare_state_string()).alignment(Alignment::Right)), + ]), + Row::new(vec![ + Cell::from(Text::from("Imbalance".to_string()).alignment(Alignment::Left)), + Cell::from(Text::from(self.prepare_stake_imbalance()).alignment(Alignment::Right)), + ]), ], [ Constraint::Max(12), diff --git a/src/components/validator/reward_details.rs b/src/components/validator/reward_details.rs index aa6bb04..b8fc8f6 100644 --- a/src/components/validator/reward_details.rs +++ b/src/components/validator/reward_details.rs @@ -76,7 +76,7 @@ impl Component for RewardDetails { match action { Action::SetStashAccount(stash) => self.stash = stash, Action::SetValidatorPrefs(commission, disabled, account_id) if self.stash == account_id => { - self.commission = Some(commission); + self.commission = commission; self.nominators_blocked = disabled; } Action::Apy(apy) => self.apy = apy, diff --git a/src/components/validator/stash_details.rs b/src/components/validator/stash_details.rs index 5ebdab1..979debf 100644 --- a/src/components/validator/stash_details.rs +++ b/src/components/validator/stash_details.rs @@ -99,7 +99,7 @@ impl Component for StashDetails { Action::SetStashSecret(secret) => self.stash_secret = secret, Action::SetStashAccount(account_id) => self.stash_account_id = account_id, Action::SetIsBonded(is_bonded) => self.is_bonded = is_bonded, - Action::SetStakedAmountRatio(total, active) => { + Action::SetStakedAmountRatio(total, active, account_id) if self.stash_account_id == account_id => { self.staked_total = Some(total); self.staked_active = Some(active); }, diff --git a/src/components/validator/withdraw_popup.rs b/src/components/validator/withdraw_popup.rs index 237306a..2081158 100644 --- a/src/components/validator/withdraw_popup.rs +++ b/src/components/validator/withdraw_popup.rs @@ -21,6 +21,7 @@ pub struct WithdrawPopup { is_active: bool, action_tx: Option>, network_tx: Option>, + stash_account: [u8; 32], secret_seed: [u8; 32], slashing_spans_length: u32, unlocking_is_empty: bool, @@ -39,6 +40,7 @@ impl WithdrawPopup { pub fn new() -> Self { Self { is_active: false, + stash_account: [0u8; 32], secret_seed: [0u8; 32], slashing_spans_length: 0u32, unlocking_is_empty: false, @@ -118,9 +120,12 @@ impl Component for WithdrawPopup { fn update(&mut self, action: Action) -> Result> { match action { + Action::SetStashAccount(account_id) => self.stash_account = account_id, Action::SetStashSecret(secret_seed) => self.secret_seed = secret_seed, - Action::SetSlashingSpansLength(length) => self.slashing_spans_length = length as u32, - Action::SetStakedAmountRatio(_, active_balance) => self.active_balance = active_balance, + Action::SetSlashingSpansLength(length, account_id) if self.stash_account == account_id => + self.slashing_spans_length = length as u32, + Action::SetStakedAmountRatio(_, active_balance, account_id) if self.stash_account == account_id => + self.active_balance = active_balance, Action::SetUnlockingIsEmpty(is_empty) => self.unlocking_is_empty = is_empty, Action::SetExistentialDeposit(existential_deposit) => self.existential_deposit = existential_deposit, _ => {} diff --git a/src/network/predefined_calls.rs b/src/network/predefined_calls.rs index b64d2ac..bf3e8e4 100644 --- a/src/network/predefined_calls.rs +++ b/src/network/predefined_calls.rs @@ -434,7 +434,7 @@ pub async fn get_validators_ledger( .await?; if let Some(ledger) = maybe_ledger { - action_tx.send(Action::SetStakedAmountRatio(ledger.total, ledger.active))?; + action_tx.send(Action::SetStakedAmountRatio(ledger.total, ledger.active, *account_id))?; action_tx.send(Action::SetUnlockingIsEmpty(ledger.unlocking.0.is_empty()))?; for chunk in ledger.unlocking.0.iter() { action_tx.send(Action::SetValidatorEraUnlocking(chunk.era, chunk.value))?; @@ -514,12 +514,11 @@ pub async fn get_validator_prefs( ) -> Result<()> { let maybe_validator_prefs = super::raw_calls::staking::validators(api, None, account_id) .await?; - if let Some(prefs) = maybe_validator_prefs { - action_tx.send(Action::SetValidatorPrefs( - prefs.commission.0, - prefs.blocked, - *account_id))?; - } + let (comission, blocked) = match maybe_validator_prefs { + Some(prefs) => (Some(prefs.commission.0), prefs.blocked), + None => (None, false), + }; + action_tx.send(Action::SetValidatorPrefs(comission, blocked, *account_id))?; Ok(()) } @@ -543,6 +542,6 @@ pub async fn get_slashing_spans( .await? .map(|spans| spans.prior.len()) .unwrap_or_default(); - action_tx.send(Action::SetSlashingSpansLength(slashing_spans_length))?; + action_tx.send(Action::SetSlashingSpansLength(slashing_spans_length, *account_id))?; Ok(()) }