diff --git a/locales/en.yml b/locales/en.yml index 9a187a2..17ca6bc 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -70,10 +70,9 @@ network_mining: connected: Connected disconnected: Disconnected network_settings: - ip: IP Address - port: Port change_value: Change value - stratum_port: Stratum server port + stratum_ip: Stratum IP Address + stratum_port: Stratum port port_unavailable: Specified port is unavailable restart_node_required: Node restart is required to apply changes. enable: Enable @@ -101,6 +100,17 @@ network_settings: reset_settings_desc: Reset node settings to default values reset_settings: Reset settings reset: Reset + tx_pool: Transaction pool + pool_fee: Base fee that's accepted into the pool + reorg_period: Reorg cache retention period (in minutes) + max_tx_pool: Maximum number of transactions in the pool + max_tx_stempool: Maximum number of transactions in the stem-pool + max_tx_weight: Maximum total weight of transactions that can get selected to build a block + epoch_duration: Epoch duration (in seconds) + embargo_timer: Embargo timer (in seconds) + aggregation_period: Aggregation period (in seconds) + stem_probability: Stem phase probability + stem_txs: Stem transactions modal: cancel: Cancel save: Save diff --git a/locales/ru.yml b/locales/ru.yml index 306db6e..6cd1b20 100644 --- a/locales/ru.yml +++ b/locales/ru.yml @@ -70,10 +70,9 @@ network_mining: connected: Подключен disconnected: Отключен network_settings: - ip: IP Адрес - port: Порт change_value: Изменить значение - stratum_port: Порт Stratum сервера + stratum_ip: Stratum IP Адрес + stratum_port: Порт Stratum port_unavailable: Указанный порт недоступен restart_node_required: Для применения изменений требуется перезапуск узла. enable: Включить @@ -101,6 +100,17 @@ network_settings: reset_settings_desc: Сбросить настройки узла до стандартных значений reset_settings: Сброс настроек reset: Сбросить + tx_pool: Пул транзакций + pool_fee: Базовая комиссия, принимаемая в пул + reorg_period: Срок хранения кэша реорганизации (в минутах) + max_tx_pool: Максимальное количество транзакций в пуле + max_tx_stempool: Максимальное количество транзакций в stem-пуле + max_tx_weight: Максимальный общий вес транзакций, которые могут быть выбраны для построения блока + epoch_duration: Длительность эпохи (в секундах) + embargo_timer: Таймер эмбарго (в секундах) + aggregation_period: Период агрегации (в секундах) + stem_probability: Вероятность фазы Stem + stem_txs: Stem транзакций modal: cancel: Отмена save: Сохранить diff --git a/src/gui/colors.rs b/src/gui/colors.rs index 118db5b..0b822fc 100644 --- a/src/gui/colors.rs +++ b/src/gui/colors.rs @@ -27,9 +27,10 @@ impl Colors { pub const RED: Color32 = Color32::from_rgb(0x8B, 0, 0); pub const FILL: Color32 = Color32::from_gray(244); pub const FILL_DARK: Color32 = Color32::from_gray(232); - pub const TITLE: Color32 = Color32::from_gray(60); + pub const CHECKBOX: Color32 = Color32::from_gray(100); pub const TEXT: Color32 = Color32::from_gray(80); pub const TEXT_BUTTON: Color32 = Color32::from_gray(70); + pub const TITLE: Color32 = Color32::from_gray(60); pub const BUTTON: Color32 = Color32::from_gray(249); pub const GRAY: Color32 = Color32::from_gray(120); pub const STROKE: Color32 = Color32::from_gray(190); diff --git a/src/gui/views/network/configs.rs b/src/gui/views/network/configs.rs index b3666e1..6dae75d 100644 --- a/src/gui/views/network/configs.rs +++ b/src/gui/views/network/configs.rs @@ -13,7 +13,7 @@ // limitations under the License. pub mod stratum; -pub mod server; +pub mod node; pub mod p2p; pub mod pool; pub mod dandelion; \ No newline at end of file diff --git a/src/gui/views/network/configs/dandelion.rs b/src/gui/views/network/configs/dandelion.rs index 6ddbed9..2e949f5 100644 --- a/src/gui/views/network/configs/dandelion.rs +++ b/src/gui/views/network/configs/dandelion.rs @@ -12,3 +12,435 @@ // See the License for the specific language governing permissions and // limitations under the License. +use egui::{Id, RichText, TextStyle, Ui, Widget}; + +use crate::gui::{Colors, Navigator}; +use crate::gui::icons::{CLOCK_COUNTDOWN, LINE_SEGMENTS, TIMER, WATCH}; +use crate::gui::platform::PlatformCallbacks; +use crate::gui::views::{Modal, ModalPosition, View}; +use crate::gui::views::network::settings::NetworkSettings; +use crate::node::NodeConfig; + +/// Dandelion setup ui section. +pub struct DandelionSetup { + /// Epoch duration value in seconds. + epoch_edit: String, + + /// Embargo expiration time value in seconds to fluff and broadcast if tx not seen on network. + embargo_edit: String, + + /// Aggregation period value in seconds. + aggregation_edit: String, + + /// Stem phase probability value (stem 90% of the time, fluff 10% of the time by default). + stem_prob_edit: String, + + /// Flag to always stem our (pushed via api) txs regardless of stem/fluff epoch. + always_stem_our_txs_edit: bool, +} + +impl Default for DandelionSetup { + fn default() -> Self { + Self { + epoch_edit: NodeConfig::get_dandelion_epoch(), + embargo_edit: NodeConfig::get_reorg_cache_period(), + aggregation_edit: NodeConfig::get_dandelion_aggregation(), + stem_prob_edit: NodeConfig::get_stem_probability(), + always_stem_our_txs_edit: NodeConfig::always_stem_our_txs(), + } + } +} + +impl DandelionSetup { + /// Identifier epoch duration value [`Modal`]. + pub const EPOCH_MODAL: &'static str = "epoch_secs"; + /// Identifier for embargo expiration time value [`Modal`]. + pub const EMBARGO_MODAL: &'static str = "embargo_secs"; + /// Identifier for aggregation period value [`Modal`]. + pub const AGGREGATION_MODAL: &'static str = "aggregation_secs"; + /// Identifier for Stem phase probability value [`Modal`]. + pub const STEM_PROBABILITY_MODAL: &'static str = "stem_probability"; + + pub fn ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) { + View::sub_title(ui, format!("{} {}", LINE_SEGMENTS, "Dandelion")); + View::horizontal_line(ui, Colors::STROKE); + ui.add_space(6.0); + + ui.vertical_centered(|ui| { + // Show epoch duration setup. + self.epoch_ui(ui, cb); + + ui.add_space(6.0); + View::horizontal_line(ui, Colors::ITEM_STROKE); + ui.add_space(6.0); + + // Show embargo expiration time setup. + self.embargo_ui(ui, cb); + + ui.add_space(6.0); + View::horizontal_line(ui, Colors::ITEM_STROKE); + ui.add_space(6.0); + + // Show aggregation period setup. + self.aggregation_ui(ui, cb); + + ui.add_space(6.0); + View::horizontal_line(ui, Colors::ITEM_STROKE); + ui.add_space(6.0); + + // Show Stem phase probability setup. + self.stem_prob_ui(ui, cb); + + ui.add_space(6.0); + View::horizontal_line(ui, Colors::ITEM_STROKE); + ui.add_space(8.0); + + // Show setup to always stem our txs. + let always_stem = NodeConfig::always_stem_our_txs(); + View::checkbox(ui, always_stem, t!("network_settings.stem_txs"), || { + NodeConfig::toggle_always_stem_our_txs(); + }); + ui.add_space(6.0); + }); + } + + /// Draw epoch duration setup content. + fn epoch_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) { + ui.label(RichText::new(t!("network_settings.epoch_duration")) + .size(16.0) + .color(Colors::GRAY) + ); + ui.add_space(6.0); + + let epoch = NodeConfig::get_dandelion_epoch(); + View::button(ui, format!("{} {}", WATCH, epoch.clone()), Colors::BUTTON, || { + // Setup values for modal. + self.epoch_edit = epoch; + // Show epoch setup modal. + let epoch_modal = Modal::new(Self::EPOCH_MODAL) + .position(ModalPosition::CenterTop) + .title(t!("network_settings.change_value")); + Navigator::show_modal(epoch_modal); + cb.show_keyboard(); + }); + ui.add_space(6.0); + } + + /// Draw epoch duration [`Modal`] content. + pub fn epoch_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { + ui.add_space(6.0); + ui.vertical_centered(|ui| { + ui.label(RichText::new(t!("network_settings.epoch_duration")) + .size(18.0) + .color(Colors::GRAY)); + ui.add_space(8.0); + + // Draw epoch text edit. + let text_edit_resp = egui::TextEdit::singleline(&mut self.epoch_edit) + .id(Id::from(modal.id)) + .font(TextStyle::Heading) + .desired_width(46.0) + .cursor_at_end(true) + .ui(ui); + text_edit_resp.request_focus(); + if text_edit_resp.clicked() { + cb.show_keyboard(); + } + + // Show error when specified value is not valid or reminder to restart enabled node. + if self.epoch_edit.parse::().is_err() { + ui.add_space(12.0); + ui.label(RichText::new(t!("network_settings.not_valid_value")) + .size(18.0) + .color(Colors::RED)); + } else { + NetworkSettings::node_restart_required_ui(ui); + } + ui.add_space(12.0); + }); + + // Show modal buttons. + ui.scope(|ui| { + // Setup spacing between buttons. + ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0); + + // Save button callback. + let on_save = || { + if let Ok(epoch) = self.epoch_edit.parse::() { + NodeConfig::save_dandelion_epoch(epoch); + cb.hide_keyboard(); + modal.close(); + } + }; + + ui.columns(2, |columns| { + columns[0].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.cancel"), Colors::WHITE, || { + // Close modal. + cb.hide_keyboard(); + modal.close(); + }); + }); + columns[1].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.save"), Colors::WHITE, on_save); + }); + }); + ui.add_space(6.0); + }); + } + + /// Draw embargo expiration time setup content. + fn embargo_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) { + ui.label(RichText::new(t!("network_settings.embargo_timer")) + .size(16.0) + .color(Colors::GRAY) + ); + ui.add_space(6.0); + + let embargo = NodeConfig::get_dandelion_embargo(); + View::button(ui, format!("{} {}", TIMER, embargo.clone()), Colors::BUTTON, || { + // Setup values for modal. + self.embargo_edit = embargo; + // Show embargo setup modal. + let embargo_modal = Modal::new(Self::EMBARGO_MODAL) + .position(ModalPosition::CenterTop) + .title(t!("network_settings.change_value")); + Navigator::show_modal(embargo_modal); + cb.show_keyboard(); + }); + ui.add_space(6.0); + } + + /// Draw epoch duration [`Modal`] content. + pub fn embargo_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { + ui.add_space(6.0); + ui.vertical_centered(|ui| { + ui.label(RichText::new(t!("network_settings.embargo_timer")) + .size(18.0) + .color(Colors::GRAY)); + ui.add_space(8.0); + + // Draw embargo text edit. + let text_edit_resp = egui::TextEdit::singleline(&mut self.embargo_edit) + .id(Id::from(modal.id)) + .font(TextStyle::Heading) + .desired_width(46.0) + .cursor_at_end(true) + .ui(ui); + text_edit_resp.request_focus(); + if text_edit_resp.clicked() { + cb.show_keyboard(); + } + + // Show error when specified value is not valid or reminder to restart enabled node. + if self.embargo_edit.parse::().is_err() { + ui.add_space(12.0); + ui.label(RichText::new(t!("network_settings.not_valid_value")) + .size(18.0) + .color(Colors::RED)); + } else { + NetworkSettings::node_restart_required_ui(ui); + } + ui.add_space(12.0); + }); + + // Show modal buttons. + ui.scope(|ui| { + // Setup spacing between buttons. + ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0); + + // Save button callback. + let on_save = || { + if let Ok(embargo) = self.embargo_edit.parse::() { + NodeConfig::save_dandelion_embargo(embargo); + cb.hide_keyboard(); + modal.close(); + } + }; + + ui.columns(2, |columns| { + columns[0].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.cancel"), Colors::WHITE, || { + // Close modal. + cb.hide_keyboard(); + modal.close(); + }); + }); + columns[1].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.save"), Colors::WHITE, on_save); + }); + }); + ui.add_space(6.0); + }); + } + + /// Draw aggregation period setup content. + fn aggregation_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) { + ui.label(RichText::new(t!("network_settings.aggregation_period")) + .size(16.0) + .color(Colors::GRAY) + ); + ui.add_space(6.0); + + let agg = NodeConfig::get_dandelion_aggregation(); + View::button(ui, format!("{} {}", CLOCK_COUNTDOWN, agg.clone()), Colors::BUTTON, || { + // Setup values for modal. + self.aggregation_edit = agg; + // Show aggregation setup modal. + let aggregation_modal = Modal::new(Self::AGGREGATION_MODAL) + .position(ModalPosition::CenterTop) + .title(t!("network_settings.change_value")); + Navigator::show_modal(aggregation_modal); + cb.show_keyboard(); + }); + ui.add_space(6.0); + } + + /// Draw aggregation period [`Modal`] content. + pub fn aggregation_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { + ui.add_space(6.0); + ui.vertical_centered(|ui| { + ui.label(RichText::new(t!("network_settings.aggregation_period")) + .size(18.0) + .color(Colors::GRAY)); + ui.add_space(8.0); + + // Draw aggregation period text edit. + let text_edit_resp = egui::TextEdit::singleline(&mut self.aggregation_edit) + .id(Id::from(modal.id)) + .font(TextStyle::Heading) + .desired_width(36.0) + .cursor_at_end(true) + .ui(ui); + text_edit_resp.request_focus(); + if text_edit_resp.clicked() { + cb.show_keyboard(); + } + + // Show error when specified value is not valid or reminder to restart enabled node. + if self.aggregation_edit.parse::().is_err() { + ui.add_space(12.0); + ui.label(RichText::new(t!("network_settings.not_valid_value")) + .size(18.0) + .color(Colors::RED)); + } else { + NetworkSettings::node_restart_required_ui(ui); + } + ui.add_space(12.0); + }); + + // Show modal buttons. + ui.scope(|ui| { + // Setup spacing between buttons. + ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0); + + // Save button callback. + let on_save = || { + if let Ok(embargo) = self.aggregation_edit.parse::() { + NodeConfig::save_dandelion_aggregation(embargo); + cb.hide_keyboard(); + modal.close(); + } + }; + + ui.columns(2, |columns| { + columns[0].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.cancel"), Colors::WHITE, || { + // Close modal. + cb.hide_keyboard(); + modal.close(); + }); + }); + columns[1].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.save"), Colors::WHITE, on_save); + }); + }); + ui.add_space(6.0); + }); + } + + /// Draw stem phase probability setup content. + fn stem_prob_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) { + ui.label(RichText::new(t!("network_settings.stem_probability")) + .size(16.0) + .color(Colors::GRAY) + ); + ui.add_space(6.0); + + let stem_prob = NodeConfig::get_stem_probability(); + View::button(ui, format!("{}%", stem_prob.clone()), Colors::BUTTON, || { + // Setup values for modal. + self.stem_prob_edit = stem_prob; + // Show stem probability setup modal. + let embargo_modal = Modal::new(Self::STEM_PROBABILITY_MODAL) + .position(ModalPosition::CenterTop) + .title(t!("network_settings.change_value")); + Navigator::show_modal(embargo_modal); + cb.show_keyboard(); + }); + ui.add_space(6.0); + } + + /// Draw stem phase probability [`Modal`] content. + pub fn stem_prob_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { + ui.add_space(6.0); + ui.vertical_centered(|ui| { + ui.label(RichText::new(t!("network_settings.stem_probability")) + .size(18.0) + .color(Colors::GRAY)); + ui.add_space(8.0); + + // Draw stem phase probability text edit. + let text_edit_resp = egui::TextEdit::singleline(&mut self.stem_prob_edit) + .id(Id::from(modal.id)) + .font(TextStyle::Heading) + .desired_width(36.0) + .cursor_at_end(true) + .ui(ui); + text_edit_resp.request_focus(); + if text_edit_resp.clicked() { + cb.show_keyboard(); + } + + // Show error when specified value is not valid or reminder to restart enabled node. + if self.stem_prob_edit.parse::().is_err() { + ui.add_space(12.0); + ui.label(RichText::new(t!("network_settings.not_valid_value")) + .size(18.0) + .color(Colors::RED)); + } else { + NetworkSettings::node_restart_required_ui(ui); + } + ui.add_space(12.0); + }); + + // Show modal buttons. + ui.scope(|ui| { + // Setup spacing between buttons. + ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0); + + // Save button callback. + let on_save = || { + if let Ok(prob) = self.stem_prob_edit.parse::() { + NodeConfig::save_stem_probability(prob); + cb.hide_keyboard(); + modal.close(); + } + }; + + ui.columns(2, |columns| { + columns[0].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.cancel"), Colors::WHITE, || { + // Close modal. + cb.hide_keyboard(); + modal.close(); + }); + }); + columns[1].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.save"), Colors::WHITE, on_save); + }); + }); + ui.add_space(6.0); + }); + } +} \ No newline at end of file diff --git a/src/gui/views/network/configs/server.rs b/src/gui/views/network/configs/node.rs similarity index 87% rename from src/gui/views/network/configs/server.rs rename to src/gui/views/network/configs/node.rs index 91b0dcf..16c296e 100644 --- a/src/gui/views/network/configs/server.rs +++ b/src/gui/views/network/configs/node.rs @@ -13,7 +13,7 @@ // limitations under the License. use eframe::emath::Align; -use egui::{Id, Layout, RichText, TextStyle, Widget}; +use egui::{Id, Layout, RichText, TextStyle, Ui, Widget}; use grin_core::global::ChainTypes; use crate::AppConfig; @@ -25,49 +25,53 @@ use crate::gui::views::network::settings::NetworkSettings; use crate::node::{Node, NodeConfig}; /// Integrated node server setup ui section. -pub struct ServerSetup { - /// API port to be used inside edit modal. +pub struct NodeSetup { + /// IP Addresses available at system. + available_ips: Vec, + + /// API port value. api_port_edit: String, - /// Flag to check if API port is available inside edit modal. + /// Flag to check if API port is available. api_port_available_edit: bool, - /// Flag to check if API port is available from saved config value. + /// Flag to check if API port from saved config value is available. pub(crate) is_api_port_available: bool, - /// API secret to be used inside edit modal. + /// Rest API and v2 Owner API secret value. api_secret_edit: String, - /// Foreign API secret to be used inside edit modal. + /// Foreign API secret value. foreign_api_secret_edit: String, - /// Future Time Limit to be used inside edit modal. + /// Future Time Limit value. ftl_edit: String, } -impl Default for ServerSetup { +impl Default for NodeSetup { fn default() -> Self { let (api_ip, api_port) = NodeConfig::get_api_address(); let is_api_port_available = NodeConfig::is_api_port_available(&api_ip, &api_port); Self { + available_ips: NodeConfig::get_ip_addrs(), api_port_edit: api_port, api_port_available_edit: is_api_port_available, is_api_port_available, api_secret_edit: "".to_string(), foreign_api_secret_edit: "".to_string(), - ftl_edit: "".to_string(), + ftl_edit: NodeConfig::get_ftl(), } } } -impl ServerSetup { +impl NodeSetup { pub const API_PORT_MODAL: &'static str = "api_port"; pub const API_SECRET_MODAL: &'static str = "api_secret"; pub const FOREIGN_API_SECRET_MODAL: &'static str = "foreign_api_secret"; pub const FTL_MODAL: &'static str = "ftl"; - pub fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) { + pub fn ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) { View::sub_title(ui, format!("{} {}", COMPUTER_TOWER, t!("network_settings.server"))); - View::horizontal_line(ui, Colors::ITEM_STROKE); + View::horizontal_line(ui, Colors::STROKE); ui.add_space(4.0); // Show chain type setup. @@ -126,12 +130,9 @@ impl ServerSetup { }); ui.add_space(6.0); - let addrs = NodeConfig::get_ip_addrs(); - if addrs.is_empty() { + if self.available_ips.is_empty() { // Show message when IP addresses are not available on the system. NetworkSettings::no_ip_address_ui(ui); - - ui.add_space(4.0); } else { View::horizontal_line(ui, Colors::ITEM_STROKE); ui.add_space(6.0); @@ -145,35 +146,15 @@ impl ServerSetup { // Show API IP addresses to select. let (api_ip, api_port) = NodeConfig::get_api_address(); - NetworkSettings::ip_addrs_ui(ui, &api_ip, &addrs, |selected_ip| { + NetworkSettings::ip_addrs_ui(ui, &api_ip, &self.available_ips, |selected_ip| { let api_available = NodeConfig::is_api_port_available(selected_ip, &api_port); self.is_api_port_available = api_available; NodeConfig::save_api_address(selected_ip, &api_port); }); - - ui.label(RichText::new(t!("network_settings.api_port")) - .size(16.0) - .color(Colors::GRAY) - ); - ui.add_space(6.0); // Show API port setup. self.api_port_setup_ui(ui, cb); - - ui.label(RichText::new(t!("network_settings.api_secret")) - .size(16.0) - .color(Colors::GRAY) - ); - ui.add_space(6.0); // Show API secret setup. self.secret_ui(Self::API_SECRET_MODAL, ui, cb); - - ui.add_space(6.0); - - ui.label(RichText::new(t!("network_settings.foreign_api_secret")) - .size(16.0) - .color(Colors::GRAY) - ); - ui.add_space(6.0); // Show Foreign API secret setup. self.secret_ui(Self::FOREIGN_API_SECRET_MODAL, ui, cb); }); @@ -184,11 +165,6 @@ impl ServerSetup { ui.add_space(6.0); ui.vertical_centered(|ui| { - ui.label(RichText::new(t!("network_settings.ftl")) - .size(16.0) - .color(Colors::GRAY) - ); - ui.add_space(6.0); // Show FTL setup. self.ftl_ui(ui, cb); @@ -205,15 +181,11 @@ impl ServerSetup { // Archive mode setup. self.archive_mode_ui(ui); - - ui.add_space(6.0); - View::horizontal_line(ui, Colors::ITEM_STROKE); - ui.add_space(6.0); }); } - /// Draw [`ChainTypes`] setup ui. - fn chain_type_ui(&mut self, ui: &mut egui::Ui) { + /// Draw [`ChainTypes`] setup content. + fn chain_type_ui(&mut self, ui: &mut Ui) { let saved_chain_type = AppConfig::chain_type(); let mut selected_chain_type = saved_chain_type; @@ -236,8 +208,14 @@ impl ServerSetup { } } - /// Draw API port setup ui. - fn api_port_setup_ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) { + /// Draw API port setup content. + fn api_port_setup_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) { + ui.label(RichText::new(t!("network_settings.api_port")) + .size(16.0) + .color(Colors::GRAY) + ); + ui.add_space(6.0); + let (_, port) = NodeConfig::get_api_address(); View::button(ui, format!("{} {}", PLUG, port.clone()), Colors::BUTTON, || { // Setup values for modal. @@ -263,11 +241,8 @@ impl ServerSetup { ui.add_space(6.0); } - /// Draw API port [`Modal`] content ui. - pub fn api_port_modal(&mut self, - ui: &mut egui::Ui, - modal: &Modal, - cb: &dyn PlatformCallbacks) { + /// Draw API port [`Modal`] content. + pub fn api_port_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { ui.add_space(6.0); ui.vertical_centered(|ui| { ui.label(RichText::new(t!("network_settings.api_port")) @@ -335,8 +310,18 @@ impl ServerSetup { }); } - /// Draw API secret token setup ui. - fn secret_ui(&mut self, modal_id: &'static str, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) { + /// Draw API secret token setup content. + fn secret_ui(&mut self, modal_id: &'static str, ui: &mut Ui, cb: &dyn PlatformCallbacks) { + let secret_title = match modal_id { + Self::API_SECRET_MODAL => t!("network_settings.api_secret"), + _ => t!("network_settings.foreign_api_secret") + }; + ui.label(RichText::new(secret_title) + .size(16.0) + .color(Colors::GRAY) + ); + ui.add_space(6.0); + let secret_value = match modal_id { Self::API_SECRET_MODAL => NodeConfig::get_api_secret(), _ => NodeConfig::get_foreign_api_secret() @@ -365,11 +350,11 @@ impl ServerSetup { Navigator::show_modal(port_modal); cb.show_keyboard(); }); - ui.add_space(6.0); + ui.add_space(12.0); } - /// Draw API port [`Modal`] content ui. - pub fn secret_modal(&mut self, ui: &mut egui::Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { + /// Draw API port [`Modal`] content. + pub fn secret_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { ui.add_space(6.0); ui.vertical_centered(|ui| { let description = match modal.id { @@ -475,8 +460,14 @@ impl ServerSetup { }); } - /// Draw FTL setup ui. - fn ftl_ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) { + /// Draw FTL setup content. + fn ftl_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) { + ui.label(RichText::new(t!("network_settings.ftl")) + .size(16.0) + .color(Colors::GRAY) + ); + ui.add_space(6.0); + let ftl = NodeConfig::get_ftl(); View::button(ui, format!("{} {}", CLOCK_CLOCKWISE, ftl.clone()), Colors::BUTTON, || { // Setup values for modal. @@ -497,7 +488,7 @@ impl ServerSetup { } /// Draw FTL [`Modal`] content. - pub fn ftl_modal(&mut self, ui: &mut egui::Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { + pub fn ftl_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { ui.add_space(6.0); ui.vertical_centered(|ui| { ui.label(RichText::new(t!("network_settings.ftl")) @@ -534,7 +525,7 @@ impl ServerSetup { // Setup spacing between buttons. ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0); - // Save button callback + // Save button callback. let on_save = || { if let Ok(ftl) = self.ftl_edit.parse::() { NodeConfig::save_ftl(ftl); @@ -559,8 +550,8 @@ impl ServerSetup { }); } - /// Draw chain validation mode setup ui. - pub fn validation_mode_ui(&mut self, ui: &mut egui::Ui) { + /// Draw chain validation mode setup content. + pub fn validation_mode_ui(&mut self, ui: &mut Ui) { let validate = NodeConfig::is_full_chain_validation(); View::checkbox(ui, validate, t!("network_settings.full_validation"), || { NodeConfig::toggle_full_chain_validation(); @@ -573,8 +564,8 @@ impl ServerSetup { ); } - /// Draw archive mode setup ui. - pub fn archive_mode_ui(&mut self, ui: &mut egui::Ui) { + /// Draw archive mode setup content. + pub fn archive_mode_ui(&mut self, ui: &mut Ui) { let archive_mode = NodeConfig::is_archive_mode(); View::checkbox(ui, archive_mode, t!("network_settings.archive_mode"), || { NodeConfig::toggle_archive_mode(); diff --git a/src/gui/views/network/configs/p2p.rs b/src/gui/views/network/configs/p2p.rs index 6ddbed9..aa04af4 100644 --- a/src/gui/views/network/configs/p2p.rs +++ b/src/gui/views/network/configs/p2p.rs @@ -10,5 +10,4 @@ // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and -// limitations under the License. - +// limitations under the License. \ No newline at end of file diff --git a/src/gui/views/network/configs/pool.rs b/src/gui/views/network/configs/pool.rs index 6ddbed9..ae4555c 100644 --- a/src/gui/views/network/configs/pool.rs +++ b/src/gui/views/network/configs/pool.rs @@ -12,3 +12,518 @@ // See the License for the specific language governing permissions and // limitations under the License. +use egui::{Id, RichText, TextStyle, Ui, Widget}; + +use crate::gui::{Colors, Navigator}; +use crate::gui::icons::{BEZIER_CURVE, BOUNDING_BOX, CHART_SCATTER, CIRCLES_THREE, CLOCK_COUNTDOWN, HAND_COINS}; +use crate::gui::platform::PlatformCallbacks; +use crate::gui::views::{Modal, ModalPosition, View}; +use crate::gui::views::network::settings::NetworkSettings; +use crate::node::NodeConfig; + +/// Memory pool setup ui section. +pub struct PoolSetup { + /// Base fee value that's accepted into the pool. + fee_base_edit: String, + + /// Reorg cache retention period value in minutes. + reorg_period_edit: String, + + /// Maximum number of transactions allowed in the pool. + pool_size_edit: String, + + /// Maximum number of transactions allowed in the stempool. + stempool_size_edit: String, + + /// Maximum total weight of transactions to build a block. + max_weight_edit: String, +} + +impl Default for PoolSetup { + fn default() -> Self { + Self { + fee_base_edit: NodeConfig::get_base_fee(), + reorg_period_edit: NodeConfig::get_reorg_cache_period(), + pool_size_edit: NodeConfig::get_max_pool_size(), + stempool_size_edit: NodeConfig::get_max_stempool_size(), + max_weight_edit: NodeConfig::get_mineable_max_weight(), + } + } +} + +impl PoolSetup { + /// Identifier for base fee value [`Modal`]. + pub const FEE_BASE_MODAL: &'static str = "fee_base"; + /// Identifier for reorg cache retention period value [`Modal`]. + pub const REORG_PERIOD_MODAL: &'static str = "reorg_period"; + /// Identifier for maximum number of transactions in the pool [`Modal`]. + pub const POOL_SIZE_MODAL: &'static str = "pool_size"; + /// Identifier for maximum number of transactions in the stempool [`Modal`]. + pub const STEMPOOL_SIZE_MODAL: &'static str = "stempool_size"; + /// Identifier for maximum total weight of transactions [`Modal`]. + pub const MAX_WEIGHT_MODAL: &'static str = "max_weight"; + + pub fn ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) { + View::sub_title(ui, format!("{} {}", CHART_SCATTER, t!("network_settings.tx_pool"))); + View::horizontal_line(ui, Colors::STROKE); + ui.add_space(6.0); + + ui.vertical_centered(|ui| { + // Show base fee setup. + self.fee_base_ui(ui, cb); + + ui.add_space(6.0); + View::horizontal_line(ui, Colors::ITEM_STROKE); + ui.add_space(6.0); + + // Show reorg cache retention period setup. + self.reorg_period_ui(ui, cb); + + ui.add_space(6.0); + View::horizontal_line(ui, Colors::ITEM_STROKE); + ui.add_space(6.0); + + // Show pool size setup. + self.pool_size_ui(ui, cb); + + ui.add_space(6.0); + View::horizontal_line(ui, Colors::ITEM_STROKE); + ui.add_space(6.0); + + // Show stem pool size setup. + self.stempool_size_ui(ui, cb); + + ui.add_space(6.0); + View::horizontal_line(ui, Colors::ITEM_STROKE); + ui.add_space(6.0); + + // Show max weight of transactions setup. + self.max_weight_ui(ui, cb); + }); + } + + /// Draw fee base setup content. + fn fee_base_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) { + ui.label(RichText::new(t!("network_settings.pool_fee")) + .size(16.0) + .color(Colors::GRAY) + ); + ui.add_space(6.0); + + let fee = NodeConfig::get_base_fee(); + View::button(ui, format!("{} {}", HAND_COINS, fee.clone()), Colors::BUTTON, || { + // Setup values for modal. + self.fee_base_edit = fee; + // Show fee setup modal. + let fee_modal = Modal::new(Self::FEE_BASE_MODAL) + .position(ModalPosition::CenterTop) + .title(t!("network_settings.change_value")); + Navigator::show_modal(fee_modal); + cb.show_keyboard(); + }); + ui.add_space(6.0); + } + + /// Draw fee base [`Modal`] content. + pub fn fee_base_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { + ui.add_space(6.0); + ui.vertical_centered(|ui| { + ui.label(RichText::new(t!("network_settings.pool_fee")) + .size(18.0) + .color(Colors::GRAY)); + ui.add_space(8.0); + + // Draw fee base text edit. + let text_edit_resp = egui::TextEdit::singleline(&mut self.fee_base_edit) + .id(Id::from(modal.id)) + .font(TextStyle::Heading) + .desired_width(70.0) + .cursor_at_end(true) + .ui(ui); + text_edit_resp.request_focus(); + if text_edit_resp.clicked() { + cb.show_keyboard(); + } + + // Show error when specified value is not valid or reminder to restart enabled node. + if self.fee_base_edit.parse::().is_err() { + ui.add_space(12.0); + ui.label(RichText::new(t!("network_settings.not_valid_value")) + .size(18.0) + .color(Colors::RED)); + } else { + NetworkSettings::node_restart_required_ui(ui); + } + ui.add_space(12.0); + + // Show modal buttons. + ui.scope(|ui| { + // Setup spacing between buttons. + ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0); + + // Save button callback. + let on_save = || { + if let Ok(fee) = self.fee_base_edit.parse::() { + NodeConfig::save_base_fee(fee); + cb.hide_keyboard(); + modal.close(); + } + }; + + ui.columns(2, |columns| { + columns[0].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.cancel"), Colors::WHITE, || { + // Close modal. + cb.hide_keyboard(); + modal.close(); + }); + }); + columns[1].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.save"), Colors::WHITE, on_save); + }); + }); + ui.add_space(6.0); + }); + }); + } + + /// Draw reorg cache retention period setup content. + fn reorg_period_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) { + ui.label(RichText::new(t!("network_settings.reorg_period")) + .size(16.0) + .color(Colors::GRAY) + ); + ui.add_space(6.0); + + let period = NodeConfig::get_reorg_cache_period(); + View::button(ui, format!("{} {}", CLOCK_COUNTDOWN, period.clone()), Colors::BUTTON, || { + // Setup values for modal. + self.reorg_period_edit = period; + // Show reorg period setup modal. + let reorg_modal = Modal::new(Self::REORG_PERIOD_MODAL) + .position(ModalPosition::CenterTop) + .title(t!("network_settings.change_value")); + Navigator::show_modal(reorg_modal); + cb.show_keyboard(); + }); + ui.add_space(6.0); + } + + /// Draw reorg cache retention period [`Modal`] content. + pub fn reorg_period_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { + ui.add_space(6.0); + ui.vertical_centered(|ui| { + ui.label(RichText::new(t!("network_settings.reorg_period")) + .size(18.0) + .color(Colors::GRAY)); + ui.add_space(8.0); + + // Draw reorg period text edit. + let text_edit_resp = egui::TextEdit::singleline(&mut self.reorg_period_edit) + .id(Id::from(modal.id)) + .font(TextStyle::Heading) + .desired_width(36.0) + .cursor_at_end(true) + .ui(ui); + text_edit_resp.request_focus(); + if text_edit_resp.clicked() { + cb.show_keyboard(); + } + + // Show error when specified value is not valid or reminder to restart enabled node. + if self.reorg_period_edit.parse::().is_err() { + ui.add_space(12.0); + ui.label(RichText::new(t!("network_settings.reorg_period")) + .size(18.0) + .color(Colors::RED)); + } else { + NetworkSettings::node_restart_required_ui(ui); + } + ui.add_space(12.0); + + // Show modal buttons. + ui.scope(|ui| { + // Setup spacing between buttons. + ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0); + + // Save button callback. + let on_save = || { + if let Ok(period) = self.reorg_period_edit.parse::() { + NodeConfig::save_reorg_cache_period(period); + cb.hide_keyboard(); + modal.close(); + } + }; + + ui.columns(2, |columns| { + columns[0].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.cancel"), Colors::WHITE, || { + // Close modal. + cb.hide_keyboard(); + modal.close(); + }); + }); + columns[1].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.save"), Colors::WHITE, on_save); + }); + }); + ui.add_space(6.0); + }); + }); + } + + /// Draw maximum number of transactions in the pool setup content. + fn pool_size_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) { + ui.label(RichText::new(t!("network_settings.max_tx_pool")) + .size(16.0) + .color(Colors::GRAY) + ); + ui.add_space(6.0); + + let size = NodeConfig::get_max_pool_size(); + View::button(ui, format!("{} {}", CIRCLES_THREE, size.clone()), Colors::BUTTON, || { + // Setup values for modal. + self.pool_size_edit = size; + // Show pool size setup modal. + let size_modal = Modal::new(Self::POOL_SIZE_MODAL) + .position(ModalPosition::CenterTop) + .title(t!("network_settings.change_value")); + Navigator::show_modal(size_modal); + cb.show_keyboard(); + }); + ui.add_space(6.0); + } + + /// Draw maximum number of transactions in the pool [`Modal`] content. + pub fn pool_size_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { + ui.add_space(6.0); + ui.vertical_centered(|ui| { + ui.label(RichText::new(t!("network_settings.max_tx_pool")) + .size(18.0) + .color(Colors::GRAY)); + ui.add_space(8.0); + + // Draw pool size text edit. + let text_edit_resp = egui::TextEdit::singleline(&mut self.pool_size_edit) + .id(Id::from(modal.id)) + .font(TextStyle::Heading) + .desired_width(58.0) + .cursor_at_end(true) + .ui(ui); + text_edit_resp.request_focus(); + if text_edit_resp.clicked() { + cb.show_keyboard(); + } + + // Show error when specified value is not valid or reminder to restart enabled node. + if self.pool_size_edit.parse::().is_err() { + ui.add_space(12.0); + ui.label(RichText::new(t!("network_settings.not_valid_value")) + .size(18.0) + .color(Colors::RED)); + } else { + NetworkSettings::node_restart_required_ui(ui); + } + ui.add_space(12.0); + + // Show modal buttons. + ui.scope(|ui| { + // Setup spacing between buttons. + ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0); + + // Save button callback. + let on_save = || { + if let Ok(size) = self.pool_size_edit.parse::() { + NodeConfig::save_max_pool_size(size); + cb.hide_keyboard(); + modal.close(); + } + }; + + ui.columns(2, |columns| { + columns[0].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.cancel"), Colors::WHITE, || { + // Close modal. + cb.hide_keyboard(); + modal.close(); + }); + }); + columns[1].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.save"), Colors::WHITE, on_save); + }); + }); + ui.add_space(6.0); + }); + }); + } + + /// Draw maximum number of transactions in the stempool setup content. + fn stempool_size_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) { + ui.label(RichText::new(t!("network_settings.max_tx_stempool")) + .size(16.0) + .color(Colors::GRAY) + ); + ui.add_space(6.0); + + let size = NodeConfig::get_max_stempool_size(); + View::button(ui, format!("{} {}", BEZIER_CURVE, size.clone()), Colors::BUTTON, || { + // Setup values for modal. + self.stempool_size_edit = size; + // Show stempool size setup modal. + let stem_modal = Modal::new(Self::STEMPOOL_SIZE_MODAL) + .position(ModalPosition::CenterTop) + .title(t!("network_settings.change_value")); + Navigator::show_modal(stem_modal); + cb.show_keyboard(); + }); + ui.add_space(6.0); + } + + /// Draw maximum number of transactions in the stempool [`Modal`] content. + pub fn stempool_size_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { + ui.add_space(6.0); + ui.vertical_centered(|ui| { + ui.label(RichText::new(t!("network_settings.max_tx_stempool")) + .size(18.0) + .color(Colors::GRAY)); + ui.add_space(8.0); + + // Draw stempool size text edit. + let text_edit_resp = egui::TextEdit::singleline(&mut self.stempool_size_edit) + .id(Id::from(modal.id)) + .font(TextStyle::Heading) + .desired_width(58.0) + .cursor_at_end(true) + .ui(ui); + text_edit_resp.request_focus(); + if text_edit_resp.clicked() { + cb.show_keyboard(); + } + + // Show error when specified value is not valid or reminder to restart enabled node. + if self.stempool_size_edit.parse::().is_err() { + ui.add_space(12.0); + ui.label(RichText::new(t!("network_settings.not_valid_value")) + .size(18.0) + .color(Colors::RED)); + } else { + NetworkSettings::node_restart_required_ui(ui); + } + ui.add_space(12.0); + + // Show modal buttons. + ui.scope(|ui| { + // Setup spacing between buttons. + ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0); + + // Save button callback. + let on_save = || { + if let Ok(size) = self.stempool_size_edit.parse::() { + NodeConfig::save_max_stempool_size(size); + cb.hide_keyboard(); + modal.close(); + } + }; + + ui.columns(2, |columns| { + columns[0].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.cancel"), Colors::WHITE, || { + // Close modal. + cb.hide_keyboard(); + modal.close(); + }); + }); + columns[1].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.save"), Colors::WHITE, on_save); + }); + }); + ui.add_space(6.0); + }); + }); + } + + /// Draw maximum total weight of transactions setup content. + fn max_weight_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) { + ui.label(RichText::new(t!("network_settings.max_tx_weight")) + .size(16.0) + .color(Colors::GRAY) + ); + ui.add_space(6.0); + + let weight = NodeConfig::get_mineable_max_weight(); + View::button(ui, format!("{} {}", BOUNDING_BOX, weight.clone()), Colors::BUTTON, || { + // Setup values for modal. + self.max_weight_edit = weight; + // Show total tx weight setup modal. + let weight_modal = Modal::new(Self::MAX_WEIGHT_MODAL) + .position(ModalPosition::CenterTop) + .title(t!("network_settings.change_value")); + Navigator::show_modal(weight_modal); + cb.show_keyboard(); + }); + ui.add_space(6.0); + } + + /// Draw maximum total weight of transactions [`Modal`] content. + pub fn max_weight_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { + ui.add_space(6.0); + ui.vertical_centered(|ui| { + ui.label(RichText::new(t!("network_settings.max_tx_weight")) + .size(18.0) + .color(Colors::GRAY)); + ui.add_space(8.0); + + // Draw tx weight text edit. + let text_edit_resp = egui::TextEdit::singleline(&mut self.max_weight_edit) + .id(Id::from(modal.id)) + .font(TextStyle::Heading) + .desired_width(58.0) + .cursor_at_end(true) + .ui(ui); + text_edit_resp.request_focus(); + if text_edit_resp.clicked() { + cb.show_keyboard(); + } + + // Show error when specified value is not valid or reminder to restart enabled node. + if self.max_weight_edit.parse::().is_err() { + ui.add_space(12.0); + ui.label(RichText::new(t!("network_settings.not_valid_value")) + .size(18.0) + .color(Colors::RED)); + } else { + NetworkSettings::node_restart_required_ui(ui); + } + ui.add_space(12.0); + + // Show modal buttons. + ui.scope(|ui| { + // Setup spacing between buttons. + ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0); + + // Save button callback. + let on_save = || { + if let Ok(weight) = self.max_weight_edit.parse::() { + NodeConfig::save_mineable_max_weight(weight); + cb.hide_keyboard(); + modal.close(); + } + }; + + ui.columns(2, |columns| { + columns[0].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.cancel"), Colors::WHITE, || { + // Close modal. + cb.hide_keyboard(); + modal.close(); + }); + }); + columns[1].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.save"), Colors::WHITE, on_save); + }); + }); + ui.add_space(6.0); + }); + }); + } +} \ No newline at end of file diff --git a/src/gui/views/network/configs/stratum.rs b/src/gui/views/network/configs/stratum.rs index 0951fb9..c4537ca 100644 --- a/src/gui/views/network/configs/stratum.rs +++ b/src/gui/views/network/configs/stratum.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use egui::{Id, RichText, TextStyle, Widget}; +use egui::{Id, RichText, TextStyle, Ui, Widget}; use crate::gui::{Colors, Navigator}; use crate::gui::icons::{BARBELL, HARD_DRIVES, PLUG, TIMER}; @@ -22,40 +22,41 @@ use crate::gui::views::network::settings::NetworkSettings; use crate::node::{Node, NodeConfig}; /// Stratum server setup ui section. -pub struct StratumServerSetup { - /// Stratum port value to be used inside edit modal. +pub struct StratumSetup { + /// IP Addresses available at system. + available_ips: Vec, + + /// Stratum port value. stratum_port_edit: String, - /// Flag to check if stratum port is available inside edit modal. + /// Flag to check if stratum port is available. stratum_port_available_edit: bool, - /// Flag to check if stratum port is available from saved config value. + /// Flag to check if stratum port from saved config value is available. pub(crate) is_port_available: bool, - /// Attempt time value to be used inside edit modal. + /// Attempt time value in seconds to mine on a particular header. attempt_time_edit: String, - /// Minimum share difficulty value to be used inside edit modal. + /// Minimum share difficulty value to request from miners. min_share_diff_edit: String } -impl Default for StratumServerSetup { +impl Default for StratumSetup { fn default() -> Self { let (ip, port) = NodeConfig::get_stratum_address(); let is_port_available = NodeConfig::is_stratum_port_available(&ip, &port); - let attempt_time = NodeConfig::get_stratum_attempt_time(); - let min_share_diff = NodeConfig::get_stratum_min_share_diff(); Self { + available_ips: NodeConfig::get_ip_addrs(), stratum_port_edit: port, stratum_port_available_edit: is_port_available, is_port_available, - attempt_time_edit: attempt_time, - min_share_diff_edit: min_share_diff - + attempt_time_edit: NodeConfig::get_stratum_attempt_time(), + min_share_diff_edit: NodeConfig::get_stratum_min_share_diff() } } } -impl StratumServerSetup { +impl StratumSetup { /// Identifier for stratum port [`Modal`]. pub const STRATUM_PORT_MODAL: &'static str = "stratum_port"; /// Identifier for attempt time [`Modal`]. @@ -63,9 +64,9 @@ impl StratumServerSetup { /// Identifier for minimum share difficulty [`Modal`]. pub const MIN_SHARE_DIFF_MODAL: &'static str = "stratum_min_share_diff"; - pub fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) { + pub fn ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) { View::sub_title(ui, format!("{} {}", HARD_DRIVES, t!("network_mining.server_setup"))); - View::horizontal_line(ui, Colors::ITEM_STROKE); + View::horizontal_line(ui, Colors::STROKE); ui.add_space(6.0); ui.vertical_centered(|ui| { @@ -98,21 +99,20 @@ impl StratumServerSetup { ui.add_space(6.0); // Show message when IP addresses are not available on the system. - let all_ips = NodeConfig::get_ip_addrs(); - if all_ips.is_empty() { + if self.available_ips.is_empty() { NetworkSettings::no_ip_address_ui(ui); return; } ui.vertical_centered(|ui| { - ui.label(RichText::new(t!("network_settings.ip")) + ui.label(RichText::new(t!("network_settings.stratum_ip")) .size(16.0) .color(Colors::GRAY) ); ui.add_space(6.0); // Show stratum IP addresses to select. let (ip, port) = NodeConfig::get_stratum_address(); - NetworkSettings::ip_addrs_ui(ui, &ip, &all_ips, |selected_ip| { + NetworkSettings::ip_addrs_ui(ui, &ip, &self.available_ips, |selected_ip| { NodeConfig::save_stratum_address(selected_ip, &port); self.is_port_available = NodeConfig::is_stratum_port_available(selected_ip, &port); @@ -134,9 +134,9 @@ impl StratumServerSetup { }); } - /// Draw stratum port value setup ui. - fn port_setup_ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) { - ui.label(RichText::new(t!("network_settings.port")) + /// Draw stratum port value setup content. + fn port_setup_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) { + ui.label(RichText::new(t!("network_settings.stratum_port")) .size(16.0) .color(Colors::GRAY) ); @@ -166,8 +166,8 @@ impl StratumServerSetup { } } - /// Draw stratum port [`Modal`] content ui. - pub fn port_modal(&mut self, ui: &mut egui::Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { + /// Draw stratum port [`Modal`] content. + pub fn port_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { ui.add_space(6.0); ui.vertical_centered(|ui| { ui.label(RichText::new(t!("network_settings.stratum_port")) @@ -202,7 +202,7 @@ impl StratumServerSetup { // Setup spacing between buttons. ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0); - // Save button callback + // Save button callback. let on_save = || { // Check if port is available. let (stratum_ip, _) = NodeConfig::get_stratum_address(); @@ -239,8 +239,8 @@ impl StratumServerSetup { }); } - /// Draw attempt time value setup ui. - fn attempt_time_ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) { + /// Draw attempt time value setup content. + fn attempt_time_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) { ui.label(RichText::new(t!("network_settings.attempt_time_desc")) .size(16.0) .color(Colors::GRAY) @@ -262,8 +262,8 @@ impl StratumServerSetup { ui.add_space(12.0); } - /// Draw attempt time [`Modal`] content ui. - pub fn attempt_modal(&mut self, ui: &mut egui::Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { + /// Draw attempt time [`Modal`] content. + pub fn attempt_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { ui.add_space(6.0); ui.vertical_centered(|ui| { ui.label(RichText::new(t!("network_settings.attempt_time")) @@ -275,7 +275,7 @@ impl StratumServerSetup { let text_edit_resp = egui::TextEdit::singleline(&mut self.attempt_time_edit) .id(Id::from(modal.id)) .font(TextStyle::Heading) - .desired_width(34.0) + .desired_width(36.0) .cursor_at_end(true) .ui(ui); text_edit_resp.request_focus(); @@ -300,7 +300,7 @@ impl StratumServerSetup { // Setup spacing between buttons. ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0); - // Save button callback + // Save button callback. let on_save = || { if let Ok(time) = self.attempt_time_edit.parse::() { NodeConfig::save_stratum_attempt_time(time); @@ -325,8 +325,8 @@ impl StratumServerSetup { }); } - /// Draw minimum share difficulty value setup ui. - fn min_diff_ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) { + /// Draw minimum share difficulty value setup content. + fn min_diff_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) { ui.label(RichText::new(t!("network_settings.min_share_diff")) .size(16.0) .color(Colors::GRAY) @@ -348,8 +348,8 @@ impl StratumServerSetup { ui.add_space(12.0); } - /// Draw minimum acceptable share difficulty [`Modal`] content ui. - pub fn min_diff_modal(&mut self, ui: &mut egui::Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { + /// Draw minimum acceptable share difficulty [`Modal`] content. + pub fn min_diff_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { ui.add_space(6.0); ui.vertical_centered(|ui| { ui.label(RichText::new(t!("network_settings.min_share_diff")) @@ -361,7 +361,7 @@ impl StratumServerSetup { let text_edit_resp = egui::TextEdit::singleline(&mut self.min_share_diff_edit) .id(Id::from(modal.id)) .font(TextStyle::Heading) - .desired_width(34.0) + .desired_width(36.0) .cursor_at_end(true) .ui(ui); text_edit_resp.request_focus(); @@ -386,7 +386,7 @@ impl StratumServerSetup { // Setup spacing between buttons. ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0); - // Save button callback + // Save button callback. let on_save = || { if let Ok(diff) = self.min_share_diff_edit.parse::() { NodeConfig::save_stratum_min_share_diff(diff); diff --git a/src/gui/views/network/container.rs b/src/gui/views/network/container.rs index 1ad9844..f157fe3 100644 --- a/src/gui/views/network/container.rs +++ b/src/gui/views/network/container.rs @@ -24,8 +24,10 @@ use crate::gui::{Colors, Navigator}; use crate::gui::icons::{CARDHOLDER, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE}; use crate::gui::platform::PlatformCallbacks; use crate::gui::views::{Modal, ModalContainer, TitlePanel, View}; -use crate::gui::views::network::configs::server::ServerSetup; -use crate::gui::views::network::configs::stratum::StratumServerSetup; +use crate::gui::views::network::configs::dandelion::DandelionSetup; +use crate::gui::views::network::configs::node::NodeSetup; +use crate::gui::views::network::configs::pool::PoolSetup; +use crate::gui::views::network::configs::stratum::StratumSetup; use crate::gui::views::network::metrics::NetworkMetrics; use crate::gui::views::network::mining::NetworkMining; use crate::gui::views::network::node::NetworkNode; @@ -67,15 +69,29 @@ impl Default for NetworkContainer { Self { current_tab: Box::new(NetworkNode::default()), modal_ids: vec![ + // Network settings modals. NetworkSettings::NODE_RESTART_REQUIRED_MODAL, NetworkSettings::RESET_SETTINGS_MODAL, - StratumServerSetup::STRATUM_PORT_MODAL, - StratumServerSetup::ATTEMPT_TIME_MODAL, - StratumServerSetup::MIN_SHARE_DIFF_MODAL, - ServerSetup::API_PORT_MODAL, - ServerSetup::API_SECRET_MODAL, - ServerSetup::FOREIGN_API_SECRET_MODAL, - ServerSetup::FTL_MODAL + // Node setup modals. + NodeSetup::API_PORT_MODAL, + NodeSetup::API_SECRET_MODAL, + NodeSetup::FOREIGN_API_SECRET_MODAL, + NodeSetup::FTL_MODAL, + // Stratum setup modals. + StratumSetup::STRATUM_PORT_MODAL, + StratumSetup::ATTEMPT_TIME_MODAL, + StratumSetup::MIN_SHARE_DIFF_MODAL, + // Pool setup modals. + PoolSetup::FEE_BASE_MODAL, + PoolSetup::REORG_PERIOD_MODAL, + PoolSetup::POOL_SIZE_MODAL, + PoolSetup::STEMPOOL_SIZE_MODAL, + PoolSetup::MAX_WEIGHT_MODAL, + // Dandelion setup modals. + DandelionSetup::EPOCH_MODAL, + DandelionSetup::EMBARGO_MODAL, + DandelionSetup::AGGREGATION_MODAL, + DandelionSetup::STEM_PROBABILITY_MODAL, ] } } @@ -240,7 +256,7 @@ impl NetworkContainer { // Repaint based on sync status if idle { - ui.ctx().request_repaint_after(Duration::from_millis(600)); + ui.ctx().request_repaint_after(Duration::from_millis(250)); } else { ui.ctx().request_repaint(); } diff --git a/src/gui/views/network/mining.rs b/src/gui/views/network/mining.rs index e670a51..8874093 100644 --- a/src/gui/views/network/mining.rs +++ b/src/gui/views/network/mining.rs @@ -22,12 +22,12 @@ use crate::gui::icons::{BARBELL, CLOCK_AFTERNOON, COMPUTER_TOWER, CPU, CUBE, FAD use crate::gui::platform::PlatformCallbacks; use crate::gui::views::{Modal, NetworkContainer, View}; use crate::gui::views::network::{NetworkTab, NetworkTabType}; -use crate::gui::views::network::configs::stratum::StratumServerSetup; +use crate::gui::views::network::configs::stratum::StratumSetup; use crate::node::{Node, NodeConfig}; #[derive(Default)] pub struct NetworkMining { - stratum_server_setup: StratumServerSetup + stratum_server_setup: StratumSetup } impl NetworkTab for NetworkMining { @@ -199,7 +199,7 @@ impl NetworkTab for NetworkMining { fn on_modal_ui(&mut self, ui: &mut egui::Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { match modal.id { - StratumServerSetup::STRATUM_PORT_MODAL => { + StratumSetup::STRATUM_PORT_MODAL => { self.stratum_server_setup.port_modal(ui, modal, cb); }, _ => {} diff --git a/src/gui/views/network/settings.rs b/src/gui/views/network/settings.rs index 28d8763..ea59add 100644 --- a/src/gui/views/network/settings.rs +++ b/src/gui/views/network/settings.rs @@ -12,9 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::net::IpAddr; -use std::str::FromStr; - use egui::{RichText, ScrollArea}; use crate::gui::{Colors, Navigator}; @@ -22,14 +19,18 @@ use crate::gui::icons::ARROW_COUNTER_CLOCKWISE; use crate::gui::platform::PlatformCallbacks; use crate::gui::views::{Modal, ModalPosition, View}; use crate::gui::views::network::{NetworkTab, NetworkTabType}; -use crate::gui::views::network::configs::server::ServerSetup; -use crate::gui::views::network::configs::stratum::StratumServerSetup; +use crate::gui::views::network::configs::dandelion::DandelionSetup; +use crate::gui::views::network::configs::node::NodeSetup; +use crate::gui::views::network::configs::pool::PoolSetup; +use crate::gui::views::network::configs::stratum::StratumSetup; use crate::node::{Node, NodeConfig}; #[derive(Default)] pub struct NetworkSettings { - server_setup: ServerSetup, - stratum_server_setup: StratumServerSetup + node: NodeSetup, + stratum: StratumSetup, + pool: PoolSetup, + dandelion: DandelionSetup } impl NetworkTab for NetworkSettings { @@ -42,31 +43,59 @@ impl NetworkTab for NetworkSettings { .id_source("network_settings") .auto_shrink([false; 2]) .show(ui, |ui| { - self.server_setup.ui(ui, cb); - self.stratum_server_setup.ui(ui, cb); + self.node.ui(ui, cb); + + ui.add_space(6.0); + View::horizontal_line(ui, Colors::STROKE); + ui.add_space(4.0); + + self.stratum.ui(ui, cb); + + ui.add_space(6.0); + View::horizontal_line(ui, Colors::STROKE); + ui.add_space(4.0); + + self.pool.ui(ui, cb); + + ui.add_space(6.0); + View::horizontal_line(ui, Colors::STROKE); + ui.add_space(4.0); + + self.dandelion.ui(ui, cb); + + ui.add_space(6.0); + View::horizontal_line(ui, Colors::STROKE); + ui.add_space(6.0); + self.reset_settings_ui(ui); }); } fn on_modal_ui(&mut self, ui: &mut egui::Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { match modal.id { + // Settings modals. Self::NODE_RESTART_REQUIRED_MODAL => self.node_restart_required_modal(ui, modal), Self::RESET_SETTINGS_MODAL => self.reset_settings_confirmation_modal(ui, modal), - - ServerSetup::API_PORT_MODAL => self.server_setup.api_port_modal(ui, modal, cb), - ServerSetup::API_SECRET_MODAL => self.server_setup.secret_modal(ui, modal, cb), - ServerSetup::FOREIGN_API_SECRET_MODAL => self.server_setup.secret_modal(ui, modal, cb), - ServerSetup::FTL_MODAL => self.server_setup.ftl_modal(ui, modal, cb), - - StratumServerSetup::STRATUM_PORT_MODAL => { - self.stratum_server_setup.port_modal(ui, modal, cb); - } - StratumServerSetup::ATTEMPT_TIME_MODAL => { - self.stratum_server_setup.attempt_modal(ui, modal, cb); - } - StratumServerSetup::MIN_SHARE_DIFF_MODAL => { - self.stratum_server_setup.min_diff_modal(ui, modal, cb); - } + // Node server setup modals. + NodeSetup::API_PORT_MODAL => self.node.api_port_modal(ui, modal, cb), + NodeSetup::API_SECRET_MODAL => self.node.secret_modal(ui, modal, cb), + NodeSetup::FOREIGN_API_SECRET_MODAL => self.node.secret_modal(ui, modal, cb), + NodeSetup::FTL_MODAL => self.node.ftl_modal(ui, modal, cb), + // Stratum server setup modals. + StratumSetup::STRATUM_PORT_MODAL => self.stratum.port_modal(ui, modal, cb), + StratumSetup::ATTEMPT_TIME_MODAL => self.stratum.attempt_modal(ui, modal, cb), + StratumSetup::MIN_SHARE_DIFF_MODAL => self.stratum.min_diff_modal(ui, modal, cb), + // Pool setup modals. + PoolSetup::FEE_BASE_MODAL => self.pool.fee_base_modal(ui, modal, cb), + PoolSetup::REORG_PERIOD_MODAL => self.pool.reorg_period_modal(ui, modal, cb), + PoolSetup::POOL_SIZE_MODAL => self.pool.pool_size_modal(ui, modal, cb), + PoolSetup::STEMPOOL_SIZE_MODAL => self.pool.stempool_size_modal(ui, modal, cb), + PoolSetup::MAX_WEIGHT_MODAL => self.pool.max_weight_modal(ui, modal, cb), + // Dandelion setup modals. + DandelionSetup::EPOCH_MODAL => self.dandelion.epoch_modal(ui, modal, cb), + DandelionSetup::EMBARGO_MODAL => self.dandelion.embargo_modal(ui, modal, cb), + DandelionSetup::AGGREGATION_MODAL => self.dandelion.aggregation_modal(ui, modal, cb), + DandelionSetup::STEM_PROBABILITY_MODAL => self.dandelion.stem_prob_modal(ui, modal, cb), _ => {} } } @@ -80,13 +109,11 @@ impl NetworkSettings { /// Draw button to reset integrated node settings to default values. fn reset_settings_ui(&self, ui: &mut egui::Ui) { - View::horizontal_line(ui, Colors::ITEM_STROKE); - ui.add_space(6.0); ui.vertical_centered(|ui| { ui.label(RichText::new(t!("network_settings.reset_settings_desc")) .size(16.0) .color(Colors::TEXT)); - ui.add_space(10.0); + ui.add_space(8.0); let button_text = format!("{} {}", ARROW_COUNTER_CLOCKWISE, t!("network_settings.reset_settings")); @@ -200,48 +227,39 @@ impl NetworkSettings { /// Draw IP addresses as radio buttons. pub fn ip_addrs_ui(ui: &mut egui::Ui, saved_ip: &String, - ip_addrs: &Vec, + ips: &Vec, on_change: impl FnOnce(&String)) { - let saved_ip_addr = &IpAddr::from_str(saved_ip.as_str()).unwrap(); - let mut selected_ip_addr = saved_ip_addr; + let mut selected_ip = saved_ip; // Set first IP address as current if saved is not present at system. - if !ip_addrs.contains(selected_ip_addr) { - selected_ip_addr = ip_addrs.get(0).unwrap(); + if !ips.contains(saved_ip) { + selected_ip = ips.get(0).unwrap(); } ui.add_space(2.0); + // Show available IP addresses on the system. - let _ = ip_addrs.chunks(2).map(|x| { + let _ = ips.chunks(2).map(|x| { if x.len() == 2 { ui.columns(2, |columns| { - let ip_addr_l = x.get(0).unwrap(); + let ip_left = x.get(0).unwrap(); columns[0].vertical_centered(|ui| { - View::radio_value(ui, - &mut selected_ip_addr, - ip_addr_l, - ip_addr_l.to_string()); + View::radio_value(ui, &mut selected_ip, ip_left, ip_left.to_string()); }); - let ip_addr_r = x.get(1).unwrap(); + let ip_right = x.get(1).unwrap(); columns[1].vertical_centered(|ui| { - View::radio_value(ui, - &mut selected_ip_addr, - ip_addr_r, - ip_addr_r.to_string()); + View::radio_value(ui, &mut selected_ip, ip_right, ip_right.to_string()); }) }); } else { - let ip_addr = x.get(0).unwrap(); - View::radio_value(ui, - &mut selected_ip_addr, - ip_addr, - ip_addr.to_string()); + let ip = x.get(0).unwrap(); + View::radio_value(ui, &mut selected_ip, ip, ip.to_string()); } ui.add_space(12.0); }).collect::>(); - if saved_ip_addr != selected_ip_addr { - (on_change)(&selected_ip_addr.to_string()); + if saved_ip != selected_ip { + (on_change)(&selected_ip.to_string()); } } diff --git a/src/gui/views/views.rs b/src/gui/views/views.rs index 2e6353c..b071348 100644 --- a/src/gui/views/views.rs +++ b/src/gui/views/views.rs @@ -209,7 +209,7 @@ impl View { pub fn checkbox(ui: &mut egui::Ui, checked: bool, text: String, callback: impl FnOnce()) { let (text_value, color) = match checked { true => (format!("{} {}", CHECK_SQUARE, text), Colors::TEXT_BUTTON), - false => (format!("{} {}", SQUARE, text), Colors::TEXT) + false => (format!("{} {}", SQUARE, text), Colors::CHECKBOX) }; let br = Button::new(RichText::new(text_value).size(18.0).color(color)) diff --git a/src/node/config.rs b/src/node/config.rs index 6bb61b9..ea9059f 100644 --- a/src/node/config.rs +++ b/src/node/config.rs @@ -121,12 +121,12 @@ impl NodeConfig { } /// List of available IP addresses. - pub fn get_ip_addrs() -> Vec { + pub fn get_ip_addrs() -> Vec { let mut ip_addrs = Vec::new(); for net_if in pnet::datalink::interfaces() { for ip in net_if.ips { if ip.is_ipv4() { - ip_addrs.push(ip.ip()); + ip_addrs.push(ip.ip().to_string()); } } } @@ -563,7 +563,7 @@ impl NodeConfig { Settings::node_config_to_read().members.server.p2p_config.ban_window() } - /// Set how long a banned peer should stay banned in ms. + /// Save for how long a banned peer should stay banned in ms. pub fn save_ban_window(time: i64) { let mut w_node_config = Settings::node_config_to_update(); w_node_config.members.server.p2p_config.ban_window = Some(time); @@ -575,7 +575,7 @@ impl NodeConfig { Settings::node_config_to_read().members.server.p2p_config.peer_max_inbound_count() } - /// Set maximum number of inbound peer connections. + /// Save maximum number of inbound peer connections. pub fn save_max_inbound_count(count: u32) { let mut w_node_config = Settings::node_config_to_update(); w_node_config.members.server.p2p_config.peer_max_inbound_count = Some(count); @@ -587,7 +587,7 @@ impl NodeConfig { Settings::node_config_to_read().members.server.p2p_config.peer_max_outbound_count() } - /// Set maximum number of outbound peer connections. + /// Save maximum number of outbound peer connections. pub fn save_max_outbound_count(count: u32) { let mut w_node_config = Settings::node_config_to_update(); w_node_config.members.server.p2p_config.peer_max_outbound_count = Some(count); @@ -603,7 +603,7 @@ impl NodeConfig { .peer_min_preferred_outbound_count() } - /// Set minimum number of outbound peer connections. + /// Save minimum number of outbound peer connections. pub fn save_min_outbound_count(count: u32) { let mut w_node_config = Settings::node_config_to_update(); w_node_config.members.server.p2p_config.peer_min_preferred_outbound_count = Some(count); @@ -613,23 +613,23 @@ impl NodeConfig { // Pool settings /// Base fee that's accepted into the pool. - pub fn get_base_fee() -> u64 { - Settings::node_config_to_read().members.server.pool_config.accept_fee_base + pub fn get_base_fee() -> String { + Settings::node_config_to_read().members.server.pool_config.accept_fee_base.to_string() } - /// Set base fee that's accepted into the pool. + /// Save base fee that's accepted into the pool. pub fn save_base_fee(fee: u64) { let mut w_node_config = Settings::node_config_to_update(); w_node_config.members.server.pool_config.accept_fee_base = fee; w_node_config.save(); } - /// Reorg cache retention period in minute. - pub fn get_reorg_cache_period() -> u32 { - Settings::node_config_to_read().members.server.pool_config.reorg_cache_period + /// Reorg cache retention period in minutes. + pub fn get_reorg_cache_period() -> String { + Settings::node_config_to_read().members.server.pool_config.reorg_cache_period.to_string() } - /// Set reorg cache retention period in minute. + /// Save reorg cache retention period in minutes. pub fn save_reorg_cache_period(period: u32) { let mut w_node_config = Settings::node_config_to_update(); w_node_config.members.server.pool_config.reorg_cache_period = period; @@ -637,11 +637,11 @@ impl NodeConfig { } /// Max amount of transactions at pool. - pub fn get_max_pool_size() -> usize { - Settings::node_config_to_read().members.server.pool_config.max_pool_size + pub fn get_max_pool_size() -> String { + Settings::node_config_to_read().members.server.pool_config.max_pool_size.to_string() } - /// Set max amount of transactions at pool. + /// Save max amount of transactions at pool. pub fn save_max_pool_size(amount: usize) { let mut w_node_config = Settings::node_config_to_update(); w_node_config.members.server.pool_config.max_pool_size = amount; @@ -649,11 +649,11 @@ impl NodeConfig { } /// Max amount of transactions at stem pool. - pub fn get_max_stempool_size() -> usize { - Settings::node_config_to_read().members.server.pool_config.max_stempool_size + pub fn get_max_stempool_size() -> String { + Settings::node_config_to_read().members.server.pool_config.max_stempool_size.to_string() } - /// Set max amount of transactions at stem pool. + /// Save max amount of transactions at stem pool. pub fn save_max_stempool_size(amount: usize) { let mut w_node_config = Settings::node_config_to_update(); w_node_config.members.server.pool_config.max_stempool_size = amount; @@ -661,8 +661,8 @@ impl NodeConfig { } /// Max total weight of transactions that can get selected to build a block. - pub fn get_mineable_max_weight() -> u64 { - Settings::node_config_to_read().members.server.pool_config.mineable_max_weight + pub fn get_mineable_max_weight() -> String { + Settings::node_config_to_read().members.server.pool_config.mineable_max_weight.to_string() } /// Set max total weight of transactions that can get selected to build a block. @@ -674,37 +674,49 @@ impl NodeConfig { // Dandelion settings - /// Dandelion epoch duration in secs. - pub fn get_epoch() -> u16 { - Settings::node_config_to_read().members.server.dandelion_config.epoch_secs + /// Dandelion epoch duration in seconds. + pub fn get_dandelion_epoch() -> String { + Settings::node_config_to_read().members.server.dandelion_config.epoch_secs.to_string() } - /// Set Dandelion epoch duration in secs. - pub fn save_epoch(secs: u16) { + /// Save Dandelion epoch duration in seconds. + pub fn save_dandelion_epoch(secs: u16) { let mut w_node_config = Settings::node_config_to_update(); w_node_config.members.server.dandelion_config.epoch_secs = secs; w_node_config.save(); } - /// Dandelion embargo timer in secs. + /// Dandelion embargo timer in seconds. /// Fluff and broadcast after embargo expires if tx not seen on network. - pub fn get_embargo() -> u16 { - Settings::node_config_to_read().members.server.dandelion_config.embargo_secs + pub fn get_dandelion_embargo() -> String { + Settings::node_config_to_read().members.server.dandelion_config.embargo_secs.to_string() } - /// Set Dandelion embargo timer. - pub fn save_embargo(secs: u16) { + /// Save Dandelion embargo timer in seconds. + pub fn save_dandelion_embargo(secs: u16) { let mut w_node_config = Settings::node_config_to_update(); w_node_config.members.server.dandelion_config.embargo_secs = secs; w_node_config.save(); } - /// Dandelion stem probability (default: stem 90% of the time, fluff 10% of the time). - pub fn get_stem_probability() -> u8 { - Settings::node_config_to_read().members.server.dandelion_config.stem_probability + /// Dandelion aggregation period in seconds. + pub fn get_dandelion_aggregation() -> String { + Settings::node_config_to_read().members.server.dandelion_config.aggregation_secs.to_string() } - /// Set Dandelion stem probability. + /// Save Dandelion aggregation period in seconds. + pub fn save_dandelion_aggregation(secs: u16) { + let mut w_node_config = Settings::node_config_to_update(); + w_node_config.members.server.dandelion_config.aggregation_secs = secs; + w_node_config.save(); + } + + /// Dandelion stem probability (default: stem 90% of the time, fluff 10% of the time). + pub fn get_stem_probability() -> String { + Settings::node_config_to_read().members.server.dandelion_config.stem_probability.to_string() + } + + /// Save Dandelion stem probability. pub fn save_stem_probability(percent: u8) { let mut w_node_config = Settings::node_config_to_update(); w_node_config.members.server.dandelion_config.stem_probability = percent; @@ -720,7 +732,7 @@ impl NodeConfig { pub fn toggle_always_stem_our_txs() { let stem_txs = Self::always_stem_our_txs(); let mut w_node_config = Settings::node_config_to_update(); - w_node_config.members.server.dandelion_config.always_stem_our_txs = stem_txs; + w_node_config.members.server.dandelion_config.always_stem_our_txs = !stem_txs; w_node_config.save(); } } \ No newline at end of file