config + ui + node: all server config values, stratum config ui refactoring, global modal position fix, modal id refactoring, remove chain data on node launch error
This commit is contained in:
parent
4ad134c5e3
commit
1346b04bc9
20 changed files with 906 additions and 241 deletions
|
@ -19,7 +19,7 @@ sync_status:
|
|||
awaiting_peers: Waiting for peers
|
||||
header_sync: Downloading headers
|
||||
header_sync_percent: 'Downloading headers: %{percent}%'
|
||||
tx_hashset_pibd: 'Downloading state (PIBD)'
|
||||
tx_hashset_pibd: Downloading state (PIBD)
|
||||
tx_hashset_pibd_percent: 'Downloading state (PIBD): %{percent}%'
|
||||
tx_hashset_download: Downloading chain state
|
||||
tx_hashset_download_percent: 'Downloading chain state: %{percent}%'
|
||||
|
@ -57,22 +57,28 @@ network_mining:
|
|||
loading: Mining will be available after the synchronization
|
||||
server_setup: Stratum server setup
|
||||
enable_server: Enable server
|
||||
server_setting: 'Enable stratum server or change more settings by selecting %{settings} at the bottom of the screen.'
|
||||
server_setting: 'Enable stratum server or change more settings by selecting %{settings} at the bottom of the screen. App restart is required to change settings of the running server.'
|
||||
info: 'Mining server is enabled, you can change settings by selecting %{settings} at the bottom of the screen. Data is updating when devices are connected.'
|
||||
no_ip_addresses: There are no available IP addresses on your system, the server cannot be started, check your network connectivity.
|
||||
choose_ip_address: 'Choose IP Address:'
|
||||
change_port: 'Change port:'
|
||||
ip_address: IP Address
|
||||
no_ip_addresses: There are no available IP addresses on your system, stratum server cannot be started, check your network connectivity.
|
||||
port_unavailable: Specified port is unavailable
|
||||
rewards_wallet: Wallet for rewards
|
||||
server: Stratum server
|
||||
address: Address
|
||||
miners: Miners
|
||||
devices: Devices
|
||||
blocks_found: Blocks found
|
||||
hashrate: 'Hashrate (C%{bits})'
|
||||
connected: Connected
|
||||
disconnected: Disconnected
|
||||
network_settings:
|
||||
server: Server
|
||||
port: Port
|
||||
ip_address: IP Address
|
||||
change_port: Change port
|
||||
enter_value: 'Enter value:'
|
||||
modal:
|
||||
cancel: Cancel
|
||||
save: Save
|
||||
modal_exit:
|
||||
description: Are you sure you want to quit the application?
|
||||
exit: Exit
|
|
@ -19,7 +19,7 @@ sync_status:
|
|||
awaiting_peers: Ожидание пиров
|
||||
header_sync: Загрузка заголовков
|
||||
header_sync_percent: 'Загрузка заголовков: %{percent}%'
|
||||
tx_hashset_pibd: 'Загрузка состояния (PIBD)'
|
||||
tx_hashset_pibd: Загрузка состояния (PIBD)
|
||||
tx_hashset_pibd_percent: 'Загрузка состояния (PIBD): %{percent}%'
|
||||
tx_hashset_download: Загрузка состояния цепи
|
||||
tx_hashset_download_percent: 'Загрузка состояния цепи: %{percent}%'
|
||||
|
@ -57,22 +57,28 @@ network_mining:
|
|||
loading: Майнинг будет доступен после синхронизации
|
||||
server_setup: Настройка stratum-сервера
|
||||
enable_server: Включить сервер
|
||||
server_setting: 'Включите stratum-сервер или измените больше настроек, выбрав %{settings} внизу экрана.'
|
||||
server_setting: 'Включите stratum-сервер или измените больше настроек, выбрав %{settings} внизу экрана. Для изменения настроек запущенного сервера потребуется перезапуск приложения.'
|
||||
info: 'Сервер майнинга запущен, вы можете изменить настройки, выбрав %{settings} внизу экрана. Данные обновляются, когда устройства подключены.'
|
||||
no_ip_addresses: В вашей системе отсутствуют доступные IP адреса, запуск сервера невозможен, проверьте ваше подключение к сети.
|
||||
choose_ip_address: 'Выберите IP адрес:'
|
||||
change_port: 'Измените порт:'
|
||||
ip_address: IP Адрес
|
||||
no_ip_addresses: В вашей системе отсутствуют доступные IP адреса, запуск stratum-сервера невозможен, проверьте ваше подключение к сети.
|
||||
port_unavailable: Указанный порт недоступен
|
||||
rewards_wallet: Кошелёк для наград
|
||||
server: Stratum-сервер
|
||||
address: Адрес
|
||||
miners: Майнеры
|
||||
devices: Устройства
|
||||
found: Найдено
|
||||
hashrate: 'Хешрэйт (C%{bits})'
|
||||
connected: Подключен
|
||||
disconnected: Отключен
|
||||
network_settings:
|
||||
server: Сервер
|
||||
ip_address: IP Адрес
|
||||
port: Порт
|
||||
change_port: Изменить порт
|
||||
enter_value: 'Введите значение:'
|
||||
modal:
|
||||
cancel: Отмена
|
||||
save: Сохранить
|
||||
modal_exit:
|
||||
description: Вы уверены, что хотите выйти из приложения?
|
||||
exit: Выход
|
|
@ -64,7 +64,6 @@ impl App {
|
|||
|
||||
/// Setup application styles.
|
||||
pub fn setup_visuals(ctx: &Context) {
|
||||
// Setup style
|
||||
let mut style = (*ctx.style()).clone();
|
||||
// Setup spacing for buttons.
|
||||
style.spacing.button_padding = egui::vec2(12.0, 8.0);
|
||||
|
@ -76,14 +75,16 @@ impl App {
|
|||
style.spacing.icon_width = 24.0;
|
||||
style.spacing.icon_width_inner = 14.0;
|
||||
style.spacing.icon_spacing = 10.0;
|
||||
|
||||
// Setup style
|
||||
ctx.set_style(style);
|
||||
|
||||
// Setup visuals
|
||||
let mut visuals = egui::Visuals::light();
|
||||
|
||||
// Setup selection color.
|
||||
visuals.selection.stroke = Stroke { width: 1.0, color: Colors::TEXT };
|
||||
visuals.selection.bg_fill = Colors::GOLD;
|
||||
// Disable stroke around panels by default
|
||||
visuals.widgets.noninteractive.bg_stroke = Stroke::NONE;
|
||||
// Setup visuals
|
||||
ctx.set_visuals(visuals);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,10 +25,12 @@ impl Colors {
|
|||
pub const GOLD: Color32 = Color32::from_rgb(255, 215, 0);
|
||||
pub const GREEN: Color32 = Color32::from_rgb(0, 0x64, 0);
|
||||
pub const RED: Color32 = Color32::from_rgb(0x8B, 0, 0);
|
||||
pub const FILL: Color32 = Color32::from_gray(240);
|
||||
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 TEXT: Color32 = Color32::from_gray(80);
|
||||
pub const BUTTON: Color32 = Color32::from_gray(70);
|
||||
pub const TEXT_BUTTON: Color32 = Color32::from_gray(70);
|
||||
pub const BUTTON: Color32 = Color32::from_gray(249);
|
||||
pub const GRAY: Color32 = Color32::from_gray(120);
|
||||
pub const STROKE: Color32 = Color32::from_gray(190);
|
||||
pub const INACTIVE_TEXT: Color32 = Color32::from_gray(150);
|
||||
|
|
|
@ -19,7 +19,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
|||
use lazy_static::lazy_static;
|
||||
|
||||
use crate::gui::screens::ScreenId;
|
||||
use crate::gui::views::{Modal, ModalId, ModalLocation};
|
||||
use crate::gui::views::{Modal, ModalLocation};
|
||||
|
||||
lazy_static! {
|
||||
/// Static [`Navigator`] state to be accessible from anywhere.
|
||||
|
@ -53,6 +53,9 @@ impl Default for Navigator {
|
|||
}
|
||||
|
||||
impl Navigator {
|
||||
/// Identifier for exit [`Modal`].
|
||||
pub const EXIT_MODAL: &'static str = "exit";
|
||||
|
||||
/// Initialize navigation from provided [`ScreenId`].
|
||||
pub fn init(from: ScreenId) {
|
||||
let mut w_nav = NAVIGATOR_STATE.write().unwrap();
|
||||
|
@ -118,7 +121,7 @@ impl Navigator {
|
|||
|
||||
/// Open exit confirmation [`Modal`] with provided [NAVIGATOR_STATE] lock.
|
||||
fn open_exit_modal_nav(mut w_nav: RwLockWriteGuard<Navigator>) {
|
||||
let m = Modal::new(ModalId::Exit, ModalLocation::Global).title(t!("modal_exit.exit"));
|
||||
let m = Modal::new(Self::EXIT_MODAL, ModalLocation::Global).title(t!("modal_exit.exit"));
|
||||
w_nav.global_modal = Some(m);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
use egui::Frame;
|
||||
|
||||
use crate::gui::icons::{ARROW_CIRCLE_LEFT, GLOBE, PLUS};
|
||||
use crate::gui::Navigator;
|
||||
use crate::gui::{Colors, Navigator};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::screens::{Screen, ScreenId};
|
||||
use crate::gui::views::{TitlePanel, TitlePanelAction, View};
|
||||
|
@ -43,6 +43,7 @@ impl Screen for Accounts {
|
|||
egui::CentralPanel::default()
|
||||
.frame(Frame {
|
||||
stroke: View::DEFAULT_STROKE,
|
||||
fill: Colors::FILL_DARK,
|
||||
..Default::default()
|
||||
})
|
||||
.show_inside(ui, |ui| {
|
||||
|
|
|
@ -17,7 +17,7 @@ use std::cmp::min;
|
|||
use crate::gui::{App, Colors, Navigator};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::screens::{Account, Accounts, Screen, ScreenId};
|
||||
use crate::gui::views::{ModalId, ModalLocation, Network, View};
|
||||
use crate::gui::views::{ModalLocation, Network, View};
|
||||
use crate::node::Node;
|
||||
|
||||
pub struct Root {
|
||||
|
@ -67,10 +67,9 @@ impl Root {
|
|||
ui: &mut egui::Ui,
|
||||
frame: &mut eframe::Frame,
|
||||
cb: &dyn PlatformCallbacks) {
|
||||
let location = ModalLocation::Global;
|
||||
Navigator::modal_ui(ui, location, |ui, modal| {
|
||||
Navigator::modal_ui(ui, ModalLocation::Global, |ui, modal| {
|
||||
match modal.id {
|
||||
ModalId::Exit => {
|
||||
Navigator::EXIT_MODAL => {
|
||||
if self.show_exit_progress {
|
||||
if !Node::is_running() {
|
||||
App::exit(frame, cb);
|
||||
|
@ -89,30 +88,36 @@ impl Root {
|
|||
ui.label(t!("modal_exit.description"));
|
||||
});
|
||||
ui.add_space(10.0);
|
||||
// Setup spacing between buttons
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(6.0, 0.0);
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal_exit.exit"), Colors::WHITE, || {
|
||||
if !Node::is_running() {
|
||||
App::exit(frame, cb);
|
||||
|
||||
// Show modal buttons.
|
||||
ui.scope(|ui| {
|
||||
// Setup spacing between buttons.
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(6.0, 0.0);
|
||||
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal_exit.exit"), Colors::WHITE, || {
|
||||
if !Node::is_running() {
|
||||
App::exit(frame, cb);
|
||||
modal.close();
|
||||
} else {
|
||||
Node::stop(true);
|
||||
modal.disable_closing();
|
||||
self.show_exit_progress = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
columns[1].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
|
||||
modal.close();
|
||||
} else {
|
||||
Node::stop(true);
|
||||
modal.disable_closing();
|
||||
self.show_exit_progress = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
columns[1].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
|
||||
modal.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -27,4 +27,6 @@ pub use network::*;
|
|||
mod network_node;
|
||||
mod network_settings;
|
||||
mod network_metrics;
|
||||
mod network_mining;
|
||||
mod network_mining;
|
||||
mod settings_stratum;
|
||||
mod settings_node_server;
|
|
@ -21,11 +21,6 @@ use egui::epaint::RectShape;
|
|||
use crate::gui::Colors;
|
||||
use crate::gui::views::View;
|
||||
|
||||
/// Identifier for [`Modal`] content to draw at [`Modal::ui`].
|
||||
pub enum ModalId {
|
||||
Exit
|
||||
}
|
||||
|
||||
/// Location for [`Modal`] at application UI.
|
||||
pub enum ModalLocation {
|
||||
/// To draw globally above side panel and screen.
|
||||
|
@ -46,8 +41,8 @@ pub enum ModalPosition {
|
|||
|
||||
/// Stores data to draw dialog box/popup at UI, powered by [`egui::Window`].
|
||||
pub struct Modal {
|
||||
/// Identifier for content.
|
||||
pub(crate) id: ModalId,
|
||||
/// Identifier for modal.
|
||||
pub(crate) id: &'static str,
|
||||
/// Location at UI.
|
||||
pub(crate) location: ModalLocation,
|
||||
/// Position on the screen.
|
||||
|
@ -65,7 +60,7 @@ impl Modal {
|
|||
const DEFAULT_WIDTH: i64 = 380;
|
||||
|
||||
/// Create open and closeable Modal with center position.
|
||||
pub fn new(id: ModalId, location: ModalLocation) -> Self {
|
||||
pub fn new(id: &'static str, location: ModalLocation) -> Self {
|
||||
Self {
|
||||
id,
|
||||
location,
|
||||
|
@ -116,9 +111,7 @@ impl Modal {
|
|||
|
||||
/// Show Modal with provided content.
|
||||
pub fn ui(&self, ui: &mut egui::Ui, add_content: impl FnOnce(&mut egui::Ui, &Modal)) {
|
||||
let width = min(ui.available_width() as i64 - 20, Self::DEFAULT_WIDTH) as f32;
|
||||
|
||||
// Show background Window at full available size
|
||||
// Show background Window at full available size.
|
||||
egui::Window::new(self.window_id(true))
|
||||
.title_bar(false)
|
||||
.resizable(false)
|
||||
|
@ -133,13 +126,17 @@ impl Modal {
|
|||
ui.set_min_size(ui.available_size());
|
||||
});
|
||||
|
||||
// Show main content Window at given position
|
||||
// Choose width of modal content.
|
||||
let width = min(ui.available_width() as i64 - 20, Self::DEFAULT_WIDTH) as f32;
|
||||
|
||||
// Show main content Window at given position.
|
||||
let (content_align, content_offset) = self.modal_position();
|
||||
let layer_id = egui::Window::new(self.window_id(false))
|
||||
.title_bar(false)
|
||||
.resizable(false)
|
||||
.collapsible(false)
|
||||
.default_width(width)
|
||||
.anchor(self.modal_position(), Vec2::default())
|
||||
.anchor(content_align, content_offset)
|
||||
.frame(egui::Frame {
|
||||
rounding: Rounding::same(8.0),
|
||||
fill: Colors::YELLOW,
|
||||
|
@ -152,7 +149,7 @@ impl Modal {
|
|||
self.draw_content(ui, add_content);
|
||||
}).unwrap().response.layer_id;
|
||||
|
||||
// Always show main content Window above background Window
|
||||
// Always show main content Window above background Window.
|
||||
ui.ctx().move_to_top(layer_id);
|
||||
|
||||
}
|
||||
|
@ -173,11 +170,16 @@ impl Modal {
|
|||
}
|
||||
|
||||
/// Get [`egui::Window`] position based on [`ModalPosition`].
|
||||
fn modal_position(&self) -> Align2 {
|
||||
match self.position {
|
||||
fn modal_position(&self) -> (Align2, Vec2) {
|
||||
let align = match self.position {
|
||||
ModalPosition::CenterTop => { Align2::CENTER_TOP }
|
||||
ModalPosition::Center => { Align2::CENTER_CENTER }
|
||||
}
|
||||
};
|
||||
let offset = match self.position {
|
||||
ModalPosition::CenterTop => { Vec2::new(0.0, 20.0) }
|
||||
ModalPosition::Center => { Vec2::new(0.0, 0.0) }
|
||||
};
|
||||
(align, offset)
|
||||
}
|
||||
|
||||
/// Draw provided content.
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddrV4, TcpListener};
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
use egui::{Color32, lerp, Rgba, RichText, Stroke};
|
||||
|
@ -22,17 +24,18 @@ use grin_chain::SyncStatus;
|
|||
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, ModalLocation, View};
|
||||
use crate::gui::views::network_metrics::NetworkMetrics;
|
||||
use crate::gui::views::network_mining::NetworkMining;
|
||||
use crate::gui::views::network_node::NetworkNode;
|
||||
use crate::gui::views::network_settings::NetworkSettings;
|
||||
use crate::gui::views::View;
|
||||
use crate::node::Node;
|
||||
use crate::Settings;
|
||||
|
||||
pub trait NetworkTab {
|
||||
fn get_type(&self) -> NetworkTabType;
|
||||
fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks);
|
||||
fn on_modal_ui(&mut self, ui: &mut egui::Ui, modal: &Modal, cb: &dyn PlatformCallbacks);
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
|
@ -68,13 +71,19 @@ impl Default for Network {
|
|||
|
||||
impl Network {
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, cb: &dyn PlatformCallbacks) {
|
||||
// Show modal if it's opened.
|
||||
if Navigator::is_modal_open(ModalLocation::SidePanel) {
|
||||
Navigator::modal_ui(ui, ModalLocation::SidePanel, |ui, modal| {
|
||||
self.current_tab.as_mut().on_modal_ui(ui, modal, cb);
|
||||
});
|
||||
}
|
||||
|
||||
egui::TopBottomPanel::top("network_title")
|
||||
.resizable(false)
|
||||
.frame(egui::Frame {
|
||||
fill: Colors::YELLOW,
|
||||
inner_margin: Margin::same(0.0),
|
||||
outer_margin: Margin::same(0.0),
|
||||
stroke: Stroke::NONE,
|
||||
..Default::default()
|
||||
})
|
||||
.show_inside(ui, |ui| {
|
||||
|
@ -217,7 +226,8 @@ impl Network {
|
|||
});
|
||||
}
|
||||
|
||||
pub fn disabled_server_content(ui: &mut egui::Ui) {
|
||||
/// Content to draw when node is disabled.
|
||||
pub fn disabled_node_ui(ui: &mut egui::Ui) {
|
||||
View::center_content(ui, 162.0, |ui| {
|
||||
let text = t!("network.disabled_server", "dots" => DOTS_THREE_OUTLINE_VERTICAL);
|
||||
ui.label(RichText::new(text)
|
||||
|
@ -241,5 +251,25 @@ impl Network {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// List of available IP addresses.
|
||||
pub fn get_ip_list() -> Vec<IpAddr> {
|
||||
let mut addresses = Vec::new();
|
||||
for net_if in pnet::datalink::interfaces() {
|
||||
for ip in net_if.ips {
|
||||
if ip.is_ipv4() {
|
||||
addresses.push(ip.ip());
|
||||
}
|
||||
}
|
||||
}
|
||||
addresses
|
||||
}
|
||||
|
||||
/// Check whether a port is available on the provided host.
|
||||
pub fn is_port_available(host: &str, port: u16) -> bool {
|
||||
let ip_addr = Ipv4Addr::from_str(host).unwrap();
|
||||
let ipv4 = SocketAddrV4::new(ip_addr, port);
|
||||
TcpListener::bind(ipv4).is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,13 +13,13 @@
|
|||
// limitations under the License.
|
||||
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
use egui::{RichText, Rounding, ScrollArea, Stroke};
|
||||
use egui::{RichText, Rounding, ScrollArea, Stroke, Ui};
|
||||
use grin_servers::DiffBlock;
|
||||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::{AT, COINS, CUBE_TRANSPARENT, HASH, HOURGLASS_LOW, HOURGLASS_MEDIUM, TIMER};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Network, NetworkTab, NetworkTabType, View};
|
||||
use crate::gui::views::{Modal, Network, NetworkTab, NetworkTabType, View};
|
||||
use crate::node::Node;
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -39,7 +39,7 @@ impl NetworkTab for NetworkMetrics {
|
|||
// Show message when node is not running or loading spinner when metrics are not available.
|
||||
if server_stats.is_none() || server_stats.as_ref().unwrap().diff_stats.height == 0 {
|
||||
if !Node::is_running() {
|
||||
Network::disabled_server_content(ui);
|
||||
Network::disabled_node_ui(ui);
|
||||
} else {
|
||||
View::center_content(ui, 162.0, |ui| {
|
||||
View::big_loading_spinner(ui);
|
||||
|
@ -113,9 +113,9 @@ impl NetworkTab for NetworkMetrics {
|
|||
// Show difficulty adjustment window blocks
|
||||
let blocks_size = stats.diff_stats.last_blocks.len();
|
||||
ScrollArea::vertical()
|
||||
.id_source("difficulty_scroll")
|
||||
.auto_shrink([false; 2])
|
||||
.stick_to_bottom(true)
|
||||
.id_source("difficulty_scroll")
|
||||
.show_rows(
|
||||
ui,
|
||||
DIFF_BLOCK_UI_HEIGHT,
|
||||
|
@ -137,6 +137,8 @@ impl NetworkTab for NetworkMetrics {
|
|||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn on_modal_ui(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {}
|
||||
}
|
||||
|
||||
const DIFF_BLOCK_UI_HEIGHT: f32 = 76.60;
|
||||
|
|
|
@ -12,24 +12,23 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::fmt::format;
|
||||
use std::net::IpAddr;
|
||||
use std::str::FromStr;
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
use egui::{RichText, Rounding, ScrollArea, Stroke};
|
||||
use egui::{Response, RichText, Rounding, ScrollArea, Stroke, TextStyle, Widget};
|
||||
use grin_chain::SyncStatus;
|
||||
use grin_servers::WorkerStats;
|
||||
use pnet::ipnetwork::IpNetwork;
|
||||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::{BARBELL, CLOCK_AFTERNOON, COMPUTER_TOWER, CPU, CUBE, FADERS, FOLDER_DASHED, FOLDER_NOTCH_MINUS, FOLDER_NOTCH_PLUS, PLUGS, PLUGS_CONNECTED, POLYGON, WRENCH};
|
||||
use crate::gui::{Colors, Navigator};
|
||||
use crate::gui::icons::{BARBELL, CLOCK_AFTERNOON, COMPUTER_TOWER, CPU, CUBE, FADERS, FOLDER_DASHED, FOLDER_NOTCH_MINUS, FOLDER_NOTCH_PLUS, PLUGS, PLUGS_CONNECTED, POLYGON};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Network, NetworkTab, NetworkTabType, View};
|
||||
use crate::node::Node;
|
||||
use crate::gui::views::{Modal, Network, NetworkTab, NetworkTabType, View};
|
||||
use crate::gui::views::settings_stratum::StratumServerSetup;
|
||||
use crate::node::{Node, NodeConfig};
|
||||
use crate::Settings;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct NetworkMining;
|
||||
pub struct NetworkMining {
|
||||
stratum_server_setup: StratumServerSetup
|
||||
}
|
||||
|
||||
impl NetworkTab for NetworkMining {
|
||||
fn get_type(&self) -> NetworkTabType {
|
||||
|
@ -42,7 +41,7 @@ impl NetworkTab for NetworkMining {
|
|||
// Show message when node is not running or loading spinner when mining are not available.
|
||||
if !server_stats.is_some() || Node::get_sync_status().unwrap() != SyncStatus::NoSync {
|
||||
if !Node::is_running() {
|
||||
Network::disabled_server_content(ui);
|
||||
Network::disabled_node_ui(ui);
|
||||
} else {
|
||||
View::center_content(ui, 162.0, |ui| {
|
||||
View::big_loading_spinner(ui);
|
||||
|
@ -58,137 +57,31 @@ impl NetworkTab for NetworkMining {
|
|||
|
||||
let stratum_stats = &server_stats.as_ref().unwrap().stratum_stats;
|
||||
|
||||
// Stratum server address + port from config.
|
||||
let saved_stratum_addr = Settings::node_config_to_read()
|
||||
.members.clone()
|
||||
.server.stratum_mining_config.unwrap()
|
||||
.stratum_server_addr.unwrap();
|
||||
let (stratum_addr, stratum_port) = saved_stratum_addr.split_once(":").unwrap();
|
||||
|
||||
// List of available ip addresses.
|
||||
let mut addresses = Vec::new();
|
||||
for net_if in pnet::datalink::interfaces() {
|
||||
for ip in net_if.ips {
|
||||
if ip.is_ipv4() {
|
||||
addresses.push(ip.ip());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Show error message when IP addresses are not available on the system.
|
||||
if addresses.is_empty() {
|
||||
View::center_content(ui, 52.0, |ui| {
|
||||
ui.label(RichText::new(t!("network_mining.no_ip_addresses"))
|
||||
.size(16.0)
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Show stratum server setup when mining server is not enabled.
|
||||
// Show stratum server setup when mining server is not running.
|
||||
if !stratum_stats.is_running && !Node::is_stratum_server_starting() {
|
||||
ScrollArea::vertical()
|
||||
.id_source("stratum_server_setup")
|
||||
.auto_shrink([false; 2])
|
||||
.show(ui, |ui| {
|
||||
ui.add_space(6.0);
|
||||
View::sub_title(ui,
|
||||
format!("{} {}", WRENCH, t!("network_mining.server_setup")));
|
||||
|
||||
ui.add_space(4.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
self.stratum_server_setup.ui(ui, cb);
|
||||
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("network_mining.choose_ip_address"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY)
|
||||
);
|
||||
ui.add_space(10.0);
|
||||
|
||||
if addresses.len() != 0 {
|
||||
let saved_ip_addr = &IpAddr::from_str(stratum_addr).unwrap();
|
||||
let mut selected_addr = saved_ip_addr;
|
||||
|
||||
// Set first IP address as current if saved is not present at system.
|
||||
if !addresses.contains(selected_addr) {
|
||||
selected_addr = addresses.get(0).unwrap();
|
||||
}
|
||||
|
||||
// Show available IP addresses on the system.
|
||||
let _ = addresses.chunks(2).map(|x| {
|
||||
if x.len() == 2 {
|
||||
ui.columns(2, |columns| {
|
||||
let addr0 = x.get(0).unwrap();
|
||||
columns[0].vertical_centered(|ui| {
|
||||
View::radio_value(ui,
|
||||
&mut selected_addr,
|
||||
addr0,
|
||||
addr0.to_string());
|
||||
});
|
||||
let addr1 = x.get(1).unwrap();
|
||||
columns[1].vertical_centered(|ui| {
|
||||
View::radio_value(ui,
|
||||
&mut selected_addr,
|
||||
addr1,
|
||||
addr1.to_string());
|
||||
})
|
||||
});
|
||||
ui.add_space(12.0);
|
||||
} else {
|
||||
let addr = x.get(0).unwrap();
|
||||
View::radio_value(ui,
|
||||
&mut selected_addr,
|
||||
addr,
|
||||
addr.to_string());
|
||||
ui.add_space(4.0);
|
||||
}
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
// Save stratum server address at config if it was changed.
|
||||
if saved_ip_addr != selected_addr {
|
||||
let addr_to_save = format!("{}:{}", selected_addr, stratum_port);
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
w_node_config.members
|
||||
.server.stratum_mining_config.as_mut().unwrap()
|
||||
.stratum_server_addr = Some(addr_to_save);
|
||||
w_node_config.save();
|
||||
}
|
||||
}
|
||||
|
||||
ui.label(RichText::new(t!("network_mining.change_port"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY)
|
||||
);
|
||||
|
||||
// Show button to choose server port.
|
||||
ui.add_space(6.0);
|
||||
View::button(ui, stratum_port.to_string(), Colors::WHITE, || {
|
||||
//TODO: Open modal to change value
|
||||
cb.show_keyboard();
|
||||
});
|
||||
|
||||
ui.add_space(14.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
|
||||
// Show message about stratum server config.
|
||||
let text = t!(
|
||||
"network_mining.server_setting",
|
||||
"address" => saved_stratum_addr,
|
||||
"settings" => FADERS
|
||||
);
|
||||
let text = t!("network_mining.server_setting", "settings" => FADERS);
|
||||
ui.label(RichText::new(text)
|
||||
.size(16.0)
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
ui.add_space(8.0);
|
||||
ui.add_space(4.0);
|
||||
|
||||
// Show button to enable server.
|
||||
View::button(ui, t!("network_mining.enable_server"), Colors::GOLD, || {
|
||||
Node::start_stratum_server();
|
||||
});
|
||||
ui.add_space(2.0);
|
||||
// Show button to enable stratum server if port is available.
|
||||
if self.stratum_server_setup.stratum_port_available {
|
||||
ui.add_space(6.0);
|
||||
View::button(ui, t!("network_mining.enable_server"), Colors::GOLD, || {
|
||||
Node::start_stratum_server();
|
||||
});
|
||||
ui.add_space(2.0);
|
||||
}
|
||||
|
||||
let stratum_enabled = Settings::node_config_to_read()
|
||||
.members.clone()
|
||||
|
@ -218,9 +111,10 @@ impl NetworkTab for NetworkMining {
|
|||
View::sub_title(ui, format!("{} {}", COMPUTER_TOWER, t!("network_mining.server")));
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered(|ui| {
|
||||
let (stratum_addr, stratum_port) = NodeConfig::get_stratum_address_port();
|
||||
View::rounded_box(ui,
|
||||
saved_stratum_addr,
|
||||
t!("network_mining.ip_address"),
|
||||
format!("{}:{}", stratum_addr, stratum_port),
|
||||
t!("network_mining.address"),
|
||||
[true, false, true, false]);
|
||||
});
|
||||
columns[1].vertical_centered(|ui| {
|
||||
|
@ -302,7 +196,6 @@ impl NetworkTab for NetworkMining {
|
|||
ui.add_space(4.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(4.0);
|
||||
|
||||
ScrollArea::vertical()
|
||||
.auto_shrink([false; 2])
|
||||
.id_source("stratum_workers_scroll")
|
||||
|
@ -322,7 +215,7 @@ impl NetworkTab for NetworkMining {
|
|||
} else {
|
||||
[false, false]
|
||||
};
|
||||
draw_worker_stats(ui, worker, rounding)
|
||||
draw_workers_stats(ui, worker, rounding)
|
||||
}
|
||||
},
|
||||
);
|
||||
|
@ -335,11 +228,20 @@ 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 => {
|
||||
self.stratum_server_setup.stratum_port_modal_ui(ui, modal, cb);
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const WORKER_UI_HEIGHT: f32 = 77.0;
|
||||
|
||||
fn draw_worker_stats(ui: &mut egui::Ui, ws: &WorkerStats, rounding: [bool; 2]) {
|
||||
fn draw_workers_stats(ui: &mut egui::Ui, ws: &WorkerStats, rounding: [bool; 2]) {
|
||||
// Add space before the first item.
|
||||
if rounding[0] {
|
||||
ui.add_space(4.0);
|
||||
|
|
|
@ -13,13 +13,13 @@
|
|||
// limitations under the License.
|
||||
|
||||
use eframe::epaint::Stroke;
|
||||
use egui::{RichText, Rounding, ScrollArea};
|
||||
use egui::{RichText, Rounding, ScrollArea, Ui};
|
||||
use grin_servers::PeerStats;
|
||||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::{AT, CUBE, DEVICES, FLOW_ARROW, HANDSHAKE, PACKAGE, PLUGS_CONNECTED, SHARE_NETWORK};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Network, NetworkTab, NetworkTabType, View};
|
||||
use crate::gui::views::{Modal, Network, NetworkTab, NetworkTabType, View};
|
||||
use crate::node::Node;
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -35,7 +35,7 @@ impl NetworkTab for NetworkNode {
|
|||
// Show message when node is not running or loading spinner when stats are not available.
|
||||
if !server_stats.is_some() {
|
||||
if !Node::is_running() {
|
||||
Network::disabled_server_content(ui);
|
||||
Network::disabled_node_ui(ui);
|
||||
} else {
|
||||
ui.centered_and_justified(|ui| {
|
||||
View::big_loading_spinner(ui);
|
||||
|
@ -47,6 +47,7 @@ impl NetworkTab for NetworkNode {
|
|||
let stats = server_stats.as_ref().unwrap();
|
||||
|
||||
ScrollArea::vertical()
|
||||
.id_source("integrated_node")
|
||||
.auto_shrink([false; 2])
|
||||
.show(ui, |ui| {
|
||||
// Show header info.
|
||||
|
@ -180,6 +181,8 @@ impl NetworkTab for NetworkNode {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn on_modal_ui(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {}
|
||||
}
|
||||
|
||||
fn draw_peer_stats(ui: &mut egui::Ui, peer: &PeerStats, rounding: [bool; 2]) {
|
||||
|
|
|
@ -12,9 +12,12 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use egui::Ui;
|
||||
use grin_core::global::ChainTypes;
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::COMPUTER_TOWER;
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{NetworkTab, NetworkTabType};
|
||||
use crate::gui::views::{Modal, NetworkTab, NetworkTabType, View};
|
||||
use crate::Settings;
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -26,5 +29,13 @@ impl NetworkTab for NetworkSettings {
|
|||
}
|
||||
|
||||
fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) {
|
||||
View::sub_title(ui, format!("{} {}", COMPUTER_TOWER, t!("network_settings.server")));
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(4.0);
|
||||
|
||||
}
|
||||
|
||||
fn on_modal_ui(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
||||
|
||||
}
|
||||
}
|
16
src/gui/views/settings_node_server.rs
Normal file
16
src/gui/views/settings_node_server.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2023 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.
|
||||
|
||||
// /// Integrated node server setup ui section.
|
||||
// struct
|
247
src/gui/views/settings_stratum.rs
Normal file
247
src/gui/views/settings_stratum.rs
Normal file
|
@ -0,0 +1,247 @@
|
|||
// Copyright 2023 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 std::net::IpAddr;
|
||||
use std::str::FromStr;
|
||||
|
||||
use egui::{RichText, TextStyle, Widget};
|
||||
|
||||
use crate::gui::{Colors, Navigator};
|
||||
use crate::gui::icons::WRENCH;
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Modal, ModalLocation, ModalPosition, Network, View};
|
||||
use crate::node::NodeConfig;
|
||||
|
||||
/// Stratum server setup ui section.
|
||||
pub struct StratumServerSetup {
|
||||
/// Stratum address to be used inside edit modal.
|
||||
stratum_address_edit: String,
|
||||
/// Stratum port to be used inside edit modal.
|
||||
stratum_port_edit: String,
|
||||
/// Flag to check if stratum port is available inside edit modal.
|
||||
port_available_edit: bool,
|
||||
|
||||
/// Flag to check if stratum port is available from saved config value.
|
||||
pub(crate) stratum_port_available: bool
|
||||
}
|
||||
|
||||
impl Default for StratumServerSetup {
|
||||
fn default() -> Self {
|
||||
let (stratum_address, stratum_port) = NodeConfig::get_stratum_address_port();
|
||||
let is_port_available = Network::is_port_available(stratum_address.as_str(), stratum_port);
|
||||
Self {
|
||||
stratum_address_edit: stratum_address,
|
||||
stratum_port_edit: stratum_port.to_string(),
|
||||
port_available_edit: is_port_available,
|
||||
stratum_port_available: is_port_available
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StratumServerSetup {
|
||||
/// Identifier for stratum port [`Modal`].
|
||||
pub const STRATUM_PORT_MODAL: &'static str = "stratum_port";
|
||||
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) {
|
||||
View::sub_title(ui, format!("{} {}", WRENCH, t!("network_mining.server_setup")));
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(4.0);
|
||||
|
||||
// Show error message when IP addresses are not available on the system.
|
||||
let mut addresses = Network::get_ip_list();
|
||||
if addresses.is_empty() {
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("network_mining.no_ip_addresses"))
|
||||
.size(16.0)
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("network_settings.ip_address"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY)
|
||||
);
|
||||
ui.add_space(6.0);
|
||||
|
||||
// Show stratum IP address setup.
|
||||
Self::ip_address_setup_ui(ui, addresses);
|
||||
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
|
||||
ui.label(RichText::new(t!("network_settings.port"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY)
|
||||
);
|
||||
|
||||
// Show button to choose stratum server port.
|
||||
ui.add_space(6.0);
|
||||
let (stratum_address, stratum_port) = NodeConfig::get_stratum_address_port();
|
||||
View::button(ui, stratum_port.to_string(), Colors::BUTTON, || {
|
||||
// Setup values for modal.
|
||||
self.stratum_address_edit = stratum_address.clone();
|
||||
self.stratum_port_edit = stratum_port.to_string();
|
||||
self.port_available_edit = Network::is_port_available(
|
||||
stratum_address.as_str(),
|
||||
stratum_port
|
||||
);
|
||||
|
||||
// Show stratum port modal.
|
||||
let port_modal = Modal::new(Self::STRATUM_PORT_MODAL,
|
||||
ModalLocation::SidePanel)
|
||||
.position(ModalPosition::CenterTop)
|
||||
.title(t!("network_settings.change_port"));
|
||||
Navigator::open_modal(port_modal);
|
||||
cb.show_keyboard();
|
||||
});
|
||||
ui.add_space(12.0);
|
||||
|
||||
// Show error when stratum server port is unavailable.
|
||||
if !self.stratum_port_available {
|
||||
ui.label(RichText::new(t!("network_mining.port_unavailable"))
|
||||
.size(16.0)
|
||||
.color(Colors::RED));
|
||||
ui.add_space(12.0);
|
||||
}
|
||||
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
}
|
||||
|
||||
/// Draw stratum port [`Modal`] content.
|
||||
pub fn stratum_port_modal_ui(&mut self,
|
||||
ui: &mut egui::Ui,
|
||||
modal: &Modal,
|
||||
cb: &dyn PlatformCallbacks) {
|
||||
ui.add_space(6.0);
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("network_settings.enter_value"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY));
|
||||
ui.add_space(8.0);
|
||||
|
||||
// Draw stratum port text edit.
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.stratum_port_edit)
|
||||
.font(TextStyle::Button)
|
||||
.desired_width(48.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
if text_edit_resp.clicked() {
|
||||
cb.show_keyboard();
|
||||
}
|
||||
|
||||
// Show error when specified port is unavailable.
|
||||
if !self.port_available_edit {
|
||||
ui.add_space(12.0);
|
||||
ui.label(RichText::new(t!("network_mining.port_unavailable"))
|
||||
.size(16.0)
|
||||
.color(Colors::RED));
|
||||
}
|
||||
|
||||
ui.add_space(12.0);
|
||||
|
||||
// Show modal buttons.
|
||||
ui.scope(|ui| {
|
||||
// Setup spacing between buttons.
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(6.0, 0.0);
|
||||
|
||||
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, || {
|
||||
// Check if port is available.
|
||||
let port_parse = self.stratum_port_edit.parse::<u16>();
|
||||
let is_available = port_parse.is_ok() && Network::is_port_available(
|
||||
self.stratum_address_edit.as_str(),
|
||||
port_parse.unwrap()
|
||||
);
|
||||
self.port_available_edit = is_available;
|
||||
|
||||
// Save port at config if it's available.
|
||||
if self.port_available_edit {
|
||||
NodeConfig::save_stratum_address_port(
|
||||
self.stratum_address_edit.clone(),
|
||||
self.stratum_port_edit.clone()
|
||||
);
|
||||
|
||||
self.stratum_port_available = true;
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Show stratum IP address setup.
|
||||
fn ip_address_setup_ui(ui: &mut egui::Ui, addresses: Vec<IpAddr>) {
|
||||
let (addr, port) = NodeConfig::get_stratum_address_port();
|
||||
let saved_ip_addr = &IpAddr::from_str(addr.as_str()).unwrap();
|
||||
let mut selected_addr = saved_ip_addr;
|
||||
|
||||
// Set first IP address as current if saved is not present at system.
|
||||
if !addresses.contains(selected_addr) {
|
||||
selected_addr = addresses.get(0).unwrap();
|
||||
}
|
||||
|
||||
// Show available IP addresses on the system.
|
||||
let _ = addresses.chunks(2).map(|x| {
|
||||
if x.len() == 2 {
|
||||
ui.columns(2, |columns| {
|
||||
let addr0 = x.get(0).unwrap();
|
||||
columns[0].vertical_centered(|ui| {
|
||||
View::radio_value(ui,
|
||||
&mut selected_addr,
|
||||
addr0,
|
||||
addr0.to_string());
|
||||
});
|
||||
let addr1 = x.get(1).unwrap();
|
||||
columns[1].vertical_centered(|ui| {
|
||||
View::radio_value(ui,
|
||||
&mut selected_addr,
|
||||
addr1,
|
||||
addr1.to_string());
|
||||
})
|
||||
});
|
||||
} else {
|
||||
let addr = x.get(0).unwrap();
|
||||
View::radio_value(ui,
|
||||
&mut selected_addr,
|
||||
addr,
|
||||
addr.to_string());
|
||||
}
|
||||
ui.add_space(10.0);
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
// Save stratum server address at config if it was changed.
|
||||
if saved_ip_addr != selected_addr {
|
||||
NodeConfig::save_stratum_address_port(selected_addr.to_string(), port.to_string());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -115,7 +115,7 @@ impl View {
|
|||
|
||||
/// Draw [`Button`] with specified background fill color.
|
||||
pub fn button(ui: &mut egui::Ui, text: String, fill_color: Color32, action: impl FnOnce()) {
|
||||
let br = Button::new(RichText::new(text.to_uppercase()).size(18.0).color(Colors::BUTTON))
|
||||
let br = Button::new(RichText::new(text.to_uppercase()).size(18.0).color(Colors::TEXT_BUTTON))
|
||||
.stroke(Self::DEFAULT_STROKE)
|
||||
.fill(fill_color)
|
||||
.ui(ui);
|
||||
|
@ -207,7 +207,7 @@ impl View {
|
|||
/// Draw the button that looks like checkbox with callback on check.
|
||||
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::BUTTON) }
|
||||
true => { (format!("{} {}", CHECK_SQUARE, text), Colors::TEXT_BUTTON) }
|
||||
false => { (format!("{} {}", SQUARE, text), Colors::TEXT) }
|
||||
};
|
||||
let br = Button::new(RichText::new(text_value).size(18.0).color(color))
|
||||
|
|
|
@ -12,9 +12,17 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Write};
|
||||
use std::net::IpAddr;
|
||||
use std::str::FromStr;
|
||||
|
||||
use grin_config::{config, ConfigError, ConfigMembers, GlobalConfig};
|
||||
use grin_config::config::{API_SECRET_FILE_NAME, FOREIGN_API_SECRET_FILE_NAME, SERVER_CONFIG_FILE_NAME};
|
||||
use grin_core::global::ChainTypes;
|
||||
use grin_p2p::msg::PeerAddrs;
|
||||
use grin_p2p::{PeerAddr, Seeding};
|
||||
use grin_servers::common::types::ChainValidationMode;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::Settings;
|
||||
|
@ -73,4 +81,429 @@ impl NodeConfig {
|
|||
config::check_api_secret(&api_secret_path)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get stratum server IP address and port.
|
||||
pub fn get_stratum_address_port() -> (String, u16) {
|
||||
let r_config = Settings::node_config_to_read();
|
||||
let saved_stratum_addr = r_config
|
||||
.members
|
||||
.server
|
||||
.stratum_mining_config
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.stratum_server_addr
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
let (addr, port) = saved_stratum_addr.split_once(":").unwrap();
|
||||
(addr.to_string(), port.parse().unwrap())
|
||||
}
|
||||
|
||||
/// Save stratum server IP address and port.
|
||||
pub fn save_stratum_address_port(addr: String, port: String) {
|
||||
let addr_to_save = format!("{}:{}", addr, port);
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
w_node_config
|
||||
.members
|
||||
.server
|
||||
.stratum_mining_config
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.stratum_server_addr = Some(addr_to_save);
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
/// Get API server IP address and port.
|
||||
pub fn get_api_address_port() -> (String, u16) {
|
||||
let r_config = Settings::node_config_to_read();
|
||||
let saved_api_addr = r_config
|
||||
.members
|
||||
.server
|
||||
.api_http_addr
|
||||
.as_str();
|
||||
let (addr, port) = saved_api_addr.split_once(":").unwrap();
|
||||
(addr.to_string(), port.parse().unwrap())
|
||||
}
|
||||
|
||||
/// Save API server IP address and port.
|
||||
pub fn save_api_server_address_port(addr: String, port: String) {
|
||||
let addr_to_save = format!("{}:{}", addr, port);
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
w_node_config.members.server.api_http_addr = addr_to_save;
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
/// Get API secret text.
|
||||
pub fn get_api_secret() -> String {
|
||||
let r_config = Settings::node_config_to_read();
|
||||
let api_secret_path = r_config
|
||||
.members
|
||||
.server
|
||||
.api_secret_path
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
let api_secret_file = File::open(api_secret_path).unwrap();
|
||||
let buf_reader = BufReader::new(api_secret_file);
|
||||
let mut lines_iter = buf_reader.lines();
|
||||
let first_line = lines_iter.next().unwrap();
|
||||
first_line.unwrap()
|
||||
}
|
||||
|
||||
/// Save API secret text.
|
||||
pub fn save_api_secret(api_secret: String) {
|
||||
if api_secret.is_empty() {
|
||||
return;
|
||||
}
|
||||
let r_config = Settings::node_config_to_read();
|
||||
let api_secret_path = r_config
|
||||
.members
|
||||
.server
|
||||
.api_secret_path
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
let mut api_secret_file = File::create(api_secret_path).unwrap();
|
||||
api_secret_file.write_all(api_secret.as_bytes()).unwrap();
|
||||
}
|
||||
|
||||
/// Get Foreign API secret text.
|
||||
pub fn get_foreign_api_secret() -> String {
|
||||
let r_config = Settings::node_config_to_read();
|
||||
let foreign_api_secret_path = r_config
|
||||
.members
|
||||
.server
|
||||
.foreign_api_secret_path
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
let foreign_api_secret_file = File::open(foreign_api_secret_path).unwrap();
|
||||
let buf_reader = BufReader::new(foreign_api_secret_file);
|
||||
let mut lines_iter = buf_reader.lines();
|
||||
let first_line = lines_iter.next().unwrap();
|
||||
first_line.unwrap()
|
||||
}
|
||||
|
||||
/// Save Foreign API secret text.
|
||||
pub fn save_foreign_api_secret(api_secret: String) {
|
||||
if api_secret.is_empty() {
|
||||
return;
|
||||
}
|
||||
let r_config = Settings::node_config_to_read();
|
||||
let foreign_api_secret_path = r_config
|
||||
.members
|
||||
.server
|
||||
.foreign_api_secret_path
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
let mut foreign_api_secret_file = File::create(foreign_api_secret_path).unwrap();
|
||||
foreign_api_secret_file.write_all(api_secret.as_bytes()).unwrap();
|
||||
}
|
||||
|
||||
/// Get Future Time Limit.
|
||||
pub fn get_ftl() -> u64 {
|
||||
Settings::node_config_to_read().members.server.future_time_limit
|
||||
}
|
||||
|
||||
/// Save Future Time Limit.
|
||||
pub fn save_ftl(ftl: u64) {
|
||||
let mut w_config = Settings::node_config_to_update();
|
||||
w_config.members.server.future_time_limit = ftl;
|
||||
w_config.save();
|
||||
}
|
||||
|
||||
/// Check if full chain validation mode is enabled.
|
||||
pub fn is_full_chain_validation() -> bool {
|
||||
let mode = Settings::node_config_to_read().members.clone().server.chain_validation_mode;
|
||||
mode == ChainValidationMode::EveryBlock
|
||||
}
|
||||
|
||||
/// Toggle full chain validation.
|
||||
pub fn toggle_chain_validation() {
|
||||
let mode = Settings::node_config_to_read().members.clone().server.chain_validation_mode;
|
||||
let new_mode = if mode == ChainValidationMode::Disabled {
|
||||
ChainValidationMode::Disabled
|
||||
} else {
|
||||
ChainValidationMode::EveryBlock
|
||||
};
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
w_node_config.members.server.chain_validation_mode = new_mode;
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
/// Check if node is running in archive mode.
|
||||
pub fn is_archive_mode() -> bool {
|
||||
let archive_mode = Settings::node_config_to_read().members.clone().server.archive_mode;
|
||||
archive_mode.is_some() && archive_mode.unwrap()
|
||||
}
|
||||
|
||||
/// 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.members.server.archive_mode = Some(!archive_mode);
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
// P2P settings
|
||||
|
||||
/// Get P2P server port.
|
||||
pub fn get_p2p_port() -> u16 {
|
||||
Settings::node_config_to_read().members.server.p2p_config.port
|
||||
}
|
||||
|
||||
/// Get P2P server port.
|
||||
pub fn save_p2p_port(port: u16) {
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
w_node_config.members.server.p2p_config.port = port;
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
/// Get peers seeding type.
|
||||
pub fn get_peers_seeding_type() -> Seeding {
|
||||
Settings::node_config_to_read().members.server.p2p_config.seeding_type
|
||||
}
|
||||
|
||||
/// Get seeds for [`Seeding::List`] type.
|
||||
pub fn get_seeds() -> PeerAddrs {
|
||||
let r_config = Settings::node_config_to_read();
|
||||
r_config.members.server.p2p_config.seeds.clone().unwrap_or(PeerAddrs::default())
|
||||
}
|
||||
|
||||
/// Save peers seeding type, with list of peers for [`Seeding::List`] type.
|
||||
pub fn save_peers_seeding_type(seeding_type: Seeding, peers: Option<PeerAddrs>) {
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
w_node_config.members.server.p2p_config.seeding_type = seeding_type;
|
||||
if seeding_type == Seeding::List {
|
||||
w_node_config.members.server.p2p_config.seeds = peers;
|
||||
}
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
/// Get denied peer list.
|
||||
pub fn get_denied_peers() -> PeerAddrs {
|
||||
let r_config = Settings::node_config_to_read();
|
||||
r_config.members.server.p2p_config.peers_deny.clone().unwrap_or(PeerAddrs::default())
|
||||
}
|
||||
|
||||
/// Add peer at denied list.
|
||||
pub fn deny_peer(peer: String) {
|
||||
let ip_addr = IpAddr::from_str(peer.as_str()).unwrap();
|
||||
let peer_addr = PeerAddr::from_ip(ip_addr);
|
||||
|
||||
let mut deny_peers = Self::get_denied_peers();
|
||||
deny_peers.peers.insert(0, peer_addr);
|
||||
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
w_node_config.members.server.p2p_config.peers_deny = Some(deny_peers);
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
/// Save denied peer list.
|
||||
pub fn save_denied_peers(peers: Option<PeerAddrs>) {
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
w_node_config.members.server.p2p_config.peers_deny = peers;
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
/// Get allowed peer list.
|
||||
pub fn get_allowed_peers() -> PeerAddrs {
|
||||
let r_config = Settings::node_config_to_read();
|
||||
r_config.members.server.p2p_config.peers_allow.clone().unwrap_or(PeerAddrs::default())
|
||||
}
|
||||
|
||||
/// Save allowed peer list.
|
||||
pub fn save_allowed_peers(peers: Option<PeerAddrs>) {
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
w_node_config.members.server.p2p_config.peers_allow = peers;
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
/// Get preferred peer list.
|
||||
pub fn get_preferred_peers() -> PeerAddrs {
|
||||
let r_config = Settings::node_config_to_read();
|
||||
r_config.members.server.p2p_config.peers_preferred.clone().unwrap_or(PeerAddrs::default())
|
||||
}
|
||||
|
||||
/// Add peer at preferred list.
|
||||
pub fn prefer_peer(peer: String) {
|
||||
let ip_addr = IpAddr::from_str(peer.as_str()).unwrap();
|
||||
let peer_addr = PeerAddr::from_ip(ip_addr);
|
||||
|
||||
let mut prefer_peers = Self::get_preferred_peers();
|
||||
prefer_peers.peers.insert(0, peer_addr);
|
||||
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
w_node_config.members.server.p2p_config.peers_preferred = Some(prefer_peers);
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
/// Save preferred peer list.
|
||||
pub fn save_preferred_peers(peers: Option<PeerAddrs>) {
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
w_node_config.members.server.p2p_config.peers_preferred = peers;
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
/// How long a banned peer should stay banned in ms.
|
||||
pub fn get_ban_window() -> i64 {
|
||||
Settings::node_config_to_read().members.server.p2p_config.ban_window()
|
||||
}
|
||||
|
||||
/// Set how long a banned peer should stay banned in ms.
|
||||
pub fn set_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);
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
/// Maximum number of inbound peer connections.
|
||||
pub fn get_max_inbound_count() -> u32 {
|
||||
Settings::node_config_to_read().members.server.p2p_config.peer_max_inbound_count()
|
||||
}
|
||||
|
||||
/// Set maximum number of inbound peer connections.
|
||||
pub fn set_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);
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
/// Maximum number of outbound peer connections.
|
||||
pub fn get_max_outbound_count() -> u32 {
|
||||
Settings::node_config_to_read().members.server.p2p_config.peer_max_outbound_count()
|
||||
}
|
||||
|
||||
/// Set maximum number of outbound peer connections.
|
||||
pub fn set_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);
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
/// Minimum number of outbound peer connections.
|
||||
pub fn get_min_outbound_count() -> u32 {
|
||||
Settings::node_config_to_read()
|
||||
.members
|
||||
.server
|
||||
.p2p_config
|
||||
.peer_min_preferred_outbound_count()
|
||||
}
|
||||
|
||||
/// Set minimum number of outbound peer connections.
|
||||
pub fn set_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);
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
/// Set base fee that's accepted into the pool.
|
||||
pub fn set_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
|
||||
}
|
||||
|
||||
/// Set reorg cache retention period in minute.
|
||||
pub fn set_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;
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
/// 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
|
||||
}
|
||||
|
||||
/// Set max amount of transactions at pool.
|
||||
pub fn set_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;
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
/// 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
|
||||
}
|
||||
|
||||
/// Set max amount of transactions at stem pool.
|
||||
pub fn set_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;
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
/// 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
|
||||
}
|
||||
|
||||
/// Set max total weight of transactions that can get selected to build a block.
|
||||
pub fn set_mineable_max_weight(weight: u64) {
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
w_node_config.members.server.pool_config.mineable_max_weight = weight;
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
// Dandelion settings
|
||||
|
||||
/// Dandelion epoch duration in secs.
|
||||
pub fn get_epoch() -> u16 {
|
||||
Settings::node_config_to_read().members.server.dandelion_config.epoch_secs
|
||||
}
|
||||
|
||||
/// Set Dandelion epoch duration in secs.
|
||||
pub fn set_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.
|
||||
/// 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
|
||||
}
|
||||
|
||||
/// Set Dandelion embargo timer.
|
||||
pub fn set_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
|
||||
}
|
||||
|
||||
/// Set Dandelion stem probability.
|
||||
pub fn set_stem_probability(percent: u8) {
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
w_node_config.members.server.dandelion_config.stem_probability = percent;
|
||||
w_node_config.save();
|
||||
}
|
||||
|
||||
/// Default to always stem our txs as described in Dandelion++ paper.
|
||||
pub fn always_stem_our_txs() -> bool {
|
||||
Settings::node_config_to_read().members.server.dandelion_config.always_stem_our_txs
|
||||
}
|
||||
|
||||
/// 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.members.server.dandelion_config.always_stem_our_txs = stem_txs;
|
||||
w_node_config.save();
|
||||
}
|
||||
}
|
|
@ -355,7 +355,6 @@ fn start_server() -> Server {
|
|||
if !global::GLOBAL_CHAIN_TYPE.is_init() {
|
||||
global::init_global_chain_type(config.server.chain_type);
|
||||
}
|
||||
info!("Chain: {:?}", global::get_chain_type());
|
||||
|
||||
if !global::GLOBAL_NRD_FEATURE_ENABLED.is_init() {
|
||||
match global::get_chain_type() {
|
||||
|
@ -372,39 +371,33 @@ fn start_server() -> Server {
|
|||
if !global::GLOBAL_ACCEPT_FEE_BASE.is_init() {
|
||||
let afb = config.server.pool_config.accept_fee_base;
|
||||
global::init_global_accept_fee_base(afb);
|
||||
info!("Accept Fee Base: {:?}", global::get_accept_fee_base());
|
||||
}
|
||||
if !global::GLOBAL_FUTURE_TIME_LIMIT.is_init() {
|
||||
let future_time_limit = config.server.future_time_limit;
|
||||
global::init_global_future_time_limit(future_time_limit);
|
||||
info!("Future Time Limit: {:?}", global::get_future_time_limit());
|
||||
}
|
||||
|
||||
let api_chan: &'static mut (oneshot::Sender<()>, oneshot::Receiver<()>) =
|
||||
Box::leak(Box::new(oneshot::channel::<()>()));
|
||||
let server_result = Server::new(server_config, None, api_chan);
|
||||
//TODO: handle server errors
|
||||
//
|
||||
// if server_result.is_err() {
|
||||
// let mut db_path = PathBuf::from(&server_config.db_root);
|
||||
// db_path.push("grin.lock");
|
||||
// fs::remove_file(db_path).unwrap();
|
||||
//
|
||||
// // Remove chain data on server start error
|
||||
// let dirs_to_remove: Vec<&str> = vec!["header", "lmdb", "txhashset"];
|
||||
// for dir in dirs_to_remove {
|
||||
// let mut path = PathBuf::from(&server_config.db_root);
|
||||
// path.push(dir);
|
||||
// fs::remove_dir_all(path).unwrap();
|
||||
// }
|
||||
//
|
||||
// // Recreate server
|
||||
// let config = node_config.clone().unwrap();
|
||||
// let server_config = config.members.as_ref().unwrap().server.clone();
|
||||
// let api_chan: &'static mut (oneshot::Sender<()>, oneshot::Receiver<()>) =
|
||||
// Box::leak(Box::new(oneshot::channel::<()>()));
|
||||
// server_result = Server::new(server_config.clone(), None, api_chan);
|
||||
// }
|
||||
let mut server_result = Server::new(server_config.clone(), None, api_chan);
|
||||
if server_result.is_err() {
|
||||
let mut db_path = PathBuf::from(&server_config.db_root);
|
||||
db_path.push("grin.lock");
|
||||
fs::remove_file(db_path).unwrap();
|
||||
|
||||
// Remove chain data on server start error
|
||||
let dirs_to_remove: Vec<&str> = vec!["header", "lmdb", "txhashset"];
|
||||
for dir in dirs_to_remove {
|
||||
let mut path = PathBuf::from(&server_config.db_root);
|
||||
path.push(dir);
|
||||
fs::remove_dir_all(path).unwrap();
|
||||
}
|
||||
|
||||
// Recreate server
|
||||
let api_chan: &'static mut (oneshot::Sender<()>, oneshot::Receiver<()>) =
|
||||
Box::leak(Box::new(oneshot::channel::<()>()));
|
||||
server_result = Server::new(server_config.clone(), None, api_chan);
|
||||
}
|
||||
|
||||
server_result.unwrap()
|
||||
}
|
||||
|
|
|
@ -37,15 +37,15 @@ const APP_CONFIG_FILE_NAME: &'static str = "app.toml";
|
|||
pub struct AppConfig {
|
||||
/// Run node server on startup.
|
||||
pub auto_start_node: bool,
|
||||
/// Chain type for node server.
|
||||
node_chain_type: ChainTypes
|
||||
/// Chain type for node and wallets.
|
||||
chain_type: ChainTypes
|
||||
}
|
||||
|
||||
impl Default for AppConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
auto_start_node: false,
|
||||
node_chain_type: ChainTypes::default(),
|
||||
chain_type: ChainTypes::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -66,10 +66,10 @@ impl AppConfig {
|
|||
|
||||
/// Change chain type and load new [`NodeConfig`] accordingly.
|
||||
pub fn change_chain_type(&mut self, chain_type: ChainTypes) {
|
||||
if self.node_chain_type == chain_type {
|
||||
if self.chain_type == chain_type {
|
||||
return;
|
||||
} else {
|
||||
self.node_chain_type = chain_type;
|
||||
self.chain_type = chain_type;
|
||||
self.save();
|
||||
|
||||
// Load config for selected chain type.
|
||||
|
@ -95,7 +95,7 @@ impl Settings {
|
|||
/// Initialize settings with app and node configs.
|
||||
fn init() -> Self {
|
||||
let app_config = AppConfig::init();
|
||||
let chain_type = app_config.node_chain_type;
|
||||
let chain_type = app_config.chain_type;
|
||||
Self {
|
||||
app_config: Arc::new(RwLock::new(app_config)),
|
||||
node_config: Arc::new(RwLock::new(NodeConfig::init(chain_type)))
|
||||
|
|
Loading…
Reference in a new issue