From 38bb68736bb2cc6355e62233045f733b060cf6c2 Mon Sep 17 00:00:00 2001 From: ardocrat Date: Thu, 1 Aug 2024 01:59:51 +0300 Subject: [PATCH] stratum: wallet selection, wallet api port saving, fix stratum config saving, modules optimization --- locales/de.yml | 3 +- locales/en.yml | 1 + locales/fr.yml | 1 + locales/ru.yml | 1 + locales/tr.yml | 1 + src/gui/views/content.rs | 4 +- src/gui/views/mod.rs | 6 +- src/gui/views/network/connections.rs | 5 +- src/gui/views/network/content.rs | 3 +- src/gui/views/network/metrics.rs | 3 +- src/gui/views/network/mining.rs | 3 +- src/gui/views/network/node.rs | 3 +- src/gui/views/network/setup/node.rs | 3 +- src/gui/views/network/setup/stratum.rs | 84 ++++-- src/gui/views/wallets/content.rs | 11 +- src/gui/views/wallets/mod.rs | 2 +- src/gui/views/wallets/modals/conn.rs | 12 +- src/gui/views/wallets/modals/mod.rs | 5 +- src/gui/views/wallets/modals/wallets.rs | 135 ++++++++++ .../wallets/wallet/settings/connection.rs | 5 +- src/node/config.rs | 248 +++++++++--------- src/node/stratum.rs | 12 +- src/wallet/config.rs | 16 +- src/wallet/wallet.rs | 17 +- 24 files changed, 396 insertions(+), 188 deletions(-) create mode 100644 src/gui/views/wallets/modals/wallets.rs diff --git a/locales/de.yml b/locales/de.yml index 4b50f39..c6fa96c 100644 --- a/locales/de.yml +++ b/locales/de.yml @@ -227,6 +227,7 @@ network_settings: port_unavailable: Der angegebene Port ist nicht verfügbar restart_node_required: Ein Neustart der Node ist erforderlich, um die Änderungen zu übernehmen. choose_wallet: Wählen Wallet + stratum_wallet_warning: Wallet muss geöffnet sein, um Belohnungen zu erhalten. enable: Aktivieren disable: Deaktivieren restart: Neustarten @@ -288,4 +289,4 @@ modal: add: Hinzufügen modal_exit: description: Sind Sie sicher, dass Sie die Anwendung beenden wollen? - exit: Schließen + exit: Schließen \ No newline at end of file diff --git a/locales/en.yml b/locales/en.yml index 476035d..1c783cd 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -227,6 +227,7 @@ network_settings: port_unavailable: Specified port is unavailable restart_node_required: Node restart is required to apply changes. choose_wallet: Choose wallet + stratum_wallet_warning: Wallet must be opened to receive rewards. enable: Enable disable: Disable restart: Restart diff --git a/locales/fr.yml b/locales/fr.yml index ea2568c..64e9879 100644 --- a/locales/fr.yml +++ b/locales/fr.yml @@ -227,6 +227,7 @@ network_settings: port_unavailable: Le port spécifié est indisponible restart_node_required: Le redémarrage du noeud est nécessaire pour appliquer les modifications. choose_wallet: Choisir un portefeuille + stratum_wallet_warning: Le portefeuille doit être ouvert pour recevoir des récompenses. enable: Activer disable: Désactiver restart: Redémarrer diff --git a/locales/ru.yml b/locales/ru.yml index e91ad0a..2e2f175 100644 --- a/locales/ru.yml +++ b/locales/ru.yml @@ -227,6 +227,7 @@ network_settings: port_unavailable: Указанный порт недоступен restart_node_required: Для применения изменений требуется перезапуск узла. choose_wallet: Выбрать кошелёк + stratum_wallet_warning: Кошелёк должен быть открыт для получения наград. enable: Включить disable: Выключить restart: Перезапуск diff --git a/locales/tr.yml b/locales/tr.yml index a3305a6..286d993 100644 --- a/locales/tr.yml +++ b/locales/tr.yml @@ -227,6 +227,7 @@ network_settings: port_unavailable: Belirlenen port mevcut degil restart_node_required: Degisiklikler için yeniden Node BASLAT choose_wallet: Cüzdan seç + stratum_wallet_warning: Odul almak için cüzdan açilmalidir. enable: Etkinlestir disable: Devredisi birak restart: Restart diff --git a/src/gui/views/content.rs b/src/gui/views/content.rs index 5b46262..188ed3a 100644 --- a/src/gui/views/content.rs +++ b/src/gui/views/content.rs @@ -19,11 +19,13 @@ use lazy_static::lazy_static; use crate::gui::Colors; use crate::gui::platform::PlatformCallbacks; -use crate::gui::views::{Modal, NetworkContent, NodeSetup, View, WalletsContent}; +use crate::gui::views::{Modal, View}; use crate::gui::views::types::ModalContainer; use crate::node::Node; use crate::AppConfig; use crate::gui::icons::{CHECK, CHECK_FAT}; +use crate::gui::views::network::{NetworkContent, NodeSetup}; +use crate::gui::views::wallets::WalletsContent; lazy_static! { /// Global state to check if [`NetworkContent`] panel is open. diff --git a/src/gui/views/mod.rs b/src/gui/views/mod.rs index 3da79fa..03a2fbd 100644 --- a/src/gui/views/mod.rs +++ b/src/gui/views/mod.rs @@ -26,11 +26,9 @@ pub use modal::*; mod content; pub use content::*; -mod network; -pub use network::*; +pub mod network; -mod wallets; -pub use wallets::*; +pub mod wallets; mod camera; pub use camera::*; diff --git a/src/gui/views/network/connections.rs b/src/gui/views/network/connections.rs index b7cabad..4159778 100644 --- a/src/gui/views/network/connections.rs +++ b/src/gui/views/network/connections.rs @@ -18,8 +18,9 @@ use crate::AppConfig; use crate::gui::Colors; use crate::gui::icons::{CARET_RIGHT, CHECK_CIRCLE, COMPUTER_TOWER, DOTS_THREE_CIRCLE, GLOBE_SIMPLE, PENCIL, PLUS_CIRCLE, POWER, TRASH, X_CIRCLE}; use crate::gui::platform::PlatformCallbacks; -use crate::gui::views::{Modal, NodeSetup, View}; -use crate::gui::views::modals::ExternalConnectionModal; +use crate::gui::views::{Modal, View}; +use crate::gui::views::network::modals::ExternalConnectionModal; +use crate::gui::views::network::NodeSetup; use crate::gui::views::types::{ModalContainer, ModalPosition}; use crate::node::{Node, NodeConfig}; use crate::wallet::{ConnectionsConfig, ExternalConnection}; diff --git a/src/gui/views/network/content.rs b/src/gui/views/network/content.rs index 23ad918..f1c094d 100644 --- a/src/gui/views/network/content.rs +++ b/src/gui/views/network/content.rs @@ -20,7 +20,8 @@ use crate::AppConfig; use crate::gui::Colors; use crate::gui::icons::{ARROWS_COUNTER_CLOCKWISE, BRIEFCASE, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE, POWER}; use crate::gui::platform::PlatformCallbacks; -use crate::gui::views::{ConnectionsContent, NetworkMetrics, NetworkMining, NetworkNode, NetworkSettings, Content, TitlePanel, View}; +use crate::gui::views::{Content, TitlePanel, View}; +use crate::gui::views::network::{ConnectionsContent, NetworkMetrics, NetworkMining, NetworkNode, NetworkSettings}; use crate::gui::views::network::types::{NetworkTab, NetworkTabType}; use crate::gui::views::types::{TitleContentType, TitleType}; use crate::node::{Node, NodeError}; diff --git a/src/gui/views/network/metrics.rs b/src/gui/views/network/metrics.rs index 30e1129..62319c6 100644 --- a/src/gui/views/network/metrics.rs +++ b/src/gui/views/network/metrics.rs @@ -19,7 +19,8 @@ use grin_servers::{DiffBlock, ServerStats}; use crate::gui::Colors; use crate::gui::icons::{AT, COINS, CUBE_TRANSPARENT, HOURGLASS_LOW, HOURGLASS_MEDIUM, TIMER}; use crate::gui::platform::PlatformCallbacks; -use crate::gui::views::{NetworkContent, Content, View}; +use crate::gui::views::{Content, View}; +use crate::gui::views::network::NetworkContent; use crate::gui::views::network::types::{NetworkTab, NetworkTabType}; use crate::node::Node; diff --git a/src/gui/views/network/mining.rs b/src/gui/views/network/mining.rs index 5a7475d..7266c00 100644 --- a/src/gui/views/network/mining.rs +++ b/src/gui/views/network/mining.rs @@ -20,7 +20,8 @@ use grin_servers::WorkerStats; use crate::gui::Colors; use crate::gui::icons::{BARBELL, CLOCK_AFTERNOON, CPU, CUBE, FADERS, FOLDER_DASHED, FOLDER_SIMPLE_MINUS, FOLDER_SIMPLE_PLUS, HARD_DRIVES, PLUGS, PLUGS_CONNECTED, POLYGON}; use crate::gui::platform::PlatformCallbacks; -use crate::gui::views::{NetworkContent, Content, View}; +use crate::gui::views::{Content, View}; +use crate::gui::views::network::NetworkContent; use crate::gui::views::network::setup::StratumSetup; use crate::gui::views::network::types::{NetworkTab, NetworkTabType}; use crate::node::{Node, NodeConfig}; diff --git a/src/gui/views/network/node.rs b/src/gui/views/network/node.rs index db75190..ec0ea4c 100644 --- a/src/gui/views/network/node.rs +++ b/src/gui/views/network/node.rs @@ -19,7 +19,8 @@ use grin_servers::PeerStats; use crate::gui::Colors; use crate::gui::icons::{AT, CUBE, DEVICES, FLOW_ARROW, HANDSHAKE, PACKAGE, SHARE_NETWORK}; use crate::gui::platform::PlatformCallbacks; -use crate::gui::views::{NetworkContent, Content, View}; +use crate::gui::views::{Content, View}; +use crate::gui::views::network::NetworkContent; use crate::gui::views::network::types::{NetworkTab, NetworkTabType}; use crate::node::{Node, NodeConfig}; diff --git a/src/gui/views/network/setup/node.rs b/src/gui/views/network/setup/node.rs index 5ba145b..ebe4041 100644 --- a/src/gui/views/network/setup/node.rs +++ b/src/gui/views/network/setup/node.rs @@ -19,7 +19,8 @@ use crate::AppConfig; use crate::gui::Colors; use crate::gui::icons::{CLOCK_CLOCKWISE, COMPUTER_TOWER, PLUG, POWER, SHIELD, SHIELD_SLASH}; use crate::gui::platform::PlatformCallbacks; -use crate::gui::views::{Modal, NetworkContent, View}; +use crate::gui::views::{Modal, View}; +use crate::gui::views::network::NetworkContent; use crate::gui::views::network::settings::NetworkSettings; use crate::gui::views::types::{ModalContainer, ModalPosition, TextEditOptions}; use crate::node::{Node, NodeConfig}; diff --git a/src/gui/views/network/setup/stratum.rs b/src/gui/views/network/setup/stratum.rs index 09c8581..1d811d6 100644 --- a/src/gui/views/network/setup/stratum.rs +++ b/src/gui/views/network/setup/stratum.rs @@ -20,11 +20,17 @@ use crate::gui::platform::PlatformCallbacks; use crate::gui::views::{Modal, View}; use crate::gui::views::network::settings::NetworkSettings; use crate::gui::views::types::{ModalContainer, ModalPosition, TextEditOptions}; +use crate::gui::views::wallets::modals::WalletsModal; use crate::node::{Node, NodeConfig}; -use crate::wallet::WalletConfig; +use crate::wallet::{WalletConfig, WalletList}; /// Stratum server setup section content. pub struct StratumSetup { + /// Wallet list to select for mining rewards. + wallets: WalletList, + /// Wallets [`Modal`] content. + wallets_modal: WalletsModal, + /// IP Addresses available at system. available_ips: Vec, @@ -49,6 +55,8 @@ pub struct StratumSetup { modal_ids: Vec<&'static str> } +/// Identifier for wallet selection [`Modal`]. +const WALLET_SELECTION_MODAL: &'static str = "stratum_wallet_selection_modal"; /// Identifier for stratum port [`Modal`]. const STRATUM_PORT_MODAL: &'static str = "stratum_port"; /// Identifier for attempt time [`Modal`]. @@ -60,12 +68,21 @@ 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 wallet_name = if let Some(id) = NodeConfig::get_stratum_wallet_id() { + + // Setup mining rewards wallet name and identifier. + let mut wallet_id = NodeConfig::get_stratum_wallet_id(); + let wallet_name = if let Some(id) = wallet_id { WalletConfig::name_by_id(id) } else { None }; + if wallet_name.is_none() { + wallet_id = None; + } + Self { + wallets: WalletList::default(), + wallets_modal: WalletsModal::new(wallet_id), available_ips: NodeConfig::get_ip_addrs(), stratum_port_edit: port, stratum_port_available_edit: is_port_available, @@ -74,6 +91,7 @@ impl Default for StratumSetup { attempt_time_edit: NodeConfig::get_stratum_attempt_time(), min_share_diff_edit: NodeConfig::get_stratum_min_share_diff(), modal_ids: vec![ + WALLET_SELECTION_MODAL, STRATUM_PORT_MODAL, ATTEMPT_TIME_MODAL, MIN_SHARE_DIFF_MODAL @@ -92,6 +110,10 @@ impl ModalContainer for StratumSetup { modal: &Modal, cb: &dyn PlatformCallbacks) { match modal.id { + WALLET_SELECTION_MODAL => self.wallets_modal.ui(ui, modal, &self.wallets, |id| { + NodeConfig::save_stratum_wallet_id(id); + self.wallet_name = WalletConfig::name_by_id(id); + }), STRATUM_PORT_MODAL => self.port_modal(ui, modal, cb), ATTEMPT_TIME_MODAL => self.attempt_modal(ui, modal, cb), MIN_SHARE_DIFF_MODAL => self.min_diff_modal(ui, modal, cb), @@ -110,7 +132,7 @@ impl StratumSetup { ui.add_space(6.0); ui.vertical_centered(|ui| { - // Show loading indicator or controls to start/stop stratum server if port is available. + // Show loading indicator or controls to start/stop stratum server. if self.is_port_available && self.wallet_name.is_some() { if Node::is_stratum_starting() || Node::is_stratum_stopping() { ui.vertical_centered(|ui| { @@ -150,30 +172,32 @@ impl StratumSetup { ); } ui.add_space(8.0); + View::horizontal_line(ui, Colors::item_stroke()); + ui.add_space(8.0); + + // Show wallet name. + ui.label(RichText::new(self.wallet_name.as_ref().unwrap_or(&"-".to_string())) + .size(16.0) + .color(Colors::white_or_black(true))); + ui.add_space(8.0); + + // Show button to select wallet. + View::button(ui, t!("network_settings.choose_wallet"), Colors::button(), || { + self.show_wallets_modal(); + }); + ui.add_space(12.0); + + if self.wallet_name.is_some() { + ui.label(RichText::new(t!("network_settings.stratum_wallet_warning")) + .size(16.0) + .color(Colors::inactive_text()) + ); + ui.add_space(12.0); + } + View::horizontal_line(ui, Colors::item_stroke()); + ui.add_space(6.0); }); - View::horizontal_line(ui, Colors::item_stroke()); - ui.add_space(6.0); - - // Show wallet name. - ui.add_space(2.0); - ui.label(RichText::new(t!("wallets.wallet")) - .size(16.0) - .color(Colors::gray())); - ui.add_space(2.0); - ui.label(RichText::new(self.wallet_name.as_ref().unwrap_or(&"-".to_string())) - .size(16.0) - .color(Colors::white_or_black(true))); - ui.add_space(8.0); - - View::button(ui, t!("network_settings.choose_wallet"), Colors::button(), || { - //TODO: select wallet - }); - - ui.add_space(12.0); - View::horizontal_line(ui, Colors::item_stroke()); - ui.add_space(6.0); - // Show message when IP addresses are not available on the system. if self.available_ips.is_empty() { NetworkSettings::no_ip_address_ui(ui); @@ -210,6 +234,16 @@ impl StratumSetup { }); } + /// Show wallet selection [`Modal`]. + fn show_wallets_modal(&mut self) { + self.wallets_modal = WalletsModal::new(NodeConfig::get_stratum_wallet_id()); + // Show modal. + Modal::new(WALLET_SELECTION_MODAL) + .position(ModalPosition::Center) + .title(t!("network_settings.choose_wallet")) + .show(); + } + /// Draw stratum port value setup content. fn port_setup_ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) { ui.label(RichText::new(t!("network_settings.stratum_port")) diff --git a/src/gui/views/wallets/content.rs b/src/gui/views/wallets/content.rs index e64c5c6..a98097b 100644 --- a/src/gui/views/wallets/content.rs +++ b/src/gui/views/wallets/content.rs @@ -53,6 +53,8 @@ pub struct WalletsContent { modal_ids: Vec<&'static str> } +/// Identifier for connection selection [`Modal`]. +const CONNECTION_SELECTION_MODAL: &'static str = "wallets_connection_selection_modal"; /// Identifier for wallet opening [`Modal`]. const OPEN_WALLET_MODAL: &'static str = "open_wallet_modal"; @@ -69,7 +71,7 @@ impl Default for WalletsContent { modal_ids: vec![ OPEN_WALLET_MODAL, WalletCreation::NAME_PASS_MODAL, - WalletConnectionModal::ID, + CONNECTION_SELECTION_MODAL, ] } } @@ -89,7 +91,7 @@ impl ModalContainer for WalletsContent { WalletCreation::NAME_PASS_MODAL => { self.creation_content.name_pass_modal_ui(ui, modal, cb) }, - WalletConnectionModal::ID => { + CONNECTION_SELECTION_MODAL => { if let Some(content) = self.conn_modal_content.as_mut() { content.ui(ui, modal, cb, |id| { let list = self.wallets.list(); @@ -415,9 +417,6 @@ impl WalletsContent { ui.painter().rect(rect, rounding, bg, stroke); ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| { - // Setup padding for item buttons. - ui.style_mut().spacing.button_padding = egui::vec2(14.0, 0.0); - if !wallet.is_open() { // Show button to open closed wallet. View::item_button(ui, View::item_rounding(0, 1, true), FOLDER_OPEN, None, || { @@ -520,7 +519,7 @@ impl WalletsContent { let ext_conn = wallet.get_current_ext_conn(); self.conn_modal_content = Some(WalletConnectionModal::new(ext_conn)); // Show modal. - Modal::new(WalletConnectionModal::ID) + Modal::new(CONNECTION_SELECTION_MODAL) .position(ModalPosition::CenterTop) .title(t!("wallets.conn_method")) .show(); diff --git a/src/gui/views/wallets/mod.rs b/src/gui/views/wallets/mod.rs index bef81f5..3dcbef4 100644 --- a/src/gui/views/wallets/mod.rs +++ b/src/gui/views/wallets/mod.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -mod modals; +pub mod modals; mod creation; mod content; diff --git a/src/gui/views/wallets/modals/conn.rs b/src/gui/views/wallets/modals/conn.rs index 634a2fe..b048305 100644 --- a/src/gui/views/wallets/modals/conn.rs +++ b/src/gui/views/wallets/modals/conn.rs @@ -18,11 +18,12 @@ use egui::scroll_area::ScrollBarVisibility; use crate::gui::Colors; use crate::gui::icons::{CHECK, CHECK_FAT, PLUS_CIRCLE}; use crate::gui::platform::PlatformCallbacks; -use crate::gui::views::{ConnectionsContent, Modal, View}; -use crate::gui::views::modals::ExternalConnectionModal; +use crate::gui::views::{Modal, View}; +use crate::gui::views::network::ConnectionsContent; +use crate::gui::views::network::modals::ExternalConnectionModal; use crate::wallet::{ConnectionsConfig, ExternalConnection}; -/// Wallet connection content. +/// Wallet connection [`Modal`] content. pub struct WalletConnectionModal { /// Current external connection. pub ext_conn: Option, @@ -35,9 +36,6 @@ pub struct WalletConnectionModal { } impl WalletConnectionModal { - /// Identifier for [`Modal`]. - pub const ID: &'static str = "select_connection_modal"; - /// Create from provided wallet connection. pub fn new(ext_conn: Option) -> Self { ExternalConnection::check_ext_conn_availability(None); @@ -69,7 +67,7 @@ impl WalletConnectionModal { .max_height(if ext_conn_list.len() < 4 { 330.0 } else { - 323.0 + 350.0 }) .id_source("integrated_node") .scroll_bar_visibility(ScrollBarVisibility::AlwaysHidden) diff --git a/src/gui/views/wallets/modals/mod.rs b/src/gui/views/wallets/modals/mod.rs index a4b1622..c4f566c 100644 --- a/src/gui/views/wallets/modals/mod.rs +++ b/src/gui/views/wallets/modals/mod.rs @@ -13,4 +13,7 @@ // limitations under the License. mod conn; -pub use conn::*; \ No newline at end of file +pub use conn::*; + +mod wallets; +pub use wallets::*; \ No newline at end of file diff --git a/src/gui/views/wallets/modals/wallets.rs b/src/gui/views/wallets/modals/wallets.rs new file mode 100644 index 0000000..b082c4e --- /dev/null +++ b/src/gui/views/wallets/modals/wallets.rs @@ -0,0 +1,135 @@ +// Copyright 2024 The Grim Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// 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. + +use egui::scroll_area::ScrollBarVisibility; +use egui::{Align, Layout, RichText, ScrollArea}; + +use crate::gui::Colors; +use crate::gui::icons::{CHECK, CHECK_FAT, COMPUTER_TOWER, GLOBE_SIMPLE, PLUGS_CONNECTED}; +use crate::gui::views::{Modal, View}; +use crate::wallet::{Wallet, WalletList}; + +/// Wallet list [`Modal`] content +pub struct WalletsModal { + /// Selected wallet id. + selected: Option +} + +impl WalletsModal { + pub fn new(selected: Option) -> Self { + Self { + selected, + } + } + + /// Draw [`Modal`] content. + pub fn ui(&mut self, + ui: &mut egui::Ui, + modal: &Modal, + wallets: &WalletList, + mut on_select: impl FnMut(i64)) { + ui.add_space(4.0); + ScrollArea::vertical() + .max_height(373.0) + .id_source("select_wallet_list") + .scroll_bar_visibility(ScrollBarVisibility::AlwaysHidden) + .auto_shrink([true; 2]) + .show(ui, |ui| { + ui.add_space(2.0); + ui.vertical_centered(|ui| { + for wallet in wallets.list() { + // Draw wallet list item. + self.wallet_item_ui(ui, wallet, modal, |id| { + on_select(id); + }); + ui.add_space(5.0); + } + }); + }); + + ui.add_space(2.0); + View::horizontal_line(ui, Colors::stroke()); + ui.add_space(6.0); + + // Show button to close modal. + ui.vertical_centered_justified(|ui| { + View::button(ui, t!("modal.cancel"), Colors::white_or_black(false), || { + modal.close(); + }); + }); + ui.add_space(6.0); + } + + /// Draw wallet list item. + fn wallet_item_ui(&mut self, + ui: &mut egui::Ui, + wallet: &Wallet, + modal: &Modal, + mut on_select: impl FnMut(i64)) { + let config = wallet.get_config(); + let id = config.id; + + // Draw round background. + let mut rect = ui.available_rect_before_wrap(); + rect.set_height(78.0); + let rounding = View::item_rounding(0, 1, false); + ui.painter().rect(rect, rounding, Colors::fill(), View::hover_stroke()); + + ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| { + // Draw button to select wallet. + let current = self.selected.unwrap_or(0) == id; + if current { + ui.add_space(12.0); + ui.label(RichText::new(CHECK_FAT).size(20.0).color(Colors::green())); + } else { + View::item_button(ui, View::item_rounding(0, 1, true), CHECK, None, || { + on_select(id); + modal.close(); + }); + } + + let layout_size = ui.available_size(); + ui.allocate_ui_with_layout(layout_size, Layout::left_to_right(Align::Center), |ui| { + ui.add_space(6.0); + ui.vertical(|ui| { + ui.add_space(3.0); + // Setup wallet name text. + ui.with_layout(Layout::left_to_right(Align::Min), |ui| { + ui.add_space(1.0); + View::ellipsize_text(ui, config.name, 18.0, Colors::title(false)); + }); + + // Setup wallet API text. + let address = if let Some(port) = config.api_port { + format!("127.0.0.1:{}", port) + } else { + "-".to_string() + }; + let api_text = format!("{} {}", PLUGS_CONNECTED, address); + ui.label(RichText::new(api_text).size(15.0).color(Colors::text(false))); + ui.add_space(1.0); + + // Setup wallet connection text. + let conn = if let Some(conn) = wallet.get_current_ext_conn() { + format!("{} {}", GLOBE_SIMPLE, conn.url) + } else { + format!("{} {}", COMPUTER_TOWER, t!("network.node")) + }; + View::ellipsize_text(ui, conn, 15.0, Colors::gray()); + ui.add_space(3.0); + }); + }); + }); + } +} \ No newline at end of file diff --git a/src/gui/views/wallets/wallet/settings/connection.rs b/src/gui/views/wallets/wallet/settings/connection.rs index 88b8178..1d4bc76 100644 --- a/src/gui/views/wallets/wallet/settings/connection.rs +++ b/src/gui/views/wallets/wallet/settings/connection.rs @@ -17,8 +17,9 @@ use egui::{Align, Layout, RichText}; use crate::gui::Colors; use crate::gui::icons::{CHECK, CHECK_CIRCLE, CHECK_FAT, DOTS_THREE_CIRCLE, GLOBE, GLOBE_SIMPLE, PLUS_CIRCLE, X_CIRCLE}; use crate::gui::platform::PlatformCallbacks; -use crate::gui::views::{ConnectionsContent, Modal, View}; -use crate::gui::views::modals::ExternalConnectionModal; +use crate::gui::views::{Modal, View}; +use crate::gui::views::network::ConnectionsContent; +use crate::gui::views::network::modals::ExternalConnectionModal; use crate::gui::views::types::{ModalContainer, ModalPosition}; use crate::wallet::{ConnectionsConfig, ExternalConnection, Wallet}; use crate::wallet::types::ConnectionMethod; diff --git a/src/node/config.rs b/src/node/config.rs index 4fbca49..997d649 100644 --- a/src/node/config.rs +++ b/src/node/config.rs @@ -72,11 +72,11 @@ impl PeersConfig { /// Load saved peers to node server [`ConfigMembers`] config. pub(crate) fn load_to_server_config() { - let mut w_node_config = Settings::node_config_to_update(); + let mut w_config = Settings::node_config_to_update(); // Load seeds. - for seed in w_node_config.peers.seeds.clone() { + for seed in w_config.peers.seeds.clone() { if let Some(p) = Self::peer_to_addr(seed.to_string()) { - let mut seeds = w_node_config + let mut seeds = w_config .node .server .p2p_config @@ -84,13 +84,13 @@ impl PeersConfig { .clone() .unwrap_or(PeerAddrs::default()); seeds.peers.insert(seeds.peers.len(), p); - w_node_config.node.server.p2p_config.seeds = Some(seeds); + w_config.node.server.p2p_config.seeds = Some(seeds); } } // Load allowed peers. - for peer in w_node_config.peers.allowed.clone() { + for peer in w_config.peers.allowed.clone() { if let Some(p) = Self::peer_to_addr(peer.clone()) { - let mut allowed = w_node_config + let mut allowed = w_config .node .server .p2p_config @@ -98,13 +98,13 @@ impl PeersConfig { .clone() .unwrap_or(PeerAddrs::default()); allowed.peers.insert(allowed.peers.len(), p); - w_node_config.node.server.p2p_config.peers_allow = Some(allowed); + w_config.node.server.p2p_config.peers_allow = Some(allowed); } } // Load denied peers. - for peer in w_node_config.peers.denied.clone() { + for peer in w_config.peers.denied.clone() { if let Some(p) = Self::peer_to_addr(peer.clone()) { - let mut denied = w_node_config + let mut denied = w_config .node .server .p2p_config @@ -112,13 +112,13 @@ impl PeersConfig { .clone() .unwrap_or(PeerAddrs::default()); denied.peers.insert(denied.peers.len(), p); - w_node_config.node.server.p2p_config.peers_deny = Some(denied); + w_config.node.server.p2p_config.peers_deny = Some(denied); } } // Load preferred peers. - for peer in &w_node_config.peers.preferred.clone() { + for peer in &w_config.peers.preferred.clone() { if let Some(p) = Self::peer_to_addr(peer.clone()) { - let mut preferred = w_node_config + let mut preferred = w_config .node .server .p2p_config @@ -126,7 +126,7 @@ impl PeersConfig { .clone() .unwrap_or(PeerAddrs::default()); preferred.peers.insert(preferred.peers.len(), p); - w_node_config.node.server.p2p_config.peers_preferred = Some(preferred); + w_config.node.server.p2p_config.peers_preferred = Some(preferred); } } } @@ -242,9 +242,9 @@ impl NodeConfig { let node_server_config = Self::save_default_node_server_config(&chain_type); let peers_config = Self::save_default_peers_config(&chain_type); { - let mut w_node_config = Settings::node_config_to_update(); - w_node_config.node = node_server_config; - w_node_config.peers = peers_config; + let mut w_config = Settings::node_config_to_update(); + w_config.node = node_server_config; + w_config.peers = peers_config; } } @@ -329,15 +329,15 @@ impl NodeConfig { /// Save stratum server IP address and port. pub fn save_stratum_address(addr: &String, port: &String) { let addr_to_save = format!("{}:{}", addr, port); - let mut w_node_config = Settings::node_config_to_update(); - w_node_config + let mut w_config = Settings::node_config_to_update(); + w_config .node .server .stratum_mining_config .as_mut() .unwrap() .stratum_server_addr = Some(addr_to_save); - w_node_config.save(); + w_config.save(); } /// Check if stratum server port is available across the system and config. @@ -383,23 +383,24 @@ impl NodeConfig { /// Save stratum mining server wallet address to get rewards. pub fn save_stratum_wallet_id(id: i64) { - let w_config = Settings::node_config_to_update(); + let mut w_config = Settings::node_config_to_update(); w_config.node - .clone() .server .stratum_mining_config + .as_mut() .unwrap() .wallet_listener_url = id.to_string(); w_config.save(); + println!() } /// Get the amount of time in seconds to attempt to mine on a particular header. pub fn get_stratum_attempt_time() -> String { let r_config = Settings::node_config_to_read(); r_config.node - .clone() .server .stratum_mining_config + .as_ref() .unwrap() .attempt_time_per_block .to_string() @@ -407,23 +408,23 @@ impl NodeConfig { /// Save stratum attempt time value in seconds. pub fn save_stratum_attempt_time(time: u32) { - let w_node_config = Settings::node_config_to_update(); - w_node_config.node - .clone() + let mut w_config = Settings::node_config_to_update(); + w_config.node .server .stratum_mining_config + .as_mut() .unwrap() .attempt_time_per_block = time; - w_node_config.save(); + w_config.save(); } /// Get minimum acceptable share difficulty to request from miners. pub fn get_stratum_min_share_diff() -> String { let r_config = Settings::node_config_to_read(); r_config.node - .clone() .server .stratum_mining_config + .as_ref() .unwrap() .minimum_share_difficulty .to_string() @@ -431,23 +432,24 @@ impl NodeConfig { /// Save minimum acceptable share difficulty. pub fn save_stratum_min_share_diff(diff: u64) { - let w_node_config = Settings::node_config_to_update(); - w_node_config.node - .clone() + let mut w_config = Settings::node_config_to_update(); + w_config.node .server .stratum_mining_config + .as_mut() .unwrap() .minimum_share_difficulty = diff; - w_node_config.save(); + w_config.save(); } /// Check if stratum mining server autorun is enabled. pub fn is_stratum_autorun_enabled() -> bool { - let stratum_config = Settings::node_config_to_read() + let r_config = Settings::node_config_to_read(); + let stratum_config = r_config .node - .clone() .server .stratum_mining_config + .as_ref() .unwrap(); if let Some(enable) = stratum_config.enable_stratum_server { return enable; @@ -458,14 +460,14 @@ impl NodeConfig { /// Toggle stratum mining server autorun. pub fn toggle_stratum_autorun() { let autorun = Self::is_stratum_autorun_enabled(); - let mut w_node_config = Settings::node_config_to_update(); - w_node_config.node + let mut w_config = Settings::node_config_to_update(); + w_config.node .server .stratum_mining_config .as_mut() .unwrap() .enable_stratum_server = Some(!autorun); - w_node_config.save(); + w_config.save(); } /// Get API server address. @@ -484,9 +486,9 @@ impl NodeConfig { /// Save API server IP address and port. pub fn save_api_address(addr: &String, port: &String) { let addr_to_save = format!("{}:{}", addr, port); - let mut w_node_config = Settings::node_config_to_update(); - w_node_config.node.server.api_http_addr = addr_to_save; - w_node_config.save(); + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.api_http_addr = addr_to_save; + w_config.save(); } /// Check if api server port is available across the system and config. @@ -624,9 +626,9 @@ impl NodeConfig { } else { ChainValidationMode::EveryBlock }; - let mut w_node_config = Settings::node_config_to_update(); - w_node_config.node.server.chain_validation_mode = new_mode; - w_node_config.save(); + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.chain_validation_mode = new_mode; + w_config.save(); } /// Check if node is running in archive mode. @@ -638,9 +640,9 @@ impl NodeConfig { /// Toggle archive node mode. pub fn toggle_archive_mode() { let archive_mode = Self::is_archive_mode(); - let mut w_node_config = Settings::node_config_to_update(); - w_node_config.node.server.archive_mode = Some(!archive_mode); - w_node_config.save(); + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.archive_mode = Some(!archive_mode); + w_config.save(); } /// Get P2P server port. @@ -669,9 +671,9 @@ impl NodeConfig { /// Save P2P server port. pub fn save_p2p_port(port: u16) { - let mut w_node_config = Settings::node_config_to_update(); - w_node_config.node.server.p2p_config.port = port; - w_node_config.save(); + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.p2p_config.port = port; + w_config.save(); } /// Check if default seed list is used. @@ -686,9 +688,9 @@ impl NodeConfig { } else { Seeding::DNSSeed }; - let mut w_node_config = Settings::node_config_to_update(); - w_node_config.node.server.p2p_config.seeding_type = seeding_type; - w_node_config.save(); + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.p2p_config.seeding_type = seeding_type; + w_config.save(); } /// Get custom seed peers. @@ -698,21 +700,21 @@ impl NodeConfig { /// Save custom seed peer. pub fn save_custom_seed(peer: String) { - let mut w_node_config = Settings::node_config_to_update(); - let size = w_node_config.peers.seeds.len(); - w_node_config.peers.seeds.insert(size, peer); - w_node_config.peers.save(); + let mut w_config = Settings::node_config_to_update(); + let size = w_config.peers.seeds.len(); + w_config.peers.seeds.insert(size, peer); + w_config.peers.save(); } /// Remove custom seed peer. pub fn remove_custom_seed(peer: &String) { - let mut w_node_config = Settings::node_config_to_update(); - let mut seeds = w_node_config.peers.seeds.clone(); + let mut w_config = Settings::node_config_to_update(); + let mut seeds = w_config.peers.seeds.clone(); if let Some(index) = seeds.iter().position(|x| x == peer) { seeds.remove(index); } - w_node_config.peers.seeds = seeds; - w_node_config.peers.save(); + w_config.peers.seeds = seeds; + w_config.peers.save(); } /// Get denied peer list. @@ -722,21 +724,21 @@ impl NodeConfig { /// Save peer to denied list. pub fn deny_peer(peer: String) { - let mut w_node_config = Settings::node_config_to_update(); - let size = w_node_config.peers.denied.len(); - w_node_config.peers.denied.insert(size, peer); - w_node_config.peers.save(); + let mut w_config = Settings::node_config_to_update(); + let size = w_config.peers.denied.len(); + w_config.peers.denied.insert(size, peer); + w_config.peers.save(); } /// Remove denied peer. pub fn remove_denied_peer(peer: &String) { - let mut w_node_config = Settings::node_config_to_update(); - let mut denied = w_node_config.peers.denied.clone(); + let mut w_config = Settings::node_config_to_update(); + let mut denied = w_config.peers.denied.clone(); if let Some(index) = denied.iter().position(|x| x == peer) { denied.remove(index); } - w_node_config.peers.denied = denied; - w_node_config.peers.save(); + w_config.peers.denied = denied; + w_config.peers.save(); } /// Get allowed peer list. @@ -746,21 +748,21 @@ impl NodeConfig { /// Save peer to allowed list. pub fn allow_peer(peer: String) { - let mut w_node_config = Settings::node_config_to_update(); - let size = w_node_config.peers.allowed.len(); - w_node_config.peers.allowed.insert(size, peer); - w_node_config.peers.save(); + let mut w_config = Settings::node_config_to_update(); + let size = w_config.peers.allowed.len(); + w_config.peers.allowed.insert(size, peer); + w_config.peers.save(); } /// Remove allowed peer. pub fn remove_allowed_peer(peer: &String) { - let mut w_node_config = Settings::node_config_to_update(); - let mut allowed = w_node_config.peers.allowed.clone(); + let mut w_config = Settings::node_config_to_update(); + let mut allowed = w_config.peers.allowed.clone(); if let Some(index) = allowed.iter().position(|x| x == peer) { allowed.remove(index); } - w_node_config.peers.allowed = allowed; - w_node_config.peers.save(); + w_config.peers.allowed = allowed; + w_config.peers.save(); } /// Get preferred peer list. @@ -770,21 +772,21 @@ impl NodeConfig { /// Add peer at preferred list. pub fn prefer_peer(peer: String) { - let mut w_node_config = Settings::node_config_to_update(); - let size = w_node_config.peers.preferred.len(); - w_node_config.peers.preferred.insert(size, peer); - w_node_config.peers.save(); + let mut w_config = Settings::node_config_to_update(); + let size = w_config.peers.preferred.len(); + w_config.peers.preferred.insert(size, peer); + w_config.peers.save(); } /// Remove preferred peer. pub fn remove_preferred_peer(peer: &String) { - let mut w_node_config = Settings::node_config_to_update(); - let mut preferred = w_node_config.peers.preferred.clone(); + let mut w_config = Settings::node_config_to_update(); + let mut preferred = w_config.peers.preferred.clone(); if let Some(index) = preferred.iter().position(|x| x == peer) { preferred.remove(index); } - w_node_config.peers.preferred = preferred; - w_node_config.peers.save(); + w_config.peers.preferred = preferred; + w_config.peers.save(); } /// How long a banned peer should stay banned in ms. @@ -794,9 +796,9 @@ impl NodeConfig { /// Save for how long a banned peer should stay banned in ms. pub fn save_p2p_ban_window(time: i64) { - let mut w_node_config = Settings::node_config_to_update(); - w_node_config.node.server.p2p_config.ban_window = Some(time); - w_node_config.save(); + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.p2p_config.ban_window = Some(time); + w_config.save(); } /// Maximum number of inbound peer connections. @@ -810,9 +812,9 @@ impl NodeConfig { /// Save maximum number of inbound peer connections. pub fn save_max_inbound_peers(count: u32) { - let mut w_node_config = Settings::node_config_to_update(); - w_node_config.node.server.p2p_config.peer_max_inbound_count = Some(count); - w_node_config.save(); + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.p2p_config.peer_max_inbound_count = Some(count); + w_config.save(); } /// Maximum number of outbound peer connections. @@ -827,11 +829,11 @@ impl NodeConfig { /// Save maximum number of outbound peer connections. pub fn save_max_outbound_peers(count: u32) { - let mut w_node_config = Settings::node_config_to_update(); - w_node_config.node.server.p2p_config.peer_max_outbound_count = Some(count); + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.p2p_config.peer_max_outbound_count = Some(count); // Same value for preferred. - w_node_config.node.server.p2p_config.peer_min_preferred_outbound_count = Some(count); - w_node_config.save(); + w_config.node.server.p2p_config.peer_min_preferred_outbound_count = Some(count); + w_config.save(); } /// Base fee that's accepted into the pool. @@ -841,9 +843,9 @@ impl NodeConfig { /// 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.node.server.pool_config.accept_fee_base = fee; - w_node_config.save(); + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.pool_config.accept_fee_base = fee; + w_config.save(); } /// Reorg cache retention period in minutes. @@ -853,9 +855,9 @@ impl NodeConfig { /// 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.node.server.pool_config.reorg_cache_period = period; - w_node_config.save(); + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.pool_config.reorg_cache_period = period; + w_config.save(); } /// Max amount of transactions at pool. @@ -865,9 +867,9 @@ impl NodeConfig { /// 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.node.server.pool_config.max_pool_size = amount; - w_node_config.save(); + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.pool_config.max_pool_size = amount; + w_config.save(); } /// Max amount of transactions at stem pool. @@ -877,9 +879,9 @@ impl NodeConfig { /// 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.node.server.pool_config.max_stempool_size = amount; - w_node_config.save(); + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.pool_config.max_stempool_size = amount; + w_config.save(); } /// Max total weight of transactions that can get selected to build a block. @@ -889,9 +891,9 @@ impl NodeConfig { /// Set max total weight of transactions that can get selected to build a block. pub fn save_mineable_max_weight(weight: u64) { - let mut w_node_config = Settings::node_config_to_update(); - w_node_config.node.server.pool_config.mineable_max_weight = weight; - w_node_config.save(); + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.pool_config.mineable_max_weight = weight; + w_config.save(); } // Dandelion settings @@ -903,9 +905,9 @@ impl NodeConfig { /// 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.node.server.dandelion_config.epoch_secs = secs; - w_node_config.save(); + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.dandelion_config.epoch_secs = secs; + w_config.save(); } /// Dandelion embargo timer in seconds. @@ -916,9 +918,9 @@ impl NodeConfig { /// 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.node.server.dandelion_config.embargo_secs = secs; - w_node_config.save(); + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.dandelion_config.embargo_secs = secs; + w_config.save(); } /// Dandelion aggregation period in seconds. @@ -928,9 +930,9 @@ impl NodeConfig { /// 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.node.server.dandelion_config.aggregation_secs = secs; - w_node_config.save(); + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.dandelion_config.aggregation_secs = secs; + w_config.save(); } /// Dandelion stem probability (default: stem 90% of the time, fluff 10% of the time). @@ -940,9 +942,9 @@ impl NodeConfig { /// Save Dandelion stem probability. pub fn save_stem_probability(percent: u8) { - let mut w_node_config = Settings::node_config_to_update(); - w_node_config.node.server.dandelion_config.stem_probability = percent; - w_node_config.save(); + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.dandelion_config.stem_probability = percent; + w_config.save(); } /// Default to always stem our txs as described in Dandelion++ paper. @@ -953,8 +955,8 @@ impl NodeConfig { /// Toggle stem of our txs. 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.node.server.dandelion_config.always_stem_our_txs = !stem_txs; - w_node_config.save(); + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.dandelion_config.always_stem_our_txs = !stem_txs; + w_config.save(); } } \ No newline at end of file diff --git a/src/node/stratum.rs b/src/node/stratum.rs index 7cc5b25..5ad9c58 100644 --- a/src/node/stratum.rs +++ b/src/node/stratum.rs @@ -47,6 +47,7 @@ use grin_util::ToHex; use grin_servers::ServerTxPool; use log::{debug, error, info, warn}; use serde_derive::{Deserialize, Serialize}; +use crate::wallet::WalletConfig; type Tx = mpsc::UnboundedSender; @@ -586,7 +587,16 @@ impl Handler { { let mut state = self.current_state.write(); let wallet_listener_url = if !config.burn_reward { - Some(config.wallet_listener_url.clone()) + if let Ok(id) = config.wallet_listener_url.parse::() { + if let Some(port) = WalletConfig::api_port_by_id(id) { + let url = format!("http://127.0.0.1:{}", port); + Some(url) + } else { + None + } + } else { + None + } } else { None }; diff --git a/src/wallet/config.rs b/src/wallet/config.rs index a7c46a9..13cb3c6 100644 --- a/src/wallet/config.rs +++ b/src/wallet/config.rs @@ -18,6 +18,7 @@ use std::string::ToString; use grin_core::global::ChainTypes; use grin_wallet_libwallet::{Slate}; +use rand::Rng; use serde_derive::{Deserialize, Serialize}; use crate::{AppConfig, Settings}; @@ -41,7 +42,9 @@ pub struct WalletConfig { /// Flag to use Dandelion to broadcast transactions. pub use_dandelion: Option, /// Flag to enable Tor listener on start. - pub enable_tor_listener: Option + pub enable_tor_listener: Option, + /// Wallet API port. + pub api_port: Option, } /// Base wallets directory name. @@ -77,6 +80,7 @@ impl WalletConfig { min_confirmations: MIN_CONFIRMATIONS_DEFAULT, use_dandelion: Some(true), enable_tor_listener: Some(true), + api_port: Some(rand::thread_rng().gen_range(10000..30000)), }; Settings::write_to_file(&config, config_path); config @@ -102,6 +106,16 @@ impl WalletConfig { None } + /// Get wallet API port by provided identifier. + pub fn api_port_by_id(id: i64) -> Option { + let mut wallet_dir = WalletConfig::get_base_path(AppConfig::chain_type()); + wallet_dir.push(id.to_string()); + if let Some(cfg) = Self::load(wallet_dir) { + return cfg.api_port; + } + None + } + /// Save wallet config. pub fn save(&self) { let config_path = Self::get_config_file_path(self.chain_type, self.id); diff --git a/src/wallet/wallet.rs b/src/wallet/wallet.rs index 3c3b9c0..280465a 100644 --- a/src/wallet/wallet.rs +++ b/src/wallet/wallet.rs @@ -24,7 +24,6 @@ use std::thread::Thread; use std::time::Duration; use futures::channel::oneshot; use serde_json::{json, Value}; -use rand::Rng; use grin_api::{ApiServer, Router}; use grin_chain::SyncStatus; @@ -42,6 +41,7 @@ use grin_wallet_impls::{DefaultLCProvider, DefaultWalletImpl, HTTPNodeClient}; use grin_wallet_libwallet::{address, Error, InitTxArgs, IssueInvoiceTxArgs, NodeClient, RetrieveTxQueryArgs, RetrieveTxQuerySortField, RetrieveTxQuerySortOrder, Slate, SlatepackAddress, SlateState, SlateVersion, StatusMessage, TxLogEntry, TxLogEntryType, VersionedSlate, WalletInst, WalletLCProvider}; use grin_wallet_libwallet::api_impl::owner::{cancel_tx, retrieve_summary_info, retrieve_txs}; use grin_wallet_util::OnionV3Address; +use rand::Rng; use crate::AppConfig; use crate::node::{Node, NodeConfig}; @@ -1450,18 +1450,19 @@ fn sync_wallet_data(wallet: &Wallet, from_node: bool) { /// Start Foreign API server to receive txs over transport and mining rewards. fn start_api_server(wallet: &Wallet) -> Result<(ApiServer, u16), Error> { let host = "127.0.0.1"; - // Find free port. - let port = if wallet.get_config().chain_type == ChainTypes::Mainnet { - rand::thread_rng().gen_range(37000..40000) - } else { - rand::thread_rng().gen_range(47000..50000) - }; + let port = wallet.get_config().api_port.unwrap_or(rand::thread_rng().gen_range(10000..30000)); let free_port = (port..).find(|port| { return match TcpListener::bind((host, port.to_owned())) { Ok(_) => { let node_p2p_port = NodeConfig::get_p2p_port(); let node_api_port = NodeConfig::get_api_ip_port().1; - port.to_string() != node_p2p_port && port.to_string() != node_api_port + let free = port.to_string() != node_p2p_port && port.to_string() != node_api_port; + if free { + let mut config = wallet.config.write(); + config.api_port = Some(*port); + config.save(); + } + free }, Err(_) => false }