diff --git a/Servers.toml b/Servers.toml index fc0a326..836a52c 100644 --- a/Servers.toml +++ b/Servers.toml @@ -1,24 +1,32 @@ [[server]] -# if port is not present, port is automatically -# determined by the protocol+network combination -# this means the address is capable of serving -# multiple networks. Supported networks must be -# specified in the network field. -name = "local network agnostic server" +name = "kaspa-ng.org" location = "EU" -protocol = "wrpc:borsh" -network = ["mainnet","testnet-10"] -address = "127.0.0.1" +protocol = "borsh" +network = ["mainnet"] +address = "wss://kaspa-ng.org:443/mainnet" [[server]] -# if the port is present, this means the address -# is only capable of serving a single network -# on a dedicated port. The network field should -# contains a single network entry. -name = "local testnet server" +name = "kaspa-ng.org" location = "EU" -protocol = "wrpc:borsh" +protocol = "borsh" +network = ["testnet-11"] +address = "wss://kaspa-ng.org:443/testnet-11" + +[[server]] +name = "localhost" +protocol = "borsh" +network = ["mainnet"] +address = "127.0.0.1" + +[[server]] +name = "localhost" +protocol = "borsh" network = ["testnet-10"] address = "127.0.0.1" -port = 17210 + +[[server]] +name = "localhost" +protocol = "borsh" +network = ["testnet-11"] +address = "127.0.0.1" diff --git a/core/src/core.rs b/core/src/core.rs index 9c9ba39..a630aac 100644 --- a/core/src/core.rs +++ b/core/src/core.rs @@ -14,6 +14,8 @@ use std::borrow::Cow; use workflow_i18n::*; use workflow_wasm::callback::CallbackMap; +const MAX_NETWORK_LOAD_SAMPLES: usize = 16; + pub enum Exception { UtxoIndexNotEnabled { url: Option }, } @@ -54,6 +56,7 @@ pub struct Core { pub debug: bool, pub window_frame: bool, callback_map: CallbackMap, + network_load_samples: VecDeque, } impl Core { @@ -183,12 +186,13 @@ impl Core { release: None, - device: Device::default(), + device: Device::new(window_frame), market: None, servers: parse_default_servers().clone(), debug: false, window_frame, callback_map: CallbackMap::default(), + network_load_samples: VecDeque::default(), }; modules.values().for_each(|module| { @@ -635,6 +639,19 @@ impl Core { Events::Metrics { snapshot } => { self.metrics = Some(snapshot); } + Events::MempoolSize { mempool_size } => { + // println!("mempool_size: {} tps: {}", mempool_size,self.settings.node.network.tps()); + let load = mempool_size as f32 / self.settings.node.network.tps() as f32; + self.network_load_samples.push_back(load); + if self.network_load_samples.len() > MAX_NETWORK_LOAD_SAMPLES { + self.network_load_samples.pop_front(); + } + let network_load = self.network_load_samples.iter().sum::() + / self.network_load_samples.len() as f32; + self.state.network_load.replace(network_load); + + // println!("network_load: {}", network_load); + } Events::Exit => { cfg_if! { if #[cfg(not(target_arch = "wasm32"))] { @@ -692,7 +709,9 @@ impl Core { self.state.url = None; self.state.network_id = None; self.state.current_daa_score = None; + self.state.network_load = None; self.metrics = Some(Box::default()); + self.network_load_samples.clear(); } CoreWallet::UtxoIndexNotEnabled { url } => { self.exception = Some(Exception::UtxoIndexNotEnabled { url }); diff --git a/core/src/device.rs b/core/src/device.rs index 04a0702..4420b0c 100644 --- a/core/src/device.rs +++ b/core/src/device.rs @@ -7,23 +7,25 @@ pub enum Orientation { Portrait, } -#[derive(Default, Clone)] +#[derive(Clone)] pub struct Device { pub mobile_device: bool, pub mobile_forced: bool, pub orientation: Orientation, pub orientation_forced: Option, pub screen_size: Vec2, + pub top_offset: f32, } impl Device { - pub fn new() -> Self { + pub fn new(window_frame: bool) -> Self { Self { mobile_device: false, mobile_forced: false, orientation: Orientation::default(), orientation_forced: None, screen_size: Vec2::ZERO, + top_offset: if window_frame { 0.0 } else { 32.0 }, } } @@ -39,6 +41,10 @@ impl Device { self.screen_size = rect.size(); } + pub fn top_offset(&self) -> f32 { + self.top_offset + } + pub fn orientation(&self) -> Orientation { self.orientation_forced.unwrap_or(self.orientation) } diff --git a/core/src/error.rs b/core/src/error.rs index be5b10f..519dd93 100644 --- a/core/src/error.rs +++ b/core/src/error.rs @@ -71,6 +71,9 @@ pub enum Error { #[error("Invalid network type")] InvalidNetworkType, + #[error("Invalid network '{0}'")] + InvalidNetwork(String), + #[error("Http error: {0}")] HttpError(#[from] workflow_http::error::Error), diff --git a/core/src/events.rs b/core/src/events.rs index dca882c..0dfa60b 100644 --- a/core/src/events.rs +++ b/core/src/events.rs @@ -17,6 +17,9 @@ pub enum Events { Metrics { snapshot: Box, }, + MempoolSize { + mempool_size: usize, + }, Error(Box), ServerList { server_list: Arc>, diff --git a/core/src/modules/logs.rs b/core/src/modules/logs.rs index 8fa87dc..6202408 100644 --- a/core/src/modules/logs.rs +++ b/core/src/modules/logs.rs @@ -17,13 +17,15 @@ impl ModuleT for Logs { fn render( &mut self, - _core: &mut Core, + core: &mut Core, _ctx: &egui::Context, _frame: &mut eframe::Frame, ui: &mut egui::Ui, ) { use egui_phosphor::light::CLIPBOARD_TEXT; + let available_width = ui.available_width(); + #[cfg(not(target_arch = "wasm32"))] egui::ScrollArea::vertical() .id_source("node_logs") @@ -38,9 +40,8 @@ impl ModuleT for Logs { let copy_to_clipboard = Button::new(RichText::new(format!(" {CLIPBOARD_TEXT} ")).size(20.)); - let screen_rect = ui.ctx().screen_rect(); let button_rect = Rect::from_min_size( - pos2(screen_rect.max.x - 48.0, screen_rect.min.y + 32.0), + pos2(available_width - 48.0, core.device().top_offset() + 32.0), vec2(38.0, 20.0), ); diff --git a/core/src/modules/overview.rs b/core/src/modules/overview.rs index 5049b59..f6adb44 100644 --- a/core/src/modules/overview.rs +++ b/core/src/modules/overview.rs @@ -92,7 +92,7 @@ impl Overview { let screen_rect = ui.ctx().screen_rect(); let logo_size = vec2(648., 994.,) * 0.25; let left = screen_rect.width() - logo_size.x - 8.; - let top = if core.window_frame { 64. } else { 32. }; + let top = core.device().top_offset() + 32.0; let logo_rect = Rect::from_min_size(Pos2::new(left, top), logo_size); if screen_rect.width() > 768.0 && !core.device().single_pane() { diff --git a/core/src/modules/settings/mod.rs b/core/src/modules/settings/mod.rs index a61c328..e53a0eb 100644 --- a/core/src/modules/settings/mod.rs +++ b/core/src/modules/settings/mod.rs @@ -7,17 +7,28 @@ pub struct Settings { settings : crate::settings::Settings, grpc_network_interface : NetworkInterfaceEditor, reset_settings : bool, - - + secure_wrpc_only : bool, } impl Settings { pub fn new(runtime: Runtime) -> Self { + + cfg_if!{ + if #[cfg(target_arch = "wasm32")] { + use workflow_dom::utils::*; + let protocol = window().location().protocol().unwrap(); + let secure_wrpc_only = protocol == "https:"; + } else { + let secure_wrpc_only = false; + } + } + Self { runtime, settings : crate::settings::Settings::default(), grpc_network_interface : NetworkInterfaceEditor::default(), reset_settings : false, + secure_wrpc_only, } } @@ -57,6 +68,68 @@ impl ModuleT for Settings { impl Settings { + + fn render_available_servers( + &mut self, + core: &mut Core, + ui: &mut egui::Ui, + ) { + + let servers = core.servers.iter().filter(|server| { + if server.network.contains(&self.settings.node.network) { + !(self.secure_wrpc_only && !(server.address.starts_with("wss://") || server.address.starts_with("wrpcs://"))) + } else { + false + } + }).collect::>(); + let server_count = servers.len(); + + CollapsingHeader::new(format!("{} {} {}", i18n("Public p2p Nodes for"), self.settings.node.network, server_count)) + .default_open(true) + .show(ui, |ui| { + ui.add_space(4.); + + let use_popup = false; + + if !use_popup { + + for server in servers { + if ui.add(Label::new(format!("• {server}")).sense(Sense::click())).clicked() { + self.settings.node.wrpc_encoding = server.wrpc_encoding(); + self.settings.node.wrpc_url = server.address(); + } + } + + } else { + + PopupPanel::new(ui, "server_selector_popup",|ui|{ ui.add(Label::new(format!("{} ⏷",i18n("Select Available Server"))).sense(Sense::click())) }, |ui, _close| { + egui::ScrollArea::vertical() + .id_source("server_selector_popup_scroll") + .auto_shrink([true; 2]) + .show(ui, |ui| { + for server in servers { + if ui.add_sized(theme_style().large_button_size,CompositeButton::opt_image_and_text( + None, + Some(server.to_string().into()), + None, + )).clicked() { + self.settings.node.wrpc_encoding = server.wrpc_encoding(); + self.settings.node.wrpc_url = server.address(); + } + } + }); + }) + .with_min_width(240.) + .with_max_height(core.device().screen_size.y * 0.5) + .with_close_on_interaction(true) + .build(ui); + } + + ui.add_space(4.); + }); + + } + fn render_node_settings( &mut self, core: &mut Core, @@ -71,18 +144,17 @@ impl Settings { .default_open(true) .show(ui, |ui| { - // if !disable_node_settings { - CollapsingHeader::new("Kaspa Network") - .default_open(true) - .show(ui, |ui| { - ui.horizontal_wrapped(|ui|{ - Network::iter().for_each(|network| { - ui.radio_value(&mut self.settings.node.network, *network, network.to_string()); - }); + CollapsingHeader::new("Kaspa Network") + .default_open(true) + .show(ui, |ui| { + ui.horizontal_wrapped(|ui|{ + Network::iter().for_each(|network| { + ui.radio_value(&mut self.settings.node.network, *network, network.to_string()); }); }); + }); + - CollapsingHeader::new("Kaspa Node") .default_open(true) .show(ui, |ui| { @@ -135,7 +207,7 @@ impl Settings { } #[cfg(not(target_arch = "wasm32"))] - if core.settings.developer.custom_daemon_args_enabled() && core.settings.node.node_kind.is_config_capable() { + if core.settings.developer.custom_daemon_args_enabled() && self.settings.node.node_kind.is_config_capable() { use kaspad_lib::args::Args; use clap::error::ErrorKind as ClapErrorKind; use crate::runtime::services::kaspa::Config; @@ -202,9 +274,16 @@ impl Settings { } else { self.settings.node.grpc_network_interface = self.grpc_network_interface.as_ref().try_into().unwrap(); //NetworkInterfaceConfig::try_from(&self.grpc_network_interface).unwrap(); } + + ui.add_space(4.); }); if self.settings.node.node_kind == KaspadNodeKind::Remote { + + self.render_available_servers(core,ui); + + + CollapsingHeader::new(i18n("Remote p2p Node Configuration")) .default_open(true) .show(ui, |ui| { @@ -233,14 +312,18 @@ impl Settings { node_settings_error = Some(i18n("Invalid wRPC URL")); } - #[cfg(not(target_arch = "wasm32"))] - ui.horizontal_wrapped(|ui|{ - // ui.set_max_width(half_width); - ui.label(i18n("Recommended arguments for the remote node: ")); - ui.label(RichText::new("kaspad --utxoindex --rpclisten-borsh=0.0.0.0").code().font(FontId::monospace(14.0)).color(theme_color().strong_color)); - ui.label(i18n("If you are running locally, use: ")); - ui.label(RichText::new("--rpclisten-borsh=127.0.0.1.").code().font(FontId::monospace(14.0)).color(theme_color().strong_color)); - }); + cfg_if! { + if #[cfg(not(target_arch = "wasm32"))] { + ui.horizontal_wrapped(|ui|{ + ui.label(i18n("Recommended arguments for the remote node: ")); + ui.label(RichText::new("kaspad --utxoindex --rpclisten-borsh=0.0.0.0").code().font(FontId::monospace(14.0)).color(theme_color().strong_color)); + }); + ui.horizontal_wrapped(|ui|{ + ui.label(i18n("If you are running locally, use: ")); + ui.label(RichText::new("--rpclisten-borsh=127.0.0.1.").code().font(FontId::monospace(14.0)).color(theme_color().strong_color)); + }); + } + } }); } @@ -330,9 +413,7 @@ impl Settings { ui: &mut egui::Ui, ) { - if !core.settings.disable_node_settings { - self.render_node_settings(core,ui); - } + self.render_node_settings(core,ui); CollapsingHeader::new(i18n("Centralized Services")) .default_open(true) diff --git a/core/src/modules/welcome.rs b/core/src/modules/welcome.rs index 76d015b..2563c33 100644 --- a/core/src/modules/welcome.rs +++ b/core/src/modules/welcome.rs @@ -51,11 +51,9 @@ impl ModuleT for Welcome { match self.settings.node.network { Network::Mainnet => { ui.colored_label(theme_color().warning_color, i18n("Please note that this is an alpha release. Until this message is removed, avoid using this software with mainnet funds.")); - }, - Network::Testnet11 => { - ui.colored_label(theme_color().warning_color, i18n("Testnet 11 is not yet enabled for public testing. You can, however, configure the node to connect to the private developer testnet in the Settings panel.")); - }, - _ => { } + } + Network::Testnet10 => { } + Network::Testnet11 => { } } }); diff --git a/core/src/network.rs b/core/src/network.rs index d5e70b4..089cbde 100644 --- a/core/src/network.rs +++ b/core/src/network.rs @@ -1,3 +1,6 @@ +use kaspa_consensus_core::config::params::Params; +use kaspa_wallet_core::tx::MAXIMUM_STANDARD_TRANSACTION_MASS; + use crate::imports::*; #[derive(Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] @@ -21,6 +24,19 @@ impl std::fmt::Display for Network { } } +impl FromStr for Network { + type Err = Error; + + fn from_str(s: &str) -> std::result::Result { + match s { + "mainnet" => Ok(Network::Mainnet), + "testnet-10" => Ok(Network::Testnet10), + "testnet-11" => Ok(Network::Testnet11), + _ => Err(Error::InvalidNetwork(s.to_string())), + } + } +} + impl From for NetworkType { fn from(network: Network) -> Self { match network { @@ -41,6 +57,12 @@ impl From for NetworkId { } } +impl From for Params { + fn from(network: Network) -> Self { + NetworkId::from(network).into() + } +} + const NETWORKS: [Network; 3] = [Network::Mainnet, Network::Testnet10, Network::Testnet11]; impl Network { @@ -55,4 +77,10 @@ impl Network { Network::Testnet11 => i18n("Testnet-11 (10 BPS)"), } } + + pub fn tps(&self) -> u64 { + let params = Params::from(*self); + // println!("{}, bps: {}, block mass: {} tx size: {} tx/block : {}",self, params.bps(), params.max_block_mass, MAXIMUM_STANDARD_TRANSACTION_MASS, params.max_block_mass / MAXIMUM_STANDARD_TRANSACTION_MASS); + params.max_block_mass / MAXIMUM_STANDARD_TRANSACTION_MASS * params.bps() + } } diff --git a/core/src/runtime/services/metrics_monitor.rs b/core/src/runtime/services/metrics_monitor.rs index 199a801..4f7a068 100644 --- a/core/src/runtime/services/metrics_monitor.rs +++ b/core/src/runtime/services/metrics_monitor.rs @@ -72,6 +72,13 @@ impl MetricsService { }); } + self.application_events + .sender + .try_send(crate::events::Events::MempoolSize { + mempool_size: snapshot.get(&Metric::NetworkMempoolSize) as usize, + }) + .unwrap(); + self.application_events .sender .try_send(crate::events::Events::Metrics { snapshot }) diff --git a/core/src/servers.rs b/core/src/servers.rs index 9755ccb..93c387e 100644 --- a/core/src/servers.rs +++ b/core/src/servers.rs @@ -4,12 +4,37 @@ use crate::imports::*; pub struct Server { pub name: Option, pub location: Option, - pub protocol: String, + pub protocol: WrpcEncoding, pub network: Vec, pub port: Option, pub address: String, } +impl std::fmt::Display for Server { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut title = self.name.clone().unwrap_or(self.address.to_string()); + if let Some(location) = self.location.as_ref() { + title += format!(" ({location})").as_str(); + } + + write!(f, "{}", title) + } +} + +impl Server { + pub fn address(&self) -> String { + if let Some(port) = self.port { + format!("{}:{port}", self.address) + } else { + self.address.clone() + } + } + + pub fn wrpc_encoding(&self) -> WrpcEncoding { + self.protocol + } +} + #[derive(Clone, Debug, Serialize, Deserialize)] pub struct ServerConfig { server: Vec, diff --git a/core/src/settings.rs b/core/src/settings.rs index 5c9fdd5..ac3f458 100644 --- a/core/src/settings.rs +++ b/core/src/settings.rs @@ -93,20 +93,21 @@ impl KaspadNodeKind { } } -// #[cfg(target_arch = "wasm32")] +#[cfg(target_arch = "wasm32")] fn get_hostname() -> Option { - use workflow_dom::utils::*; use workflow_core::runtime; + use workflow_dom::utils::*; if runtime::is_chrome_extension() { None } else { - let location = location().unwrap(); - let hostname = location.hostname().expect("KaspadNodeKind: Unable to get hostname"); + let hostname = location() + .unwrap() + .hostname() + .expect("KaspadNodeKind: Unable to get hostname"); Some(hostname.to_string()) } } - #[derive(Default, Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] pub enum RpcKind { #[default] @@ -224,10 +225,12 @@ impl Default for NodeSettings { let (network, wrpc_url) = if let Some(hostname) = get_hostname() { if hostname.contains(".kaspa-ng.") { - let network = hostname.split('.').first().map(|s| s.to_string()).unwrap_or_default() + let network = hostname.split('.').collect::>().first().map(|s| s.to_string()).unwrap_or_default() .parse::().unwrap_or(Network::Mainnet); let wrpc_url = format!("wss://{hostname}/{network}"); (network, wrpc_url) + } else if hostname == "wallet.kaspanet.io" { + (Network::default(), "wss://wallet.kaspanet.io/mainnet".to_string()) } else if hostname.contains("127.0.0.1") || hostname.contains("localhost") { (Network::default(), "ws://127.0.0.1".to_string()) } else { @@ -250,7 +253,7 @@ impl Default for NodeSettings { grpc_network_interface: NetworkInterfaceConfig::default(), enable_upnp: true, // network: Network::Mainnet, - network,//: Network::Testnet10, + network, //: Network::Testnet10, // network: Network::default(), node_kind: KaspadNodeKind::default(), kaspad_daemon_binary: String::default(), @@ -414,7 +417,6 @@ impl DeveloperSettings { pub struct Settings { pub initialized: bool, pub splash_screen: bool, - pub disable_node_settings : bool, pub version: String, pub developer: DeveloperSettings, pub node: NodeSettings, @@ -426,26 +428,12 @@ pub struct Settings { impl Default for Settings { fn default() -> Self { - - cfg_if! { - if #[cfg(not(target_arch = "wasm32"))] { - let disable_node_settings = if let Some(hostname) = get_hostname() { - hostname.contains(".kaspa-ng.") - } else { - false - }; - } else { - let disable_node_settings = false; - } - } - Self { #[cfg(not(target_arch = "wasm32"))] initialized: false, #[cfg(target_arch = "wasm32")] initialized: true, - disable_node_settings, splash_screen: true, version: "0.0.0".to_string(), developer: DeveloperSettings::default(), diff --git a/core/src/state.rs b/core/src/state.rs index fbd64be..7598d10 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -11,6 +11,7 @@ pub struct State { pub url: Option, pub network_id: Option, pub current_daa_score: Option, + pub network_load: Option, } impl State { diff --git a/resources/i18n/i18n.json b/resources/i18n/i18n.json index 3a865b7..783ab0d 100644 --- a/resources/i18n/i18n.json +++ b/resources/i18n/i18n.json @@ -14,13 +14,13 @@ "nl": "Dutch", "vi": "Vietnamese", "fa": "Farsi", + "pa": "Panjabi", "fil": "Filipino", "lt": "Lithuanian", "sv": "Swedish", + "es": "Español", "fi": "Finnish", - "pa": "Panjabi", "uk": "Ukrainian", - "es": "Español", "af": "Afrikaans", "et": "Esti", "en": "English", @@ -62,223 +62,293 @@ "nl": {}, "vi": {}, "fa": {}, + "pa": {}, "fil": {}, "lt": {}, "sv": {}, "es": {}, - "fi": {}, - "pa": {}, "uk": {}, + "fi": {}, "af": {}, "et": {}, "en": { - "Starting...": "Starting...", - "Storage": "Storage", - "Wallet:": "Wallet:", - "Address:": "Address:", - "Dimensions": "Dimensions", - "Developer mode enables advanced and experimental features": "Developer mode enables advanced and experimental features", "Market": "Market", - "Submitted Blocks": "Submitted Blocks", "Local p2p Node Configuration": "Local p2p Node Configuration", - "Connection": "Connection", - "The node runs as a part of the Kaspa-NG application process. This reduces communication overhead (experimental).": "The node runs as a part of the Kaspa-NG application process. This reduces communication overhead (experimental).", "Kaspa NG on GitHub": "Kaspa NG on GitHub", - "Show balances in alternate currencies for testnet coins": "Show balances in alternate currencies for testnet coins", "wRPC Borsh Rx/s": "wRPC Borsh Rx/s", "Kaspa Discord": "Kaspa Discord", "Developer Mode": "Developer Mode", - "Borsh Handshake Failures": "Borsh Handshake Failures", - "Show Grid": "Show Grid", - "Block Scale": "Block Scale", - "None": "None", "Enter the password for your wallet": "Enter the password for your wallet", - "Medium Narrow": "Medium Narrow", - "Type": "Type", "Parents": "Parents", - "Presets": "Presets", + "Please specify the name of the new wallet": "Please specify the name of the new wallet", "Memory": "Memory", - "Centralized Services": "Centralized Services", "Blocks": "Blocks", - "DAA Range": "DAA Range", - "Volume": "Volume", "DB Headers": "DB Headers", "Virtual Parent Hashes": "Virtual Parent Hashes", - "gRPC Rx/s": "gRPC Rx/s", - "Kaspa NG": "Kaspa NG", + "You can configure remote connection in Settings": "You can configure remote connection in Settings", "Node Status": "Node Status", "Spread": "Spread", "Track in the background": "Track in the background", - "Storage Read/s": "Storage Read/s", "Enable custom daemon arguments": "Enable custom daemon arguments", "Connections": "Connections", - "Export Wallet Data": "Export Wallet Data", - "Please select the private key to export": "Please select the private key to export", "Levels": "Levels", - "Reset Settings": "Reset Settings", - "CONNECTED": "CONNECTED", + "Enter the amount": "Enter the amount", "CPU": "CPU", - "Storage Write/s": "Storage Write/s", "Unlocking": "Unlocking", - "Mass Processed": "Mass Processed", + "Please configure your Kaspa NG settings": "Please configure your Kaspa NG settings", "Unlock": "Unlock", "DAA Offset": "DAA Offset", - "Disables node connectivity (Offline Mode).": "Disables node connectivity (Offline Mode).", - "Total Tx/s": "Total Tx/s", + "If you are running locally, use: ": "If you are running locally, use: ", "Select a wallet to unlock": "Select a wallet to unlock", - "A binary at another location is spawned a child process (experimental, for development purposes only).": "A binary at another location is spawned a child process (experimental, for development purposes only).", "System": "System", - "Virtual Memory": "Virtual Memory", + "A binary at another location is spawned a child process (experimental, for development purposes only).": "A binary at another location is spawned a child process (experimental, for development purposes only).", "Resident Memory": "Resident Memory", "Inbound": "Inbound", - "Donations": "Donations", - "Bezier Curves": "Bezier Curves", - "Metrics": "Metrics", + "Payment & Recovery Password": "Payment & Recovery Password", "All": "All", - "Enable gRPC": "Enable gRPC", - "Account Name": "Account Name", "Processed Headers": "Processed Headers", - "Mempool Size": "Mempool Size", + "Creating Wallet": "Creating Wallet", "Medium Wide": "Medium Wide", + "Apply": "Apply", + "Select Private Key Type": "Select Private Key Type", "Because of its focus on security and performance, this software is entirely developed in Rust, demanding significantly more time and effort compared to other traditional modern web-driven software.": "Because of its focus on security and performance, this software is entirely developed in Rust, demanding significantly more time and effort compared to other traditional modern web-driven software.", - "No transactions": "No transactions", - "Json Connection Attempts": "Json Connection Attempts", + "Settings": "Settings", + "Optional": "Optional", + "wRPC URL:": "wRPC URL:", "Check for Updates": "Check for Updates", - "Tools ⏷": "Tools ⏷", - "Threshold": "Threshold", "p2p Rx/s": "p2p Rx/s", "Theme Color": "Theme Color", - "Connects to a Remote Rusty Kaspa Node via wRPC.": "Connects to a Remote Rusty Kaspa Node via wRPC.", "Difficulty": "Difficulty", "Uptime:": "Uptime:", - "Enable Market Monitor": "Enable Market Monitor", - "Not connected": "Not connected", - "Copy logs to clipboard": "Copy logs to clipboard", - "Shows balances in alternate currencies (BTC, USD) when using testnet coins as if you are on mainnet": "Shows balances in alternate currencies (BTC, USD) when using testnet coins as if you are on mainnet", - "Handles": "Handles", - "UTXOs": "UTXOs", "Small (10 BPS)": "Small (10 BPS)", - "Account:": "Account:", - "Address derivation scan": "Address derivation scan", - "Supporting Kaspa NG development": "Supporting Kaspa NG development", + "Not connected": "Not connected", + "Your wallet has been created and is ready to use.": "Your wallet has been created and is ready to use.", + "Please create a stronger password": "Please create a stronger password", + "Very dangerous (may be cracked within few seconds)": "Very dangerous (may be cracked within few seconds)", + "Secret is too weak": "Secret is too weak", "Please note, copying to clipboard carries a risk of exposing your mnemonic to malware.": "Please note, copying to clipboard carries a risk of exposing your mnemonic to malware.", "Resulting daemon arguments:": "Resulting daemon arguments:", "Network": "Network", - "Select Wallet": "Select Wallet", "Time Offset:": "Time Offset:", "Market Monitor": "Market Monitor", "Unlock Wallet": "Unlock Wallet", - "DAA": "DAA", - "Theme Style": "Theme Style", - "Large (1 BPS)": "Large (1 BPS)", - "Balance: N/A": "Balance: N/A", - "gRPC Tx": "gRPC Tx", + "Wallet Encryption Password": "Wallet Encryption Password", "Dependencies": "Dependencies", "Active p2p Peers": "Active p2p Peers", "Updating...": "Updating...", "Chain Blocks": "Chain Blocks", - "p2p Rx": "p2p Rx", + "Check for Software Updates via GitHub": "Check for Software Updates via GitHub", "p2p Tx": "p2p Tx", "Advanced": "Advanced", - "Check for Software Updates via GitHub": "Check for Software Updates via GitHub", - "ECDSA": "ECDSA", - "Derivation Indexes": "Derivation Indexes", - "WASM SDK for JavaScript and TypeScript": "WASM SDK for JavaScript and TypeScript", - "Kaspa p2p Node": "Kaspa p2p Node", + "Payment Request": "Payment Request", + "The balance may be out of date during node sync": "The balance may be out of date during node sync", "p2p Tx/s": "p2p Tx/s", - "Enable experimental features": "Enable experimental features", - "gRPC Rx": "gRPC Rx", - "NPM Modules for NodeJS": "NPM Modules for NodeJS", + "wRPC Encoding:": "wRPC Encoding:", "License Information": "License Information", "Storage Write": "Storage Write", - "Processed Bodies": "Processed Bodies", - "Contributions directed toward this project directly fuel the Kaspa NG software and its ecosystem.": "Contributions directed toward this project directly fuel the Kaspa NG software and its ecosystem.", - "Stor Write": "Stor Write", - "Total Rx/s": "Total Rx/s", - "MT": "MT", + "User Interface": "User Interface", "Processed Mass Counts": "Processed Mass Counts", "User Agent": "User Agent", - "Allow custom arguments for the Rusty Kaspa daemon": "Allow custom arguments for the Rusty Kaspa daemon", + "Welcome to Kaspa NG": "Welcome to Kaspa NG", "bye!": "bye!", - "Range:": "Range:", "Json Handshake Failures": "Json Handshake Failures", - "Storage Read": "Storage Read", - "wRPC JSON Rx": "wRPC JSON Rx", "The node is spawned as a child daemon process (recommended).": "The node is spawned as a child daemon process (recommended).", + "Storage Read": "Storage Read", + "Allows you to take screenshots from within the application": "Allows you to take screenshots from within the application", + "Change Address": "Change Address", "Network Peers": "Network Peers", "gRPC Tx/s": "gRPC Tx/s", "wRPC JSON Rx/s": "wRPC JSON Rx/s", - "Allows you to take screenshots from within the application": "Allows you to take screenshots from within the application", - "Custom arguments:": "Custom arguments:", - "Receive Address": "Receive Address", - "Outbound": "Outbound", - "Change Address": "Change Address", - "Build": "Build", - "Removes security restrictions, allows for single-letter passwords": "Removes security restrictions, allows for single-letter passwords", - "UTXO Manager": "UTXO Manager", + "Enable optional BIP39 passphrase": "Enable optional BIP39 passphrase", + "Skip": "Skip", "Total Tx": "Total Tx", "Peers": "Peers", "Processed Transactions": "Processed Transactions", "Borsh Connection Attempts": "Borsh Connection Attempts", - "TPS": "TPS", + "Decrypting wallet, please wait...": "Decrypting wallet, please wait...", "wRPC Borsh Tx": "wRPC Borsh Tx", "Mempool": "Mempool", "wRPC Borsh Rx": "wRPC Borsh Rx", - "Protocol:": "Protocol:", + "Medium Narrow": "Medium Narrow", "Transactions": "Transactions", "Enable screen capture": "Enable screen capture", - "Opening wallet:": "Opening wallet:", - "wRPC JSON Tx/s": "wRPC JSON Tx/s", - "Virt Parents": "Virt Parents", + "24 word mnemonic": "24 word mnemonic", + "Activate custom daemon arguments": "Activate custom daemon arguments", + "Dimensions": "Dimensions", "Create new wallet": "Create new wallet", "DB Blocks": "DB Blocks", - "Market Cap": "Market Cap", "The Kaspa NG software represents an ongoing effort focused on building a state-of-the-art software platform dedicated to the Kaspa BlockDAG cryptocurrency network. Ideological at its core, this software prioritizes security, privacy, performance, and decentralization.": "The Kaspa NG software represents an ongoing effort focused on building a state-of-the-art software platform dedicated to the Kaspa BlockDAG cryptocurrency network. Ideological at its core, this software prioritizes security, privacy, performance, and decentralization.", - "File Handles": "File Handles", "Json Active Connections": "Json Active Connections", "Show DAA": "Show DAA", - "p2p RPC": "p2p RPC", - "Activate custom daemon arguments": "Activate custom daemon arguments", - "wRPC Borsh Tx/s": "wRPC Borsh Tx/s", - "Create New Wallet": "Create New Wallet", + "Your private key mnemonic is:": "Your private key mnemonic is:", + "Kaspa p2p Node & Connection": "Kaspa p2p Node & Connection", "Disable password score restrictions": "Disable password score restrictions", - "Close": "Close", "Database Headers": "Database Headers", + "Close": "Close", "Tip Hashes": "Tip Hashes", - "Decrypting wallet, please wait...": "Decrypting wallet, please wait...", "Resources": "Resources", - "Center VSPC": "Center VSPC", - "Rusty Kaspa on GitHub": "Rusty Kaspa on GitHub", + "Kaspa Network": "Kaspa Network", + "Testnet 11 is not yet enabled for public testing. You can, however, configure the node to connect to the private developer testnet in the Settings panel.": "Testnet 11 is not yet enabled for public testing. You can, however, configure the node to connect to the private developer testnet in the Settings panel.", "Ping:": "Ping:", - "Xpub Keys": "Xpub Keys", - "Enable UPnP": "Enable UPnP", - "Account Index": "Account Index", - "Bodies": "Bodies", - "Network Difficulty": "Network Difficulty", - "IBD:": "IBD:", - "Your private key mnemonic is:": "Your private key mnemonic is:", "Key Perf.": "Key Perf.", "24h Change": "24h Change", "Processed Dependencies": "Processed Dependencies", - "Bandwidth": "Bandwidth", "Price": "Price", "Rust Wallet SDK": "Rust Wallet SDK", - "Total Rx": "Total Rx", - "Show VSPC": "Show VSPC", "Enables features currently in development": "Enables features currently in development", - "Details": "Details", + "Show VSPC": "Show VSPC", "Create New Account": "Create New Account", - "Enter the password to unlock your wallet": "Enter the password to unlock your wallet", - "Borsh Active Connections": "Borsh Active Connections", - "Please wait for the node to sync...": "Please wait for the node to sync...", + "Confirm wallet password": "Confirm wallet password", + "The node is currently syncing with the Kaspa p2p network.": "The node is currently syncing with the Kaspa p2p network.", + "A wallet is stored in a file on your computer.": "A wallet is stored in a file on your computer.", "Client RPC": "Client RPC", "wRPC JSON Tx": "wRPC JSON Tx", + "Virtual DAA Score": "Virtual DAA Score", + "Wallet:": "Wallet:", "Double click on the graph to re-center...": "Double click on the graph to re-center...", - "Past Median Time": "Past Median Time", + "Stor Read": "Stor Read", "Database Blocks": "Database Blocks", - "Virtual DAA Score": "Virtual DAA Score", "Headers": "Headers", - "Stor Read": "Stor Read" + "Address:": "Address:", + "Mainnet (Main Kaspa network)": "Mainnet (Main Kaspa network)", + "Developer mode enables advanced and experimental features": "Developer mode enables advanced and experimental features", + "Submitted Blocks": "Submitted Blocks", + "Remote p2p Node Configuration": "Remote p2p Node Configuration", + "Connection": "Connection", + "The node runs as a part of the Kaspa-NG application process. This reduces communication overhead (experimental).": "The node runs as a part of the Kaspa-NG application process. This reduces communication overhead (experimental).", + "Show balances in alternate currencies for testnet coins": "Show balances in alternate currencies for testnet coins", + "Testnet-11 (10 BPS)": "Testnet-11 (10 BPS)", + "If not specified, the account will be represented by the numeric id.": "If not specified, the account will be represented by the numeric id.", + "Borsh Handshake Failures": "Borsh Handshake Failures", + "Show Grid": "Show Grid", + "None": "None", + "Type": "Type", + "Filename:": "Filename:", + "Please wait...": "Please wait...", + "Centralized Services": "Centralized Services", + "DAA Range": "DAA Range", + "Volume": "Volume", + "You can create multiple wallets, but only one wallet can be open at a time.": "You can create multiple wallets, but only one wallet can be open at a time.", + "gRPC Rx/s": "gRPC Rx/s", + "Kaspa NG": "Kaspa NG", + "Storage Read/s": "Storage Read/s", + "Export Wallet Data": "Export Wallet Data", + "Please select the private key to export": "Please select the private key to export", + "Reset Settings": "Reset Settings", + "Copied to clipboard": "Copied to clipboard", + "CONNECTED": "CONNECTED", + "Testnet-10 (1 BPS)": "Testnet-10 (1 BPS)", + "Storage Write/s": "Storage Write/s", + "Wallet Name": "Wallet Name", + "Mass Processed": "Mass Processed", + "Please specify the private key type for the new wallet": "Please specify the private key type for the new wallet", + "Public p2p Nodes for": "Public p2p Nodes for", + "Disables node connectivity (Offline Mode).": "Disables node connectivity (Offline Mode).", + "Total Tx/s": "Total Tx/s", + "Threshold": "Threshold", + "Virtual Memory": "Virtual Memory", + "Metrics": "Metrics", + "Donations": "Donations", + "Account Name": "Account Name", + "Bezier Curves": "Bezier Curves", + "Wallet password is used to encrypt your wallet data.": "Wallet password is used to encrypt your wallet data.", + "Enable gRPC": "Enable gRPC", + "Enter wallet password": "Enter wallet password", + "Go to Settings": "Go to Settings", + "Mempool Size": "Mempool Size", + "No transactions": "No transactions", + "Json Connection Attempts": "Json Connection Attempts", + "Tools ⏷": "Tools ⏷", + "Connects to a Remote Rusty Kaspa Node via wRPC.": "Connects to a Remote Rusty Kaspa Node via wRPC.", + "Enable Market Monitor": "Enable Market Monitor", + "Copy logs to clipboard": "Copy logs to clipboard", + "UTXOs": "UTXOs", + "Please specify the name of the default account. The wallet will be created with a default account. Once created, you will be able to create additional accounts as you need.": "Please specify the name of the default account. The wallet will be created with a default account. Once created, you will be able to create additional accounts as you need.", + "Shows balances in alternate currencies (BTC, USD) when using testnet coins as if you are on mainnet": "Shows balances in alternate currencies (BTC, USD) when using testnet coins as if you are on mainnet", + "Handles": "Handles", + "Secret score:": "Secret score:", + "Account:": "Account:", + "Address derivation scan": "Address derivation scan", + "This wallet will never ask you for this mnemonic phrase unless you manually initiate a private key recovery.": "This wallet will never ask you for this mnemonic phrase unless you manually initiate a private key recovery.", + "Large (1 BPS)": "Large (1 BPS)", + "Supporting Kaspa NG development": "Supporting Kaspa NG development", + "DAA": "DAA", + "Your default wallet private key mnemonic is:": "Your default wallet private key mnemonic is:", + "Select Wallet": "Select Wallet", + "Theme Color:": "Theme Color:", + "Theme Style": "Theme Style", + "Show password": "Show password", + "Balance: N/A": "Balance: N/A", + "gRPC Tx": "gRPC Tx", + "Language:": "Language:", + "p2p Rx": "p2p Rx", + "Other operations": "Other operations", + "12 word mnemonic": "12 word mnemonic", + "ECDSA": "ECDSA", + "Derivation Indexes": "Derivation Indexes", + "Continue": "Continue", + "Enter wallet name": "Enter wallet name", + "Kaspa p2p Node": "Kaspa p2p Node", + "WASM SDK for JavaScript and TypeScript": "WASM SDK for JavaScript and TypeScript", + "Enable experimental features": "Enable experimental features", + "gRPC Rx": "gRPC Rx", + "NPM Modules for NodeJS": "NPM Modules for NodeJS", + "Processed Bodies": "Processed Bodies", + "Contributions directed toward this project directly fuel the Kaspa NG software and its ecosystem.": "Contributions directed toward this project directly fuel the Kaspa NG software and its ecosystem.", + "The following will guide you through the process of creating or importing a wallet.": "The following will guide you through the process of creating or importing a wallet.", + "Stor Write": "Stor Write", + "Total Rx/s": "Total Rx/s", + "MT": "MT", + "Allow custom arguments for the Rusty Kaspa daemon": "Allow custom arguments for the Rusty Kaspa daemon", + "Range:": "Range:", + "Custom arguments:": "Custom arguments:", + "wRPC JSON Rx": "wRPC JSON Rx", + "Receive Address": "Receive Address", + "Phishing Hint": "Phishing Hint", + "UTXO Manager": "UTXO Manager", + "Recommended arguments for the remote node: ": "Recommended arguments for the remote node: ", + "Outbound": "Outbound", + "Wallet Created": "Wallet Created", + "Build": "Build", + "Removes security restrictions, allows for single-letter passwords": "Removes security restrictions, allows for single-letter passwords", + "TPS": "TPS", + "Block Scale": "Block Scale", + "Protocol:": "Protocol:", + "Please wait for the node to sync or connect to a remote node.": "Please wait for the node to sync or connect to a remote node.", + "Create New Wallet": "Create New Wallet", + "Presets": "Presets", + "Opening wallet:": "Opening wallet:", + "wRPC JSON Tx/s": "wRPC JSON Tx/s", + "Virt Parents": "Virt Parents", + "Your mnemonic phrase allows your to re-create your private key. The person who has access to this mnemonic will have full control of the Kaspa stored in it. Keep your mnemonic safe. Write it down and store it in a safe, preferably in a fire-resistant location. Do not store your mnemonic on this computer or a mobile device. This wallet will never ask you for this mnemonic phrase unless you manually initiate a private key recovery.": "Your mnemonic phrase allows your to re-create your private key. The person who has access to this mnemonic will have full control of the Kaspa stored in it. Keep your mnemonic safe. Write it down and store it in a safe, preferably in a fire-resistant location. Do not store your mnemonic on this computer or a mobile device. This wallet will never ask you for this mnemonic phrase unless you manually initiate a private key recovery.", + "Market Cap": "Market Cap", + "File Handles": "File Handles", + "Select Available Server": "Select Available Server", + "p2p RPC": "p2p RPC", + "wRPC Borsh Tx/s": "wRPC Borsh Tx/s", + "Private Key Mnemonic": "Private Key Mnemonic", + "Center VSPC": "Center VSPC", + "Enter first account name": "Enter first account name", + "Rusty Kaspa on GitHub": "Rusty Kaspa on GitHub", + "Enable UPnP": "Enable UPnP", + "Xpub Keys": "Xpub Keys", + "Account Index": "Account Index", + "Bodies": "Bodies", + "Network Difficulty": "Network Difficulty", + "IBD:": "IBD:", + "Details": "Details", + "Bandwidth": "Bandwidth", + "Total Rx": "Total Rx", + "Default Account Name": "Default Account Name", + "Enter the password to unlock your wallet": "Enter the password to unlock your wallet", + "Borsh Active Connections": "Borsh Active Connections", + "Theme Style:": "Theme Style:", + "Please wait for the node to sync...": "Please wait for the node to sync...", + "Starting...": "Starting...", + "Storage": "Storage", + "Enter phishing hint": "Enter phishing hint", + "Past Median Time": "Past Median Time", + "Import existing": "Import existing" }, "el": {}, "it": {},