diff --git a/Cargo.toml b/Cargo.toml index bfd2d38..7681f88 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.75" +version = "0.3.76" edition = "2021" homepage = "https://git.ghostchain.io/ghostchain" repository = "https://git.ghostchain.io/ghostchain/ghost-eye" diff --git a/src/action.rs b/src/action.rs index a6f331b..04e9ff8 100644 --- a/src/action.rs +++ b/src/action.rs @@ -1,13 +1,13 @@ use serde::{Deserialize, Serialize}; use strum::Display; -use subxt::utils::H256; use subxt::config::substrate::DigestItem; +use subxt::utils::H256; use crate::types::{ - ActionLevel, ActionTarget, CasperExtrinsicDetails, EraInfo, EraRewardPoints, - Nominator, Nominations, PeerInformation, SessionKeyInfo, UnlockChunk, SystemAccount, - RewardDestination, Gatekeeper, BlockRange, + ActionLevel, ActionTarget, BlockRange, CasperExtrinsicDetails, EraInfo, EraRewardPoints, + Gatekeeper, Nominations, Nominator, PeerInformation, RewardDestination, SessionKeyInfo, + SystemAccount, UnlockChunk, }; #[derive(Debug, Clone, PartialEq, Eq, Display, Serialize, Deserialize)] @@ -141,7 +141,7 @@ pub enum Action { SetActiveEra(EraInfo), SetCurrentEra(u32), SetEpochProgress(u64, u64), - SetPendingExtrinsicsLength(usize), + SetPendingExtrinsicsLength(usize), SetConnectedPeers(Vec), SetSessionKey(String, SessionKeyInfo), SetListenAddresses(Vec), diff --git a/src/app.rs b/src/app.rs index 17e38fb..b642f18 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,19 +1,18 @@ use color_eyre::Result; use crossterm::event::KeyEvent; use ratatui::prelude::Rect; -use tokio::sync::mpsc::{UnboundedSender, UnboundedReceiver}; use std::sync::mpsc::Sender; +use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender}; use tracing::info; use crate::{ action::Action, + components::{ + empty::Empty, explorer::Explorer, fps::FpsCounter, health::Health, help::Help, menu::Menu, + validator::Validator, version::Version, wallet::Wallet, Component, + }, config::Config, tui::{Event, Tui}, - components::{ - menu::Menu, version::Version, explorer::Explorer, wallet::Wallet, - validator::Validator, empty::Empty, help::Help, health::Health, - fps::FpsCounter, Component, - }, }; pub use crate::modes::Mode; @@ -190,7 +189,9 @@ impl App { fn handle_actions(&mut self, tui: &mut Tui) -> Result<()> { while let Ok(action) = self.action_rx.try_recv() { match action { - Action::Tick => { self.last_tick_key_events.drain(..); }, + Action::Tick => { + self.last_tick_key_events.drain(..); + } Action::Quit => self.should_quite = true, Action::Suspend => self.should_suspend = true, Action::Resume => self.should_suspend = false, @@ -226,7 +227,7 @@ impl App { .send(Action::Error(format!("failed to draw: {:?}", err))); } } - }, + } Mode::Wallet => { if let Some(component) = self.components.get_mut(6) { if let Err(err) = component.draw(frame, frame.area()) { @@ -235,7 +236,7 @@ impl App { .send(Action::Error(format!("failed to draw: {:?}", err))); } } - }, + } Mode::Validator => { if let Some(component) = self.components.get_mut(7) { if let Err(err) = component.draw(frame, frame.area()) { @@ -244,7 +245,7 @@ impl App { .send(Action::Error(format!("failed to draw: {:?}", err))); } } - }, + } _ => { if let Some(component) = self.components.last_mut() { if let Err(err) = component.draw(frame, frame.area()) { @@ -253,7 +254,7 @@ impl App { .send(Action::Error(format!("failed to draw: {:?}", err))); } } - }, + } } for component in self.components.iter_mut().take(5) { diff --git a/src/casper.rs b/src/casper.rs index 2447517..6df27ee 100644 --- a/src/casper.rs +++ b/src/casper.rs @@ -1,8 +1,10 @@ //! Casper specific configuration use subxt::{ - Config, blocks::Block, client::OnlineClient, - config::{DefaultExtrinsicParamsBuilder, DefaultExtrinsicParams, SubstrateConfig}, + blocks::Block, + client::OnlineClient, + config::{DefaultExtrinsicParams, DefaultExtrinsicParamsBuilder, SubstrateConfig}, + Config, }; /// Default set of commonly used type by Casper nodes. @@ -21,7 +23,7 @@ impl Config for CasperConfig { } /// A 32-byte cryptographic identifier. This is a simplified version of -/// `sp_core::crypto::AccountId32`. +/// `sp_core::crypto::AccountId32`. pub type CasperAccountId = subxt::utils::AccountId32; pub type CasperBlock = Block>; diff --git a/src/components/empty.rs b/src/components/empty.rs index 004c45a..303351e 100644 --- a/src/components/empty.rs +++ b/src/components/empty.rs @@ -1,5 +1,5 @@ use color_eyre::Result; -use crossterm::event::{KeyEvent, KeyCode}; +use crossterm::event::{KeyCode, KeyEvent}; use ratatui::{ layout::{Alignment, Rect}, text::Line, @@ -8,10 +8,7 @@ use ratatui::{ }; use super::Component; -use crate::{ - components::generic::Activatable, - action::Action, app::Mode -}; +use crate::{action::Action, app::Mode, components::generic::Activatable}; #[derive(Debug, Clone, Default)] pub struct Empty { @@ -19,10 +16,18 @@ pub struct Empty { } impl Activatable for Empty { - fn is_active(&self) -> bool { self.is_active } - fn is_inactive(&self) -> bool { !self.is_active } - fn set_inactive(&mut self) { self.is_active = false; } - fn set_active(&mut self) { self.is_active = true; } + fn is_active(&self) -> bool { + self.is_active + } + fn is_inactive(&self) -> bool { + !self.is_active + } + fn set_inactive(&mut self) { + self.is_active = false; + } + fn set_active(&mut self) { + self.is_active = true; + } } impl Empty { @@ -110,7 +115,7 @@ impl Component for Empty { fn handle_key_event(&mut self, key: KeyEvent) -> Result> { match key.code { - KeyCode::Esc if self.is_active() => self.move_out(), + KeyCode::Esc if self.is_active() => self.move_out(), _ => Ok(None), } } @@ -125,10 +130,7 @@ impl Component for Empty { }; let lines_len = lines.len() as u16; - let padding_top = screen - .as_size() - .height - .saturating_sub(lines_len) / 2; + let padding_top = screen.as_size().height.saturating_sub(lines_len) / 2; let paragraph = Paragraph::new(lines) .block(Block::bordered().padding(Padding::new(0, 0, padding_top / 2, 0))) diff --git a/src/components/explorer/block_explorer.rs b/src/components/explorer/block_explorer.rs index 23155e6..abc687b 100644 --- a/src/components/explorer/block_explorer.rs +++ b/src/components/explorer/block_explorer.rs @@ -3,17 +3,19 @@ use crossterm::event::KeyEvent; use ratatui::layout::{Constraint, Margin}; use ratatui::widgets::{Padding, Scrollbar, ScrollbarOrientation}; use ratatui::{ + layout::{Alignment, Rect}, text::Text, - layout::{Alignment, Rect}, - widgets::{Block, ScrollbarState, Cell, Row, Table, TableState}, - Frame + widgets::{Block, Cell, Row, ScrollbarState, Table, TableState}, + Frame, }; use subxt::utils::H256; use super::{Component, CurrentTab}; use crate::{ - components::generic::{Activatable, Scrollable, PartialComponent}, - action::Action, config::Config, palette::StylePalette, + action::Action, + components::generic::{Activatable, PartialComponent, Scrollable}, + config::Config, + palette::StylePalette, }; #[derive(Debug, Default)] @@ -39,10 +41,18 @@ impl Default for BlockExplorer { } impl Activatable for BlockExplorer { - fn is_active(&self) -> bool { self.is_active } - fn is_inactive(&self) -> bool { !self.is_active } - fn set_inactive(&mut self) { self.is_active = false; } - fn set_active(&mut self) { self.is_active = true; } + fn is_active(&self) -> bool { + self.is_active + } + fn is_inactive(&self) -> bool { + !self.is_active + } + fn set_inactive(&mut self) { + self.is_active = false; + } + fn set_active(&mut self) { + self.is_active = true; + } } impl Scrollable for BlockExplorer { @@ -101,7 +111,8 @@ impl BlockExplorer { hash: H256, block_number: u32, ) -> Result> { - let front_block_number = self.blocks + let front_block_number = self + .blocks .front() .map(|block| block.block_number) .unwrap_or_default(); @@ -125,7 +136,7 @@ impl BlockExplorer { return match self.table_state.selected() { Some(_) => self.next_row(), None => Ok(None), - } + }; } Ok(None) } @@ -136,9 +147,11 @@ impl BlockExplorer { block_number: u32, ) -> Result> { for idx in 0..self.items_length() { - if self.blocks[idx].finalized { break; } - else if self.blocks[idx].block_number > block_number { continue; } - else { + if self.blocks[idx].finalized { + break; + } else if self.blocks[idx].block_number > block_number { + continue; + } else { self.block_headers.insert(block_number, header); self.blocks[idx].finalized = true; } @@ -161,7 +174,7 @@ impl PartialComponent for BlockExplorer { self.set_inactive(); self.table_state.select(None); self.scroll_state = self.scroll_state.position(0); - }, + } } } } @@ -169,26 +182,38 @@ impl PartialComponent for BlockExplorer { impl Component for BlockExplorer { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Explorer) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } Ok(()) } fn update(&mut self, action: Action) -> Result> { match action { - Action::BestBlockInformation(header, block_number) => self.update_latest_block_info(header, block_number), - Action::FinalizedBlockInformation(header, block_number) => self.update_finalized_block_info(header, block_number), + Action::BestBlockInformation(header, block_number) => { + self.update_latest_block_info(header, block_number) + } + Action::FinalizedBlockInformation(header, block_number) => { + self.update_finalized_block_info(header, block_number) + } Action::SetBlockAuthor(header, author) => { let _ = self.block_authors.insert(header, author); Ok(None) - }, + } _ => Ok(None), } } @@ -206,25 +231,30 @@ impl Component for BlockExplorer { let (border_style, border_type) = self.palette.create_border_style(self.is_active()); let default_hash = H256::repeat_byte(69u8); let default_author = "...".to_string(); - let rows = self.blocks + let rows = self + .blocks .iter() .map(|info| { - let header = self.block_headers + let header = self + .block_headers .get(&info.block_number) .unwrap_or(&default_hash); - let author = self.block_authors - .get(&header) - .unwrap_or(&default_author); + let author = self.block_authors.get(&header).unwrap_or(&default_author); if info.finalized { Row::new(vec![ - Cell::from(Text::from(info.block_number.to_string()).alignment(Alignment::Left)), + Cell::from( + Text::from(info.block_number.to_string()).alignment(Alignment::Left), + ), Cell::from(Text::from(header.to_string()).alignment(Alignment::Center)), Cell::from(Text::from(author.clone()).alignment(Alignment::Right)), - ]).style(self.palette.create_highlight_style()) + ]) + .style(self.palette.create_highlight_style()) } else { Row::new(vec![ - Cell::from(Text::from(info.block_number.to_string()).alignment(Alignment::Left)), + Cell::from( + Text::from(info.block_number.to_string()).alignment(Alignment::Left), + ), Cell::from(Text::from(header.to_string()).alignment(Alignment::Center)), Cell::from(Text::from(author.clone()).alignment(Alignment::Right)), ]) @@ -232,12 +262,14 @@ impl Component for BlockExplorer { }) .collect::>(); - let max_block_number_length = self.blocks + let max_block_number_length = self + .blocks .front() .map(|block| block.block_number) .unwrap_or_default() .checked_ilog10() - .unwrap_or(0) as u16 + 1; + .unwrap_or(0) as u16 + + 1; let table = Table::new( rows, @@ -250,13 +282,15 @@ impl Component for BlockExplorer { .style(self.palette.create_basic_style(false)) .highlight_style(self.palette.create_basic_style(true)) .column_spacing(1) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .padding(Padding::right(2)) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("Blocks")); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .padding(Padding::right(2)) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("Blocks"), + ); let scrollbar = Scrollbar::default() .orientation(ScrollbarOrientation::VerticalRight) @@ -266,8 +300,11 @@ impl Component for BlockExplorer { frame.render_stateful_widget(table, place, &mut self.table_state); frame.render_stateful_widget( - scrollbar, - place.inner(Margin { vertical: 1, horizontal: 1 }), + scrollbar, + place.inner(Margin { + vertical: 1, + horizontal: 1, + }), &mut self.scroll_state, ); diff --git a/src/components/explorer/block_ticker.rs b/src/components/explorer/block_ticker.rs index 899b10f..6a94557 100644 --- a/src/components/explorer/block_ticker.rs +++ b/src/components/explorer/block_ticker.rs @@ -2,23 +2,25 @@ use std::time::Instant; use color_eyre::Result; use ratatui::{ - layout::{Alignment, Rect}, - widgets::{Block, Padding, Paragraph, Wrap}, - Frame + layout::{Alignment, Rect}, + widgets::{Block, Padding, Paragraph, Wrap}, + Frame, }; use super::{Component, CurrentTab}; use crate::{ + action::Action, components::generic::PartialComponent, - config::Config, action::Action, palette::StylePalette, - widgets::{BigText, PixelSize}, + config::Config, + palette::StylePalette, + widgets::{BigText, PixelSize}, }; #[derive(Debug)] pub struct BlockTicker { last_block: u32, last_block_time: Instant, - palette: StylePalette + palette: StylePalette, } impl Default for BlockTicker { @@ -49,12 +51,18 @@ impl PartialComponent for BlockTicker {} impl Component for BlockTicker { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Explorer) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); } Ok(()) } @@ -88,13 +96,15 @@ impl Component for BlockTicker { if width < text_width || height < 7 { let paragraph = Paragraph::new(text) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .padding(Padding::new(0, 0, height.saturating_sub(2) / 2, 0)) - .title("Passed")) + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .padding(Padding::new(0, 0, height.saturating_sub(2) / 2, 0)) + .title("Passed"), + ) .alignment(Alignment::Center) .wrap(Wrap { trim: true }); frame.render_widget(paragraph, place); @@ -103,23 +113,27 @@ impl Component for BlockTicker { .centered() .pixel_size(PixelSize::Quadrant) .style(self.palette.create_basic_style(false)) - .lines(vec![ - text.into(), - ]) + .lines(vec![text.into()]) .build(); let paragraph = Paragraph::new("") - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("Passed")) + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("Passed"), + ) .alignment(Alignment::Center) .wrap(Wrap { trim: true }); frame.render_widget(paragraph, place); let height_offset = height.saturating_sub(2) / 2; - let place = place.offset(ratatui::layout::Offset { x: 1, y: height_offset as i32 }) + let place = place + .offset(ratatui::layout::Offset { + x: 1, + y: height_offset as i32, + }) .intersection(place); frame.render_widget(big_text, place); } diff --git a/src/components/explorer/current_epoch.rs b/src/components/explorer/current_epoch.rs index eb1790b..841533f 100644 --- a/src/components/explorer/current_epoch.rs +++ b/src/components/explorer/current_epoch.rs @@ -1,16 +1,18 @@ use color_eyre::Result; use ratatui::{ - layout::{Alignment, Rect}, - text::Line, + layout::{Alignment, Rect}, + text::Line, widgets::{Block, Padding, Paragraph, Wrap}, Frame, }; use super::{Component, CurrentTab}; use crate::{ + action::Action, components::generic::PartialComponent, - config::Config, action::Action, palette::StylePalette, - widgets::{PixelSize, BigText}, + config::Config, + palette::StylePalette, + widgets::{BigText, PixelSize}, }; #[derive(Debug, Default)] @@ -22,9 +24,9 @@ pub struct CurrentEpoch { impl CurrentEpoch { const SECONDS_IN_BLOCK: u64 = 6; - const SESSION_LENGTH: u64 = 2_400; - const SECONDS_IN_DAY: u64 = 86_400; - const SECONDS_IN_HOUR: u64 = 3_600; + const SESSION_LENGTH: u64 = 2_400; + const SECONDS_IN_DAY: u64 = 86_400; + const SECONDS_IN_HOUR: u64 = 3_600; } impl PartialComponent for CurrentEpoch {} @@ -32,12 +34,18 @@ impl PartialComponent for CurrentEpoch {} impl Component for CurrentEpoch { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Explorer) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); } Ok(()) } @@ -47,7 +55,7 @@ impl Component for CurrentEpoch { Action::SetEpochProgress(number, progress) => { self.number = number; self.progress = progress; - }, + } _ => {} }; Ok(None) @@ -56,14 +64,15 @@ impl Component for CurrentEpoch { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { let [place, _] = super::layouts::explorer_era_info_layout(area); - let seconds_to_next = Self::SESSION_LENGTH.saturating_sub(self.progress) * Self::SECONDS_IN_BLOCK; + let seconds_to_next = + Self::SESSION_LENGTH.saturating_sub(self.progress) * Self::SECONDS_IN_BLOCK; let hours = (seconds_to_next % Self::SECONDS_IN_DAY) / Self::SECONDS_IN_HOUR; let minutes = (seconds_to_next % Self::SECONDS_IN_HOUR) / 60; let seconds = seconds_to_next % 60; let text = self.number.to_string(); let big_time = hours > 0; - + let (border_style, border_type) = self.palette.create_border_style(false); let height = place.as_size().height; @@ -73,20 +82,24 @@ impl Component for CurrentEpoch { if width < text_width || height < 7 { let text = vec![ Line::from(text), - Line::from(format!("{}{} {}{}", - if big_time { hours } else { minutes }, - if big_time { "hrs" } else { "mins" }, - if big_time { minutes } else { seconds }, - if big_time { "mins" } else { "secs" })), + Line::from(format!( + "{}{} {}{}", + if big_time { hours } else { minutes }, + if big_time { "hrs" } else { "mins" }, + if big_time { minutes } else { seconds }, + if big_time { "mins" } else { "secs" } + )), ]; let paragraph = Paragraph::new(text) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .padding(Padding::new(0, 0, height.saturating_sub(3) / 2, 0)) - .title("Epoch")) + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .padding(Padding::new(0, 0, height.saturating_sub(3) / 2, 0)) + .title("Epoch"), + ) .alignment(Alignment::Center) .wrap(Wrap { trim: true }); frame.render_widget(paragraph, place); @@ -95,28 +108,36 @@ impl Component for CurrentEpoch { .centered() .pixel_size(PixelSize::Quadrant) .style(self.palette.create_basic_style(false)) - .lines(vec![ - text.into(), - ]) + .lines(vec![text.into()]) .build(); let paragraph = Paragraph::new("") - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_style(self.palette.create_title_style(false)) - .title_top(Line::from("Epoch").right_aligned()) - .title_top(Line::from(format!("{}{} {}{}", + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_style(self.palette.create_title_style(false)) + .title_top(Line::from("Epoch").right_aligned()) + .title_top( + Line::from(format!( + "{}{} {}{}", if big_time { hours } else { minutes }, if big_time { "hrs" } else { "mins" }, if big_time { minutes } else { seconds }, - if big_time { "mins" } else { "secs" })) - .centered())) + if big_time { "mins" } else { "secs" } + )) + .centered(), + ), + ) .alignment(Alignment::Center) .wrap(Wrap { trim: true }); frame.render_widget(paragraph, place); let height_offset = height.saturating_sub(2) / 2; - let place = place.offset(ratatui::layout::Offset { x: 1, y: height_offset as i32 }) + let place = place + .offset(ratatui::layout::Offset { + x: 1, + y: height_offset as i32, + }) .intersection(place); frame.render_widget(big_text, place); } diff --git a/src/components/explorer/current_era.rs b/src/components/explorer/current_era.rs index 8684ae0..b8795e9 100644 --- a/src/components/explorer/current_era.rs +++ b/src/components/explorer/current_era.rs @@ -8,22 +8,26 @@ use ratatui::{ use super::{Component, CurrentTab}; use crate::{ - config::Config, action::Action, palette::StylePalette, types::EraInfo, - components::generic::PartialComponent, widgets::{PixelSize, BigText}, + action::Action, + components::generic::PartialComponent, + config::Config, + palette::StylePalette, + types::EraInfo, + widgets::{BigText, PixelSize}, }; #[derive(Debug, Default)] -pub struct CurrentEra{ +pub struct CurrentEra { era: EraInfo, palette: StylePalette, } impl CurrentEra { - const ERA_OFFSET_IN_SLOTS: u64 = 2_400 * 6; + const ERA_OFFSET_IN_SLOTS: u64 = 2_400 * 6; const ERA_OFFSET_IN_MILLIS: u64 = Self::ERA_OFFSET_IN_SLOTS * 6_000; - const MILLIS_IN_DAY: u64 = 86_400_000; - const MILLIS_IN_HOUR: u64 = 3_600_000; + const MILLIS_IN_DAY: u64 = 86_400_000; + const MILLIS_IN_HOUR: u64 = 3_600_000; const MILLIS_IN_MINUTE: u64 = 60_000; } @@ -32,12 +36,18 @@ impl PartialComponent for CurrentEra {} impl Component for CurrentEra { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Explorer) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); } Ok(()) } @@ -45,7 +55,7 @@ impl Component for CurrentEra { fn update(&mut self, action: Action) -> Result> { match action { Action::SetActiveEra(era_info) => self.era = era_info, - _ => {}, + _ => {} }; Ok(None) } @@ -73,7 +83,7 @@ impl Component for CurrentEra { let text = self.era.index.to_string(); let big_time = hours > 0; - + let (border_style, border_type) = self.palette.create_border_style(false); let height = place.as_size().height; @@ -83,21 +93,25 @@ impl Component for CurrentEra { if width < text_width || height < 7 { let text = vec![ Line::from(text), - Line::from(format!("{}{}{} {}{}", - reversed_char, - if big_time { hours } else { minutes }, - if big_time { "hrs" } else { "mins" }, - if big_time { minutes } else { seconds }, - if big_time { "mins" } else { "secs" })), + Line::from(format!( + "{}{}{} {}{}", + reversed_char, + if big_time { hours } else { minutes }, + if big_time { "hrs" } else { "mins" }, + if big_time { minutes } else { seconds }, + if big_time { "mins" } else { "secs" } + )), ]; let paragraph = Paragraph::new(text) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .padding(Padding::new(0, 0, (height.saturating_sub(3)) / 2, 0)) - .title("Era")) + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .padding(Padding::new(0, 0, (height.saturating_sub(3)) / 2, 0)) + .title("Era"), + ) .alignment(Alignment::Center) .wrap(Wrap { trim: true }); frame.render_widget(paragraph, place); @@ -106,28 +120,36 @@ impl Component for CurrentEra { .centered() .pixel_size(PixelSize::Quadrant) .style(self.palette.create_basic_style(false)) - .lines(vec![ - text.into(), - ]) + .lines(vec![text.into()]) .build(); let paragraph = Paragraph::new("") - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_style(self.palette.create_title_style(false)) - .title_top(Line::from("Era").right_aligned()) - .title_top(Line::from(format!("{}{} {}{}", + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_style(self.palette.create_title_style(false)) + .title_top(Line::from("Era").right_aligned()) + .title_top( + Line::from(format!( + "{}{} {}{}", if big_time { hours } else { minutes }, if big_time { "hrs" } else { "mins" }, if big_time { minutes } else { seconds }, - if big_time { "mins" } else { "secs" })) - .centered())) + if big_time { "mins" } else { "secs" } + )) + .centered(), + ), + ) .alignment(Alignment::Center) .wrap(Wrap { trim: true }); frame.render_widget(paragraph, place); let height_offset = height.saturating_sub(2) / 2; - let place = place.offset(ratatui::layout::Offset { x: 1, y: height_offset as i32 }) + let place = place + .offset(ratatui::layout::Offset { + x: 1, + y: height_offset as i32, + }) .intersection(place); frame.render_widget(big_text, place); } diff --git a/src/components/explorer/extrinsic_explorer.rs b/src/components/explorer/extrinsic_explorer.rs index b7a1d16..441eb6c 100644 --- a/src/components/explorer/extrinsic_explorer.rs +++ b/src/components/explorer/extrinsic_explorer.rs @@ -1,21 +1,23 @@ -use std::collections::{HashMap, VecDeque}; -use std::usize; use color_eyre::Result; use crossterm::event::KeyEvent; use ratatui::layout::{Constraint, Margin}; use ratatui::widgets::{Padding, Scrollbar, ScrollbarOrientation}; use ratatui::{ + layout::{Alignment, Rect}, text::Text, - layout::{Alignment, Rect}, - widgets::{Block, ScrollbarState, Cell, Row, Table, TableState}, - Frame + widgets::{Block, Cell, Row, ScrollbarState, Table, TableState}, + Frame, }; +use std::collections::{HashMap, VecDeque}; +use std::usize; use super::{Component, CurrentTab}; use crate::{ - components::generic::{Activatable, Scrollable, PartialComponent}, - types::CasperExtrinsicDetails, - action::Action, config::Config, palette::StylePalette, + action::Action, + components::generic::{Activatable, PartialComponent, Scrollable}, + config::Config, + palette::StylePalette, + types::CasperExtrinsicDetails, }; pub struct ExtrinsicExplorer { @@ -35,10 +37,18 @@ impl Default for ExtrinsicExplorer { } impl Activatable for ExtrinsicExplorer { - fn is_active(&self) -> bool { self.is_active } - fn is_inactive(&self) -> bool { !self.is_active } - fn set_inactive(&mut self) { self.is_active = false; } - fn set_active(&mut self) { self.is_active = true; } + fn is_active(&self) -> bool { + self.is_active + } + fn is_inactive(&self) -> bool { + !self.is_active + } + fn set_inactive(&mut self) { + self.is_active = false; + } + fn set_active(&mut self) { + self.is_active = true; + } } impl Scrollable for ExtrinsicExplorer { @@ -96,10 +106,9 @@ impl ExtrinsicExplorer { } fn update_used_explorer_block(&mut self, block_number: u32) { - let maybe_exts = self.extrinsics - .get(&block_number) - .map(|exts| exts.to_vec()); - let exts_length = self.extrinsics + let maybe_exts = self.extrinsics.get(&block_number).map(|exts| exts.to_vec()); + let exts_length = self + .extrinsics .get(&block_number) .map(|exts| exts.len()) .unwrap_or_default(); @@ -108,7 +117,6 @@ impl ExtrinsicExplorer { self.scroll_state = self.scroll_state.content_length(exts_length); } - fn update_extrinsics_for_header( &mut self, block_number: u32, @@ -125,11 +133,13 @@ impl ExtrinsicExplorer { } fn send_used_explorer_log(&mut self, index: usize) -> Result> { - let maybe_log = self.current_extrinsics + let maybe_log = self + .current_extrinsics .as_ref() - .map(|ext| ext.get(index).map(|ext| { - hex::encode(&ext.field_bytes.clone()) - })) + .map(|ext| { + ext.get(index) + .map(|ext| hex::encode(&ext.field_bytes.clone())) + }) .flatten(); Ok(Some(Action::UsedExplorerLog(maybe_log.clone()))) } @@ -150,25 +160,35 @@ impl PartialComponent for ExtrinsicExplorer { impl Component for ExtrinsicExplorer { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Explorer) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } Ok(()) } fn update(&mut self, action: Action) -> Result> { match action { - Action::UsedExplorerBlock(maybe_block_number) => - self.update_used_explorer_block(maybe_block_number.unwrap_or_default()), - Action::ExtrinsicsForBlock(block_number, extrinsics) => - self.update_extrinsics_for_header(block_number, extrinsics), - _ => {}, + Action::UsedExplorerBlock(maybe_block_number) => { + self.update_used_explorer_block(maybe_block_number.unwrap_or_default()) + } + Action::ExtrinsicsForBlock(block_number, extrinsics) => { + self.update_extrinsics_for_header(block_number, extrinsics) + } + _ => {} }; Ok(None) } @@ -192,12 +212,14 @@ impl Component for ExtrinsicExplorer { .iter() .enumerate() .map(|(idx, ext)| { - longest_pallet_name_length = longest_pallet_name_length.max(ext.pallet_name.len()); - longest_variant_name_length = longest_variant_name_length.max(ext.variant_name.len()); + longest_pallet_name_length = + longest_pallet_name_length.max(ext.pallet_name.len()); + longest_variant_name_length = + longest_variant_name_length.max(ext.variant_name.len()); Row::new(vec![ Cell::from(Text::from(idx.to_string()).alignment(Alignment::Left)), Cell::from(Text::from(ext.pallet_name.clone()).alignment(Alignment::Right)), - Cell::from(Text::from(ext.variant_name.clone()).alignment(Alignment::Left)), + Cell::from(Text::from(ext.variant_name.clone()).alignment(Alignment::Left)), Cell::from(Text::from(ext.hash.to_string()).alignment(Alignment::Right)), ]) }) @@ -217,13 +239,15 @@ impl Component for ExtrinsicExplorer { .style(self.palette.create_basic_style(false)) .highlight_style(self.palette.create_basic_style(true)) .column_spacing(1) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .padding(Padding::right(2)) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("Extrinsics")); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .padding(Padding::right(2)) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("Extrinsics"), + ); let scrollbar = Scrollbar::default() .orientation(ScrollbarOrientation::VerticalRight) @@ -233,8 +257,11 @@ impl Component for ExtrinsicExplorer { frame.render_stateful_widget(table, place, &mut self.table_state); frame.render_stateful_widget( - scrollbar, - place.inner(Margin { vertical: 1, horizontal: 1 }), + scrollbar, + place.inner(Margin { + vertical: 1, + horizontal: 1, + }), &mut self.scroll_state, ); diff --git a/src/components/explorer/extrinsics_chart.rs b/src/components/explorer/extrinsics_chart.rs index 117db82..875d513 100644 --- a/src/components/explorer/extrinsics_chart.rs +++ b/src/components/explorer/extrinsics_chart.rs @@ -1,16 +1,15 @@ -use std::collections::VecDeque; use color_eyre::Result; use ratatui::{ - layout::{Alignment, Rect}, - text::Line, + layout::{Alignment, Rect}, + text::Line, widgets::{Bar, BarChart, BarGroup, Block}, Frame, }; +use std::collections::VecDeque; use super::{Component, CurrentTab}; use crate::{ - components::generic::PartialComponent, - palette::StylePalette, config::Config, action::Action, + action::Action, components::generic::PartialComponent, config::Config, palette::StylePalette, }; #[derive(Debug, Default)] @@ -28,7 +27,8 @@ impl ExtrinsicsChart { let (border_style, border_type) = self.palette.create_border_style(false); let length = (width as usize) / (Self::BAR_WIDTH + Self::BAR_GAP); - let bars: Vec = self.extrinsics + let bars: Vec = self + .extrinsics .iter() .rev() .take(length) @@ -37,12 +37,14 @@ impl ExtrinsicsChart { BarChart::default() .data(BarGroup::default().bars(&bars)) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_style(self.palette.create_title_style(false)) - .title_alignment(Alignment::Right) - .title("Tx. Heat Map")) + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_style(self.palette.create_title_style(false)) + .title_alignment(Alignment::Right) + .title("Tx. Heat Map"), + ) .bar_width(8) .bar_gap(1) } @@ -54,7 +56,11 @@ impl ExtrinsicsChart { .text_value(ext_len.to_string()) } - fn update_extrinsics_length(&mut self, block_number: u32, extrinsics_length: usize) -> Result<()> { + fn update_extrinsics_length( + &mut self, + block_number: u32, + extrinsics_length: usize, + ) -> Result<()> { match self.extrinsics.back() { Some(back) => { if back.0 < block_number { @@ -63,7 +69,7 @@ impl ExtrinsicsChart { let _ = self.extrinsics.pop_front(); } } - }, + } None => { self.extrinsics.push_back((block_number, extrinsics_length)); } @@ -78,19 +84,27 @@ impl PartialComponent for ExtrinsicsChart {} impl Component for ExtrinsicsChart { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Explorer) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); } Ok(()) } fn update(&mut self, action: Action) -> Result> { match action { - Action::ExtrinsicsLength(block, length) => self.update_extrinsics_length(block, length)?, + Action::ExtrinsicsLength(block, length) => { + self.update_extrinsics_length(block, length)? + } _ => {} }; Ok(None) diff --git a/src/components/explorer/finalized_block.rs b/src/components/explorer/finalized_block.rs index 0c85c59..bfcc767 100644 --- a/src/components/explorer/finalized_block.rs +++ b/src/components/explorer/finalized_block.rs @@ -7,9 +7,11 @@ use ratatui::{ use super::{Component, CurrentTab}; use crate::{ + action::Action, components::generic::PartialComponent, - config::Config, action::Action, palette::StylePalette, - widgets::{PixelSize, BigText}, + config::Config, + palette::StylePalette, + widgets::{BigText, PixelSize}, }; #[derive(Debug, Default)] @@ -30,12 +32,18 @@ impl PartialComponent for FinalizedBlock {} impl Component for FinalizedBlock { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Explorer) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); } Ok(()) } @@ -60,13 +68,15 @@ impl Component for FinalizedBlock { if width < text_width || height < 7 { let paragraph = Paragraph::new(text) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .padding(Padding::new(0, 0, height.saturating_sub(2) / 2, 0)) - .title("Finalized")) + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .padding(Padding::new(0, 0, height.saturating_sub(2) / 2, 0)) + .title("Finalized"), + ) .alignment(Alignment::Center) .wrap(Wrap { trim: true }); frame.render_widget(paragraph, place); @@ -75,23 +85,27 @@ impl Component for FinalizedBlock { .centered() .pixel_size(PixelSize::Quadrant) .style(self.palette.create_basic_style(false)) - .lines(vec![ - text.into(), - ]) + .lines(vec![text.into()]) .build(); let paragraph = Paragraph::new("") - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("Finalized")) + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("Finalized"), + ) .alignment(Alignment::Center) .wrap(Wrap { trim: true }); frame.render_widget(paragraph, place); let height_offset = height.saturating_sub(2) / 2; - let place = place.offset(ratatui::layout::Offset { x: 1, y: height_offset as i32 }) + let place = place + .offset(ratatui::layout::Offset { + x: 1, + y: height_offset as i32, + }) .intersection(place); frame.render_widget(big_text, place); } diff --git a/src/components/explorer/latest_block.rs b/src/components/explorer/latest_block.rs index fcca5fc..3beb108 100644 --- a/src/components/explorer/latest_block.rs +++ b/src/components/explorer/latest_block.rs @@ -7,15 +7,17 @@ use ratatui::{ use super::{Component, CurrentTab}; use crate::{ + action::Action, components::generic::PartialComponent, - config::Config, action::Action, palette::StylePalette, - widgets::{PixelSize, BigText}, + config::Config, + palette::StylePalette, + widgets::{BigText, PixelSize}, }; #[derive(Debug, Default)] pub struct LatestBlock { number: u32, - palette: StylePalette + palette: StylePalette, } impl LatestBlock { @@ -30,12 +32,18 @@ impl PartialComponent for LatestBlock {} impl Component for LatestBlock { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Explorer) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); } Ok(()) } @@ -60,13 +68,15 @@ impl Component for LatestBlock { if width < text_width || height < 7 { let paragraph = Paragraph::new(text) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .padding(Padding::new(0, 0, height.saturating_sub(2) / 2, 0)) - .title("Latest")) + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .padding(Padding::new(0, 0, height.saturating_sub(2) / 2, 0)) + .title("Latest"), + ) .alignment(Alignment::Center) .wrap(Wrap { trim: true }); frame.render_widget(paragraph, place); @@ -75,23 +85,27 @@ impl Component for LatestBlock { .centered() .pixel_size(PixelSize::Quadrant) .style(self.palette.create_basic_style(false)) - .lines(vec![ - text.into(), - ]) + .lines(vec![text.into()]) .build(); let paragraph = Paragraph::new("") - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("Latest")) + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("Latest"), + ) .alignment(Alignment::Center) .wrap(Wrap { trim: true }); frame.render_widget(paragraph, place); let height_offset = height.saturating_sub(2) / 2; - let place = place.offset(ratatui::layout::Offset { x: 1, y: height_offset as i32 }) + let place = place + .offset(ratatui::layout::Offset { + x: 1, + y: height_offset as i32, + }) .intersection(place); frame.render_widget(big_text, place); } diff --git a/src/components/explorer/layouts.rs b/src/components/explorer/layouts.rs index fe3125d..bed17df 100644 --- a/src/components/explorer/layouts.rs +++ b/src/components/explorer/layouts.rs @@ -5,46 +5,39 @@ pub fn explorer_layout(area: Rect) -> [Rect; 3] { Constraint::Percentage(30), Constraint::Percentage(40), Constraint::Percentage(30), - ]).areas(area) + ]) + .areas(area) } pub fn explorer_header_layout(area: Rect) -> [Rect; 2] { let [header, _, _] = explorer_layout(area); - Layout::horizontal([ - Constraint::Percentage(50), - Constraint::Percentage(50), - ]).areas(header) + Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]).areas(header) } pub fn explorer_info_layout(area: Rect) -> [Rect; 2] { - let [info, _] = explorer_header_layout(area); - Layout::vertical([ - Constraint::Percentage(100), - Constraint::Percentage(100), - ]).areas(info) + let [info, _] = explorer_header_layout(area); + Layout::vertical([Constraint::Percentage(100), Constraint::Percentage(100)]).areas(info) } pub fn explorer_block_info_layout(area: Rect) -> [Rect; 3] { - let [blocks, _] = explorer_info_layout(area); + let [blocks, _] = explorer_info_layout(area); Layout::horizontal([ Constraint::Percentage(33), Constraint::Percentage(33), Constraint::Percentage(33), - ]).flex(Flex::SpaceBetween).areas(blocks) + ]) + .flex(Flex::SpaceBetween) + .areas(blocks) } pub fn explorer_era_info_layout(area: Rect) -> [Rect; 2] { - let [_, blocks] = explorer_info_layout(area); - Layout::horizontal([ - Constraint::Percentage(50), - Constraint::Percentage(50), - ]).flex(Flex::SpaceBetween).areas(blocks) + let [_, blocks] = explorer_info_layout(area); + Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]) + .flex(Flex::SpaceBetween) + .areas(blocks) } pub fn explorer_scrollbars_layout(area: Rect) -> [Rect; 2] { let [_, place, _] = explorer_layout(area); - Layout::horizontal([ - Constraint::Percentage(50), - Constraint::Percentage(50), - ]).areas(place) + Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]).areas(place) } diff --git a/src/components/explorer/log_explorer.rs b/src/components/explorer/log_explorer.rs index 8072705..dac58ad 100644 --- a/src/components/explorer/log_explorer.rs +++ b/src/components/explorer/log_explorer.rs @@ -1,15 +1,14 @@ use color_eyre::Result; use ratatui::{ - layout::{Alignment, Rect}, - text::Line, - widgets::{Block, Paragraph, Wrap}, - Frame + layout::{Alignment, Rect}, + text::Line, + widgets::{Block, Paragraph, Wrap}, + Frame, }; use super::{Component, CurrentTab}; use crate::{ - components::generic::PartialComponent, - action::Action, config::Config, palette::StylePalette + action::Action, components::generic::PartialComponent, config::Config, palette::StylePalette, }; #[derive(Default)] @@ -23,9 +22,12 @@ impl PartialComponent for LogExplorer {} impl Component for LogExplorer { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Explorer) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); } Ok(()) } @@ -33,7 +35,7 @@ impl Component for LogExplorer { fn update(&mut self, action: Action) -> Result> { match action { Action::UsedExplorerLog(maybe_log) => self.maybe_log = maybe_log, - _ => {}, + _ => {} }; Ok(None) } @@ -49,12 +51,14 @@ impl Component for LogExplorer { }; let paragraph = Paragraph::new(line) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("Logs")) + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("Logs"), + ) .alignment(Alignment::Center) .wrap(Wrap { trim: true }); diff --git a/src/components/explorer/mod.rs b/src/components/explorer/mod.rs index 733730d..8d0cc5c 100644 --- a/src/components/explorer/mod.rs +++ b/src/components/explorer/mod.rs @@ -9,25 +9,25 @@ use super::{ }; use crate::{action::Action, app::Mode, config::Config}; -pub mod layouts; -mod latest_block; -mod finalized_block; -mod block_ticker; -mod current_era; -mod current_epoch; -mod extrinsics_chart; mod block_explorer; +mod block_ticker; +mod current_epoch; +mod current_era; mod extrinsic_explorer; +mod extrinsics_chart; +mod finalized_block; +mod latest_block; +pub mod layouts; mod log_explorer; -use latest_block::LatestBlock; -use finalized_block::FinalizedBlock; -use block_ticker::BlockTicker; -use current_era::CurrentEra; -use current_epoch::CurrentEpoch; -use extrinsics_chart::ExtrinsicsChart; use block_explorer::BlockExplorer; +use block_ticker::BlockTicker; +use current_epoch::CurrentEpoch; +use current_era::CurrentEra; use extrinsic_explorer::ExtrinsicExplorer; +use extrinsics_chart::ExtrinsicsChart; +use finalized_block::FinalizedBlock; +use latest_block::LatestBlock; use log_explorer::LogExplorer; #[derive(Debug, Clone, Copy, PartialEq)] @@ -40,7 +40,7 @@ pub enum CurrentTab { pub struct Explorer { is_active: bool, current_tab: CurrentTab, - components: Vec>> + components: Vec>>, } impl Default for Explorer { @@ -58,7 +58,7 @@ impl Default for Explorer { Box::new(BlockExplorer::default()), Box::new(ExtrinsicExplorer::default()), Box::new(LogExplorer::default()), - ] + ], } } } @@ -80,10 +80,18 @@ impl Explorer { } impl Activatable for Explorer { - fn is_active(&self) -> bool { self.is_active } - fn is_inactive(&self) -> bool { !self.is_active } - fn set_inactive(&mut self) { self.is_active = false; } - fn set_active(&mut self) { self.is_active = true; } + fn is_active(&self) -> bool { + self.is_active + } + fn is_inactive(&self) -> bool { + !self.is_active + } + fn set_inactive(&mut self) { + self.is_active = false; + } + fn set_active(&mut self) { + self.is_active = true; + } } impl PartialComponent for Explorer {} @@ -106,7 +114,9 @@ impl Component for Explorer { } fn handle_key_event(&mut self, key: KeyEvent) -> Result> { - if self.is_inactive() { return Ok(None); } + if self.is_inactive() { + return Ok(None); + } match key.code { KeyCode::Esc => { @@ -116,19 +126,19 @@ impl Component for Explorer { component.set_active_tab(self.current_tab); } return Ok(Some(Action::SetActiveScreen(Mode::Menu))); - }, + } KeyCode::Enter | KeyCode::Char('l') | KeyCode::Right => { self.move_right(); for component in self.components.iter_mut() { component.set_active_tab(self.current_tab); } - }, + } KeyCode::Char('h') | KeyCode::Left => { self.move_left(); for component in self.components.iter_mut() { component.set_active_tab(self.current_tab); } - }, + } _ => { for component in self.components.iter_mut() { let maybe_action = component.handle_key_event(key); @@ -136,7 +146,7 @@ impl Component for Explorer { return maybe_action; } } - }, + } } Ok(None) } diff --git a/src/components/fps.rs b/src/components/fps.rs index 2523f2a..444028c 100644 --- a/src/components/fps.rs +++ b/src/components/fps.rs @@ -79,8 +79,7 @@ impl Component for FpsCounter { let message = format!( " {:.2} ticks/sec | {:.2} FPS", - self.ticks_per_second, - self.frames_per_second + self.ticks_per_second, self.frames_per_second ); let span = Span::styled(message, Style::new().dim()); diff --git a/src/components/generic/helpable.rs b/src/components/generic/helpable.rs index ae1fdc6..97f6b5c 100644 --- a/src/components/generic/helpable.rs +++ b/src/components/generic/helpable.rs @@ -1,5 +1,5 @@ -use color_eyre::Result; use crate::action::Action; +use color_eyre::Result; use super::Activatable; diff --git a/src/components/generic/mod.rs b/src/components/generic/mod.rs index e157cbd..e6a06da 100644 --- a/src/components/generic/mod.rs +++ b/src/components/generic/mod.rs @@ -1,9 +1,9 @@ mod activatable; mod helpable; -mod scrollable; mod partial; +mod scrollable; pub use activatable::Activatable; pub use helpable::Helpable; -pub use scrollable::Scrollable; pub use partial::PartialComponent; +pub use scrollable::Scrollable; diff --git a/src/components/generic/scrollable.rs b/src/components/generic/scrollable.rs index 15a88d1..ce28cb4 100644 --- a/src/components/generic/scrollable.rs +++ b/src/components/generic/scrollable.rs @@ -1,10 +1,11 @@ -use std::{ - cmp::{PartialEq, PartialOrd}, ops::{Add, Sub} -}; use crossterm::event::KeyCode; +use std::{ + cmp::{PartialEq, PartialOrd}, + ops::{Add, Sub}, +}; -use color_eyre::Result; use crate::action::Action; +use color_eyre::Result; pub trait Scrollable { type IndexType: Add @@ -15,13 +16,20 @@ pub trait Scrollable { + Copy; fn selected_index(&self) -> Option; - fn items_length(&self) -> Self::IndexType; - - fn apply_next_row(&mut self, _new_index: Self::IndexType) -> Result> { Ok(None) } - fn apply_prev_row(&mut self, _new_index: Self::IndexType) -> Result> { Ok(None) } - fn apply_first_row(&mut self) -> Result> { Ok(None) } - fn apply_last_row(&mut self) -> Result> { Ok(None) } + fn items_length(&self) -> Self::IndexType; + fn apply_next_row(&mut self, _new_index: Self::IndexType) -> Result> { + Ok(None) + } + fn apply_prev_row(&mut self, _new_index: Self::IndexType) -> Result> { + Ok(None) + } + fn apply_first_row(&mut self) -> Result> { + Ok(None) + } + fn apply_last_row(&mut self) -> Result> { + Ok(None) + } fn next_row(&mut self) -> Result> { let length = self.items_length(); @@ -36,7 +44,7 @@ pub trait Scrollable { } else { index } - }, + } None => 0.into(), }; self.apply_next_row(new_index) @@ -55,7 +63,7 @@ pub trait Scrollable { index - 1.into() } } - None => 0.into() + None => 0.into(), }; self.apply_prev_row(new_index) } diff --git a/src/components/health.rs b/src/components/health.rs index a70f6c4..c9a3960 100644 --- a/src/components/health.rs +++ b/src/components/health.rs @@ -10,14 +10,14 @@ use ratatui::{ use super::Component; use crate::{ action::Action, - widgets::{DotSpinner, OghamCenter, VerticalBlocks} + widgets::{DotSpinner, OghamCenter, VerticalBlocks}, }; #[derive(Debug, Clone, PartialEq)] pub struct Health { name: Option, peers: Option, - is_syncing: bool, + is_syncing: bool, should_have_peers: bool, tx_pool_length: usize, validators_count: u32, @@ -44,9 +44,9 @@ impl Health { } pub fn is_syncing_as_string(&self) -> String { - if self.is_syncing { + if self.is_syncing { format!("syncing {}", VerticalBlocks::default().to_string()) - } else { + } else { String::from("synced") } } @@ -73,7 +73,7 @@ impl Component for Health { self.peers = peers; self.is_syncing = is_syncing; self.should_have_peers = should_have_peers; - }, + } Action::SetNodeName(name) => self.name = name, Action::SetPendingExtrinsicsLength(length) => self.tx_pool_length = length, Action::NominatorsNumber(number) => self.nominators_count = number, diff --git a/src/components/help.rs b/src/components/help.rs index 21ccc2a..63df17f 100644 --- a/src/components/help.rs +++ b/src/components/help.rs @@ -1,18 +1,18 @@ use color_eyre::Result; -use crossterm::event::{KeyEvent, KeyCode}; +use crossterm::event::{KeyCode, KeyEvent}; use ratatui::{ - layout::{Alignment, Constraint, Flex, Layout, Margin, Rect}, - style::{palette::tailwind, Style, Modifier}, - text::Text, + layout::{Alignment, Constraint, Flex, Layout, Margin, Rect}, + style::{palette::tailwind, Modifier, Style}, + text::Text, widgets::{ - Block, BorderType, Cell, Clear, HighlightSpacing, Paragraph, Row, - Scrollbar, ScrollbarOrientation, ScrollbarState, Table, TableState, - }, - Frame + Block, BorderType, Cell, Clear, HighlightSpacing, Paragraph, Row, Scrollbar, + ScrollbarOrientation, ScrollbarState, Table, TableState, + }, + Frame, }; -use super::palette::StylePalette; use super::generic::{Activatable, Helpable, Scrollable}; +use super::palette::StylePalette; use super::Component; use crate::{action::Action, app::Mode, config::Config}; @@ -49,13 +49,21 @@ impl Default for Help { } impl Activatable for Help { - fn is_active(&self) -> bool { self.is_active } - fn is_inactive(&self) -> bool { !self.is_active } - fn set_inactive(&mut self) { self.is_active = false; } - fn set_active(&mut self) { self.is_active = true; } + fn is_active(&self) -> bool { + self.is_active + } + fn is_inactive(&self) -> bool { + !self.is_active + } + fn set_inactive(&mut self) { + self.is_active = false; + } + fn set_active(&mut self) { + self.is_active = true; + } } -impl Helpable for Help { } +impl Helpable for Help {} impl Scrollable for Help { type IndexType = usize; @@ -80,11 +88,16 @@ impl Scrollable for Help { impl Component for Help { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Help) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -96,7 +109,9 @@ impl Component for Help { if self.current_mode != mode { self.current_mode = mode; self.table_state.select(None); - self.scroll_state = ScrollbarState::new((self.current_mode.get_help_data().len() - 1) * ITEM_HEIGHT); + self.scroll_state = ScrollbarState::new( + (self.current_mode.get_help_data().len() - 1) * ITEM_HEIGHT, + ); } } _ => {} @@ -111,18 +126,14 @@ impl Component for Help { KeyCode::Esc if self.is_active() => { self.set_inactive(); Ok(Some(Action::SetActiveScreen(self.current_mode))) - }, + } _ => Ok(None), } } fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { if self.is_active() { - let highlight_symbol = Text::from(vec![ - "".into(), - " █ ".into(), - "".into(), - ]); + let highlight_symbol = Text::from(vec!["".into(), " █ ".into(), "".into()]); let table = Table::new( self.current_mode @@ -135,38 +146,46 @@ impl Component for Help { _ => tailwind::SLATE.c900, }; - Row::from(content - .into_iter() - .map(|data| Cell::from(Text::from(*data))) - .collect::() - .style(Style::default().fg(tailwind::BLUE.c200).bg(color)) - .height(ITEM_HEIGHT as u16)) + Row::from( + content + .into_iter() + .map(|data| Cell::from(Text::from(*data))) + .collect::() + .style(Style::default().fg(tailwind::BLUE.c200).bg(color)) + .height(ITEM_HEIGHT as u16), + ) }) .collect::>(), - self.current_mode.get_help_constraints() + self.current_mode.get_help_constraints(), ) - .header(self.current_mode - .get_help_headers() - .into_iter() - .map(|h| Cell::from(Text::from(*h))) - .collect::() - .style(Style::default() - .fg(tailwind::SLATE.c200) - .bg(tailwind::BLUE.c900) - ) - .height(1) + .header( + self.current_mode + .get_help_headers() + .into_iter() + .map(|h| Cell::from(Text::from(*h))) + .collect::() + .style( + Style::default() + .fg(tailwind::SLATE.c200) + .bg(tailwind::BLUE.c900), + ) + .height(1), + ) + .highlight_style( + Style::default() + .add_modifier(Modifier::REVERSED) + .fg(tailwind::BLUE.c400) + .bg(tailwind::YELLOW.c200), ) - .highlight_style(Style::default() - .add_modifier(Modifier::REVERSED) - .fg(tailwind::BLUE.c400) - .bg(tailwind::YELLOW.c200)) .highlight_spacing(HighlightSpacing::Always) .highlight_symbol(highlight_symbol) - .block(Block::default() - .style(Style::default().bg(tailwind::SLATE.c950)) - .title_alignment(Alignment::Right) - .title_style(tailwind::YELLOW.c200) - .title(self.current_mode.get_help_title())); + .block( + Block::default() + .style(Style::default().bg(tailwind::SLATE.c950)) + .title_alignment(Alignment::Right) + .title_style(tailwind::YELLOW.c200) + .title(self.current_mode.get_help_title()), + ); let scrollbar = Scrollbar::default() .orientation(ScrollbarOrientation::VerticalRight) @@ -174,11 +193,16 @@ impl Component for Help { .end_symbol(None); let footer = Paragraph::new(Text::from(self.current_mode.get_help_text())) - .style(Style::default().fg(tailwind::SLATE.c200).bg(tailwind::SLATE.c950)) + .style( + Style::default() + .fg(tailwind::SLATE.c200) + .bg(tailwind::SLATE.c950), + ) .centered() - .block(Block::bordered() - .border_type(BorderType::Double) - .border_style(Style::default().fg(tailwind::BLUE.c400)) + .block( + Block::bordered() + .border_type(BorderType::Double) + .border_style(Style::default().fg(tailwind::BLUE.c400)), ); let v = Layout::vertical([Constraint::Length(23)]).flex(Flex::Center); @@ -187,14 +211,16 @@ impl Component for Help { let [area] = v.areas(area); let [area] = h.areas(area); - let [main_area, footer_area] = Layout::vertical([ - Constraint::Fill(1), - Constraint::Length(3), - ]).areas(area); + let [main_area, footer_area] = + Layout::vertical([Constraint::Fill(1), Constraint::Length(3)]).areas(area); frame.render_widget(Clear, area); frame.render_stateful_widget(table, main_area, &mut self.table_state); - frame.render_stateful_widget(scrollbar, main_area.inner(Margin::new(1, 2)), &mut self.scroll_state); + frame.render_stateful_widget( + scrollbar, + main_area.inner(Margin::new(1, 2)), + &mut self.scroll_state, + ); frame.render_widget(footer, footer_area); } Ok(()) diff --git a/src/components/layouts.rs b/src/components/layouts.rs index 7e9e8b0..e5eb9f3 100644 --- a/src/components/layouts.rs +++ b/src/components/layouts.rs @@ -1,34 +1,22 @@ use ratatui::layout::{Constraint, Layout, Rect}; pub fn global_layout(area: Rect) -> [Rect; 2] { - Layout::vertical([ - Constraint::Length(1), - Constraint::Fill(1), - ]).areas(area) + Layout::vertical([Constraint::Length(1), Constraint::Fill(1)]).areas(area) } pub fn header_layout(area: Rect) -> [Rect; 2] { let [header, _] = global_layout(area); - Layout::horizontal([ - Constraint::Fill(1), - Constraint::Length(27), - ]).areas(header) + Layout::horizontal([Constraint::Fill(1), Constraint::Length(27)]).areas(header) } pub fn main_layout(area: Rect) -> [Rect; 2] { let [_, main] = global_layout(area); - Layout::horizontal([ - Constraint::Max(30), - Constraint::Fill(1), - ]).areas(main) + Layout::horizontal([Constraint::Max(30), Constraint::Fill(1)]).areas(main) } pub fn menu_layout(area: Rect) -> [Rect; 2] { let [menu, _] = main_layout(area); - Layout::vertical([ - Constraint::Min(0), - Constraint::Length(5), - ]).areas(menu) + Layout::vertical([Constraint::Min(0), Constraint::Length(5)]).areas(menu) } pub fn screen_layout(area: Rect) -> Rect { diff --git a/src/components/menu.rs b/src/components/menu.rs index bc0f9af..2f3f318 100644 --- a/src/components/menu.rs +++ b/src/components/menu.rs @@ -1,10 +1,10 @@ use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent}; use ratatui::{prelude::*, widgets::*}; -use crossterm::event::{KeyEvent, KeyCode}; -use super::Component; use super::palette::StylePalette; -use crate::{config::Config, action::Action, app::Mode}; +use super::Component; +use crate::{action::Action, app::Mode, config::Config}; use super::generic::{Activatable, Helpable, Scrollable}; @@ -16,17 +16,27 @@ pub struct Menu { } impl Default for Menu { - fn default() -> Self { Menu::new() } + fn default() -> Self { + Menu::new() + } } impl Activatable for Menu { - fn is_active(&self) -> bool { self.is_active } - fn is_inactive(&self) -> bool { !self.is_active } - fn set_inactive(&mut self) { self.is_active = false; } - fn set_active(&mut self) { self.is_active = true; } + fn is_active(&self) -> bool { + self.is_active + } + fn is_inactive(&self) -> bool { + !self.is_active + } + fn set_inactive(&mut self) { + self.is_active = false; + } + fn set_active(&mut self) { + self.is_active = true; + } } -impl Helpable for Menu { } +impl Helpable for Menu {} impl Scrollable for Menu { type IndexType = usize; @@ -62,7 +72,6 @@ impl Menu { ], palette: StylePalette::default(), is_active: true, - }; new_list.list_state.select(Some(0)); new_list @@ -90,19 +99,24 @@ impl Component for Menu { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Menu) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); } Ok(()) } fn handle_key_event(&mut self, key: KeyEvent) -> Result> { match key.code { - KeyCode::Up | KeyCode::Char('k') if self.is_active() => self.prev_row(), - KeyCode::Down | KeyCode::Char('j') if self.is_active() => self.next_row(), + KeyCode::Up | KeyCode::Char('k') if self.is_active() => self.prev_row(), + KeyCode::Down | KeyCode::Char('j') if self.is_active() => self.next_row(), KeyCode::Enter | KeyCode::Char('l') | KeyCode::Right if self.is_active() => { self.set_inactive(); match self.list_state.selected() { @@ -111,7 +125,7 @@ impl Component for Menu { Some(2) => Ok(Some(Action::SetActiveScreen(Mode::Validator))), _ => Ok(Some(Action::SetActiveScreen(Mode::Empty))), } - }, + } KeyCode::Char('?') if self.is_active() => self.open_help_popup(), _ => Ok(None), } @@ -126,12 +140,13 @@ impl Component for Menu { .border_type(border_type); let list = List::default() - .items(self.items - .iter() - .map(|item| ListItem::new( - Line::raw(item.as_str()).alignment(Alignment::Center) - )) - .collect::>() + .items( + self.items + .iter() + .map(|item| { + ListItem::new(Line::raw(item.as_str()).alignment(Alignment::Center)) + }) + .collect::>(), ) .block(block) .style(self.palette.create_basic_style(false)) diff --git a/src/components/mod.rs b/src/components/mod.rs index c89b63b..c5ab240 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -4,22 +4,22 @@ use ratatui::{ layout::{Rect, Size}, Frame, }; -use tokio::sync::mpsc::UnboundedSender; use std::sync::mpsc::Sender; +use tokio::sync::mpsc::UnboundedSender; -use crate::{palette, action::Action, config::Config, tui::Event}; +use crate::{action::Action, config::Config, palette, tui::Event}; -pub mod layouts; -pub mod fps; -pub mod health; -pub mod menu; -pub mod version; -pub mod explorer; -pub mod wallet; -pub mod validator; pub mod empty; -pub mod help; +pub mod explorer; +pub mod fps; pub mod generic; +pub mod health; +pub mod help; +pub mod layouts; +pub mod menu; +pub mod validator; +pub mod version; +pub mod wallet; pub trait Component { fn register_network_handler(&mut self, tx: Sender) -> Result<()> { diff --git a/src/components/validator/bond_popup.rs b/src/components/validator/bond_popup.rs index 0c9139f..d0768dc 100644 --- a/src/components/validator/bond_popup.rs +++ b/src/components/validator/bond_popup.rs @@ -1,19 +1,19 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Position, Alignment, Constraint, Flex, Layout, Rect}, - widgets::{Block, Clear, Paragraph}, - Frame + layout::{Alignment, Constraint, Flex, Layout, Position, Rect}, + widgets::{Block, Clear, Paragraph}, + Frame, }; -use tokio::sync::mpsc::UnboundedSender; use std::sync::mpsc::Sender; +use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ - action::Action, - config::Config, - palette::StylePalette, - types::{ActionLevel, ActionTarget}, + action::Action, + config::Config, + palette::StylePalette, + types::{ActionLevel, ActionTarget}, widgets::{Input, InputRequest}, }; @@ -27,7 +27,7 @@ pub struct BondPopup { minimal_bond: u128, is_bonded: bool, amount: Input, - palette: StylePalette + palette: StylePalette, } impl Default for BondPopup { @@ -60,13 +60,12 @@ impl BondPopup { fn log_event(&mut self, message: String, level: ActionLevel) { if let Some(action_tx) = &self.action_tx { - let _ = action_tx.send( - Action::EventLog(message, level, ActionTarget::ValidatorLog)); + let _ = action_tx.send(Action::EventLog(message, level, ActionTarget::ValidatorLog)); } } fn submit_message(&mut self) { - if let Some(network_tx) = &self.network_tx { + if let Some(network_tx) = &self.network_tx { let str_amount = self.amount.value(); let str_amount = if str_amount.starts_with('.') { &format!("0{}", str_amount)[..] @@ -78,16 +77,25 @@ impl BondPopup { let amount = (value * 1_000_000_000_000_000_000.0) as u128; let log_target = ActionTarget::ValidatorLog; let _ = if self.is_bonded { - network_tx.send(Action::BondValidatorExtraFrom(self.stash_secret_seed, amount, log_target)) + network_tx.send(Action::BondValidatorExtraFrom( + self.stash_secret_seed, + amount, + log_target, + )) } else { - network_tx.send(Action::BondValidatorFrom(self.stash_secret_seed, amount, log_target)) + network_tx.send(Action::BondValidatorFrom( + self.stash_secret_seed, + amount, + log_target, + )) }; if let Some(action_tx) = &self.action_tx { let _ = action_tx.send(Action::ClosePopup); } - }, - Err(err) => self.log_event( - format!("invalid amount, error: {err}"), ActionLevel::Error), + } + Err(err) => { + self.log_event(format!("invalid amount, error: {err}"), ActionLevel::Error) + } } } } @@ -137,11 +145,16 @@ impl Component for BondPopup { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -153,8 +166,8 @@ impl Component for BondPopup { KeyCode::Backspace => self.delete_char(), KeyCode::Left => self.move_cursor_left(), KeyCode::Right => self.move_cursor_right(), - KeyCode::Esc => self.close_popup(), - _ => {}, + KeyCode::Esc => self.close_popup(), + _ => {} }; } Ok(None) @@ -162,8 +175,9 @@ impl Component for BondPopup { fn update(&mut self, action: Action) -> Result> { match action { - Action::SetIsBonded(is_bonded, account_id) if self.stash_account_id == account_id => - self.is_bonded = is_bonded, + Action::SetIsBonded(is_bonded, account_id) if self.stash_account_id == account_id => { + self.is_bonded = is_bonded + } Action::SetMinValidatorBond(minimal_bond) => self.minimal_bond = minimal_bond, Action::SetStashSecret(secret_seed) => self.stash_secret_seed = secret_seed, Action::SetStashAccount(account_id) => self.stash_account_id = account_id, @@ -175,13 +189,14 @@ impl Component for BondPopup { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { if self.is_active { let (border_style, border_type) = self.palette.create_popup_style(); - let input = Paragraph::new(self.amount.value()) - .block(Block::bordered() + let input = Paragraph::new(self.amount.value()).block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title(format!("Staking bond amount"))); + .title(format!("Staking bond amount")), + ); let v = Layout::vertical([Constraint::Max(3)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(50)]).flex(Flex::Center); let [area] = v.areas(area); @@ -190,8 +205,8 @@ impl Component for BondPopup { frame.render_widget(Clear, area); frame.render_widget(input, area); frame.set_cursor_position(Position::new( - area.x + self.amount.cursor() as u16 + 1, - area.y + 1 + area.x + self.amount.cursor() as u16 + 1, + area.y + 1, )); } Ok(()) diff --git a/src/components/validator/change_blocks_popup.rs b/src/components/validator/change_blocks_popup.rs index fbf98ab..58b183b 100644 --- a/src/components/validator/change_blocks_popup.rs +++ b/src/components/validator/change_blocks_popup.rs @@ -1,19 +1,19 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Position, Alignment, Constraint, Flex, Layout, Rect}, - widgets::{Block, Clear, Paragraph}, - Frame + layout::{Alignment, Constraint, Flex, Layout, Position, Rect}, + widgets::{Block, Clear, Paragraph}, + Frame, }; use std::sync::mpsc::Sender; use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ - action::Action, - config::Config, - palette::StylePalette, - types::{ActionTarget, ActionLevel}, + action::Action, + config::Config, + palette::StylePalette, + types::{ActionLevel, ActionTarget}, widgets::{Input, InputRequest}, }; @@ -24,7 +24,7 @@ pub struct ChangeBlocksPopup { network_tx: Option>, chain_id: u64, block_number: Input, - palette: StylePalette + palette: StylePalette, } impl ChangeBlocksPopup { @@ -36,7 +36,7 @@ impl ChangeBlocksPopup { } fn submit_new_block(&mut self) { - if let Some(network_tx) = &self.network_tx { + if let Some(network_tx) = &self.network_tx { if let Some(action_tx) = &self.action_tx { let _ = match self.block_number.value().parse::() { Ok(new_block) => { @@ -44,9 +44,9 @@ impl ChangeBlocksPopup { action_tx.send(Action::ClosePopup) } Err(_) => action_tx.send(Action::EventLog( - "Incorrect block number format".to_string(), - ActionLevel::Error, - ActionTarget::ValidatorLog, + "Incorrect block number format".to_string(), + ActionLevel::Error, + ActionTarget::ValidatorLog, )), }; } @@ -98,11 +98,16 @@ impl Component for ChangeBlocksPopup { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -111,12 +116,12 @@ impl Component for ChangeBlocksPopup { if self.is_active && key.kind == KeyEventKind::Press { match key.code { KeyCode::Enter => self.submit_new_block(), - KeyCode::Esc => self.close_popup(), + KeyCode::Esc => self.close_popup(), KeyCode::Char(to_insert) => self.enter_char(to_insert), KeyCode::Backspace => self.delete_char(), KeyCode::Left => self.move_cursor_left(), KeyCode::Right => self.move_cursor_right(), - _ => {}, + _ => {} }; } Ok(None) @@ -133,13 +138,14 @@ impl Component for ChangeBlocksPopup { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { if self.is_active { let (border_style, border_type) = self.palette.create_popup_style(); - let input = Paragraph::new(self.block_number.value()) - .block(Block::bordered() + let input = Paragraph::new(self.block_number.value()).block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title(format!("Bump blocks for #{:?}", self.chain_id))); + .title(format!("Bump blocks for #{:?}", self.chain_id)), + ); let v = Layout::vertical([Constraint::Max(3)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(57)]).flex(Flex::Center); let [area] = v.areas(area); @@ -148,8 +154,8 @@ impl Component for ChangeBlocksPopup { frame.render_widget(Clear, area); frame.render_widget(input, area); frame.set_cursor_position(Position::new( - area.x + self.block_number.cursor() as u16 + 1, - area.y + 1 + area.x + self.block_number.cursor() as u16 + 1, + area.y + 1, )); } Ok(()) diff --git a/src/components/validator/chill_popup.rs b/src/components/validator/chill_popup.rs index ec439f5..a4ec012 100644 --- a/src/components/validator/chill_popup.rs +++ b/src/components/validator/chill_popup.rs @@ -1,19 +1,15 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Alignment, Constraint, Flex, Layout, Rect}, - widgets::{Block, Clear, Paragraph}, - Frame + layout::{Alignment, Constraint, Flex, Layout, Rect}, + widgets::{Block, Clear, Paragraph}, + Frame, }; use std::sync::mpsc::Sender; use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, -}; +use super::{Component, CurrentTab, PartialComponent}; +use crate::{action::Action, config::Config, palette::StylePalette}; #[derive(Debug)] pub struct ChillPopup { @@ -21,7 +17,7 @@ pub struct ChillPopup { action_tx: Option>, network_tx: Option>, secret_seed: [u8; 32], - palette: StylePalette + palette: StylePalette, } impl Default for ChillPopup { @@ -49,7 +45,7 @@ impl ChillPopup { } fn submit_message(&mut self) { - if let Some(network_tx) = &self.network_tx { + if let Some(network_tx) = &self.network_tx { let _ = network_tx.send(Action::ChillFrom(self.secret_seed)); if let Some(action_tx) = &self.action_tx { let _ = action_tx.send(Action::ClosePopup); @@ -80,11 +76,16 @@ impl Component for ChillPopup { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -92,8 +93,8 @@ impl Component for ChillPopup { if self.is_active && key.kind == KeyEventKind::Press { match key.code { KeyCode::Enter => self.submit_message(), - KeyCode::Esc => self.close_popup(), - _ => {}, + KeyCode::Esc => self.close_popup(), + _ => {} }; } Ok(None) @@ -111,12 +112,14 @@ impl Component for ChillPopup { if self.is_active { let (border_style, border_type) = self.palette.create_popup_style(); let input = Paragraph::new(" Do you want to chill stash account and stop validation?") - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_style(self.palette.create_popup_title_style()) - .title_alignment(Alignment::Right) - .title(format!("Chill stash"))); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_style(self.palette.create_popup_title_style()) + .title_alignment(Alignment::Right) + .title(format!("Chill stash")), + ); let v = Layout::vertical([Constraint::Max(3)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(57)]).flex(Flex::Center); let [area] = v.areas(area); diff --git a/src/components/validator/event_log.rs b/src/components/validator/event_log.rs index 9078613..3f80490 100644 --- a/src/components/validator/event_log.rs +++ b/src/components/validator/event_log.rs @@ -1,19 +1,22 @@ use color_eyre::Result; use crossterm::event::{KeyCode, KeyEvent}; use ratatui::{ - layout::{Alignment, Constraint, Margin, Rect}, - style::{Color, Style}, - text::Text, + layout::{Alignment, Constraint, Margin, Rect}, + style::{Color, Style}, + text::Text, widgets::{ - Block, Padding, Cell, Row, Scrollbar, ScrollbarOrientation, - ScrollbarState, Table, TableState, - }, - Frame + Block, Cell, Padding, Row, Scrollbar, ScrollbarOrientation, ScrollbarState, Table, + TableState, + }, + Frame, }; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ - action::Action, config::Config, palette::StylePalette, types::{ActionLevel, ActionTarget} + action::Action, + config::Config, + palette::StylePalette, + types::{ActionLevel, ActionTarget}, }; #[derive(Debug, Default)] @@ -29,7 +32,7 @@ pub struct EventLogs { scroll_state: ScrollbarState, table_state: TableState, logs: std::collections::VecDeque, - palette: StylePalette + palette: StylePalette, } impl EventLogs { @@ -62,7 +65,7 @@ impl EventLogs { } else { i + 1 } - }, + } None => 0, }; self.table_state.select(Some(i)); @@ -85,8 +88,8 @@ impl EventLogs { } else { i - 1 } - }, - None => 0 + } + None => 0, }; self.table_state.select(Some(i)); self.scroll_state = self.scroll_state.position(i); @@ -109,33 +112,42 @@ impl PartialComponent for EventLogs { impl Component for EventLogs { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Validator) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } Ok(()) } fn handle_key_event(&mut self, key: KeyEvent) -> Result> { match key.code { - KeyCode::Up | KeyCode::Char('k') if self.is_active => self.previous_row(), - KeyCode::Down | KeyCode::Char('j') if self.is_active => self.next_row(), - KeyCode::Char('g') if self.is_active => self.first_row(), - KeyCode::Char('G') if self.is_active => self.last_row(), - _ => {}, + KeyCode::Up | KeyCode::Char('k') if self.is_active => self.previous_row(), + KeyCode::Down | KeyCode::Char('j') if self.is_active => self.next_row(), + KeyCode::Char('g') if self.is_active => self.first_row(), + KeyCode::Char('G') if self.is_active => self.last_row(), + _ => {} }; Ok(None) } fn update(&mut self, action: Action) -> Result> { match action { - Action::EventLog(message, level, target) if target == ActionTarget::ValidatorLog => - self.add_new_log(message, level), + Action::EventLog(message, level, target) if target == ActionTarget::ValidatorLog => { + self.add_new_log(message, level) + } _ => {} }; Ok(None) @@ -150,33 +162,38 @@ impl Component for EventLogs { let info_style = Style::new().fg(Color::Green); let table = Table::new( - self.logs - .iter() - .map(|log| { - let style = match log.level { - ActionLevel::Info => info_style, - ActionLevel::Warn => warn_style, - ActionLevel::Error => error_style, - }; - Row::new(vec![ - Cell::from(Text::from(log.time.format("%H:%M:%S").to_string()).style(style).alignment(Alignment::Left)), - Cell::from(Text::from(log.message.clone()).style(style).alignment(Alignment::Left)), - ]) - }), - [ - Constraint::Max(8), - Constraint::Min(0), - ], + self.logs.iter().map(|log| { + let style = match log.level { + ActionLevel::Info => info_style, + ActionLevel::Warn => warn_style, + ActionLevel::Error => error_style, + }; + Row::new(vec![ + Cell::from( + Text::from(log.time.format("%H:%M:%S").to_string()) + .style(style) + .alignment(Alignment::Left), + ), + Cell::from( + Text::from(log.message.clone()) + .style(style) + .alignment(Alignment::Left), + ), + ]) + }), + [Constraint::Max(8), Constraint::Min(0)], ) .column_spacing(1) .highlight_style(self.palette.create_highlight_style()) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .padding(Padding::right(2)) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("Action Logs")); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .padding(Padding::right(2)) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("Action Logs"), + ); let scrollbar = Scrollbar::default() .orientation(ScrollbarOrientation::VerticalRight) @@ -187,7 +204,10 @@ impl Component for EventLogs { frame.render_stateful_widget(table, place, &mut self.table_state); frame.render_stateful_widget( scrollbar, - place.inner(Margin { vertical: 1, horizontal: 1 }), + place.inner(Margin { + vertical: 1, + horizontal: 1, + }), &mut self.scroll_state, ); Ok(()) diff --git a/src/components/validator/gatekeeper_details.rs b/src/components/validator/gatekeeper_details.rs index a069443..0563ca2 100644 --- a/src/components/validator/gatekeeper_details.rs +++ b/src/components/validator/gatekeeper_details.rs @@ -1,20 +1,16 @@ -use std::collections::HashMap; use color_eyre::Result; use ratatui::layout::Constraint; use ratatui::{ + layout::{Alignment, Rect}, text::Text, - layout::{Alignment, Rect}, - widgets::{Block, Cell, Row, Table}, - Frame + widgets::{Block, Cell, Row, Table}, + Frame, }; +use std::collections::HashMap; -use super::{PartialComponent, Component, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::types::BlockRange; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, -}; +use crate::{action::Action, config::Config, palette::StylePalette}; #[derive(Debug, Default, Clone)] struct Details { @@ -26,25 +22,33 @@ struct Details { pub struct GatekeeperDetails { palette: StylePalette, gatekeeper_details: HashMap, - block_ranges: HashMap, + block_ranges: HashMap, selected_chain_id: u64, } impl PartialComponent for GatekeeperDetails { - fn set_active(&mut self, _current_tab: CurrentTab) { } + fn set_active(&mut self, _current_tab: CurrentTab) {} } impl Component for GatekeeperDetails { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Validator) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } Ok(()) } @@ -54,12 +58,15 @@ impl Component for GatekeeperDetails { Action::SetChoosenGatekeeper(chain_id) => self.selected_chain_id = chain_id, Action::SetBlockRange(chain_id, block_range) => { let _ = self.block_ranges.insert(chain_id, block_range); - }, + } Action::SetGatekeepedNetwork(network) => { - self.gatekeeper_details.insert(network.chain_id, Details { - incoming_fee: format!("{:.5}%", network.incoming_fee as f64 / 10_000_000.0), - outgoing_fee: format!("{:.5}%", network.outgoing_fee as f64 / 10_000_000.0), - }); + self.gatekeeper_details.insert( + network.chain_id, + Details { + incoming_fee: format!("{:.5}%", network.incoming_fee as f64 / 10_000_000.0), + outgoing_fee: format!("{:.5}%", network.outgoing_fee as f64 / 10_000_000.0), + }, + ); } _ => {} }; @@ -70,12 +77,14 @@ impl Component for GatekeeperDetails { let [_, place] = super::validator_gatekeeped_networks_layout(area); let (border_style, border_type) = self.palette.create_border_style(false); - let current_gatekeeper_details = self.gatekeeper_details + let current_gatekeeper_details = self + .gatekeeper_details .get(&self.selected_chain_id) .cloned() .unwrap_or_default(); - let current_block_range = self.block_ranges + let current_block_range = self + .block_ranges .get(&self.selected_chain_id) .copied() .unwrap_or_default(); @@ -84,34 +93,45 @@ impl Component for GatekeeperDetails { vec![ Row::new(vec![ Cell::from(Text::from("From block".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(current_block_range.from_block.to_string()).alignment(Alignment::Right)), + Cell::from( + Text::from(current_block_range.from_block.to_string()) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("To block".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(current_block_range.to_block.to_string()).alignment(Alignment::Right)), + Cell::from( + Text::from(current_block_range.to_block.to_string()) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("Incoming fee".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(current_gatekeeper_details.incoming_fee).alignment(Alignment::Right)), + Cell::from( + Text::from(current_gatekeeper_details.incoming_fee) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("Outgoing fee".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(current_gatekeeper_details.outgoing_fee).alignment(Alignment::Right)), + Cell::from( + Text::from(current_gatekeeper_details.outgoing_fee) + .alignment(Alignment::Right), + ), ]), ], - [ - Constraint::Length(12), - Constraint::Fill(1), - ], + [Constraint::Length(12), Constraint::Fill(1)], ) .highlight_style(self.palette.create_highlight_style()) .column_spacing(1) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title(format!("Chain ID: {}", self.selected_chain_id))); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title(format!("Chain ID: {}", self.selected_chain_id)), + ); frame.render_widget(table, place); diff --git a/src/components/validator/gatekeeper_endpoints_popup.rs b/src/components/validator/gatekeeper_endpoints_popup.rs index cc6df37..78654a2 100644 --- a/src/components/validator/gatekeeper_endpoints_popup.rs +++ b/src/components/validator/gatekeeper_endpoints_popup.rs @@ -1,14 +1,24 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Alignment, Constraint, Flex, Layout, Position, Rect}, prelude::Margin, style::{Color, Style}, widgets::{Block, BorderType, Cell, Clear, Paragraph, Row, Scrollbar, ScrollbarOrientation, ScrollbarState, Table, TableState}, Frame + layout::{Alignment, Constraint, Flex, Layout, Position, Rect}, + prelude::Margin, + style::{Color, Style}, + widgets::{ + Block, BorderType, Cell, Clear, Paragraph, Row, Scrollbar, ScrollbarOrientation, + ScrollbarState, Table, TableState, + }, + Frame, }; -use tokio::sync::mpsc::UnboundedSender; use std::sync::mpsc::Sender; +use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ - action::Action, config::Config, palette::StylePalette, widgets::{Input, InputRequest} + action::Action, + config::Config, + palette::StylePalette, + widgets::{Input, InputRequest}, }; #[derive(Debug, Default, Eq, PartialEq)] @@ -52,13 +62,14 @@ impl GatekeeperEndpoints { } fn submit_message(&mut self) { - if let Some(network_tx) = &self.network_tx { + if let Some(network_tx) = &self.network_tx { if self.selected == Selected::Input { let mut stored_endpoints = self.stored_endpoints.clone(); stored_endpoints.push(self.rpc_input.value().to_string()); let _ = network_tx.send(Action::UpdateStoredRpcEndpoints( - self.chain_id, - stored_endpoints)); + self.chain_id, + stored_endpoints, + )); self.rpc_input = Input::new(String::new()); } } @@ -68,27 +79,26 @@ impl GatekeeperEndpoints { match self.selected { Selected::Input => { let _ = self.rpc_input.handle(InputRequest::InsertChar(new_char)); - }, + } Selected::StoredRpcs if (new_char == 'd' || new_char == 'D') => { if let Some(index) = self.stored_table_state.selected() { let mut stored_endpoints = self.stored_endpoints.clone(); if let Some(network_tx) = &self.network_tx { stored_endpoints.remove(index); let _ = network_tx.send(Action::UpdateStoredRpcEndpoints( - self.chain_id, - stored_endpoints)); + self.chain_id, + stored_endpoints, + )); } } - }, - _ => { - match new_char { - 'j' => self.move_cursor_down(), - 'k' => self.move_cursor_up(), - 'l' => self.move_cursor_right(), - 'h' => self.move_cursor_left(), - _ => {} - } } + _ => match new_char { + 'j' => self.move_cursor_down(), + 'k' => self.move_cursor_up(), + 'l' => self.move_cursor_right(), + 'h' => self.move_cursor_left(), + _ => {} + }, } } @@ -100,7 +110,7 @@ impl GatekeeperEndpoints { fn move_cursor_up(&mut self) { match self.selected { - Selected::Input => {}, + Selected::Input => {} Selected::DefaultRpcs => { let i = match self.default_table_state.selected() { Some(i) => { @@ -109,12 +119,12 @@ impl GatekeeperEndpoints { } else { i - 1 } - }, - None => 0 + } + None => 0, }; self.default_table_state.select(Some(i)); self.default_scroll_state = self.default_scroll_state.position(i); - }, + } Selected::StoredRpcs => { let i = match self.stored_table_state.selected() { Some(i) => { @@ -123,18 +133,18 @@ impl GatekeeperEndpoints { } else { i - 1 } - }, - None => 0 + } + None => 0, }; self.stored_table_state.select(Some(i)); self.stored_scroll_state = self.stored_scroll_state.position(i); - }, + } }; } fn move_cursor_down(&mut self) { match self.selected { - Selected::Input => {}, + Selected::Input => {} Selected::DefaultRpcs => { let i = match self.default_table_state.selected() { Some(i) => { @@ -143,12 +153,12 @@ impl GatekeeperEndpoints { } else { i + 1 } - }, + } None => 0, }; self.default_table_state.select(Some(i)); self.default_scroll_state = self.default_scroll_state.position(i); - }, + } Selected::StoredRpcs => { let i = match self.stored_table_state.selected() { Some(i) => { @@ -157,12 +167,12 @@ impl GatekeeperEndpoints { } else { i + 1 } - }, + } None => 0, }; self.stored_table_state.select(Some(i)); self.stored_scroll_state = self.stored_scroll_state.position(i); - }, + } }; } @@ -200,18 +210,20 @@ impl GatekeeperEndpoints { scrollbar_style: Style, ) -> (Table<'a>, Scrollbar<'a>) { let table = Table::new( - rpcs.iter().map(|endpoint| Row::new(vec![ - Cell::from(endpoint.as_str()) - ])).collect::>(), + rpcs.iter() + .map(|endpoint| Row::new(vec![Cell::from(endpoint.as_str())])) + .collect::>(), [Constraint::Min(1)], ) - .highlight_style(self.palette.create_highlight_style()) - .block(Block::bordered() + .highlight_style(self.palette.create_highlight_style()) + .block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_alignment(Alignment::Right) .title_style(self.palette.create_title_style(false)) - .title(title_name)); + .title(title_name), + ); let scrollbar = Scrollbar::default() .orientation(ScrollbarOrientation::VerticalRight) @@ -230,7 +242,7 @@ impl PartialComponent for GatekeeperEndpoints { _ => { self.is_active = false; self.rpc_input = Input::new(String::new()); - }, + } }; } } @@ -248,16 +260,26 @@ impl Component for GatekeeperEndpoints { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } Ok(()) } @@ -272,8 +294,8 @@ impl Component for GatekeeperEndpoints { KeyCode::Right => self.move_cursor_right(), KeyCode::Up => self.move_cursor_up(), KeyCode::Down => self.move_cursor_down(), - KeyCode::Esc => self.close_popup(), - _ => {}, + KeyCode::Esc => self.close_popup(), + _ => {} }; } Ok(None) @@ -282,10 +304,12 @@ impl Component for GatekeeperEndpoints { fn update(&mut self, action: Action) -> Result> { match action { Action::SetChoosenGatekeeper(chain_id) => self.set_chain_id(chain_id), - Action::SetGatekeepedNetwork(network) => - self.default_endpoints = network.default_endpoints, - Action::SetStoredRpcEndpoints(stored_endpoints) => - self.stored_endpoints = stored_endpoints, + Action::SetGatekeepedNetwork(network) => { + self.default_endpoints = network.default_endpoints + } + Action::SetStoredRpcEndpoints(stored_endpoints) => { + self.stored_endpoints = stored_endpoints + } _ => {} }; Ok(None) @@ -294,7 +318,8 @@ impl Component for GatekeeperEndpoints { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { if self.is_active { let (border_style, border_type) = self.palette.create_popup_style(); - let (selected_border_style, selected_border_type) = self.palette.create_border_style(true); + let (selected_border_style, selected_border_type) = + self.palette.create_border_style(true); let scrollbar_style = self.palette.create_scrollbar_style(); let (default_border_style, default_border_type) = match self.selected { @@ -327,13 +352,14 @@ impl Component for GatekeeperEndpoints { scrollbar_style, ); - let input = Paragraph::new(self.rpc_input.value()) - .block(Block::bordered() + let input = Paragraph::new(self.rpc_input.value()).block( + Block::bordered() .border_style(input_border_style) .border_type(input_border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title("Input new RPC")); + .title("Input new RPC"), + ); let v = Layout::vertical([Constraint::Max(14)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(80)]).flex(Flex::Center); @@ -341,34 +367,44 @@ impl Component for GatekeeperEndpoints { let [area] = h.areas(area); frame.render_widget(Clear, area); - let [tables_area, input_area] = Layout::vertical([ - Constraint::Length(11), - Constraint::Length(3), - ]).areas(area); + let [tables_area, input_area] = + Layout::vertical([Constraint::Length(11), Constraint::Length(3)]).areas(area); - let [default_table_area, stored_table_area] = Layout::horizontal([ - Constraint::Max(40), - Constraint::Max(40), - ]).areas(tables_area); + let [default_table_area, stored_table_area] = + Layout::horizontal([Constraint::Max(40), Constraint::Max(40)]).areas(tables_area); - frame.render_stateful_widget(default_rpcs, default_table_area, &mut self.default_table_state); + frame.render_stateful_widget( + default_rpcs, + default_table_area, + &mut self.default_table_state, + ); frame.render_stateful_widget( default_scrollbar, - default_table_area.inner(Margin { vertical: 1, horizontal: 1 }), + default_table_area.inner(Margin { + vertical: 1, + horizontal: 1, + }), &mut self.default_scroll_state, ); - frame.render_stateful_widget(stored_rpcs, stored_table_area, &mut self.stored_table_state); + frame.render_stateful_widget( + stored_rpcs, + stored_table_area, + &mut self.stored_table_state, + ); frame.render_stateful_widget( stored_scrollbar, - stored_table_area.inner(Margin { vertical: 1, horizontal: 1 }), + stored_table_area.inner(Margin { + vertical: 1, + horizontal: 1, + }), &mut self.stored_scroll_state, ); frame.render_widget(input, input_area); frame.set_cursor_position(Position::new( - input_area.x + self.rpc_input.cursor() as u16 + 1, - input_area.y + 1 + input_area.x + self.rpc_input.cursor() as u16 + 1, + input_area.y + 1, )); } Ok(()) diff --git a/src/components/validator/gatekeepers.rs b/src/components/validator/gatekeepers.rs index 762cf9b..b446906 100644 --- a/src/components/validator/gatekeepers.rs +++ b/src/components/validator/gatekeepers.rs @@ -1,24 +1,17 @@ -use std::collections::HashMap; use color_eyre::Result; use crossterm::event::{KeyCode, KeyEvent}; use ratatui::layout::Margin; use ratatui::{ - layout::{Alignment, Rect}, - widgets::{ - Block, List, ListState, ListItem, Scrollbar, - ScrollbarOrientation, ScrollbarState, - }, - Frame + layout::{Alignment, Rect}, + widgets::{Block, List, ListItem, ListState, Scrollbar, ScrollbarOrientation, ScrollbarState}, + Frame, }; +use std::collections::HashMap; use tokio::sync::mpsc::UnboundedSender; -use super::{PartialComponent, Component, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::types::Gatekeeper; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, -}; +use crate::{action::Action, config::Config, palette::StylePalette}; struct NetworkDetails { chain_id: u64, @@ -69,13 +62,11 @@ impl Gatekeepers { fn change_choosen_gatekeeper(&mut self) { if let Some(action_tx) = &self.action_tx { - if let Some(chain_id) = self.list_state + if let Some(chain_id) = self + .list_state .selected() - .map(|index| self.gatekeepers - .get(index) - .map(|data| data.chain_id) - ) - .flatten() + .map(|index| self.gatekeepers.get(index).map(|data| data.chain_id)) + .flatten() { let _ = action_tx.send(Action::SetChoosenGatekeeper(chain_id)); } @@ -120,7 +111,7 @@ impl Gatekeepers { } else { i + 1 } - }, + } None => 0, }; self.list_state.select(Some(i)); @@ -145,8 +136,8 @@ impl Gatekeepers { } else { i - 1 } - }, - None => 0 + } + None => 0, }; self.list_state.select(Some(i)); self.scroll_state = self.scroll_state.position(i); @@ -175,22 +166,29 @@ impl Component for Gatekeepers { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Validator) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } Ok(()) } fn update(&mut self, action: Action) -> Result> { match action { - Action::SetGatekeepedNetwork(network) => - self.update_gatekeeped_network(network), + Action::SetGatekeepedNetwork(network) => self.update_gatekeeped_network(network), _ => {} }; Ok(None) @@ -199,13 +197,13 @@ impl Component for Gatekeepers { fn handle_key_event(&mut self, key: KeyEvent) -> Result> { if self.is_active { match key.code { - KeyCode::Up | KeyCode::Char('k') => self.previous_row(), - KeyCode::Down | KeyCode::Char('j') => self.next_row(), + KeyCode::Up | KeyCode::Char('k') => self.previous_row(), + KeyCode::Down | KeyCode::Char('j') => self.next_row(), KeyCode::Char('g') => self.first_row(), KeyCode::Char('G') => self.last_row(), KeyCode::Char('O') => self.nullify_evm_blocks(), KeyCode::Enter => self.gatekeeper_endpoints(), - _ => {}, + _ => {} }; } Ok(None) @@ -214,21 +212,21 @@ impl Component for Gatekeepers { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { let [place, _] = super::validator_gatekeeped_networks_layout(area); let (border_style, border_type) = self.palette.create_border_style(self.is_active); - let list = List::new( - self.gatekeepers - .iter() - .map(|network| ListItem::new(format!("{} (type {})", - network.chain_name, - network.chain_type)) - ) - ) - .highlight_style(self.palette.create_highlight_style()) - .block(Block::bordered() + let list = List::new(self.gatekeepers.iter().map(|network| { + ListItem::new(format!( + "{} (type {})", + network.chain_name, network.chain_type + )) + })) + .highlight_style(self.palette.create_highlight_style()) + .block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_alignment(Alignment::Right) .title_style(self.palette.create_title_style(false)) - .title("Gatekeeped Networks")); + .title("Gatekeeped Networks"), + ); let scrollbar = Scrollbar::default() .orientation(ScrollbarOrientation::VerticalRight) @@ -239,7 +237,10 @@ impl Component for Gatekeepers { frame.render_stateful_widget(list, place, &mut self.list_state); frame.render_stateful_widget( scrollbar, - place.inner(Margin { vertical: 1, horizontal: 1 }), + place.inner(Margin { + vertical: 1, + horizontal: 1, + }), &mut self.scroll_state, ); diff --git a/src/components/validator/history.rs b/src/components/validator/history.rs index 355c95e..c9b96a1 100644 --- a/src/components/validator/history.rs +++ b/src/components/validator/history.rs @@ -1,4 +1,4 @@ -use std::collections::{HashSet, BTreeMap}; +use std::collections::{BTreeMap, HashSet}; use std::sync::mpsc::Sender; use color_eyre::Result; @@ -6,24 +6,20 @@ use crossterm::event::{KeyCode, KeyEvent}; use ratatui::layout::{Constraint, Margin}; use ratatui::style::Modifier; use ratatui::{ + layout::{Alignment, Rect}, prelude::Stylize, text::Text, - layout::{Alignment, Rect}, widgets::{ - Block, Cell, Row, Table, TableState, Scrollbar, Padding, - ScrollbarOrientation, ScrollbarState, - }, - Frame + Block, Cell, Padding, Row, Scrollbar, ScrollbarOrientation, ScrollbarState, Table, + TableState, + }, + Frame, }; use tokio::sync::mpsc::UnboundedSender; -use super::{PartialComponent, Component, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::types::{ActionLevel, ActionTarget}; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, -}; +use crate::{action::Action, config::Config, palette::StylePalette}; struct EraStakingInfo { reward: u128, @@ -66,7 +62,8 @@ impl History { } fn payout_all_available(&mut self) { - let unclaimed_keys = self.rewards + let unclaimed_keys = self + .rewards .iter() .filter_map(|(k, v)| (!v.is_claimed && v.reward > 0).then(|| *k)) .collect::>(); @@ -74,9 +71,10 @@ impl History { if let Some(action_tx) = &self.action_tx { let _ = if unclaimed_keys.len() == 0 { action_tx.send(Action::EventLog( - String::from("no available payouts found for current validator"), - ActionLevel::Warn, - ActionTarget::ValidatorLog)) + String::from("no available payouts found for current validator"), + ActionLevel::Warn, + ActionTarget::ValidatorLog, + )) } else { self.pending_payout.extend(&unclaimed_keys); action_tx.send(Action::PayoutAllValidatorPopup(unclaimed_keys)) @@ -86,12 +84,11 @@ impl History { fn payout_by_era_index(&mut self) { if let Some(index) = self.table_state.selected() { - let rev_index = self.rewards.len() - .saturating_sub(index) - .saturating_sub(1); + let rev_index = self.rewards.len().saturating_sub(index).saturating_sub(1); if let Some(era_index) = self.rewards.keys().nth(rev_index) { - let is_claimed = self.rewards + let is_claimed = self + .rewards .get(&era_index) .map(|x| x.is_claimed) .expect("BTreeMap of rewards is indexed; qed"); @@ -103,13 +100,18 @@ impl History { action_tx.send(Action::PayoutValidatorPopup(*era_index)) } (false, true) => action_tx.send(Action::EventLog( - format!("payout for era #{} is in-flight already", era_index), - ActionLevel::Warn, - ActionTarget::ValidatorLog)), + format!("payout for era #{} is in-flight already", era_index), + ActionLevel::Warn, + ActionTarget::ValidatorLog, + )), (true, _) => action_tx.send(Action::EventLog( - format!("staking rewards for era index #{} already claimed", era_index), - ActionLevel::Warn, - ActionTarget::ValidatorLog)), + format!( + "staking rewards for era index #{} already claimed", + era_index + ), + ActionLevel::Warn, + ActionTarget::ValidatorLog, + )), }; } } @@ -131,7 +133,7 @@ impl History { } else { i + 1 } - }, + } None => 0, }; self.table_state.select(Some(i)); @@ -154,8 +156,8 @@ impl History { } else { i - 1 } - }, - None => 0 + } + None => 0, }; self.table_state.select(Some(i)); self.scroll_state = self.scroll_state.position(i); @@ -165,11 +167,14 @@ impl History { match self.rewards.get_mut(&era_index) { Some(reward_item) => reward_item.reward = reward, None => { - let _ = self.rewards.insert(era_index, EraStakingInfo { - reward, - slash: 0u128, - is_claimed: false, - }); + let _ = self.rewards.insert( + era_index, + EraStakingInfo { + reward, + slash: 0u128, + is_claimed: false, + }, + ); } } self.scroll_state = self.scroll_state.content_length(self.rewards.len()); @@ -187,11 +192,14 @@ impl History { reward_item.is_claimed = is_claimed; } None => { - let _ = self.rewards.insert(era_index, EraStakingInfo { - reward: 0u128, - slash: 0u128, - is_claimed, - }); + let _ = self.rewards.insert( + era_index, + EraStakingInfo { + reward: 0u128, + slash: 0u128, + is_claimed, + }, + ); } } } @@ -200,11 +208,14 @@ impl History { match self.rewards.get_mut(&era_index) { Some(reward_item) => reward_item.slash = slash, None => { - let _ = self.rewards.insert(era_index, EraStakingInfo { - reward: 0u128, - slash, - is_claimed: false, - }); + let _ = self.rewards.insert( + era_index, + EraStakingInfo { + reward: 0u128, + slash, + is_claimed: false, + }, + ); } } } @@ -222,7 +233,7 @@ impl PartialComponent for History { CurrentTab::History => { self.is_active = true; self.pending_payout = Default::default(); - }, + } _ => self.is_active = false, } } @@ -241,22 +252,34 @@ impl Component for History { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Validator) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } Ok(()) } fn update(&mut self, action: Action) -> Result> { match action { - Action::SetValidatorEraReward(era_index, reward) => self.update_rewards(era_index, reward), - Action::SetValidatorEraClaimed(era_index, is_claimed) => self.update_claims(era_index, is_claimed), + Action::SetValidatorEraReward(era_index, reward) => { + self.update_rewards(era_index, reward) + } + Action::SetValidatorEraClaimed(era_index, is_claimed) => { + self.update_claims(era_index, is_claimed) + } Action::SetValidatorEraSlash(era_index, slash) => self.update_slashes(era_index, slash), _ => {} }; @@ -266,13 +289,13 @@ impl Component for History { fn handle_key_event(&mut self, key: KeyEvent) -> Result> { if self.is_active { match key.code { - KeyCode::Up | KeyCode::Char('k') => self.previous_row(), - KeyCode::Down | KeyCode::Char('j') => self.next_row(), + KeyCode::Up | KeyCode::Char('k') => self.previous_row(), + KeyCode::Down | KeyCode::Char('j') => self.next_row(), KeyCode::Char('g') => self.first_row(), KeyCode::Char('G') => self.last_row(), KeyCode::Char('H') => self.payout_all_available(), KeyCode::Enter => self.payout_by_era_index(), - _ => {}, + _ => {} }; } Ok(None) @@ -282,38 +305,38 @@ impl Component for History { let [_, place, _] = super::validator_statistics_layout(area); let (border_style, border_type) = self.palette.create_border_style(self.is_active); let table = Table::new( - self.rewards - .iter() - .rev() - .map(|(key, value)| { - let mut era_index_text = Text::from(key.to_string()).alignment(Alignment::Left); - let mut slash_text = Text::from(self.prepare_u128(value.slash)).alignment(Alignment::Center); - let mut reward_text = Text::from(self.prepare_u128(value.reward)).alignment(Alignment::Right); + self.rewards.iter().rev().map(|(key, value)| { + let mut era_index_text = Text::from(key.to_string()).alignment(Alignment::Left); + let mut slash_text = + Text::from(self.prepare_u128(value.slash)).alignment(Alignment::Center); + let mut reward_text = + Text::from(self.prepare_u128(value.reward)).alignment(Alignment::Right); - if value.is_claimed { - era_index_text = era_index_text.add_modifier(Modifier::CROSSED_OUT); - slash_text = slash_text.add_modifier(Modifier::CROSSED_OUT); - reward_text = reward_text.add_modifier(Modifier::CROSSED_OUT); + if value.is_claimed { + era_index_text = era_index_text.add_modifier(Modifier::CROSSED_OUT); + slash_text = slash_text.add_modifier(Modifier::CROSSED_OUT); + reward_text = reward_text.add_modifier(Modifier::CROSSED_OUT); - Row::new(vec![ - Cell::from(era_index_text), - Cell::from(slash_text), - Cell::from(reward_text), - ]).style(self.palette.create_highlight_style()) - } else { - if self.pending_payout.contains(key) { - era_index_text = era_index_text.add_modifier(Modifier::SLOW_BLINK); - slash_text = slash_text.add_modifier(Modifier::SLOW_BLINK); - reward_text = reward_text.add_modifier(Modifier::SLOW_BLINK); - } - - Row::new(vec![ - Cell::from(era_index_text), - Cell::from(slash_text), - Cell::from(reward_text), - ]) + Row::new(vec![ + Cell::from(era_index_text), + Cell::from(slash_text), + Cell::from(reward_text), + ]) + .style(self.palette.create_highlight_style()) + } else { + if self.pending_payout.contains(key) { + era_index_text = era_index_text.add_modifier(Modifier::SLOW_BLINK); + slash_text = slash_text.add_modifier(Modifier::SLOW_BLINK); + reward_text = reward_text.add_modifier(Modifier::SLOW_BLINK); } - }), + + Row::new(vec![ + Cell::from(era_index_text), + Cell::from(slash_text), + Cell::from(reward_text), + ]) + } + }), [ Constraint::Length(4), Constraint::Fill(1), @@ -322,13 +345,15 @@ impl Component for History { ) .highlight_style(self.palette.create_basic_style(true)) .column_spacing(1) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .padding(Padding::right(2)) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("Staking history")); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .padding(Padding::right(2)) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("Staking history"), + ); let scrollbar = Scrollbar::default() .orientation(ScrollbarOrientation::VerticalRight) @@ -339,7 +364,10 @@ impl Component for History { frame.render_stateful_widget(table, place, &mut self.table_state); frame.render_stateful_widget( scrollbar, - place.inner(Margin { vertical: 1, horizontal: 1 }), + place.inner(Margin { + vertical: 1, + horizontal: 1, + }), &mut self.scroll_state, ); diff --git a/src/components/validator/listen_addresses.rs b/src/components/validator/listen_addresses.rs index 5f3f421..b0eaac4 100644 --- a/src/components/validator/listen_addresses.rs +++ b/src/components/validator/listen_addresses.rs @@ -3,21 +3,14 @@ use crossterm::event::{KeyCode, KeyEvent}; use ratatui::layout::Margin; use ratatui::widgets::ListItem; use ratatui::{ - layout::{Alignment, Rect}, - widgets::{ - Block, List, ListState, Scrollbar, - ScrollbarOrientation, ScrollbarState, - }, - Frame + layout::{Alignment, Rect}, + widgets::{Block, List, ListState, Scrollbar, ScrollbarOrientation, ScrollbarState}, + Frame, }; use tokio::sync::mpsc::UnboundedSender; -use super::{PartialComponent, Component, CurrentTab}; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, -}; +use super::{Component, CurrentTab, PartialComponent}; +use crate::{action::Action, config::Config, palette::StylePalette}; pub struct ListenAddresses { is_active: bool, @@ -63,7 +56,7 @@ impl ListenAddresses { } else { i + 1 } - }, + } None => 0, }; self.list_state.select(Some(i)); @@ -86,8 +79,8 @@ impl ListenAddresses { } else { i - 1 } - }, - None => 0 + } + None => 0, }; self.list_state.select(Some(i)); self.scroll_state = self.scroll_state.position(i); @@ -115,14 +108,22 @@ impl Component for ListenAddresses { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Wallet) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } Ok(()) } @@ -139,11 +140,11 @@ impl Component for ListenAddresses { fn handle_key_event(&mut self, key: KeyEvent) -> Result> { if self.is_active { match key.code { - KeyCode::Up | KeyCode::Char('k') => self.previous_row(), - KeyCode::Down | KeyCode::Char('j') => self.next_row(), + KeyCode::Up | KeyCode::Char('k') => self.previous_row(), + KeyCode::Down | KeyCode::Char('j') => self.next_row(), KeyCode::Char('g') => self.first_row(), KeyCode::Char('G') => self.last_row(), - _ => {}, + _ => {} }; } Ok(None) @@ -155,15 +156,17 @@ impl Component for ListenAddresses { let list = List::new( self.listen_addresses .iter() - .map(|addr| ListItem::new(addr.clone())) - ) - .highlight_style(self.palette.create_highlight_style()) - .block(Block::bordered() + .map(|addr| ListItem::new(addr.clone())), + ) + .highlight_style(self.palette.create_highlight_style()) + .block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_alignment(Alignment::Right) .title_style(self.palette.create_title_style(false)) - .title(self.local_identity.clone())); + .title(self.local_identity.clone()), + ); let scrollbar = Scrollbar::default() .orientation(ScrollbarOrientation::VerticalRight) @@ -174,7 +177,10 @@ impl Component for ListenAddresses { frame.render_stateful_widget(list, place, &mut self.list_state); frame.render_stateful_widget( scrollbar, - place.inner(Margin { vertical: 1, horizontal: 1 }), + place.inner(Margin { + vertical: 1, + horizontal: 1, + }), &mut self.scroll_state, ); diff --git a/src/components/validator/mod.rs b/src/components/validator/mod.rs index 5312db8..024df70 100644 --- a/src/components/validator/mod.rs +++ b/src/components/validator/mod.rs @@ -11,55 +11,55 @@ use tokio::sync::mpsc::UnboundedSender; use super::Component; use crate::{action::Action, app::Mode, config::Config}; -mod event_log; -mod peers; -mod stash_info; -mod nominators; -mod listen_addresses; -mod gatekeepers; -mod gatekeeper_details; -mod history; -mod withdrawals; -mod stash_details; -mod staking_details; -mod reward_details; mod bond_popup; -mod payout_popup; -mod payout_all_popup; -mod rotate_popup; -mod validate_popup; -mod chill_popup; -mod unbond_popup; -mod rebond_popup; -mod withdraw_popup; -mod payee_popup; mod change_blocks_popup; +mod chill_popup; +mod event_log; +mod gatekeeper_details; mod gatekeeper_endpoints_popup; +mod gatekeepers; +mod history; +mod listen_addresses; +mod nominators; +mod payee_popup; +mod payout_all_popup; +mod payout_popup; +mod peers; +mod rebond_popup; +mod reward_details; +mod rotate_popup; +mod staking_details; +mod stash_details; +mod stash_info; +mod unbond_popup; +mod validate_popup; +mod withdraw_popup; +mod withdrawals; -use stash_details::StashDetails; -use staking_details::StakingDetails; -use reward_details::RewardDetails; -use event_log::EventLogs; -use peers::Peers; -use stash_info::StashInfo; -use listen_addresses::ListenAddresses; -use gatekeepers::Gatekeepers; -use gatekeeper_details::GatekeeperDetails; -use nominators::NominatorsByValidator; -use history::History; -use withdrawals::Withdrawals; use bond_popup::BondPopup; -use payout_popup::PayoutPopup; -use payout_all_popup::PayoutAllPopup; -use rotate_popup::RotatePopup; -use validate_popup::ValidatePopup; -use chill_popup::ChillPopup; -use unbond_popup::UnbondPopup; -use rebond_popup::RebondPopup; -use withdraw_popup::WithdrawPopup; -use payee_popup::PayeePopup; use change_blocks_popup::ChangeBlocksPopup; +use chill_popup::ChillPopup; +use event_log::EventLogs; +use gatekeeper_details::GatekeeperDetails; use gatekeeper_endpoints_popup::GatekeeperEndpoints; +use gatekeepers::Gatekeepers; +use history::History; +use listen_addresses::ListenAddresses; +use nominators::NominatorsByValidator; +use payee_popup::PayeePopup; +use payout_all_popup::PayoutAllPopup; +use payout_popup::PayoutPopup; +use peers::Peers; +use rebond_popup::RebondPopup; +use reward_details::RewardDetails; +use rotate_popup::RotatePopup; +use staking_details::StakingDetails; +use stash_details::StashDetails; +use stash_info::StashInfo; +use unbond_popup::UnbondPopup; +use validate_popup::ValidatePopup; +use withdraw_popup::WithdrawPopup; +use withdrawals::Withdrawals; #[derive(Debug, Copy, Clone, PartialEq)] pub enum CurrentTab { @@ -182,24 +182,26 @@ impl Component for Validator { } fn handle_key_event(&mut self, key: KeyEvent) -> Result> { - if !self.is_active { return Ok(None) } + if !self.is_active { + return Ok(None); + } match self.current_tab { - CurrentTab::BondPopup | - CurrentTab::RotatePopup | - CurrentTab::ValidatePopup | - CurrentTab::ChillPopup | - CurrentTab::UnbondPopup | - CurrentTab::RebondPopup | - CurrentTab::WithdrawPopup | - CurrentTab::PayoutPopup | - CurrentTab::PayoutAllPopup | - CurrentTab::ChangeBlocksPopup | - CurrentTab::GatekeeperEndpoints => { - for component in self.components.iter_mut() { - component.handle_key_event(key)?; - } - }, + CurrentTab::BondPopup + | CurrentTab::RotatePopup + | CurrentTab::ValidatePopup + | CurrentTab::ChillPopup + | CurrentTab::UnbondPopup + | CurrentTab::RebondPopup + | CurrentTab::WithdrawPopup + | CurrentTab::PayoutPopup + | CurrentTab::PayoutAllPopup + | CurrentTab::ChangeBlocksPopup + | CurrentTab::GatekeeperEndpoints => { + for component in self.components.iter_mut() { + component.handle_key_event(key)?; + } + } _ => match key.code { KeyCode::Esc => { self.is_active = false; @@ -208,51 +210,51 @@ impl Component for Validator { component.set_active(self.current_tab.clone()); } return Ok(Some(Action::SetActiveScreen(Mode::Menu))); - }, + } KeyCode::Char('R') => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::RotatePopup; - }, + } KeyCode::Char('V') => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::ValidatePopup; - }, + } KeyCode::Char('U') => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::UnbondPopup; - }, + } KeyCode::Char('C') => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::ChillPopup; - }, + } KeyCode::Char('B') => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::BondPopup; - }, + } KeyCode::Char('E') => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::RebondPopup; - }, + } KeyCode::Char('W') => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::WithdrawPopup; - }, + } KeyCode::Char('L') => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::ListenAddresses; - }, + } KeyCode::Char('I') => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::PayeePopup; - }, + } KeyCode::Char('l') | KeyCode::Right => self.move_right(), KeyCode::Char('h') | KeyCode::Left => self.move_left(), _ => { for component in self.components.iter_mut() { component.handle_key_event(key)?; } - }, - } + } + }, } Ok(None) } @@ -275,17 +277,17 @@ impl Component for Validator { Action::WithdrawValidatorPopup => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::WithdrawPopup; - }, + } Action::ChangeBlocksPopup => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::ChangeBlocksPopup; - }, + } Action::GatekeeperEndpoints => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::GatekeeperEndpoints; - }, + } Action::ClosePopup => self.current_tab = self.previous_tab, - _ => {}, + _ => {} } for component in self.components.iter_mut() { component.set_active(self.current_tab.clone()); @@ -309,15 +311,13 @@ pub fn validator_layout(area: Rect) -> [Rect; 4] { Constraint::Fill(1), Constraint::Fill(1), Constraint::Percentage(25), - ]).areas(area) + ]) + .areas(area) } pub fn validator_details_layout(area: Rect) -> [Rect; 2] { let [place, _, _, _] = validator_layout(area); - Layout::horizontal([ - Constraint::Length(31), - Constraint::Fill(1), - ]).areas(place) + Layout::horizontal([Constraint::Length(31), Constraint::Fill(1)]).areas(place) } pub fn validator_session_and_listen_layout(area: Rect) -> [Rect; 3] { @@ -326,15 +326,13 @@ pub fn validator_session_and_listen_layout(area: Rect) -> [Rect; 3] { Constraint::Length(6), Constraint::Length(6), Constraint::Fill(1), - ]).areas(place) + ]) + .areas(place) } pub fn validator_gatekeeped_networks_layout(area: Rect) -> [Rect; 2] { let [_, _, place] = validator_session_and_listen_layout(area); - Layout::horizontal([ - Constraint::Fill(1), - Constraint::Length(30), - ]).areas(place) + Layout::horizontal([Constraint::Fill(1), Constraint::Length(30)]).areas(place) } pub fn validator_statistics_layout(area: Rect) -> [Rect; 3] { @@ -343,7 +341,8 @@ pub fn validator_statistics_layout(area: Rect) -> [Rect; 3] { Constraint::Percentage(30), Constraint::Percentage(40), Constraint::Percentage(30), - ]).areas(place) + ]) + .areas(place) } pub fn validator_balance_layout(area: Rect) -> [Rect; 3] { @@ -352,5 +351,6 @@ pub fn validator_balance_layout(area: Rect) -> [Rect; 3] { Constraint::Length(6), Constraint::Length(6), Constraint::Fill(1), - ]).areas(place) + ]) + .areas(place) } diff --git a/src/components/validator/nominators.rs b/src/components/validator/nominators.rs index 2ddfc3c..c7c8019 100644 --- a/src/components/validator/nominators.rs +++ b/src/components/validator/nominators.rs @@ -2,23 +2,19 @@ use color_eyre::Result; use crossterm::event::{KeyCode, KeyEvent}; use ratatui::layout::{Constraint, Margin}; use ratatui::{ + layout::{Alignment, Rect}, text::Text, - layout::{Alignment, Rect}, widgets::{ - Block, Cell, Row, Table, TableState, Scrollbar, Padding, - ScrollbarOrientation, ScrollbarState, - }, - Frame + Block, Cell, Padding, Row, Scrollbar, ScrollbarOrientation, ScrollbarState, Table, + TableState, + }, + Frame, }; use tokio::sync::mpsc::UnboundedSender; -use super::{PartialComponent, Component, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::types::Nominator; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, -}; +use crate::{action::Action, config::Config, palette::StylePalette}; pub struct NominatorsByValidator { is_active: bool, @@ -76,7 +72,7 @@ impl NominatorsByValidator { } else { i + 1 } - }, + } None => 0, }; self.table_state.select(Some(i)); @@ -99,8 +95,8 @@ impl NominatorsByValidator { } else { i - 1 } - }, - None => 0 + } + None => 0, }; self.table_state.select(Some(i)); self.scroll_state = self.scroll_state.position(i); @@ -134,14 +130,22 @@ impl Component for NominatorsByValidator { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Validator) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } Ok(()) } @@ -149,8 +153,11 @@ impl Component for NominatorsByValidator { fn update(&mut self, action: Action) -> Result> { match action { Action::SetStashAccount(stash) => self.stash = stash, - Action::SetNominatorsByValidator(nominators, account_id) if self.stash == account_id => - self.update_nominators(nominators), + Action::SetNominatorsByValidator(nominators, account_id) + if self.stash == account_id => + { + self.update_nominators(nominators) + } _ => {} }; Ok(None) @@ -159,11 +166,11 @@ impl Component for NominatorsByValidator { fn handle_key_event(&mut self, key: KeyEvent) -> Result> { if self.is_active { match key.code { - KeyCode::Up | KeyCode::Char('k') => self.previous_row(), - KeyCode::Down | KeyCode::Char('j') => self.next_row(), + KeyCode::Up | KeyCode::Char('k') => self.previous_row(), + KeyCode::Down | KeyCode::Char('j') => self.next_row(), KeyCode::Char('g') => self.first_row(), KeyCode::Char('G') => self.last_row(), - _ => {}, + _ => {} }; } Ok(None) @@ -173,28 +180,27 @@ impl Component for NominatorsByValidator { let [place, _, _] = super::validator_statistics_layout(area); let (border_style, border_type) = self.palette.create_border_style(self.is_active); let table = Table::new( - self.nominators - .iter() - .map(|info| { - Row::new(vec![ - Cell::from(Text::from(info.address.clone()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(info.value)).alignment(Alignment::Right)), - ]) - }), - [ - Constraint::Min(0), - Constraint::Min(11), - ], + self.nominators.iter().map(|info| { + Row::new(vec![ + Cell::from(Text::from(info.address.clone()).alignment(Alignment::Left)), + Cell::from( + Text::from(self.prepare_u128(info.value)).alignment(Alignment::Right), + ), + ]) + }), + [Constraint::Min(0), Constraint::Min(11)], ) .highlight_style(self.palette.create_highlight_style()) .column_spacing(1) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .padding(Padding::right(2)) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("My Nominators")); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .padding(Padding::right(2)) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("My Nominators"), + ); let scrollbar = Scrollbar::default() .orientation(ScrollbarOrientation::VerticalRight) @@ -205,7 +211,10 @@ impl Component for NominatorsByValidator { frame.render_stateful_widget(table, place, &mut self.table_state); frame.render_stateful_widget( scrollbar, - place.inner(Margin { vertical: 1, horizontal: 1 }), + place.inner(Margin { + vertical: 1, + horizontal: 1, + }), &mut self.scroll_state, ); diff --git a/src/components/validator/payee_popup.rs b/src/components/validator/payee_popup.rs index 154fe80..1f615d4 100644 --- a/src/components/validator/payee_popup.rs +++ b/src/components/validator/payee_popup.rs @@ -1,23 +1,21 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Alignment, Constraint, Flex, Layout, Position, Rect}, - text::Text, - widgets::{Block, Cell, Clear, Paragraph, Row, Table, TableState}, + layout::{Alignment, Constraint, Flex, Layout, Position, Rect}, + text::Text, + widgets::{Block, Cell, Clear, Paragraph, Row, Table, TableState}, Frame, }; -use subxt::ext::sp_core::crypto::{ - ByteArray, Ss58Codec, Ss58AddressFormat, AccountId32, -}; -use tokio::sync::mpsc::UnboundedSender; use std::sync::mpsc::Sender; +use subxt::ext::sp_core::crypto::{AccountId32, ByteArray, Ss58AddressFormat, Ss58Codec}; +use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ - action::Action, - config::Config, - palette::StylePalette, - types::{ActionLevel, ActionTarget, RewardDestination}, + action::Action, + config::Config, + palette::StylePalette, + types::{ActionLevel, ActionTarget, RewardDestination}, widgets::{Input, InputRequest}, }; @@ -36,7 +34,7 @@ pub struct PayeePopup { address: Input, possible_payee_options: &'static [(&'static str, &'static str)], current_reward_destination: RewardDestination, - palette: StylePalette + palette: StylePalette, } impl Default for PayeePopup { @@ -61,9 +59,18 @@ impl PayeePopup { address: Input::new(String::new()), current_reward_destination: Default::default(), possible_payee_options: &[ - ("Re-stake", "(pay into the stash account, increasing the amount at stake accordingly)"), - ("Stake", "(pay into the stash account, not increasing the amount at stake)"), - ("Account", "(pay into a specified account different from stash)"), + ( + "Re-stake", + "(pay into the stash account, increasing the amount at stake accordingly)", + ), + ( + "Stake", + "(pay into the stash account, not increasing the amount at stake)", + ), + ( + "Account", + "(pay into a specified account different from stash)", + ), ("None", "(refuse to receive all rewards from staking)"), ], palette: StylePalette::default(), @@ -85,7 +92,7 @@ impl PayeePopup { let address = AccountId32::from(account_id) .to_ss58check_with_version(Ss58AddressFormat::custom(1996)); (2, address) - }, + } RewardDestination::None => (3, Default::default()), _ => (0, Default::default()), }; @@ -106,13 +113,12 @@ impl PayeePopup { } else { i + 1 } - }, + } None => 0, }; self.move_to_row(i); } - fn previous_row(&mut self) { let i = match self.table_state.selected() { Some(i) => { @@ -121,18 +127,15 @@ impl PayeePopup { } else { i - 1 } - }, - None => 0 + } + None => 0, }; self.move_to_row(i); } fn log_event(&mut self, message: String, level: ActionLevel) { if let Some(action_tx) = &self.action_tx { - let _ = action_tx.send(Action::EventLog( - message, - level, - ActionTarget::ValidatorLog)); + let _ = action_tx.send(Action::EventLog(message, level, ActionTarget::ValidatorLog)); } } @@ -145,8 +148,12 @@ impl PayeePopup { Ok((account_id, format)) => { if format != Ss58AddressFormat::custom(1996) { self.log_event( - format!("provided public address for {} is not part of Casper/Ghost ecosystem", self.address.value()), - ActionLevel::Error); + format!( + "provided public address for {} is not part of Casper/Ghost ecosystem", + self.address.value() + ), + ActionLevel::Error, + ); } let seed_vec = account_id.to_raw_vec(); let mut account_id = [0u8; 32]; @@ -154,15 +161,18 @@ impl PayeePopup { self.proposed_account_id = Some(account_id); self.submit_new_payee(); - }, + } _ => { self.log_event( - format!("could not create valid account id from {}", self.address.value()), - ActionLevel::Error); + format!( + "could not create valid account id from {}", + self.address.value() + ), + ActionLevel::Error, + ); self.proposed_account_id = None; } }; - } fn submit_new_payee(&mut self) { @@ -171,7 +181,8 @@ impl PayeePopup { 0 => RewardDestination::Staked, 1 => RewardDestination::Stash, 2 => { - let account_id = self.proposed_account_id + let account_id = self + .proposed_account_id .expect("checked before in submit_new_input; qed"); RewardDestination::Account(account_id) } @@ -182,17 +193,20 @@ impl PayeePopup { if !self.is_bonded { self.log_event( "no bond detected, stake minimum bond amount first".to_string(), - ActionLevel::Warn); + ActionLevel::Warn, + ); } else if new_destination == self.current_reward_destination { self.log_event( "same destination choosen, no need for transaction".to_string(), - ActionLevel::Warn); + ActionLevel::Warn, + ); } else { if let Some(network_tx) = &self.network_tx { let _ = network_tx.send(Action::SetPayee( - self.stash_secret_seed, - new_destination, - ActionTarget::ValidatorLog)); + self.stash_secret_seed, + new_destination, + ActionTarget::ValidatorLog, + )); } } if let Some(action_tx) = &self.action_tx { @@ -247,12 +261,18 @@ impl Component for PayeePopup { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); } Ok(()) } @@ -266,8 +286,8 @@ impl Component for PayeePopup { KeyCode::Backspace => self.delete_char(), KeyCode::Left => self.move_cursor_left(), KeyCode::Right => self.move_cursor_right(), - KeyCode::Esc => self.trigger_address_input(), - _ => {}, + KeyCode::Esc => self.trigger_address_input(), + _ => {} }; } else { match key.code { @@ -276,7 +296,7 @@ impl Component for PayeePopup { KeyCode::Up | KeyCode::Char('k') => self.previous_row(), KeyCode::Down | KeyCode::Char('j') => self.next_row(), KeyCode::Esc => self.close_popup(), - _ => {}, + _ => {} }; } } @@ -287,9 +307,12 @@ impl Component for PayeePopup { match action { Action::SetStashAccount(account_id) => self.stash_account_id = account_id, Action::SetStashSecret(secret_seed) => self.stash_secret_seed = secret_seed, - Action::SetIsBonded(is_bonded, account_id) if self.stash_account_id == account_id => - self.is_bonded = is_bonded, - Action::SetStakingPayee(reward_destination, account_id) if self.stash_account_id == account_id => { + Action::SetIsBonded(is_bonded, account_id) if self.stash_account_id == account_id => { + self.is_bonded = is_bonded + } + Action::SetStakingPayee(reward_destination, account_id) + if self.stash_account_id == account_id => + { let destination_changed = self.current_reward_destination != reward_destination; self.current_reward_destination = reward_destination; if destination_changed || self.table_state.selected().is_none() { @@ -306,7 +329,7 @@ impl Component for PayeePopup { if self.is_active { let (border_style, border_type) = self.palette.create_popup_style(); let size = area.as_size(); - let input_area = Rect::new(size.width / 2, size.height / 2, 51, 3); + let input_area = Rect::new(size.width / 2, size.height / 2, 51, 3); let table = Table::new( self.possible_payee_options @@ -318,16 +341,18 @@ impl Component for PayeePopup { ]) }) .collect::>(), - [Constraint::Length(8), Constraint::Min(0)] + [Constraint::Length(8), Constraint::Min(0)], ) .highlight_style(self.palette.create_highlight_style()) .column_spacing(1) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_style(self.palette.create_popup_title_style()) - .title_alignment(Alignment::Right) - .title("Select reward destination")); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_style(self.palette.create_popup_title_style()) + .title_alignment(Alignment::Right) + .title("Select reward destination"), + ); let v = Layout::vertical([Constraint::Max(6)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(83)]).flex(Flex::Center); @@ -338,13 +363,14 @@ impl Component for PayeePopup { frame.render_stateful_widget(table, area, &mut self.table_state); if self.is_input_active { - let input_amount = Paragraph::new(self.address.value()) - .block(Block::bordered() + let input_amount = Paragraph::new(self.address.value()).block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title("Destination account")); + .title("Destination account"), + ); let v = Layout::vertical([Constraint::Max(8)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(51)]).flex(Flex::Center); @@ -355,8 +381,8 @@ impl Component for PayeePopup { frame.render_widget(input_amount, input_area); frame.set_cursor_position(Position::new( - input_area.x + self.address.cursor() as u16 + 1, - input_area.y + 1 + input_area.x + self.address.cursor() as u16 + 1, + input_area.y + 1, )); } } diff --git a/src/components/validator/payout_all_popup.rs b/src/components/validator/payout_all_popup.rs index c7e1dbe..ef5e2d4 100644 --- a/src/components/validator/payout_all_popup.rs +++ b/src/components/validator/payout_all_popup.rs @@ -1,19 +1,15 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Alignment, Constraint, Flex, Layout, Rect}, - widgets::{Block, Clear, Paragraph}, - Frame + layout::{Alignment, Constraint, Flex, Layout, Rect}, + widgets::{Block, Clear, Paragraph}, + Frame, }; -use tokio::sync::mpsc::UnboundedSender; use std::sync::mpsc::Sender; +use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, -}; +use super::{Component, CurrentTab, PartialComponent}; +use crate::{action::Action, config::Config, palette::StylePalette}; #[derive(Debug)] pub struct PayoutAllPopup { @@ -23,7 +19,7 @@ pub struct PayoutAllPopup { secret_seed: [u8; 32], stash_account_id: [u8; 32], era_indexes: Vec, - palette: StylePalette + palette: StylePalette, } impl Default for PayoutAllPopup { @@ -57,9 +53,10 @@ impl PayoutAllPopup { if let Some(network_tx) = &self.network_tx { for era_index in &self.era_indexes { let _ = network_tx.send(Action::PayoutStakers( - self.secret_seed, - self.stash_account_id, - *era_index)); + self.secret_seed, + self.stash_account_id, + *era_index, + )); } } self.close_popup(); @@ -88,11 +85,16 @@ impl Component for PayoutAllPopup { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -101,8 +103,8 @@ impl Component for PayoutAllPopup { if self.is_active && key.kind == KeyEventKind::Press { match key.code { KeyCode::Enter => self.start_payout(), - KeyCode::Esc => self.close_popup(), - _ => {}, + KeyCode::Esc => self.close_popup(), + _ => {} }; } Ok(None) @@ -121,17 +123,24 @@ impl Component for PayoutAllPopup { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { if self.is_active { let (border_style, border_type) = self.palette.create_popup_style(); - let popup = Paragraph::new( - format!(" Do payout for {} eras, from {} to {}", - self.era_indexes.len(), - self.era_indexes.first().expect("Length of unclaimed indexes always more then one; qed"), - self.era_indexes.last().expect("Length of unclaimed indexes always more then one; qed"))) - .block(Block::bordered() + let popup = Paragraph::new(format!( + " Do payout for {} eras, from {} to {}", + self.era_indexes.len(), + self.era_indexes + .first() + .expect("Length of unclaimed indexes always more then one; qed"), + self.era_indexes + .last() + .expect("Length of unclaimed indexes always more then one; qed") + )) + .block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title("Enter to proceed / Esc to close")); + .title("Enter to proceed / Esc to close"), + ); let v = Layout::vertical([Constraint::Max(3)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(50)]).flex(Flex::Center); let [area] = v.areas(area); diff --git a/src/components/validator/payout_popup.rs b/src/components/validator/payout_popup.rs index 4ff301e..ab27e7b 100644 --- a/src/components/validator/payout_popup.rs +++ b/src/components/validator/payout_popup.rs @@ -1,19 +1,15 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Alignment, Constraint, Flex, Layout, Rect}, - widgets::{Block, Clear, Paragraph}, - Frame + layout::{Alignment, Constraint, Flex, Layout, Rect}, + widgets::{Block, Clear, Paragraph}, + Frame, }; -use tokio::sync::mpsc::UnboundedSender; use std::sync::mpsc::Sender; +use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, -}; +use super::{Component, CurrentTab, PartialComponent}; +use crate::{action::Action, config::Config, palette::StylePalette}; #[derive(Debug)] pub struct PayoutPopup { @@ -23,7 +19,7 @@ pub struct PayoutPopup { secret_seed: [u8; 32], stash_account_id: [u8; 32], era_index: u32, - palette: StylePalette + palette: StylePalette, } impl Default for PayoutPopup { @@ -55,9 +51,10 @@ impl PayoutPopup { fn start_payout(&mut self) { if let Some(network_tx) = &self.network_tx { let _ = network_tx.send(Action::PayoutStakers( - self.secret_seed, - self.stash_account_id, - self.era_index)); + self.secret_seed, + self.stash_account_id, + self.era_index, + )); } if let Some(action_tx) = &self.action_tx { let _ = action_tx.send(Action::ClosePopup); @@ -87,11 +84,16 @@ impl Component for PayoutPopup { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -100,8 +102,8 @@ impl Component for PayoutPopup { if self.is_active && key.kind == KeyEventKind::Press { match key.code { KeyCode::Enter => self.start_payout(), - KeyCode::Esc => self.close_popup(), - _ => {}, + KeyCode::Esc => self.close_popup(), + _ => {} }; } Ok(None) @@ -120,13 +122,14 @@ impl Component for PayoutPopup { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { if self.is_active { let (border_style, border_type) = self.palette.create_popup_style(); - let popup = Paragraph::new(format!(" Do payout for era #{}", self.era_index)) - .block(Block::bordered() + let popup = Paragraph::new(format!(" Do payout for era #{}", self.era_index)).block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title("Enter to proceed / Esc to close")); + .title("Enter to proceed / Esc to close"), + ); let v = Layout::vertical([Constraint::Max(3)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(50)]).flex(Flex::Center); let [area] = v.areas(area); diff --git a/src/components/validator/peers.rs b/src/components/validator/peers.rs index 28e4233..0212517 100644 --- a/src/components/validator/peers.rs +++ b/src/components/validator/peers.rs @@ -2,22 +2,18 @@ use color_eyre::Result; use crossterm::event::{KeyCode, KeyEvent}; use ratatui::layout::{Constraint, Margin}; use ratatui::{ + layout::{Alignment, Rect}, text::Text, - layout::{Alignment, Rect}, widgets::{ - Block, Cell, Row, Table, TableState, Scrollbar, Padding, - ScrollbarOrientation, ScrollbarState, - }, - Frame + Block, Cell, Padding, Row, Scrollbar, ScrollbarOrientation, ScrollbarState, Table, + TableState, + }, + Frame, }; -use super::{PartialComponent, Component, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::types::PeerInformation; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, -}; +use crate::{action::Action, config::Config, palette::StylePalette}; pub struct Peers { is_active: bool, @@ -69,7 +65,7 @@ impl Peers { } else { i + 1 } - }, + } None => 0, }; self.table_state.select(Some(i)); @@ -92,8 +88,8 @@ impl Peers { } else { i - 1 } - }, - None => 0 + } + None => 0, }; self.table_state.select(Some(i)); self.scroll_state = self.scroll_state.position(i); @@ -116,14 +112,22 @@ impl PartialComponent for Peers { impl Component for Peers { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Validator) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } Ok(()) } @@ -139,11 +143,11 @@ impl Component for Peers { fn handle_key_event(&mut self, key: KeyEvent) -> Result> { if self.is_active { match key.code { - KeyCode::Up | KeyCode::Char('k') => self.previous_row(), - KeyCode::Down | KeyCode::Char('j') => self.next_row(), + KeyCode::Up | KeyCode::Char('k') => self.previous_row(), + KeyCode::Down | KeyCode::Char('j') => self.next_row(), KeyCode::Char('g') => self.first_row(), KeyCode::Char('G') => self.last_row(), - _ => {}, + _ => {} }; } Ok(None) @@ -153,16 +157,16 @@ impl Component for Peers { let [_, _, place, _] = super::validator_layout(area); let (border_style, border_type) = self.palette.create_border_style(self.is_active); let table = Table::new( - self.peers - .iter() - .map(|info| { - Row::new(vec![ - Cell::from(Text::from(info.peer_id.clone()).alignment(Alignment::Left)), - Cell::from(Text::from(info.roles.clone()).alignment(Alignment::Center)), - Cell::from(Text::from(info.best_hash.to_string()).alignment(Alignment::Center)), - Cell::from(Text::from(info.best_number.to_string()).alignment(Alignment::Right)), - ]) - }), + self.peers.iter().map(|info| { + Row::new(vec![ + Cell::from(Text::from(info.peer_id.clone()).alignment(Alignment::Left)), + Cell::from(Text::from(info.roles.clone()).alignment(Alignment::Center)), + Cell::from(Text::from(info.best_hash.to_string()).alignment(Alignment::Center)), + Cell::from( + Text::from(info.best_number.to_string()).alignment(Alignment::Right), + ), + ]) + }), [ Constraint::Fill(1), Constraint::Length(11), @@ -172,13 +176,15 @@ impl Component for Peers { ) .highlight_style(self.palette.create_highlight_style()) .column_spacing(1) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .padding(Padding::right(2)) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("My Peers")); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .padding(Padding::right(2)) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("My Peers"), + ); let scrollbar = Scrollbar::default() .orientation(ScrollbarOrientation::VerticalRight) @@ -189,7 +195,10 @@ impl Component for Peers { frame.render_stateful_widget(table, place, &mut self.table_state); frame.render_stateful_widget( scrollbar, - place.inner(Margin { vertical: 1, horizontal: 1 }), + place.inner(Margin { + vertical: 1, + horizontal: 1, + }), &mut self.scroll_state, ); diff --git a/src/components/validator/rebond_popup.rs b/src/components/validator/rebond_popup.rs index cdf740f..b0bf47f 100644 --- a/src/components/validator/rebond_popup.rs +++ b/src/components/validator/rebond_popup.rs @@ -1,19 +1,19 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Position, Alignment, Constraint, Flex, Layout, Rect}, - widgets::{Block, Clear, Paragraph}, - Frame + layout::{Alignment, Constraint, Flex, Layout, Position, Rect}, + widgets::{Block, Clear, Paragraph}, + Frame, }; -use tokio::sync::mpsc::UnboundedSender; use std::sync::mpsc::Sender; +use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ - action::Action, - config::Config, - palette::StylePalette, - types::{ActionLevel, ActionTarget}, + action::Action, + config::Config, + palette::StylePalette, + types::{ActionLevel, ActionTarget}, widgets::{Input, InputRequest}, }; @@ -24,7 +24,7 @@ pub struct RebondPopup { network_tx: Option>, secret_seed: [u8; 32], amount: Input, - palette: StylePalette + palette: StylePalette, } impl Default for RebondPopup { @@ -54,13 +54,12 @@ impl RebondPopup { fn log_event(&mut self, message: String, level: ActionLevel) { if let Some(action_tx) = &self.action_tx { - let _ = action_tx.send( - Action::EventLog(message, level, ActionTarget::ValidatorLog)); + let _ = action_tx.send(Action::EventLog(message, level, ActionTarget::ValidatorLog)); } } fn submit_message(&mut self) { - if let Some(network_tx) = &self.network_tx { + if let Some(network_tx) = &self.network_tx { let str_amount = self.amount.value(); let str_amount = if str_amount.starts_with('.') { &format!("0{}", str_amount)[..] @@ -74,9 +73,10 @@ impl RebondPopup { if let Some(action_tx) = &self.action_tx { let _ = action_tx.send(Action::ClosePopup); } - }, - Err(err) => self.log_event( - format!("invalid amount, error: {err}"), ActionLevel::Error), + } + Err(err) => { + self.log_event(format!("invalid amount, error: {err}"), ActionLevel::Error) + } } } } @@ -126,11 +126,16 @@ impl Component for RebondPopup { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -143,7 +148,7 @@ impl Component for RebondPopup { KeyCode::Left => self.move_cursor_left(), KeyCode::Right => self.move_cursor_right(), KeyCode::Esc => self.close_popup(), - _ => {}, + _ => {} }; } Ok(None) @@ -160,13 +165,14 @@ impl Component for RebondPopup { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { if self.is_active { let (border_style, border_type) = self.palette.create_popup_style(); - let input = Paragraph::new(self.amount.value()) - .block(Block::bordered() + let input = Paragraph::new(self.amount.value()).block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title(format!("Amount to rebond"))); + .title(format!("Amount to rebond")), + ); let v = Layout::vertical([Constraint::Max(3)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(50)]).flex(Flex::Center); let [area] = v.areas(area); @@ -175,8 +181,8 @@ impl Component for RebondPopup { frame.render_widget(Clear, area); frame.render_widget(input, area); frame.set_cursor_position(Position::new( - area.x + self.amount.cursor() as u16 + 1, - area.y + 1 + area.x + self.amount.cursor() as u16 + 1, + area.y + 1, )); } Ok(()) diff --git a/src/components/validator/reward_details.rs b/src/components/validator/reward_details.rs index dd96f31..cc32498 100644 --- a/src/components/validator/reward_details.rs +++ b/src/components/validator/reward_details.rs @@ -1,20 +1,16 @@ use color_eyre::Result; use ratatui::layout::Constraint; use ratatui::{ + layout::{Alignment, Rect}, text::Text, - layout::{Alignment, Rect}, - widgets::{Block, Cell, Row, Table}, - Frame + widgets::{Block, Cell, Row, Table}, + Frame, }; -use super::{PartialComponent, Component, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::types::EraRewardPoints; use crate::widgets::DotSpinner; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, -}; +use crate::{action::Action, config::Config, palette::StylePalette}; pub struct RewardDetails { palette: StylePalette, @@ -24,7 +20,7 @@ pub struct RewardDetails { treasury_apy: String, inflation: String, stash: [u8; 32], - in_staking_validators: bool, + in_staking_validators: bool, in_queued_keys: bool, in_next_keys: bool, is_disabled: bool, @@ -47,7 +43,7 @@ impl RewardDetails { treasury_apy: String::from("0.0%"), inflation: String::from("0.0%"), stash: [0u8; 32], - in_staking_validators: false, + in_staking_validators: false, in_queued_keys: false, in_next_keys: false, is_disabled: false, @@ -58,9 +54,12 @@ impl RewardDetails { fn comission_to_string(&self) -> String { match self.commission { Some(commission) => { - if self.nominators_blocked { "blocked".to_string() } - else { format!("{:.2}%", commission as f64 / 10_000_000.0) } - }, + if self.nominators_blocked { + "blocked".to_string() + } else { + format!("{:.2}%", commission as f64 / 10_000_000.0) + } + } None => DotSpinner::default().to_string(), } } @@ -77,20 +76,28 @@ impl RewardDetails { } impl PartialComponent for RewardDetails { - fn set_active(&mut self, _current_tab: CurrentTab) { } + fn set_active(&mut self, _current_tab: CurrentTab) {} } impl Component for RewardDetails { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Validator) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } Ok(()) } @@ -98,8 +105,12 @@ impl Component for RewardDetails { fn update(&mut self, action: Action) -> Result> { match action { Action::SetStashAccount(stash) => self.stash = stash, - Action::SetCurrentValidatorEraRewards(_, _, individual) => self.update_individual(&individual), - Action::SetValidatorPrefs(commission, disabled, account_id) if self.stash == account_id => { + Action::SetCurrentValidatorEraRewards(_, _, individual) => { + self.update_individual(&individual) + } + Action::SetValidatorPrefs(commission, disabled, account_id) + if self.stash == account_id => + { self.commission = commission; self.in_staking_validators = commission.is_some(); self.nominators_blocked = disabled; @@ -110,7 +121,7 @@ impl Component for RewardDetails { } else { self.in_next_keys = !session_key_info.key.is_empty(); } - }, + } Action::Apy(apy) => self.apy = apy, Action::TreasuryApy(apy) => self.treasury_apy = apy, Action::Inflation(inflation) => self.inflation = inflation, @@ -130,8 +141,8 @@ impl Component for RewardDetails { match (self.in_staking_validators, is_fully_in_session) { (true, true) => "Active", (true, false) => "Rotating", - (false, true) if self.in_rewards => { "Stopping" } - (false, true) if !self.in_rewards => { "Chill" } + (false, true) if self.in_rewards => "Stopping", + (false, true) if !self.in_rewards => "Chill", _ => "Nothing", } }; @@ -141,34 +152,33 @@ impl Component for RewardDetails { vec![ Row::new(vec![ Cell::from(Text::from("Nominators".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.comission_to_string()).alignment(Alignment::Right)), + Cell::from(Text::from(self.comission_to_string()).alignment(Alignment::Right)), ]), Row::new(vec![ Cell::from(Text::from("Validator APY".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.apy.clone()).alignment(Alignment::Right)), + Cell::from(Text::from(self.apy.clone()).alignment(Alignment::Right)), ]), Row::new(vec![ Cell::from(Text::from("Treasury APY".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.treasury_apy.clone()).alignment(Alignment::Right)), + Cell::from(Text::from(self.treasury_apy.clone()).alignment(Alignment::Right)), ]), Row::new(vec![ Cell::from(Text::from("Inflation".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.inflation.clone()).alignment(Alignment::Right)), + Cell::from(Text::from(self.inflation.clone()).alignment(Alignment::Right)), ]), ], - [ - Constraint::Min(13), - Constraint::Min(0), - ], + [Constraint::Min(13), Constraint::Min(0)], ) .highlight_style(self.palette.create_highlight_style()) .column_spacing(1) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title(staking_status)); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title(staking_status), + ); frame.render_widget(table, place); diff --git a/src/components/validator/rotate_popup.rs b/src/components/validator/rotate_popup.rs index f6e4873..c9a4cd6 100644 --- a/src/components/validator/rotate_popup.rs +++ b/src/components/validator/rotate_popup.rs @@ -1,20 +1,16 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Alignment, Constraint, Flex, Layout, Rect}, - text::Text, - widgets::{Block, Cell, Clear, Row, Table}, + layout::{Alignment, Constraint, Flex, Layout, Rect}, + text::Text, + widgets::{Block, Cell, Clear, Row, Table}, Frame, }; -use tokio::sync::mpsc::UnboundedSender; use std::sync::mpsc::Sender; +use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, -}; +use super::{Component, CurrentTab, PartialComponent}; +use crate::{action::Action, config::Config, palette::StylePalette}; #[derive(Debug)] pub struct RotatePopup { @@ -23,7 +19,7 @@ pub struct RotatePopup { network_tx: Option>, cached_keys: String, secret_seed: [u8; 32], - palette: StylePalette + palette: StylePalette, } impl Default for RotatePopup { @@ -55,7 +51,9 @@ impl RotatePopup { if !self.cached_keys.is_empty() && self.cached_keys.len() == 258 { if let Some(network_tx) = &self.network_tx { let _ = network_tx.send(Action::SetSessionKeys( - self.secret_seed, self.cached_keys.clone())); + self.secret_seed, + self.cached_keys.clone(), + )); } if let Some(action_tx) = &self.action_tx { let _ = action_tx.send(Action::ClosePopup); @@ -108,11 +106,16 @@ impl Component for RotatePopup { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -130,8 +133,8 @@ impl Component for RotatePopup { if self.is_active && key.kind == KeyEventKind::Press { match key.code { KeyCode::Enter => self.rotate_keys(), - KeyCode::Esc => self.close_popup(), - _ => {}, + KeyCode::Esc => self.close_popup(), + _ => {} }; } Ok(None) @@ -146,34 +149,33 @@ impl Component for RotatePopup { vec![ Row::new(vec![ Cell::from(Text::from("gran".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(gran_key).alignment(Alignment::Right)), + Cell::from(Text::from(gran_key).alignment(Alignment::Right)), ]), Row::new(vec![ Cell::from(Text::from("babe".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(babe_key).alignment(Alignment::Right)), + Cell::from(Text::from(babe_key).alignment(Alignment::Right)), ]), Row::new(vec![ Cell::from(Text::from("audi".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(audi_key).alignment(Alignment::Right)), + Cell::from(Text::from(audi_key).alignment(Alignment::Right)), ]), Row::new(vec![ Cell::from(Text::from("slow".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(slow_key).alignment(Alignment::Right)), + Cell::from(Text::from(slow_key).alignment(Alignment::Right)), ]), - ], - [ - Constraint::Length(4), - Constraint::Min(0), ], + [Constraint::Length(4), Constraint::Min(0)], ) .highlight_style(self.palette.create_highlight_style()) .column_spacing(1) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("Rotate session keys (Enter to proceed / Esc to close)")); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("Rotate session keys (Enter to proceed / Esc to close)"), + ); let v = Layout::vertical([Constraint::Max(6)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(73)]).flex(Flex::Center); diff --git a/src/components/validator/staking_details.rs b/src/components/validator/staking_details.rs index 0dec02d..6dbc412 100644 --- a/src/components/validator/staking_details.rs +++ b/src/components/validator/staking_details.rs @@ -1,20 +1,16 @@ use color_eyre::Result; use ratatui::layout::Constraint; use ratatui::{ + layout::{Alignment, Rect}, text::Text, - layout::{Alignment, Rect}, - widgets::{Block, Cell, Row, Table}, - Frame + widgets::{Block, Cell, Row, Table}, + Frame, }; -use subxt::ext::sp_core::crypto::{Ss58Codec, Ss58AddressFormat, AccountId32}; +use subxt::ext::sp_core::crypto::{AccountId32, Ss58AddressFormat, Ss58Codec}; -use super::{PartialComponent, Component, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::types::RewardDestination; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, -}; +use crate::{action::Action, config::Config, palette::StylePalette}; pub struct StakingDetails { palette: StylePalette, @@ -63,27 +59,34 @@ impl StakingDetails { .to_ss58check_with_version(Ss58AddressFormat::custom(1996)); let tail = address.len().saturating_sub(5); format!("{}..{}", &address[..5], &address[tail..]) - }, + } } } - } impl PartialComponent for StakingDetails { - fn set_active(&mut self, _current_tab: CurrentTab) { } + fn set_active(&mut self, _current_tab: CurrentTab) {} } impl Component for StakingDetails { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Validator) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } Ok(()) } @@ -92,8 +95,9 @@ impl Component for StakingDetails { match action { Action::SetStashAccount(account_id) => self.stash = account_id, Action::NextReward(next_reward) => self.next_reward = next_reward, - Action::SetStakingPayee(destination, account_id) if self.stash == account_id => - self.reward_destination = destination, + Action::SetStakingPayee(destination, account_id) if self.stash == account_id => { + self.reward_destination = destination + } Action::SetStakedRatio(total, own, account_id) if self.stash == account_id => { self.staked_total = total; self.staked_own = own; @@ -107,39 +111,50 @@ impl Component for StakingDetails { let [_, place, _] = super::validator_balance_layout(area); let (border_style, border_type) = self.palette.create_border_style(false); - let title = format!("Staking details: {}", self.get_reward_destination()); + let title = format!("Staking details: {}", self.get_reward_destination()); let table = Table::new( vec![ Row::new(vec![ Cell::from(Text::from("Stake value".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.staked_total)).alignment(Alignment::Right)), + Cell::from( + Text::from(self.prepare_u128(self.staked_total)) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("Own stake".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.staked_own)).alignment(Alignment::Right)), + Cell::from( + Text::from(self.prepare_u128(self.staked_own)).alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("Other stake".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.staked_total.saturating_sub(self.staked_own))).alignment(Alignment::Right)), + Cell::from( + Text::from( + self.prepare_u128(self.staked_total.saturating_sub(self.staked_own)), + ) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("Next reward".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.next_reward)).alignment(Alignment::Right)), + Cell::from( + Text::from(self.prepare_u128(self.next_reward)).alignment(Alignment::Right), + ), ]), ], - [ - Constraint::Min(11), - Constraint::Min(0), - ], + [Constraint::Min(11), Constraint::Min(0)], ) .highlight_style(self.palette.create_highlight_style()) .column_spacing(1) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title(title)); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title(title), + ); frame.render_widget(table, place); diff --git a/src/components/validator/stash_details.rs b/src/components/validator/stash_details.rs index 92aee81..35aa7ce 100644 --- a/src/components/validator/stash_details.rs +++ b/src/components/validator/stash_details.rs @@ -1,20 +1,16 @@ use color_eyre::Result; use ratatui::layout::Constraint; use ratatui::{ + layout::{Alignment, Rect}, text::Text, - layout::{Alignment, Rect}, - widgets::{Block, Cell, Row, Table}, - Frame + widgets::{Block, Cell, Row, Table}, + Frame, }; use std::sync::mpsc::Sender; -use super::{PartialComponent, Component, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::widgets::DotSpinner; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, -}; +use crate::{action::Action, config::Config, palette::StylePalette}; pub struct StashDetails { palette: StylePalette, @@ -56,8 +52,8 @@ impl StashDetails { let value = value as f64 / 10f64.powi(18); let after = Self::DECIMALS; format!("{:.after$}{}", value, Self::TICKER) - }, - None => format!("{}{}", DotSpinner::default().to_string(), Self::TICKER) + } + None => format!("{}{}", DotSpinner::default().to_string(), Self::TICKER), } } @@ -71,7 +67,7 @@ impl StashDetails { } impl PartialComponent for StashDetails { - fn set_active(&mut self, _current_tab: CurrentTab) { } + fn set_active(&mut self, _current_tab: CurrentTab) {} } impl Component for StashDetails { @@ -82,14 +78,22 @@ impl Component for StashDetails { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Validator) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } Ok(()) } @@ -98,22 +102,31 @@ impl Component for StashDetails { match action { Action::SetStashSecret(secret) => self.stash_secret = secret, Action::SetStashAccount(account_id) => self.stash_account_id = account_id, - Action::SetIsBonded(is_bonded, account_id) if self.stash_account_id == account_id => - self.is_bonded = is_bonded, - Action::SetStakedAmountRatio(total, active, account_id) if self.stash_account_id == account_id => { + Action::SetIsBonded(is_bonded, account_id) if self.stash_account_id == account_id => { + self.is_bonded = is_bonded + } + Action::SetStakedAmountRatio(total, active, account_id) + if self.stash_account_id == account_id => + { self.staked_total = total; self.staked_active = active; - }, - Action::BalanceResponse(account_id, maybe_balance) if account_id == self.stash_account_id => { + } + Action::BalanceResponse(account_id, maybe_balance) + if account_id == self.stash_account_id => + { if let Some(network_tx) = &self.network_tx { let _ = network_tx.send(Action::SetSender( - hex::encode(self.stash_secret), - maybe_balance.clone().map(|b| b.nonce))); + hex::encode(self.stash_secret), + maybe_balance.clone().map(|b| b.nonce), + )); } - self.free_balance = maybe_balance.map(|balance| balance.free - .saturating_sub(balance.frozen) - .saturating_sub(balance.reserved)); - }, + self.free_balance = maybe_balance.map(|balance| { + balance + .free + .saturating_sub(balance.frozen) + .saturating_sub(balance.reserved) + }); + } _ => {} }; Ok(None) @@ -127,34 +140,42 @@ impl Component for StashDetails { vec![ Row::new(vec![ Cell::from(Text::from("Bond ready".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.is_bonded_to_string()).alignment(Alignment::Right)), + Cell::from(Text::from(self.is_bonded_to_string()).alignment(Alignment::Right)), ]), Row::new(vec![ Cell::from(Text::from("Free balance".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.free_balance)).alignment(Alignment::Right)), + Cell::from( + Text::from(self.prepare_u128(self.free_balance)) + .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.staked_total)).alignment(Alignment::Right)), + Cell::from( + Text::from(self.prepare_u128(self.staked_total)) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("Active staked".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.staked_active)).alignment(Alignment::Right)), + Cell::from( + Text::from(self.prepare_u128(self.staked_active)) + .alignment(Alignment::Right), + ), ]), ], - [ - Constraint::Min(14), - Constraint::Min(0), - ], + [Constraint::Min(14), Constraint::Min(0)], ) .highlight_style(self.palette.create_highlight_style()) .column_spacing(1) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("Stash details")); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("Stash details"), + ); frame.render_widget(table, place); diff --git a/src/components/validator/stash_info.rs b/src/components/validator/stash_info.rs index 85ec760..f9e81d7 100644 --- a/src/components/validator/stash_info.rs +++ b/src/components/validator/stash_info.rs @@ -1,37 +1,32 @@ -use std::path::PathBuf; use std::fs::File; -use std::io::{Write, BufRead, BufReader}; +use std::io::{BufRead, BufReader, Write}; +use std::path::PathBuf; use color_eyre::Result; use ratatui::layout::Constraint; use ratatui::style::{Modifier, Stylize}; use ratatui::{ + layout::{Alignment, Rect}, text::Text, - layout::{Alignment, Rect}, - widgets::{Block, Cell, Row, Table}, - Frame + widgets::{Block, Cell, Row, Table}, + Frame, }; +use std::sync::mpsc::Sender; use subxt::{ - tx::PairSigner, ext::sp_core::{ - Pair as PairT, + crypto::{AccountId32, Ss58AddressFormat, Ss58Codec}, sr25519::Pair, - crypto::{Ss58Codec, Ss58AddressFormat, AccountId32}, + Pair as PairT, }, + tx::PairSigner, }; use tokio::sync::mpsc::UnboundedSender; -use std::sync::mpsc::Sender; -use super::{PartialComponent, Component, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::casper::CasperConfig; use crate::types::{ActionLevel, ActionTarget}; -use crate::{ - types::SessionKeyInfo, - action::Action, - config::Config, - palette::StylePalette, -}; +use crate::{action::Action, config::Config, palette::StylePalette, types::SessionKeyInfo}; pub struct StashInfo { is_active: bool, @@ -68,8 +63,7 @@ impl StashInfo { fn log_event(&mut self, message: String, level: ActionLevel) { if let Some(action_tx) = &self.action_tx { - let _ = action_tx.send( - Action::EventLog(message, level, ActionTarget::ValidatorLog)); + let _ = action_tx.send(Action::EventLog(message, level, ActionTarget::ValidatorLog)); } } @@ -95,8 +89,9 @@ impl StashInfo { self.initiate_stash_info(account_id, seed); self.log_event( - format!("stash key {address} read from disk"), - ActionLevel::Info); + format!("stash key {address} read from disk"), + ActionLevel::Info, + ); self.stash_address = address; self.stash_pair = Some(pair_signer); @@ -104,16 +99,24 @@ impl StashInfo { Ok(()) } else { self.log_event( - format!("file at '{:?}' is empty, trying to create new key", &self.stash_filepath), - ActionLevel::Warn); + format!( + "file at '{:?}' is empty, trying to create new key", + &self.stash_filepath + ), + ActionLevel::Warn, + ); self.generate_and_save_new_key() } - }, + } Err(_) => { self.log_event( - format!("file at '{:?}' not found, trying to create new key", &self.stash_filepath), - ActionLevel::Warn); + format!( + "file at '{:?}' not found, trying to create new key", + &self.stash_filepath + ), + ActionLevel::Warn, + ); self.generate_and_save_new_key() } @@ -133,8 +136,12 @@ impl StashInfo { self.initiate_stash_info(account_id, seed); self.log_event( - format!("new stash key {} created and stored at {:?}", &address, self.stash_filepath), - ActionLevel::Info); + format!( + "new stash key {} created and stored at {:?}", + &address, self.stash_filepath + ), + ActionLevel::Info, + ); self.stash_address = address; self.stash_pair = Some(pair_signer); @@ -179,7 +186,7 @@ impl StashInfo { } impl PartialComponent for StashInfo { - fn set_active(&mut self, _current_tab: CurrentTab) { } + fn set_active(&mut self, _current_tab: CurrentTab) {} } impl Component for StashInfo { @@ -195,14 +202,22 @@ impl Component for StashInfo { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Wallet) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } self.read_or_create_stash()?; Ok(()) @@ -220,37 +235,38 @@ impl Component for StashInfo { let [place, _, _] = super::validator_session_and_listen_layout(area); let (border_style, border_type) = self.palette.create_border_style(self.is_active); let table = Table::new( - self.key_names - .iter() - .map(|name| { - let address_text = match self.session_keys.get(*name) { - Some(key_info) => { - let mut address_text = Text::from(key_info.key.clone()).alignment(Alignment::Center); - if !key_info.is_stored { - address_text = address_text.add_modifier(Modifier::CROSSED_OUT); - } - address_text - }, - None => Text::from("-").alignment(Alignment::Center), - }; - let queued_name = format!("q_{}", name); - let queued_address_text = match self.session_keys.get(&queued_name) { - Some(key_info) => { - let mut queued_address_text = Text::from(key_info.key.clone()).alignment(Alignment::Right); - if !key_info.is_stored { - queued_address_text = queued_address_text.add_modifier(Modifier::CROSSED_OUT); - } - queued_address_text - }, - None => Text::from("-").alignment(Alignment::Right), - }; - Row::new(vec![ - Cell::from(Text::from(name.to_string()).alignment(Alignment::Left)), - Cell::from(address_text), - Cell::from(Text::from("-->".to_string()).alignment(Alignment::Center)), - Cell::from(queued_address_text), - ]) - }), + self.key_names.iter().map(|name| { + let address_text = match self.session_keys.get(*name) { + Some(key_info) => { + let mut address_text = + Text::from(key_info.key.clone()).alignment(Alignment::Center); + if !key_info.is_stored { + address_text = address_text.add_modifier(Modifier::CROSSED_OUT); + } + address_text + } + None => Text::from("-").alignment(Alignment::Center), + }; + let queued_name = format!("q_{}", name); + let queued_address_text = match self.session_keys.get(&queued_name) { + Some(key_info) => { + let mut queued_address_text = + Text::from(key_info.key.clone()).alignment(Alignment::Right); + if !key_info.is_stored { + queued_address_text = + queued_address_text.add_modifier(Modifier::CROSSED_OUT); + } + queued_address_text + } + None => Text::from("-").alignment(Alignment::Right), + }; + Row::new(vec![ + Cell::from(Text::from(name.to_string()).alignment(Alignment::Left)), + Cell::from(address_text), + Cell::from(Text::from("-->".to_string()).alignment(Alignment::Center)), + Cell::from(queued_address_text), + ]) + }), [ Constraint::Length(4), Constraint::Min(0), @@ -260,12 +276,14 @@ impl Component for StashInfo { ) .highlight_style(self.palette.create_highlight_style()) .column_spacing(1) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title(self.stash_address.clone())); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title(self.stash_address.clone()), + ); frame.render_widget(table, place); Ok(()) diff --git a/src/components/validator/unbond_popup.rs b/src/components/validator/unbond_popup.rs index dca4840..9bb84b3 100644 --- a/src/components/validator/unbond_popup.rs +++ b/src/components/validator/unbond_popup.rs @@ -1,19 +1,19 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Position, Alignment, Constraint, Flex, Layout, Rect}, - widgets::{Block, Clear, Paragraph}, - Frame + layout::{Alignment, Constraint, Flex, Layout, Position, Rect}, + widgets::{Block, Clear, Paragraph}, + Frame, }; -use tokio::sync::mpsc::UnboundedSender; use std::sync::mpsc::Sender; +use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ - action::Action, - config::Config, - palette::StylePalette, - types::{ActionLevel, ActionTarget}, + action::Action, + config::Config, + palette::StylePalette, + types::{ActionLevel, ActionTarget}, widgets::{Input, InputRequest}, }; @@ -26,7 +26,7 @@ pub struct UnbondPopup { stash_account_id: [u8; 32], is_bonded: bool, amount: Input, - palette: StylePalette + palette: StylePalette, } impl Default for UnbondPopup { @@ -58,13 +58,12 @@ impl UnbondPopup { fn log_event(&mut self, message: String, level: ActionLevel) { if let Some(action_tx) = &self.action_tx { - let _ = action_tx.send( - Action::EventLog(message, level, ActionTarget::ValidatorLog)); + let _ = action_tx.send(Action::EventLog(message, level, ActionTarget::ValidatorLog)); } } fn submit_message(&mut self) { - if let Some(network_tx) = &self.network_tx { + if let Some(network_tx) = &self.network_tx { let str_amount = self.amount.value(); let str_amount = if str_amount.starts_with('.') { &format!("0{}", str_amount)[..] @@ -75,19 +74,20 @@ impl UnbondPopup { Ok(value) => { if self.is_bonded { let amount = (value * 1_000_000_000_000_000_000.0) as u128; - let _ = network_tx.send(Action::UnbondFrom( - self.stash_secret_seed, amount)); + let _ = network_tx.send(Action::UnbondFrom(self.stash_secret_seed, amount)); } else { self.log_event( - format!("current stash doesn't have bond yet"), - ActionLevel::Warn); + format!("current stash doesn't have bond yet"), + ActionLevel::Warn, + ); } if let Some(action_tx) = &self.action_tx { let _ = action_tx.send(Action::ClosePopup); } - }, - Err(err) => self.log_event( - format!("invalid amount, error: {err}"), ActionLevel::Error), + } + Err(err) => { + self.log_event(format!("invalid amount, error: {err}"), ActionLevel::Error) + } } } } @@ -137,11 +137,16 @@ impl Component for UnbondPopup { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -153,8 +158,8 @@ impl Component for UnbondPopup { KeyCode::Backspace => self.delete_char(), KeyCode::Left => self.move_cursor_left(), KeyCode::Right => self.move_cursor_right(), - KeyCode::Esc => self.close_popup(), - _ => {}, + KeyCode::Esc => self.close_popup(), + _ => {} }; } Ok(None) @@ -162,8 +167,9 @@ impl Component for UnbondPopup { fn update(&mut self, action: Action) -> Result> { match action { - Action::SetIsBonded(is_bonded, account_id) if self.stash_account_id == account_id => - self.is_bonded = is_bonded, + Action::SetIsBonded(is_bonded, account_id) if self.stash_account_id == account_id => { + self.is_bonded = is_bonded + } Action::SetStashSecret(secret_seed) => self.stash_secret_seed = secret_seed, Action::SetStashAccount(account_id) => self.stash_account_id = account_id, _ => {} @@ -174,13 +180,14 @@ impl Component for UnbondPopup { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { if self.is_active { let (border_style, border_type) = self.palette.create_popup_style(); - let input = Paragraph::new(self.amount.value()) - .block(Block::bordered() + let input = Paragraph::new(self.amount.value()).block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title(format!("Unbond amount"))); + .title(format!("Unbond amount")), + ); let v = Layout::vertical([Constraint::Max(3)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(50)]).flex(Flex::Center); let [area] = v.areas(area); @@ -189,8 +196,8 @@ impl Component for UnbondPopup { frame.render_widget(Clear, area); frame.render_widget(input, area); frame.set_cursor_position(Position::new( - area.x + self.amount.cursor() as u16 + 1, - area.y + 1 + area.x + self.amount.cursor() as u16 + 1, + area.y + 1, )); } Ok(()) diff --git a/src/components/validator/validate_popup.rs b/src/components/validator/validate_popup.rs index a8e4e1f..05bb1c2 100644 --- a/src/components/validator/validate_popup.rs +++ b/src/components/validator/validate_popup.rs @@ -1,19 +1,19 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Position, Alignment, Constraint, Flex, Layout, Rect}, - widgets::{Block, Clear, Paragraph}, - Frame + layout::{Alignment, Constraint, Flex, Layout, Position, Rect}, + widgets::{Block, Clear, Paragraph}, + Frame, }; -use tokio::sync::mpsc::UnboundedSender; use std::sync::mpsc::Sender; +use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ - action::Action, - config::Config, - palette::StylePalette, - types::{ActionLevel, ActionTarget}, + action::Action, + config::Config, + palette::StylePalette, + types::{ActionLevel, ActionTarget}, widgets::{Input, InputRequest}, }; @@ -24,7 +24,7 @@ pub struct ValidatePopup { network_tx: Option>, secret_seed: [u8; 32], amount: Input, - palette: StylePalette + palette: StylePalette, } impl Default for ValidatePopup { @@ -54,13 +54,12 @@ impl ValidatePopup { fn log_event(&mut self, message: String, level: ActionLevel) { if let Some(action_tx) = &self.action_tx { - let _ = action_tx.send( - Action::EventLog(message, level, ActionTarget::ValidatorLog)); + let _ = action_tx.send(Action::EventLog(message, level, ActionTarget::ValidatorLog)); } } fn submit_message(&mut self) { - if let Some(network_tx) = &self.network_tx { + if let Some(network_tx) = &self.network_tx { let str_amount = self.amount.value(); let str_amount = if str_amount.starts_with('.') { &format!("0{}", str_amount)[..] @@ -74,9 +73,10 @@ impl ValidatePopup { if let Some(action_tx) = &self.action_tx { let _ = action_tx.send(Action::ClosePopup); } - }, - Err(err) => self.log_event( - format!("invalid amount, error: {err}"), ActionLevel::Error), + } + Err(err) => { + self.log_event(format!("invalid amount, error: {err}"), ActionLevel::Error) + } } } } @@ -126,11 +126,16 @@ impl Component for ValidatePopup { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -142,8 +147,8 @@ impl Component for ValidatePopup { KeyCode::Backspace => self.delete_char(), KeyCode::Left => self.move_cursor_left(), KeyCode::Right => self.move_cursor_right(), - KeyCode::Esc => self.close_popup(), - _ => {}, + KeyCode::Esc => self.close_popup(), + _ => {} }; } Ok(None) @@ -160,13 +165,14 @@ impl Component for ValidatePopup { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { if self.is_active { let (border_style, border_type) = self.palette.create_popup_style(); - let input = Paragraph::new(self.amount.value()) - .block(Block::bordered() + let input = Paragraph::new(self.amount.value()).block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title(format!("Commission for nominators"))); + .title(format!("Commission for nominators")), + ); let v = Layout::vertical([Constraint::Max(3)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(50)]).flex(Flex::Center); let [area] = v.areas(area); @@ -175,8 +181,8 @@ impl Component for ValidatePopup { frame.render_widget(Clear, area); frame.render_widget(input, area); frame.set_cursor_position(Position::new( - area.x + self.amount.cursor() as u16 + 1, - area.y + 1 + area.x + self.amount.cursor() as u16 + 1, + area.y + 1, )); } Ok(()) diff --git a/src/components/validator/withdraw_popup.rs b/src/components/validator/withdraw_popup.rs index ce81003..9ae9ecb 100644 --- a/src/components/validator/withdraw_popup.rs +++ b/src/components/validator/withdraw_popup.rs @@ -1,19 +1,19 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Alignment, Constraint, Flex, Layout, Rect}, - widgets::{Block, Clear, Paragraph}, - Frame + layout::{Alignment, Constraint, Flex, Layout, Rect}, + widgets::{Block, Clear, Paragraph}, + Frame, }; -use tokio::sync::mpsc::UnboundedSender; use std::sync::mpsc::Sender; +use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ - action::Action, - config::Config, - palette::StylePalette, - types::{ActionLevel, ActionTarget}, + action::Action, + config::Config, + palette::StylePalette, + types::{ActionLevel, ActionTarget}, }; #[derive(Debug)] @@ -27,7 +27,7 @@ pub struct WithdrawPopup { unlocking_is_empty: bool, existential_deposit: u128, active_balance: u128, - palette: StylePalette + palette: StylePalette, } impl Default for WithdrawPopup { @@ -64,13 +64,14 @@ impl WithdrawPopup { } fn proceed(&mut self) { - if let Some(network_tx) = &self.network_tx { + if let Some(network_tx) = &self.network_tx { let spans_needed = if self.stash_should_be_killed() { if let Some(action_tx) = &self.action_tx { let _ = action_tx.send(Action::EventLog( - "Current stash account will be killed during this transaction".to_string(), - ActionLevel::Warn, - ActionTarget::ValidatorLog)); + "Current stash account will be killed during this transaction".to_string(), + ActionLevel::Warn, + ActionTarget::ValidatorLog, + )); } self.slashing_spans_length } else { @@ -106,11 +107,16 @@ impl Component for WithdrawPopup { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -119,8 +125,8 @@ impl Component for WithdrawPopup { if self.is_active && key.kind == KeyEventKind::Press { match key.code { KeyCode::Enter => self.proceed(), - KeyCode::Esc => self.close_popup(), - _ => {}, + KeyCode::Esc => self.close_popup(), + _ => {} }; } Ok(None) @@ -128,15 +134,26 @@ impl Component for WithdrawPopup { fn update(&mut self, action: Action) -> Result> { match action { - Action::SetExistentialDeposit(existential_deposit) => self.existential_deposit = existential_deposit, + Action::SetExistentialDeposit(existential_deposit) => { + self.existential_deposit = existential_deposit + } Action::SetStashAccount(account_id) => self.stash_account = account_id, Action::SetStashSecret(secret_seed) => self.secret_seed = secret_seed, - 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.unwrap_or_default(), - Action::SetValidatorEraUnlocking(unlockings, account_id) if self.stash_account == account_id => - self.unlocking_is_empty = unlockings.is_empty(), + 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.unwrap_or_default() + } + Action::SetValidatorEraUnlocking(unlockings, account_id) + if self.stash_account == account_id => + { + self.unlocking_is_empty = unlockings.is_empty() + } _ => {} }; Ok(None) @@ -150,13 +167,14 @@ impl Component for WithdrawPopup { } else { " Do you want to withdraw all unbonded funds?" }; - let input = Paragraph::new(text) - .block(Block::bordered() + let input = Paragraph::new(text).block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title("Enter to proceed / Esc to close")); + .title("Enter to proceed / Esc to close"), + ); let v = Layout::vertical([Constraint::Max(3)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(50)]).flex(Flex::Center); let [area] = v.areas(area); diff --git a/src/components/validator/withdrawals.rs b/src/components/validator/withdrawals.rs index 88374d2..e403038 100644 --- a/src/components/validator/withdrawals.rs +++ b/src/components/validator/withdrawals.rs @@ -3,23 +3,18 @@ use crossterm::event::{KeyCode, KeyEvent}; use ratatui::layout::{Constraint, Margin}; use ratatui::style::{Modifier, Stylize}; use ratatui::{ + layout::{Alignment, Rect}, text::Text, - layout::{Alignment, Rect}, widgets::{ - Block, Cell, Row, Table, TableState, Scrollbar, - ScrollbarOrientation, ScrollbarState, - }, - Frame + Block, Cell, Row, Scrollbar, ScrollbarOrientation, ScrollbarState, Table, TableState, + }, + Frame, }; use tokio::sync::mpsc::UnboundedSender; -use super::{PartialComponent, Component, CurrentTab}; -use crate::types::{ActionTarget, ActionLevel, UnlockChunk}; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, -}; +use super::{Component, CurrentTab, PartialComponent}; +use crate::types::{ActionLevel, ActionTarget, UnlockChunk}; +use crate::{action::Action, config::Config, palette::StylePalette}; pub struct Withdrawals { is_active: bool, @@ -27,7 +22,7 @@ pub struct Withdrawals { palette: StylePalette, scroll_state: ScrollbarState, table_state: TableState, - unlockings: Vec, + unlockings: Vec, stash_account: [u8; 32], current_era: u32, } @@ -59,12 +54,13 @@ impl Withdrawals { if let Some(action_tx) = &self.action_tx { if let Some(index) = self.table_state.selected() { if index == 0 && self.unlockings[0].era < self.current_era { - let _ = action_tx.send(Action::WithdrawValidatorPopup); + let _ = action_tx.send(Action::WithdrawValidatorPopup); } else { let _ = action_tx.send(Action::EventLog( - "Nothing to be witdrawn yet on the selected unlocking".to_string(), - ActionLevel::Info, - ActionTarget::ValidatorLog)); + "Nothing to be witdrawn yet on the selected unlocking".to_string(), + ActionLevel::Info, + ActionTarget::ValidatorLog, + )); } } } @@ -85,7 +81,7 @@ impl Withdrawals { } else { i + 1 } - }, + } None => 0, }; self.table_state.select(Some(i)); @@ -108,8 +104,8 @@ impl Withdrawals { } else { i - 1 } - }, - None => 0 + } + None => 0, }; self.table_state.select(Some(i)); self.scroll_state = self.scroll_state.position(i); @@ -128,8 +124,7 @@ impl Withdrawals { } } self.unlockings = updated_unlockings; - self.scroll_state = self.scroll_state - .content_length(self.unlockings.len()); + self.scroll_state = self.scroll_state.content_length(self.unlockings.len()); } fn prepare_u128(&self, value: u128) -> String { @@ -143,7 +138,7 @@ impl Withdrawals { format!("{} eras", era_index - self.current_era) } else { String::from("ready") - } + } } } @@ -168,14 +163,22 @@ impl Component for Withdrawals { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Validator) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } Ok(()) } @@ -184,8 +187,11 @@ impl Component for Withdrawals { match action { Action::SetStashAccount(account_id) => self.stash_account = account_id, Action::SetActiveEra(era_info) => self.current_era = era_info.index, - Action::SetValidatorEraUnlocking(unlockings, account_id) if self.stash_account == account_id => - self.add_new_unlocking(unlockings), + Action::SetValidatorEraUnlocking(unlockings, account_id) + if self.stash_account == account_id => + { + self.add_new_unlocking(unlockings) + } _ => {} }; Ok(None) @@ -194,12 +200,12 @@ impl Component for Withdrawals { fn handle_key_event(&mut self, key: KeyEvent) -> Result> { if self.is_active { match key.code { - KeyCode::Up | KeyCode::Char('k') => self.previous_row(), - KeyCode::Down | KeyCode::Char('j') => self.next_row(), + KeyCode::Up | KeyCode::Char('k') => self.previous_row(), + KeyCode::Down | KeyCode::Char('j') => self.next_row(), KeyCode::Char('g') => self.first_row(), KeyCode::Char('G') => self.last_row(), KeyCode::Enter => self.try_open_popup(), - _ => {}, + _ => {} }; } Ok(None) @@ -209,35 +215,31 @@ impl Component for Withdrawals { let [_, _, place] = super::validator_statistics_layout(area); let (border_style, border_type) = self.palette.create_border_style(self.is_active); let table = Table::new( - self.unlockings - .iter() - .map(|unlock| { - let mut est_era_text = Text::from(self.estimate_time(unlock.era)).alignment(Alignment::Center); - let mut value_text = Text::from(self.prepare_u128(unlock.value)).alignment(Alignment::Right); + self.unlockings.iter().map(|unlock| { + let mut est_era_text = + Text::from(self.estimate_time(unlock.era)).alignment(Alignment::Center); + let mut value_text = + Text::from(self.prepare_u128(unlock.value)).alignment(Alignment::Right); - if unlock.era > self.current_era { - est_era_text = est_era_text.add_modifier(Modifier::CROSSED_OUT); - value_text = value_text.add_modifier(Modifier::CROSSED_OUT); - } + if unlock.era > self.current_era { + est_era_text = est_era_text.add_modifier(Modifier::CROSSED_OUT); + value_text = value_text.add_modifier(Modifier::CROSSED_OUT); + } - Row::new(vec![ - Cell::from(est_era_text), - Cell::from(value_text), - ]) - }), - [ - Constraint::Length(7), - Constraint::Min(0), - ], + Row::new(vec![Cell::from(est_era_text), Cell::from(value_text)]) + }), + [Constraint::Length(7), Constraint::Min(0)], ) .highlight_style(self.palette.create_highlight_style()) .column_spacing(1) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("Withdrawals")); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("Withdrawals"), + ); let scrollbar = Scrollbar::default() .orientation(ScrollbarOrientation::VerticalRight) @@ -248,7 +250,10 @@ impl Component for Withdrawals { frame.render_stateful_widget(table, place, &mut self.table_state); frame.render_stateful_widget( scrollbar, - place.inner(Margin { vertical: 1, horizontal: 1 }), + place.inner(Margin { + vertical: 1, + horizontal: 1, + }), &mut self.scroll_state, ); diff --git a/src/components/version.rs b/src/components/version.rs index e652634..2741bde 100644 --- a/src/components/version.rs +++ b/src/components/version.rs @@ -8,12 +8,7 @@ use ratatui::{ use subxt::utils::H256; use super::Component; -use crate::{ - config::Config, - action::Action, - palette::StylePalette, - widgets::OghamCenter, -}; +use crate::{action::Action, config::Config, palette::StylePalette, widgets::OghamCenter}; #[derive(Debug, Clone, Default)] pub struct Version { @@ -35,8 +30,10 @@ impl Version { impl Component for Version { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Menu) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); } Ok(()) } @@ -57,14 +54,25 @@ impl Component for Version { let text_style = self.palette.create_basic_style(false); let (border_style, border_type) = self.palette.create_border_style(false); let text = vec![ - Line::styled(self.chain_name.clone().unwrap_or(OghamCenter::default().to_string()), text_style), - Line::styled(self.node_version.clone().unwrap_or(OghamCenter::default().to_string()), text_style), + Line::styled( + self.chain_name + .clone() + .unwrap_or(OghamCenter::default().to_string()), + text_style, + ), + Line::styled( + self.node_version + .clone() + .unwrap_or(OghamCenter::default().to_string()), + text_style, + ), Line::styled(self.prepared_genesis_hash(), text_style), ]; let paragraph = Paragraph::new(text) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type), ) .alignment(Alignment::Center) .wrap(Wrap { trim: true }); diff --git a/src/components/wallet/account_details.rs b/src/components/wallet/account_details.rs index c5e6645..0a4dfde 100644 --- a/src/components/wallet/account_details.rs +++ b/src/components/wallet/account_details.rs @@ -1,20 +1,15 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Alignment, Constraint, Flex, Layout, Rect}, - widgets::{Block, Cell, Clear, Row, Table}, - text::Text, + layout::{Alignment, Constraint, Flex, Layout, Rect}, + text::Text, + widgets::{Block, Cell, Clear, Row, Table}, Frame, }; use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, - widgets::DotSpinner, -}; +use super::{Component, CurrentTab, PartialComponent}; +use crate::{action::Action, config::Config, palette::StylePalette, widgets::DotSpinner}; #[derive(Debug)] pub struct AccountDetails { @@ -66,8 +61,8 @@ impl AccountDetails { let value = value as f64 / 10f64.powi(18); let after = Self::DECIMALS; format!("{:.after$}{}", value, Self::TICKER) - }, - None => format!("{}{}", DotSpinner::default().to_string(), Self::TICKER) + } + None => format!("{}{}", DotSpinner::default().to_string(), Self::TICKER), } } } @@ -99,11 +94,16 @@ impl Component for AccountDetails { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -119,11 +119,12 @@ impl Component for AccountDetails { self.reserved_balance = Some(account_info.reserved); self.nonce = Some(account_info.nonce); - let transferable = account_info.free + let transferable = account_info + .free .saturating_sub(account_info.reserved) .saturating_sub(account_info.frozen); self.transferable_balance = Some(transferable); - }, + } None => { self.transferable_balance = None; self.locked_balance = None; @@ -141,8 +142,8 @@ impl Component for AccountDetails { fn handle_key_event(&mut self, key: KeyEvent) -> Result> { if self.is_active && key.kind == KeyEventKind::Press { match key.code { - KeyCode::Esc | KeyCode::Enter => self.close_popup(), - _ => {}, + KeyCode::Esc | KeyCode::Enter => self.close_popup(), + _ => {} }; } Ok(None) @@ -155,39 +156,54 @@ impl Component for AccountDetails { [ Row::new(vec![ Cell::from(Text::from("nonce: ".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.nonce - .map(|n| n.to_string()) - .unwrap_or(DotSpinner::default().to_string()) - ).alignment(Alignment::Right)), + Cell::from( + Text::from( + self.nonce + .map(|n| n.to_string()) + .unwrap_or(DotSpinner::default().to_string()), + ) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("total: ".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.total_balance)).alignment(Alignment::Right)) + Cell::from( + Text::from(self.prepare_u128(self.total_balance)) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("free: ".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.transferable_balance)).alignment(Alignment::Right)) + Cell::from( + Text::from(self.prepare_u128(self.transferable_balance)) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("locked: ".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.locked_balance)).alignment(Alignment::Right)), + Cell::from( + Text::from(self.prepare_u128(self.locked_balance)) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("reserved: ".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.reserved_balance)).alignment(Alignment::Right)), + Cell::from( + Text::from(self.prepare_u128(self.reserved_balance)) + .alignment(Alignment::Right), + ), ]), ], - [ - Constraint::Max(10), - Constraint::Min(14), - ] + [Constraint::Max(10), Constraint::Min(14)], ) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title(format!("Details for {}", &self.name))); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title(format!("Details for {}", &self.name)), + ); let v = Layout::vertical([Constraint::Max(7)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(50)]).flex(Flex::Center); diff --git a/src/components/wallet/accounts.rs b/src/components/wallet/accounts.rs index c732c41..63c95c9 100644 --- a/src/components/wallet/accounts.rs +++ b/src/components/wallet/accounts.rs @@ -1,36 +1,32 @@ -use std::path::PathBuf; use std::fs::File; -use std::io::{Write, BufRead, BufReader}; +use std::io::{BufRead, BufReader, Write}; +use std::path::PathBuf; use std::process::Command; use color_eyre::Result; use crossterm::event::{KeyCode, KeyEvent}; use ratatui::layout::{Constraint, Margin}; use ratatui::{ + layout::{Alignment, Rect}, text::Text, - layout::{Alignment, Rect}, widgets::{ - Block, Cell, Row, Table, TableState, Scrollbar, Padding, - ScrollbarOrientation, ScrollbarState, - }, - Frame + Block, Cell, Padding, Row, Scrollbar, ScrollbarOrientation, ScrollbarState, Table, + TableState, + }, + Frame, }; +use std::sync::mpsc::Sender; use subxt::ext::sp_core::{ - Pair as PairT, + crypto::{AccountId32, Ss58AddressFormat, Ss58Codec}, sr25519::Pair, - crypto::{Ss58Codec, Ss58AddressFormat, AccountId32}, + Pair as PairT, }; use tokio::sync::mpsc::UnboundedSender; -use std::sync::mpsc::Sender; -use super::{PartialComponent, Component, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::types::{ActionLevel, ActionTarget, SystemAccount}; use crate::widgets::DotSpinner; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, -}; +use crate::{action::Action, config::Config, palette::StylePalette}; struct AccountInfo { name: String, @@ -79,9 +75,7 @@ impl Accounts { if let Some(network_tx) = &self.network_tx { let used_seed = self.wallet_keys[index].seed.clone(); let account_id = self.wallet_keys[index].account_id; - let used_nonce = self.balances - .get(&account_id) - .map(|info| info.nonce); + let used_nonce = self.balances.get(&account_id).map(|info| info.nonce); let _ = network_tx.send(Action::SetSender(used_seed, used_nonce)); } } @@ -90,22 +84,17 @@ impl Accounts { let used_seed = self.wallet_keys[index].seed.clone(); let account_id = self.wallet_keys[index].account_id; if let Some(action_tx) = &self.action_tx { - let _ = action_tx.send(Action::UsedAccount( - account_id, - used_seed.clone())); + let _ = action_tx.send(Action::UsedAccount(account_id, used_seed.clone())); } if let Some(network_tx) = &self.network_tx { - let _ = network_tx.send(Action::GetNominatorsByAccount( - account_id, - false)); + let _ = network_tx.send(Action::GetNominatorsByAccount(account_id, false)); } self.set_sender_nonce(index); } fn log_event(&mut self, message: String, level: ActionLevel) { if let Some(action_tx) = &self.action_tx { - let _ = action_tx.send( - Action::EventLog(message, level, ActionTarget::WalletLog)); + let _ = action_tx.send(Action::EventLog(message, level, ActionTarget::WalletLog)); } } @@ -119,16 +108,15 @@ impl Accounts { if let Some(action_tx) = &self.action_tx { let account_id = self.wallet_keys[index].account_id; let _ = action_tx.send(Action::BalanceSetActive( - self.balances.get(&account_id).cloned())); + self.balances.get(&account_id).cloned(), + )); } } fn update_account_name(&mut self) { if let Some(index) = self.table_state.selected() { if let Some(action_tx) = &self.action_tx { - let _ = action_tx.send(Action::RenameAccount( - self.wallet_keys[index].name.clone() - )); + let _ = action_tx.send(Action::RenameAccount(self.wallet_keys[index].name.clone())); } } } @@ -141,19 +129,20 @@ impl Accounts { .arg("clipboard") .stdin(std::process::Stdio::piped()) .spawn() - .and_then(|child| Ok(child + .and_then(|child| { + Ok(child .stdin - .and_then(|mut cs| cs - .write_all(address.as_bytes()) - .ok()) - )) - { + .and_then(|mut cs| cs.write_all(address.as_bytes()).ok())) + }) { Ok(Some(())) => self.log_event( - format!("address {} copied to clipboard", &address), - ActionLevel::Warn), + format!("address {} copied to clipboard", &address), + ActionLevel::Warn, + ), _ => self.log_event( - "command `xclip` not found, consider installing `xclip` on your machine".to_string(), - ActionLevel::Error), + "command `xclip` not found, consider installing `xclip` on your machine" + .to_string(), + ActionLevel::Error, + ), } } } @@ -166,16 +155,19 @@ impl Accounts { .to_ss58check_with_version(Ss58AddressFormat::custom(1996)); self.log_event( - format!("new wallet '{}' with public address {} created", - &name, &address), - ActionLevel::Info); + format!( + "new wallet '{}' with public address {} created", + &name, &address + ), + ActionLevel::Info, + ); self.send_balance_request(account_id, false); self.wallet_keys.push(AccountInfo { - name, - address, + name, + address, account_id, - seed: secret_seed, + seed: secret_seed, }); self.last_row(); self.save_to_file(); @@ -185,16 +177,16 @@ impl Accounts { if let Some(index) = self.table_state.selected() { let old_name = self.wallet_keys[index].name.clone(); - self.log_event(format!("wallet '{}' renamed to {}", - &new_name, &old_name), - ActionLevel::Info); + self.log_event( + format!("wallet '{}' renamed to {}", &new_name, &old_name), + ActionLevel::Info, + ); self.wallet_keys[index].name = new_name; self.save_to_file(); - } } - fn swap_up(&mut self) { + fn swap_up(&mut self) { if let Some(src_index) = self.table_state.selected() { let dst_index = src_index.saturating_sub(1); if src_index > dst_index { @@ -224,9 +216,13 @@ impl Accounts { self.previous_row(); self.save_to_file(); - self.log_event(format!("wallet `{}` with public address {} removed", - &wallet.name, &wallet.address), - ActionLevel::Warn); + self.log_event( + format!( + "wallet `{}` with public address {} removed", + &wallet.name, &wallet.address + ), + ActionLevel::Warn, + ); } } } @@ -262,16 +258,17 @@ impl Accounts { self.send_balance_request(account_id, false); self.wallet_keys.push(AccountInfo { - name: wallet_name.to_string(), - account_id, - address, - seed: wallet_key.to_string(), + name: wallet_name.to_string(), + account_id, + address, + seed: wallet_key.to_string(), }); } - self.log_event(format!("read {} wallets from disk", - self.wallet_keys.len()), - ActionLevel::Info); - }, + self.log_event( + format!("read {} wallets from disk", self.wallet_keys.len()), + ActionLevel::Info, + ); + } Err(_) => { let (pair, seed) = match std::fs::read_to_string("/etc/ghost/wallet-key") { Ok(content) => { @@ -285,7 +282,8 @@ impl Accounts { self.log_event( "wallet read from the `/etc/ghost/wallet-key`".to_string(), - ActionLevel::Warn); + ActionLevel::Warn, + ); let pair = Pair::from_seed(&seed); (pair, seed) @@ -293,7 +291,8 @@ impl Accounts { Err(_) => { self.log_event( "no wallets found on disk, new wallet created".to_string(), - ActionLevel::Warn); + ActionLevel::Warn, + ); let (pair, seed) = Pair::generate(); (pair, seed) } @@ -309,10 +308,10 @@ impl Accounts { self.send_balance_request(account_id, false); self.wallet_keys.push(AccountInfo { - name: "ghostie".to_string(), - address, - account_id, - seed: secret_seed, + name: "ghostie".to_string(), + address, + account_id, + seed: secret_seed, }); } }; @@ -346,27 +345,32 @@ impl Accounts { if self.wallet_keys.iter().any(|key| key.seed == secret_seed) { self.log_event( format!("{} from `{}` already loaded", name_for_key, path_to_key), - ActionLevel::Warn); + ActionLevel::Warn, + ); } else { self.log_event( - format!("{} from `{}` loaded to ghost-eye", name_for_key, path_to_key), - ActionLevel::Warn); + format!( + "{} from `{}` loaded to ghost-eye", + name_for_key, path_to_key + ), + ActionLevel::Warn, + ); self.send_balance_request(account_id, false); self.wallet_keys.push(AccountInfo { - name: name_for_key.to_string(), - address, + name: name_for_key.to_string(), + address, account_id, - seed: secret_seed, + seed: secret_seed, }); self.save_to_file(); } - } Err(_) => { self.log_event( format!("nothing found inside `{}`", path_to_key), - ActionLevel::Warn); + ActionLevel::Warn, + ); } }; } @@ -374,12 +378,14 @@ impl Accounts { fn push_to_address_book(&mut self) { if let Some(index) = self.table_state.selected() { if let Some(action_tx) = &self.action_tx { - let wallet_key = self.wallet_keys + let wallet_key = self + .wallet_keys .get(index) .expect("wallet key index should be in range; qed"); let _ = action_tx.send(Action::NewAddressBookRecord( - wallet_key.name.clone(), - wallet_key.address.clone())); + wallet_key.name.clone(), + wallet_key.address.clone(), + )); } } } @@ -401,7 +407,7 @@ impl Accounts { } else { i + 1 } - }, + } None => 0, }; self.table_state.select(Some(i)); @@ -428,8 +434,8 @@ impl Accounts { } else { i - 1 } - }, - None => 0 + } + None => 0, }; self.table_state.select(Some(i)); self.scroll_state = self.scroll_state.position(i); @@ -444,7 +450,7 @@ impl Accounts { let after = Self::DECIMALS; format!("{:.after$}{}", value, Self::TICKER) } - None => format!("{}{}", DotSpinner::default().to_string(), Self::TICKER) + None => format!("{}{}", DotSpinner::default().to_string(), Self::TICKER), } } } @@ -471,14 +477,22 @@ impl Component for Accounts { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Wallet) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } let mut wallet_keys_file = config.config.data_dir; @@ -493,7 +507,11 @@ impl Component for Accounts { Action::NewAccount(name) => self.create_new_account(name), Action::UpdateAccountName(new_name) => self.rename_account(new_name), Action::BalanceResponse(account_id, maybe_balance) => { - if self.wallet_keys.iter().any(|wallet| wallet.account_id == account_id) { + if self + .wallet_keys + .iter() + .any(|wallet| wallet.account_id == account_id) + { let _ = match maybe_balance { Some(balance) => self.balances.insert(account_id, balance), None => self.balances.remove(&account_id), @@ -505,7 +523,7 @@ impl Component for Accounts { } } } - }, + } _ => {} }; Ok(None) @@ -514,8 +532,8 @@ impl Component for Accounts { fn handle_key_event(&mut self, key: KeyEvent) -> Result> { if self.is_active { match key.code { - KeyCode::Up | KeyCode::Char('k') => self.previous_row(), - KeyCode::Down | KeyCode::Char('j') => self.next_row(), + KeyCode::Up | KeyCode::Char('k') => self.previous_row(), + KeyCode::Down | KeyCode::Char('j') => self.next_row(), KeyCode::Char('K') => self.swap_up(), KeyCode::Char('J') => self.swap_down(), KeyCode::Char('g') => self.first_row(), @@ -525,7 +543,7 @@ impl Component for Accounts { KeyCode::Char('Y') => self.copy_to_clipboard(), KeyCode::Char('L') => self.load_initial_keys(), KeyCode::Char('P') => self.push_to_address_book(), - _ => {}, + _ => {} }; } Ok(None) @@ -536,33 +554,27 @@ impl Component for Accounts { let (border_style, border_type) = self.palette.create_border_style(self.is_active); let table = Table::new( - self.wallet_keys - .iter() - .map(|info| { - let balance = self.balances - .get(&info.account_id) - .map(|b| b.free); - Row::new(vec![ - Cell::from(Text::from(info.name.clone()).alignment(Alignment::Left)), - Cell::from(Text::from(info.address.clone()).alignment(Alignment::Center)), - Cell::from(Text::from(self.prepare_u128(balance)).alignment(Alignment::Right)), - ]) - }), - [ - Constraint::Min(5), - Constraint::Max(51), - Constraint::Min(11), - ], + self.wallet_keys.iter().map(|info| { + let balance = self.balances.get(&info.account_id).map(|b| b.free); + Row::new(vec![ + Cell::from(Text::from(info.name.clone()).alignment(Alignment::Left)), + Cell::from(Text::from(info.address.clone()).alignment(Alignment::Center)), + Cell::from(Text::from(self.prepare_u128(balance)).alignment(Alignment::Right)), + ]) + }), + [Constraint::Min(5), Constraint::Max(51), Constraint::Min(11)], ) .highlight_style(self.palette.create_highlight_style()) .column_spacing(1) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .padding(Padding::right(2)) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("My Accounts")); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .padding(Padding::right(2)) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("My Accounts"), + ); let scrollbar = Scrollbar::default() .orientation(ScrollbarOrientation::VerticalRight) @@ -573,7 +585,10 @@ impl Component for Accounts { frame.render_stateful_widget(table, place, &mut self.table_state); frame.render_stateful_widget( scrollbar, - place.inner(Margin { vertical: 1, horizontal: 1 }), + place.inner(Margin { + vertical: 1, + horizontal: 1, + }), &mut self.scroll_state, ); diff --git a/src/components/wallet/add_account.rs b/src/components/wallet/add_account.rs index 135f94a..063b49c 100644 --- a/src/components/wallet/add_account.rs +++ b/src/components/wallet/add_account.rs @@ -1,18 +1,18 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Position, Alignment, Constraint, Flex, Layout, Rect}, - widgets::{Block, Clear, Paragraph}, - Frame + layout::{Alignment, Constraint, Flex, Layout, Position, Rect}, + widgets::{Block, Clear, Paragraph}, + Frame, }; use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ + action::Action, + config::Config, + palette::StylePalette, widgets::{Input, InputRequest}, - action::Action, - config::Config, - palette::StylePalette, }; #[derive(Debug)] @@ -20,7 +20,7 @@ pub struct AddAccount { is_active: bool, action_tx: Option>, name: Input, - palette: StylePalette + palette: StylePalette, } impl Default for AddAccount { @@ -48,8 +48,7 @@ impl AddAccount { fn submit_message(&mut self) { if let Some(action_tx) = &self.action_tx { - let _ = action_tx.send(Action::NewAccount( - self.name.value().to_string())); + let _ = action_tx.send(Action::NewAccount(self.name.value().to_string())); let _ = action_tx.send(Action::ClosePopup); } } @@ -78,7 +77,7 @@ impl PartialComponent for AddAccount { _ => { self.is_active = false; self.name = Input::new(String::new()); - }, + } }; } } @@ -91,11 +90,16 @@ impl Component for AddAccount { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -109,7 +113,7 @@ impl Component for AddAccount { KeyCode::Left => self.move_cursor_left(), KeyCode::Right => self.move_cursor_right(), KeyCode::Esc => self.close_popup(), - _ => {}, + _ => {} }; } Ok(None) @@ -118,16 +122,17 @@ impl Component for AddAccount { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { if self.is_active { let size = area.as_size(); - let area = Rect::new(size.width / 2, size.height / 2, 50, 3); + let area = Rect::new(size.width / 2, size.height / 2, 50, 3); let (border_style, border_type) = self.palette.create_popup_style(); - let input = Paragraph::new(self.name.value()) - .block(Block::bordered() + let input = Paragraph::new(self.name.value()).block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title("New wallet name")); + .title("New wallet name"), + ); let v = Layout::vertical([Constraint::Max(3)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(50)]).flex(Flex::Center); let [area] = v.areas(area); @@ -136,8 +141,8 @@ impl Component for AddAccount { frame.render_widget(Clear, area); frame.render_widget(input, area); frame.set_cursor_position(Position::new( - area.x + self.name.cursor() as u16 + 1, - area.y + 1 + area.x + self.name.cursor() as u16 + 1, + area.y + 1, )); } Ok(()) diff --git a/src/components/wallet/add_address_book_record.rs b/src/components/wallet/add_address_book_record.rs index f3bf8b0..58b0eab 100644 --- a/src/components/wallet/add_address_book_record.rs +++ b/src/components/wallet/add_address_book_record.rs @@ -1,18 +1,18 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Position, Alignment, Constraint, Flex, Layout, Rect}, - widgets::{Block, Clear, Paragraph}, - Frame + layout::{Alignment, Constraint, Flex, Layout, Position, Rect}, + widgets::{Block, Clear, Paragraph}, + Frame, }; use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ + action::Action, + config::Config, + palette::StylePalette, widgets::{Input, InputRequest}, - action::Action, - config::Config, - palette::StylePalette, }; #[derive(Debug)] @@ -28,7 +28,7 @@ pub struct AddAddressBookRecord { action_tx: Option>, name: Input, address: Input, - palette: StylePalette + palette: StylePalette, } impl Default for AddAddressBookRecord { @@ -59,11 +59,14 @@ impl AddAddressBookRecord { fn submit_message(&mut self) { match self.name_or_address { NameOrAddress::Name => self.name_or_address = NameOrAddress::Address, - NameOrAddress::Address => if let Some(action_tx) = &self.action_tx { - let _ = action_tx.send(Action::NewAddressBookRecord( + NameOrAddress::Address => { + if let Some(action_tx) = &self.action_tx { + let _ = action_tx.send(Action::NewAddressBookRecord( self.name.value().to_string(), - self.address.value().to_string())); - let _ = action_tx.send(Action::ClosePopup); + self.address.value().to_string(), + )); + let _ = action_tx.send(Action::ClosePopup); + } } } } @@ -72,7 +75,7 @@ impl AddAddressBookRecord { match self.name_or_address { NameOrAddress::Name => { let _ = self.name.handle(InputRequest::InsertChar(new_char)); - }, + } NameOrAddress::Address => { let _ = self.address.handle(InputRequest::InsertChar(new_char)); } @@ -83,7 +86,7 @@ impl AddAddressBookRecord { match self.name_or_address { NameOrAddress::Name => { let _ = self.name.handle(InputRequest::DeletePrevChar); - }, + } NameOrAddress::Address => { let _ = self.address.handle(InputRequest::DeletePrevChar); } @@ -94,7 +97,7 @@ impl AddAddressBookRecord { match self.name_or_address { NameOrAddress::Name => { let _ = self.name.handle(InputRequest::GoToNextChar); - }, + } NameOrAddress::Address => { let _ = self.address.handle(InputRequest::GoToNextChar); } @@ -105,7 +108,7 @@ impl AddAddressBookRecord { match self.name_or_address { NameOrAddress::Name => { let _ = self.name.handle(InputRequest::GoToPrevChar); - }, + } NameOrAddress::Address => { let _ = self.address.handle(InputRequest::GoToPrevChar); } @@ -124,7 +127,7 @@ impl PartialComponent for AddAddressBookRecord { self.address = Input::new(String::new()); self.name_or_address = NameOrAddress::Name; } - }, + } }; } } @@ -137,11 +140,16 @@ impl Component for AddAddressBookRecord { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -156,8 +164,8 @@ impl Component for AddAddressBookRecord { KeyCode::Backspace => self.delete_char(), KeyCode::Left => self.move_cursor_left(), KeyCode::Right => self.move_cursor_right(), - KeyCode::Esc => self.close_popup(), - _ => {}, + KeyCode::Esc => self.close_popup(), + _ => {} }; } Ok(None) @@ -166,25 +174,27 @@ impl Component for AddAddressBookRecord { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { if self.is_active { let size = area.as_size(); - let name_area = Rect::new(size.width / 2, size.height / 2, 51, 3); - let address_area = Rect::new(size.width / 2, size.height / 2 + 3, 51, 3); + let name_area = Rect::new(size.width / 2, size.height / 2, 51, 3); + let address_area = Rect::new(size.width / 2, size.height / 2 + 3, 51, 3); let (border_style, border_type) = self.palette.create_popup_style(); - let input_name = Paragraph::new(self.name.value()) - .block(Block::bordered() + let input_name = Paragraph::new(self.name.value()).block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title("New name in Address Book")); + .title("New name in Address Book"), + ); - let input_address = Paragraph::new(self.address.value()) - .block(Block::bordered() + let input_address = Paragraph::new(self.address.value()).block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title("Address for new name")); + .title("Address for new name"), + ); let v = Layout::vertical([Constraint::Length(3)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Length(51)]).flex(Flex::Center); @@ -202,14 +212,14 @@ impl Component for AddAddressBookRecord { match self.name_or_address { NameOrAddress::Name => { frame.set_cursor_position(Position::new( - name_area.x + self.name.cursor() as u16 + 1, - name_area.y + 1 + name_area.x + self.name.cursor() as u16 + 1, + name_area.y + 1, )); - }, + } NameOrAddress::Address => { frame.set_cursor_position(Position::new( - address_area.x + self.address.cursor() as u16 + 1, - address_area.y + 1 + address_area.x + self.address.cursor() as u16 + 1, + address_area.y + 1, )); } } diff --git a/src/components/wallet/address_book.rs b/src/components/wallet/address_book.rs index aa84796..6256870 100644 --- a/src/components/wallet/address_book.rs +++ b/src/components/wallet/address_book.rs @@ -1,6 +1,6 @@ use std::fs::File; +use std::io::{BufRead, BufReader, Write}; use std::path::PathBuf; -use std::io::{Write, BufRead, BufReader}; use color_eyre::Result; use crossterm::event::{KeyCode, KeyEvent}; @@ -8,24 +8,18 @@ use ratatui::layout::{Constraint, Margin}; use ratatui::text::Text; use ratatui::widgets::{Cell, Padding, Scrollbar, ScrollbarOrientation}; use ratatui::{ - layout::{Alignment, Rect}, - widgets::{Block, ScrollbarState, Row, Table, TableState}, - Frame + layout::{Alignment, Rect}, + widgets::{Block, Row, ScrollbarState, Table, TableState}, + Frame, }; -use subxt::ext::sp_core::crypto::{ - ByteArray, Ss58Codec, Ss58AddressFormat, AccountId32, -}; -use tokio::sync::mpsc::UnboundedSender; use std::sync::mpsc::Sender; +use subxt::ext::sp_core::crypto::{AccountId32, ByteArray, Ss58AddressFormat, Ss58Codec}; +use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::types::{ActionLevel, ActionTarget, SystemAccount}; use crate::widgets::DotSpinner; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, -}; +use crate::{action::Action, config::Config, palette::StylePalette}; struct BookRecord { name: String, @@ -80,8 +74,8 @@ impl AddressBook { fn send_transfer_to(&mut self) { if let Some(action_tx) = &self.action_tx { if let Some(index) = self.table_state.selected() { - let _ = action_tx.send(Action::TransferTo( - self.address_book[index].address.clone())); + let _ = + action_tx.send(Action::TransferTo(self.address_book[index].address.clone())); } } } @@ -94,8 +88,7 @@ impl AddressBook { fn log_event(&mut self, message: String, level: ActionLevel) { if let Some(action_tx) = &self.action_tx { - let _ = action_tx.send( - Action::EventLog(message, level, ActionTarget::WalletLog)); + let _ = action_tx.send(Action::EventLog(message, level, ActionTarget::WalletLog)); } } @@ -120,56 +113,86 @@ impl AddressBook { .to_ss58check_with_version(Ss58AddressFormat::custom(1996)); self.address_book.push(BookRecord { - name: name.to_string(), - address, - account_id, + name: name.to_string(), + address, + account_id, seed: seed_str.to_string(), }); self.send_balance_request(account_id, false); } self.log_event( format!("read {} records from address book", self.address_book.len()), - ActionLevel::Info) - }, + ActionLevel::Info, + ) + } Err(_) => { let chad_boyz = vec![ - ("Pierre", "328d3b7c3046ef7700937d99fb2e98ce2591682c2b5dcf3f562e4da157650237"), - ("Ghost_7", "3666e4e19f87bb8680495f31864ce1f1c69d4178002cc01911aef2cc7313f203"), - ("Neptune1", "ac871e8bab00dd56ba3a1c0bd289357203dcaf10010b0b04ad7472870cd22a3c"), - ("Neptune2", "425ccd7bda4f5c76788ba23bc0381d7a2e496179c93301208c57501c80a4232a"), - ("Doctor K", "927a98dcf8f721103005f168476c24b91d7d10d580f457006a908e10e62c7729"), - ("Starman", "ac9e227e30a63ce6eeb55cfbb1fb832aa7e1d3fad2bcb3f663de4a91d744fd50"), - ("Kitsune1", "46c78fcacffd80abc9cca4917ef8369a37e21a1691ca11e7a3b53f80be745313"), - ("Scientio", "fa5e5a295ec74c3dda81118d9240db1552b28f831838465ae0712e97e78a6728"), - ("Kitsune2", "4078ddb1ba1388f768fe6aa40ba9124a72692ecbcc83dc088fa86c735e4dc128"), - ("Proxmio", "5e1456904c40192cd3a18183df7dffea90d97739830a902cabb702ecdae4f649"), + ( + "Pierre", + "328d3b7c3046ef7700937d99fb2e98ce2591682c2b5dcf3f562e4da157650237", + ), + ( + "Ghost_7", + "3666e4e19f87bb8680495f31864ce1f1c69d4178002cc01911aef2cc7313f203", + ), + ( + "Neptune1", + "ac871e8bab00dd56ba3a1c0bd289357203dcaf10010b0b04ad7472870cd22a3c", + ), + ( + "Neptune2", + "425ccd7bda4f5c76788ba23bc0381d7a2e496179c93301208c57501c80a4232a", + ), + ( + "Doctor K", + "927a98dcf8f721103005f168476c24b91d7d10d580f457006a908e10e62c7729", + ), + ( + "Starman", + "ac9e227e30a63ce6eeb55cfbb1fb832aa7e1d3fad2bcb3f663de4a91d744fd50", + ), + ( + "Kitsune1", + "46c78fcacffd80abc9cca4917ef8369a37e21a1691ca11e7a3b53f80be745313", + ), + ( + "Scientio", + "fa5e5a295ec74c3dda81118d9240db1552b28f831838465ae0712e97e78a6728", + ), + ( + "Kitsune2", + "4078ddb1ba1388f768fe6aa40ba9124a72692ecbcc83dc088fa86c735e4dc128", + ), + ( + "Proxmio", + "5e1456904c40192cd3a18183df7dffea90d97739830a902cabb702ecdae4f649", + ), ]; let mut new_file = File::create(file_path)?; - chad_boyz - .iter() - .for_each(|chad_info| { - writeln!(new_file, "{}:0x{}", chad_info.0, chad_info.1) - .expect("should write to address book; qed"); - let chad_account_id: [u8; 32] = hex::decode(&chad_info.1[..]) - .expect("stored seed is valid hex string; qed") - .as_slice() - .try_into() - .expect("stored seed is valid length; qed"); - let address = AccountId32::from(chad_account_id) - .to_ss58check_with_version(Ss58AddressFormat::custom(1996)); + chad_boyz.iter().for_each(|chad_info| { + writeln!(new_file, "{}:0x{}", chad_info.0, chad_info.1) + .expect("should write to address book; qed"); + let chad_account_id: [u8; 32] = hex::decode(&chad_info.1[..]) + .expect("stored seed is valid hex string; qed") + .as_slice() + .try_into() + .expect("stored seed is valid length; qed"); + let address = AccountId32::from(chad_account_id) + .to_ss58check_with_version(Ss58AddressFormat::custom(1996)); - self.address_book.push(BookRecord { - name: chad_info.0.to_string(), - address, - account_id: chad_account_id, - seed: chad_info.1.to_string(), - }); - self.send_balance_request(chad_account_id, false); + self.address_book.push(BookRecord { + name: chad_info.0.to_string(), + address, + account_id: chad_account_id, + seed: chad_info.1.to_string(), }); + self.send_balance_request(chad_account_id, false); + }); self.log_event( format!("address book is empty, filling it with giga chad boyz as default"), - ActionLevel::Warn) + ActionLevel::Warn, + ) } }; self.scroll_state = self.scroll_state.content_length(self.address_book.len()); @@ -181,7 +204,8 @@ impl AddressBook { let old_name = self.address_book[index].name.clone(); self.log_event( format!("record renamed from {} to {}", &old_name, &new_name), - ActionLevel::Info); + ActionLevel::Info, + ); self.address_book[index].name = new_name; self.save_to_file(); } @@ -192,21 +216,34 @@ impl AddressBook { Ok((account_id, format)) => { if format != Ss58AddressFormat::custom(1996) { self.log_event( - format!("provided public address for {} is not part of Casper/Ghost ecosystem", &address), - ActionLevel::Error); + format!( + "provided public address for {} is not part of Casper/Ghost ecosystem", + &address + ), + ActionLevel::Error, + ); } - match self.address_book.iter().position(|record| record.address == address) { + match self + .address_book + .iter() + .position(|record| record.address == address) + { Some(index) => { - let record = self.address_book + let record = self + .address_book .get(index) .expect("record should be in range of address book; qed"); self.log_event( - format!("record with name `{}` already stores address {}", &record.name, &record.address), - ActionLevel::Warn); + format!( + "record with name `{}` already stores address {}", + &record.name, &record.address + ), + ActionLevel::Warn, + ); self.table_state.select(Some(index)); self.scroll_state = self.scroll_state.position(index); - }, + } None => { let seed_vec = account_id.to_raw_vec(); let mut account_id = [0u8; 32]; @@ -214,26 +251,32 @@ impl AddressBook { let seed_str = hex::encode(seed_vec); self.log_event( - format!("account {} with address {} added to address book", &name, &address), - ActionLevel::Info); + format!( + "account {} with address {} added to address book", + &name, &address + ), + ActionLevel::Info, + ); self.address_book.push(BookRecord { - name, - address, - account_id, + name, + address, + account_id, seed: seed_str, }); - self.scroll_state = self.scroll_state.content_length(self.address_book.len()); + self.scroll_state = + self.scroll_state.content_length(self.address_book.len()); self.save_to_file(); self.send_balance_request(account_id, false); self.last_row(); - }, + } } - }, + } Err(_) => self.log_event( format!("provided account address {} is invalid", &address), - ActionLevel::Error), + ActionLevel::Error, + ), } } @@ -241,7 +284,7 @@ impl AddressBook { if let Some(index) = self.table_state.selected() { if let Some(action_tx) = &self.action_tx { let _ = action_tx.send(Action::RenameAddressBookRecord( - self.address_book[index].name.clone() + self.address_book[index].name.clone(), )); } } @@ -251,10 +294,10 @@ impl AddressBook { if let Some(index) = self.table_state.selected() { if let Some(action_tx) = &self.action_tx { let _ = action_tx.send(Action::AccountDetailsOf( - self.address_book[index].name.clone(), - self.balances - .get(&self.address_book[index].account_id) - .map(|data| data.clone()), + self.address_book[index].name.clone(), + self.balances + .get(&self.address_book[index].account_id) + .map(|data| data.clone()), )); } } @@ -287,9 +330,13 @@ impl AddressBook { let record = self.address_book.remove(index); self.previous_row(); self.save_to_file(); - self.log_event(format!("record `{}` with public address {} removed", - &record.name, &record.address), - ActionLevel::Warn); + self.log_event( + format!( + "record `{}` with public address {} removed", + &record.name, &record.address + ), + ActionLevel::Warn, + ); } } @@ -308,7 +355,7 @@ impl AddressBook { } else { i + 1 } - }, + } None => 0, }; self.table_state.select(Some(i)); @@ -331,8 +378,8 @@ impl AddressBook { } else { i - 1 } - }, - None => 0 + } + None => 0, }; self.table_state.select(Some(i)); self.scroll_state = self.scroll_state.position(i); @@ -344,8 +391,8 @@ impl AddressBook { let value = value as f64 / 10f64.powi(18); let after = Self::DECIMALS; format!("{:.after$}{}", value, Self::TICKER) - }, - None => format!("{}{}", DotSpinner::default().to_string(), Self::TICKER) + } + None => format!("{}{}", DotSpinner::default().to_string(), Self::TICKER), } } } @@ -371,14 +418,22 @@ impl Component for AddressBook { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Wallet) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } let mut address_book_file = config.config.data_dir; @@ -390,29 +445,30 @@ impl Component for AddressBook { fn update(&mut self, action: Action) -> Result> { match action { - Action::UpdateAddressBookRecord(new_name) => - self.rename_record(new_name), - Action::NewAddressBookRecord(name, address) => - self.add_new_record(name, address), + Action::UpdateAddressBookRecord(new_name) => self.rename_record(new_name), + Action::NewAddressBookRecord(name, address) => self.add_new_record(name, address), Action::BalanceResponse(account_id, maybe_balance) => { - if self.address_book.iter().any(|record| record.account_id == account_id) { + if self + .address_book + .iter() + .any(|record| record.account_id == account_id) + { let _ = match maybe_balance { Some(balance) => self.balances.insert(account_id, balance), None => self.balances.remove(&account_id), }; } - }, + } _ => {} }; Ok(None) } - fn handle_key_event(&mut self, key: KeyEvent) -> Result> { if self.is_active { match key.code { - KeyCode::Up | KeyCode::Char('k') => self.previous_row(), - KeyCode::Down | KeyCode::Char('j') => self.next_row(), + KeyCode::Up | KeyCode::Char('k') => self.previous_row(), + KeyCode::Down | KeyCode::Char('j') => self.next_row(), KeyCode::Char('g') => self.first_row(), KeyCode::Char('G') => self.last_row(), KeyCode::Char('K') => self.swap_up(), @@ -421,7 +477,7 @@ impl Component for AddressBook { KeyCode::Char('R') => self.update_address_book_record(), KeyCode::Char('I') => self.show_account_details(), KeyCode::Enter => self.send_transfer_to(), - _ => {}, + _ => {} }; } Ok(None) @@ -432,34 +488,31 @@ impl Component for AddressBook { let (border_style, border_type) = self.palette.create_border_style(self.is_active); let table = Table::new( - self.address_book - .iter() - .map(|info| { - let balance = self.balances - .get(&info.account_id) - .map(|inner_balance| inner_balance.free); - Row::new(vec![ - Cell::from(Text::from(info.name.clone()).alignment(Alignment::Left)), - Cell::from(Text::from(info.address.clone()).alignment(Alignment::Center)), - Cell::from(Text::from(self.prepare_u128(balance)).alignment(Alignment::Right)), - ]) - }), - [ - Constraint::Min(5), - Constraint::Max(51), - Constraint::Min(11), - ], + self.address_book.iter().map(|info| { + let balance = self + .balances + .get(&info.account_id) + .map(|inner_balance| inner_balance.free); + Row::new(vec![ + Cell::from(Text::from(info.name.clone()).alignment(Alignment::Left)), + Cell::from(Text::from(info.address.clone()).alignment(Alignment::Center)), + Cell::from(Text::from(self.prepare_u128(balance)).alignment(Alignment::Right)), + ]) + }), + [Constraint::Min(5), Constraint::Max(51), Constraint::Min(11)], ) .style(self.palette.create_basic_style(false)) .highlight_style(self.palette.create_basic_style(true)) .column_spacing(1) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .padding(Padding::right(2)) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("Address Book")); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .padding(Padding::right(2)) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("Address Book"), + ); let scrollbar = Scrollbar::default() .orientation(ScrollbarOrientation::VerticalRight) @@ -469,8 +522,11 @@ impl Component for AddressBook { frame.render_stateful_widget(table, place, &mut self.table_state); frame.render_stateful_widget( - scrollbar, - place.inner(Margin { vertical: 1, horizontal: 1 }), + scrollbar, + place.inner(Margin { + vertical: 1, + horizontal: 1, + }), &mut self.scroll_state, ); diff --git a/src/components/wallet/balance.rs b/src/components/wallet/balance.rs index 0550b67..7cda728 100644 --- a/src/components/wallet/balance.rs +++ b/src/components/wallet/balance.rs @@ -1,18 +1,13 @@ use color_eyre::Result; use ratatui::{ + layout::{Alignment, Constraint, Rect}, text::Text, - layout::{Alignment, Constraint, Rect}, - widgets::{Block, Cell, Row, Table}, - Frame + widgets::{Block, Cell, Row, Table}, + Frame, }; -use super::{Component, PartialComponent, CurrentTab}; -use crate::{ - widgets::DotSpinner, - action::Action, - config::Config, - palette::StylePalette, -}; +use super::{Component, CurrentTab, PartialComponent}; +use crate::{action::Action, config::Config, palette::StylePalette, widgets::DotSpinner}; #[derive(Debug)] pub struct Balance { @@ -22,7 +17,7 @@ pub struct Balance { locked_balance: Option, reserved_balance: Option, nonce: Option, - palette: StylePalette + palette: StylePalette, } impl Default for Balance { @@ -53,8 +48,8 @@ impl Balance { let value = value as f64 / 10f64.powi(18); let after = Self::DECIMALS; format!("{:.after$}{}", value, Self::TICKER) - }, - None => format!("{}{}", DotSpinner::default().to_string(), Self::TICKER) + } + None => format!("{}{}", DotSpinner::default().to_string(), Self::TICKER), } } } @@ -71,38 +66,43 @@ impl PartialComponent for Balance { impl Component for Balance { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Wallet) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); } Ok(()) } fn update(&mut self, action: Action) -> Result> { match action { - Action::BalanceSetActive(maybe_balance) => { - match maybe_balance { - Some(balance) => { - self.total_balance = Some(balance.free); - self.locked_balance = Some(balance.frozen); - self.reserved_balance = Some(balance.reserved); - self.nonce = Some(balance.nonce); + Action::BalanceSetActive(maybe_balance) => match maybe_balance { + Some(balance) => { + self.total_balance = Some(balance.free); + self.locked_balance = Some(balance.frozen); + self.reserved_balance = Some(balance.reserved); + self.nonce = Some(balance.nonce); - let transferable = balance.free - .saturating_sub(balance.reserved) - .saturating_sub(balance.frozen); - self.transferable_balance = Some(transferable); - }, - None => { - self.transferable_balance = None; - self.locked_balance = None; - self.reserved_balance = None; - self.total_balance = None; - self.nonce = None; - } + let transferable = balance + .free + .saturating_sub(balance.reserved) + .saturating_sub(balance.frozen); + self.transferable_balance = Some(transferable); + } + None => { + self.transferable_balance = None; + self.locked_balance = None; + self.reserved_balance = None; + self.total_balance = None; + self.nonce = None; } }, _ => {} @@ -112,46 +112,60 @@ impl Component for Balance { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { let [_, _, place, _] = super::account_layout(area); - 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 table = Table::new( [ Row::new(vec![ Cell::from(Text::from("nonce: ".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.nonce - .map(|n| n.to_string()) - .unwrap_or(DotSpinner::default().to_string()) - ).alignment(Alignment::Right)), + Cell::from( + Text::from( + self.nonce + .map(|n| n.to_string()) + .unwrap_or(DotSpinner::default().to_string()), + ) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("account: ".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.total_balance)).alignment(Alignment::Right)), + Cell::from( + Text::from(self.prepare_u128(self.total_balance)) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("free: ".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.transferable_balance)).alignment(Alignment::Right)) + Cell::from( + Text::from(self.prepare_u128(self.transferable_balance)) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("locked: ".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.locked_balance)).alignment(Alignment::Right)), + Cell::from( + Text::from(self.prepare_u128(self.locked_balance)) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("reserved: ".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.reserved_balance)).alignment(Alignment::Right)), + Cell::from( + Text::from(self.prepare_u128(self.reserved_balance)) + .alignment(Alignment::Right), + ), ]), ], - [ - Constraint::Max(10), - Constraint::Min(14), - ] + [Constraint::Max(10), Constraint::Min(14)], ) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("Balance")); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("Balance"), + ); frame.render_widget(table, place); Ok(()) diff --git a/src/components/wallet/bond_popup.rs b/src/components/wallet/bond_popup.rs index 8e81e02..779b286 100644 --- a/src/components/wallet/bond_popup.rs +++ b/src/components/wallet/bond_popup.rs @@ -1,19 +1,19 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Position, Alignment, Constraint, Flex, Layout, Rect}, - widgets::{Block, Clear, Paragraph}, - Frame + layout::{Alignment, Constraint, Flex, Layout, Position, Rect}, + widgets::{Block, Clear, Paragraph}, + Frame, }; -use tokio::sync::mpsc::UnboundedSender; use std::sync::mpsc::Sender; +use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ - action::Action, - config::Config, - palette::StylePalette, - types::{ActionLevel, ActionTarget}, + action::Action, + config::Config, + palette::StylePalette, + types::{ActionLevel, ActionTarget}, widgets::{Input, InputRequest}, }; @@ -27,7 +27,7 @@ pub struct BondPopup { minimal_bond: u128, is_bonded: bool, amount: Input, - palette: StylePalette + palette: StylePalette, } impl Default for BondPopup { @@ -53,8 +53,7 @@ impl BondPopup { fn log_event(&mut self, message: String, level: ActionLevel) { if let Some(action_tx) = &self.action_tx { - let _ = action_tx.send( - Action::EventLog(message, level, ActionTarget::WalletLog)); + let _ = action_tx.send(Action::EventLog(message, level, ActionTarget::WalletLog)); } } @@ -76,7 +75,7 @@ impl BondPopup { } fn submit_message(&mut self) { - if let Some(network_tx) = &self.network_tx { + if let Some(network_tx) = &self.network_tx { let str_amount = self.amount.value(); let str_amount = if str_amount.starts_with('.') { &format!("0{}", str_amount)[..] @@ -88,16 +87,25 @@ impl BondPopup { let amount = (value * 1_000_000_000_000_000_000.0) as u128; let log_target = ActionTarget::WalletLog; let _ = if self.is_bonded { - network_tx.send(Action::BondValidatorExtraFrom(self.account_secret_seed, amount, log_target)) + network_tx.send(Action::BondValidatorExtraFrom( + self.account_secret_seed, + amount, + log_target, + )) } else { - network_tx.send(Action::BondValidatorFrom(self.account_secret_seed, amount, log_target)) + network_tx.send(Action::BondValidatorFrom( + self.account_secret_seed, + amount, + log_target, + )) }; if let Some(action_tx) = &self.action_tx { let _ = action_tx.send(Action::ClosePopup); } - }, - Err(err) => self.log_event( - format!("invalid amount, error: {err}"), ActionLevel::Error), + } + Err(err) => { + self.log_event(format!("invalid amount, error: {err}"), ActionLevel::Error) + } } } } @@ -147,11 +155,16 @@ impl Component for BondPopup { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -164,8 +177,8 @@ impl Component for BondPopup { KeyCode::Backspace => self.delete_char(), KeyCode::Left => self.move_cursor_left(), KeyCode::Right => self.move_cursor_right(), - KeyCode::Esc => self.close_popup(), - _ => {}, + KeyCode::Esc => self.close_popup(), + _ => {} }; } Ok(None) @@ -173,9 +186,12 @@ impl Component for BondPopup { fn update(&mut self, action: Action) -> Result> { match action { - Action::SetIsBonded(is_bonded, account_id) if self.account_id == account_id => - self.is_bonded = is_bonded, - Action::UsedAccount(account_id, secret_seed) => self.update_used_account(account_id, secret_seed), + Action::SetIsBonded(is_bonded, account_id) if self.account_id == account_id => { + self.is_bonded = is_bonded + } + Action::UsedAccount(account_id, secret_seed) => { + self.update_used_account(account_id, secret_seed) + } Action::SetMinValidatorBond(minimal_bond) => self.minimal_bond = minimal_bond, _ => {} }; @@ -185,13 +201,14 @@ impl Component for BondPopup { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { if self.is_active { let (border_style, border_type) = self.palette.create_popup_style(); - let input = Paragraph::new(self.amount.value()) - .block(Block::bordered() + let input = Paragraph::new(self.amount.value()).block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title(format!("Staking bond amount"))); + .title(format!("Staking bond amount")), + ); let v = Layout::vertical([Constraint::Max(3)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(50)]).flex(Flex::Center); let [area] = v.areas(area); @@ -200,8 +217,8 @@ impl Component for BondPopup { frame.render_widget(Clear, area); frame.render_widget(input, area); frame.set_cursor_position(Position::new( - area.x + self.amount.cursor() as u16 + 1, - area.y + 1 + area.x + self.amount.cursor() as u16 + 1, + area.y + 1, )); } Ok(()) diff --git a/src/components/wallet/current_validator_details.rs b/src/components/wallet/current_validator_details.rs index bd1de7d..f56f796 100644 --- a/src/components/wallet/current_validator_details.rs +++ b/src/components/wallet/current_validator_details.rs @@ -2,14 +2,14 @@ use std::sync::mpsc::Sender; use color_eyre::Result; use ratatui::{ + layout::{Alignment, Constraint, Rect}, + text::Text, widgets::Clear, - layout::{Alignment, Constraint, Rect}, - text::Text, - widgets::{Block, Cell, Row, Table}, - Frame + widgets::{Block, Cell, Row, Table}, + Frame, }; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{action::Action, config::Config, palette::StylePalette}; #[derive(Debug)] @@ -86,11 +86,11 @@ impl CurrentValidatorDetails { Some(commission) => { self.commission = commission as f64 / 10_000_000.0; self.is_active_validator = true; - }, + } None => { self.commission = 0.0; self.is_active_validator = false; - }, + } } } @@ -130,29 +130,53 @@ impl Component for CurrentValidatorDetails { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Wallet) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } Ok(()) } 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::SetStakedAmountRatio(_, active_stake, account_id) if self.choosen == account_id => self.active_stake = active_stake.unwrap_or_default(), - Action::SetValidatorLatestClaim(era_index, account_id) if self.choosen == account_id => self.latest_era_claim = era_index, + 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::SetStakedAmountRatio(_, active_stake, account_id) + if self.choosen == account_id => + { + self.active_stake = active_stake.unwrap_or_default() + } + Action::SetValidatorLatestClaim(era_index, account_id) + if self.choosen == account_id => + { + self.latest_era_claim = era_index + } Action::SetStakedRatio(total, own, account_id) if self.choosen == account_id => { self.total_balance = total; self.own_balance = own; - }, + } _ => {} }; @@ -167,54 +191,85 @@ impl Component for CurrentValidatorDetails { 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)), + Cell::from( + Text::from(self.is_nomination_disabled.to_string()) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("Nominators".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.others_len.to_string()).alignment(Alignment::Right)), + Cell::from( + Text::from(self.others_len.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)), + Cell::from( + Text::from("Total staked".to_string()).alignment(Alignment::Left), + ), + Cell::from( + Text::from(self.prepare_u128(self.total_balance)) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("Own stake".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.own_balance)).alignment(Alignment::Right)), + Cell::from( + Text::from(self.prepare_u128(self.own_balance)) + .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)), + Cell::from( + Text::from(self.prepare_stake_imbalance()).alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("Commission".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(format!("{:.4}%", self.commission)).alignment(Alignment::Right)), + Cell::from( + Text::from(format!("{:.4}%", self.commission)) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ - Cell::from(Text::from("Points ratio".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(format!("{:.4}%", self.points_ratio)).alignment(Alignment::Right)), + 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)), + 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("Last payout".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(format!("{} days ago", self.latest_era_claim)).alignment(Alignment::Right)), + Cell::from( + Text::from("Last payout".to_string()).alignment(Alignment::Left), + ), + Cell::from( + Text::from(format!("{} days ago", self.latest_era_claim)) + .alignment(Alignment::Right), + ), ]), ], - [ - Constraint::Max(12), - Constraint::Min(0), - ], + [Constraint::Max(12), Constraint::Min(0)], ) .column_spacing(1) .highlight_style(self.palette.create_highlight_style()) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("Validator details")); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("Validator details"), + ); frame.render_widget(Clear, place); frame.render_widget(table, place); diff --git a/src/components/wallet/current_validators.rs b/src/components/wallet/current_validators.rs index 26a2958..af292d5 100644 --- a/src/components/wallet/current_validators.rs +++ b/src/components/wallet/current_validators.rs @@ -1,33 +1,29 @@ use std::fs::File; +use std::io::{BufRead, BufReader, Write}; use std::path::PathBuf; -use std::io::{Write, BufRead, BufReader}; use subxt::ext::sp_core::crypto::{AccountId32, Ss58AddressFormat, Ss58Codec}; use color_eyre::Result; use crossterm::event::{KeyCode, KeyEvent}; use ratatui::layout::{Constraint, Margin}; -use ratatui::style::{Stylize, Modifier}; +use ratatui::style::{Modifier, Stylize}; use ratatui::widgets::Clear; use ratatui::{ + layout::{Alignment, Rect}, text::{Line, Text}, - layout::{Alignment, Rect}, widgets::{ - Block, Cell, Row, Table, TableState, Scrollbar, Padding, - ScrollbarOrientation, ScrollbarState, - }, - Frame + Block, Cell, Padding, Row, Scrollbar, ScrollbarOrientation, ScrollbarState, Table, + TableState, + }, + Frame, }; -use tokio::sync::mpsc::UnboundedSender; use std::sync::mpsc::Sender; +use tokio::sync::mpsc::UnboundedSender; -use super::{PartialComponent, Component, CurrentTab}; -use crate::types::{ActionLevel, Nominations, ActionTarget, EraRewardPoints}; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, -}; +use super::{Component, CurrentTab, PartialComponent}; +use crate::types::{ActionLevel, ActionTarget, EraRewardPoints, Nominations}; +use crate::{action::Action, config::Config, palette::StylePalette}; pub struct CurrentValidators { is_active: bool, @@ -116,8 +112,8 @@ impl CurrentValidators { account_id: *account, address: AccountId32::from(*account) .to_ss58check_with_version(Ss58AddressFormat::custom(1996)), - points: 0, - disabled: true, + points: 0, + disabled: true, }); } } @@ -127,15 +123,17 @@ impl CurrentValidators { fn update_choosen_details(&self, index: usize) { if let Some(action_tx) = &self.action_tx { - let (selected_account_id, selected_points) = self.filtered_vector + let (selected_account_id, selected_points) = self + .filtered_vector .get(index) .map(|data| (data.account_id, data.points)) .unwrap_or_default(); let _ = action_tx.send(Action::SetChoosenValidator( - selected_account_id, - selected_points, - self.total_points)); + selected_account_id, + selected_points, + self.total_points, + )); } } @@ -145,21 +143,24 @@ impl CurrentValidators { 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()); + 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)); + 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 + self.filtered_vector = self + .individual .iter() .filter_map(|data| { let is_good = !is_individual || self.checked_validators.contains(&data.account_id); @@ -193,8 +194,8 @@ impl CurrentValidators { let account_id = self.filtered_vector[index].account_id; let _ = self.known_validators.insert(account_id, new_name); - let mut file = File::create(&self.known_validators_file) - .expect("file should be accessible; qed"); + let mut file = + File::create(&self.known_validators_file).expect("file should be accessible; qed"); for (account_id, name) in self.known_validators.iter() { let seed = hex::encode(account_id); @@ -246,7 +247,7 @@ impl CurrentValidators { } else { i + 1 } - }, + } None => 0, }; self.move_selected(i); @@ -267,15 +268,15 @@ impl CurrentValidators { } else { i - 1 } - }, - None => 0 + } + None => 0, }; self.move_selected(i); } fn update_era_rewards( - &mut self, - era_index: u32, + &mut self, + era_index: u32, total_points: u32, individual: &Vec, ) { @@ -294,21 +295,28 @@ impl CurrentValidators { } fn nominate_choosen(&mut self) { - if self.my_stash_id.map(|acc| acc == self.account_id).unwrap_or_default() { + 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, + ActionLevel::Error, ActionTarget::WalletLog)); } } else { if let Some(network_tx) = &self.network_tx { - let nominate_targets: Vec<[u8; 32]> = self.checked_validators + let nominate_targets: Vec<[u8; 32]> = self + .checked_validators .clone() .into_iter() .collect::>(); let _ = network_tx.send(Action::NominateTargets( - self.account_secret_seed, nominate_targets)); + self.account_secret_seed, + nominate_targets, + )); } } self.close_popup(); @@ -316,7 +324,8 @@ impl CurrentValidators { fn prepare_nomination_line(&self) -> String { let empty_nominations = Nominations::default(); - let nominations = self.my_nominations + let nominations = self + .my_nominations .get(&self.account_id) .unwrap_or(&empty_nominations); @@ -328,9 +337,9 @@ impl CurrentValidators { } else { "Active" }; - format!("Submitted at era #{} | {} ", - nominations.submitted_in, - status, + format!( + "Submitted at era #{} | {} ", + nominations.submitted_in, status, ) } } @@ -358,14 +367,22 @@ impl Component for CurrentValidators { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Wallet) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } let mut known_validators_file = config.config.data_dir; known_validators_file.push(Self::KNOWN_VALIDATORS_FILE); @@ -376,12 +393,19 @@ impl Component for CurrentValidators { fn update(&mut self, action: Action) -> Result> { match action { - 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::SetNominatorsByAccount(nominations, account_id) => self.store_nominators(nominations, account_id), + 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::SetNominatorsByAccount(nominations, account_id) => { + self.store_nominators(nominations, account_id) + } Action::SetStashAccount(account_id) => self.my_stash_id = Some(account_id), - Action::SetCurrentValidatorEraRewards(era_index, total_points, individual) => - self.update_era_rewards(era_index, total_points, &individual), + Action::SetCurrentValidatorEraRewards(era_index, total_points, individual) => { + self.update_era_rewards(era_index, total_points, &individual) + } _ => {} }; Ok(None) @@ -390,8 +414,8 @@ impl Component for CurrentValidators { fn handle_key_event(&mut self, key: KeyEvent) -> Result> { if self.is_active { match key.code { - KeyCode::Up | KeyCode::Char('k') => self.previous_row(), - KeyCode::Down | KeyCode::Char('j') => self.next_row(), + KeyCode::Up | KeyCode::Char('k') => self.previous_row(), + KeyCode::Down | KeyCode::Char('j') => self.next_row(), KeyCode::Char('g') => self.first_row(), KeyCode::Char('G') => self.last_row(), KeyCode::Char('R') => self.update_known_validator_record(), @@ -404,7 +428,7 @@ impl Component for CurrentValidators { KeyCode::Char('N') => self.nominate_choosen(), KeyCode::Enter => self.flip_validator_check(), KeyCode::Esc => self.close_popup(), - _ => {}, + _ => {} }; } Ok(None) @@ -415,7 +439,11 @@ impl Component for CurrentValidators { let (border_style, border_type) = self.palette.create_border_style(self.is_active); let [place, _] = super::nominator_layout(area); - let top_title = format!("Validators {} | Total points: {}", self.individual.len(), self.total_points); + let top_title = format!( + "Validators {} | Total points: {}", + self.individual.len(), + self.total_points + ); let bottom_title = self.prepare_nomination_line(); let table = Table::new( @@ -423,14 +451,18 @@ impl Component for CurrentValidators { .iter() .chain(&self.not_active_nominations) .map(|info| { - let is_validator_choosen = self.checked_validators.contains(&info.account_id); - let is_current_nomination = self.my_nominations + 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 points_text = Text::from(info.points.to_string()).alignment(Alignment::Right); + 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 (row_style, is_choosen_text) = if is_validator_choosen { address_text = address_text.add_modifier(Modifier::ITALIC); @@ -447,14 +479,14 @@ impl Component for CurrentValidators { points_text = points_text.add_modifier(Modifier::CROSSED_OUT); } - let default_name = self.my_stash_id - .map(|account_id| - account_id.eq(&info.account_id).then(|| "My stash") - ) + let default_name = self + .my_stash_id + .map(|account_id| account_id.eq(&info.account_id).then(|| "My stash")) .flatten() .unwrap_or("Ghostie"); - let name = self.known_validators + let name = self + .known_validators .get(&info.account_id) .cloned() .unwrap_or(default_name.to_string()); @@ -463,8 +495,9 @@ impl Component for CurrentValidators { 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), - ]).style(row_style) + Cell::from(points_text), + ]) + .style(row_style) }), [ Constraint::Length(1), @@ -473,16 +506,18 @@ impl Component for CurrentValidators { Constraint::Length(6), ], ) - .style(self.palette.create_basic_style(false)) - .highlight_style(self.palette.create_basic_style(true)) - .column_spacing(1) - .block(Block::bordered() + .style(self.palette.create_basic_style(false)) + .highlight_style(self.palette.create_basic_style(true)) + .column_spacing(1) + .block( + Block::bordered() .border_style(border_style) .border_type(border_type) .padding(Padding::right(2)) .title_style(self.palette.create_title_style(false)) .title_bottom(Line::from(bottom_title).left_aligned()) - .title_top(Line::from(top_title).right_aligned())); + .title_top(Line::from(top_title).right_aligned()), + ); let scrollbar = Scrollbar::default() .orientation(ScrollbarOrientation::VerticalRight) @@ -494,7 +529,10 @@ impl Component for CurrentValidators { frame.render_stateful_widget(table, place, &mut self.table_state); frame.render_stateful_widget( scrollbar, - place.inner(Margin { vertical: 1, horizontal: 1 }), + place.inner(Margin { + vertical: 1, + horizontal: 1, + }), &mut self.scroll_state, ); } diff --git a/src/components/wallet/event_logs.rs b/src/components/wallet/event_logs.rs index 6569b96..d78c27e 100644 --- a/src/components/wallet/event_logs.rs +++ b/src/components/wallet/event_logs.rs @@ -1,21 +1,21 @@ use color_eyre::Result; use crossterm::event::{KeyCode, KeyEvent}; use ratatui::{ - layout::{Alignment, Constraint, Margin, Rect}, - style::{Color, Style}, - text::Text, + layout::{Alignment, Constraint, Margin, Rect}, + style::{Color, Style}, + text::Text, widgets::{ - Block, Padding, Cell, Row, Scrollbar, ScrollbarOrientation, - ScrollbarState, Table, TableState, - }, - Frame + Block, Cell, Padding, Row, Scrollbar, ScrollbarOrientation, ScrollbarState, Table, + TableState, + }, + Frame, }; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ - action::Action, - config::Config, - palette::StylePalette, + action::Action, + config::Config, + palette::StylePalette, types::{ActionLevel, ActionTarget}, }; @@ -32,7 +32,7 @@ pub struct EventLogs { scroll_state: ScrollbarState, table_state: TableState, logs: std::collections::VecDeque, - palette: StylePalette + palette: StylePalette, } impl EventLogs { @@ -65,7 +65,7 @@ impl EventLogs { } else { i + 1 } - }, + } None => 0, }; self.table_state.select(Some(i)); @@ -88,8 +88,8 @@ impl EventLogs { } else { i - 1 } - }, - None => 0 + } + None => 0, }; self.table_state.select(Some(i)); self.scroll_state = self.scroll_state.position(i); @@ -112,33 +112,42 @@ impl PartialComponent for EventLogs { impl Component for EventLogs { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Wallet) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); - self.palette.with_scrollbar_style(style.get("scrollbar_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_scrollbar_style(style.get("scrollbar_style").copied()); } Ok(()) } fn handle_key_event(&mut self, key: KeyEvent) -> Result> { match key.code { - KeyCode::Up | KeyCode::Char('k') if self.is_active => self.previous_row(), - KeyCode::Down | KeyCode::Char('j') if self.is_active => self.next_row(), - KeyCode::Char('g') if self.is_active => self.first_row(), - KeyCode::Char('G') if self.is_active => self.last_row(), - _ => {}, + KeyCode::Up | KeyCode::Char('k') if self.is_active => self.previous_row(), + KeyCode::Down | KeyCode::Char('j') if self.is_active => self.next_row(), + KeyCode::Char('g') if self.is_active => self.first_row(), + KeyCode::Char('G') if self.is_active => self.last_row(), + _ => {} }; Ok(None) } fn update(&mut self, action: Action) -> Result> { match action { - Action::EventLog(message, level, target) if target == ActionTarget::WalletLog => - self.add_new_log(message, level), + Action::EventLog(message, level, target) if target == ActionTarget::WalletLog => { + self.add_new_log(message, level) + } _ => {} }; Ok(None) @@ -153,33 +162,38 @@ impl Component for EventLogs { let info_style = Style::new().fg(Color::Green); let table = Table::new( - self.logs - .iter() - .map(|log| { - let style = match log.level { - ActionLevel::Info => info_style, - ActionLevel::Warn => warn_style, - ActionLevel::Error => error_style, - }; - Row::new(vec![ - Cell::from(Text::from(log.time.format("%H:%M:%S").to_string()).style(style).alignment(Alignment::Left)), - Cell::from(Text::from(log.message.clone()).style(style).alignment(Alignment::Left)), - ]) - }), - [ - Constraint::Max(8), - Constraint::Min(0), - ], + self.logs.iter().map(|log| { + let style = match log.level { + ActionLevel::Info => info_style, + ActionLevel::Warn => warn_style, + ActionLevel::Error => error_style, + }; + Row::new(vec![ + Cell::from( + Text::from(log.time.format("%H:%M:%S").to_string()) + .style(style) + .alignment(Alignment::Left), + ), + Cell::from( + Text::from(log.message.clone()) + .style(style) + .alignment(Alignment::Left), + ), + ]) + }), + [Constraint::Max(8), Constraint::Min(0)], ) .column_spacing(1) .highlight_style(self.palette.create_highlight_style()) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .padding(Padding::right(2)) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("Action Logs")); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .padding(Padding::right(2)) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("Action Logs"), + ); let scrollbar = Scrollbar::default() .orientation(ScrollbarOrientation::VerticalRight) @@ -190,7 +204,10 @@ impl Component for EventLogs { frame.render_stateful_widget(table, place, &mut self.table_state); frame.render_stateful_widget( scrollbar, - place.inner(Margin { vertical: 1, horizontal: 1 }), + place.inner(Margin { + vertical: 1, + horizontal: 1, + }), &mut self.scroll_state, ); Ok(()) diff --git a/src/components/wallet/mod.rs b/src/components/wallet/mod.rs index c60ea1d..add2bc3 100644 --- a/src/components/wallet/mod.rs +++ b/src/components/wallet/mod.rs @@ -8,41 +8,41 @@ use ratatui::{ use std::sync::mpsc::Sender; use tokio::sync::mpsc::UnboundedSender; -mod balance; -mod transfer; -mod address_book; -mod add_account; -mod rename_account; -mod event_logs; -mod accounts; -mod overview; -mod add_address_book_record; -mod rename_address_book_record; mod account_details; -mod staking_ledger; +mod accounts; +mod add_account; +mod add_address_book_record; +mod address_book; +mod balance; mod bond_popup; -mod payee_popup; -mod current_validators; mod current_validator_details; +mod current_validators; +mod event_logs; +mod overview; +mod payee_popup; +mod rename_account; +mod rename_address_book_record; mod rename_known_validator; +mod staking_ledger; +mod transfer; -use balance::Balance; -use transfer::Transfer; -use address_book::AddressBook; -use add_account::AddAccount; -use rename_account::RenameAccount; -use event_logs::EventLogs; -use accounts::Accounts; -use overview::Overview; -use add_address_book_record::AddAddressBookRecord; -use rename_address_book_record::RenameAddressBookRecord; use account_details::AccountDetails; -use staking_ledger::StakingLedger; +use accounts::Accounts; +use add_account::AddAccount; +use add_address_book_record::AddAddressBookRecord; +use address_book::AddressBook; +use balance::Balance; use bond_popup::BondPopup; -use payee_popup::PayeePopup; -use current_validators::CurrentValidators; use current_validator_details::CurrentValidatorDetails; +use current_validators::CurrentValidators; +use event_logs::EventLogs; +use overview::Overview; +use payee_popup::PayeePopup; +use rename_account::RenameAccount; +use rename_address_book_record::RenameAddressBookRecord; use rename_known_validator::RenameKnownValidator; +use staking_ledger::StakingLedger; +use transfer::Transfer; use super::Component; use crate::{action::Action, app::Mode, config::Config}; @@ -146,61 +146,63 @@ impl Component for Wallet { } fn handle_key_event(&mut self, key: KeyEvent) -> Result> { - if !self.is_active { return Ok(None) } + if !self.is_active { + return Ok(None); + } match self.current_tab { // block the default key handle for popups - CurrentTab::AddAccount | - CurrentTab::RenameAccount | - CurrentTab::RenameAddressBookRecord | - CurrentTab::Transfer | - CurrentTab::AccountDetails | - CurrentTab::BondPopup | - CurrentTab::PayeePopup | - CurrentTab::CurrentValidatorsPopup | - CurrentTab::AddAddressBookRecord => { - for component in self.components.iter_mut() { - component.handle_key_event(key)?; - } - }, + CurrentTab::AddAccount + | CurrentTab::RenameAccount + | CurrentTab::RenameAddressBookRecord + | CurrentTab::Transfer + | CurrentTab::AccountDetails + | CurrentTab::BondPopup + | CurrentTab::PayeePopup + | CurrentTab::CurrentValidatorsPopup + | CurrentTab::AddAddressBookRecord => { + for component in self.components.iter_mut() { + component.handle_key_event(key)?; + } + } _ => match key.code { KeyCode::Esc => { self.is_active = false; self.current_tab = CurrentTab::Nothing; return Ok(Some(Action::SetActiveScreen(Mode::Menu))); - }, + } KeyCode::Char('W') => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::AddAccount; - }, + } KeyCode::Char('A') => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::AddAddressBookRecord; - }, + } KeyCode::Char('T') => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::Transfer; - }, + } KeyCode::Char('B') => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::BondPopup; - }, + } KeyCode::Char('O') => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::PayeePopup; - }, + } KeyCode::Char('N') => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::CurrentValidatorsPopup; - }, + } KeyCode::Char('l') | KeyCode::Right => self.move_right(), KeyCode::Char('h') | KeyCode::Left => self.move_left(), _ => { for component in self.components.iter_mut() { component.handle_key_event(key)?; } - }, - } + } + }, } Ok(None) } @@ -211,11 +213,11 @@ impl Component for Wallet { self.is_active = true; self.current_tab = CurrentTab::Accounts; self.previous_tab = CurrentTab::Accounts; - }, + } Action::RenameAccount(_) => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::RenameAccount; - }, + } Action::RenameAddressBookRecord(_) => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::RenameAddressBookRecord; @@ -223,11 +225,11 @@ impl Component for Wallet { Action::TransferTo(_) => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::Transfer; - }, + } Action::AccountDetailsOf(_, _) => { self.previous_tab = self.current_tab; self.current_tab = CurrentTab::AccountDetails; - }, + } Action::ClosePopup => self.current_tab = self.previous_tab, _ => {} } @@ -248,18 +250,12 @@ impl Component for Wallet { } pub fn wallet_layout(area: Rect) -> [Rect; 2] { - Layout::vertical([ - Constraint::Percentage(75), - Constraint::Percentage(25), - ]).areas(area) + Layout::vertical([Constraint::Percentage(75), Constraint::Percentage(25)]).areas(area) } pub fn bars_layout(area: Rect) -> [Rect; 2] { let [place, _] = wallet_layout(area); - Layout::horizontal([ - Constraint::Percentage(50), - Constraint::Percentage(50), - ]).areas(place) + Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]).areas(place) } pub fn account_layout(area: Rect) -> [Rect; 4] { @@ -269,14 +265,12 @@ pub fn account_layout(area: Rect) -> [Rect; 4] { Constraint::Min(0), Constraint::Max(7), Constraint::Max(6), - ]).areas(place) + ]) + .areas(place) } pub fn nominator_layout(area: Rect) -> [Rect; 2] { let v = Layout::vertical([Constraint::Max(11)]).flex(Flex::Center); let [area] = v.areas(area); - Layout::horizontal([ - Constraint::Percentage(60), - Constraint::Percentage(40), - ]).areas(area) + Layout::horizontal([Constraint::Percentage(60), Constraint::Percentage(40)]).areas(area) } diff --git a/src/components/wallet/overview.rs b/src/components/wallet/overview.rs index 935931b..8f3b16d 100644 --- a/src/components/wallet/overview.rs +++ b/src/components/wallet/overview.rs @@ -1,24 +1,20 @@ use color_eyre::Result; use ratatui::{ + layout::{Alignment, Constraint, Rect}, text::Text, - layout::{Alignment, Constraint, Rect}, - widgets::{Block, Cell, Row, Table}, - Frame + widgets::{Block, Cell, Row, Table}, + Frame, }; -use super::{Component, PartialComponent, CurrentTab}; -use crate::{ - action::Action, - config::Config, - palette::StylePalette, widgets::DotSpinner, -}; +use super::{Component, CurrentTab, PartialComponent}; +use crate::{action::Action, config::Config, palette::StylePalette, widgets::DotSpinner}; #[derive(Debug)] pub struct Overview { is_active: bool, existential_balance: Option, total_issuance: Option, - palette: StylePalette + palette: StylePalette, } impl Default for Overview { @@ -46,8 +42,8 @@ impl Overview { let value = value as f64 / 10f64.powi(18); let after = Self::DECIMALS; format!("{:.after$}{}", value, Self::TICKER) - }, - None => format!("{}{}", DotSpinner::default().to_string(), Self::TICKER) + } + None => format!("{}{}", DotSpinner::default().to_string(), Self::TICKER), } } } @@ -64,12 +60,18 @@ impl PartialComponent for Overview { impl Component for Overview { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Wallet) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); } Ok(()) } @@ -85,31 +87,35 @@ impl Component for Overview { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { let [place, _, _, _] = super::account_layout(area); - 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 table = Table::new( [ Row::new(vec![ Cell::from(Text::from("total supply: ".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.total_issuance)).alignment(Alignment::Right)), + Cell::from( + Text::from(self.prepare_u128(self.total_issuance)) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("min deposit: ".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.existential_balance)).alignment(Alignment::Right)), + Cell::from( + Text::from(self.prepare_u128(self.existential_balance)) + .alignment(Alignment::Right), + ), ]), ], - [ - Constraint::Max(15), - Constraint::Min(0), - ] + [Constraint::Max(15), Constraint::Min(0)], ) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("Overview")); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("Overview"), + ); frame.render_widget(table, place); Ok(()) diff --git a/src/components/wallet/payee_popup.rs b/src/components/wallet/payee_popup.rs index 5dd7aa9..30b706b 100644 --- a/src/components/wallet/payee_popup.rs +++ b/src/components/wallet/payee_popup.rs @@ -1,23 +1,21 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Alignment, Constraint, Flex, Layout, Position, Rect}, - text::Text, - widgets::{Block, Cell, Clear, Paragraph, Row, Table, TableState}, + layout::{Alignment, Constraint, Flex, Layout, Position, Rect}, + text::Text, + widgets::{Block, Cell, Clear, Paragraph, Row, Table, TableState}, Frame, }; -use subxt::ext::sp_core::crypto::{ - ByteArray, Ss58Codec, Ss58AddressFormat, AccountId32, -}; -use tokio::sync::mpsc::UnboundedSender; use std::sync::mpsc::Sender; +use subxt::ext::sp_core::crypto::{AccountId32, ByteArray, Ss58AddressFormat, Ss58Codec}; +use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ - action::Action, - config::Config, - palette::StylePalette, - types::{ActionLevel, ActionTarget, RewardDestination}, + action::Action, + config::Config, + palette::StylePalette, + types::{ActionLevel, ActionTarget, RewardDestination}, widgets::{Input, InputRequest}, }; @@ -36,7 +34,7 @@ pub struct PayeePopup { address: Input, possible_payee_options: &'static [(&'static str, &'static str)], current_reward_destination: RewardDestination, - palette: StylePalette + palette: StylePalette, } impl Default for PayeePopup { @@ -61,9 +59,18 @@ impl PayeePopup { address: Input::new(String::new()), current_reward_destination: Default::default(), possible_payee_options: &[ - ("Re-stake", "(pay into the stash account, increasing the amount at stake accordingly)"), - ("Stake", "(pay into the stash account, not increasing the amount at stake)"), - ("Account", "(pay into a specified account different from stash)"), + ( + "Re-stake", + "(pay into the stash account, increasing the amount at stake accordingly)", + ), + ( + "Stake", + "(pay into the stash account, not increasing the amount at stake)", + ), + ( + "Account", + "(pay into a specified account different from stash)", + ), ("None", "(refuse to receive all rewards from staking)"), ], palette: StylePalette::default(), @@ -85,7 +92,7 @@ impl PayeePopup { let address = AccountId32::from(account_id) .to_ss58check_with_version(Ss58AddressFormat::custom(1996)); (2, address) - }, + } RewardDestination::None => (3, Default::default()), _ => (0, Default::default()), }; @@ -106,13 +113,12 @@ impl PayeePopup { } else { i + 1 } - }, + } None => 0, }; self.move_to_row(i); } - fn previous_row(&mut self) { let i = match self.table_state.selected() { Some(i) => { @@ -121,18 +127,15 @@ impl PayeePopup { } else { i - 1 } - }, - None => 0 + } + None => 0, }; self.move_to_row(i); } fn log_event(&mut self, message: String, level: ActionLevel) { if let Some(action_tx) = &self.action_tx { - let _ = action_tx.send(Action::EventLog( - message, - level, - ActionTarget::WalletLog)); + let _ = action_tx.send(Action::EventLog(message, level, ActionTarget::WalletLog)); } } @@ -155,8 +158,12 @@ impl PayeePopup { Ok((account_id, format)) => { if format != Ss58AddressFormat::custom(1996) { self.log_event( - format!("provided public address for {} is not part of Casper/Ghost ecosystem", self.address.value()), - ActionLevel::Error); + format!( + "provided public address for {} is not part of Casper/Ghost ecosystem", + self.address.value() + ), + ActionLevel::Error, + ); } let seed_vec = account_id.to_raw_vec(); let mut account_id = [0u8; 32]; @@ -164,15 +171,18 @@ impl PayeePopup { self.proposed_account_id = Some(account_id); self.submit_new_payee(); - }, + } _ => { self.log_event( - format!("could not create valid account id from {}", self.address.value()), - ActionLevel::Error); + format!( + "could not create valid account id from {}", + self.address.value() + ), + ActionLevel::Error, + ); self.proposed_account_id = None; } }; - } fn submit_new_payee(&mut self) { @@ -181,7 +191,8 @@ impl PayeePopup { 0 => RewardDestination::Staked, 1 => RewardDestination::Stash, 2 => { - let account_id = self.proposed_account_id + let account_id = self + .proposed_account_id .expect("checked before in submit_new_input; qed"); RewardDestination::Account(account_id) } @@ -192,17 +203,20 @@ impl PayeePopup { if !self.is_bonded { self.log_event( "no bond detected, stake minimum bond amount first".to_string(), - ActionLevel::Warn); + ActionLevel::Warn, + ); } else if new_destination == self.current_reward_destination { self.log_event( "same destination choosen, no need for transaction".to_string(), - ActionLevel::Warn); + ActionLevel::Warn, + ); } else { if let Some(network_tx) = &self.network_tx { let _ = network_tx.send(Action::SetPayee( - self.account_secret_seed, - new_destination, - ActionTarget::WalletLog)); + self.account_secret_seed, + new_destination, + ActionTarget::WalletLog, + )); } } if let Some(action_tx) = &self.action_tx { @@ -257,12 +271,18 @@ impl Component for PayeePopup { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); - self.palette.with_highlight_style(style.get("highlight_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_highlight_style(style.get("highlight_style").copied()); } Ok(()) } @@ -276,8 +296,8 @@ impl Component for PayeePopup { KeyCode::Backspace => self.delete_char(), KeyCode::Left => self.move_cursor_left(), KeyCode::Right => self.move_cursor_right(), - KeyCode::Esc => self.trigger_address_input(), - _ => {}, + KeyCode::Esc => self.trigger_address_input(), + _ => {} }; } else { match key.code { @@ -286,7 +306,7 @@ impl Component for PayeePopup { KeyCode::Up | KeyCode::Char('k') => self.previous_row(), KeyCode::Down | KeyCode::Char('j') => self.next_row(), KeyCode::Esc => self.close_popup(), - _ => {}, + _ => {} }; } } @@ -295,10 +315,15 @@ impl Component for PayeePopup { fn update(&mut self, action: Action) -> Result> { match action { - Action::UsedAccount(account_id, secret_seed) => self.update_used_account(account_id, secret_seed), - Action::SetIsBonded(is_bonded, account_id) if self.account_id == account_id => - self.is_bonded = is_bonded, - Action::SetStakingPayee(reward_destination, account_id) if self.account_id == account_id => { + Action::UsedAccount(account_id, secret_seed) => { + self.update_used_account(account_id, secret_seed) + } + Action::SetIsBonded(is_bonded, account_id) if self.account_id == account_id => { + self.is_bonded = is_bonded + } + Action::SetStakingPayee(reward_destination, account_id) + if self.account_id == account_id => + { let destination_changed = self.current_reward_destination != reward_destination; self.current_reward_destination = reward_destination; if destination_changed || self.table_state.selected().is_none() { @@ -315,7 +340,7 @@ impl Component for PayeePopup { if self.is_active { let (border_style, border_type) = self.palette.create_popup_style(); let size = area.as_size(); - let input_area = Rect::new(size.width / 2, size.height / 2, 51, 3); + let input_area = Rect::new(size.width / 2, size.height / 2, 51, 3); let table = Table::new( self.possible_payee_options @@ -327,16 +352,18 @@ impl Component for PayeePopup { ]) }) .collect::>(), - [Constraint::Length(8), Constraint::Min(0)] + [Constraint::Length(8), Constraint::Min(0)], ) .highlight_style(self.palette.create_highlight_style()) .column_spacing(1) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_style(self.palette.create_popup_title_style()) - .title_alignment(Alignment::Right) - .title("Select reward destination")); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_style(self.palette.create_popup_title_style()) + .title_alignment(Alignment::Right) + .title("Select reward destination"), + ); let v = Layout::vertical([Constraint::Max(6)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(83)]).flex(Flex::Center); @@ -347,13 +374,14 @@ impl Component for PayeePopup { frame.render_stateful_widget(table, area, &mut self.table_state); if self.is_input_active { - let input_amount = Paragraph::new(self.address.value()) - .block(Block::bordered() + let input_amount = Paragraph::new(self.address.value()).block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title("Destination account")); + .title("Destination account"), + ); let v = Layout::vertical([Constraint::Max(8)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(51)]).flex(Flex::Center); @@ -364,8 +392,8 @@ impl Component for PayeePopup { frame.render_widget(input_amount, input_area); frame.set_cursor_position(Position::new( - input_area.x + self.address.cursor() as u16 + 1, - input_area.y + 1 + input_area.x + self.address.cursor() as u16 + 1, + input_area.y + 1, )); } } diff --git a/src/components/wallet/rename_account.rs b/src/components/wallet/rename_account.rs index a821092..411c7ca 100644 --- a/src/components/wallet/rename_account.rs +++ b/src/components/wallet/rename_account.rs @@ -1,18 +1,18 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Position, Alignment, Constraint, Flex, Layout, Rect}, - widgets::{Block, Clear, Paragraph}, - Frame + layout::{Alignment, Constraint, Flex, Layout, Position, Rect}, + widgets::{Block, Clear, Paragraph}, + Frame, }; use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ + action::Action, + config::Config, + palette::StylePalette, widgets::{Input, InputRequest}, - action::Action, - config::Config, - palette::StylePalette, }; #[derive(Debug)] @@ -21,7 +21,7 @@ pub struct RenameAccount { action_tx: Option>, old_name: String, name: Input, - palette: StylePalette + palette: StylePalette, } impl Default for RenameAccount { @@ -50,8 +50,7 @@ impl RenameAccount { fn submit_message(&mut self) { if let Some(action_tx) = &self.action_tx { - let _ = action_tx.send(Action::UpdateAccountName( - self.name.value().to_string())); + let _ = action_tx.send(Action::UpdateAccountName(self.name.value().to_string())); let _ = action_tx.send(Action::ClosePopup); } } @@ -94,11 +93,16 @@ impl Component for RenameAccount { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -119,8 +123,8 @@ impl Component for RenameAccount { KeyCode::Backspace => self.delete_char(), KeyCode::Left => self.move_cursor_left(), KeyCode::Right => self.move_cursor_right(), - KeyCode::Esc => self.close_popup(), - _ => {}, + KeyCode::Esc => self.close_popup(), + _ => {} }; } Ok(None) @@ -129,13 +133,14 @@ impl Component for RenameAccount { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { if self.is_active { let (border_style, border_type) = self.palette.create_popup_style(); - let input = Paragraph::new(self.name.value()) - .block(Block::bordered() + let input = Paragraph::new(self.name.value()).block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title(format!("New name for '{}'", self.old_name))); + .title(format!("New name for '{}'", self.old_name)), + ); let v = Layout::vertical([Constraint::Max(3)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(50)]).flex(Flex::Center); let [area] = v.areas(area); @@ -144,8 +149,8 @@ impl Component for RenameAccount { frame.render_widget(Clear, area); frame.render_widget(input, area); frame.set_cursor_position(Position::new( - area.x + self.name.cursor() as u16 + 1, - area.y + 1 + area.x + self.name.cursor() as u16 + 1, + area.y + 1, )); } Ok(()) diff --git a/src/components/wallet/rename_address_book_record.rs b/src/components/wallet/rename_address_book_record.rs index 8d7295a..fd6ffb6 100644 --- a/src/components/wallet/rename_address_book_record.rs +++ b/src/components/wallet/rename_address_book_record.rs @@ -1,18 +1,18 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Position, Alignment, Constraint, Flex, Layout, Rect}, - widgets::{Block, Clear, Paragraph}, - Frame + layout::{Alignment, Constraint, Flex, Layout, Position, Rect}, + widgets::{Block, Clear, Paragraph}, + Frame, }; use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ + action::Action, + config::Config, + palette::StylePalette, widgets::{Input, InputRequest}, - action::Action, - config::Config, - palette::StylePalette, }; #[derive(Debug)] @@ -21,7 +21,7 @@ pub struct RenameAddressBookRecord { action_tx: Option>, old_name: String, name: Input, - palette: StylePalette + palette: StylePalette, } impl Default for RenameAddressBookRecord { @@ -51,7 +51,8 @@ impl RenameAddressBookRecord { fn submit_message(&mut self) { if let Some(action_tx) = &self.action_tx { let _ = action_tx.send(Action::UpdateAddressBookRecord( - self.name.value().to_string())); + self.name.value().to_string(), + )); let _ = action_tx.send(Action::ClosePopup); } } @@ -94,11 +95,16 @@ impl Component for RenameAddressBookRecord { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -119,8 +125,8 @@ impl Component for RenameAddressBookRecord { KeyCode::Backspace => self.delete_char(), KeyCode::Left => self.move_cursor_left(), KeyCode::Right => self.move_cursor_right(), - KeyCode::Esc => self.close_popup(), - _ => {}, + KeyCode::Esc => self.close_popup(), + _ => {} }; } Ok(None) @@ -129,13 +135,14 @@ impl Component for RenameAddressBookRecord { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { if self.is_active { let (border_style, border_type) = self.palette.create_popup_style(); - let input = Paragraph::new(self.name.value()) - .block(Block::bordered() + let input = Paragraph::new(self.name.value()).block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title(format!("New name for '{}'", self.old_name))); + .title(format!("New name for '{}'", self.old_name)), + ); let v = Layout::vertical([Constraint::Max(3)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(50)]).flex(Flex::Center); let [area] = v.areas(area); @@ -144,8 +151,8 @@ impl Component for RenameAddressBookRecord { frame.render_widget(Clear, area); frame.render_widget(input, area); frame.set_cursor_position(Position::new( - area.x + self.name.cursor() as u16 + 1, - area.y + 1 + area.x + self.name.cursor() as u16 + 1, + area.y + 1, )); } Ok(()) diff --git a/src/components/wallet/rename_known_validator.rs b/src/components/wallet/rename_known_validator.rs index c21de1c..609fdd3 100644 --- a/src/components/wallet/rename_known_validator.rs +++ b/src/components/wallet/rename_known_validator.rs @@ -1,18 +1,18 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use color_eyre::Result; +use crossterm::event::{KeyCode, KeyEvent, KeyEventKind}; use ratatui::{ - layout::{Position, Alignment, Constraint, Flex, Layout, Rect}, - widgets::{Block, Clear, Paragraph}, - Frame + layout::{Alignment, Constraint, Flex, Layout, Position, Rect}, + widgets::{Block, Clear, Paragraph}, + Frame, }; use tokio::sync::mpsc::UnboundedSender; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ + action::Action, + config::Config, + palette::StylePalette, widgets::{Input, InputRequest}, - action::Action, - config::Config, - palette::StylePalette, }; #[derive(Debug)] @@ -20,7 +20,7 @@ pub struct RenameKnownValidator { is_active: bool, action_tx: Option>, name: Input, - palette: StylePalette + palette: StylePalette, } impl Default for RenameKnownValidator { @@ -43,11 +43,10 @@ impl RenameKnownValidator { self.is_active = false; self.name = Input::new(String::new()); } - + fn submit_message(&mut self) { if let Some(action_tx) = &self.action_tx { - let _ = action_tx.send(Action::UpdateKnownValidator( - self.name.value().to_string())); + let _ = action_tx.send(Action::UpdateKnownValidator(self.name.value().to_string())); } self.close_popup(); } @@ -70,7 +69,7 @@ impl RenameKnownValidator { } impl PartialComponent for RenameKnownValidator { - fn set_active(&mut self, _current_tab: CurrentTab) { } + fn set_active(&mut self, _current_tab: CurrentTab) {} } impl Component for RenameKnownValidator { @@ -89,11 +88,16 @@ impl Component for RenameKnownValidator { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -106,8 +110,8 @@ impl Component for RenameKnownValidator { KeyCode::Backspace => self.delete_char(), KeyCode::Left => self.move_cursor_left(), KeyCode::Right => self.move_cursor_right(), - KeyCode::Esc => self.close_popup(), - _ => {}, + KeyCode::Esc => self.close_popup(), + _ => {} }; } Ok(None) @@ -116,16 +120,17 @@ impl Component for RenameKnownValidator { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { if self.is_active { let size = area.as_size(); - let area = Rect::new(size.width / 2, size.height / 2, 51, 3); + let area = Rect::new(size.width / 2, size.height / 2, 51, 3); let (border_style, border_type) = self.palette.create_popup_style(); - let input = Paragraph::new(self.name.value()) - .block(Block::bordered() + let input = Paragraph::new(self.name.value()).block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title("Know validator name")); + .title("Know validator name"), + ); let v = Layout::vertical([Constraint::Max(3)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Max(50)]).flex(Flex::Center); let [area] = v.areas(area); @@ -134,8 +139,8 @@ impl Component for RenameKnownValidator { frame.render_widget(Clear, area); frame.render_widget(input, area); frame.set_cursor_position(Position::new( - area.x + self.name.cursor() as u16 + 1, - area.y + 1 + area.x + self.name.cursor() as u16 + 1, + area.y + 1, )); } Ok(()) diff --git a/src/components/wallet/staking_ledger.rs b/src/components/wallet/staking_ledger.rs index c287798..99c3cf5 100644 --- a/src/components/wallet/staking_ledger.rs +++ b/src/components/wallet/staking_ledger.rs @@ -1,17 +1,17 @@ use color_eyre::Result; use ratatui::{ + layout::{Alignment, Constraint, Rect}, text::Text, - layout::{Alignment, Constraint, Rect}, - widgets::{Block, Cell, Row, Table}, - Frame + widgets::{Block, Cell, Row, Table}, + Frame, }; -use subxt::ext::sp_core::crypto::{Ss58Codec, Ss58AddressFormat, AccountId32}; use std::sync::mpsc::Sender; +use subxt::ext::sp_core::crypto::{AccountId32, Ss58AddressFormat, Ss58Codec}; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ - action::Action, config::Config, palette::StylePalette, - types::RewardDestination, widgets::DotSpinner, + action::Action, config::Config, palette::StylePalette, types::RewardDestination, + widgets::DotSpinner, }; #[derive(Debug)] @@ -23,7 +23,7 @@ pub struct StakingLedger { total_staked: Option, active_staked: Option, reward_destination: RewardDestination, - palette: StylePalette + palette: StylePalette, } impl Default for StakingLedger { @@ -64,8 +64,8 @@ impl StakingLedger { let value = value as f64 / 10f64.powi(18); let after = Self::DECIMALS; format!("{:.after$}{}", value, Self::TICKER) - }, - None => format!("{}{}", DotSpinner::default().to_string(), Self::TICKER) + } + None => format!("{}{}", DotSpinner::default().to_string(), Self::TICKER), } } @@ -80,7 +80,7 @@ impl StakingLedger { .to_ss58check_with_version(Ss58AddressFormat::custom(1996)); let tail = address.len().saturating_sub(5); format!("{}..{}", &address[..5], &address[tail..]) - }, + } } } @@ -110,12 +110,18 @@ impl Component for StakingLedger { fn register_config_handler(&mut self, config: Config) -> Result<()> { if let Some(style) = config.styles.get(&crate::app::Mode::Wallet) { - self.palette.with_normal_style(style.get("normal_style").copied()); - self.palette.with_hover_style(style.get("hover_style").copied()); - self.palette.with_normal_border_style(style.get("normal_border_style").copied()); - self.palette.with_hover_border_style(style.get("hover_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_hover_title_style(style.get("hover_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_hover_style(style.get("hover_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_hover_border_style(style.get("hover_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_hover_title_style(style.get("hover_title_style").copied()); } Ok(()) } @@ -123,14 +129,20 @@ impl Component for StakingLedger { fn update(&mut self, action: Action) -> Result> { match action { Action::UsedAccount(account_id, _) => self.set_used_account_id(account_id), - Action::SetIsBonded(is_bonded, account_id) if self.account_id == account_id => - self.is_bonded = is_bonded, - Action::SetStakingPayee(reward_destination, account_id) if self.account_id == account_id => - self.reward_destination = reward_destination, - Action::SetStakedAmountRatio(total, active, account_id) if self.account_id == account_id => { + Action::SetIsBonded(is_bonded, account_id) if self.account_id == account_id => { + self.is_bonded = is_bonded + } + Action::SetStakingPayee(reward_destination, account_id) + if self.account_id == account_id => + { + self.reward_destination = reward_destination + } + Action::SetStakedAmountRatio(total, active, account_id) + if self.account_id == account_id => + { self.total_staked = total; self.active_staked = active; - }, + } _ => {} }; Ok(None) @@ -138,8 +150,7 @@ impl Component for StakingLedger { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { let [_, _, _, place] = super::account_layout(area); - 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 table = Table::new( [ @@ -149,28 +160,35 @@ impl Component for StakingLedger { ]), Row::new(vec![ Cell::from(Text::from("destination:".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.get_reward_destination()).alignment(Alignment::Right)), + Cell::from( + Text::from(self.get_reward_destination()).alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("total:".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.total_staked)).alignment(Alignment::Right)) + Cell::from( + Text::from(self.prepare_u128(self.total_staked)) + .alignment(Alignment::Right), + ), ]), Row::new(vec![ Cell::from(Text::from("active:".to_string()).alignment(Alignment::Left)), - Cell::from(Text::from(self.prepare_u128(self.active_staked)).alignment(Alignment::Right)), + Cell::from( + Text::from(self.prepare_u128(self.active_staked)) + .alignment(Alignment::Right), + ), ]), ], - [ - Constraint::Max(12), - Constraint::Min(14), - ] + [Constraint::Max(12), Constraint::Min(14)], ) - .block(Block::bordered() - .border_style(border_style) - .border_type(border_type) - .title_alignment(Alignment::Right) - .title_style(self.palette.create_title_style(false)) - .title("Nomination stake")); + .block( + Block::bordered() + .border_style(border_style) + .border_type(border_type) + .title_alignment(Alignment::Right) + .title_style(self.palette.create_title_style(false)) + .title("Nomination stake"), + ); frame.render_widget(table, place); Ok(()) diff --git a/src/components/wallet/transfer.rs b/src/components/wallet/transfer.rs index 086c1a4..32c2340 100644 --- a/src/components/wallet/transfer.rs +++ b/src/components/wallet/transfer.rs @@ -5,19 +5,17 @@ use ratatui::{ widgets::{Block, Clear, Paragraph}, Frame, }; -use tokio::sync::mpsc::UnboundedSender; use std::sync::mpsc::Sender; +use tokio::sync::mpsc::UnboundedSender; -use subxt::ext::sp_core::crypto::{ - ByteArray, Ss58Codec, Ss58AddressFormat, AccountId32, -}; +use subxt::ext::sp_core::crypto::{AccountId32, ByteArray, Ss58AddressFormat, Ss58Codec}; -use super::{Component, PartialComponent, CurrentTab}; +use super::{Component, CurrentTab, PartialComponent}; use crate::{ - action::Action, - config::Config, - palette::StylePalette, - types::{ActionLevel, ActionTarget}, + action::Action, + config::Config, + palette::StylePalette, + types::{ActionLevel, ActionTarget}, widgets::{Input, InputRequest}, }; @@ -68,49 +66,58 @@ impl Transfer { fn log_event(&mut self, message: String, level: ActionLevel) { if let Some(action_tx) = &self.action_tx { - let _ = action_tx.send( - Action::EventLog(message, level, ActionTarget::WalletLog)); + let _ = action_tx.send(Action::EventLog(message, level, ActionTarget::WalletLog)); } } fn submit_message(&mut self) { match self.receiver_or_amount { - ReceiverOrAmount::Receiver => - self.receiver_or_amount = ReceiverOrAmount::Amount, - ReceiverOrAmount::Amount => if let Some(network_tx) = &self.network_tx { - match AccountId32::from_ss58check_with_version(self.receiver.value()) { - Ok((_account_id, format)) if format != Ss58AddressFormat::custom(1996) => { - self.log_event( + ReceiverOrAmount::Receiver => self.receiver_or_amount = ReceiverOrAmount::Amount, + ReceiverOrAmount::Amount => { + if let Some(network_tx) = &self.network_tx { + match AccountId32::from_ss58check_with_version(self.receiver.value()) { + Ok((_account_id, format)) if format != Ss58AddressFormat::custom(1996) => { + self.log_event( format!("provided public address for {} is not part of Casper/Ghost ecosystem", self.receiver.value()), ActionLevel::Error); - }, - Ok((account_id, format)) if format == Ss58AddressFormat::custom(1996) => { - let seed_vec = account_id.to_raw_vec(); - let mut account_id = [0u8; 32]; - account_id.copy_from_slice(&seed_vec); - - let str_amount = self.amount.value(); - let str_amount = if str_amount.starts_with('.') { - &format!("0{}", str_amount)[..] - } else { - str_amount - }; - match str_amount.parse::() { - Ok(value) => { - let amount = (value * 1_000_000_000_000_000_000.0) as u128; - let _ = network_tx.send(Action::TransferBalance( - self.sender.clone(), account_id, amount)); - if let Some(action_tx) = &self.action_tx { - let _ = action_tx.send(Action::ClosePopup); - } - }, - Err(err) => self.log_event( - format!("invalid amount, error: {err}"), ActionLevel::Error), } - }, - _ => self.log_event( - format!("could not create valid account id from {}", self.receiver.value()), - ActionLevel::Error), + Ok((account_id, format)) if format == Ss58AddressFormat::custom(1996) => { + let seed_vec = account_id.to_raw_vec(); + let mut account_id = [0u8; 32]; + account_id.copy_from_slice(&seed_vec); + + let str_amount = self.amount.value(); + let str_amount = if str_amount.starts_with('.') { + &format!("0{}", str_amount)[..] + } else { + str_amount + }; + match str_amount.parse::() { + Ok(value) => { + let amount = (value * 1_000_000_000_000_000_000.0) as u128; + let _ = network_tx.send(Action::TransferBalance( + self.sender.clone(), + account_id, + amount, + )); + if let Some(action_tx) = &self.action_tx { + let _ = action_tx.send(Action::ClosePopup); + } + } + Err(err) => self.log_event( + format!("invalid amount, error: {err}"), + ActionLevel::Error, + ), + } + } + _ => self.log_event( + format!( + "could not create valid account id from {}", + self.receiver.value() + ), + ActionLevel::Error, + ), + } } } } @@ -120,7 +127,7 @@ impl Transfer { match self.receiver_or_amount { ReceiverOrAmount::Receiver => { let _ = self.receiver.handle(InputRequest::InsertChar(new_char)); - }, + } ReceiverOrAmount::Amount => { let is_separator_needed = !self.amount.value().contains('.') && new_char == '.'; if new_char.is_digit(10) || is_separator_needed { @@ -134,7 +141,7 @@ impl Transfer { match self.receiver_or_amount { ReceiverOrAmount::Receiver => { let _ = self.receiver.handle(InputRequest::DeletePrevChar); - }, + } ReceiverOrAmount::Amount => { let _ = self.amount.handle(InputRequest::DeletePrevChar); } @@ -145,7 +152,7 @@ impl Transfer { match self.receiver_or_amount { ReceiverOrAmount::Receiver => { let _ = self.receiver.handle(InputRequest::GoToNextChar); - }, + } ReceiverOrAmount::Amount => { let _ = self.amount.handle(InputRequest::GoToNextChar); } @@ -156,7 +163,7 @@ impl Transfer { match self.receiver_or_amount { ReceiverOrAmount::Receiver => { let _ = self.receiver.handle(InputRequest::GoToPrevChar); - }, + } ReceiverOrAmount::Amount => { let _ = self.amount.handle(InputRequest::GoToPrevChar); } @@ -175,12 +182,11 @@ impl PartialComponent for Transfer { self.amount = Input::new(String::new()); self.receiver_or_amount = ReceiverOrAmount::Receiver; } - }, + } }; } } - impl Component for Transfer { fn register_network_handler(&mut self, tx: Sender) -> Result<()> { self.network_tx = Some(tx); @@ -194,11 +200,16 @@ impl Component for Transfer { fn register_config_handler(&mut self, config: Config) -> Result<()> { 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_border_style(style.get("normal_border_style").copied()); - self.palette.with_normal_title_style(style.get("normal_title_style").copied()); - self.palette.with_popup_style(style.get("popup_style").copied()); - self.palette.with_popup_title_style(style.get("popup_title_style").copied()); + self.palette + .with_normal_style(style.get("normal_style").copied()); + self.palette + .with_normal_border_style(style.get("normal_border_style").copied()); + self.palette + .with_normal_title_style(style.get("normal_title_style").copied()); + self.palette + .with_popup_style(style.get("popup_style").copied()); + self.palette + .with_popup_title_style(style.get("popup_title_style").copied()); } Ok(()) } @@ -213,8 +224,8 @@ impl Component for Transfer { KeyCode::Backspace => self.delete_char(), KeyCode::Left => self.move_cursor_left(), KeyCode::Right => self.move_cursor_right(), - KeyCode::Esc => self.close_popup(), - _ => {}, + KeyCode::Esc => self.close_popup(), + _ => {} }; } Ok(None) @@ -235,25 +246,27 @@ impl Component for Transfer { fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { if self.is_active { let size = area.as_size(); - let receiver_area = Rect::new(size.width / 2, size.height / 2, 51, 3); - let amount_area = Rect::new(size.width / 2, size.height / 2 + 3, 51, 3); + let receiver_area = Rect::new(size.width / 2, size.height / 2, 51, 3); + let amount_area = Rect::new(size.width / 2, size.height / 2 + 3, 51, 3); let (border_style, border_type) = self.palette.create_popup_style(); - let input_receiver = Paragraph::new(self.receiver.value()) - .block(Block::bordered() + let input_receiver = Paragraph::new(self.receiver.value()).block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title("Receiver")); + .title("Receiver"), + ); - let input_amount = Paragraph::new(self.amount.value()) - .block(Block::bordered() + let input_amount = Paragraph::new(self.amount.value()).block( + Block::bordered() .border_style(border_style) .border_type(border_type) .title_style(self.palette.create_popup_title_style()) .title_alignment(Alignment::Right) - .title("Amount to send")); + .title("Amount to send"), + ); let v = Layout::vertical([Constraint::Length(3)]).flex(Flex::Center); let h = Layout::horizontal([Constraint::Length(51)]).flex(Flex::Center); @@ -271,14 +284,14 @@ impl Component for Transfer { match self.receiver_or_amount { ReceiverOrAmount::Receiver => { frame.set_cursor_position(Position::new( - receiver_area.x + self.receiver.cursor() as u16 + 1, - receiver_area.y + 1 + receiver_area.x + self.receiver.cursor() as u16 + 1, + receiver_area.y + 1, )); - }, + } ReceiverOrAmount::Amount => { frame.set_cursor_position(Position::new( - amount_area.x + self.amount.cursor() as u16 + 1, - amount_area.y + 1 + amount_area.x + self.amount.cursor() as u16 + 1, + amount_area.y + 1, )); } } diff --git a/src/config.rs b/src/config.rs index 8c8b77e..4f6009d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -36,7 +36,7 @@ lazy_static::lazy_static! { pub static ref PROJECT_NAME: String = env!("CARGO_CRATE_NAME") .to_uppercase() .to_string(); - pub static ref DATA_FOLDER: Option = + pub static ref DATA_FOLDER: Option = env::var(format!("{}_DATA", PROJECT_NAME.clone())) .ok() .map(PathBuf::from); @@ -93,9 +93,7 @@ impl Config { for (mode, default_styles) in default_config.styles.iter() { let user_styles = cfg.styles.entry(*mode).or_default(); for (style_key, style) in default_styles.iter() { - user_styles - .entry(style_key.clone()) - .or_insert(*style); + user_styles.entry(style_key.clone()).or_insert(*style); } } @@ -132,7 +130,8 @@ pub struct KeyBindings(pub HashMap, Action>>); impl<'de> Deserialize<'de> for KeyBindings { fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de>, + where + D: Deserializer<'de>, { let parsed_map = HashMap::>::deserialize(deserializer)?; @@ -200,7 +199,7 @@ fn parse_key_code_with_modifiers( "backtab" => { modifiers.insert(KeyModifiers::SHIFT); KeyCode::BackTab - }, + } "backspace" => KeyCode::Backspace, "delete" => KeyCode::Delete, "insert" => KeyCode::Insert, @@ -253,12 +252,12 @@ pub fn key_event_to_string(key_event: &KeyEvent) -> String { KeyCode::F(c) => { char = format!("f({c})"); &char - }, + } KeyCode::Char(' ') => "space", KeyCode::Char(c) => { char = c.to_string(); &char - }, + } KeyCode::Esc => "esc", KeyCode::Null => "", KeyCode::CapsLock => "", @@ -327,7 +326,8 @@ pub struct Styles(pub HashMap>); impl<'de> Deserialize<'de> for Styles { fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de> + where + D: Deserializer<'de>, { let parsed_map = HashMap::>::deserialize(deserializer)?; @@ -347,7 +347,7 @@ impl<'de> Deserialize<'de> for Styles { } pub fn parse_style(line: &str) -> Style { - let (foreground, background) = + let (foreground, background) = line.split_at(line.to_lowercase().find("on ").unwrap_or(line.len())); let foreground = process_color_string(foreground); let background = process_color_string(&background.replace("on ", "")); @@ -417,7 +417,7 @@ fn parse_color(s: &str) -> Option { let red = (s.as_bytes()[3] as char).to_digit(10).unwrap_or_default() as u8; let green = (s.as_bytes()[4] as char).to_digit(10).unwrap_or_default() as u8; let blue = (s.as_bytes()[5] as char).to_digit(10).unwrap_or_default() as u8; - + let c = 16 + red * 36 + green * 6 + blue; Some(Color::Indexed(c)) } else if s == "bold black" { diff --git a/src/errors.rs b/src/errors.rs index eb041d3..ceabf39 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -6,8 +6,8 @@ use tracing::error; pub fn init() -> Result<()> { let (_panic_hook, eyre_hook) = color_eyre::config::HookBuilder::default() .panic_section(format!( - "This is a bug. Consider reporting it at {}", - env!("CARGO_PKG_REPOSITORY") + "This is a bug. Consider reporting it at {}", + env!("CARGO_PKG_REPOSITORY") )) .capture_span_trace_by_default(false) .display_location_section(false) diff --git a/src/logging.rs b/src/logging.rs index 4fed622..99670bd 100644 --- a/src/logging.rs +++ b/src/logging.rs @@ -16,8 +16,7 @@ pub fn init() -> Result<()> { let log_path = directory.join(LOG_FILE.clone()); let log_file = std::fs::File::create(log_path)?; - let env_filter = EnvFilter::builder() - .with_default_directive(tracing::Level::INFO.into()); + let env_filter = EnvFilter::builder().with_default_directive(tracing::Level::INFO.into()); let env_filter = env_filter .try_from_env() .or_else(|_| env_filter.with_env_var(LOG_ENV.clone()).from_env())?; diff --git a/src/main.rs b/src/main.rs index 1a200f0..a2b8a1d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,24 +1,21 @@ use clap::Parser; use color_eyre::Result; -use subxt::{ - OnlineClient, - backend::rpc::RpcClient, -}; +use subxt::{backend::rpc::RpcClient, OnlineClient}; -mod modes; mod action; mod app; +mod casper; mod cli; mod components; mod config; mod errors; mod logging; -mod tui; +mod modes; mod network; -mod widgets; -mod types; mod palette; -mod casper; +mod tui; +mod types; +mod widgets; use casper::{CasperAccountId, CasperConfig}; @@ -27,7 +24,7 @@ pub mod casper_network {} #[tokio::main] async fn start_tokio_action_loop( - io_rx: std::sync::mpsc::Receiver, + io_rx: std::sync::mpsc::Receiver, network: &mut network::Network, ) { while let Ok(io_event) = io_rx.recv() { @@ -62,11 +59,7 @@ async fn main() -> Result<()> { let cloned_action_tx = action_tx.clone(); std::thread::spawn(move || { - let mut network = network::Network::new( - cloned_action_tx, - online_client, - rpc_client, - ); + let mut network = network::Network::new(cloned_action_tx, online_client, rpc_client); start_tokio_action_loop(sync_io_rx, &mut network); }); @@ -84,11 +77,8 @@ async fn main() -> Result<()> { let cloned_action_tx = action_tx.clone(); let cloned_sync_tx = sync_io_tx.clone(); std::thread::spawn(move || { - let mut subscription = network::BestSubscription::new( - cloned_action_tx, - cloned_sync_tx, - best_blocks_sub, - ); + let mut subscription = + network::BestSubscription::new(cloned_action_tx, cloned_sync_tx, best_blocks_sub); start_tokio_best_subscription(&mut subscription); }); diff --git a/src/modes.rs b/src/modes.rs index 49335e7..17fad1d 100644 --- a/src/modes.rs +++ b/src/modes.rs @@ -1,5 +1,5 @@ use ratatui::layout::Constraint; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Mode { @@ -19,7 +19,7 @@ impl Default for Mode { impl Mode { const MENU_DATA_TITLE: &str = "Help for navigation menu "; - const MENU_DATA_HEADERS: &[&str] = &["Hot Key", "Target", "Description"]; + const MENU_DATA_HEADERS: &[&str] = &["Hot Key", "Target", "Description"]; const MENU_DATA_CONSTRAINTS: &[Constraint] = &[Constraint::Length(10), Constraint::Min(0)]; const MENU_DATA_ROWS: &[&[&str]] = &[ &["(↑) | k", "Select side menu item above"], diff --git a/src/network/legacy_rpc_calls.rs b/src/network/legacy_rpc_calls.rs index 9204e5f..7f640d1 100644 --- a/src/network/legacy_rpc_calls.rs +++ b/src/network/legacy_rpc_calls.rs @@ -1,18 +1,22 @@ -use tokio::sync::mpsc::UnboundedSender; +use codec::{Decode, Encode}; use color_eyre::Result; -use subxt::{backend::{legacy::rpc_methods::SystemHealth, rpc::RpcClient}, rpc_params}; -use codec::{Encode, Decode}; +use subxt::{ + backend::{legacy::rpc_methods::SystemHealth, rpc::RpcClient}, + rpc_params, +}; +use tokio::sync::mpsc::UnboundedSender; -use crate::{action::Action, network::miscellaneous::get_slow_clap_storage_key, types::{ActionLevel, ActionTarget, BlockRange, PeerInformation}}; +use crate::{ + action::Action, + network::miscellaneous::get_slow_clap_storage_key, + types::{ActionLevel, ActionTarget, BlockRange, PeerInformation}, +}; pub async fn get_node_name( action_tx: &UnboundedSender, rpc_client: &RpcClient, ) -> Result<()> { - let maybe_node_name = rpc_client - .request("system_name", rpc_params![]) - .await - .ok(); + let maybe_node_name = rpc_client.request("system_name", rpc_params![]).await.ok(); action_tx.send(Action::SetNodeName(maybe_node_name))?; Ok(()) } @@ -25,15 +29,18 @@ pub async fn get_system_health( .request("system_health", rpc_params![]) .await .ok() - .map_or((None, false, false), |health: SystemHealth| ( + .map_or((None, false, false), |health: SystemHealth| { + ( Some(health.peers), health.is_syncing, health.should_have_peers, - )); + ) + }); action_tx.send(Action::SetSystemHealth( - maybe_peers, - is_syncing, - should_have_peers))?; + maybe_peers, + is_syncing, + should_have_peers, + ))?; Ok(()) } @@ -42,10 +49,7 @@ pub async fn get_genesis_hash( rpc_client: &RpcClient, ) -> Result<()> { let params = rpc_params![0u32]; - let maybe_genesis_hash = rpc_client - .request("chain_getBlockHash", params) - .await - .ok(); + let maybe_genesis_hash = rpc_client.request("chain_getBlockHash", params).await.ok(); action_tx.send(Action::SetGenesisHash(maybe_genesis_hash))?; Ok(()) } @@ -54,10 +58,7 @@ pub async fn get_chain_name( action_tx: &UnboundedSender, rpc_client: &RpcClient, ) -> Result<()> { - let maybe_chain_name = rpc_client - .request("system_chain", rpc_params![]) - .await - .ok(); + let maybe_chain_name = rpc_client.request("system_chain", rpc_params![]).await.ok(); action_tx.send(Action::SetChainName(maybe_chain_name))?; Ok(()) } @@ -137,7 +138,7 @@ pub async fn rotate_keys( pub async fn get_block_range( action_tx: &UnboundedSender, rpc_client: &RpcClient, - chain_id: u64 + chain_id: u64, ) -> Result<()> { let chain_id_encoded = chain_id.encode(); let block_range_key_raw = get_slow_clap_storage_key(b"block-", &chain_id_encoded); @@ -146,7 +147,10 @@ pub async fn get_block_range( block_range_key.push_str(&format!("{:02x}", byte)); } let block_range: BlockRange = rpc_client - .request("offchain_localStorageGet", rpc_params!["PERSISTENT", block_range_key]) + .request( + "offchain_localStorageGet", + rpc_params!["PERSISTENT", block_range_key], + ) .await .ok() .map(|hex_string: String| { @@ -154,7 +158,10 @@ pub async fn get_block_range( let mut cursor = &bytes[..]; let from_block: u64 = u64::decode(&mut cursor).expect("first valid"); let to_block: u64 = u64::decode(&mut cursor).expect("second valid"); - BlockRange { from_block, to_block } + BlockRange { + from_block, + to_block, + } }) .unwrap_or_default(); @@ -166,7 +173,7 @@ pub async fn nullify_blocks( action_tx: &UnboundedSender, rpc_client: &RpcClient, chain_id: u64, - new_block: u64 + new_block: u64, ) -> Result<()> { let chain_id_encoded = chain_id.encode(); let block_range_key_raw = get_slow_clap_storage_key(b"block-", &chain_id_encoded); @@ -182,18 +189,21 @@ pub async fn nullify_blocks( } match rpc_client - .request::<()>("offchain_localStorageSet", rpc_params!["PERSISTENT", block_range_key, zeroes_bytes]) + .request::<()>( + "offchain_localStorageSet", + rpc_params!["PERSISTENT", block_range_key, zeroes_bytes], + ) .await { Ok(_) => action_tx.send(Action::EventLog( - format!("Blocks changed for chain id #{:?}", chain_id), - ActionLevel::Info, - ActionTarget::ValidatorLog, + format!("Blocks changed for chain id #{:?}", chain_id), + ActionLevel::Info, + ActionTarget::ValidatorLog, ))?, Err(err) => action_tx.send(Action::EventLog( - format!("Block changing failed: {:?}", err), - ActionLevel::Error, - ActionTarget::ValidatorLog, + format!("Block changing failed: {:?}", err), + ActionLevel::Error, + ActionTarget::ValidatorLog, ))?, }; @@ -213,7 +223,10 @@ pub async fn get_stored_rpc_endpoints( } let stored_rpc_endpoints: String = rpc_client - .request("offchain_localStorageGet", rpc_params!["PERSISTENT", endpoint_key]) + .request( + "offchain_localStorageGet", + rpc_params!["PERSISTENT", endpoint_key], + ) .await .ok() .unwrap_or_default(); @@ -249,7 +262,11 @@ pub async fn set_stored_rpc_endpoints( encoded_endpoints.push_str(&format!("{:02x}", byte)); } - match rpc_client.request::<()>("offchain_localStorageSet", rpc_params!["PERSISTENT", endpoint_key, encoded_endpoints]) + match rpc_client + .request::<()>( + "offchain_localStorageSet", + rpc_params!["PERSISTENT", endpoint_key, encoded_endpoints], + ) .await { Ok(_) => { @@ -261,9 +278,9 @@ pub async fn set_stored_rpc_endpoints( get_stored_rpc_endpoints(action_tx, rpc_client, chain_id).await?; } Err(err) => action_tx.send(Action::EventLog( - format!("RPC endpoints update failed: {:?}", err), - ActionLevel::Error, - ActionTarget::ValidatorLog, + format!("RPC endpoints update failed: {:?}", err), + ActionLevel::Error, + ActionTarget::ValidatorLog, ))?, }; diff --git a/src/network/miscellaneous.rs b/src/network/miscellaneous.rs index 1636e46..8006c51 100644 --- a/src/network/miscellaneous.rs +++ b/src/network/miscellaneous.rs @@ -9,38 +9,131 @@ const SLOW_CLAP_DB_PREFIX: &[u8] = b"slow_clap::"; // FALLOFF: u32 = 0_050_000; // MAX_PIECE_COUNT: u32 = 40; const PIECEWISE_LINEAR_POUNTS: [(Perbill, Perbill); 32] = [ - (Perbill::from_parts(0), Perbill::from_parts(6900000)), - (Perbill::from_parts(690000000), Perbill::from_parts(690000000)), - (Perbill::from_parts(692740000), Perbill::from_parts(664536000)), - (Perbill::from_parts(695588000), Perbill::from_parts(639072000)), - (Perbill::from_parts(698554000), Perbill::from_parts(613608000)), - (Perbill::from_parts(701647000), Perbill::from_parts(588144000)), - (Perbill::from_parts(704879000), Perbill::from_parts(562680000)), - (Perbill::from_parts(708262000), Perbill::from_parts(537216000)), - (Perbill::from_parts(711811000), Perbill::from_parts(511752000)), - (Perbill::from_parts(715545000), Perbill::from_parts(486288000)), - (Perbill::from_parts(719482000), Perbill::from_parts(460824000)), - (Perbill::from_parts(723646000), Perbill::from_parts(435360000)), - (Perbill::from_parts(728066000), Perbill::from_parts(409896000)), - (Perbill::from_parts(732774000), Perbill::from_parts(384432000)), - (Perbill::from_parts(737811000), Perbill::from_parts(358968000)), - (Perbill::from_parts(743227000), Perbill::from_parts(333504000)), - (Perbill::from_parts(749083000), Perbill::from_parts(308040000)), - (Perbill::from_parts(755456000), Perbill::from_parts(282576000)), - (Perbill::from_parts(762447000), Perbill::from_parts(257112000)), - (Perbill::from_parts(770189000), Perbill::from_parts(231648000)), - (Perbill::from_parts(778863000), Perbill::from_parts(206184000)), - (Perbill::from_parts(788725000), Perbill::from_parts(180720000)), - (Perbill::from_parts(800151000), Perbill::from_parts(155256000)), - (Perbill::from_parts(813735000), Perbill::from_parts(129792000)), - (Perbill::from_parts(830484000), Perbill::from_parts(104328000)), - (Perbill::from_parts(852337000), Perbill::from_parts(78864000)), - (Perbill::from_parts(877801000), Perbill::from_parts(57460000)), - (Perbill::from_parts(903265000), Perbill::from_parts(42422000)), - (Perbill::from_parts(928728000), Perbill::from_parts(31857000)), - (Perbill::from_parts(954189000), Perbill::from_parts(24435000)), - (Perbill::from_parts(979651000), Perbill::from_parts(19220000)), - (Perbill::from_parts(1000000000), Perbill::from_parts(16291000)), + (Perbill::from_parts(0), Perbill::from_parts(6900000)), + ( + Perbill::from_parts(690000000), + Perbill::from_parts(690000000), + ), + ( + Perbill::from_parts(692740000), + Perbill::from_parts(664536000), + ), + ( + Perbill::from_parts(695588000), + Perbill::from_parts(639072000), + ), + ( + Perbill::from_parts(698554000), + Perbill::from_parts(613608000), + ), + ( + Perbill::from_parts(701647000), + Perbill::from_parts(588144000), + ), + ( + Perbill::from_parts(704879000), + Perbill::from_parts(562680000), + ), + ( + Perbill::from_parts(708262000), + Perbill::from_parts(537216000), + ), + ( + Perbill::from_parts(711811000), + Perbill::from_parts(511752000), + ), + ( + Perbill::from_parts(715545000), + Perbill::from_parts(486288000), + ), + ( + Perbill::from_parts(719482000), + Perbill::from_parts(460824000), + ), + ( + Perbill::from_parts(723646000), + Perbill::from_parts(435360000), + ), + ( + Perbill::from_parts(728066000), + Perbill::from_parts(409896000), + ), + ( + Perbill::from_parts(732774000), + Perbill::from_parts(384432000), + ), + ( + Perbill::from_parts(737811000), + Perbill::from_parts(358968000), + ), + ( + Perbill::from_parts(743227000), + Perbill::from_parts(333504000), + ), + ( + Perbill::from_parts(749083000), + Perbill::from_parts(308040000), + ), + ( + Perbill::from_parts(755456000), + Perbill::from_parts(282576000), + ), + ( + Perbill::from_parts(762447000), + Perbill::from_parts(257112000), + ), + ( + Perbill::from_parts(770189000), + Perbill::from_parts(231648000), + ), + ( + Perbill::from_parts(778863000), + Perbill::from_parts(206184000), + ), + ( + Perbill::from_parts(788725000), + Perbill::from_parts(180720000), + ), + ( + Perbill::from_parts(800151000), + Perbill::from_parts(155256000), + ), + ( + Perbill::from_parts(813735000), + Perbill::from_parts(129792000), + ), + ( + Perbill::from_parts(830484000), + Perbill::from_parts(104328000), + ), + ( + Perbill::from_parts(852337000), + Perbill::from_parts(78864000), + ), + ( + Perbill::from_parts(877801000), + Perbill::from_parts(57460000), + ), + ( + Perbill::from_parts(903265000), + Perbill::from_parts(42422000), + ), + ( + Perbill::from_parts(928728000), + Perbill::from_parts(31857000), + ), + ( + Perbill::from_parts(954189000), + Perbill::from_parts(24435000), + ), + ( + Perbill::from_parts(979651000), + Perbill::from_parts(19220000), + ), + ( + Perbill::from_parts(1000000000), + Perbill::from_parts(16291000), + ), ]; const MAXIMUM_INFLATION: Perbill = Perbill::from_parts(690000000); @@ -48,23 +141,34 @@ pub fn calculate_for_fraction(n: u128, d: u128) -> (Perbill, Perbill) { let n = n.min(d.clone()); if PIECEWISE_LINEAR_POUNTS.is_empty() { - return (MAXIMUM_INFLATION, Perbill::zero()) + return (MAXIMUM_INFLATION, Perbill::zero()); } - let next_point_index = PIECEWISE_LINEAR_POUNTS.iter().position(|p| n < p.0 * d.clone()); + let next_point_index = PIECEWISE_LINEAR_POUNTS + .iter() + .position(|p| n < p.0 * d.clone()); let (prev, next) = if let Some(next_point_index) = next_point_index { if let Some(previous_point_index) = next_point_index.checked_sub(1) { - (PIECEWISE_LINEAR_POUNTS[previous_point_index], PIECEWISE_LINEAR_POUNTS[next_point_index]) + ( + PIECEWISE_LINEAR_POUNTS[previous_point_index], + PIECEWISE_LINEAR_POUNTS[next_point_index], + ) } else { // There is no previous points, take first point ordinate - let fraction = PIECEWISE_LINEAR_POUNTS.first().map(|p| p.1).unwrap_or_else(Perbill::zero); - return (MAXIMUM_INFLATION, fraction) + let fraction = PIECEWISE_LINEAR_POUNTS + .first() + .map(|p| p.1) + .unwrap_or_else(Perbill::zero); + return (MAXIMUM_INFLATION, fraction); } } else { // There is no next points, take last point ordinate - let fraction = PIECEWISE_LINEAR_POUNTS.last().map(|p| p.1).unwrap_or_else(Perbill::zero); - return (MAXIMUM_INFLATION, fraction) + let fraction = PIECEWISE_LINEAR_POUNTS + .last() + .map(|p| p.1) + .unwrap_or_else(Perbill::zero); + return (MAXIMUM_INFLATION, fraction); }; let delta_y = multiply_by_rational_saturating( @@ -86,19 +190,19 @@ pub fn calculate_for_fraction(n: u128, d: u128) -> (Perbill, Perbill) { } fn abs_sub + Clone>(a: N, b: N) -> N where { - a.clone().max(b.clone()) - a.min(b) + a.clone().max(b.clone()) - a.min(b) } fn multiply_by_rational_saturating(value: u128, p: u32, q: u32) -> u128 { - let q = q.max(1); - let result_divisor_part = (value / q as u128).saturating_mul(p as u128); - let result_remainder_part = { - let rem = value % q as u128; - let rem_u32 = rem as u32; - let rem_part = rem_u32 as u64 * p as u64 / q as u64; - rem_part as u128 - }; - result_divisor_part.saturating_add(result_remainder_part) + let q = q.max(1); + let result_divisor_part = (value / q as u128).saturating_mul(p as u128); + let result_remainder_part = { + let rem = value % q as u128; + let rem_u32 = rem as u32; + let rem_part = rem_u32 as u64 * p as u64 / q as u64; + rem_part as u128 + }; + result_divisor_part.saturating_add(result_remainder_part) } pub fn get_slow_clap_storage_key(first: &[u8], second: &[u8]) -> Vec { diff --git a/src/network/mod.rs b/src/network/mod.rs index 7a70670..986907a 100644 --- a/src/network/mod.rs +++ b/src/network/mod.rs @@ -1,25 +1,28 @@ -use tokio::sync::mpsc::UnboundedSender; use color_eyre::Result; use subxt::{ - backend::rpc::RpcClient, tx::{TxProgress, TxStatus}, utils::H256, OnlineClient + backend::rpc::RpcClient, + tx::{TxProgress, TxStatus}, + utils::H256, + OnlineClient, }; +use tokio::sync::mpsc::UnboundedSender; mod legacy_rpc_calls; +mod miscellaneous; mod predefined_calls; mod predefined_txs; -mod subscriptions; -mod miscellaneous; mod raw_calls; +mod subscriptions; pub use miscellaneous::calculate_for_fraction; use crate::{ - types::{ActionLevel, ActionTarget}, - action::Action, + action::Action, casper::CasperConfig, + types::{ActionLevel, ActionTarget}, }; -pub use subscriptions::{FinalizedSubscription, BestSubscription}; +pub use subscriptions::{BestSubscription, FinalizedSubscription}; const GATEKEEPED_CHAIN_IDS: [u64; 1] = [ 11155111, //Sepolia @@ -47,11 +50,11 @@ pub struct Network { impl Network { pub fn new( - action_tx: UnboundedSender, + action_tx: UnboundedSender, online_client_api: OnlineClient, rpc_client: RpcClient, ) -> Self { - Self { + Self { action_tx, online_client_api, rpc_client, @@ -69,12 +72,12 @@ impl Network { fn store_stash_or_validator_if_possible(&mut self, account_id: [u8; 32], is_stash: bool) { if is_stash { match self.stash_to_watch { - Some(stash) if stash == account_id => {}, + Some(stash) if stash == account_id => {} _ => self.stash_to_watch = Some(account_id), } } else { match self.validator_details_to_watch { - Some(stash) if stash == account_id => {}, + Some(stash) if stash == account_id => {} _ => self.validator_details_to_watch = Some(account_id), } } @@ -107,40 +110,138 @@ impl Network { Action::NewBestHash(hash) => { self.best_hash = Some(hash); Ok(()) - }, + } Action::NewFinalizedHash(hash) => { self.finalized_hash = Some(hash); if let Some(stash_to_watch) = self.stash_to_watch { - predefined_calls::get_session_keys(&self.action_tx, &self.online_client_api, &self.rpc_client, &stash_to_watch).await?; - predefined_calls::get_queued_session_keys(&self.action_tx, &self.online_client_api, &self.rpc_client, &stash_to_watch).await?; - predefined_calls::get_nominators_by_validator(&self.action_tx, &self.online_client_api, &stash_to_watch).await?; - predefined_calls::get_validator_prefs(&self.action_tx, &self.online_client_api, &stash_to_watch).await?; - predefined_calls::get_staking_value_ratio(&self.action_tx, &self.online_client_api, &stash_to_watch).await?; - predefined_calls::get_is_stash_bonded(&self.action_tx, &self.online_client_api, &stash_to_watch).await?; - predefined_calls::get_validators_ledger(&self.action_tx, &self.online_client_api, &stash_to_watch).await?; - predefined_calls::get_account_payee(&self.action_tx, &self.online_client_api, &stash_to_watch).await?; - predefined_calls::get_slashing_spans(&self.action_tx, &self.online_client_api, &stash_to_watch).await?; + predefined_calls::get_session_keys( + &self.action_tx, + &self.online_client_api, + &self.rpc_client, + &stash_to_watch, + ) + .await?; + predefined_calls::get_queued_session_keys( + &self.action_tx, + &self.online_client_api, + &self.rpc_client, + &stash_to_watch, + ) + .await?; + predefined_calls::get_nominators_by_validator( + &self.action_tx, + &self.online_client_api, + &stash_to_watch, + ) + .await?; + predefined_calls::get_validator_prefs( + &self.action_tx, + &self.online_client_api, + &stash_to_watch, + ) + .await?; + predefined_calls::get_staking_value_ratio( + &self.action_tx, + &self.online_client_api, + &stash_to_watch, + ) + .await?; + predefined_calls::get_is_stash_bonded( + &self.action_tx, + &self.online_client_api, + &stash_to_watch, + ) + .await?; + predefined_calls::get_validators_ledger( + &self.action_tx, + &self.online_client_api, + &stash_to_watch, + ) + .await?; + predefined_calls::get_account_payee( + &self.action_tx, + &self.online_client_api, + &stash_to_watch, + ) + .await?; + predefined_calls::get_slashing_spans( + &self.action_tx, + &self.online_client_api, + &stash_to_watch, + ) + .await?; for era_index in self.eras_to_watch.iter() { - predefined_calls::get_validator_staking_result(&self.action_tx, &self.online_client_api, &stash_to_watch, *era_index).await?; + predefined_calls::get_validator_staking_result( + &self.action_tx, + &self.online_client_api, + &stash_to_watch, + *era_index, + ) + .await?; } } if let Some(validator_details_to_watch) = self.validator_details_to_watch { - predefined_calls::get_nominators_by_validator(&self.action_tx, &self.online_client_api, &validator_details_to_watch).await?; - predefined_calls::get_validator_prefs(&self.action_tx, &self.online_client_api, &validator_details_to_watch).await?; - predefined_calls::get_staking_value_ratio(&self.action_tx, &self.online_client_api, &validator_details_to_watch).await?; - predefined_calls::get_validator_latest_claim(&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_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?; + predefined_calls::get_nominators_by_validator( + &self.action_tx, + &self.online_client_api, + &validator_details_to_watch, + ) + .await?; + predefined_calls::get_validator_prefs( + &self.action_tx, + &self.online_client_api, + &validator_details_to_watch, + ) + .await?; + predefined_calls::get_staking_value_ratio( + &self.action_tx, + &self.online_client_api, + &validator_details_to_watch, + ) + .await?; + predefined_calls::get_validator_latest_claim( + &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_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() { - 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?; } Ok(()) - }, + } Action::CheckPendingTransactions => { let length = self.transactions_to_watch.len(); for i in (0..length).rev() { @@ -148,70 +249,198 @@ impl Network { let ext_hash = pending_tx.tx_progress.extrinsic_hash(); let log_target = pending_tx.target.clone(); match (*pending_tx).tx_progress.next().await { - Some(Ok(status)) => { - match status { - TxStatus::Validated => self.action_tx.send(Action::EventLog(format!("transaction {} is part of future queue", ext_hash), ActionLevel::Info, log_target))?, - TxStatus::Broadcasted { num_peers } => self.action_tx.send(Action::EventLog(format!("transaction {} has been broardcasted to {} nodes", ext_hash, num_peers), ActionLevel::Info, log_target))?, - TxStatus::NoLongerInBestBlock => self.action_tx.send(Action::EventLog(format!("transaction {} is no longer in a best block", ext_hash), ActionLevel::Warn, log_target))?, - TxStatus::InBestBlock(b) => self.action_tx.send(Action::EventLog(format!("transaction {} included in the block header {}", b.extrinsic_hash(), b.block_hash()), ActionLevel::Info, log_target))?, - TxStatus::InFinalizedBlock(b) => { - self.action_tx.send(Action::EventLog(format!("transaction {} has been finalized in block header {}", b.extrinsic_hash(), b.block_hash()), ActionLevel::Info, log_target))?; - self.transactions_to_watch.remove(i); - } - TxStatus::Error { message } => { - self.action_tx.send(Action::EventLog(format!("transaction {} error, something get wrong: {message}", ext_hash), ActionLevel::Error, log_target))?; - self.remove_transaction_and_decrement_nonce(i); - } - TxStatus::Invalid { message } => { - self.action_tx.send(Action::EventLog(format!("transaction {} invalid: {message}", ext_hash), ActionLevel::Error, log_target))?; - self.remove_transaction_and_decrement_nonce(i); - } - TxStatus::Dropped { message } => { - self.action_tx.send(Action::EventLog(format!("transaction {} was dropped: {message}", ext_hash), ActionLevel::Error, log_target))?; - self.remove_transaction_and_decrement_nonce(i); - } + Some(Ok(status)) => match status { + TxStatus::Validated => self.action_tx.send(Action::EventLog( + format!("transaction {} is part of future queue", ext_hash), + ActionLevel::Info, + log_target, + ))?, + TxStatus::Broadcasted { num_peers } => { + self.action_tx.send(Action::EventLog( + format!( + "transaction {} has been broardcasted to {} nodes", + ext_hash, num_peers + ), + ActionLevel::Info, + log_target, + ))? + } + TxStatus::NoLongerInBestBlock => { + self.action_tx.send(Action::EventLog( + format!( + "transaction {} is no longer in a best block", + ext_hash + ), + ActionLevel::Warn, + log_target, + ))? + } + TxStatus::InBestBlock(b) => self.action_tx.send(Action::EventLog( + format!( + "transaction {} included in the block header {}", + b.extrinsic_hash(), + b.block_hash() + ), + ActionLevel::Info, + log_target, + ))?, + TxStatus::InFinalizedBlock(b) => { + self.action_tx.send(Action::EventLog( + format!( + "transaction {} has been finalized in block header {}", + b.extrinsic_hash(), + b.block_hash() + ), + ActionLevel::Info, + log_target, + ))?; + self.transactions_to_watch.remove(i); + } + TxStatus::Error { message } => { + self.action_tx.send(Action::EventLog( + format!( + "transaction {} error, something get wrong: {message}", + ext_hash + ), + ActionLevel::Error, + log_target, + ))?; + self.remove_transaction_and_decrement_nonce(i); + } + TxStatus::Invalid { message } => { + self.action_tx.send(Action::EventLog( + format!("transaction {} invalid: {message}", ext_hash), + ActionLevel::Error, + log_target, + ))?; + self.remove_transaction_and_decrement_nonce(i); + } + TxStatus::Dropped { message } => { + self.action_tx.send(Action::EventLog( + format!("transaction {} was dropped: {message}", ext_hash), + ActionLevel::Error, + log_target, + ))?; + self.remove_transaction_and_decrement_nonce(i); } }, _ => { - self.action_tx.send(Action::EventLog(format!("transaction {} was dropped", ext_hash), ActionLevel::Error, log_target))?; + self.action_tx.send(Action::EventLog( + format!("transaction {} was dropped", ext_hash), + ActionLevel::Error, + log_target, + ))?; self.remove_transaction_and_decrement_nonce(i); } } } Ok(()) - }, - Action::GetSystemHealth => legacy_rpc_calls::get_system_health(&self.action_tx, &self.rpc_client).await, - Action::GetNodeName => legacy_rpc_calls::get_node_name(&self.action_tx, &self.rpc_client).await, - Action::GetGenesisHash => legacy_rpc_calls::get_genesis_hash(&self.action_tx, &self.rpc_client).await, - Action::GetChainName => legacy_rpc_calls::get_chain_name(&self.action_tx, &self.rpc_client).await, - Action::GetChainVersion => legacy_rpc_calls::get_system_version(&self.action_tx, &self.rpc_client).await, - Action::GetPendingExtrinsics => legacy_rpc_calls::get_pending_extrinsics(&self.action_tx, &self.rpc_client).await, - Action::GetConnectedPeers => legacy_rpc_calls::get_connected_peers(&self.action_tx, &self.rpc_client).await, - Action::GetListenAddresses => legacy_rpc_calls::get_listen_addresses(&self.action_tx, &self.rpc_client).await, - Action::GetLocalIdentity => legacy_rpc_calls::get_local_identity(&self.action_tx, &self.rpc_client).await, - Action::GetRpcEndpoints(chain_id) => legacy_rpc_calls::get_stored_rpc_endpoints(&self.action_tx, &self.rpc_client, chain_id).await, - Action::RotateSessionKeys => legacy_rpc_calls::rotate_keys(&self.action_tx, &self.rpc_client).await, + } + Action::GetSystemHealth => { + legacy_rpc_calls::get_system_health(&self.action_tx, &self.rpc_client).await + } + Action::GetNodeName => { + legacy_rpc_calls::get_node_name(&self.action_tx, &self.rpc_client).await + } + Action::GetGenesisHash => { + legacy_rpc_calls::get_genesis_hash(&self.action_tx, &self.rpc_client).await + } + Action::GetChainName => { + legacy_rpc_calls::get_chain_name(&self.action_tx, &self.rpc_client).await + } + Action::GetChainVersion => { + legacy_rpc_calls::get_system_version(&self.action_tx, &self.rpc_client).await + } + Action::GetPendingExtrinsics => { + legacy_rpc_calls::get_pending_extrinsics(&self.action_tx, &self.rpc_client).await + } + Action::GetConnectedPeers => { + legacy_rpc_calls::get_connected_peers(&self.action_tx, &self.rpc_client).await + } + Action::GetListenAddresses => { + legacy_rpc_calls::get_listen_addresses(&self.action_tx, &self.rpc_client).await + } + Action::GetLocalIdentity => { + legacy_rpc_calls::get_local_identity(&self.action_tx, &self.rpc_client).await + } + Action::GetRpcEndpoints(chain_id) => { + legacy_rpc_calls::get_stored_rpc_endpoints( + &self.action_tx, + &self.rpc_client, + chain_id, + ) + .await + } + Action::RotateSessionKeys => { + legacy_rpc_calls::rotate_keys(&self.action_tx, &self.rpc_client).await + } Action::GetBlockRange => { for chain_id in GATEKEEPED_CHAIN_IDS { - legacy_rpc_calls::get_block_range(&self.action_tx, &self.rpc_client, chain_id).await?; + legacy_rpc_calls::get_block_range(&self.action_tx, &self.rpc_client, chain_id) + .await?; } Ok(()) } - Action::GetBlockAuthor(hash, logs) => predefined_calls::get_block_author(&self.action_tx, &self.online_client_api, &logs, &hash).await, - Action::GetActiveEra => predefined_calls::get_active_era(&self.action_tx, &self.online_client_api).await, - Action::GetCurrentEra => predefined_calls::get_current_era(&self.action_tx, &self.online_client_api).await, - Action::GetEpochProgress => predefined_calls::get_epoch_progress(&self.action_tx, &self.online_client_api).await, - Action::GetMinValidatorBond => predefined_calls::get_minimal_validator_bond(&self.action_tx, &self.online_client_api).await, - Action::GetGatekeepedNetwork(chain_id) => predefined_calls::get_gatekeeped_network(&self.action_tx, &self.online_client_api, chain_id).await, - + Action::GetBlockAuthor(hash, logs) => { + predefined_calls::get_block_author( + &self.action_tx, + &self.online_client_api, + &logs, + &hash, + ) + .await + } + Action::GetActiveEra => { + predefined_calls::get_active_era(&self.action_tx, &self.online_client_api).await + } + Action::GetCurrentEra => { + predefined_calls::get_current_era(&self.action_tx, &self.online_client_api).await + } + Action::GetEpochProgress => { + predefined_calls::get_epoch_progress(&self.action_tx, &self.online_client_api).await + } + Action::GetMinValidatorBond => { + predefined_calls::get_minimal_validator_bond( + &self.action_tx, + &self.online_client_api, + ) + .await + } + Action::GetGatekeepedNetwork(chain_id) => { + predefined_calls::get_gatekeeped_network( + &self.action_tx, + &self.online_client_api, + chain_id, + ) + .await + } - Action::GetExistentialDeposit => predefined_calls::get_existential_deposit(&self.action_tx, &self.online_client_api).await, - Action::GetTotalIssuance => predefined_calls::get_total_issuance(&self.action_tx, &self.online_client_api).await, - Action::GetValidatorsNumber => predefined_calls::get_validators_number(&self.action_tx, &self.online_client_api).await, - Action::GetNominatorsNumber => predefined_calls::get_nominators_number(&self.action_tx, &self.online_client_api).await, - Action::GetInflation => predefined_calls::get_inflation(&self.action_tx, &self.online_client_api).await, - Action::GetCurrentValidatorEraRewards => predefined_calls::get_current_validator_reward_in_era(&self.action_tx, &self.online_client_api).await, + Action::GetExistentialDeposit => { + predefined_calls::get_existential_deposit(&self.action_tx, &self.online_client_api) + .await + } + Action::GetTotalIssuance => { + predefined_calls::get_total_issuance(&self.action_tx, &self.online_client_api).await + } + Action::GetValidatorsNumber => { + predefined_calls::get_validators_number(&self.action_tx, &self.online_client_api) + .await + } + Action::GetNominatorsNumber => { + predefined_calls::get_nominators_number(&self.action_tx, &self.online_client_api) + .await + } + Action::GetInflation => { + predefined_calls::get_inflation(&self.action_tx, &self.online_client_api).await + } + Action::GetCurrentValidatorEraRewards => { + predefined_calls::get_current_validator_reward_in_era( + &self.action_tx, + &self.online_client_api, + ) + .await + } Action::SetSender(seed, maybe_nonce) => { self.store_sender_nonce(&seed, maybe_nonce); @@ -224,59 +453,126 @@ impl Network { Action::GetStakingPayee(account_id, is_stash) => { self.store_stash_or_validator_if_possible(account_id, is_stash); - predefined_calls::get_account_payee(&self.action_tx, &self.online_client_api, &account_id).await + predefined_calls::get_account_payee( + &self.action_tx, + &self.online_client_api, + &account_id, + ) + .await } Action::GetValidatorLatestClaim(account_id, is_stash) => { self.store_stash_or_validator_if_possible(account_id, is_stash); - predefined_calls::get_validator_latest_claim(&self.action_tx, &self.online_client_api, &account_id).await + predefined_calls::get_validator_latest_claim( + &self.action_tx, + &self.online_client_api, + &account_id, + ) + .await } Action::GetSlashingSpans(account_id, is_stash) => { self.store_stash_or_validator_if_possible(account_id, is_stash); - predefined_calls::get_slashing_spans(&self.action_tx, &self.online_client_api, &account_id).await + predefined_calls::get_slashing_spans( + &self.action_tx, + &self.online_client_api, + &account_id, + ) + .await } Action::GetValidatorLedger(account_id, is_stash) => { self.store_stash_or_validator_if_possible(account_id, is_stash); - predefined_calls::get_validators_ledger(&self.action_tx, &self.online_client_api, &account_id).await + predefined_calls::get_validators_ledger( + &self.action_tx, + &self.online_client_api, + &account_id, + ) + .await } Action::GetIsStashBonded(account_id, is_stash) => { self.store_stash_or_validator_if_possible(account_id, is_stash); - predefined_calls::get_is_stash_bonded(&self.action_tx, &self.online_client_api, &account_id).await - }, + predefined_calls::get_is_stash_bonded( + &self.action_tx, + &self.online_client_api, + &account_id, + ) + .await + } Action::GetErasStakersOverview(account_id, is_stash) => { self.store_stash_or_validator_if_possible(account_id, is_stash); - predefined_calls::get_staking_value_ratio(&self.action_tx, &self.online_client_api, &account_id).await - }, + predefined_calls::get_staking_value_ratio( + &self.action_tx, + &self.online_client_api, + &account_id, + ) + .await + } Action::GetValidatorPrefs(account_id, is_stash) => { self.store_stash_or_validator_if_possible(account_id, is_stash); - predefined_calls::get_validator_prefs(&self.action_tx, &self.online_client_api, &account_id).await - }, + predefined_calls::get_validator_prefs( + &self.action_tx, + &self.online_client_api, + &account_id, + ) + .await + } Action::GetNominatorsByValidator(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 - }, + predefined_calls::get_nominators_by_account( + &self.action_tx, + &self.online_client_api, + &account_id, + ) + .await + } Action::GetValidatorAllRewards(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 + } Action::GetQueuedSessionKeys(account_id, is_stash) => { self.store_stash_or_validator_if_possible(account_id, is_stash); - predefined_calls::get_queued_session_keys(&self.action_tx, &self.online_client_api, &self.rpc_client, &account_id).await - }, + predefined_calls::get_queued_session_keys( + &self.action_tx, + &self.online_client_api, + &self.rpc_client, + &account_id, + ) + .await + } Action::GetSessionKeys(account_id, is_stash) => { self.store_stash_or_validator_if_possible(account_id, is_stash); - predefined_calls::get_session_keys(&self.action_tx, &self.online_client_api, &self.rpc_client, &account_id).await - }, + predefined_calls::get_session_keys( + &self.action_tx, + &self.online_client_api, + &self.rpc_client, + &account_id, + ) + .await + } Action::BalanceRequest(account_id, remove) => { if remove { let _ = self.accounts_to_watch.remove(&account_id); Ok(()) } else { let _ = self.accounts_to_watch.insert(account_id); - 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 } } Action::TransferBalance(sender, receiver, amount) => { @@ -290,13 +586,15 @@ impl Network { .expect("stored seed is valid length; qed"); if let Ok(tx_progress) = predefined_txs::transfer_balance( - &self.action_tx, - &self.online_client_api, - &sender, - &receiver, + &self.action_tx, + &self.online_client_api, + &sender, + &receiver, &amount, maybe_nonce, - ).await { + ) + .await + { self.transactions_to_watch.push(TxToWatch { tx_progress, sender: sender_cloned, @@ -310,13 +608,15 @@ impl Network { let maybe_nonce = self.senders.get_mut(&sender_str); if let Ok(tx_progress) = predefined_txs::bond_extra( - &self.action_tx, - &self.online_client_api, - &sender, + &self.action_tx, + &self.online_client_api, + &sender, &amount, maybe_nonce, log_target, - ).await { + ) + .await + { self.transactions_to_watch.push(TxToWatch { tx_progress, sender: sender_str, @@ -329,13 +629,15 @@ impl Network { let sender_str = hex::encode(sender); let maybe_nonce = self.senders.get_mut(&sender_str); if let Ok(tx_progress) = predefined_txs::bond( - &self.action_tx, - &self.online_client_api, - &sender, + &self.action_tx, + &self.online_client_api, + &sender, &amount, maybe_nonce, log_target, - ).await { + ) + .await + { self.transactions_to_watch.push(TxToWatch { tx_progress, sender: sender_str, @@ -354,7 +656,9 @@ impl Network { &stash, era_index, maybe_nonce, - ).await { + ) + .await + { self.eras_to_watch.insert(era_index); self.transactions_to_watch.push(TxToWatch { tx_progress, @@ -373,7 +677,9 @@ impl Network { &sender, &hashed_keys, maybe_nonce, - ).await { + ) + .await + { self.transactions_to_watch.push(TxToWatch { tx_progress, sender: sender_str, @@ -391,7 +697,9 @@ impl Network { &sender, percent, maybe_nonce, - ).await { + ) + .await + { self.transactions_to_watch.push(TxToWatch { tx_progress, sender: sender_str, @@ -408,7 +716,9 @@ impl Network { &self.online_client_api, &sender, maybe_nonce, - ).await { + ) + .await + { self.transactions_to_watch.push(TxToWatch { tx_progress, sender: sender_str, @@ -426,7 +736,9 @@ impl Network { &sender, &amount, maybe_nonce, - ).await { + ) + .await + { self.transactions_to_watch.push(TxToWatch { tx_progress, sender: sender_str, @@ -444,7 +756,9 @@ impl Network { &sender, &amount, maybe_nonce, - ).await { + ) + .await + { self.transactions_to_watch.push(TxToWatch { tx_progress, sender: sender_str, @@ -462,7 +776,9 @@ impl Network { &sender, &spans, maybe_nonce, - ).await { + ) + .await + { self.transactions_to_watch.push(TxToWatch { tx_progress, sender: sender_str, @@ -481,7 +797,9 @@ impl Network { reward_destination, maybe_nonce, log_target, - ).await { + ) + .await + { self.transactions_to_watch.push(TxToWatch { tx_progress, sender: sender_str, @@ -499,7 +817,9 @@ impl Network { &sender, &nomination_targets, maybe_nonce, - ).await { + ) + .await + { self.transactions_to_watch.push(TxToWatch { tx_progress, sender: sender_str, @@ -514,7 +834,8 @@ impl Network { &self.rpc_client, chain_id, new_block, - ).await + ) + .await } Action::UpdateStoredRpcEndpoints(chain_id, stored_endpoints) => { legacy_rpc_calls::set_stored_rpc_endpoints( @@ -522,9 +843,10 @@ impl Network { &self.rpc_client, chain_id, stored_endpoints, - ).await + ) + .await } - _ => Ok(()) + _ => Ok(()), } } } diff --git a/src/network/predefined_calls.rs b/src/network/predefined_calls.rs index 9d27cf8..ba454c7 100644 --- a/src/network/predefined_calls.rs +++ b/src/network/predefined_calls.rs @@ -1,21 +1,24 @@ -use tokio::sync::mpsc::UnboundedSender; use color_eyre::Result; use subxt::{ - backend::rpc::RpcClient, - client::OnlineClient, - config::substrate::DigestItem, - ext::sp_core::crypto::{ - AccountId32, Ss58AddressFormat, Ss58Codec, - }, - rpc_params, + backend::rpc::RpcClient, + client::OnlineClient, + config::substrate::DigestItem, + ext::sp_core::crypto::{AccountId32, Ss58AddressFormat, Ss58Codec}, + rpc_params, utils::H256, }; +use tokio::sync::mpsc::UnboundedSender; use crate::{ - action::Action, - casper_network::runtime_types::{ghost_networks::NetworkType, pallet_staking::RewardDestination, sp_consensus_slots}, - types::{EraInfo, EraRewardPoints, Gatekeeper, Nominations, Nominator, SessionKeyInfo, SystemAccount, UnlockChunk}, - CasperAccountId, CasperConfig + action::Action, + casper_network::runtime_types::{ + ghost_networks::NetworkType, pallet_staking::RewardDestination, sp_consensus_slots, + }, + types::{ + EraInfo, EraRewardPoints, Gatekeeper, Nominations, Nominator, SessionKeyInfo, + SystemAccount, UnlockChunk, + }, + CasperAccountId, CasperConfig, }; pub async fn get_block_author( @@ -24,22 +27,29 @@ pub async fn get_block_author( logs: &Vec, at_hash: &H256, ) -> Result<()> { - use codec::Decode; use crate::casper_network::runtime_types::sp_consensus_babe::digests::PreDigest; + use codec::Decode; let validators = super::raw_calls::session::validators(api, Some(at_hash)) .await? .unwrap_or_default(); - let maybe_author = match logs.iter().find(|item| matches!(item, DigestItem::PreRuntime(..))) { + let maybe_author = match logs + .iter() + .find(|item| matches!(item, DigestItem::PreRuntime(..))) + { Some(DigestItem::PreRuntime(engine, data)) if *engine == [b'B', b'A', b'B', b'E'] => { match PreDigest::decode(&mut &data[..]) { Ok(PreDigest::Primary(primary)) => validators.get(primary.authority_index as usize), - Ok(PreDigest::SecondaryPlain(secondary)) => validators.get(secondary.authority_index as usize), - Ok(PreDigest::SecondaryVRF(secondary)) => validators.get(secondary.authority_index as usize), + Ok(PreDigest::SecondaryPlain(secondary)) => { + validators.get(secondary.authority_index as usize) + } + Ok(PreDigest::SecondaryVRF(secondary)) => { + validators.get(secondary.authority_index as usize) + } _ => None, } - }, + } _ => None, }; @@ -49,7 +59,7 @@ pub async fn get_block_author( .expect("author should be valid AccountId32; qed"); let account_id = AccountId32::from(extended_author.0); account_id.to_ss58check_with_version(Ss58AddressFormat::custom(1996)) - }, + } None => "...".to_string(), }; @@ -74,7 +84,7 @@ pub async fn get_active_era( api: &OnlineClient, ) -> Result<()> { if let Some(active_era) = super::raw_calls::staking::active_era(api, None).await? { - action_tx.send(Action::SetActiveEra(EraInfo { + action_tx.send(Action::SetActiveEra(EraInfo { index: active_era.index, start: active_era.start, }))?; @@ -111,8 +121,7 @@ pub async fn get_total_issuance( action_tx: &UnboundedSender, api: &OnlineClient, ) -> Result<()> { - let maybe_total_issuance = super::raw_calls::balances::total_issuance(api, None) - .await?; + let maybe_total_issuance = super::raw_calls::balances::total_issuance(api, None).await?; action_tx.send(Action::SetTotalIssuance(maybe_total_issuance))?; Ok(()) } @@ -134,12 +143,11 @@ pub async fn get_balance( let maybe_balance = super::raw_calls::system::balance(api, None, account_id) .await? .map(|balance| SystemAccount { - nonce: balance.nonce, - free: balance.data.free, - reserved: balance.data.reserved, - frozen: balance.data.frozen, - } - ); + nonce: balance.nonce, + free: balance.data.free, + reserved: balance.data.reserved, + frozen: balance.data.frozen, + }); action_tx.send(Action::BalanceResponse(*account_id, maybe_balance))?; Ok(()) } @@ -185,10 +193,11 @@ pub async fn get_inflation( let adjusted_issuance = super::raw_calls::networks::bridged_imbalance(api, None) .await? - .map(|imbalance| total_issuance - .saturating_add(imbalance.bridged_out) - .saturating_sub(imbalance.bridged_in) - ) + .map(|imbalance| { + total_issuance + .saturating_add(imbalance.bridged_out) + .saturating_sub(imbalance.bridged_in) + }) .unwrap_or_default(); let accumulated_commission = super::raw_calls::networks::accumulated_commission(api, None) @@ -230,7 +239,7 @@ pub async fn get_session_keys( let slow_key = format!("0x{}", hex::encode(session_keys.slow_clap.0)); (gran_key, babe_key, audi_key, slow_key) - }, + } None => (String::new(), String::new(), String::new(), String::new()), }; @@ -252,19 +261,17 @@ pub async fn get_queued_session_keys( let maybe_queued_keys = super::raw_calls::session::queued_keys(api, None).await?; let (gran_key, babe_key, audi_key, slow_key) = match maybe_queued_keys { - Some(session_keys) => { - match session_keys.iter().find(|tuple| tuple.0 == account) { - Some(keys) => { - let session_keys = &keys.1; - let gran_key = format!("0x{}", hex::encode(session_keys.grandpa.0)); - let babe_key = format!("0x{}", hex::encode(session_keys.babe.0)); - let audi_key = format!("0x{}", hex::encode(session_keys.authority_discovery.0)); - let slow_key = format!("0x{}", hex::encode(session_keys.slow_clap.0)); + Some(session_keys) => match session_keys.iter().find(|tuple| tuple.0 == account) { + Some(keys) => { + let session_keys = &keys.1; + let gran_key = format!("0x{}", hex::encode(session_keys.grandpa.0)); + let babe_key = format!("0x{}", hex::encode(session_keys.babe.0)); + let audi_key = format!("0x{}", hex::encode(session_keys.authority_discovery.0)); + let slow_key = format!("0x{}", hex::encode(session_keys.slow_clap.0)); - (gran_key, babe_key, audi_key, slow_key) - }, - None => (String::new(), String::new(), String::new(), String::new()), + (gran_key, babe_key, audi_key, slow_key) } + None => (String::new(), String::new(), String::new(), String::new()), }, None => (String::new(), String::new(), String::new(), String::new()), }; @@ -279,8 +286,8 @@ pub async fn get_queued_session_keys( async fn check_author_has_key( rpc_client: &RpcClient, - action_tx: &UnboundedSender, - key: &str, + action_tx: &UnboundedSender, + key: &str, name: &str, ) -> Result<()> { let params_name = if name.starts_with("q_") { @@ -293,7 +300,7 @@ async fn check_author_has_key( .await?; let session_key_info = SessionKeyInfo { key: key.to_string(), - is_stored + is_stored, }; action_tx.send(Action::SetSessionKey(name.to_string(), session_key_info))?; Ok(()) @@ -342,34 +349,36 @@ pub async fn get_current_validator_reward_in_era( .await? .unwrap_or_default(); - let maybe_era_reward_points = super::raw_calls::staking::eras_reward_points(api, None, era_index) - .await?; + let maybe_era_reward_points = + super::raw_calls::staking::eras_reward_points(api, None, era_index).await?; let (total_points, individual) = match maybe_era_reward_points { - Some(era_reward_points) => { - ( - era_reward_points.total, - era_reward_points.individual - .iter() - .enumerate() - .map(|(index, (account_id, points))| { - let address = AccountId32::from(account_id.0) - .to_ss58check_with_version(Ss58AddressFormat::custom(1996)); - EraRewardPoints { - address, - account_id: account_id.0, - points: *points, - disabled: disabled_validators.contains(&(index as u32)), - } - }) - .collect(), - ) - }, + Some(era_reward_points) => ( + era_reward_points.total, + era_reward_points + .individual + .iter() + .enumerate() + .map(|(index, (account_id, points))| { + let address = AccountId32::from(account_id.0) + .to_ss58check_with_version(Ss58AddressFormat::custom(1996)); + EraRewardPoints { + address, + account_id: account_id.0, + points: *points, + disabled: disabled_validators.contains(&(index as u32)), + } + }) + .collect(), + ), None => (0, Vec::new()), }; action_tx.send(Action::SetCurrentValidatorEraRewards( - era_index, total_points, individual))?; + era_index, + total_points, + individual, + ))?; Ok(()) } @@ -380,12 +389,16 @@ async fn get_validator_reward_in_era( account_id: &[u8; 32], era_index: u32, ) -> Result<()> { - let maybe_era_reward_points = super::raw_calls::staking::eras_reward_points(api, None, era_index).await?; - let era_reward = super::raw_calls::staking::eras_validator_reward(api, None, era_index).await?.unwrap_or_default(); + let maybe_era_reward_points = + super::raw_calls::staking::eras_reward_points(api, None, era_index).await?; + let era_reward = super::raw_calls::staking::eras_validator_reward(api, None, era_index) + .await? + .unwrap_or_default(); let my_reward = match maybe_era_reward_points { Some(era_reward_points) => { - let my_points = era_reward_points.individual + let my_points = era_reward_points + .individual .iter() .find(|(acc, _)| acc.0 == *account_id) .map(|info| info.1) @@ -393,7 +406,7 @@ async fn get_validator_reward_in_era( era_reward .saturating_mul(my_points as u128) .saturating_div(era_reward_points.total as u128) - }, + } None => 0u128, }; @@ -408,14 +421,11 @@ async fn get_validator_claims_in_era( account_id: &[u8; 32], era_index: u32, ) -> Result<()> { - let maybe_claimed_rewards = super::raw_calls::staking::claimed_rewards(api, None, era_index, account_id) - .await?; + let maybe_claimed_rewards = + super::raw_calls::staking::claimed_rewards(api, None, era_index, account_id).await?; if let Some(claimed_rewards) = maybe_claimed_rewards { - let already_claimed = claimed_rewards - .first() - .map(|x| *x == 0) - .unwrap_or(false); + let already_claimed = claimed_rewards.first().map(|x| *x == 0).unwrap_or(false); action_tx.send(Action::SetValidatorEraClaimed(era_index, already_claimed))?; } @@ -428,8 +438,8 @@ async fn get_validator_slashes_in_era( account_id: &[u8; 32], era_index: u32, ) -> Result<()> { - let maybe_slash_in_era = super::raw_calls::staking::validator_slash_in_era(api, None, era_index, account_id) - .await?; + let maybe_slash_in_era = + super::raw_calls::staking::validator_slash_in_era(api, None, era_index, account_id).await?; if let Some(slash_in_era) = maybe_slash_in_era { action_tx.send(Action::SetValidatorEraSlash(era_index, slash_in_era.1))?; @@ -443,18 +453,26 @@ pub async fn get_validators_ledger( api: &OnlineClient, account_id: &[u8; 32], ) -> Result<()> { - let maybe_ledger = super::raw_calls::staking::ledger(api, None, account_id) - .await?; + let maybe_ledger = super::raw_calls::staking::ledger(api, None, account_id).await?; match maybe_ledger { Some(ledger) => { - let chunks = ledger.unlocking.0 + let chunks = ledger + .unlocking + .0 .iter() - .map(|chunk| UnlockChunk { value: chunk.value, era: chunk.era }) + .map(|chunk| UnlockChunk { + value: chunk.value, + era: chunk.era, + }) .collect::>(); - action_tx.send(Action::SetStakedAmountRatio(Some(ledger.total), Some(ledger.active), *account_id))?; + action_tx.send(Action::SetStakedAmountRatio( + Some(ledger.total), + Some(ledger.active), + *account_id, + ))?; action_tx.send(Action::SetValidatorEraUnlocking(chunks, *account_id))?; - }, + } None => { action_tx.send(Action::SetStakedAmountRatio(None, None, *account_id))?; action_tx.send(Action::SetValidatorEraUnlocking(Vec::new(), *account_id))?; @@ -472,7 +490,8 @@ pub async fn get_nominators_by_account( let nominators = super::raw_calls::staking::nominators(api, None, account_id) .await? .map(|n| Nominations { - targets: n.targets + targets: n + .targets .0 .into_iter() .map(|account_id_32| account_id_32.0) @@ -484,7 +503,7 @@ pub async fn get_nominators_by_account( action_tx.send(Action::SetNominatorsByAccount(nominators, *account_id))?; Ok(()) } - + pub async fn get_nominators_by_validator( action_tx: &UnboundedSender, api: &OnlineClient, @@ -495,32 +514,41 @@ pub async fn get_nominators_by_validator( .map(|era_info| era_info.index) .unwrap_or_default(); - let maybe_eras_stakers_overview = super::raw_calls::staking::eras_stakers_overview(api, None, active_era_index, account_id) - .await?; + let maybe_eras_stakers_overview = + super::raw_calls::staking::eras_stakers_overview(api, None, active_era_index, account_id) + .await?; let nominators = match maybe_eras_stakers_overview { Some(overview) => { 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() - .map(|info| Nominator { - account_id: info.who.0, - address: AccountId32::from(info.who.0) - .to_ss58check_with_version(Ss58AddressFormat::custom(1996)), - value: info.value, + 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() + .map(|info| Nominator { + account_id: info.who.0, + address: AccountId32::from(info.who.0) + .to_ss58check_with_version(Ss58AddressFormat::custom(1996)), + value: info.value, + }) + .collect::>() }) - .collect::>() - ) - .unwrap_or_default() + .unwrap_or_default(), ); } others - }, + } None => Vec::new(), }; @@ -549,8 +577,9 @@ pub async fn get_staking_value_ratio( .await? .map(|era_info| era_info.index) .unwrap_or_default(); - let maybe_era_stakers_overview = super::raw_calls::staking::eras_stakers_overview(api, None, active_era_index, account_id) - .await?; + let maybe_era_stakers_overview = + super::raw_calls::staking::eras_stakers_overview(api, None, active_era_index, account_id) + .await?; let (total, own) = match maybe_era_stakers_overview { Some(overview) => (overview.total, overview.own), None => (0, 0), @@ -564,8 +593,8 @@ pub async fn get_validator_prefs( api: &OnlineClient, account_id: &[u8; 32], ) -> Result<()> { - let maybe_validator_prefs = super::raw_calls::staking::validators(api, None, account_id) - .await?; + let maybe_validator_prefs = + super::raw_calls::staking::validators(api, None, account_id).await?; let (commission, blocked) = match maybe_validator_prefs { Some(prefs) => (Some(prefs.commission.0), prefs.blocked), None => (None, false), @@ -594,7 +623,10 @@ pub async fn get_slashing_spans( .await? .map(|spans| spans.prior.len().saturating_add(1)) .unwrap_or_default(); - action_tx.send(Action::SetSlashingSpansLength(slashing_spans_length, *account_id))?; + action_tx.send(Action::SetSlashingSpansLength( + slashing_spans_length, + *account_id, + ))?; Ok(()) } @@ -613,19 +645,23 @@ pub async fn get_validator_latest_claim( let mut claimed_era = current_era; while claimed_era > last_era { - let is_claimed = super::raw_calls::staking::claimed_rewards(api, None, claimed_era, account_id) - .await? - .map(|claimed_rewards| claimed_rewards.len() > 0) - .unwrap_or_default(); + let is_claimed = + super::raw_calls::staking::claimed_rewards(api, None, claimed_era, account_id) + .await? + .map(|claimed_rewards| claimed_rewards.len() > 0) + .unwrap_or_default(); if is_claimed { break; } - claimed_era -= 1; + claimed_era -= 1; } - action_tx.send(Action::SetValidatorLatestClaim(current_era.saturating_sub(claimed_era), *account_id))?; + action_tx.send(Action::SetValidatorLatestClaim( + current_era.saturating_sub(claimed_era), + *account_id, + ))?; Ok(()) } @@ -640,7 +676,9 @@ pub async fn get_account_payee( .map(|payee| match payee { RewardDestination::Stash => crate::types::RewardDestination::Stash, RewardDestination::Staked => crate::types::RewardDestination::Staked, - RewardDestination::Account(account_id_32) => crate::types::RewardDestination::Account(account_id_32.0), + RewardDestination::Account(account_id_32) => { + crate::types::RewardDestination::Account(account_id_32.0) + } RewardDestination::Controller => crate::types::RewardDestination::Controller, RewardDestination::None => crate::types::RewardDestination::None, }) @@ -658,19 +696,18 @@ pub async fn get_gatekeeped_network( .await? .map(|network| Gatekeeper { chain_id, - chain_name: String::from_utf8_lossy(&network.chain_name) - .to_string(), + chain_name: String::from_utf8_lossy(&network.chain_name).to_string(), chain_type: match network.network_type { NetworkType::Evm => String::from("EVM"), NetworkType::Utxo => String::from("UTXO"), NetworkType::Undefined => String::from("???"), }, - default_endpoints: network.default_endpoints + default_endpoints: network + .default_endpoints .iter() .map(|endpoint| String::from_utf8_lossy(&endpoint).to_string()) .collect(), - gatekeeper: String::from_utf8_lossy(&network.gatekeeper) - .to_string(), + gatekeeper: String::from_utf8_lossy(&network.gatekeeper).to_string(), incoming_fee: network.incoming_fee, outgoing_fee: network.outgoing_fee, }) diff --git a/src/network/predefined_txs.rs b/src/network/predefined_txs.rs index c519d90..d3c20fa 100644 --- a/src/network/predefined_txs.rs +++ b/src/network/predefined_txs.rs @@ -1,15 +1,15 @@ use color_eyre::Result; use subxt::{ - ext::sp_core::{sr25519::Pair, Pair as PairT}, - tx::{PairSigner, TxProgress}, + ext::sp_core::{sr25519::Pair, Pair as PairT}, + tx::{PairSigner, TxProgress}, OnlineClient, }; use tokio::sync::mpsc::UnboundedSender; use crate::{ - action::Action, - casper::{CasperConfig, CasperExtrinsicParamsBuilder}, - casper_network::{self, runtime_types}, + action::Action, + casper::{CasperConfig, CasperExtrinsicParamsBuilder}, + casper_network::{self, runtime_types}, types::{ActionLevel, ActionTarget, RewardDestination}, }; @@ -22,16 +22,19 @@ pub async fn transfer_balance( maybe_nonce: Option<&mut u32>, ) -> Result>> { let receiver_id = subxt::utils::MultiAddress::Id(subxt::utils::AccountId32::from(*receiver)); - let transfer_tx = casper_network::tx().balances().transfer_allow_death(receiver_id, *amount); + let transfer_tx = casper_network::tx() + .balances() + .transfer_allow_death(receiver_id, *amount); inner_sign_and_submit_then_watch( - action_tx, - api, - sender, - maybe_nonce, - Box::new(transfer_tx), - "transfer", + action_tx, + api, + sender, + maybe_nonce, + Box::new(transfer_tx), + "transfer", ActionTarget::WalletLog, - ).await + ) + .await } pub async fn bond_extra( @@ -44,14 +47,15 @@ pub async fn bond_extra( ) -> Result>> { let bond_extra_tx = casper_network::tx().staking().bond_extra(*amount); inner_sign_and_submit_then_watch( - action_tx, - api, - sender, - maybe_nonce, - Box::new(bond_extra_tx), - "bond extra", + action_tx, + api, + sender, + maybe_nonce, + Box::new(bond_extra_tx), + "bond extra", log_target, - ).await + ) + .await } pub async fn bond( @@ -63,17 +67,21 @@ pub async fn bond( log_target: ActionTarget, ) -> Result>> { // auto-stake everything by now - let reward_destination = casper_network::runtime_types::pallet_staking::RewardDestination::Staked; - let bond_tx = casper_network::tx().staking().bond(*amount, reward_destination); + let reward_destination = + casper_network::runtime_types::pallet_staking::RewardDestination::Staked; + let bond_tx = casper_network::tx() + .staking() + .bond(*amount, reward_destination); inner_sign_and_submit_then_watch( - action_tx, - api, - sender, - maybe_nonce, - Box::new(bond_tx), - "bond", + action_tx, + api, + sender, + maybe_nonce, + Box::new(bond_tx), + "bond", log_target, - ).await + ) + .await } pub async fn payout_stakers( @@ -85,16 +93,19 @@ pub async fn payout_stakers( maybe_nonce: Option<&mut u32>, ) -> Result>> { let stash_id = subxt::utils::AccountId32::from(*stash); - let payout_stakers_tx = casper_network::tx().staking().payout_stakers(stash_id, era_index); + let payout_stakers_tx = casper_network::tx() + .staking() + .payout_stakers(stash_id, era_index); inner_sign_and_submit_then_watch( - action_tx, - api, - sender, - maybe_nonce, - Box::new(payout_stakers_tx), - "payout stakers", + action_tx, + api, + sender, + maybe_nonce, + Box::new(payout_stakers_tx), + "payout stakers", ActionTarget::ValidatorLog, - ).await + ) + .await } pub async fn set_keys( @@ -107,10 +118,26 @@ pub async fn set_keys( let (gran_key, babe_key, audi_key, slow_key) = { let s = hashed_keys_str.trim_start_matches("0x"); ( - hex::decode(&s[0..64]).unwrap().as_slice().try_into().unwrap(), - hex::decode(&s[64..128]).unwrap().as_slice().try_into().unwrap(), - hex::decode(&s[128..192]).unwrap().as_slice().try_into().unwrap(), - hex::decode(&s[192..256]).unwrap().as_slice().try_into().unwrap(), + hex::decode(&s[0..64]) + .unwrap() + .as_slice() + .try_into() + .unwrap(), + hex::decode(&s[64..128]) + .unwrap() + .as_slice() + .try_into() + .unwrap(), + hex::decode(&s[128..192]) + .unwrap() + .as_slice() + .try_into() + .unwrap(), + hex::decode(&s[192..256]) + .unwrap() + .as_slice() + .try_into() + .unwrap(), ) }; let session_keys = runtime_types::casper_runtime::opaque::SessionKeys { @@ -121,16 +148,19 @@ pub async fn set_keys( }; // it seems like there is no check for the second paramter, that's why // we it can be anything. For example empty vector. - let set_keys_tx = casper_network::tx().session().set_keys(session_keys, Vec::new()); + let set_keys_tx = casper_network::tx() + .session() + .set_keys(session_keys, Vec::new()); inner_sign_and_submit_then_watch( - action_tx, - api, - sender, - maybe_nonce, - Box::new(set_keys_tx), - "set keys", + action_tx, + api, + sender, + maybe_nonce, + Box::new(set_keys_tx), + "set keys", ActionTarget::ValidatorLog, - ).await + ) + .await } pub async fn validate( @@ -146,14 +176,15 @@ pub async fn validate( }; let validate_tx = casper_network::tx().staking().validate(validator_prefs); inner_sign_and_submit_then_watch( - action_tx, - api, - sender, - maybe_nonce, - Box::new(validate_tx), - "validate", + action_tx, + api, + sender, + maybe_nonce, + Box::new(validate_tx), + "validate", ActionTarget::ValidatorLog, - ).await + ) + .await } pub async fn chill( @@ -164,14 +195,15 @@ pub async fn chill( ) -> Result>> { let chill_tx = casper_network::tx().staking().chill(); inner_sign_and_submit_then_watch( - action_tx, - api, - sender, - maybe_nonce, - Box::new(chill_tx), - "chill", + action_tx, + api, + sender, + maybe_nonce, + Box::new(chill_tx), + "chill", ActionTarget::ValidatorLog, - ).await + ) + .await } pub async fn unbond( @@ -183,14 +215,15 @@ pub async fn unbond( ) -> Result>> { let unbond_tx = casper_network::tx().staking().unbond(*amount); inner_sign_and_submit_then_watch( - action_tx, - api, - sender, - maybe_nonce, - Box::new(unbond_tx), - "unbond", + action_tx, + api, + sender, + maybe_nonce, + Box::new(unbond_tx), + "unbond", ActionTarget::ValidatorLog, - ).await + ) + .await } pub async fn rebond( @@ -202,14 +235,15 @@ pub async fn rebond( ) -> Result>> { let rebond_tx = casper_network::tx().staking().rebond(*amount); inner_sign_and_submit_then_watch( - action_tx, - api, - sender, - maybe_nonce, - Box::new(rebond_tx), - "rebond", + action_tx, + api, + sender, + maybe_nonce, + Box::new(rebond_tx), + "rebond", ActionTarget::ValidatorLog, - ).await + ) + .await } pub async fn withdraw_unbonded( @@ -221,14 +255,15 @@ pub async fn withdraw_unbonded( ) -> Result>> { let withdraw_unbonded_tx = casper_network::tx().staking().withdraw_unbonded(*spans); inner_sign_and_submit_then_watch( - action_tx, - api, - sender, - maybe_nonce, - Box::new(withdraw_unbonded_tx), - "withdraw unbonded", + action_tx, + api, + sender, + maybe_nonce, + Box::new(withdraw_unbonded_tx), + "withdraw unbonded", ActionTarget::ValidatorLog, - ).await + ) + .await } pub async fn set_payee( @@ -240,10 +275,18 @@ pub async fn set_payee( log_target: ActionTarget, ) -> Result>> { let reward_destination = match reward_destination { - RewardDestination::Staked => casper_network::runtime_types::pallet_staking::RewardDestination::Staked, - RewardDestination::Stash => casper_network::runtime_types::pallet_staking::RewardDestination::Stash, - RewardDestination::Controller => casper_network::runtime_types::pallet_staking::RewardDestination::Controller, - RewardDestination::None => casper_network::runtime_types::pallet_staking::RewardDestination::None, + RewardDestination::Staked => { + casper_network::runtime_types::pallet_staking::RewardDestination::Staked + } + RewardDestination::Stash => { + casper_network::runtime_types::pallet_staking::RewardDestination::Stash + } + RewardDestination::Controller => { + casper_network::runtime_types::pallet_staking::RewardDestination::Controller + } + RewardDestination::None => { + casper_network::runtime_types::pallet_staking::RewardDestination::None + } RewardDestination::Account(account) => { let account_id = subxt::utils::AccountId32::from(account); casper_network::runtime_types::pallet_staking::RewardDestination::Account(account_id) @@ -251,14 +294,15 @@ pub async fn set_payee( }; let set_payee_tx = casper_network::tx().staking().set_payee(reward_destination); inner_sign_and_submit_then_watch( - action_tx, - api, - sender, - maybe_nonce, - Box::new(set_payee_tx), - "set payee", + action_tx, + api, + sender, + maybe_nonce, + Box::new(set_payee_tx), + "set payee", log_target, - ).await + ) + .await } pub async fn nominate( @@ -274,14 +318,15 @@ pub async fn nominate( .collect::>(); 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", + action_tx, + api, + sender, + maybe_nonce, + Box::new(nominate_tx), + "nominate", ActionTarget::WalletLog, - ).await + ) + .await } async fn inner_sign_and_submit_then_watch( @@ -300,30 +345,36 @@ async fn inner_sign_and_submit_then_watch( CasperExtrinsicParamsBuilder::new() .nonce(nonce.saturating_sub(1) as u64) .build() - }, + } None => CasperExtrinsicParamsBuilder::new().build(), }; match api .tx() .sign_and_submit_then_watch(&tx_call, &signer, tx_params) - .await { - Ok(tx_progress) => { - action_tx.send(Action::EventLog( - format!("{tx_name} transaction {} sent", tx_progress.extrinsic_hash()), - ActionLevel::Info, - target))?; - Ok(tx_progress) - }, - Err(err) => { - if let Some(ref mut nonce) = maybe_nonce { - **nonce = nonce.saturating_sub(1); - } - action_tx.send(Action::EventLog( - format!("error during {tx_name} transaction: {err}"), - ActionLevel::Error, - target))?; - Err(err.into()) - } + .await + { + Ok(tx_progress) => { + action_tx.send(Action::EventLog( + format!( + "{tx_name} transaction {} sent", + tx_progress.extrinsic_hash() + ), + ActionLevel::Info, + target, + ))?; + Ok(tx_progress) } + Err(err) => { + if let Some(ref mut nonce) = maybe_nonce { + **nonce = nonce.saturating_sub(1); + } + action_tx.send(Action::EventLog( + format!("error during {tx_name} transaction: {err}"), + ActionLevel::Error, + target, + ))?; + Err(err.into()) + } + } } diff --git a/src/network/raw_calls/babe.rs b/src/network/raw_calls/babe.rs index 15bd9c0..183395e 100644 --- a/src/network/raw_calls/babe.rs +++ b/src/network/raw_calls/babe.rs @@ -1,10 +1,10 @@ use color_eyre::Result; -use subxt::{ - utils::H256, - client::OnlineClient, -}; +use subxt::{client::OnlineClient, utils::H256}; -use crate::{casper_network::{self, runtime_types::sp_consensus_slots}, CasperConfig}; +use crate::{ + casper_network::{self, runtime_types::sp_consensus_slots}, + CasperConfig, +}; pub async fn current_slot( online_client: &OnlineClient, @@ -33,9 +33,7 @@ pub async fn genesis_slot( Ok(maybe_genesis_slot) } -pub fn epoch_duration( - online_client: &OnlineClient, -) -> Result { +pub fn epoch_duration(online_client: &OnlineClient) -> Result { let constant_query = casper_network::constants().babe().epoch_duration(); let epoch_duration = super::do_constant_call(online_client, &constant_query)?; Ok(epoch_duration) diff --git a/src/network/raw_calls/balances.rs b/src/network/raw_calls/balances.rs index c865293..8686cd7 100644 --- a/src/network/raw_calls/balances.rs +++ b/src/network/raw_calls/balances.rs @@ -1,10 +1,7 @@ use color_eyre::Result; -use subxt::{ - utils::H256, - client::OnlineClient, -}; +use subxt::{client::OnlineClient, utils::H256}; -use crate::{CasperConfig, casper_network}; +use crate::{casper_network, CasperConfig}; pub async fn total_issuance( online_client: &OnlineClient, @@ -15,9 +12,7 @@ pub async fn total_issuance( Ok(maybe_total_issuance) } -pub fn existential_deposit( - online_client: &OnlineClient, -) -> Result { +pub fn existential_deposit(online_client: &OnlineClient) -> Result { let constant_query = casper_network::constants().balances().existential_deposit(); let existential_deposit = super::do_constant_call(online_client, &constant_query)?; Ok(existential_deposit) diff --git a/src/network/raw_calls/mod.rs b/src/network/raw_calls/mod.rs index b829178..76513ac 100644 --- a/src/network/raw_calls/mod.rs +++ b/src/network/raw_calls/mod.rs @@ -1,40 +1,33 @@ use color_eyre::Result; use subxt::{ backend::BlockRef, - utils::{Yes, H256, AccountId32}, client::OnlineClient, + utils::{AccountId32, Yes, H256}, }; use crate::CasperConfig; -pub mod session; -pub mod staking; -pub mod system; pub mod babe; pub mod balances; pub mod networks; +pub mod session; +pub mod staking; +pub mod system; pub async fn do_storage_call<'address, Addr>( online_client: &OnlineClient, storage_key: &'address Addr, maybe_at_hash: Option<&H256>, -) -> Result, subxt::Error> +) -> Result, subxt::Error> where Addr: subxt::storage::Address + 'address, { let at_hash = match maybe_at_hash { Some(at_hash) => BlockRef::from_hash(*at_hash), - None => online_client - .backend() - .latest_finalized_block_ref() - .await?, + None => online_client.backend().latest_finalized_block_ref().await?, }; - online_client - .storage() - .at(at_hash) - .fetch(storage_key) - .await + online_client.storage().at(at_hash).fetch(storage_key).await } pub fn do_constant_call<'address, Addr>( @@ -42,10 +35,12 @@ pub fn do_constant_call<'address, Addr>( constant_query: &'address Addr, ) -> Result where - Addr: subxt::constants::Address + 'address + Addr: subxt::constants::Address + 'address, { let constant_client = online_client.constants(); - constant_client.validate(constant_query).expect("constant query should be correct; qed"); + constant_client + .validate(constant_query) + .expect("constant query should be correct; qed"); constant_client.at(constant_query) } diff --git a/src/network/raw_calls/networks.rs b/src/network/raw_calls/networks.rs index 4813204..e3adb8e 100644 --- a/src/network/raw_calls/networks.rs +++ b/src/network/raw_calls/networks.rs @@ -1,14 +1,11 @@ use color_eyre::Result; -use subxt::{ - utils::H256, - client::OnlineClient, -}; +use subxt::{client::OnlineClient, utils::H256}; use crate::{ casper_network::{ - self, + self, runtime_types::ghost_networks::{BridgeAdjustment, NetworkData}, - }, + }, CasperConfig, }; @@ -16,8 +13,11 @@ pub async fn bridged_imbalance( online_client: &OnlineClient, at_hash: Option<&H256>, ) -> Result>> { - let storage_key = casper_network::storage().ghost_networks().bridged_imbalance(); - let maybe_bridged_imbalance = super::do_storage_call(online_client, &storage_key, at_hash).await?; + let storage_key = casper_network::storage() + .ghost_networks() + .bridged_imbalance(); + let maybe_bridged_imbalance = + super::do_storage_call(online_client, &storage_key, at_hash).await?; Ok(maybe_bridged_imbalance) } @@ -25,8 +25,11 @@ pub async fn accumulated_commission( online_client: &OnlineClient, at_hash: Option<&H256>, ) -> Result> { - let storage_key = casper_network::storage().ghost_networks().accumulated_commission(); - let maybe_accumulated_commission = super::do_storage_call(online_client, &storage_key, at_hash).await?; + let storage_key = casper_network::storage() + .ghost_networks() + .accumulated_commission(); + let maybe_accumulated_commission = + super::do_storage_call(online_client, &storage_key, at_hash).await?; Ok(maybe_accumulated_commission) } @@ -35,7 +38,9 @@ pub async fn networks( at_hash: Option<&H256>, chain_id: u64, ) -> Result> { - let storage_key = casper_network::storage().ghost_networks().networks(chain_id); + let storage_key = casper_network::storage() + .ghost_networks() + .networks(chain_id); let maybe_network = super::do_storage_call(online_client, &storage_key, at_hash).await?; Ok(maybe_network) } diff --git a/src/network/raw_calls/session.rs b/src/network/raw_calls/session.rs index 1dd835b..8533d07 100644 --- a/src/network/raw_calls/session.rs +++ b/src/network/raw_calls/session.rs @@ -1,10 +1,13 @@ use color_eyre::Result; use subxt::{ - utils::{AccountId32, H256}, client::OnlineClient, + utils::{AccountId32, H256}, }; -use crate::{casper_network::{self, runtime_types::casper_runtime::opaque}, CasperConfig}; +use crate::{ + casper_network::{self, runtime_types::casper_runtime::opaque}, + CasperConfig, +}; pub async fn validators( online_client: &OnlineClient, diff --git a/src/network/raw_calls/staking.rs b/src/network/raw_calls/staking.rs index 8789799..7e3e644 100644 --- a/src/network/raw_calls/staking.rs +++ b/src/network/raw_calls/staking.rs @@ -1,24 +1,24 @@ use color_eyre::Result; use subxt::{ - client::OnlineClient, + client::OnlineClient, utils::{AccountId32, H256}, }; use crate::{ casper_network::{ - self, + self, runtime_types::{ pallet_staking::{ - slashing::SlashingSpans, ActiveEraInfo, EraRewardPoints, - RewardDestination, StakingLedger, ValidatorPrefs, Nominations, - }, - sp_arithmetic::per_things::Perbill, + slashing::SlashingSpans, ActiveEraInfo, EraRewardPoints, Nominations, + RewardDestination, StakingLedger, ValidatorPrefs, + }, + sp_arithmetic::per_things::Perbill, sp_staking::{ExposurePage, PagedExposureMetadata}, - }, - }, + }, + }, CasperConfig, }; - + pub async fn current_era( online_client: &OnlineClient, at_hash: Option<&H256>, @@ -42,7 +42,8 @@ pub async fn counter_for_validators( at_hash: Option<&H256>, ) -> Result> { let storage_key = casper_network::storage().staking().counter_for_validators(); - let maybe_counter_for_validators = super::do_storage_call(online_client, &storage_key, at_hash).await?; + let maybe_counter_for_validators = + super::do_storage_call(online_client, &storage_key, at_hash).await?; Ok(maybe_counter_for_validators) } @@ -51,7 +52,8 @@ pub async fn counter_for_nominators( at_hash: Option<&H256>, ) -> Result> { let storage_key = casper_network::storage().staking().counter_for_nominators(); - let maybe_counter_for_nominators = super::do_storage_call(online_client, &storage_key, at_hash).await?; + let maybe_counter_for_nominators = + super::do_storage_call(online_client, &storage_key, at_hash).await?; Ok(maybe_counter_for_nominators) } @@ -62,7 +64,9 @@ pub async fn nominators( ) -> Result> { 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(); + let maybe_nominators = super::do_storage_call(online_client, &storage_key, at_hash) + .await + .unwrap(); Ok(maybe_nominators) } @@ -71,8 +75,11 @@ pub async fn eras_total_stake( at_hash: Option<&H256>, era_index: u32, ) -> Result> { - let storage_key = casper_network::storage().staking().eras_total_stake(era_index); - let maybe_eras_total_stake = super::do_storage_call(online_client, &storage_key, at_hash).await?; + let storage_key = casper_network::storage() + .staking() + .eras_total_stake(era_index); + let maybe_eras_total_stake = + super::do_storage_call(online_client, &storage_key, at_hash).await?; Ok(maybe_eras_total_stake) } @@ -81,8 +88,11 @@ pub async fn eras_validator_reward( at_hash: Option<&H256>, era_index: u32, ) -> Result> { - let storage_key = casper_network::storage().staking().eras_validator_reward(era_index); - let maybe_eras_validator_reward = super::do_storage_call(online_client, &storage_key, at_hash).await?; + let storage_key = casper_network::storage() + .staking() + .eras_validator_reward(era_index); + let maybe_eras_validator_reward = + super::do_storage_call(online_client, &storage_key, at_hash).await?; Ok(maybe_eras_validator_reward) } @@ -91,8 +101,11 @@ pub async fn eras_reward_points( at_hash: Option<&H256>, era_index: u32, ) -> Result>> { - let storage_key = casper_network::storage().staking().eras_reward_points(era_index); - let maybe_eras_reward_points = super::do_storage_call(online_client, &storage_key, at_hash).await?; + let storage_key = casper_network::storage() + .staking() + .eras_reward_points(era_index); + let maybe_eras_reward_points = + super::do_storage_call(online_client, &storage_key, at_hash).await?; Ok(maybe_eras_reward_points) } @@ -103,8 +116,11 @@ pub async fn claimed_rewards( account: &[u8; 32], ) -> Result>> { let account_id = super::convert_array_to_account_id(account); - let storage_key = casper_network::storage().staking().claimed_rewards(era_index, account_id); - let maybe_claimed_rewards = super::do_storage_call(online_client, &storage_key, at_hash).await?; + let storage_key = casper_network::storage() + .staking() + .claimed_rewards(era_index, account_id); + let maybe_claimed_rewards = + super::do_storage_call(online_client, &storage_key, at_hash).await?; Ok(maybe_claimed_rewards) } @@ -115,8 +131,11 @@ pub async fn validator_slash_in_era( account: &[u8; 32], ) -> Result> { let account_id = super::convert_array_to_account_id(account); - let storage_key = casper_network::storage().staking().validator_slash_in_era(era_index, account_id); - let maybe_validator_slash_in_era = super::do_storage_call(online_client, &storage_key, at_hash).await?; + let storage_key = casper_network::storage() + .staking() + .validator_slash_in_era(era_index, account_id); + let maybe_validator_slash_in_era = + super::do_storage_call(online_client, &storage_key, at_hash).await?; Ok(maybe_validator_slash_in_era) } @@ -139,8 +158,11 @@ pub async fn eras_stakers_paged( account: &[u8; 32], ) -> Result>> { let account_id = super::convert_array_to_account_id(account); - let storage_key = casper_network::storage().staking().eras_stakers_paged(era_index, account_id, page_index); - let maybe_eras_stakers_paged = super::do_storage_call(online_client, &storage_key, at_hash).await?; + let storage_key = casper_network::storage() + .staking() + .eras_stakers_paged(era_index, account_id, page_index); + let maybe_eras_stakers_paged = + super::do_storage_call(online_client, &storage_key, at_hash).await?; Ok(maybe_eras_stakers_paged) } @@ -162,8 +184,11 @@ pub async fn eras_stakers_overview( account: &[u8; 32], ) -> Result>> { let account_id = super::convert_array_to_account_id(account); - let storage_key = casper_network::storage().staking().eras_stakers_overview(era_index, account_id); - let maybe_eras_stakers_overview = super::do_storage_call(online_client, &storage_key, at_hash).await?; + let storage_key = casper_network::storage() + .staking() + .eras_stakers_overview(era_index, account_id); + let maybe_eras_stakers_overview = + super::do_storage_call(online_client, &storage_key, at_hash).await?; Ok(maybe_eras_stakers_overview) } @@ -183,7 +208,8 @@ pub async fn disabled_validators( at_hash: Option<&H256>, ) -> Result>> { let storage_key = casper_network::storage().staking().disabled_validators(); - let maybe_disabled_validators = super::do_storage_call(online_client, &storage_key, at_hash).await?; + let maybe_disabled_validators = + super::do_storage_call(online_client, &storage_key, at_hash).await?; Ok(maybe_disabled_validators) } @@ -192,7 +218,8 @@ pub async fn min_validator_bond( at_hash: Option<&H256>, ) -> Result> { let storage_key = casper_network::storage().staking().min_validator_bond(); - let maybe_min_validator_bond = super::do_storage_call(online_client, &storage_key, at_hash).await?; + let maybe_min_validator_bond = + super::do_storage_call(online_client, &storage_key, at_hash).await?; Ok(maybe_min_validator_bond) } @@ -202,7 +229,9 @@ pub async fn slashing_spans( account: &[u8; 32], ) -> Result> { let account_id = super::convert_array_to_account_id(account); - let storage_key = casper_network::storage().staking().slashing_spans(account_id); + let storage_key = casper_network::storage() + .staking() + .slashing_spans(account_id); let maybe_slashing_spans = super::do_storage_call(online_client, &storage_key, at_hash).await?; Ok(maybe_slashing_spans) } @@ -218,9 +247,7 @@ pub async fn payee( Ok(maybe_payee) } -pub fn history_depth( - online_client: &OnlineClient, -) -> Result { +pub fn history_depth(online_client: &OnlineClient) -> Result { let constant_query = casper_network::constants().staking().history_depth(); let history_depth = super::do_constant_call(online_client, &constant_query)?; Ok(history_depth) diff --git a/src/network/raw_calls/system.rs b/src/network/raw_calls/system.rs index 7b7c270..fbd4b6c 100644 --- a/src/network/raw_calls/system.rs +++ b/src/network/raw_calls/system.rs @@ -1,14 +1,11 @@ use color_eyre::Result; -use subxt::{ - utils::H256, - client::OnlineClient, -}; +use subxt::{client::OnlineClient, utils::H256}; use crate::{ casper_network::{ - self, + self, runtime_types::{frame_system::AccountInfo, pallet_balances::types::AccountData}, - }, + }, CasperConfig, }; diff --git a/src/network/subscriptions.rs b/src/network/subscriptions.rs index 6c8646a..ce53536 100644 --- a/src/network/subscriptions.rs +++ b/src/network/subscriptions.rs @@ -1,25 +1,25 @@ -use crate::{ - types::CasperExtrinsicDetails, - action::Action, - casper::CasperBlock, -}; +use crate::{action::Action, casper::CasperBlock, types::CasperExtrinsicDetails}; use color_eyre::Result; use super::GATEKEEPED_CHAIN_IDS; pub struct FinalizedSubscription { - action_tx: tokio::sync::mpsc::UnboundedSender, + action_tx: tokio::sync::mpsc::UnboundedSender, network_tx: std::sync::mpsc::Sender, finalized_blocks_sub: subxt::backend::StreamOfResults, } impl FinalizedSubscription { pub fn new( - action_tx: tokio::sync::mpsc::UnboundedSender, + action_tx: tokio::sync::mpsc::UnboundedSender, network_tx: std::sync::mpsc::Sender, finalized_blocks_sub: subxt::backend::StreamOfResults, ) -> Self { - Self { action_tx, network_tx, finalized_blocks_sub } + Self { + action_tx, + network_tx, + finalized_blocks_sub, + } } pub async fn subscribe_finalized_blocks(&mut self) -> Result<()> { @@ -52,30 +52,40 @@ impl FinalizedSubscription { )); } - self.action_tx.send(Action::FinalizedBlockInformation(block_hash, block_number))?; - self.action_tx.send(Action::ExtrinsicsForBlock(block_number, extrinsic_details))?; - self.action_tx.send(Action::NewFinalizedBlock(block_number))?; + self.action_tx + .send(Action::FinalizedBlockInformation(block_hash, block_number))?; + self.action_tx + .send(Action::ExtrinsicsForBlock(block_number, extrinsic_details))?; + self.action_tx + .send(Action::NewFinalizedBlock(block_number))?; self.network_tx.send(Action::NewFinalizedHash(block_hash))?; - self.network_tx.send(Action::GetBlockAuthor(block_hash, block.header().digest.logs.clone()))?; + self.network_tx.send(Action::GetBlockAuthor( + block_hash, + block.header().digest.logs.clone(), + ))?; } Ok(()) } } pub struct BestSubscription { - action_tx: tokio::sync::mpsc::UnboundedSender, + action_tx: tokio::sync::mpsc::UnboundedSender, network_tx: std::sync::mpsc::Sender, best_blocks_sub: subxt::backend::StreamOfResults, } impl BestSubscription { pub fn new( - action_tx: tokio::sync::mpsc::UnboundedSender, + action_tx: tokio::sync::mpsc::UnboundedSender, network_tx: std::sync::mpsc::Sender, best_blocks_sub: subxt::backend::StreamOfResults, ) -> Self { - Self { action_tx, network_tx, best_blocks_sub } + Self { + action_tx, + network_tx, + best_blocks_sub, + } } pub async fn subscribe_best_blocks(&mut self) -> Result<()> { @@ -109,14 +119,21 @@ impl BestSubscription { )); } - self.action_tx.send(Action::BestBlockInformation(block_hash, block_number))?; - self.action_tx.send(Action::ExtrinsicsForBlock(block_number, extrinsic_details))?; - self.action_tx.send(Action::BestBlockUpdated(block_number))?; + self.action_tx + .send(Action::BestBlockInformation(block_hash, block_number))?; + self.action_tx + .send(Action::ExtrinsicsForBlock(block_number, extrinsic_details))?; + self.action_tx + .send(Action::BestBlockUpdated(block_number))?; self.action_tx.send(Action::NewBestBlock(block_number))?; - self.action_tx.send(Action::ExtrinsicsLength(block_number, extrinsics_length))?; + self.action_tx + .send(Action::ExtrinsicsLength(block_number, extrinsics_length))?; self.network_tx.send(Action::NewBestHash(block_hash))?; - self.network_tx.send(Action::GetBlockAuthor(block_hash, block.header().digest.logs.clone()))?; + self.network_tx.send(Action::GetBlockAuthor( + block_hash, + block.header().digest.logs.clone(), + ))?; self.network_tx.send(Action::GetActiveEra)?; self.network_tx.send(Action::GetCurrentEra)?; self.network_tx.send(Action::GetEpochProgress)?; @@ -124,11 +141,13 @@ impl BestSubscription { self.network_tx.send(Action::GetValidatorsNumber)?; self.network_tx.send(Action::GetNominatorsNumber)?; self.network_tx.send(Action::GetInflation)?; - self.network_tx.send(Action::GetCurrentValidatorEraRewards)?; + self.network_tx + .send(Action::GetCurrentValidatorEraRewards)?; self.network_tx.send(Action::GetMinValidatorBond)?; for chain_id in GATEKEEPED_CHAIN_IDS { - self.network_tx.send(Action::GetGatekeepedNetwork(chain_id))?; + self.network_tx + .send(Action::GetGatekeepedNetwork(chain_id))?; } } Ok(()) diff --git a/src/palette.rs b/src/palette.rs index 2aab005..969f969 100644 --- a/src/palette.rs +++ b/src/palette.rs @@ -1,4 +1,4 @@ -use ratatui::style::{Style, Color}; +use ratatui::style::{Color, Style}; use ratatui::widgets::block::BorderType; #[derive(Debug, Clone)] @@ -98,9 +98,9 @@ impl StylePalette { } pub fn create_basic_style(&mut self, active: bool) -> Style { - if active { + if active { self.hover_style.unwrap_or_default() - } else { + } else { self.normal_style.unwrap_or_default() } } @@ -108,13 +108,19 @@ impl StylePalette { pub fn create_border_style(&self, active: bool) -> (Color, BorderType) { if active { ( - self.hover_border_style.map(|style| style.fg).flatten().unwrap_or_default(), - self.hover_border_type, + self.hover_border_style + .map(|style| style.fg) + .flatten() + .unwrap_or_default(), + self.hover_border_type, ) } else { ( - self.normal_border_style.map(|style| style.fg).flatten().unwrap_or_default(), - self.normal_border_type, + self.normal_border_style + .map(|style| style.fg) + .flatten() + .unwrap_or_default(), + self.normal_border_type, ) } } @@ -129,7 +135,10 @@ impl StylePalette { pub fn create_popup_style(&self) -> (Color, BorderType) { ( - self.popup_style.map(|style| style.fg).flatten().unwrap_or_default(), + self.popup_style + .map(|style| style.fg) + .flatten() + .unwrap_or_default(), self.popup_border_type, ) } diff --git a/src/tui.rs b/src/tui.rs index 77bf09b..8467019 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -8,15 +8,14 @@ use color_eyre::Result; use crossterm::{ cursor, event::{ - DisableBracketedPaste, DisableMouseCapture, EnableBracketedPaste, - EnableMouseCapture, Event as CrosstermEvent, EventStream, KeyEvent, - KeyEventKind, MouseEvent, + DisableBracketedPaste, DisableMouseCapture, EnableBracketedPaste, EnableMouseCapture, + Event as CrosstermEvent, EventStream, KeyEvent, KeyEventKind, MouseEvent, }, terminal::{EnterAlternateScreen, LeaveAlternateScreen}, }; use futures::{FutureExt, StreamExt}; use ratatui::backend::CrosstermBackend as Backend; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use tokio::{ sync::mpsc::{self, UnboundedReceiver, UnboundedSender}, task::JoinHandle, @@ -28,7 +27,7 @@ use tracing::error; #[derive(Clone, Debug, Serialize, Deserialize)] pub enum Event { Init, - Quit, + Quit, Error, Closed, Tick, @@ -126,7 +125,7 @@ impl Tui { None => break, }, }; - + if event_tx.send(event).is_err() { break; } @@ -142,7 +141,7 @@ impl Tui { counter += 1; if counter > 50 { self.task.abort(); - } + } if counter > 100 { error!("failed to abort task in 100 milliseconds for unknown reason"); break; diff --git a/src/types/account.rs b/src/types/account.rs index 0b5fcd1..d30f29f 100644 --- a/src/types/account.rs +++ b/src/types/account.rs @@ -1,5 +1,5 @@ use codec::Decode; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Decode)] pub struct SystemAccount { diff --git a/src/types/era.rs b/src/types/era.rs index fcb6302..b582f52 100644 --- a/src/types/era.rs +++ b/src/types/era.rs @@ -1,5 +1,5 @@ use codec::Decode; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Decode)] pub struct EraInfo { diff --git a/src/types/extrinsics.rs b/src/types/extrinsics.rs index 1f7c256..cf3694b 100644 --- a/src/types/extrinsics.rs +++ b/src/types/extrinsics.rs @@ -1,4 +1,4 @@ -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use subxt::utils::H256; #[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)] diff --git a/src/types/mod.rs b/src/types/mod.rs index ad46334..2411722 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,23 +1,23 @@ +mod account; mod era; mod extrinsics; mod log; -mod account; +mod networks; +mod nominator; mod peer; mod session; -mod nominator; mod staking; -mod networks; +pub use account::SystemAccount; +pub use era::{EraInfo, EraRewardPoints}; pub use extrinsics::CasperExtrinsicDetails; -pub use era::{EraRewardPoints, EraInfo}; pub use log::ActionLevel; pub use log::ActionTarget; -pub use account::SystemAccount; +pub use networks::BlockRange; +pub use networks::Gatekeeper; +pub use nominator::Nominations; +pub use nominator::Nominator; pub use peer::PeerInformation; pub use session::SessionKeyInfo; -pub use nominator::Nominator; -pub use nominator::Nominations; -pub use staking::UnlockChunk; pub use staking::RewardDestination; -pub use networks::Gatekeeper; -pub use networks::BlockRange; +pub use staking::UnlockChunk; diff --git a/src/types/networks.rs b/src/types/networks.rs index 323df21..2515de4 100644 --- a/src/types/networks.rs +++ b/src/types/networks.rs @@ -1,11 +1,11 @@ use codec::Decode; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Decode)] pub struct Gatekeeper { pub chain_id: u64, pub chain_name: String, - pub chain_type: String, + pub chain_type: String, pub gatekeeper: String, pub incoming_fee: u32, pub outgoing_fee: u32, diff --git a/src/types/nominator.rs b/src/types/nominator.rs index 83fadcd..cdd6375 100644 --- a/src/types/nominator.rs +++ b/src/types/nominator.rs @@ -1,5 +1,5 @@ use codec::Decode; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Decode)] pub struct Nominator { diff --git a/src/types/peer.rs b/src/types/peer.rs index 0145f7f..2acbeca 100644 --- a/src/types/peer.rs +++ b/src/types/peer.rs @@ -1,6 +1,6 @@ -use subxt::utils::H256; use codec::Decode; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; +use subxt::utils::H256; #[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Decode)] #[serde(rename_all = "camelCase")] diff --git a/src/types/session.rs b/src/types/session.rs index 1b63f55..09668ed 100644 --- a/src/types/session.rs +++ b/src/types/session.rs @@ -1,5 +1,5 @@ use codec::Decode; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Decode)] pub struct SessionKeyInfo { diff --git a/src/types/staking.rs b/src/types/staking.rs index 00b5c4b..cad55c7 100644 --- a/src/types/staking.rs +++ b/src/types/staking.rs @@ -1,6 +1,6 @@ use codec::Decode; +use serde::{Deserialize, Serialize}; use strum::Display; -use serde::{Serialize, Deserialize}; #[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Decode)] pub struct UnlockChunk { diff --git a/src/widgets/input/input.rs b/src/widgets/input/input.rs index 3c183ba..6e17d1b 100644 --- a/src/widgets/input/input.rs +++ b/src/widgets/input/input.rs @@ -1,5 +1,6 @@ -#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)] -#[derive(serde::Serialize, serde::Deserialize)] +#[derive( + Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash, serde::Serialize, serde::Deserialize, +)] pub enum InputRequest { SetCursor(usize), InsertChar(char), @@ -17,8 +18,9 @@ pub enum InputRequest { DeleteTillEnd, } -#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)] -#[derive(serde::Serialize, serde::Deserialize)] +#[derive( + Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash, serde::Serialize, serde::Deserialize, +)] pub struct StateChanged { pub value: bool, pub cursor: bool, @@ -26,8 +28,7 @@ pub struct StateChanged { pub type InputResponse = Option; -#[derive(Default, Debug, Clone)] -#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Default, Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct Input { value: String, cursor: usize, @@ -78,10 +79,7 @@ impl Input { .value .chars() .take(self.cursor) - .chain( - std::iter::once(c) - .chain(self.value.chars().skip(self.cursor)), - ) + .chain(std::iter::once(c).chain(self.value.chars().skip(self.cursor))) .collect(); } self.cursor += 1; diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs index b1edb0c..5a350c8 100644 --- a/src/widgets/mod.rs +++ b/src/widgets/mod.rs @@ -1,14 +1,14 @@ +mod big_text; mod dot_spinner; +mod input; mod ogham; mod vertical_block; -mod big_text; -mod input; -pub use dot_spinner::DotSpinner; -pub use vertical_block::VerticalBlocks; -pub use ogham::OghamCenter; pub use big_text::BigText; pub use big_text::PixelSize; +pub use dot_spinner::DotSpinner; pub use input::{Input, InputRequest}; +pub use ogham::OghamCenter; +pub use vertical_block::VerticalBlocks; const CYCLE: i64 = 1560; diff --git a/src/widgets/ogham.rs b/src/widgets/ogham.rs index 4ce1767..398a21a 100644 --- a/src/widgets/ogham.rs +++ b/src/widgets/ogham.rs @@ -7,7 +7,10 @@ pub struct OghamCenter { impl Default for OghamCenter { fn default() -> Self { Self { - elements: PROGRESS_CENTER.iter().map(|s| s.to_string()).collect::>(), + elements: PROGRESS_CENTER + .iter() + .map(|s| s.to_string()) + .collect::>(), } } }