From b4c09bbcb52e19afa26967ecc15300ad00ee78b9 Mon Sep 17 00:00:00 2001 From: Shannon Tenner Date: Thu, 28 Nov 2024 15:49:09 +0200 Subject: [PATCH 01/34] split out tauri commands for readability --- src-tauri/src/commands.rs | 1479 ++++++++++++++++++++++++++++++++++ src-tauri/src/main.rs | 1606 ++----------------------------------- 2 files changed, 1551 insertions(+), 1534 deletions(-) create mode 100644 src-tauri/src/commands.rs diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs new file mode 100644 index 000000000..c80694fcb --- /dev/null +++ b/src-tauri/src/commands.rs @@ -0,0 +1,1479 @@ +use crate::app_config::{AppConfig, GpuThreads}; +use crate::app_in_memory_config::AirdropInMemoryConfig; +use crate::auto_launcher::AutoLauncher; +use crate::binaries::{Binaries, BinaryResolver}; +use crate::credential_manager::{CredentialError, CredentialManager}; +use crate::external_dependencies::{ + ExternalDependencies, ExternalDependency, RequiredExternalDependency, +}; +use crate::gpu_miner_adapter::GpuNodeSource; +use crate::hardware::hardware_status_monitor::HardwareStatusMonitor; +use crate::internal_wallet::{InternalWallet, PaperWalletConfig}; +use crate::node_manager::NodeManagerError; +use crate::p2pool::models::Stats; +use crate::progress_tracker::ProgressTracker; +use crate::systemtray_manager::{SystemtrayManager, SystrayData}; +use crate::tor_adapter::TorConfig; +use crate::wallet_adapter::TransactionInfo; +use crate::wallet_manager::WalletManagerError; +use crate::{ + setup_inner, stop_all_miners, ApplicationsVersions, BaseNodeStatus, CpuMinerMetrics, + GpuMinerMetrics, MaxUsageLevels, MinerMetrics, TariWalletDetails, UniverseAppState, + APPLICATION_FOLDER_ID, MAX_ACCEPTABLE_COMMAND_TIME, +}; +use keyring::Entry; +use log::{debug, error, info, warn}; +use monero_address_creator::Seed as MoneroSeed; +use regex::Regex; +use sentry::integrations::anyhow::capture_anyhow; +use std::fs::{read_dir, remove_dir_all, remove_file}; +use std::sync::atomic::Ordering; +use std::thread::{available_parallelism, sleep}; +use std::time::{Duration, Instant, SystemTime}; +use tari_common::configuration::Network; +use tari_core::transactions::tari_amount::MicroMinotari; +use tauri::{Manager, Window}; + +const LOG_TARGET: &str = "tari::universe::commands"; +const LOG_TARGET_WEB: &str = "tari::universe::web"; + +#[tauri::command] +pub async fn close_splashscreen(window: Window) { + window + .get_window("splashscreen") + .expect("no window labeled 'splashscreen' found") + .close() + .expect("could not close"); + window + .get_window("main") + .expect("no window labeled 'main' found") + .show() + .expect("could not show"); +} + +#[tauri::command] +pub async fn download_and_start_installer( + _missing_dependency: ExternalDependency, +) -> Result<(), String> { + let timer = Instant::now(); + + #[cfg(target_os = "windows")] + if cfg!(target_os = "windows") { + external_dependencies::ExternalDependencies::current() + .install_missing_dependencies(_missing_dependency) + .await + .map_err(|e| { + error!(target: LOG_TARGET, "Could not install missing dependency: {:?}", e); + e.to_string() + })?; + } + + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, + "download_and_start_installer took too long: {:?}", + timer.elapsed() + ); + } + Ok(()) +} + +#[tauri::command] +pub async fn exit_application( + _window: tauri::Window, + state: tauri::State<'_, UniverseAppState>, + app: tauri::AppHandle, +) -> Result<(), String> { + stop_all_miners(state.inner().clone(), 5).await?; + + app.exit(0); + Ok(()) +} + +#[tauri::command] +pub async fn fetch_tor_bridges() -> Result, String> { + let timer = Instant::now(); + let res_html = reqwest::get("https://bridges.torproject.org/bridges?transport=obfs4") + .await + .map_err(|e| e.to_string())? + .text() + .await + .map_err(|e| e.to_string())?; + + let re = Regex::new(r"obfs4.*?
").map_err(|e| e.to_string())?; + let bridges: Vec = re + .find_iter(&res_html) + .map(|m| m.as_str().trim_end_matches("
").to_string()) + .collect(); + info!(target: LOG_TARGET, "Fetched default bridges: {:?}", bridges); + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "fetch_default_tor_bridges took too long: {:?}", timer.elapsed()); + } + Ok(bridges) +} + +#[tauri::command] +pub async fn get_app_config( + _window: tauri::Window, + state: tauri::State<'_, UniverseAppState>, + _app: tauri::AppHandle, +) -> Result { + Ok(state.config.read().await.clone()) +} + +#[tauri::command] +pub async fn get_app_in_memory_config( + _window: tauri::Window, + state: tauri::State<'_, UniverseAppState>, + _app: tauri::AppHandle, +) -> Result { + let timer = Instant::now(); + let res = state.in_memory_config.read().await.clone().into(); + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, + "get_app_in_memory_config took too long: {:?}", + timer.elapsed() + ); + } + Ok(res) +} + +#[tauri::command] +pub async fn get_applications_versions( + app: tauri::AppHandle, +) -> Result { + let timer = Instant::now(); + let binary_resolver = BinaryResolver::current().read().await; + + let tari_universe_version = app.package_info().version.clone(); + let xmrig_version = binary_resolver + .get_binary_version_string(Binaries::Xmrig) + .await; + + let minotari_node_version = binary_resolver + .get_binary_version_string(Binaries::MinotariNode) + .await; + let mm_proxy_version = binary_resolver + .get_binary_version_string(Binaries::MergeMiningProxy) + .await; + let wallet_version = binary_resolver + .get_binary_version_string(Binaries::Wallet) + .await; + let sha_p2pool_version = binary_resolver + .get_binary_version_string(Binaries::ShaP2pool) + .await; + let xtrgpuminer_version = binary_resolver + .get_binary_version_string(Binaries::GpuMiner) + .await; + + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, + "get_applications_versions took too long: {:?}", + timer.elapsed() + ); + } + + drop(binary_resolver); + + Ok(ApplicationsVersions { + tari_universe: tari_universe_version.to_string(), + minotari_node: minotari_node_version, + xmrig: xmrig_version, + mm_proxy: mm_proxy_version, + wallet: wallet_version, + sha_p2pool: sha_p2pool_version, + xtrgpuminer: xtrgpuminer_version, + }) +} + +#[tauri::command] +pub async fn get_external_dependencies() -> Result { + let timer = Instant::now(); + let external_dependencies = ExternalDependencies::current() + .get_external_dependencies() + .await; + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, + "get_external_dependencies took too long: {:?}", + timer.elapsed() + ); + } + Ok(external_dependencies) +} + +#[tauri::command] +pub async fn get_max_consumption_levels( + state: tauri::State<'_, UniverseAppState>, +) -> Result { + // CPU Detection + let timer = Instant::now(); + let max_cpu_available = available_parallelism() + .map(|cores| i32::try_from(cores.get()).unwrap_or(1)) + .map_err(|e| e.to_string())?; + + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "get_available_cpu_cores took too long: {:?}", timer.elapsed()); + } + + let gpu_devices = state + .gpu_miner + .read() + .await + .get_gpu_devices() + .await + .map_err(|e| e.to_string())?; + + let mut max_gpus_threads = Vec::new(); + for gpu_device in gpu_devices { + // let max_gpu_threads = gpu_device.max_grid_size; + // For some reason this is always return 256, even when the cards can do more like + // 4096 or 8192 + let max_gpu_threads = 8192; + max_gpus_threads.push(GpuThreads { + gpu_name: gpu_device.device_name, + max_gpu_threads, + }); + } + + Ok(MaxUsageLevels { + max_cpu_threads: max_cpu_available, + max_gpus_threads, + }) +} + +#[allow(clippy::too_many_lines)] +#[tauri::command] +pub async fn get_miner_metrics( + state: tauri::State<'_, UniverseAppState>, + app: tauri::AppHandle, +) -> Result { + let timer = Instant::now(); + if state.is_getting_miner_metrics.load(Ordering::SeqCst) { + let read = state.cached_miner_metrics.read().await; + if let Some(metrics) = &*read { + warn!(target: LOG_TARGET, "Already getting miner metrics, returning cached value"); + return Ok(metrics.clone()); + } + warn!(target: LOG_TARGET, "Already getting miner metrics"); + return Err("Already getting miner metrics".to_string()); + } + state.is_getting_miner_metrics.store(true, Ordering::SeqCst); + + // info!(target: LOG_TARGET, "1 elapsed {:?}", timer.elapsed()); + let (sha_hash_rate, randomx_hash_rate, block_reward, block_height, block_time, is_synced) = + state + .node_manager + .get_network_hash_rate_and_block_reward() + .await + .unwrap_or_else(|e| { + if !matches!(e, NodeManagerError::NodeNotStarted) { + warn!(target: LOG_TARGET, "Error getting network hash rate and block reward: {}", e); + } + (0, 0, MicroMinotari(0), 0, 0, false) + }); + // info!(target: LOG_TARGET, "2 elapsed {:?}", timer.elapsed()); + + let cpu_miner = state.cpu_miner.read().await; + let cpu_mining_status = match cpu_miner + .status(randomx_hash_rate, block_reward) + .await + .map_err(|e| e.to_string()) + { + Ok(cpu) => cpu, + Err(e) => { + warn!(target: LOG_TARGET, "Error getting cpu miner status: {:?}", e); + state + .is_getting_miner_metrics + .store(false, Ordering::SeqCst); + return Err(e); + } + }; + drop(cpu_miner); + + // info!(target: LOG_TARGET, "3 elapsed {:?}", timer.elapsed()); + + let gpu_miner = state.gpu_miner.read().await; + let gpu_mining_status = match gpu_miner.status(sha_hash_rate, block_reward).await { + Ok(gpu) => gpu, + Err(e) => { + warn!(target: LOG_TARGET, "Error getting gpu miner status: {:?}", e); + state + .is_getting_miner_metrics + .store(false, Ordering::SeqCst); + return Err(e.to_string()); + } + }; + drop(gpu_miner); + + // let config_path = app + // .path_resolver() + // .app_config_dir() + // .expect("Could not get config dir"); + // let _unused = HardwareMonitor::current() + // .write() + // .await + // .load_status_file(config_path); + // let hardware_status = HardwareMonitor::current() + // .write() + // .await + // .read_hardware_parameters(); + + // info!(target: LOG_TARGET, "4 elapsed {:?}", timer.elapsed()); + let gpu_public_parameters = HardwareStatusMonitor::current() + .get_gpu_devices_public_properties() + .await + .map_err(|e| e.to_string())?; + // .map_err(|e| e.to_string())?; + // info!(target: LOG_TARGET, "5 elapsed {:?}", timer.elapsed()); + // let cpu_public_parameters = HardwareStatusMonitor::current() + // .get_cpu_public_properties() + // .await + // .map_err(|e| e.to_string())?; + + // info!(target: LOG_TARGET, "6 elapsed {:?}", timer.elapsed()); + + let new_systemtray_data: SystrayData = SystemtrayManager::current().create_systemtray_data( + cpu_mining_status.hash_rate, + gpu_mining_status.hash_rate as f64, + // gpu_public_parameters.clone(), + // cpu_public_parameters.clone(), + (cpu_mining_status.estimated_earnings + gpu_mining_status.estimated_earnings) as f64, + ); + + // info!(target: LOG_TARGET, "7 elapsed {:?}", timer.elapsed()); + SystemtrayManager::current().update_systray(app, new_systemtray_data); + + // info!(target: LOG_TARGET, "8 elapsed {:?}", timer.elapsed()); + let connected_peers = state + .node_manager + .list_connected_peers() + .await + .unwrap_or_default(); + + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "get_miner_metrics took too long: {:?}", timer.elapsed()); + } + + let ret = MinerMetrics { + sha_network_hash_rate: sha_hash_rate, + randomx_network_hash_rate: randomx_hash_rate, + cpu: CpuMinerMetrics { + // hardware: cpu_public_parameters.clone(), + mining: cpu_mining_status, + }, + gpu: GpuMinerMetrics { + hardware: gpu_public_parameters.clone(), + mining: gpu_mining_status, + }, + base_node: BaseNodeStatus { + block_height, + block_time, + is_synced, + is_connected: !connected_peers.is_empty(), + connected_peers, + }, + }; + let mut lock = state.cached_miner_metrics.write().await; + *lock = Some(ret.clone()); + state + .is_getting_miner_metrics + .store(false, Ordering::SeqCst); + + Ok(ret) +} + +#[tauri::command] +pub async fn get_monero_seed_words( + state: tauri::State<'_, UniverseAppState>, + app: tauri::AppHandle, +) -> Result, String> { + let timer = Instant::now(); + + if !state.config.read().await.monero_address_is_generated() { + return Err( + "Monero seed words are not available when a Monero address is provided".to_string(), + ); + } + + let config_path = app + .path_resolver() + .app_config_dir() + .expect("Could not get config dir"); + + let cm = CredentialManager::default_with_dir(config_path); + let cred = match cm.get_credentials() { + Ok(cred) => cred, + Err(e @ CredentialError::PreviouslyUsedKeyring) => { + return Err(e.to_string()); + } + Err(e) => { + error!(target: LOG_TARGET, "Could not get credentials: {:?}", e); + return Err(e.to_string()); + } + }; + + let seed = cred + .monero_seed + .expect("Couldn't get seed from credentials"); + + let seed = MoneroSeed::new(seed); + + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "get_seed_words took too long: {:?}", timer.elapsed()); + } + + seed.seed_words().map_err(|e| e.to_string()) +} + +#[tauri::command] +pub async fn get_p2pool_stats( + state: tauri::State<'_, UniverseAppState>, +) -> Result, String> { + let timer = Instant::now(); + if state.is_getting_p2pool_stats.load(Ordering::SeqCst) { + let read = state.cached_p2pool_stats.read().await; + if let Some(stats) = &*read { + warn!(target: LOG_TARGET, "Already getting p2pool stats, returning cached value"); + return Ok(stats.clone()); + } + warn!(target: LOG_TARGET, "Already getting p2pool stats"); + return Err("Already getting p2pool stats".to_string()); + } + state.is_getting_p2pool_stats.store(true, Ordering::SeqCst); + let p2pool_stats = match state.p2pool_manager.get_stats().await { + Ok(s) => s, + Err(e) => { + warn!(target: LOG_TARGET, "Error getting p2pool stats: {}", e); + None + } + }; + + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "get_p2pool_stats took too long: {:?}", timer.elapsed()); + } + let mut lock = state.cached_p2pool_stats.write().await; + *lock = Some(p2pool_stats.clone()); + state.is_getting_p2pool_stats.store(false, Ordering::SeqCst); + Ok(p2pool_stats) +} + +#[tauri::command] +pub async fn get_paper_wallet_details(app: tauri::AppHandle) -> Result { + let timer = Instant::now(); + let config_path = app + .path_resolver() + .app_config_dir() + .expect("Could not get config dir"); + let internal_wallet = InternalWallet::load_or_create(config_path) + .await + .map_err(|e| e.to_string())?; + let result = internal_wallet + .get_paper_wallet_details() + .await + .map_err(|e| e.to_string())?; + + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "get_paper_wallet_details took too long: {:?}", timer.elapsed()); + } + Ok(result) +} + +#[tauri::command] +pub async fn get_seed_words( + _window: tauri::Window, + _state: tauri::State<'_, UniverseAppState>, + app: tauri::AppHandle, +) -> Result, String> { + let timer = Instant::now(); + let config_path = app + .path_resolver() + .app_config_dir() + .expect("Could not get config dir"); + let internal_wallet = InternalWallet::load_or_create(config_path) + .await + .map_err(|e| e.to_string())?; + let seed_words = internal_wallet + .decrypt_seed_words() + .map_err(|e| e.to_string())?; + let mut res = vec![]; + for i in 0..seed_words.len() { + match seed_words.get_word(i) { + Ok(word) => res.push(word.clone()), + Err(error) => { + error!(target: LOG_TARGET, "Could not get seed word: {:?}", error); + } + } + } + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "get_seed_words took too long: {:?}", timer.elapsed()); + } + Ok(res) +} + +#[tauri::command] +pub async fn get_tari_wallet_details( + state: tauri::State<'_, UniverseAppState>, +) -> Result { + let timer = Instant::now(); + if state.is_getting_wallet_balance.load(Ordering::SeqCst) { + let read = state.cached_wallet_details.read().await; + if let Some(details) = &*read { + warn!(target: LOG_TARGET, "Already getting wallet balance, returning cached value"); + return Ok(details.clone()); + } + warn!(target: LOG_TARGET, "Already getting wallet balance"); + return Err("Already getting wallet balance".to_string()); + } + state + .is_getting_wallet_balance + .store(true, Ordering::SeqCst); + let wallet_balance = match state.wallet_manager.get_balance().await { + Ok(w) => Some(w), + Err(e) => { + if !matches!(e, WalletManagerError::WalletNotStarted) { + warn!(target: LOG_TARGET, "Error getting wallet balance: {}", e); + } + + None + } + }; + let tari_address = state.tari_address.read().await; + + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "get_tari_wallet_details took too long: {:?}", timer.elapsed()); + } + let result = TariWalletDetails { + wallet_balance, + tari_address_base58: tari_address.to_base58(), + tari_address_emoji: tari_address.to_emoji_string(), + }; + let mut lock = state.cached_wallet_details.write().await; + *lock = Some(result.clone()); + state + .is_getting_wallet_balance + .store(false, Ordering::SeqCst); + + Ok(result) +} + +#[tauri::command] +pub async fn get_tor_config( + _window: tauri::Window, + state: tauri::State<'_, UniverseAppState>, + _app: tauri::AppHandle, +) -> Result { + let timer = Instant::now(); + let tor_config = state.tor_manager.get_tor_config().await; + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "get_tor_config took too long: {:?}", timer.elapsed()); + } + Ok(tor_config) +} + +#[allow(clippy::too_many_lines)] +#[tauri::command] +pub async fn get_tor_entry_guards( + state: tauri::State<'_, UniverseAppState>, +) -> Result, String> { + let timer = Instant::now(); + let res = state + .tor_manager + .get_entry_guards() + .await + .map_err(|e| e.to_string())?; + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "get_tor_entry_guards took too long: {:?}", timer.elapsed()); + } + Ok(res) +} + +#[tauri::command] +pub async fn get_transaction_history( + state: tauri::State<'_, UniverseAppState>, +) -> Result, String> { + let timer = Instant::now(); + if state.is_getting_transaction_history.load(Ordering::SeqCst) { + warn!(target: LOG_TARGET, "Already getting transaction history"); + return Err("Already getting transaction history".to_string()); + } + state + .is_getting_transaction_history + .store(true, Ordering::SeqCst); + let transactions = match state.wallet_manager.get_transaction_history().await { + Ok(t) => t, + Err(e) => { + if !matches!(e, WalletManagerError::WalletNotStarted) { + warn!(target: LOG_TARGET, "Error getting transaction history: {}", e); + } + vec![] + } + }; + + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "get_transaction_history took too long: {:?}", timer.elapsed()); + } + + state + .is_getting_transaction_history + .store(false, Ordering::SeqCst); + Ok(transactions) +} + +#[tauri::command] +pub async fn import_seed_words( + seed_words: Vec, + _window: tauri::Window, + state: tauri::State<'_, UniverseAppState>, + app: tauri::AppHandle, +) -> Result<(), String> { + let timer = Instant::now(); + let config_path = app + .path_resolver() + .app_config_dir() + .expect("Could not get config dir"); + let data_dir = app + .path_resolver() + .app_local_data_dir() + .expect("Could not get data dir"); + + stop_all_miners(state.inner().clone(), 5).await?; + + tauri::async_runtime::spawn(async move { + match InternalWallet::create_from_seed(config_path, seed_words).await { + Ok(_wallet) => { + InternalWallet::clear_wallet_local_data(data_dir).await?; + info!(target: LOG_TARGET, "[import_seed_words] Restarting the app"); + app.restart(); + Ok(()) + } + Err(e) => { + error!(target: LOG_TARGET, "Error loading internal wallet: {:?}", e); + Err(e) + } + } + }); + + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "import_seed_words took too long: {:?}", timer.elapsed()); + } + Ok(()) +} + +#[tauri::command] +pub fn log_web_message(level: String, message: Vec) { + let joined_message = message.join(" "); + match level.as_str() { + "error" => { + error!(target: LOG_TARGET_WEB, "{}", joined_message) + } + _ => info!(target: LOG_TARGET_WEB, "{}", joined_message), + } +} + +#[tauri::command] +pub fn open_log_dir(app: tauri::AppHandle) { + let log_dir = app + .path_resolver() + .app_log_dir() + .expect("Could not get log dir"); + if let Err(e) = open::that(log_dir) { + error!(target: LOG_TARGET, "Could not open log dir: {:?}", e); + } +} + +#[tauri::command] +pub async fn reset_settings<'r>( + reset_wallet: bool, + _window: tauri::Window, + state: tauri::State<'_, UniverseAppState>, + app: tauri::AppHandle, +) -> Result<(), String> { + stop_all_miners(state.inner().clone(), 5).await?; + let network = Network::get_current_or_user_setting_or_default().as_key_str(); + + let app_config_dir = app.path_resolver().app_config_dir(); + let app_cache_dir = app.path_resolver().app_cache_dir(); + let app_data_dir = app.path_resolver().app_data_dir(); + let app_local_data_dir = app.path_resolver().app_local_data_dir(); + + let dirs_to_remove = [ + app_config_dir, + app_cache_dir, + app_data_dir, + app_local_data_dir, + ]; + let valid_dir_paths: Vec = dirs_to_remove + .iter() + .filter_map(|dir| { + if let Some(path) = dir { + path.to_str().map(|s| s.to_string()) + } else { + None + } + }) + .collect(); + + if valid_dir_paths.is_empty() { + error!(target: LOG_TARGET, "Could not get app directories for {:?}", valid_dir_paths); + return Err("Could not get app directories".to_string()); + } + // Exclude EBWebView because it is still being used. + let folder_block_list = ["EBWebView"]; + + for dir_path in dirs_to_remove.iter().flatten() { + if dir_path.exists() { + for entry in read_dir(dir_path).map_err(|e| e.to_string())? { + let entry = entry.map_err(|e| e.to_string())?; + let path = entry.path(); + if path.is_dir() { + if let Some(file_name) = path.file_name().and_then(|name| name.to_str()) { + if folder_block_list.contains(&file_name) { + debug!(target: LOG_TARGET, "[reset_settings] Skipping {:?} directory", path); + continue; + } + } + + let contains_wallet_config = + read_dir(&path) + .map_err(|e| e.to_string())? + .any(|inner_entry| { + inner_entry + .map(|e| e.file_name() == "wallet_config.json") + .unwrap_or(false) + }); + + let is_network_dir = path + .file_name() + .and_then(|name| name.to_str()) + .map(|name| name == network) + .unwrap_or(false); + + if !reset_wallet && contains_wallet_config { + debug!(target: LOG_TARGET, "[reset_settings] Skipping {:?} directory because it contains wallet_config.json and reset_wallet is false", path); + continue; + } + if reset_wallet && contains_wallet_config && !is_network_dir { + debug!(target: LOG_TARGET, "[reset_settings] Skipping {:?} directory because it contains wallet_config.json and does not matches network name", path); + continue; + } + + debug!(target: LOG_TARGET, "[reset_settings] Removing {:?} directory", path); + remove_dir_all(path.clone()).map_err(|e| { + error!(target: LOG_TARGET, "[reset_settings] Could not remove {:?} directory: {:?}", path, e); + format!("Could not remove directory: {}", e) + })?; + } else { + debug!(target: LOG_TARGET, "[reset_settings] Removing {:?} file", path); + remove_file(path.clone()).map_err(|e| { + error!(target: LOG_TARGET, "[reset_settings] Could not remove {:?} file: {:?}", path, e); + format!("Could not remove file: {}", e) + })?; + } + } + } + } + + debug!(target: LOG_TARGET, "[reset_settings] Removing keychain items"); + if let Ok(entry) = Entry::new(APPLICATION_FOLDER_ID, "inner_wallet_credentials") { + let _unused = entry.delete_credential(); + } + + info!(target: LOG_TARGET, "[reset_settings] Restarting the app"); + app.restart(); + + Ok(()) +} + +#[tauri::command] +pub async fn resolve_application_language( + state: tauri::State<'_, UniverseAppState>, +) -> Result { + let mut config = state.config.write().await; + let _unused = config.propose_system_language().await; + + Ok(config.application_language().to_string()) +} + +#[tauri::command] +pub async fn restart_application( + should_stop_miners: bool, + _window: tauri::Window, + state: tauri::State<'_, UniverseAppState>, + app: tauri::AppHandle, +) -> Result<(), String> { + if should_stop_miners { + stop_all_miners(state.inner().clone(), 5).await?; + } + + app.restart(); + Ok(()) +} + +#[tauri::command] +pub async fn send_feedback( + feedback: String, + include_logs: bool, + _window: tauri::Window, + state: tauri::State<'_, UniverseAppState>, + app: tauri::AppHandle, +) -> Result { + let timer = Instant::now(); + let reference = state + .feedback + .read() + .await + .send_feedback( + feedback, + include_logs, + app.path_resolver().app_log_dir().clone(), + ) + .await + .inspect_err(|e| error!("error at send_feedback {:?}", e)) + .map_err(|e| e.to_string())?; + if timer.elapsed() > Duration::from_secs(60) { + warn!(target: LOG_TARGET, "send_feedback took too long: {:?}", timer.elapsed()); + } + Ok(reference) +} + +#[tauri::command] +pub async fn set_airdrop_access_token( + token: String, + _window: tauri::Window, + state: tauri::State<'_, UniverseAppState>, + _app: tauri::AppHandle, +) -> Result<(), String> { + let timer = Instant::now(); + let mut write_lock = state.airdrop_access_token.write().await; + *write_lock = Some(token.clone()); + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, + "set_airdrop_access_token took too long: {:?}", + timer.elapsed() + ); + } + let mut in_memory_app_config = state.in_memory_config.write().await; + in_memory_app_config.airdrop_access_token = Some(token); + Ok(()) +} + +#[tauri::command] +pub async fn set_allow_telemetry( + allow_telemetry: bool, + _window: tauri::Window, + state: tauri::State<'_, UniverseAppState>, + _app: tauri::AppHandle, +) -> Result<(), String> { + state + .config + .write() + .await + .set_allow_telemetry(allow_telemetry) + .await + .inspect_err(|e| error!(target: LOG_TARGET, "error at set_allow_telemetry {:?}", e)) + .map_err(|e| e.to_string())?; + Ok(()) +} + +#[tauri::command] +pub async fn set_application_language( + state: tauri::State<'_, UniverseAppState>, + application_language: String, +) -> Result<(), String> { + state + .config + .write() + .await + .set_application_language(application_language.clone()) + .await + .map_err(|e| e.to_string())?; + Ok(()) +} + +#[tauri::command] +pub async fn set_auto_update( + auto_update: bool, + state: tauri::State<'_, UniverseAppState>, +) -> Result<(), String> { + let timer = Instant::now(); + state + .config + .write() + .await + .set_auto_update(auto_update) + .await + .inspect_err(|e| error!(target: LOG_TARGET, "error at set_auto_update {:?}", e)) + .map_err(|e| e.to_string())?; + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "set_auto_update took too long: {:?}", timer.elapsed()); + } + + Ok(()) +} + +#[tauri::command] +pub async fn set_cpu_mining_enabled<'r>( + enabled: bool, + state: tauri::State<'_, UniverseAppState>, +) -> Result<(), String> { + let timer = Instant::now(); + let mut config = state.config.write().await; + config + .set_cpu_mining_enabled(enabled) + .await + .inspect_err(|e| error!("error at set_cpu_mining_enabled {:?}", e)) + .map_err(|e| e.to_string())?; + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, + "set_cpu_mining_enabled took too long: {:?}", + timer.elapsed() + ); + } + Ok(()) +} + +#[tauri::command] +pub async fn set_display_mode( + display_mode: String, + state: tauri::State<'_, UniverseAppState>, +) -> Result<(), String> { + let timer = Instant::now(); + state + .config + .write() + .await + .set_display_mode(display_mode) + .await + .inspect_err(|e| error!(target: LOG_TARGET, "error at set_display_mode {:?}", e)) + .map_err(|e| e.to_string())?; + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "set_display_mode took too long: {:?}", timer.elapsed()); + } + + Ok(()) +} + +#[tauri::command] +pub async fn set_excluded_gpu_devices( + excluded_gpu_devices: Vec, + state: tauri::State<'_, UniverseAppState>, +) -> Result<(), String> { + let mut gpu_miner = state.gpu_miner.write().await; + gpu_miner + .set_excluded_device(excluded_gpu_devices) + .await + .inspect_err(|e| error!("error at set_excluded_gpu_devices {:?}", e)) + .map_err(|e| e.to_string())?; + Ok(()) +} + +#[tauri::command] +pub async fn set_gpu_mining_enabled( + enabled: bool, + state: tauri::State<'_, UniverseAppState>, +) -> Result<(), String> { + let timer = Instant::now(); + let mut config = state.config.write().await; + config + .set_gpu_mining_enabled(enabled) + .await + .inspect_err(|e| error!("error at set_gpu_mining_enabled {:?}", e)) + .map_err(|e| e.to_string())?; + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, + "set_gpu_mining_enabled took too long: {:?}", + timer.elapsed() + ); + } + + Ok(()) +} + +#[tauri::command] +pub async fn set_mine_on_app_start( + mine_on_app_start: bool, + state: tauri::State<'_, UniverseAppState>, +) -> Result<(), String> { + let timer = Instant::now(); + + state + .config + .write() + .await + .set_mine_on_app_start(mine_on_app_start) + .await + .inspect_err(|e| error!("error at set_mine_on_app_start {:?}", e)) + .map_err(|e| e.to_string())?; + + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "set_mine_on_app_start took too long: {:?}", timer.elapsed()); + } + + Ok(()) +} + +#[tauri::command] +pub async fn set_mode( + mode: String, + custom_cpu_usage: Option, + custom_gpu_usage: Vec, + state: tauri::State<'_, UniverseAppState>, +) -> Result<(), String> { + let timer = Instant::now(); + info!(target: LOG_TARGET, "set_mode called with mode: {:?}, custom_max_cpu_usage: {:?}, custom_max_gpu_usage: {:?}", mode, custom_cpu_usage, custom_gpu_usage); + + state + .config + .write() + .await + .set_mode(mode, custom_cpu_usage, custom_gpu_usage) + .await + .inspect_err(|e| error!(target: LOG_TARGET, "error at set_mode {:?}", e)) + .map_err(|e| e.to_string())?; + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "set_mode took too long: {:?}", timer.elapsed()); + } + + Ok(()) +} + +#[tauri::command] +pub async fn set_monero_address( + monero_address: String, + state: tauri::State<'_, UniverseAppState>, +) -> Result<(), String> { + let timer = Instant::now(); + let mut app_config = state.config.write().await; + app_config + .set_monero_address(monero_address) + .await + .map_err(|e| e.to_string())?; + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "set_monero_address took too long: {:?}", timer.elapsed()); + } + Ok(()) +} + +#[tauri::command] +pub async fn set_monerod_config( + use_monero_fail: bool, + monero_nodes: Vec, + state: tauri::State<'_, UniverseAppState>, +) -> Result<(), String> { + let timer = Instant::now(); + state + .config + .write() + .await + .set_monerod_config(use_monero_fail, monero_nodes) + .await + .inspect_err(|e| error!(target: LOG_TARGET, "error at set_monerod_config {:?}", e)) + .map_err(|e| e.to_string())?; + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "set_monerod_config took too long: {:?}", timer.elapsed()); + } + + Ok(()) +} + +#[tauri::command] +pub async fn set_p2pool_enabled( + p2pool_enabled: bool, + state: tauri::State<'_, UniverseAppState>, +) -> Result<(), String> { + let timer = Instant::now(); + state + .config + .write() + .await + .set_p2pool_enabled(p2pool_enabled) + .await + .inspect_err(|e| error!("error at set_p2pool_enabled {:?}", e)) + .map_err(|e| e.to_string())?; + + let origin_config = state.mm_proxy_manager.config().await; + let p2pool_grpc_port = state.p2pool_manager.grpc_port().await; + + match origin_config { + None => { + warn!(target: LOG_TARGET, "Tried to set p2pool_enabled but mmproxy has not been initialized yet"); + return Ok(()); + } + Some(mut origin_config) => { + if origin_config.p2pool_enabled != p2pool_enabled { + if p2pool_enabled { + origin_config.set_to_use_p2pool(p2pool_grpc_port); + } else { + let base_node_grpc_port = state + .node_manager + .get_grpc_port() + .await + .map_err(|error| error.to_string())?; + origin_config.set_to_use_base_node(base_node_grpc_port); + }; + state + .mm_proxy_manager + .change_config(origin_config) + .await + .map_err(|error| error.to_string())?; + } + } + }; + + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "set_p2pool_enabled took too long: {:?}", timer.elapsed()); + } + Ok(()) +} + +#[tauri::command] +pub async fn set_should_always_use_system_language( + should_always_use_system_language: bool, + state: tauri::State<'_, UniverseAppState>, +) -> Result<(), String> { + state + .config + .write() + .await + .set_should_always_use_system_language(should_always_use_system_language) + .await + .map_err(|e| e.to_string())?; + Ok(()) +} + +#[tauri::command] +pub async fn set_should_auto_launch( + should_auto_launch: bool, + state: tauri::State<'_, UniverseAppState>, +) -> Result<(), String> { + match state + .config + .write() + .await + .set_should_auto_launch(should_auto_launch) + .await + { + Ok(_) => { + AutoLauncher::current() + .update_auto_launcher(should_auto_launch) + .await + .map_err(|e| { + error!(target: LOG_TARGET, "Error setting should_auto_launch: {:?}", e); + e.to_string() + })?; + } + Err(e) => { + error!(target: LOG_TARGET, "Error setting should_auto_launch: {:?}", e); + return Err(e.to_string()); + } + } + + Ok(()) +} + +#[tauri::command] +pub async fn set_tor_config( + config: TorConfig, + _window: tauri::Window, + state: tauri::State<'_, UniverseAppState>, + _app: tauri::AppHandle, +) -> Result { + let timer = Instant::now(); + let tor_config = state + .tor_manager + .set_tor_config(config) + .await + .map_err(|e| e.to_string())?; + + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "set_tor_config took too long: {:?}", timer.elapsed()); + } + Ok(tor_config) +} + +#[tauri::command] +pub async fn set_use_tor( + use_tor: bool, + state: tauri::State<'_, UniverseAppState>, +) -> Result<(), String> { + let timer = Instant::now(); + state + .config + .write() + .await + .set_use_tor(use_tor) + .await + .inspect_err(|e| error!(target: LOG_TARGET, "error at set_use_tor {:?}", e)) + .map_err(|e| e.to_string())?; + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "set_use_tor took too long: {:?}", timer.elapsed()); + } + + Ok(()) +} + +#[tauri::command] +pub async fn set_visual_mode<'r>( + enabled: bool, + state: tauri::State<'_, UniverseAppState>, +) -> Result<(), String> { + let timer = Instant::now(); + let mut config = state.config.write().await; + config + .set_visual_mode(enabled) + .await + .inspect_err(|e| error!("error at set_visual_mode {:?}", e)) + .map_err(|e| e.to_string())?; + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, + "set_visual_mode took too long: {:?}", + timer.elapsed() + ); + } + Ok(()) +} + +#[tauri::command] +pub async fn setup_application( + window: tauri::Window, + state: tauri::State<'_, UniverseAppState>, + app: tauri::AppHandle, +) -> Result { + let timer = Instant::now(); + let rollback = state.setup_counter.write().await; + if rollback.get_value() { + warn!(target: LOG_TARGET, "setup_application has already been initialized, debouncing"); + let res = state.config.read().await.auto_mining(); + return Ok(res); + } + rollback.set_value(true, Duration::from_millis(1000)).await; + setup_inner(window, state.clone(), app).await.map_err(|e| { + warn!(target: LOG_TARGET, "Error setting up application: {:?}", e); + capture_anyhow(&e); + e.to_string() + })?; + + let res = state.config.read().await.auto_mining(); + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "setup_application took too long: {:?}", timer.elapsed()); + } + Ok(res) +} + +#[allow(clippy::too_many_lines)] +#[tauri::command] +pub async fn start_mining<'r>( + state: tauri::State<'_, UniverseAppState>, + app: tauri::AppHandle, +) -> Result<(), String> { + let timer = Instant::now(); + let _lock = state.stop_start_mutex.lock().await; + let config = state.config.read().await; + let cpu_mining_enabled = config.cpu_mining_enabled(); + let gpu_mining_enabled = config.gpu_mining_enabled(); + let mode = config.mode(); + let custom_cpu_usage = config.custom_cpu_usage(); + let custom_gpu_usage = config.custom_gpu_usage(); + + let cpu_miner_config = state.cpu_miner_config.read().await; + let tari_address = cpu_miner_config.tari_address.clone(); + let p2pool_enabled = config.p2pool_enabled(); + let monero_address = config.monero_address().to_string(); + let mut telemetry_id = state + .telemetry_manager + .read() + .await + .get_unique_string() + .await; + if cpu_mining_enabled { + let mm_proxy_port = state + .mm_proxy_manager + .get_monero_port() + .await + .map_err(|e| e.to_string())?; + + let res = state + .cpu_miner + .write() + .await + .start( + state.shutdown.to_signal(), + &cpu_miner_config, + monero_address.to_string(), + mm_proxy_port, + app.path_resolver() + .app_local_data_dir() + .expect("Could not get data dir"), + app.path_resolver() + .app_config_dir() + .expect("Could not get config dir"), + app.path_resolver() + .app_log_dir() + .expect("Could not get log dir"), + mode, + custom_cpu_usage, + ) + .await; + + if let Err(e) = res { + error!(target: LOG_TARGET, "Could not start mining: {:?}", e); + state + .cpu_miner + .write() + .await + .stop() + .await + .inspect_err(|e| error!("error at stopping cpu miner {:?}", e)) + .ok(); + return Err(e.to_string()); + } + } + + let gpu_available = state.gpu_miner.read().await.is_gpu_mining_available(); + info!(target: LOG_TARGET, "Gpu availability {:?} gpu_mining_enabled {}", gpu_available.clone(), gpu_mining_enabled); + + if gpu_mining_enabled && gpu_available { + info!(target: LOG_TARGET, "1. Starting gpu miner"); + // let tari_address = state.cpu_miner_config.read().await.tari_address.clone(); + // let p2pool_enabled = state.config.read().await.p2pool_enabled(); + let source = if p2pool_enabled { + let p2pool_port = state.p2pool_manager.grpc_port().await; + GpuNodeSource::P2Pool { port: p2pool_port } + } else { + let grpc_port = state + .node_manager + .get_grpc_port() + .await + .map_err(|e| e.to_string())?; + + GpuNodeSource::BaseNode { port: grpc_port } + }; + + info!(target: LOG_TARGET, "2 Starting gpu miner"); + + if telemetry_id.is_empty() { + telemetry_id = "tari-universe".to_string(); + } + + info!(target: LOG_TARGET, "3. Starting gpu miner"); + let res = state + .gpu_miner + .write() + .await + .start( + state.shutdown.to_signal(), + tari_address, + source, + app.path_resolver() + .app_local_data_dir() + .expect("Could not get data dir"), + app.path_resolver() + .app_config_dir() + .expect("Could not get config dir"), + app.path_resolver() + .app_log_dir() + .expect("Could not get log dir"), + mode, + telemetry_id, + custom_gpu_usage, + ) + .await; + + info!(target: LOG_TARGET, "4. Starting gpu miner"); + if let Err(e) = res { + error!(target: LOG_TARGET, "Could not start gpu mining: {:?}", e); + drop( + state.gpu_miner.write().await.stop().await.inspect_err( + |e| error!(target: LOG_TARGET, "Could not stop gpu miner: {:?}", e), + ), + ); + return Err(e.to_string()); + } + } + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "start_mining took too long: {:?}", timer.elapsed()); + } + Ok(()) +} + +#[tauri::command] +pub async fn stop_mining<'r>(state: tauri::State<'_, UniverseAppState>) -> Result<(), String> { + let _lock = state.stop_start_mutex.lock().await; + let timer = Instant::now(); + state + .cpu_miner + .write() + .await + .stop() + .await + .map_err(|e| e.to_string())?; + + state + .gpu_miner + .write() + .await + .stop() + .await + .map_err(|e| e.to_string())?; + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "stop_mining took too long: {:?}", timer.elapsed()); + } + Ok(()) +} + +#[tauri::command] +pub async fn update_applications( + app: tauri::AppHandle, + state: tauri::State<'_, UniverseAppState>, +) -> Result<(), String> { + let timer = Instant::now(); + let mut binary_resolver = BinaryResolver::current().write().await; + + state + .config + .write() + .await + .set_last_binaries_update_timestamp(SystemTime::now()) + .await + .inspect_err( + |e| error!(target: LOG_TARGET, "Could not set last binaries update timestamp: {:?}", e), + ) + .map_err(|e| e.to_string())?; + + let progress_tracker = ProgressTracker::new( + app.get_window("main") + .expect("Could not get main window") + .clone(), + ); + binary_resolver + .update_binary(Binaries::Xmrig, progress_tracker.clone()) + .await + .map_err(|e| e.to_string())?; + sleep(Duration::from_secs(1)); + binary_resolver + .update_binary(Binaries::MinotariNode, progress_tracker.clone()) + .await + .map_err(|e| e.to_string())?; + sleep(Duration::from_secs(1)); + binary_resolver + .update_binary(Binaries::MergeMiningProxy, progress_tracker.clone()) + .await + .map_err(|e| e.to_string())?; + sleep(Duration::from_secs(1)); + binary_resolver + .update_binary(Binaries::Wallet, progress_tracker.clone()) + .await + .map_err(|e| e.to_string())?; + binary_resolver + .update_binary(Binaries::ShaP2pool, progress_tracker.clone()) + .await + .map_err(|e| e.to_string())?; + sleep(Duration::from_secs(1)); + + if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { + warn!(target: LOG_TARGET, "update_applications took too long: {:?}", timer.elapsed()); + } + + drop(binary_resolver); + + Ok(()) +} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 8824a9d2f..f267ebff4 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1,53 +1,43 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] -use ::sentry::integrations::anyhow::capture_anyhow; use auto_launcher::AutoLauncher; -use external_dependencies::{ExternalDependencies, ExternalDependency, RequiredExternalDependency}; #[allow(unused_imports)] +use external_dependencies::RequiredExternalDependency; use hardware::hardware_status_monitor::{HardwareStatusMonitor, PublicDeviceProperties}; -use keyring::Entry; use log::trace; use log::{debug, error, info, warn}; -use monero_address_creator::Seed as MoneroSeed; use process_utils::set_interval; use log4rs::config::RawConfig; -use regex::Regex; use serde::Serialize; -use std::convert::TryFrom; -use std::fs::{read_dir, remove_dir_all, remove_file}; -use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::atomic::AtomicBool; use std::sync::Arc; -use std::thread::{available_parallelism, sleep}; -use std::time::{Duration, Instant, SystemTime}; +use std::thread::sleep; +use std::time::{Duration, SystemTime}; use tari_common::configuration::Network; use tari_common_types::tari_address::TariAddress; -use tari_core::transactions::tari_amount::MicroMinotari; use tari_shutdown::Shutdown; use tauri::async_runtime::{block_on, JoinHandle}; -use tauri::{Manager, RunEvent, UpdaterEvent, Window}; +use tauri::{Manager, RunEvent, UpdaterEvent}; use tokio::sync::{Mutex, RwLock}; -use tor_adapter::TorConfig; use utils::logging_utils::setup_logging; -use wallet_adapter::TransactionInfo; use app_config::{AppConfig, GpuThreads}; -use app_in_memory_config::{AirdropInMemoryConfig, AppInMemoryConfig}; +use app_in_memory_config::AppInMemoryConfig; use binaries::{binaries_list::Binaries, binaries_resolver::BinaryResolver}; -use gpu_miner_adapter::{GpuMinerStatus, GpuNodeSource}; +use gpu_miner_adapter::GpuMinerStatus; use node_manager::NodeManagerError; use progress_tracker::ProgressTracker; use setup_status_event::SetupStatusEvent; -use systemtray_manager::{SystemtrayManager, SystrayData}; +use systemtray_manager::SystemtrayManager; use telemetry_manager::TelemetryManager; -use wallet_manager::WalletManagerError; use crate::cpu_miner::CpuMiner; -use crate::credential_manager::{CredentialError, CredentialManager}; + use crate::feedback::Feedback; use crate::gpu_miner::GpuMiner; -use crate::internal_wallet::{InternalWallet, PaperWalletConfig}; +use crate::internal_wallet::InternalWallet; use crate::mm_proxy_manager::{MmProxyManager, StartConfig}; use crate::node_manager::NodeManager; use crate::p2pool::models::Stats; @@ -61,6 +51,7 @@ mod app_config; mod app_in_memory_config; mod auto_launcher; mod binaries; +mod commands; mod consts; mod cpu_miner; mod credential_manager; @@ -103,8 +94,6 @@ mod xmrig_adapter; const MAX_ACCEPTABLE_COMMAND_TIME: Duration = Duration::from_secs(1); const LOG_TARGET: &str = "tari::universe::main"; -const LOG_TARGET_WEB: &str = "tari::universe::web"; - #[cfg(not(any(feature = "release-ci", feature = "release-ci-beta")))] const APPLICATION_FOLDER_ID: &str = "com.tari.universe.alpha"; #[cfg(all(feature = "release-ci", feature = "release-ci-beta"))] @@ -172,492 +161,6 @@ async fn stop_all_miners(state: UniverseAppState, sleep_secs: u64) -> Result<(), Ok(()) } -#[tauri::command] -async fn set_mode( - mode: String, - custom_cpu_usage: Option, - custom_gpu_usage: Vec, - state: tauri::State<'_, UniverseAppState>, -) -> Result<(), String> { - let timer = Instant::now(); - info!(target: LOG_TARGET, "set_mode called with mode: {:?}, custom_max_cpu_usage: {:?}, custom_max_gpu_usage: {:?}", mode, custom_cpu_usage, custom_gpu_usage); - - state - .config - .write() - .await - .set_mode(mode, custom_cpu_usage, custom_gpu_usage) - .await - .inspect_err(|e| error!(target: LOG_TARGET, "error at set_mode {:?}", e)) - .map_err(|e| e.to_string())?; - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "set_mode took too long: {:?}", timer.elapsed()); - } - - Ok(()) -} - -#[tauri::command] -async fn get_max_consumption_levels( - state: tauri::State<'_, UniverseAppState>, -) -> Result { - // CPU Detection - let timer = Instant::now(); - let max_cpu_available = available_parallelism() - .map(|cores| i32::try_from(cores.get()).unwrap_or(1)) - .map_err(|e| e.to_string())?; - - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "get_available_cpu_cores took too long: {:?}", timer.elapsed()); - } - - let gpu_devices = state - .gpu_miner - .read() - .await - .get_gpu_devices() - .await - .map_err(|e| e.to_string())?; - - let mut max_gpus_threads = Vec::new(); - for gpu_device in gpu_devices { - // let max_gpu_threads = gpu_device.max_grid_size; - // For some reason this is always return 256, even when the cards can do more like - // 4096 or 8192 - let max_gpu_threads = 8192; - max_gpus_threads.push(GpuThreads { - gpu_name: gpu_device.device_name, - max_gpu_threads, - }); - } - - Ok(MaxUsageLevels { - max_cpu_threads: max_cpu_available, - max_gpus_threads, - }) -} - -#[tauri::command] -async fn set_display_mode( - display_mode: String, - state: tauri::State<'_, UniverseAppState>, -) -> Result<(), String> { - let timer = Instant::now(); - state - .config - .write() - .await - .set_display_mode(display_mode) - .await - .inspect_err(|e| error!(target: LOG_TARGET, "error at set_display_mode {:?}", e)) - .map_err(|e| e.to_string())?; - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "set_display_mode took too long: {:?}", timer.elapsed()); - } - - Ok(()) -} - -#[tauri::command] -async fn set_use_tor( - use_tor: bool, - state: tauri::State<'_, UniverseAppState>, -) -> Result<(), String> { - let timer = Instant::now(); - state - .config - .write() - .await - .set_use_tor(use_tor) - .await - .inspect_err(|e| error!(target: LOG_TARGET, "error at set_use_tor {:?}", e)) - .map_err(|e| e.to_string())?; - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "set_use_tor took too long: {:?}", timer.elapsed()); - } - - Ok(()) -} - -#[tauri::command] -async fn send_feedback( - feedback: String, - include_logs: bool, - _window: tauri::Window, - state: tauri::State<'_, UniverseAppState>, - app: tauri::AppHandle, -) -> Result { - let timer = Instant::now(); - let reference = state - .feedback - .read() - .await - .send_feedback( - feedback, - include_logs, - app.path_resolver().app_log_dir().clone(), - ) - .await - .inspect_err(|e| error!("error at send_feedback {:?}", e)) - .map_err(|e| e.to_string())?; - if timer.elapsed() > Duration::from_secs(60) { - warn!(target: LOG_TARGET, "send_feedback took too long: {:?}", timer.elapsed()); - } - Ok(reference) -} - -#[tauri::command] -async fn set_mine_on_app_start( - mine_on_app_start: bool, - state: tauri::State<'_, UniverseAppState>, -) -> Result<(), String> { - let timer = Instant::now(); - - state - .config - .write() - .await - .set_mine_on_app_start(mine_on_app_start) - .await - .inspect_err(|e| error!("error at set_mine_on_app_start {:?}", e)) - .map_err(|e| e.to_string())?; - - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "set_mine_on_app_start took too long: {:?}", timer.elapsed()); - } - - Ok(()) -} - -#[tauri::command] -async fn set_allow_telemetry( - allow_telemetry: bool, - _window: tauri::Window, - state: tauri::State<'_, UniverseAppState>, - _app: tauri::AppHandle, -) -> Result<(), String> { - state - .config - .write() - .await - .set_allow_telemetry(allow_telemetry) - .await - .inspect_err(|e| error!(target: LOG_TARGET, "error at set_allow_telemetry {:?}", e)) - .map_err(|e| e.to_string())?; - Ok(()) -} - -#[tauri::command] -async fn get_app_id( - _window: tauri::Window, - state: tauri::State<'_, UniverseAppState>, - _app: tauri::AppHandle, -) -> Result { - let timer = Instant::now(); - let app_id = state.config.read().await.anon_id().to_string(); - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "get_app_id took too long: {:?}", timer.elapsed()); - } - Ok(app_id) -} - -#[tauri::command] -async fn set_airdrop_access_token( - token: String, - _window: tauri::Window, - state: tauri::State<'_, UniverseAppState>, - _app: tauri::AppHandle, -) -> Result<(), String> { - let timer = Instant::now(); - let mut write_lock = state.airdrop_access_token.write().await; - *write_lock = Some(token.clone()); - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, - "set_airdrop_access_token took too long: {:?}", - timer.elapsed() - ); - } - let mut in_memory_app_config = state.in_memory_config.write().await; - in_memory_app_config.airdrop_access_token = Some(token); - Ok(()) -} - -#[tauri::command] -async fn get_tor_config( - _window: tauri::Window, - state: tauri::State<'_, UniverseAppState>, - _app: tauri::AppHandle, -) -> Result { - let timer = Instant::now(); - let tor_config = state.tor_manager.get_tor_config().await; - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "get_tor_config took too long: {:?}", timer.elapsed()); - } - Ok(tor_config) -} - -#[tauri::command] -async fn set_tor_config( - config: TorConfig, - _window: tauri::Window, - state: tauri::State<'_, UniverseAppState>, - _app: tauri::AppHandle, -) -> Result { - let timer = Instant::now(); - let tor_config = state - .tor_manager - .set_tor_config(config) - .await - .map_err(|e| e.to_string())?; - - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "set_tor_config took too long: {:?}", timer.elapsed()); - } - Ok(tor_config) -} - -#[tauri::command] -async fn get_app_in_memory_config( - _window: tauri::Window, - state: tauri::State<'_, UniverseAppState>, - _app: tauri::AppHandle, -) -> Result { - let timer = Instant::now(); - let res = state.in_memory_config.read().await.clone().into(); - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, - "get_app_in_memory_config took too long: {:?}", - timer.elapsed() - ); - } - Ok(res) -} - -#[tauri::command] -async fn set_monero_address( - monero_address: String, - state: tauri::State<'_, UniverseAppState>, -) -> Result<(), String> { - let timer = Instant::now(); - let mut app_config = state.config.write().await; - app_config - .set_monero_address(monero_address) - .await - .map_err(|e| e.to_string())?; - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "set_monero_address took too long: {:?}", timer.elapsed()); - } - Ok(()) -} - -#[tauri::command] -async fn set_auto_update( - auto_update: bool, - state: tauri::State<'_, UniverseAppState>, -) -> Result<(), String> { - let timer = Instant::now(); - state - .config - .write() - .await - .set_auto_update(auto_update) - .await - .inspect_err(|e| error!(target: LOG_TARGET, "error at set_auto_update {:?}", e)) - .map_err(|e| e.to_string())?; - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "set_auto_update took too long: {:?}", timer.elapsed()); - } - - Ok(()) -} - -#[tauri::command] -async fn set_monerod_config( - use_monero_fail: bool, - monero_nodes: Vec, - state: tauri::State<'_, UniverseAppState>, -) -> Result<(), String> { - let timer = Instant::now(); - state - .config - .write() - .await - .set_monerod_config(use_monero_fail, monero_nodes) - .await - .inspect_err(|e| error!(target: LOG_TARGET, "error at set_monerod_config {:?}", e)) - .map_err(|e| e.to_string())?; - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "set_monerod_config took too long: {:?}", timer.elapsed()); - } - - Ok(()) -} - -#[tauri::command] -async fn restart_application( - should_stop_miners: bool, - _window: tauri::Window, - state: tauri::State<'_, UniverseAppState>, - app: tauri::AppHandle, -) -> Result<(), String> { - if should_stop_miners { - stop_all_miners(state.inner().clone(), 5).await?; - } - - app.restart(); - Ok(()) -} - -#[tauri::command] -async fn exit_application( - _window: tauri::Window, - state: tauri::State<'_, UniverseAppState>, - app: tauri::AppHandle, -) -> Result<(), String> { - stop_all_miners(state.inner().clone(), 5).await?; - - app.exit(0); - Ok(()) -} - -#[tauri::command] -async fn set_should_always_use_system_language( - should_always_use_system_language: bool, - state: tauri::State<'_, UniverseAppState>, -) -> Result<(), String> { - state - .config - .write() - .await - .set_should_always_use_system_language(should_always_use_system_language) - .await - .map_err(|e| e.to_string())?; - Ok(()) -} - -#[tauri::command] -async fn set_application_language( - state: tauri::State<'_, UniverseAppState>, - application_language: String, -) -> Result<(), String> { - state - .config - .write() - .await - .set_application_language(application_language.clone()) - .await - .map_err(|e| e.to_string())?; - Ok(()) -} - -#[tauri::command] -async fn resolve_application_language( - state: tauri::State<'_, UniverseAppState>, -) -> Result { - let mut config = state.config.write().await; - let _unused = config.propose_system_language().await; - - Ok(config.application_language().to_string()) -} - -#[tauri::command] -async fn get_external_dependencies() -> Result { - let timer = Instant::now(); - let external_dependencies = ExternalDependencies::current() - .get_external_dependencies() - .await; - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, - "get_external_dependencies took too long: {:?}", - timer.elapsed() - ); - } - Ok(external_dependencies) -} - -#[tauri::command] -async fn download_and_start_installer( - _missing_dependency: ExternalDependency, -) -> Result<(), String> { - let timer = Instant::now(); - - #[cfg(target_os = "windows")] - if cfg!(target_os = "windows") { - ExternalDependencies::current() - .install_missing_dependencies(_missing_dependency) - .await - .map_err(|e| { - error!(target: LOG_TARGET, "Could not install missing dependency: {:?}", e); - e.to_string() - })?; - } - - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, - "download_and_start_installer took too long: {:?}", - timer.elapsed() - ); - } - Ok(()) -} - -#[tauri::command] -async fn set_should_auto_launch( - should_auto_launch: bool, - state: tauri::State<'_, UniverseAppState>, -) -> Result<(), String> { - match state - .config - .write() - .await - .set_should_auto_launch(should_auto_launch) - .await - { - Ok(_) => { - AutoLauncher::current() - .update_auto_launcher(should_auto_launch) - .await - .map_err(|e| { - error!(target: LOG_TARGET, "Error setting should_auto_launch: {:?}", e); - e.to_string() - })?; - } - Err(e) => { - error!(target: LOG_TARGET, "Error setting should_auto_launch: {:?}", e); - return Err(e.to_string()); - } - } - - Ok(()) -} - -#[tauri::command] -async fn setup_application( - window: tauri::Window, - state: tauri::State<'_, UniverseAppState>, - app: tauri::AppHandle, -) -> Result { - let timer = Instant::now(); - let rollback = state.setup_counter.write().await; - if rollback.get_value() { - warn!(target: LOG_TARGET, "setup_application has already been initialized, debouncing"); - let res = state.config.read().await.auto_mining(); - return Ok(res); - } - rollback.set_value(true, Duration::from_millis(1000)).await; - setup_inner(window, state.clone(), app).await.map_err(|e| { - warn!(target: LOG_TARGET, "Error setting up application: {:?}", e); - capture_anyhow(&e); - e.to_string() - })?; - - let res = state.config.read().await.auto_mining(); - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "setup_application took too long: {:?}", timer.elapsed()); - } - Ok(res) -} - #[allow(clippy::too_many_lines)] async fn setup_inner( window: tauri::Window, @@ -691,13 +194,13 @@ async fn setup_inner( #[cfg(target_os = "windows")] if cfg!(target_os = "windows") && !cfg!(dev) { - ExternalDependencies::current() + external_dependencies::ExternalDependencies::current() .read_registry_installed_applications() .await?; - let is_missing = ExternalDependencies::current() + let is_missing = external_dependencies::ExternalDependencies::current() .check_if_some_dependency_is_not_installed() .await; - let external_dependencies = ExternalDependencies::current() + let external_dependencies = external_dependencies::ExternalDependencies::current() .get_external_dependencies() .await; @@ -989,986 +492,22 @@ async fn setup_inner( Ok(()) } -#[tauri::command] -async fn set_p2pool_enabled( - p2pool_enabled: bool, - state: tauri::State<'_, UniverseAppState>, -) -> Result<(), String> { - let timer = Instant::now(); - state - .config - .write() - .await - .set_p2pool_enabled(p2pool_enabled) - .await - .inspect_err(|e| error!("error at set_p2pool_enabled {:?}", e)) - .map_err(|e| e.to_string())?; - - let origin_config = state.mm_proxy_manager.config().await; - let p2pool_grpc_port = state.p2pool_manager.grpc_port().await; - - match origin_config { - None => { - warn!(target: LOG_TARGET, "Tried to set p2pool_enabled but mmproxy has not been initialized yet"); - return Ok(()); - } - Some(mut origin_config) => { - if origin_config.p2pool_enabled != p2pool_enabled { - if p2pool_enabled { - origin_config.set_to_use_p2pool(p2pool_grpc_port); - } else { - let base_node_grpc_port = state - .node_manager - .get_grpc_port() - .await - .map_err(|error| error.to_string())?; - origin_config.set_to_use_base_node(base_node_grpc_port); - }; - state - .mm_proxy_manager - .change_config(origin_config) - .await - .map_err(|error| error.to_string())?; +async fn check_if_is_orphan_chain(app_handle: tauri::AppHandle) { + let state = app_handle.state::().inner(); + let check_if_orphan = state.node_manager.check_if_is_orphan_chain().await; + match check_if_orphan { + Ok(is_stuck) => { + if is_stuck { + error!(target: LOG_TARGET, "Miner is stuck on orphan chain"); } + drop(app_handle.emit_all("is_stuck", is_stuck)); + } + Err(e) => { + error!(target: LOG_TARGET, "{}", e); } - }; - - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "set_p2pool_enabled took too long: {:?}", timer.elapsed()); - } - Ok(()) -} - -#[tauri::command] -async fn set_cpu_mining_enabled<'r>( - enabled: bool, - state: tauri::State<'_, UniverseAppState>, -) -> Result<(), String> { - let timer = Instant::now(); - let mut config = state.config.write().await; - config - .set_cpu_mining_enabled(enabled) - .await - .inspect_err(|e| error!("error at set_cpu_mining_enabled {:?}", e)) - .map_err(|e| e.to_string())?; - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, - "set_cpu_mining_enabled took too long: {:?}", - timer.elapsed() - ); - } - Ok(()) -} - -#[tauri::command] -async fn set_visual_mode<'r>( - enabled: bool, - state: tauri::State<'_, UniverseAppState>, -) -> Result<(), String> { - let timer = Instant::now(); - let mut config = state.config.write().await; - config - .set_visual_mode(enabled) - .await - .inspect_err(|e| error!("error at set_visual_mode {:?}", e)) - .map_err(|e| e.to_string())?; - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, - "set_visual_mode took too long: {:?}", - timer.elapsed() - ); - } - Ok(()) -} - -#[tauri::command] -async fn set_gpu_mining_enabled( - enabled: bool, - state: tauri::State<'_, UniverseAppState>, -) -> Result<(), String> { - let timer = Instant::now(); - let mut config = state.config.write().await; - config - .set_gpu_mining_enabled(enabled) - .await - .inspect_err(|e| error!("error at set_gpu_mining_enabled {:?}", e)) - .map_err(|e| e.to_string())?; - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, - "set_gpu_mining_enabled took too long: {:?}", - timer.elapsed() - ); } - - Ok(()) } -#[tauri::command] -async fn import_seed_words( - seed_words: Vec, - _window: tauri::Window, - state: tauri::State<'_, UniverseAppState>, - app: tauri::AppHandle, -) -> Result<(), String> { - let timer = Instant::now(); - let config_path = app - .path_resolver() - .app_config_dir() - .expect("Could not get config dir"); - let data_dir = app - .path_resolver() - .app_local_data_dir() - .expect("Could not get data dir"); - - stop_all_miners(state.inner().clone(), 5).await?; - - tauri::async_runtime::spawn(async move { - match InternalWallet::create_from_seed(config_path, seed_words).await { - Ok(_wallet) => { - InternalWallet::clear_wallet_local_data(data_dir).await?; - info!(target: LOG_TARGET, "[import_seed_words] Restarting the app"); - app.restart(); - Ok(()) - } - Err(e) => { - error!(target: LOG_TARGET, "Error loading internal wallet: {:?}", e); - Err(e) - } - } - }); - - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "import_seed_words took too long: {:?}", timer.elapsed()); - } - Ok(()) -} - -#[tauri::command] -async fn set_excluded_gpu_devices( - excluded_gpu_devices: Vec, - state: tauri::State<'_, UniverseAppState>, -) -> Result<(), String> { - let mut gpu_miner = state.gpu_miner.write().await; - gpu_miner - .set_excluded_device(excluded_gpu_devices) - .await - .inspect_err(|e| error!("error at set_excluded_gpu_devices {:?}", e)) - .map_err(|e| e.to_string())?; - Ok(()) -} - -#[tauri::command] -async fn get_seed_words( - _window: tauri::Window, - _state: tauri::State<'_, UniverseAppState>, - app: tauri::AppHandle, -) -> Result, String> { - let timer = Instant::now(); - let config_path = app - .path_resolver() - .app_config_dir() - .expect("Could not get config dir"); - let internal_wallet = InternalWallet::load_or_create(config_path) - .await - .map_err(|e| e.to_string())?; - let seed_words = internal_wallet - .decrypt_seed_words() - .map_err(|e| e.to_string())?; - let mut res = vec![]; - for i in 0..seed_words.len() { - match seed_words.get_word(i) { - Ok(word) => res.push(word.clone()), - Err(error) => { - error!(target: LOG_TARGET, "Could not get seed word: {:?}", error); - } - } - } - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "get_seed_words took too long: {:?}", timer.elapsed()); - } - Ok(res) -} - -#[tauri::command] -async fn get_monero_seed_words( - state: tauri::State<'_, UniverseAppState>, - app: tauri::AppHandle, -) -> Result, String> { - let timer = Instant::now(); - - if !state.config.read().await.monero_address_is_generated() { - return Err( - "Monero seed words are not available when a Monero address is provided".to_string(), - ); - } - - let config_path = app - .path_resolver() - .app_config_dir() - .expect("Could not get config dir"); - - let cm = CredentialManager::default_with_dir(config_path); - let cred = match cm.get_credentials() { - Ok(cred) => cred, - Err(e @ CredentialError::PreviouslyUsedKeyring) => { - return Err(e.to_string()); - } - Err(e) => { - error!(target: LOG_TARGET, "Could not get credentials: {:?}", e); - return Err(e.to_string()); - } - }; - - let seed = cred - .monero_seed - .expect("Couldn't get seed from credentials"); - - let seed = MoneroSeed::new(seed); - - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "get_seed_words took too long: {:?}", timer.elapsed()); - } - - seed.seed_words().map_err(|e| e.to_string()) -} - -#[allow(clippy::too_many_lines)] -#[tauri::command] -async fn start_mining<'r>( - state: tauri::State<'_, UniverseAppState>, - app: tauri::AppHandle, -) -> Result<(), String> { - let timer = Instant::now(); - let _lock = state.stop_start_mutex.lock().await; - let config = state.config.read().await; - let cpu_mining_enabled = config.cpu_mining_enabled(); - let gpu_mining_enabled = config.gpu_mining_enabled(); - let mode = config.mode(); - let custom_cpu_usage = config.custom_cpu_usage(); - let custom_gpu_usage = config.custom_gpu_usage(); - - let cpu_miner_config = state.cpu_miner_config.read().await; - let tari_address = cpu_miner_config.tari_address.clone(); - let p2pool_enabled = config.p2pool_enabled(); - let monero_address = config.monero_address().to_string(); - let mut telemetry_id = state - .telemetry_manager - .read() - .await - .get_unique_string() - .await; - if cpu_mining_enabled { - let mm_proxy_port = state - .mm_proxy_manager - .get_monero_port() - .await - .map_err(|e| e.to_string())?; - - let res = state - .cpu_miner - .write() - .await - .start( - state.shutdown.to_signal(), - &cpu_miner_config, - monero_address.to_string(), - mm_proxy_port, - app.path_resolver() - .app_local_data_dir() - .expect("Could not get data dir"), - app.path_resolver() - .app_config_dir() - .expect("Could not get config dir"), - app.path_resolver() - .app_log_dir() - .expect("Could not get log dir"), - mode, - custom_cpu_usage, - ) - .await; - - if let Err(e) = res { - error!(target: LOG_TARGET, "Could not start mining: {:?}", e); - state - .cpu_miner - .write() - .await - .stop() - .await - .inspect_err(|e| error!("error at stopping cpu miner {:?}", e)) - .ok(); - return Err(e.to_string()); - } - } - - let gpu_available = state.gpu_miner.read().await.is_gpu_mining_available(); - info!(target: LOG_TARGET, "Gpu availability {:?} gpu_mining_enabled {}", gpu_available.clone(), gpu_mining_enabled); - - if gpu_mining_enabled && gpu_available { - info!(target: LOG_TARGET, "1. Starting gpu miner"); - // let tari_address = state.cpu_miner_config.read().await.tari_address.clone(); - // let p2pool_enabled = state.config.read().await.p2pool_enabled(); - let source = if p2pool_enabled { - let p2pool_port = state.p2pool_manager.grpc_port().await; - GpuNodeSource::P2Pool { port: p2pool_port } - } else { - let grpc_port = state - .node_manager - .get_grpc_port() - .await - .map_err(|e| e.to_string())?; - - GpuNodeSource::BaseNode { port: grpc_port } - }; - - info!(target: LOG_TARGET, "2 Starting gpu miner"); - - if telemetry_id.is_empty() { - telemetry_id = "tari-universe".to_string(); - } - - info!(target: LOG_TARGET, "3. Starting gpu miner"); - let res = state - .gpu_miner - .write() - .await - .start( - state.shutdown.to_signal(), - tari_address, - source, - app.path_resolver() - .app_local_data_dir() - .expect("Could not get data dir"), - app.path_resolver() - .app_config_dir() - .expect("Could not get config dir"), - app.path_resolver() - .app_log_dir() - .expect("Could not get log dir"), - mode, - telemetry_id, - custom_gpu_usage, - ) - .await; - - info!(target: LOG_TARGET, "4. Starting gpu miner"); - if let Err(e) = res { - error!(target: LOG_TARGET, "Could not start gpu mining: {:?}", e); - drop( - state.gpu_miner.write().await.stop().await.inspect_err( - |e| error!(target: LOG_TARGET, "Could not stop gpu miner: {:?}", e), - ), - ); - return Err(e.to_string()); - } - } - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "start_mining took too long: {:?}", timer.elapsed()); - } - Ok(()) -} - -#[tauri::command] -async fn stop_mining<'r>(state: tauri::State<'_, UniverseAppState>) -> Result<(), String> { - let _lock = state.stop_start_mutex.lock().await; - let timer = Instant::now(); - state - .cpu_miner - .write() - .await - .stop() - .await - .map_err(|e| e.to_string())?; - - state - .gpu_miner - .write() - .await - .stop() - .await - .map_err(|e| e.to_string())?; - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "stop_mining took too long: {:?}", timer.elapsed()); - } - Ok(()) -} - -#[tauri::command] -async fn fetch_tor_bridges() -> Result, String> { - let timer = Instant::now(); - let res_html = reqwest::get("https://bridges.torproject.org/bridges?transport=obfs4") - .await - .map_err(|e| e.to_string())? - .text() - .await - .map_err(|e| e.to_string())?; - - let re = Regex::new(r"obfs4.*?
").map_err(|e| e.to_string())?; - let bridges: Vec = re - .find_iter(&res_html) - .map(|m| m.as_str().trim_end_matches("
").to_string()) - .collect(); - info!(target: LOG_TARGET, "Fetched default bridges: {:?}", bridges); - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "fetch_default_tor_bridges took too long: {:?}", timer.elapsed()); - } - Ok(bridges) -} - -#[tauri::command] -fn open_log_dir(app: tauri::AppHandle) { - let log_dir = app - .path_resolver() - .app_log_dir() - .expect("Could not get log dir"); - if let Err(e) = open::that(log_dir) { - error!(target: LOG_TARGET, "Could not open log dir: {:?}", e); - } -} - -#[tauri::command] -async fn get_applications_versions(app: tauri::AppHandle) -> Result { - let timer = Instant::now(); - let binary_resolver = BinaryResolver::current().read().await; - - let tari_universe_version = app.package_info().version.clone(); - let xmrig_version = binary_resolver - .get_binary_version_string(Binaries::Xmrig) - .await; - - let minotari_node_version = binary_resolver - .get_binary_version_string(Binaries::MinotariNode) - .await; - let mm_proxy_version = binary_resolver - .get_binary_version_string(Binaries::MergeMiningProxy) - .await; - let wallet_version = binary_resolver - .get_binary_version_string(Binaries::Wallet) - .await; - let sha_p2pool_version = binary_resolver - .get_binary_version_string(Binaries::ShaP2pool) - .await; - let xtrgpuminer_version = binary_resolver - .get_binary_version_string(Binaries::GpuMiner) - .await; - - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, - "get_applications_versions took too long: {:?}", - timer.elapsed() - ); - } - - drop(binary_resolver); - - Ok(ApplicationsVersions { - tari_universe: tari_universe_version.to_string(), - minotari_node: minotari_node_version, - xmrig: xmrig_version, - mm_proxy: mm_proxy_version, - wallet: wallet_version, - sha_p2pool: sha_p2pool_version, - xtrgpuminer: xtrgpuminer_version, - }) -} - -#[tauri::command] -async fn update_applications( - app: tauri::AppHandle, - state: tauri::State<'_, UniverseAppState>, -) -> Result<(), String> { - let timer = Instant::now(); - let mut binary_resolver = BinaryResolver::current().write().await; - - state - .config - .write() - .await - .set_last_binaries_update_timestamp(SystemTime::now()) - .await - .inspect_err( - |e| error!(target: LOG_TARGET, "Could not set last binaries update timestamp: {:?}", e), - ) - .map_err(|e| e.to_string())?; - - let progress_tracker = ProgressTracker::new( - app.get_window("main") - .expect("Could not get main window") - .clone(), - ); - binary_resolver - .update_binary(Binaries::Xmrig, progress_tracker.clone()) - .await - .map_err(|e| e.to_string())?; - sleep(Duration::from_secs(1)); - binary_resolver - .update_binary(Binaries::MinotariNode, progress_tracker.clone()) - .await - .map_err(|e| e.to_string())?; - sleep(Duration::from_secs(1)); - binary_resolver - .update_binary(Binaries::MergeMiningProxy, progress_tracker.clone()) - .await - .map_err(|e| e.to_string())?; - sleep(Duration::from_secs(1)); - binary_resolver - .update_binary(Binaries::Wallet, progress_tracker.clone()) - .await - .map_err(|e| e.to_string())?; - binary_resolver - .update_binary(Binaries::ShaP2pool, progress_tracker.clone()) - .await - .map_err(|e| e.to_string())?; - sleep(Duration::from_secs(1)); - - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "update_applications took too long: {:?}", timer.elapsed()); - } - - drop(binary_resolver); - - Ok(()) -} - -#[tauri::command] -async fn get_p2pool_stats( - state: tauri::State<'_, UniverseAppState>, -) -> Result, String> { - let timer = Instant::now(); - if state.is_getting_p2pool_stats.load(Ordering::SeqCst) { - let read = state.cached_p2pool_stats.read().await; - if let Some(stats) = &*read { - warn!(target: LOG_TARGET, "Already getting p2pool stats, returning cached value"); - return Ok(stats.clone()); - } - warn!(target: LOG_TARGET, "Already getting p2pool stats"); - return Err("Already getting p2pool stats".to_string()); - } - state.is_getting_p2pool_stats.store(true, Ordering::SeqCst); - let p2pool_stats = match state.p2pool_manager.get_stats().await { - Ok(s) => s, - Err(e) => { - warn!(target: LOG_TARGET, "Error getting p2pool stats: {}", e); - None - } - }; - - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "get_p2pool_stats took too long: {:?}", timer.elapsed()); - } - let mut lock = state.cached_p2pool_stats.write().await; - *lock = Some(p2pool_stats.clone()); - state.is_getting_p2pool_stats.store(false, Ordering::SeqCst); - Ok(p2pool_stats) -} - -#[tauri::command] -async fn get_transaction_history( - state: tauri::State<'_, UniverseAppState>, -) -> Result, String> { - let timer = Instant::now(); - if state.is_getting_transaction_history.load(Ordering::SeqCst) { - warn!(target: LOG_TARGET, "Already getting transaction history"); - return Err("Already getting transaction history".to_string()); - } - state - .is_getting_transaction_history - .store(true, Ordering::SeqCst); - let transactions = match state.wallet_manager.get_transaction_history().await { - Ok(t) => t, - Err(e) => { - if !matches!(e, WalletManagerError::WalletNotStarted) { - warn!(target: LOG_TARGET, "Error getting transaction history: {}", e); - } - vec![] - } - }; - - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "get_transaction_history took too long: {:?}", timer.elapsed()); - } - - state - .is_getting_transaction_history - .store(false, Ordering::SeqCst); - Ok(transactions) -} - -#[tauri::command] -async fn get_tari_wallet_details( - state: tauri::State<'_, UniverseAppState>, -) -> Result { - let timer = Instant::now(); - if state.is_getting_wallet_balance.load(Ordering::SeqCst) { - let read = state.cached_wallet_details.read().await; - if let Some(details) = &*read { - warn!(target: LOG_TARGET, "Already getting wallet balance, returning cached value"); - return Ok(details.clone()); - } - warn!(target: LOG_TARGET, "Already getting wallet balance"); - return Err("Already getting wallet balance".to_string()); - } - state - .is_getting_wallet_balance - .store(true, Ordering::SeqCst); - let wallet_balance = match state.wallet_manager.get_balance().await { - Ok(w) => Some(w), - Err(e) => { - if !matches!(e, WalletManagerError::WalletNotStarted) { - warn!(target: LOG_TARGET, "Error getting wallet balance: {}", e); - } - - None - } - }; - let tari_address = state.tari_address.read().await; - - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "get_tari_wallet_details took too long: {:?}", timer.elapsed()); - } - let result = TariWalletDetails { - wallet_balance, - tari_address_base58: tari_address.to_base58(), - tari_address_emoji: tari_address.to_emoji_string(), - }; - let mut lock = state.cached_wallet_details.write().await; - *lock = Some(result.clone()); - state - .is_getting_wallet_balance - .store(false, Ordering::SeqCst); - - Ok(result) -} - -#[tauri::command] -async fn get_paper_wallet_details(app: tauri::AppHandle) -> Result { - let timer = Instant::now(); - let config_path = app - .path_resolver() - .app_config_dir() - .expect("Could not get config dir"); - let internal_wallet = InternalWallet::load_or_create(config_path) - .await - .map_err(|e| e.to_string())?; - let result = internal_wallet - .get_paper_wallet_details() - .await - .map_err(|e| e.to_string())?; - - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "get_paper_wallet_details took too long: {:?}", timer.elapsed()); - } - Ok(result) -} -#[tauri::command] -async fn get_app_config( - _window: tauri::Window, - state: tauri::State<'_, UniverseAppState>, - _app: tauri::AppHandle, -) -> Result { - Ok(state.config.read().await.clone()) -} - -async fn check_if_is_orphan_chain(app_handle: tauri::AppHandle) { - let state = app_handle.state::().inner(); - let check_if_orphan = state.node_manager.check_if_is_orphan_chain().await; - match check_if_orphan { - Ok(is_stuck) => { - if is_stuck { - error!(target: LOG_TARGET, "Miner is stuck on orphan chain"); - } - drop(app_handle.emit_all("is_stuck", is_stuck)); - } - Err(e) => { - error!(target: LOG_TARGET, "{}", e); - } - } -} - -#[allow(clippy::too_many_lines)] -#[tauri::command] -async fn get_tor_entry_guards( - state: tauri::State<'_, UniverseAppState>, -) -> Result, String> { - let timer = Instant::now(); - let res = state - .tor_manager - .get_entry_guards() - .await - .map_err(|e| e.to_string())?; - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "get_tor_entry_guards took too long: {:?}", timer.elapsed()); - } - Ok(res) -} - -#[allow(clippy::too_many_lines)] -#[tauri::command] -async fn get_miner_metrics( - state: tauri::State<'_, UniverseAppState>, - app: tauri::AppHandle, -) -> Result { - let timer = Instant::now(); - if state.is_getting_miner_metrics.load(Ordering::SeqCst) { - let read = state.cached_miner_metrics.read().await; - if let Some(metrics) = &*read { - warn!(target: LOG_TARGET, "Already getting miner metrics, returning cached value"); - return Ok(metrics.clone()); - } - warn!(target: LOG_TARGET, "Already getting miner metrics"); - return Err("Already getting miner metrics".to_string()); - } - state.is_getting_miner_metrics.store(true, Ordering::SeqCst); - - // info!(target: LOG_TARGET, "1 elapsed {:?}", timer.elapsed()); - let (sha_hash_rate, randomx_hash_rate, block_reward, block_height, block_time, is_synced) = - state - .node_manager - .get_network_hash_rate_and_block_reward() - .await - .unwrap_or_else(|e| { - if !matches!(e, NodeManagerError::NodeNotStarted) { - warn!(target: LOG_TARGET, "Error getting network hash rate and block reward: {}", e); - } - (0, 0, MicroMinotari(0), 0, 0, false) - }); - // info!(target: LOG_TARGET, "2 elapsed {:?}", timer.elapsed()); - - let cpu_miner = state.cpu_miner.read().await; - let cpu_mining_status = match cpu_miner - .status(randomx_hash_rate, block_reward) - .await - .map_err(|e| e.to_string()) - { - Ok(cpu) => cpu, - Err(e) => { - warn!(target: LOG_TARGET, "Error getting cpu miner status: {:?}", e); - state - .is_getting_miner_metrics - .store(false, Ordering::SeqCst); - return Err(e); - } - }; - drop(cpu_miner); - - // info!(target: LOG_TARGET, "3 elapsed {:?}", timer.elapsed()); - - let gpu_miner = state.gpu_miner.read().await; - let gpu_mining_status = match gpu_miner.status(sha_hash_rate, block_reward).await { - Ok(gpu) => gpu, - Err(e) => { - warn!(target: LOG_TARGET, "Error getting gpu miner status: {:?}", e); - state - .is_getting_miner_metrics - .store(false, Ordering::SeqCst); - return Err(e.to_string()); - } - }; - drop(gpu_miner); - - // let config_path = app - // .path_resolver() - // .app_config_dir() - // .expect("Could not get config dir"); - // let _unused = HardwareMonitor::current() - // .write() - // .await - // .load_status_file(config_path); - // let hardware_status = HardwareMonitor::current() - // .write() - // .await - // .read_hardware_parameters(); - - // info!(target: LOG_TARGET, "4 elapsed {:?}", timer.elapsed()); - let gpu_public_parameters = HardwareStatusMonitor::current() - .get_gpu_devices_public_properties() - .await - .map_err(|e| e.to_string())?; - // .map_err(|e| e.to_string())?; - // info!(target: LOG_TARGET, "5 elapsed {:?}", timer.elapsed()); - // let cpu_public_parameters = HardwareStatusMonitor::current() - // .get_cpu_public_properties() - // .await - // .map_err(|e| e.to_string())?; - - // info!(target: LOG_TARGET, "6 elapsed {:?}", timer.elapsed()); - - let new_systemtray_data: SystrayData = SystemtrayManager::current().create_systemtray_data( - cpu_mining_status.hash_rate, - gpu_mining_status.hash_rate as f64, - // gpu_public_parameters.clone(), - // cpu_public_parameters.clone(), - (cpu_mining_status.estimated_earnings + gpu_mining_status.estimated_earnings) as f64, - ); - - // info!(target: LOG_TARGET, "7 elapsed {:?}", timer.elapsed()); - SystemtrayManager::current().update_systray(app, new_systemtray_data); - - // info!(target: LOG_TARGET, "8 elapsed {:?}", timer.elapsed()); - let connected_peers = state - .node_manager - .list_connected_peers() - .await - .unwrap_or_default(); - - if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { - warn!(target: LOG_TARGET, "get_miner_metrics took too long: {:?}", timer.elapsed()); - } - - let ret = MinerMetrics { - sha_network_hash_rate: sha_hash_rate, - randomx_network_hash_rate: randomx_hash_rate, - cpu: CpuMinerMetrics { - // hardware: cpu_public_parameters.clone(), - mining: cpu_mining_status, - }, - gpu: GpuMinerMetrics { - hardware: gpu_public_parameters.clone(), - mining: gpu_mining_status, - }, - base_node: BaseNodeStatus { - block_height, - block_time, - is_synced, - is_connected: !connected_peers.is_empty(), - connected_peers, - }, - }; - let mut lock = state.cached_miner_metrics.write().await; - *lock = Some(ret.clone()); - state - .is_getting_miner_metrics - .store(false, Ordering::SeqCst); - - Ok(ret) -} - -#[tauri::command] -fn log_web_message(level: String, message: Vec) { - let joined_message = message.join(" "); - match level.as_str() { - "error" => { - error!(target: LOG_TARGET_WEB, "{}", joined_message) - } - _ => info!(target: LOG_TARGET_WEB, "{}", joined_message), - } -} - -#[tauri::command] -async fn reset_settings<'r>( - reset_wallet: bool, - _window: tauri::Window, - state: tauri::State<'_, UniverseAppState>, - app: tauri::AppHandle, -) -> Result<(), String> { - stop_all_miners(state.inner().clone(), 5).await?; - let network = Network::get_current_or_user_setting_or_default().as_key_str(); - - let app_config_dir = app.path_resolver().app_config_dir(); - let app_cache_dir = app.path_resolver().app_cache_dir(); - let app_data_dir = app.path_resolver().app_data_dir(); - let app_local_data_dir = app.path_resolver().app_local_data_dir(); - - let dirs_to_remove = [ - app_config_dir, - app_cache_dir, - app_data_dir, - app_local_data_dir, - ]; - let valid_dir_paths: Vec = dirs_to_remove - .iter() - .filter_map(|dir| { - if let Some(path) = dir { - path.to_str().map(|s| s.to_string()) - } else { - None - } - }) - .collect(); - - if valid_dir_paths.is_empty() { - error!(target: LOG_TARGET, "Could not get app directories for {:?}", valid_dir_paths); - return Err("Could not get app directories".to_string()); - } - // Exclude EBWebView because it is still being used. - let folder_block_list = ["EBWebView"]; - - for dir_path in dirs_to_remove.iter().flatten() { - if dir_path.exists() { - for entry in read_dir(dir_path).map_err(|e| e.to_string())? { - let entry = entry.map_err(|e| e.to_string())?; - let path = entry.path(); - if path.is_dir() { - if let Some(file_name) = path.file_name().and_then(|name| name.to_str()) { - if folder_block_list.contains(&file_name) { - debug!(target: LOG_TARGET, "[reset_settings] Skipping {:?} directory", path); - continue; - } - } - - let contains_wallet_config = - read_dir(&path) - .map_err(|e| e.to_string())? - .any(|inner_entry| { - inner_entry - .map(|e| e.file_name() == "wallet_config.json") - .unwrap_or(false) - }); - - let is_network_dir = path - .file_name() - .and_then(|name| name.to_str()) - .map(|name| name == network) - .unwrap_or(false); - - if !reset_wallet && contains_wallet_config { - debug!(target: LOG_TARGET, "[reset_settings] Skipping {:?} directory because it contains wallet_config.json and reset_wallet is false", path); - continue; - } - if reset_wallet && contains_wallet_config && !is_network_dir { - debug!(target: LOG_TARGET, "[reset_settings] Skipping {:?} directory because it contains wallet_config.json and does not matches network name", path); - continue; - } - - debug!(target: LOG_TARGET, "[reset_settings] Removing {:?} directory", path); - remove_dir_all(path.clone()).map_err(|e| { - error!(target: LOG_TARGET, "[reset_settings] Could not remove {:?} directory: {:?}", path, e); - format!("Could not remove directory: {}", e) - })?; - } else { - debug!(target: LOG_TARGET, "[reset_settings] Removing {:?} file", path); - remove_file(path.clone()).map_err(|e| { - error!(target: LOG_TARGET, "[reset_settings] Could not remove {:?} file: {:?}", path, e); - format!("Could not remove file: {}", e) - })?; - } - } - } - } - - debug!(target: LOG_TARGET, "[reset_settings] Removing keychain items"); - if let Ok(entry) = Entry::new(APPLICATION_FOLDER_ID, "inner_wallet_credentials") { - let _unused = entry.delete_credential(); - } - - info!(target: LOG_TARGET, "[reset_settings] Restarting the app"); - app.restart(); - - Ok(()) -} -#[tauri::command] -async fn close_splashscreen(window: Window) { - window - .get_window("splashscreen") - .expect("no window labeled 'splashscreen' found") - .close() - .expect("could not close"); - window - .get_window("main") - .expect("no window labeled 'main' found") - .show() - .expect("could not show"); -} #[derive(Debug, Serialize, Clone)] pub struct CpuMinerMetrics { // hardware: Vec, @@ -2277,54 +816,53 @@ fn main() { } }) .invoke_handler(tauri::generate_handler![ - close_splashscreen, - download_and_start_installer, - exit_application, - fetch_tor_bridges, - get_app_config, - get_app_id, - get_app_in_memory_config, - get_applications_versions, - get_external_dependencies, - get_max_consumption_levels, - get_miner_metrics, - get_p2pool_stats, - get_paper_wallet_details, - get_seed_words, - get_tari_wallet_details, - get_tor_config, - get_tor_entry_guards, - get_transaction_history, - import_seed_words, - log_web_message, - open_log_dir, - reset_settings, - resolve_application_language, - restart_application, - send_feedback, - set_airdrop_access_token, - set_allow_telemetry, - set_application_language, - set_auto_update, - set_cpu_mining_enabled, - set_display_mode, - set_excluded_gpu_devices, - set_gpu_mining_enabled, - set_mine_on_app_start, - set_mode, - set_monero_address, - set_monerod_config, - set_p2pool_enabled, - set_should_always_use_system_language, - set_should_auto_launch, - set_tor_config, - set_use_tor, - set_visual_mode, - setup_application, - start_mining, - stop_mining, - update_applications, - get_monero_seed_words + commands::close_splashscreen, + commands::download_and_start_installer, + commands::exit_application, + commands::fetch_tor_bridges, + commands::get_app_config, + commands::get_app_in_memory_config, + commands::get_applications_versions, + commands::get_external_dependencies, + commands::get_max_consumption_levels, + commands::get_miner_metrics, + commands::get_monero_seed_words, + commands::get_p2pool_stats, + commands::get_paper_wallet_details, + commands::get_seed_words, + commands::get_tari_wallet_details, + commands::get_tor_config, + commands::get_tor_entry_guards, + commands::get_transaction_history, + commands::import_seed_words, + commands::log_web_message, + commands::open_log_dir, + commands::reset_settings, + commands::resolve_application_language, + commands::restart_application, + commands::send_feedback, + commands::set_airdrop_access_token, + commands::set_allow_telemetry, + commands::set_application_language, + commands::set_auto_update, + commands::set_cpu_mining_enabled, + commands::set_display_mode, + commands::set_excluded_gpu_devices, + commands::set_gpu_mining_enabled, + commands::set_mine_on_app_start, + commands::set_mode, + commands::set_monero_address, + commands::set_monerod_config, + commands::set_p2pool_enabled, + commands::set_should_always_use_system_language, + commands::set_should_auto_launch, + commands::set_tor_config, + commands::set_use_tor, + commands::set_visual_mode, + commands::setup_application, + commands::start_mining, + commands::stop_mining, + commands::update_applications, ]) .build(tauri::generate_context!()) .inspect_err( From 4c71ee8cee02e3e941b6a13073b463826e054950 Mon Sep 17 00:00:00 2001 From: Shannon Tenner Date: Fri, 29 Nov 2024 12:09:35 +0200 Subject: [PATCH 02/34] [rebase] upgrade to Tauri V2 - wip: update dir resolvers - wip: move Systray logic to FE - wip: updated beta build workflows - wip: emit miner metrics - ci: updated workflows - merge: reolve conflicts --- .github/workflows/ci.yml | 197 +- .github/workflows/lint.yml | 32 +- .github/workflows/pr.yml | 83 + .github/workflows/pr_signed_commits_check.yml | 19 - .github/workflows/pr_title.yml | 28 - .github/workflows/release.yml | 114 +- .prettierrc | 12 +- ci/build-notes.md | 19 +- package-lock.json | 792 +++-- package.json | 8 +- public/locales/af/common.json | 2 + public/locales/af/mining-view.json | 3 + public/locales/cn/common.json | 2 + public/locales/de/common.json | 2 + public/locales/en/common.json | 2 + public/locales/fr/common.json | 2 + public/locales/hi/common.json | 2 + public/locales/id/common.json | 2 + public/locales/ja/common.json | 2 + public/locales/ko/common.json | 2 + public/locales/pl/common.json | 2 + public/locales/ru/common.json | 2 + public/locales/tr/common.json | 2 + public/splash.html | 2 +- src-tauri/Cargo.lock | 2967 +++++++++-------- src-tauri/Cargo.toml | 51 +- src-tauri/capabilities/default.json | 17 + src-tauri/capabilities/desktop.json | 11 + src-tauri/capabilities/migrated.json | 13 + src-tauri/src/binaries/adapter_github.rs | 3 +- src-tauri/src/binaries/adapter_tor.rs | 4 +- src-tauri/src/binaries/adapter_xmrig.rs | 3 +- src-tauri/src/commands.rs | 1425 ++++++++ .../src/hardware/hardware_status_monitor.rs | 20 +- src-tauri/src/main.rs | 1773 +--------- src-tauri/src/process_adapter.rs | 2 +- src-tauri/src/progress_tracker.rs | 13 +- src-tauri/src/systemtray_manager.rs | 389 --- src-tauri/src/telemetry_manager.rs | 1 + src-tauri/src/user_listener.rs | 1 + src-tauri/src/utils/shutdown_utils.rs | 7 +- src-tauri/src/xmrig_adapter.rs | 1 + src-tauri/tauri.conf.json | 127 +- src/App/App.tsx | 19 +- src/App/AppWrapper.tsx | 17 +- src/components/dialogs/RestartDialog.tsx | 2 +- src/components/dialogs/SendLogsDialog.tsx | 2 +- .../AutoUpdateDialog/AutoUpdateDialog.tsx | 16 +- .../CriticalErrorDialog.tsx | 4 +- .../ExternalDependenciesDialog.tsx | 2 +- .../ExternalDependencyCard.tsx | 2 +- .../ConnectSection/ConnectSection.tsx | 2 +- .../Settings/components/Navigation.tsx | 2 +- .../sections/airdrop/ApplyInviteCode.tsx | 2 +- .../sections/experimental/AppVersions.tsx | 3 +- .../experimental/TorMarkup/TorDebug.tsx | 2 +- .../experimental/TorMarkup/TorMarkup.tsx | 9 +- .../sections/general/LogsSettings.tsx | 26 +- .../sections/general/ResetSettingsButton.tsx | 3 +- .../MoneroAddressEditor.tsx | 2 +- .../MoneroSeedWordSettings.tsx | 2 +- .../wallet/SeedWordsMarkup/useGetSeedWords.ts | 2 +- .../sections/wallet/WalletAddressMarkup.tsx | 2 +- .../AirdropGiftTracker/AirdropGiftTracker.tsx | 12 +- .../segments/Flare/BonusGems/BonusGems.tsx | 5 +- .../sections/LoggedOut/LoggedOut.tsx | 2 +- src/containers/main/MainView.tsx | 4 +- src/containers/main/SideBar/Miner/Miner.tsx | 18 +- .../main/SideBar/components/Wallet/Wallet.tsx | 27 +- src/containers/phase/Setup/Setup.tsx | 2 +- src/hooks/app/index.ts | 9 + src/hooks/{ => app}/useDisableRefresh.ts | 4 +- src/hooks/{ => app}/useEnvironment.ts | 4 +- src/hooks/{ => app}/useHardwareStats.ts | 6 +- src/hooks/{ => app}/useLanguageResolver.ts | 2 +- .../useListenForExternalDependencies.ts | 0 src/hooks/{ => app}/useSetUp.ts | 10 +- src/hooks/{ => app}/useShuttingDown.ts | 12 +- src/hooks/app/useSystemTray.ts | 56 + src/hooks/app/useUpdateStatus.ts | 90 + src/hooks/helpers/index.ts | 4 + src/hooks/{ => helpers}/useInterval.ts | 0 src/hooks/index.ts | 3 + src/hooks/mining/index.ts | 6 + src/hooks/mining/useBlockInfo.ts | 8 +- src/hooks/mining/useEarningsRecap.ts | 12 +- .../{ => mining}/useMiningMetricsUpdater.ts | 48 +- src/hooks/mining/useMiningStatesSync.ts | 34 +- src/hooks/mining/useTransactions.ts | 2 +- src/hooks/useUpdateStatus.ts | 138 - src/hooks/useVersions.ts | 0 src/store/appStateStore.ts | 2 +- src/store/useAirdropStore.ts | 2 +- src/store/useAppConfigStore.ts | 2 +- src/store/useBlockchainVisualisationStore.ts | 3 +- src/store/useMiningStore.ts | 2 +- src/store/useP2poolStatsStore.ts | 2 +- src/store/useWalletStore.ts | 2 +- src/types/invoke.ts | 2 +- src/utils/index.ts | 6 + src/utils/shared-logger.ts | 6 +- src/utils/systray.ts | 73 + 102 files changed, 4450 insertions(+), 4452 deletions(-) create mode 100644 .github/workflows/pr.yml delete mode 100644 .github/workflows/pr_signed_commits_check.yml delete mode 100644 .github/workflows/pr_title.yml create mode 100644 src-tauri/capabilities/default.json create mode 100644 src-tauri/capabilities/desktop.json create mode 100644 src-tauri/capabilities/migrated.json create mode 100644 src-tauri/src/commands.rs delete mode 100644 src-tauri/src/systemtray_manager.rs create mode 100644 src/hooks/app/index.ts rename src/hooks/{ => app}/useDisableRefresh.ts (95%) rename src/hooks/{ => app}/useEnvironment.ts (82%) rename src/hooks/{ => app}/useHardwareStats.ts (94%) rename src/hooks/{ => app}/useLanguageResolver.ts (85%) rename src/hooks/{ => app}/useListenForExternalDependencies.ts (100%) rename src/hooks/{ => app}/useSetUp.ts (92%) rename src/hooks/{ => app}/useShuttingDown.ts (61%) create mode 100644 src/hooks/app/useSystemTray.ts create mode 100644 src/hooks/app/useUpdateStatus.ts create mode 100644 src/hooks/helpers/index.ts rename src/hooks/{ => helpers}/useInterval.ts (100%) create mode 100644 src/hooks/index.ts create mode 100644 src/hooks/mining/index.ts rename src/hooks/{ => mining}/useMiningMetricsUpdater.ts (65%) delete mode 100644 src/hooks/useUpdateStatus.ts delete mode 100644 src/hooks/useVersions.ts create mode 100644 src/utils/index.ts create mode 100644 src/utils/systray.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1b4142030..7fbb00609 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ name: CI workflow_dispatch: push: branches: - - "ci-*" + - 'ci-*' pull_request: types: - opened @@ -21,37 +21,35 @@ concurrency: permissions: {} jobs: - clippy: - name: clippy - runs-on: [ ubuntu-latest ] + cargo-checks: + name: cargo checks (fmt, clippy, check) + runs-on: ubuntu-latest steps: - - name: checkout - uses: actions/checkout@v4 - - - name: created empty dist dir + - uses: actions/checkout@v4 + - name: create empty dist dir run: | mkdir dist - - name: install dependencies (linux) - if: startsWith(runner.os,'Linux') run: | sudo apt-get update sudo apt-get install --no-install-recommends --assume-yes \ - libwebkit2gtk-4.0-dev \ + libwebkit2gtk-4.1-dev \ libappindicator3-dev \ librsvg2-dev \ patchelf \ libprotobuf-dev \ protobuf-compiler - - name: toolchain - uses: dtolnay/rust-toolchain@stable + - name: install dependencies (linux/OpenCL) + run: | + sudo apt-get install --no-install-recommends --assume-yes \ + opencl-headers \ + ocl-icd-opencl-dev + + - uses: dtolnay/rust-toolchain@stable with: components: clippy, rustfmt - - - name: cache cargo files and outputs - if: ${{ ( startsWith(runner.environment,'github-hosted') ) && ( ! startsWith(github.ref, 'refs/tags/v') ) }} - uses: swatinem/rust-cache@v2 + - uses: swatinem/rust-cache@v2.7.5 with: workspaces: './src-tauri -> target' @@ -60,7 +58,7 @@ jobs: run: | cargo fmt --all -- --check - - name: clippy check (with lints) + - name: clippy lint working-directory: ./src-tauri env: AIRDROP_BASE_URL: http://localhost:4000 @@ -69,22 +67,18 @@ jobs: run: | cargo install cargo-lints cargo lints clippy --all-targets --all-features + - name: cargo check + working-directory: ./src-tauri + run: | + cargo check --release --all-targets --workspace machete: name: machete - runs-on: [ ubuntu-latest ] + runs-on: ubuntu-latest steps: - - name: checkout - uses: actions/checkout@v4 - - - name: toolchain - uses: dtolnay/rust-toolchain@stable - with: - components: clippy, rustfmt - - - name: cache cargo files and outputs - if: ${{ ( startsWith(runner.environment,'github-hosted') ) && ( ! startsWith(github.ref, 'refs/tags/v') ) }} - uses: swatinem/rust-cache@v2 + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: swatinem/rust-cache@v2.7.5 with: workspaces: './src-tauri -> target' @@ -94,46 +88,52 @@ jobs: cargo install cargo-machete cargo machete - cargo-check: - name: cargo-check - runs-on: [ ubuntu-latest ] + tauri-test-build: + strategy: + fail-fast: true + name: tauri-build + runs-on: ubuntu-latest steps: - - name: checkout - uses: actions/checkout@v4 - + - uses: actions/checkout@v4 - name: install dependencies (linux) - if: startsWith(runner.os,'Linux') run: | sudo apt-get update sudo apt-get install --no-install-recommends --assume-yes \ - libwebkit2gtk-4.0-dev \ + libwebkit2gtk-4.1-dev \ libappindicator3-dev \ librsvg2-dev \ patchelf \ libprotobuf-dev \ protobuf-compiler - - name: toolchain - uses: dtolnay/rust-toolchain@stable - with: - components: clippy, rustfmt + - name: install dependencies (linux/OpenCL) + run: | + sudo apt-get install --no-install-recommends --assume-yes \ + opencl-headers \ + ocl-icd-opencl-dev - - name: cache cargo files and outputs - if: ${{ ( startsWith(runner.environment,'github-hosted') ) && ( ! startsWith(github.ref, 'refs/tags/v') ) }} - uses: swatinem/rust-cache@v2 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + cache: 'npm' + - name: Install dependencies (node) + run: npm ci + - uses: dtolnay/rust-toolchain@stable + - uses: swatinem/rust-cache@v2.7.5 with: workspaces: './src-tauri -> target' - - - name: cargo check + - name: cargo tauri build working-directory: ./src-tauri run: | - cargo check --release --all-targets --workspace --locked + cargo install tauri-cli --version "^2" --locked + cargo tauri --version + cargo tauri build --ci --bundles deb file-licenses: # disable for now if: ${{ false }} name: file-licenses - runs-on: [ ubuntu-latest ] + runs-on: ubuntu-latest steps: - name: checkout uses: actions/checkout@v4 @@ -145,102 +145,3 @@ jobs: rg --version || exit 1 - name: run the license check run: ./scripts/file_license_check.sh - - i18n-checks: - name: i18n-checks - runs-on: [ ubuntu-latest ] - steps: - - name: checkout - uses: actions/checkout@v4 - - - name: install jsonlint - run: | - sudo apt-get update - sudo apt-get install --no-install-recommends --assume-yes \ - python3-demjson - - - name: basic jsonlint - run: | - find public -iname '*.json' -print0 | \ - xargs -0 -n1 jsonlint -v - - - name: setup folder for logs - run: | - mkdir -p ${{ runner.temp }}/i18n_logs - - - name: i18n compare - continue-on-error: true - working-directory: ./public/locales - run: | - python3 ../../scripts/i18n_checker.py \ - compare --en-locale-path en \ - --base-path . \ - --search-path .. \ - --output-dir ${{ runner.temp }}/i18n_logs - - - name: i18n unused - continue-on-error: true - working-directory: ./public/locales - run: | - python3 ../../scripts/i18n_checker.py \ - unused --en-locale-path en \ - --base-path . \ - --search-path .. \ - --output-dir ${{ runner.temp }}/i18n_logs - - - name: Artifact upload for i18n checks - uses: actions/upload-artifact@v4 - with: - name: i18n-logs - path: ${{ runner.temp }}/i18n_logs - - tauri-build: - name: tauri-build - runs-on: [ ubuntu-latest ] - steps: - - name: checkout - uses: actions/checkout@v4 - - - name: install dependencies (linux) - run: | - sudo apt-get update - sudo apt-get install --no-install-recommends --assume-yes \ - libwebkit2gtk-4.0-dev \ - libappindicator3-dev \ - librsvg2-dev \ - patchelf \ - libprotobuf-dev \ - protobuf-compiler - - - name: install dependencies (linux/OpenCL) - run: | - sudo apt-get install --no-install-recommends --assume-yes \ - opencl-headers \ - ocl-icd-opencl-dev - - - name: Node.js setup - uses: actions/setup-node@v4 - with: - node-version: lts/* - cache: 'npm' - - - name: Install dependencies (node) - run: | - npm --version - npm install - - - name: toolchain - uses: dtolnay/rust-toolchain@stable - - - name: cache cargo files and outputs - if: ${{ ( startsWith(runner.environment,'github-hosted') ) && ( ! startsWith(github.ref, 'refs/tags/v') ) }} - uses: swatinem/rust-cache@v2 - with: - workspaces: './src-tauri -> target' - - - name: cargo tauri build - working-directory: ./src-tauri - run: | - cargo install tauri-cli --version "1.6.4" - cargo tauri --version - cargo tauri build --ci --bundles deb diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ece92cf77..0bdff66c1 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -2,20 +2,18 @@ name: Lint on: pull_request jobs: - run-linters: - name: Run linters - runs-on: ubuntu-latest - - steps: - - name: Check out Git repository - uses: actions/checkout@v4 - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: lts/* - - name: Install Node.js dependencies - run: npm ci - - name: check lint/prettier errors - run: npm run lint - - name: check taplo - run: npm run lint:taplo \ No newline at end of file + run-linters: + name: Run linters + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + cache: 'npm' + node-version: lts/* + - name: Install Node.js dependencies + run: npm ci + - name: check lint/prettier errors + run: npm run lint + - name: check taplo + run: npm run lint:taplo diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 000000000..c55755291 --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,83 @@ +--- +name: PR +on: + pull_request: + types: + - opened + - reopened + - edited + - synchronize + +concurrency: + group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}' + cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/v') || github.ref != 'refs/heads/development' || github.ref != 'refs/heads/nextnet' || github.ref != 'refs/heads/stagenet' }} + +permissions: {} + +jobs: + check-signed-commits: + name: Check signed commits + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + steps: + - uses: 1Password/check-signed-commits-action@v1 + check-title: + name: Check title + runs-on: ubuntu-latest + steps: + - name: Install Dependencies + run: | + npm install -g @commitlint/cli @commitlint/config-conventional + echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js + - name: Lint Title + env: + PR_TITLE: ${{github.event.pull_request.title}} + run: | + echo "$PR_TITLE" | commitlint + check-i18n: + name: Check i18n + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install jsonlint + run: | + sudo apt-get update + sudo apt-get install --no-install-recommends --assume-yes \ + python3-demjson + + - name: Basic jsonlint + run: | + find public -iname '*.json' -print0 | \ + xargs -0 -n1 jsonlint -v + + - name: setup folder for logs + run: | + mkdir -p ${{ runner.temp }}/i18n_logs + + - name: i18n compare + continue-on-error: true + working-directory: ./public/locales + run: | + python3 ../../scripts/i18n_checker.py \ + compare --en-locale-path en \ + --base-path . \ + --search-path .. \ + --output-dir ${{ runner.temp }}/i18n_logs + + - name: i18n unused + continue-on-error: true + working-directory: ./public/locales + run: | + python3 ../../scripts/i18n_checker.py \ + unused --en-locale-path en \ + --base-path . \ + --search-path .. \ + --output-dir ${{ runner.temp }}/i18n_logs + + - name: Artifact upload for i18n checks + uses: actions/upload-artifact@v4 + with: + name: i18n-logs + path: ${{ runner.temp }}/i18n_logs diff --git a/.github/workflows/pr_signed_commits_check.yml b/.github/workflows/pr_signed_commits_check.yml deleted file mode 100644 index 2024a9fb3..000000000 --- a/.github/workflows/pr_signed_commits_check.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- -# Checks if the comments are signed or not -name: PR - Signed commits check - -'on': - pull_request_target - -permissions: {} - -jobs: - check-signed-commits: - name: Check signed commits in PR - runs-on: ubuntu-latest - permissions: - contents: read - pull-requests: write - steps: - - name: Check signed commits in PR - uses: 1Password/check-signed-commits-action@v1 diff --git a/.github/workflows/pr_title.yml b/.github/workflows/pr_title.yml deleted file mode 100644 index 23c0688ed..000000000 --- a/.github/workflows/pr_title.yml +++ /dev/null @@ -1,28 +0,0 @@ ---- -# Checks that PR titles conform to Conventional Commits -# See https://www.conventionalcommits.org/en/v1.0.0/ for more information -name: PR - -'on': - pull_request: - types: - - opened - - reopened - - edited - - synchronize - -permissions: {} - -jobs: - check-title: - runs-on: ubuntu-latest - steps: - - name: install - run: | - npm install -g @commitlint/cli @commitlint/config-conventional - echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js - - name: lint - env: - PR_TITLE: ${{github.event.pull_request.title}} - run: | - echo "$PR_TITLE" | commitlint diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9ec5a27ae..f142b1ce1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,25 +1,22 @@ --- name: Release -'on': +on: push: paths-ignore: - '**/*.md' - # tags: - # - 'v[0-9]+.[0-9]+.[0-9]+' branches: - 'release' - 'beta' - 'build-*' schedule: - - cron: "05 00 * * *" + - cron: '05 00 * * *' workflow_dispatch: concurrency: # https://docs.github.com/en/actions/examples/using-concurrency-expressions-and-a-test-matrix group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}' cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/v') || github.ref != 'refs/heads/main' || github.ref != 'refs/heads/release' }} - permissions: {} env: @@ -34,33 +31,29 @@ jobs: fail-fast: false matrix: include: - - platform: 'ubuntu-20.04' + - platform: 'ubuntu-22.04' + args: '' + - platform: 'windows-latest' args: '' - - platform: 'windows-2019' - args: '--bundles msi,updater' - platform: 'macos-latest' args: '--target universal-apple-darwin' - runs-on: ${{ matrix.platform }} steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: beta builds - Install dependencies (windows) [yq] + - uses: actions/checkout@v4 + - name: BETA Builds - Install dependencies (windows) [yq] if: ${{ startsWith(runner.os,'Windows') }} run: | choco upgrade yq -y - - - name: beta builds - Install dependencies (linux) [yq] + - name: BETA Builds - Install dependencies (linux) [yq] if: ${{ startsWith(runner.os,'Linux') }} shell: bash run: | sudo bash ./scripts/check-get-yq.sh - - name: Set environment variables for beta builds + - name: BETA Builds - Set environment variables if: ${{ ( github.event_name == 'schedule' ) || ( ! startsWith(github.ref, 'refs/heads/release') ) }} env: - BETA_STRING: "(Beta)" + BETA_STRING: '(Beta)' AIRDROP_BASE_URL: ${{ secrets.BETA_AIRDROP_BASE_URL }} AIRDROP_API_BASE_URL: ${{ secrets.BETA_AIRDROP_API_BASE_URL }} AIRDROP_TWITTER_AUTH_URL: ${{ secrets.BETA_AIRDROP_TWITTER_AUTH_URL }} @@ -73,25 +66,20 @@ jobs: echo "AIRDROP_API_BASE_URL=${{ env.AIRDROP_API_BASE_URL }}" >> $GITHUB_ENV echo "AIRDROP_TWITTER_AUTH_URL=${{ env.AIRDROP_TWITTER_AUTH_URL }}" >> $GITHUB_ENV echo "TS_FEATURES=release-ci-beta, airdrop-env" >> $GITHUB_ENV - #export BETA_DATE=$(date +%Y-%m-%d) # numeric-only and cannot be greater than 65535 for msi target - export BETA_DATE=4$(date +%m%d) + export BETA_DATE=$(date +%m%d) cd "${GITHUB_WORKSPACE}/src-tauri" - echo "releaseName=Tari Universe ${{ env.BETA_STRING }} v__VERSION__-${BETA_DATE}" >> $GITHUB_ENV + echo "releaseName=Tari Universe ${{ env.BETA_STRING }} v__VERSION__.${BETA_DATE}" >> $GITHUB_ENV # Don't mess with the double quotes and inner escaped quotes - yq eval ".package.productName = \"Tari Universe ${{ env.BETA_STRING }}\"" -i tauri.conf.json - yq eval ".package.version += \"-${BETA_DATE}\"" -i tauri.conf.json - yq eval ".tauri.windows[0].title = \"Tari Universe ${{ env.BETA_STRING }} | Testnet\"" -i tauri.conf.json - yq eval ".tauri.bundle.identifier = \"com.tari.universe.beta\"" -i tauri.conf.json - yq eval ".tauri.updater.endpoints = [\"https://raw.githubusercontent.com/tari-project/universe/main/.updater/beta-latest.json\"]" \ + yq eval ".productName = \"Tari Universe ${{ env.BETA_STRING }}\"" -i tauri.conf.json + yq eval ".mainBinaryName = \"Tari Universe ${{ env.BETA_STRING }}\"" -i tauri.conf.json + yq eval ".app.windows[0].title = \"Tari Universe ${{ env.BETA_STRING }} | Testnet\"" -i tauri.conf.json + yq eval ".identifier = \"com.tari.universe.beta\"" -i tauri.conf.json + yq eval ".plugins.updater.endpoints = [\"https://raw.githubusercontent.com/tari-project/universe/main/.updater/beta-latest.json\"]" \ -i tauri.conf.json cat tauri.conf.json - sed -i.bak -E "s/^version\s*=\s*\"([0-9]+\.[0-9]+\.[0-9]+)\"/version = \"\1-${BETA_DATE}\"/" \ - Cargo.toml - cat Cargo.toml sed -i.bak -e "s/\"icons\//\"beta-icons\//g" tauri.conf.json - - - name: Set environment variables for RELEASE builds + - name: RELEASE Builds - Set environment variables if: ${{ startsWith(github.ref, 'refs/heads/release') }} shell: bash run: | @@ -104,59 +92,49 @@ jobs: echo "TARI_TARGET_NETWORK=nextnet" >> $GITHUB_ENV cd "${GITHUB_WORKSPACE}/src-tauri" # Don't mess with the double quotes and inner escaped quotes - yq eval ".package.productName = \"Tari Universe\"" -i tauri.conf.json - yq eval ".tauri.windows[0].title = \"Tari Universe | Testnet\"" -i tauri.conf.json - yq eval ".tauri.bundle.identifier = \"com.tari.universe\"" -i tauri.conf.json - yq eval ".tauri.updater.endpoints = [\"https://raw.githubusercontent.com/tari-project/universe/main/.updater/latest.json\"]" \ + yq eval ".productName = \"Tari Universe\"" -i tauri.conf.json + yq eval ".mainBinaryName = \"Tari Universe\"" -i tauri.conf.json + yq eval ".app.windows[0].title = \"Tari Universe | Testnet\"" -i tauri.conf.json + yq eval ".identifier = \"com.tari.universe\"" -i tauri.conf.json + yq eval ".plugins.updater.endpoints = [\"https://raw.githubusercontent.com/tari-project/universe/main/.updater/latest.json\"]" \ -i tauri.conf.json - - name: Node.js setup - uses: actions/setup-node@v4 + - uses: actions/setup-node@v4 with: node-version: lts/* cache: 'npm' - - name: Rust setup (linux) - if: startsWith(runner.os,'Linux') - uses: dtolnay/rust-toolchain@stable - env: - RUSTUP_PERMIT_COPY_RENAME: true - with: - toolchain: stable - target: aarch64-unknown-linux-gnu - - - name: Rust setup (macOS) - if: startsWith(runner.os,'macOS') + - name: Rust Setup uses: dtolnay/rust-toolchain@stable with: - target: aarch64-apple-darwin,x86_64-apple-darwin + targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }} - - name: Cache cargo files and outputs + - name: Cache Cargo files and outputs if: ${{ ( ! startsWith(github.ref, 'refs/heads/release') ) && ( ! startsWith(github.ref, 'refs/tags/v') ) }} uses: swatinem/rust-cache@v2 with: workspaces: './src-tauri -> target' - - name: Install dependencies (linux) + - name: Install Dependencies - Linux if: startsWith(runner.os,'Linux') run: | sudo apt-get update sudo apt-get install --no-install-recommends --assume-yes \ - libwebkit2gtk-4.0-dev \ + libwebkit2gtk-4.1-dev \ libappindicator3-dev \ librsvg2-dev \ patchelf \ libprotobuf-dev \ protobuf-compiler - - name: Install dependencies (linux/OpenCL) + - name: Install Dependencies - Linux/OpenCL if: startsWith(runner.os,'Linux') run: | sudo apt-get install --no-install-recommends --assume-yes \ opencl-headers \ ocl-icd-opencl-dev - - name: Install dependencies (macOS) + - name: Install Dependencies - macOS if: startsWith(runner.os,'macOS') run: | # openssl, cmake and autoconf already installed @@ -168,25 +146,25 @@ jobs: rustup toolchain install stable-x86_64-apple-darwin --force-non-host rustup toolchain install stable-aarch64-apple-darwin --force-non-host - - name: Install dependencies (windows) + - name: Install Dependencies - Windows if: startsWith(runner.os,'Windows') run: | vcpkg.exe install sqlite3:x64-windows zlib:x64-windows choco upgrade protoc -y - - name: Install dependencies (windows/OpenCL) + - name: Install Dependencies - Windows/OpenCL if: startsWith(runner.os,'Windows') run: | vcpkg.exe --triplet=x64-windows install opencl - - name: Set environment variables (windows) + - name: Set environment variables - Windows if: startsWith(runner.os,'Windows') shell: bash run: | echo "SQLITE3_LIB_DIR=C:\vcpkg\installed\x64-windows\lib" >> $GITHUB_ENV echo "LIB=C:\vcpkg\installed\x64-windows\lib" >> $GITHUB_ENV - - name: Azure code-signing setup (windows only) + - name: Azure Code-signing Setup - Windows Only if: ${{ ( startsWith(runner.os,'Windows') ) && ( env.AZURE_TENANT_ID != '' ) }} shell: bash env: @@ -195,17 +173,17 @@ jobs: run: | cd "${GITHUB_WORKSPACE}/src-tauri" echo "{}" | \ - jq '.tauri .bundle .windows += {"signCommand": "${{ env.WINDOWS_SIGN_COMMAND }}"}' > \ + jq '.bundle .windows += {"signCommand": "${{ env.WINDOWS_SIGN_COMMAND }}"}' > \ ./tauri.windows.conf.json cat ./tauri.windows.conf.json cargo install trusted-signing-cli@0.3.0 --locked - - name: Install dependencies (node) + - name: Install Dependencies - Node run: | npm --version - npm install + npm ci - - name: Build Tauri apps + - name: Build Tauri Apps id: build uses: tauri-apps/tauri-action@v0.5.15 env: @@ -220,30 +198,30 @@ jobs: AZURE_TENANT_ID: ${{ startsWith(runner.os,'Windows') && secrets.AZURE_TENANT_ID }} AZURE_CLIENT_ID: ${{ startsWith(runner.os,'Windows') && secrets.AZURE_CLIENT_ID }} AZURE_CLIENT_SECRET: ${{ startsWith(runner.os,'Windows') && secrets.AZURE_CLIENT_SECRET }} - TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} NODE_OPTIONS: '--max_old_space_size=4096' with: tagName: ${{ env.tagName }} releaseName: ${{ env.releaseName }} releaseBody: 'Tari Universe - See the assets to download this version and install' - # releaseId: ${{ env.releaseId }} releaseDraft: true prerelease: true includeDebug: false includeRelease: true args: ${{ matrix.args }} --features "${{ env.TS_FEATURES }}" - - name: Debug step {artifactPaths} - if: ${{ false }} + - name: Debug Step - artifactPaths + if: ${{ ( github.event_name == 'schedule' ) || ( ! startsWith(github.ref, 'refs/heads/release') ) }} continue-on-error: true env: artifactPaths: ${{ steps.build.outputs.artifactPaths }} shell: bash - run: echo "Artifact ID from previous job is $artifactPaths" + run: | + echo "Artifact paths:\n ${{ join(fromJSON(steps.build.outputs.artifactPaths), '\n') }}" - - name: Upload none releases + - name: BETA Builds - Upload assets if: ${{ ( github.event_name == 'schedule' ) || ( ! startsWith(github.ref, 'refs/heads/release') ) }} uses: actions/upload-artifact@v4 with: diff --git a/.prettierrc b/.prettierrc index 8934690e3..1564a3fb2 100644 --- a/.prettierrc +++ b/.prettierrc @@ -5,5 +5,13 @@ "singleQuote": true, "bracketSpacing": true, "printWidth": 120, - "endOfLine": "auto" -} \ No newline at end of file + "endOfLine": "auto", + "overrides": [ + { + "files": "*.yml", + "options": { + "tabWidth": 2 + } + } + ] +} diff --git a/ci/build-notes.md b/ci/build-notes.md index c3cc4cab2..3e2ef690d 100644 --- a/ci/build-notes.md +++ b/ci/build-notes.md @@ -1,6 +1,7 @@ # Build notes # Cross-OS compile on Apple M(x) for Linux ARM64, using docker + ```bash git clone git@github.com:tari-project/universe.git cd universe @@ -18,6 +19,7 @@ docker run -it --rm \ ``` # Install some basic utils + ```bash apt-get update apt-get install --no-install-recommends --assume-yes \ @@ -29,11 +31,13 @@ apt-get install --no-install-recommends --assume-yes \ ``` # Install compile tools + ```bash apt-get install --assume-yes build-essential ``` # Install tauri dependancies + ```bash apt-get install --no-install-recommends --assume-yes \ libwebkit2gtk-4.0-dev \ @@ -45,6 +49,7 @@ apt-get install --no-install-recommends --assume-yes \ ``` # Needed for randomx-rs build + ```bash apt-get install --assume-yes \ git \ @@ -54,6 +59,7 @@ apt-get install --assume-yes \ ``` # Needed for openssl library + ```bash apt-get install --assume-yes \ openssl \ @@ -62,24 +68,29 @@ apt-get install --assume-yes \ ``` # Install rust + ```bash curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y ``` # Get rust to work in current shell + ```bash export PATH="$HOME/.cargo/bin:$PATH" source "$HOME/.cargo/env" ``` # Check rust install + ```bash rustup target list --installed rustup toolchain list ``` # Install nodejs from nodeSource -# more info can be found at https://github.com/nodesource/distributions + +# more info can be found at https://github.com/nodesource/distributions + ```bash mkdir -p ~/temp/ curl -fsSL https://deb.nodesource.com/setup_22.x -o ~/temp/nodesource_setup.sh @@ -91,21 +102,25 @@ npm --version ``` # Install node modules + ```bash npm install ``` # Build node assets + ```bash npm run build ``` # Install tauri-cli + ```bash -cargo install tauri-cli@1.6.4 +cargo install tauri-cli@latest ``` # Build application + ```bash cargo tauri build ``` diff --git a/package-lock.json b/package-lock.json index 1b9961305..fb2ff3b64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,11 @@ "@floating-ui/react": "^0.26.28", "@lottiefiles/dotlottie-react": "^0.10.1", "@sentry/react": "^8.41.0", - "@tauri-apps/api": "^1", + "@tauri-apps/api": "^2.1.1", + "@tauri-apps/plugin-os": "^2.0.0", + "@tauri-apps/plugin-process": "^2.0.0", + "@tauri-apps/plugin-shell": "^2.0.1", + "@tauri-apps/plugin-updater": "^2.0.0", "emoji-regex": "^10.4.0", "framer-motion": "^11.12.0", "globals": "^15.12.0", @@ -35,7 +39,7 @@ "@nabla/vite-plugin-eslint": "^2.0.5", "@sentry/vite-plugin": "^2.22.6", "@taplo/cli": "^0.7.0", - "@tauri-apps/cli": "^1.6.3", + "@tauri-apps/cli": "^2.1.0", "@types/eslint__js": "^8.42.3", "@types/node": "^22.10.1", "@types/react": "^18.3.12", @@ -127,15 +131,6 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/generator": { "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", @@ -154,12 +149,12 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", "dev": true, "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -295,12 +290,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", - "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -342,9 +337,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", - "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", + "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -796,16 +791,19 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } @@ -944,6 +942,7 @@ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "levn": "^0.4.1" }, @@ -960,9 +959,9 @@ } }, "node_modules/@floating-ui/dom": { - "version": "1.6.11", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.11.tgz", - "integrity": "sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==", + "version": "1.6.12", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.12.tgz", + "integrity": "sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w==", "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.8" @@ -1247,9 +1246,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", - "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.4.tgz", + "integrity": "sha512-jfUJrFct/hTA0XDM5p/htWKoNNTbDLY0KRwEt6pyOA6k2fmk0WVwl65PdUdJZgzGEHWx+49LilkcSaumQRyNQw==", "cpu": [ "arm" ], @@ -1260,9 +1259,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", - "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.4.tgz", + "integrity": "sha512-j4nrEO6nHU1nZUuCfRKoCcvh7PIywQPUCBa2UsootTHvTHIoIu2BzueInGJhhvQO/2FTRdNYpf63xsgEqH9IhA==", "cpu": [ "arm64" ], @@ -1273,9 +1272,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", - "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.4.tgz", + "integrity": "sha512-GmU/QgGtBTeraKyldC7cDVVvAJEOr3dFLKneez/n7BvX57UdhOqDsVwzU7UOnYA7AAOt+Xb26lk79PldDHgMIQ==", "cpu": [ "arm64" ], @@ -1286,9 +1285,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", - "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.4.tgz", + "integrity": "sha512-N6oDBiZCBKlwYcsEPXGDE4g9RoxZLK6vT98M8111cW7VsVJFpNEqvJeIPfsCzbf0XEakPslh72X0gnlMi4Ddgg==", "cpu": [ "x64" ], @@ -1298,10 +1297,36 @@ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.4.tgz", + "integrity": "sha512-py5oNShCCjCyjWXCZNrRGRpjWsF0ic8f4ieBNra5buQz0O/U6mMXCpC1LvrHuhJsNPgRt36tSYMidGzZiJF6mw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.4.tgz", + "integrity": "sha512-L7VVVW9FCnTTp4i7KrmHeDsDvjB4++KOBENYtNYAiYl96jeBThFfhP6HVxL74v4SiZEVDH/1ILscR5U9S4ms4g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", - "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.4.tgz", + "integrity": "sha512-10ICosOwYChROdQoQo589N5idQIisxjaFE/PAnX2i0Zr84mY0k9zul1ArH0rnJ/fpgiqfu13TFZR5A5YJLOYZA==", "cpu": [ "arm" ], @@ -1312,9 +1337,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", - "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.4.tgz", + "integrity": "sha512-ySAfWs69LYC7QhRDZNKqNhz2UKN8LDfbKSMAEtoEI0jitwfAG2iZwVqGACJT+kfYvvz3/JgsLlcBP+WWoKCLcw==", "cpu": [ "arm" ], @@ -1325,9 +1350,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", - "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.4.tgz", + "integrity": "sha512-uHYJ0HNOI6pGEeZ/5mgm5arNVTI0nLlmrbdph+pGXpC9tFHFDQmDMOEqkmUObRfosJqpU8RliYoGz06qSdtcjg==", "cpu": [ "arm64" ], @@ -1338,9 +1363,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", - "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.4.tgz", + "integrity": "sha512-38yiWLemQf7aLHDgTg85fh3hW9stJ0Muk7+s6tIkSUOMmi4Xbv5pH/5Bofnsb6spIwD5FJiR+jg71f0CH5OzoA==", "cpu": [ "arm64" ], @@ -1351,9 +1376,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", - "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.4.tgz", + "integrity": "sha512-q73XUPnkwt9ZNF2xRS4fvneSuaHw2BXuV5rI4cw0fWYVIWIBeDZX7c7FWhFQPNTnE24172K30I+dViWRVD9TwA==", "cpu": [ "ppc64" ], @@ -1364,9 +1389,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", - "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.4.tgz", + "integrity": "sha512-Aie/TbmQi6UXokJqDZdmTJuZBCU3QBDA8oTKRGtd4ABi/nHgXICulfg1KI6n9/koDsiDbvHAiQO3YAUNa/7BCw==", "cpu": [ "riscv64" ], @@ -1377,9 +1402,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", - "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.4.tgz", + "integrity": "sha512-P8MPErVO/y8ohWSP9JY7lLQ8+YMHfTI4bAdtCi3pC2hTeqFJco2jYspzOzTUB8hwUWIIu1xwOrJE11nP+0JFAQ==", "cpu": [ "s390x" ], @@ -1390,9 +1415,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", - "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.4.tgz", + "integrity": "sha512-K03TljaaoPK5FOyNMZAAEmhlyO49LaE4qCsr0lYHUKyb6QacTNF9pnfPpXnFlFD3TXuFbFbz7tJ51FujUXkXYA==", "cpu": [ "x64" ], @@ -1403,9 +1428,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", - "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.4.tgz", + "integrity": "sha512-VJYl4xSl/wqG2D5xTYncVWW+26ICV4wubwN9Gs5NrqhJtayikwCXzPL8GDsLnaLU3WwhQ8W02IinYSFJfyo34Q==", "cpu": [ "x64" ], @@ -1416,9 +1441,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", - "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.4.tgz", + "integrity": "sha512-ku2GvtPwQfCqoPFIJCqZ8o7bJcj+Y54cZSr43hHca6jLwAiCbZdBUOrqE6y29QFajNAzzpIOwsckaTFmN6/8TA==", "cpu": [ "arm64" ], @@ -1429,9 +1454,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", - "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.4.tgz", + "integrity": "sha512-V3nCe+eTt/W6UYNr/wGvO1fLpHUrnlirlypZfKCT1fG6hWfqhPgQV/K/mRBXBpxc0eKLIF18pIOFVPh0mqHjlg==", "cpu": [ "ia32" ], @@ -1442,9 +1467,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", - "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.4.tgz", + "integrity": "sha512-LTw1Dfd0mBIEqUVCxbvTE/LLo+9ZxVC9k99v1v4ahg9Aak6FpqOfNu5kRkeTAn0wphoC4JU7No1/rL+bBCEwhg==", "cpu": [ "x64" ], @@ -1553,43 +1578,10 @@ "node": ">= 14" } }, - "node_modules/@sentry/bundler-plugin-core/node_modules/glob": { - "version": "9.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", - "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "minimatch": "^8.0.2", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@sentry/bundler-plugin-core/node_modules/minimatch": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", - "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@sentry/cli": { - "version": "2.38.0", - "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.38.0.tgz", - "integrity": "sha512-ld9+1GdPkDaFr6T4SGocxoMcrBB/K6Z37TvBx8IMrDQC+eJDkBFiyqmHnzrj/8xoj5O220pqjPZCfvqzH268sQ==", + "version": "2.38.2", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.38.2.tgz", + "integrity": "sha512-CR0oujpAnhegK2pBAv6ZReMqbFTuNJLDZLvoD1B+syrKZX+R+oxkgT2e1htsBbht+wGxAsluVWsIAydSws1GAA==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -1606,19 +1598,19 @@ "node": ">= 10" }, "optionalDependencies": { - "@sentry/cli-darwin": "2.38.0", - "@sentry/cli-linux-arm": "2.38.0", - "@sentry/cli-linux-arm64": "2.38.0", - "@sentry/cli-linux-i686": "2.38.0", - "@sentry/cli-linux-x64": "2.38.0", - "@sentry/cli-win32-i686": "2.38.0", - "@sentry/cli-win32-x64": "2.38.0" + "@sentry/cli-darwin": "2.38.2", + "@sentry/cli-linux-arm": "2.38.2", + "@sentry/cli-linux-arm64": "2.38.2", + "@sentry/cli-linux-i686": "2.38.2", + "@sentry/cli-linux-x64": "2.38.2", + "@sentry/cli-win32-i686": "2.38.2", + "@sentry/cli-win32-x64": "2.38.2" } }, "node_modules/@sentry/cli-darwin": { - "version": "2.38.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.38.0.tgz", - "integrity": "sha512-OvOaV9Vg4+b9ObK2z1oFj3zbRoqOSpD/wSz9t/mtSWwMQi7wlUXj88XGGsL5ZwF7VGBYL+kX59X3Ygl+dHFPlg==", + "version": "2.38.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.38.2.tgz", + "integrity": "sha512-21ywIcJCCFrCTyiF1o1PaT7rbelFC2fWmayKYgFElnQ55IzNYkcn8BYhbh/QknE0l1NBRaeWMXwTTdeoqETCCg==", "dev": true, "optional": true, "os": [ @@ -1629,9 +1621,9 @@ } }, "node_modules/@sentry/cli-linux-arm": { - "version": "2.38.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.38.0.tgz", - "integrity": "sha512-lXMSEX1Sv9F2wXnnAlsS+kwy09iLQTfK10n08xzeJLIvUCLua/OFInwH6WUxNT3tIBPfBVQZPR7iQMRycH4Ilw==", + "version": "2.38.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.38.2.tgz", + "integrity": "sha512-+AiKDBQKIdQe4NhBiHSHGl0KR+b//HHTrnfK1SaTrOm9HtM4ELXAkjkRF3bmbpSzSQCS5WzcbIxxCJOeaUaO0A==", "cpu": [ "arm" ], @@ -1646,9 +1638,9 @@ } }, "node_modules/@sentry/cli-linux-arm64": { - "version": "2.38.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.38.0.tgz", - "integrity": "sha512-oUiRTyek0Ixe30zoqNlEFsLY07B9hK3FRXKv5lw341rim9PiTteh5tk5ewpuD63K+QjbEAJqp4f3zM19DEASlg==", + "version": "2.38.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.38.2.tgz", + "integrity": "sha512-4Fp/jjQpNZj4Th+ZckMQvldAuuP0ZcyJ9tJCP1CCOn5poIKPYtY6zcbTP036R7Te14PS4ALOcDNX3VNKfpsifA==", "cpu": [ "arm64" ], @@ -1663,9 +1655,9 @@ } }, "node_modules/@sentry/cli-linux-i686": { - "version": "2.38.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.38.0.tgz", - "integrity": "sha512-+luFmbQymDON16O7R/A7bmnkUjtnq1nRSehnnRJjuFCtDABCKatZzBjWvan0KNgzHhCquMSvEqHKzfVSptHeHw==", + "version": "2.38.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.38.2.tgz", + "integrity": "sha512-6zVJN10dHIn4R1v+fxuzlblzVBhIVwsaN/S7aBED6Vn1HhAyAcNG2tIzeCLGeDfieYjXlE2sCI82sZkQBCbAGw==", "cpu": [ "x86", "ia32" @@ -1681,9 +1673,9 @@ } }, "node_modules/@sentry/cli-linux-x64": { - "version": "2.38.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.38.0.tgz", - "integrity": "sha512-yY593xXbf2W+afyHKDvO4QJwoWQX97/K0NYUAqnpg3TVmIfLV9DNVid+M1w6vKIif6n8UQgAFWtR1Ys4P75mBg==", + "version": "2.38.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.38.2.tgz", + "integrity": "sha512-4UiLu9zdVtqPeltELR5MDGKcuqAdQY9xz3emISuA6bm+MXGbt2W1WgX+XY3GElwjZbmH8qpyLUEd34sw6sdcbQ==", "cpu": [ "x64" ], @@ -1698,9 +1690,9 @@ } }, "node_modules/@sentry/cli-win32-i686": { - "version": "2.38.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.38.0.tgz", - "integrity": "sha512-ipDnBvXaMqi0ZbkT/pqB11F4AaicVz5YRoidn5oxi1IJPDUd8qF0mnqabALLH3mAd5TOtKBliY5pllCFG/TvzA==", + "version": "2.38.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.38.2.tgz", + "integrity": "sha512-DYfSvd5qLPerLpIxj3Xu2rRe3CIlpGOOfGSNI6xvJ5D8j6hqbOHlCzvfC4oBWYVYGtxnwQLMeDGJ7o7RMYulig==", "cpu": [ "x86", "ia32" @@ -1715,9 +1707,9 @@ } }, "node_modules/@sentry/cli-win32-x64": { - "version": "2.38.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.38.0.tgz", - "integrity": "sha512-NqlKOqNF8i239mygARkNZK9BPzwWK91j+HPEfCKoHsZKHeBT1JauoipgPykO21qn04erq5pJkA0MsiuNRNQnMA==", + "version": "2.38.2", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.38.2.tgz", + "integrity": "sha512-W5UX58PKY1hNUHo9YJxWNhGvgvv2uOYHI27KchRiUvFYBIqlUUcIdPZDfyzetDfd8qBCxlAsFnkL2VJSNdpA9A==", "cpu": [ "x64" ], @@ -1791,8 +1783,7 @@ "node_modules/@socket.io/component-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", - "license": "MIT" + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" }, "node_modules/@taplo/cli": { "version": "0.7.0", @@ -1805,27 +1796,19 @@ } }, "node_modules/@tauri-apps/api": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-1.6.0.tgz", - "integrity": "sha512-rqI++FWClU5I2UBp4HXFvl+sBWkdigBkxnpJDQUWttNyG7IZP4FwQGhTNL5EOw0vI8i6eSAJ5frLqO7n7jbJdg==", - "engines": { - "node": ">= 14.6.0", - "npm": ">= 6.6.0", - "yarn": ">= 1.19.1" - }, + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.1.1.tgz", + "integrity": "sha512-fzUfFFKo4lknXGJq8qrCidkUcKcH2UHhfaaCNt4GzgzGaW2iS26uFOg4tS3H4P8D6ZEeUxtiD5z0nwFF0UN30A==", "funding": { "type": "opencollective", "url": "https://opencollective.com/tauri" } }, "node_modules/@tauri-apps/cli": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.6.3.tgz", - "integrity": "sha512-q46umd6QLRKDd4Gg6WyZBGa2fWvk0pbeUA5vFomm4uOs1/17LIciHv2iQ4UD+2Yv5H7AO8YiE1t50V0POiEGEw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.1.0.tgz", + "integrity": "sha512-K2VhcKqBhAeS5pNOVdnR/xQRU6jwpgmkSL2ejHXcl0m+kaTggT0WRDQnFtPq6NljA7aE03cvwsbCAoFG7vtkJw==", "dev": true, - "dependencies": { - "semver": ">=7.5.2" - }, "bin": { "tauri": "tauri.js" }, @@ -1837,22 +1820,22 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "1.6.3", - "@tauri-apps/cli-darwin-x64": "1.6.3", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.6.3", - "@tauri-apps/cli-linux-arm64-gnu": "1.6.3", - "@tauri-apps/cli-linux-arm64-musl": "1.6.3", - "@tauri-apps/cli-linux-x64-gnu": "1.6.3", - "@tauri-apps/cli-linux-x64-musl": "1.6.3", - "@tauri-apps/cli-win32-arm64-msvc": "1.6.3", - "@tauri-apps/cli-win32-ia32-msvc": "1.6.3", - "@tauri-apps/cli-win32-x64-msvc": "1.6.3" + "@tauri-apps/cli-darwin-arm64": "2.1.0", + "@tauri-apps/cli-darwin-x64": "2.1.0", + "@tauri-apps/cli-linux-arm-gnueabihf": "2.1.0", + "@tauri-apps/cli-linux-arm64-gnu": "2.1.0", + "@tauri-apps/cli-linux-arm64-musl": "2.1.0", + "@tauri-apps/cli-linux-x64-gnu": "2.1.0", + "@tauri-apps/cli-linux-x64-musl": "2.1.0", + "@tauri-apps/cli-win32-arm64-msvc": "2.1.0", + "@tauri-apps/cli-win32-ia32-msvc": "2.1.0", + "@tauri-apps/cli-win32-x64-msvc": "2.1.0" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.6.3.tgz", - "integrity": "sha512-fQN6IYSL8bG4NvkdKE4sAGF4dF/QqqQq4hOAU+t8ksOzHJr0hUlJYfncFeJYutr/MMkdF7hYKadSb0j5EE9r0A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.1.0.tgz", + "integrity": "sha512-ESc6J6CE8hl1yKH2vJ+ALF+thq4Be+DM1mvmTyUCQObvezNCNhzfS6abIUd3ou4x5RGH51ouiANeT3wekU6dCw==", "cpu": [ "arm64" ], @@ -1866,9 +1849,9 @@ } }, "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.6.3.tgz", - "integrity": "sha512-1yTXZzLajKAYINJOJhZfmMhCzweHSgKQ3bEgJSn6t+1vFkOgY8Yx4oFgWcybrrWI5J1ZLZAl47+LPOY81dLcyA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.1.0.tgz", + "integrity": "sha512-TasHS442DFs8cSH2eUQzuDBXUST4ECjCd0yyP+zZzvAruiB0Bg+c8A+I/EnqCvBQ2G2yvWLYG8q/LI7c87A5UA==", "cpu": [ "x64" ], @@ -1882,9 +1865,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.6.3.tgz", - "integrity": "sha512-CjTEr9r9xgjcvos09AQw8QMRPuH152B1jvlZt4PfAsyJNPFigzuwed5/SF7XAd8bFikA7zArP4UT12RdBxrx7w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.1.0.tgz", + "integrity": "sha512-aP7ZBGNL4ny07Cbb6kKpUOSrmhcIK2KhjviTzYlh+pPhAptxnC78xQGD3zKQkTi2WliJLPmBYbOHWWQa57lQ9w==", "cpu": [ "arm" ], @@ -1898,9 +1881,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.6.3.tgz", - "integrity": "sha512-G9EUUS4M8M/Jz1UKZqvJmQQCKOzgTb8/0jZKvfBuGfh5AjFBu8LHvlFpwkKVm1l4951Xg4ulUp6P9Q7WRJ9XSA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.1.0.tgz", + "integrity": "sha512-ZTdgD5gLeMCzndMT2f358EkoYkZ5T+Qy6zPzU+l5vv5M7dHVN9ZmblNAYYXmoOuw7y+BY4X/rZvHV9pcGrcanQ==", "cpu": [ "arm64" ], @@ -1914,9 +1897,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.6.3.tgz", - "integrity": "sha512-MuBTHJyNpZRbPVG8IZBN8+Zs7aKqwD22tkWVBcL1yOGL4zNNTJlkfL+zs5qxRnHlUsn6YAlbW/5HKocfpxVwBw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.1.0.tgz", + "integrity": "sha512-NzwqjUCilhnhJzusz3d/0i0F1GFrwCQbkwR6yAHUxItESbsGYkZRJk0yMEWkg3PzFnyK4cWTlQJMEU52TjhEzA==", "cpu": [ "arm64" ], @@ -1930,9 +1913,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.6.3.tgz", - "integrity": "sha512-Uvi7M+NK3tAjCZEY1WGel+dFlzJmqcvu3KND+nqa22762NFmOuBIZ4KJR/IQHfpEYqKFNUhJfCGnpUDfiC3Oxg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.1.0.tgz", + "integrity": "sha512-TyiIpMEtZxNOQmuFyfJwaaYbg3movSthpBJLIdPlKxSAB2BW0VWLY3/ZfIxm/G2YGHyREkjJvimzYE0i37PnMA==", "cpu": [ "x64" ], @@ -1946,9 +1929,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.6.3.tgz", - "integrity": "sha512-rc6B342C0ra8VezB/OJom9j/N+9oW4VRA4qMxS2f4bHY2B/z3J9NPOe6GOILeg4v/CV62ojkLsC3/K/CeF3fqQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.1.0.tgz", + "integrity": "sha512-/dQd0TlaxBdJACrR72DhynWftzHDaX32eBtS5WBrNJ+nnNb+znM3gON6nJ9tSE9jgDa6n1v2BkI/oIDtypfUXw==", "cpu": [ "x64" ], @@ -1962,9 +1945,9 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.6.3.tgz", - "integrity": "sha512-cSH2qOBYuYC4UVIFtrc1YsGfc5tfYrotoHrpTvRjUGu0VywvmyNk82+ZsHEnWZ2UHmu3l3lXIGRqSWveLln0xg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.1.0.tgz", + "integrity": "sha512-NdQJO7SmdYqOcE+JPU7bwg7+odfZMWO6g8xF9SXYCMdUzvM2Gv/AQfikNXz5yS7ralRhNFuW32i5dcHlxh4pDg==", "cpu": [ "arm64" ], @@ -1978,9 +1961,9 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.6.3.tgz", - "integrity": "sha512-T8V6SJQqE4PSWmYBl0ChQVmS6AR2hXFHURH2DwAhgSGSQ6uBXgwlYFcfIeQpBQA727K2Eq8X2hGfvmoySyHMRw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.1.0.tgz", + "integrity": "sha512-f5h8gKT/cB8s1ticFRUpNmHqkmaLutT62oFDB7N//2YTXnxst7EpMIn1w+QimxTvTk2gcx6EcW6bEk/y2hZGzg==", "cpu": [ "ia32" ], @@ -1994,9 +1977,9 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.6.3.tgz", - "integrity": "sha512-HUkWZ+lYHI/Gjkh2QjHD/OBDpqLVmvjZGpLK9losur1Eg974Jip6k+vsoTUxQBCBDfj30eDBct9E1FvXOspWeg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.1.0.tgz", + "integrity": "sha512-P/+LrdSSb5Xbho1LRP4haBjFHdyPdjWvGgeopL96OVtrFpYnfC+RctB45z2V2XxqFk3HweDDxk266btjttfjGw==", "cpu": [ "x64" ], @@ -2009,6 +1992,38 @@ "node": ">= 10" } }, + "node_modules/@tauri-apps/plugin-os": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-os/-/plugin-os-2.0.0.tgz", + "integrity": "sha512-M7hG/nNyQYTJxVG/UhTKhp9mpXriwWzrs9mqDreB8mIgqA3ek5nHLdwRZJWhkKjZrnDT4v9CpA9BhYeplTlAiA==", + "dependencies": { + "@tauri-apps/api": "^2.0.0" + } + }, + "node_modules/@tauri-apps/plugin-process": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-process/-/plugin-process-2.0.0.tgz", + "integrity": "sha512-OYzi0GnkrF4NAnsHZU7U3tjSoP0PbeAlO7T1Z+vJoBUH9sFQ1NSLqWYWQyf8hcb3gVWe7P1JggjiskO+LST1ug==", + "dependencies": { + "@tauri-apps/api": "^2.0.0" + } + }, + "node_modules/@tauri-apps/plugin-shell": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-shell/-/plugin-shell-2.0.1.tgz", + "integrity": "sha512-akU1b77sw3qHiynrK0s930y8zKmcdrSD60htjH+mFZqv5WaakZA/XxHR3/sF1nNv9Mgmt/Shls37HwnOr00aSw==", + "dependencies": { + "@tauri-apps/api": "^2.0.0" + } + }, + "node_modules/@tauri-apps/plugin-updater": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-updater/-/plugin-updater-2.0.0.tgz", + "integrity": "sha512-N0cl71g7RPr7zK2Fe5aoIwzw14NcdLcz7XMGFWZVjprsqgDRWoxbnUkknyCQMZthjhGkppCd/wN2MIsUz+eAhQ==", + "dependencies": { + "@tauri-apps/api": "^2.0.0" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -2070,9 +2085,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "devOptional": true }, "node_modules/@types/json-schema": { @@ -2092,9 +2107,9 @@ } }, "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", "devOptional": true }, "node_modules/@types/react": { @@ -2279,6 +2294,18 @@ } } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@typescript-eslint/utils": { "version": "8.16.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.16.0.tgz", @@ -2414,12 +2441,12 @@ } }, "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, "node_modules/ansi-styles": { @@ -2943,11 +2970,11 @@ } }, "node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -3050,14 +3077,12 @@ "node_modules/emoji-regex": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", - "license": "MIT" + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==" }, "node_modules/engine.io-client": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.1.tgz", - "integrity": "sha512-aYuoak7I+R83M/BBPIOs2to51BmFIpC1wZe6zZzMrT2llVsHy5cvcmdsJgP2Qz6smHu+sD9oexiSUAVd8OfBPw==", - "license": "MIT", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.2.tgz", + "integrity": "sha512-TAr+NKeoVTjEVW8P3iHguO1LO6RlUz9O5Y8o7EY0fU+gY1NYqas7NN3slpFtbXEsLMHk0h90fJMfKjRkQ0qUIw==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", @@ -3070,7 +3095,6 @@ "version": "5.2.3", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", - "license": "MIT", "engines": { "node": ">=10.0.0" } @@ -3157,9 +3181,9 @@ } }, "node_modules/es-iterator-helpers": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.1.0.tgz", - "integrity": "sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.0.tgz", + "integrity": "sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q==", "dev": true, "dependencies": { "call-bind": "^1.0.7", @@ -3170,6 +3194,7 @@ "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "globalthis": "^1.0.4", + "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.3", "has-symbols": "^1.0.3", @@ -3475,15 +3500,6 @@ "node": "*" } }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/eslint-scope": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", @@ -3888,21 +3904,18 @@ } }, "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -3920,26 +3933,19 @@ "node": ">=10.13.0" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/globals": { @@ -4024,15 +4030,6 @@ "node": ">=0.10.0" } }, - "node_modules/has-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -4122,11 +4119,6 @@ "react-is": "^16.7.0" } }, - "node_modules/hoist-non-react-statics/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, "node_modules/html-parse-stringify": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", @@ -4792,9 +4784,9 @@ "dev": true }, "node_modules/loglevel": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.1.tgz", - "integrity": "sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz", + "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==", "dev": true, "engines": { "node": ">= 0.6.0" @@ -4814,15 +4806,6 @@ "loglevel": "^1.4.1" } }, - "node_modules/loglevel-colored-level-prefix/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/loglevel-colored-level-prefix/node_modules/ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", @@ -4857,18 +4840,6 @@ "node": ">=0.8.0" } }, - "node_modules/loglevel-colored-level-prefix/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/loglevel-colored-level-prefix/node_modules/supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -4959,9 +4930,9 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/nanoid": { "version": "3.3.7", @@ -5260,9 +5231,9 @@ } }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -5533,6 +5504,15 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/prettier-eslint/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/prettier-eslint/node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -5549,6 +5529,7 @@ "version": "8.57.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", @@ -5711,6 +5692,30 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/prettier-eslint/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prettier-eslint/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/prettier-linter-helpers": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", @@ -5749,6 +5754,12 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -5885,10 +5896,9 @@ } }, "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-qr-code": { "version": "2.0.15", @@ -5951,15 +5961,15 @@ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" + "set-function-name": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -6035,13 +6045,56 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/rollup": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz", - "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.4.tgz", + "integrity": "sha512-vGorVWIsWfX3xbcyAS+I047kFKapHYivmkaT63Smj77XwvLSJos6M1xGqZnBPFQFBRZDOcG1QnYEIxAvTr/HjA==", "devOptional": true, "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -6051,22 +6104,24 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.22.4", - "@rollup/rollup-android-arm64": "4.22.4", - "@rollup/rollup-darwin-arm64": "4.22.4", - "@rollup/rollup-darwin-x64": "4.22.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", - "@rollup/rollup-linux-arm-musleabihf": "4.22.4", - "@rollup/rollup-linux-arm64-gnu": "4.22.4", - "@rollup/rollup-linux-arm64-musl": "4.22.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", - "@rollup/rollup-linux-riscv64-gnu": "4.22.4", - "@rollup/rollup-linux-s390x-gnu": "4.22.4", - "@rollup/rollup-linux-x64-gnu": "4.22.4", - "@rollup/rollup-linux-x64-musl": "4.22.4", - "@rollup/rollup-win32-arm64-msvc": "4.22.4", - "@rollup/rollup-win32-ia32-msvc": "4.22.4", - "@rollup/rollup-win32-x64-msvc": "4.22.4", + "@rollup/rollup-android-arm-eabi": "4.24.4", + "@rollup/rollup-android-arm64": "4.24.4", + "@rollup/rollup-darwin-arm64": "4.24.4", + "@rollup/rollup-darwin-x64": "4.24.4", + "@rollup/rollup-freebsd-arm64": "4.24.4", + "@rollup/rollup-freebsd-x64": "4.24.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.4", + "@rollup/rollup-linux-arm-musleabihf": "4.24.4", + "@rollup/rollup-linux-arm64-gnu": "4.24.4", + "@rollup/rollup-linux-arm64-musl": "4.24.4", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.4", + "@rollup/rollup-linux-riscv64-gnu": "4.24.4", + "@rollup/rollup-linux-s390x-gnu": "4.24.4", + "@rollup/rollup-linux-x64-gnu": "4.24.4", + "@rollup/rollup-linux-x64-musl": "4.24.4", + "@rollup/rollup-win32-arm64-msvc": "4.24.4", + "@rollup/rollup-win32-ia32-msvc": "4.24.4", + "@rollup/rollup-win32-x64-msvc": "4.24.4", "fsevents": "~2.3.2" } }, @@ -6137,15 +6192,12 @@ } }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/set-function-length": { @@ -6251,7 +6303,6 @@ "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", - "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" @@ -6261,9 +6312,9 @@ } }, "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "engines": { "node": ">=0.10.0" } @@ -6354,15 +6405,15 @@ } }, "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.1" + "ansi-regex": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, "node_modules/strip-json-comments": { @@ -6439,9 +6490,9 @@ } }, "node_modules/synckit": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", - "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", + "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", "dev": true, "dependencies": { "@pkgr/core": "^0.1.0", @@ -6483,9 +6534,9 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", + "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", "dev": true, "engines": { "node": ">=16" @@ -6495,9 +6546,9 @@ } }, "node_modules/tsconfck": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.3.tgz", - "integrity": "sha512-ulNZP1SVpRDesxeMLON/LtWM8HIgAJEIVpVVhBM6gsmvQ8+Rh+ZG7FWGvHh7Ah3pRABwVJWklWCr/BTZSv0xnQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.4.tgz", + "integrity": "sha512-kdqWFGVJqe+KGYvlSO9NIaWn9jT1Ny4oKVzAJsKii5eoE9snzTJzL4+MMVOMn+fikWGFmKEylcXL710V/kIPJQ==", "bin": { "tsconfck": "bin/tsconfck.js" }, @@ -6514,9 +6565,9 @@ } }, "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/type-check": { "version": "0.4.0", @@ -6734,8 +6785,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", - "optional": true, - "peer": true, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } @@ -6831,9 +6880,9 @@ } }, "node_modules/vite/node_modules/postcss": { - "version": "8.4.44", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.44.tgz", - "integrity": "sha512-Aweb9unOEpQ3ezu4Q00DPvvM2ZTUitJdNKeP/+uQgr1IBIqu574IaZoURId7BKtWMREwzKa9OgzPzezWGPWFQw==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "devOptional": true, "funding": [ { @@ -6851,8 +6900,8 @@ ], "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -6923,6 +6972,18 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/vue-eslint-parser/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -7065,7 +7126,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -7083,9 +7143,9 @@ } }, "node_modules/xmlhttprequest-ssl": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.1.tgz", - "integrity": "sha512-ptjR8YSJIXoA3Mbv5po7RtSYHO6mZr8s7i5VGmEk7QY2pQWyT1o0N+W1gKbOyJPUCGXGnuw0wqe8f0L6Y0ny7g==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", "engines": { "node": ">=0.4.0" } diff --git a/package.json b/package.json index 1d047a541..a14883caf 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,11 @@ "@floating-ui/react": "^0.26.28", "@lottiefiles/dotlottie-react": "^0.10.1", "@sentry/react": "^8.41.0", - "@tauri-apps/api": "^1", + "@tauri-apps/api": "^2.1.1", + "@tauri-apps/plugin-os": "^2.0.0", + "@tauri-apps/plugin-process": "^2.0.0", + "@tauri-apps/plugin-shell": "^2.0.1", + "@tauri-apps/plugin-updater": "^2.0.0", "emoji-regex": "^10.4.0", "framer-motion": "^11.12.0", "globals": "^15.12.0", @@ -41,7 +45,7 @@ "@nabla/vite-plugin-eslint": "^2.0.5", "@sentry/vite-plugin": "^2.22.6", "@taplo/cli": "^0.7.0", - "@tauri-apps/cli": "^1.6.3", + "@tauri-apps/cli": "^2.1.0", "@types/eslint__js": "^8.42.3", "@types/node": "^22.10.1", "@types/react": "^18.3.12", diff --git a/public/locales/af/common.json b/public/locales/af/common.json index 0daef8035..afbcaa85b 100644 --- a/public/locales/af/common.json +++ b/public/locales/af/common.json @@ -9,6 +9,7 @@ "disconnect": "Ontkoppel", "hashrate": "Hashtempo", "max-temperature": "Maksimum temperatuur", + "minimize": "Minimize", "mode": "Modus", "please-try-again-later": "Probeer asseblief later weer. As die probleem voortduur, kontak ons asseblief.", "resources": "Hulpbronne", @@ -20,6 +21,7 @@ "temperature": "Temperatuur", "testnet": "Toetsnetwerk", "unknown": "Onbekend", + "unminimize": "Unminimize", "usage": "Gebruik", "utilization": "Benutting", "version": "Weergawe", diff --git a/public/locales/af/mining-view.json b/public/locales/af/mining-view.json index 6ea93e6a7..2c01e3a81 100644 --- a/public/locales/af/mining-view.json +++ b/public/locales/af/mining-view.json @@ -1,12 +1,15 @@ { "connection-to-node-lost": "Kontak met mynwerker verloor. Wag asseblief vir mynwerker om kontak te maak of begin weer.", + "cpu-hashrate": "CPU Hashrate", "cpu-power": "CPU Krag", "current-block-time": "Huidige bloktyd", "day": "day", "estimated-day": "Est tXTM/dag", "estimated-earnings": "Geskatte verdienste", "floor": "Vloer", + "gpu-hashrate": "GPU Hashrate", "gpu-power": "GPU Krag", + "gpu-usage": "GPU Usage", "mining-button-text": { "cancel-mining": "Kanselleer myn", "changing-mode": "Verander modus", diff --git a/public/locales/cn/common.json b/public/locales/cn/common.json index f9e347959..47f5a7d9f 100644 --- a/public/locales/cn/common.json +++ b/public/locales/cn/common.json @@ -9,6 +9,7 @@ "disconnect": "断开连接", "hashrate": "哈希率", "max-temperature": "最高温度", + "minimize": "Minimize", "mode": "模式", "please-try-again-later": "请稍后再试。如果问题仍然存在,请联系我们。", "resources": "资源", @@ -20,6 +21,7 @@ "temperature": "温度", "testnet": "测试网", "unknown": "未知", + "unminimize": "Unminimize", "usage": "使用", "utilization": "利用率", "version": "版本", diff --git a/public/locales/de/common.json b/public/locales/de/common.json index 22816336c..123331d65 100644 --- a/public/locales/de/common.json +++ b/public/locales/de/common.json @@ -9,6 +9,7 @@ "disconnect": "Trennen", "hashrate": "Hashrate", "max-temperature": "Maximaltemperatur", + "minimize": "Minimize", "mode": "Modus", "please-try-again-later": "Bitte versuche es später erneut. Wenn das Problem weiterhin besteht, kontaktiere uns bitte.", "resources": "Ressourcen", @@ -20,6 +21,7 @@ "temperature": "Temperatur", "testnet": "Testnet", "unknown": "Unbekannt", + "unminimize": "Unminimize", "usage": "Nutzung", "utilization": "Auslastung", "version": "Version", diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 27285b961..2b32af0c7 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -9,6 +9,7 @@ "disconnect": "Disconnect", "hashrate": "Hashrate", "max-temperature": "Max temperature", + "minimize": "Minimize", "mode": "Mode", "please-try-again-later": "Please try again later. If the problem persists, please contact us.", "resources": "Resources", @@ -20,6 +21,7 @@ "temperature": "Temperature", "testnet": "Testnet", "unknown": "Unknown", + "unminimize": "Unminimize", "usage": "Usage", "utilization": "Utilization", "version": "Version", diff --git a/public/locales/fr/common.json b/public/locales/fr/common.json index 66cfd6d02..80b897013 100644 --- a/public/locales/fr/common.json +++ b/public/locales/fr/common.json @@ -9,6 +9,7 @@ "disconnect": "Déconnecter", "hashrate": "Taux de hachage", "max-temperature": "Température maximale", + "minimize": "Minimize", "mode": "Mode", "please-try-again-later": "Réessaye plus tard s'il te plaît. Si le problème persiste, contacte-nous s'il te plaît.", "resources": "Ressources", @@ -20,6 +21,7 @@ "temperature": "Température", "testnet": "Testnet", "unknown": "Inconnu", + "unminimize": "Unminimize", "usage": "Utilisation", "utilization": "Utilisation", "version": "Version", diff --git a/public/locales/hi/common.json b/public/locales/hi/common.json index bb5b2da2b..a80e03484 100644 --- a/public/locales/hi/common.json +++ b/public/locales/hi/common.json @@ -9,6 +9,7 @@ "disconnect": "डिस्कनेक्ट करें", "hashrate": "हैश दर", "max-temperature": "अधिकतम तापमान", + "minimize": "Minimize", "mode": "मोड", "please-try-again-later": "कृपया बाद में पुनः प्रयास करें। यदि समस्या बनी रहती है, तो कृपया हमसे संपर्क करें।", "resources": "संसाधन", @@ -20,6 +21,7 @@ "temperature": "तापमान", "testnet": "टेस्टनेट", "unknown": "अज्ञात", + "unminimize": "Unminimize", "usage": "उपयोग", "utilization": "उपयोग", "version": "संस्करण", diff --git a/public/locales/id/common.json b/public/locales/id/common.json index 2632ec1be..380cc8deb 100644 --- a/public/locales/id/common.json +++ b/public/locales/id/common.json @@ -9,6 +9,7 @@ "disconnect": "Putuskan Koneksi", "hashrate": "Hashrate", "max-temperature": "Suhu maksimum", + "minimize": "Minimize", "mode": "Mode", "please-try-again-later": "Silakan coba lagi nanti. Jika masalah berlanjut, silakan hubungi kami.", "resources": "Sumber daya", @@ -20,6 +21,7 @@ "temperature": "Suhu", "testnet": "Testnet", "unknown": "Tidak diketahui", + "unminimize": "Unminimize", "usage": "Penggunaan", "utilization": "Pemanfaatan", "version": "Versi", diff --git a/public/locales/ja/common.json b/public/locales/ja/common.json index f2cffef1f..92ee6239d 100644 --- a/public/locales/ja/common.json +++ b/public/locales/ja/common.json @@ -9,6 +9,7 @@ "disconnect": "切断", "hashrate": "ハッシュレート", "max-temperature": "最大温度", + "minimize": "Minimize", "mode": "モード", "please-try-again-later": "後でもう一度お試しください。問題が続く場合は、お問い合わせください。", "resources": "リソース", @@ -20,6 +21,7 @@ "temperature": "温度", "testnet": "テストネット", "unknown": "不明", + "unminimize": "Unminimize", "usage": "使用量", "utilization": "利用率", "version": "バージョン", diff --git a/public/locales/ko/common.json b/public/locales/ko/common.json index 16c7364ac..903a6fed7 100644 --- a/public/locales/ko/common.json +++ b/public/locales/ko/common.json @@ -9,6 +9,7 @@ "disconnect": "연결 해제", "hashrate": "해시레이트", "max-temperature": "최대 온도", + "minimize": "Minimize", "mode": "모드", "please-try-again-later": "나중에 다시 시도해 주세요. 문제가 계속되면 저희에게 연락해 주세요.", "resources": "자원", @@ -20,6 +21,7 @@ "temperature": "온도", "testnet": "테스트넷", "unknown": "알 수 없음", + "unminimize": "Unminimize", "usage": "사용량", "utilization": "활용도", "version": "버전", diff --git a/public/locales/pl/common.json b/public/locales/pl/common.json index 2ba2b71c7..1b6131073 100644 --- a/public/locales/pl/common.json +++ b/public/locales/pl/common.json @@ -9,6 +9,7 @@ "disconnect": "Odłącz", "hashrate": "Prędkość ( hashrate )", "max-temperature": "Maksymalna temperatura", + "minimize": "Minimize", "mode": "Tryb", "please-try-again-later": "Spróbuj ponownie później. Jeśli problem będzie się powtarzał, skontaktuj się z nami.", "resources": "Zasoby", @@ -20,6 +21,7 @@ "temperature": "Temperatura", "testnet": "Testnet", "unknown": "Nieznany", + "unminimize": "Unminimize", "usage": "Użycie", "utilization": "Wykorzystanie", "version": "Wersja", diff --git a/public/locales/ru/common.json b/public/locales/ru/common.json index 3209a6b67..05804b747 100644 --- a/public/locales/ru/common.json +++ b/public/locales/ru/common.json @@ -9,6 +9,7 @@ "disconnect": "Отключить", "hashrate": "Хэшрейт", "max-temperature": "Максимальная температура", + "minimize": "Minimize", "mode": "Режим", "please-try-again-later": "Пожалуйста, попробуйте позже. Если проблема сохраняется, свяжитесь с нами.", "resources": "Ресурсы", @@ -20,6 +21,7 @@ "temperature": "Температура", "testnet": "Тестовая сеть", "unknown": "Неизвестно", + "unminimize": "Unminimize", "usage": "Использование", "utilization": "Использование", "version": "Версия", diff --git a/public/locales/tr/common.json b/public/locales/tr/common.json index c957883d7..abad96307 100644 --- a/public/locales/tr/common.json +++ b/public/locales/tr/common.json @@ -9,6 +9,7 @@ "disconnect": "Bağlantıyı Kes", "hashrate": "Hashrate", "max-temperature": "Maks. Sıcaklık", + "minimize": "Minimize", "mode": "Mod", "please-try-again-later": "Lütfen daha sonra tekrar deneyin. Sorun devam ederse, lütfen bizimle iletişime geçin.", "resources": "Kaynaklar", @@ -20,6 +21,7 @@ "temperature": "Sıcaklık", "testnet": "Testnet", "unknown": "Bilinmeyen", + "unminimize": "Unminimize", "usage": "Kullanım", "utilization": "Fayda", "version": "Versiyon", diff --git a/public/splash.html b/public/splash.html index 8ee044b30..68156e139 100644 --- a/public/splash.html +++ b/public/splash.html @@ -35,7 +35,7 @@ diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index a46e597e8..317335273 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -82,7 +82,7 @@ tauri = { version = "2", features = [ "unstable", ] } tauri-plugin-os = "2" -tauri-plugin-sentry = "0.2.0" +tauri-plugin-sentry = "=0.2.0" tauri-plugin-shell = "2" tauri-plugin-single-instance = "^2" tauri-plugin-updater = "^2" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 3f066ca4d..463e35da9 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -13,6 +13,7 @@ "core:window:allow-destroy", "core:window:allow-minimize", "core:window:allow-unminimize", - "shell:allow-open" + "shell:allow-open", + "sentry:default" ] } \ No newline at end of file diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 7acb72e80..c752b1105 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -664,9 +664,9 @@ fn main() { }; let app = tauri::Builder::default() - .plugin(tauri_plugin_shell::init()) - .plugin(tauri_plugin_updater::Builder::new().build()) .plugin(tauri_plugin_os::init()) + .plugin(tauri_plugin_sentry::init_with_no_injection(&client)) + .plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_single_instance::init(|app, argv, cwd| { println!("{}, {argv:?}, {cwd}", app.package_info().name); diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 7e9b7e085..896f203f0 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -52,6 +52,14 @@ "macOSPrivateApi": true, "withGlobalTauri": true, "windows": [ + { + "title": "Tari Universe (Alpha) | Testnet", + "width": 1380, + "height": 780, + "label": "splashscreen", + "url": "/splash.html", + "center": true + }, { "title": "Tari Universe (Alpha) | Testnet", "label": "main", @@ -64,14 +72,6 @@ "transparent": false, "visible": false, "center": true - }, - { - "title": "Tari Universe (Alpha) | Testnet", - "width": 1380, - "height": 780, - "label": "splashscreen", - "url": "splash.html", - "center": true } ] }, From d4467ae5228c97ae9cdbdf7efc8495b14823c971 Mon Sep 17 00:00:00 2001 From: Shannon Tenner Date: Mon, 2 Dec 2024 12:47:27 +0200 Subject: [PATCH 12/34] wip: windows build --- src-tauri/Cargo.lock | 5 ----- src-tauri/Cargo.toml | 3 +-- src-tauri/tauri.conf.json | 8 +------- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index d008861a3..9eacdc5c2 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -7323,7 +7323,6 @@ dependencies = [ "tray-icon", "url", "urlpattern", - "uuid", "webkit2gtk", "webview2-com", "window-vibrancy", @@ -7346,7 +7345,6 @@ dependencies = [ "semver", "serde", "serde_json", - "tauri-codegen", "tauri-utils", "tauri-winres", "toml 0.8.19", @@ -7562,12 +7560,10 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9271a88f99b4adea0dc71d0baca4505475a0bbd139fb135f62958721aaa8fe54" dependencies = [ - "aes-gcm", "brotli", "cargo_metadata", "ctor", "dunce", - "getrandom 0.2.15", "glob", "html5ever", "http", @@ -7586,7 +7582,6 @@ dependencies = [ "serde-untagged", "serde_json", "serde_with", - "serialize-to-javascript", "swift-rs", "thiserror 2.0.3", "toml 0.8.19", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 317335273..eac24097f 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -10,7 +10,7 @@ version = "0.8.2" [build-dependencies] embed-resource = "2.5.0" -tauri-build = { version = "2", features = ["isolation"] } +tauri-build = { version = "2", features = [] } [dependencies] anyhow = "1" @@ -75,7 +75,6 @@ tari_shutdown = { git = "https://github.com/tari-project/tari.git", branch = "de tari_utilities = "0.8.0" tauri = { version = "2", features = [ "macos-private-api", - "isolation", "image-png", "image-ico", "tray-icon", diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 896f203f0..fedbd4ffb 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -36,13 +36,7 @@ "app": { "security": { "capabilities": ["desktop-capability", "default", "migrated"], - "csp": null, - "pattern": { - "use": "isolation", - "options": { - "dir": "../dist-isolation" - } - } + "csp": null }, "trayIcon": { "id": "universe-tray-id", From e4d85e70b2c11ae38953ca678d6a461f7a05178d Mon Sep 17 00:00:00 2001 From: Shannon Tenner Date: Mon, 2 Dec 2024 14:10:29 +0200 Subject: [PATCH 13/34] move structs --- src-tauri/src/commands.rs | 107 ++++++++++++++++++++++++++++++------- src-tauri/src/cpu_miner.rs | 3 +- src-tauri/src/main.rs | 98 +++++---------------------------- 3 files changed, 102 insertions(+), 106 deletions(-) diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 0c5908e51..3f1946d36 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -6,8 +6,8 @@ use crate::credential_manager::{CredentialError, CredentialManager}; use crate::external_dependencies::{ ExternalDependencies, ExternalDependency, RequiredExternalDependency, }; -use crate::gpu_miner_adapter::GpuNodeSource; -use crate::hardware::hardware_status_monitor::HardwareStatusMonitor; +use crate::gpu_miner_adapter::{GpuMinerStatus, GpuNodeSource}; +use crate::hardware::hardware_status_monitor::{HardwareStatusMonitor, PublicDeviceProperties}; use crate::internal_wallet::{InternalWallet, PaperWalletConfig}; use crate::node_manager::NodeManagerError; use crate::p2pool::models::Stats; @@ -15,18 +15,15 @@ use crate::progress_tracker::ProgressTracker; use crate::systemtray_manager::{SystemtrayManager, SystrayData}; use crate::tor_adapter::TorConfig; use crate::utils::shutdown_utils::stop_all_processes; -use crate::wallet_adapter::TransactionInfo; +use crate::wallet_adapter::{TransactionInfo, WalletBalance}; use crate::wallet_manager::WalletManagerError; -use crate::{ - setup_inner, ApplicationsVersions, BaseNodeStatus, CpuMinerMetrics, GpuMinerMetrics, - MaxUsageLevels, MinerMetrics, TariWalletDetails, UniverseAppState, APPLICATION_FOLDER_ID, - MAX_ACCEPTABLE_COMMAND_TIME, -}; +use crate::{setup_inner, UniverseAppState, APPLICATION_FOLDER_ID}; use keyring::Entry; use log::{debug, error, info, warn}; use monero_address_creator::Seed as MoneroSeed; use regex::Regex; use sentry::integrations::anyhow::capture_anyhow; +use serde::Serialize; use std::fs::{read_dir, remove_dir_all, remove_file}; use std::sync::atomic::Ordering; use std::thread::{available_parallelism, sleep}; @@ -35,9 +32,81 @@ use tari_common::configuration::Network; use tari_core::transactions::tari_amount::MicroMinotari; use tauri::{Manager, PhysicalPosition, PhysicalSize}; +const MAX_ACCEPTABLE_COMMAND_TIME: Duration = Duration::from_secs(1); const LOG_TARGET: &str = "tari::universe::commands"; const LOG_TARGET_WEB: &str = "tari::universe::web"; +#[derive(Debug, Serialize, Clone)] +pub struct MaxUsageLevels { + max_cpu_threads: i32, + max_gpus_threads: Vec, +} + +pub enum CpuMinerConnection { + BuiltInProxy, +} + +#[derive(Debug, Serialize)] +pub struct ApplicationsVersions { + tari_universe: String, + xmrig: String, + minotari_node: String, + mm_proxy: String, + wallet: String, + sha_p2pool: String, + xtrgpuminer: String, +} + +#[derive(Debug, Serialize, Clone)] +pub struct CpuMinerMetrics { + // hardware: Vec, + mining: CpuMinerStatus, +} + +#[derive(Debug, Serialize, Clone)] +pub struct GpuMinerMetrics { + hardware: Vec, + mining: GpuMinerStatus, +} + +#[derive(Debug, Serialize, Clone)] +pub struct MinerMetrics { + sha_network_hash_rate: u64, + randomx_network_hash_rate: u64, + cpu: CpuMinerMetrics, + gpu: GpuMinerMetrics, + base_node: BaseNodeStatus, +} + +#[derive(Debug, Serialize, Clone)] +pub struct TariWalletDetails { + wallet_balance: Option, + tari_address_base58: String, + tari_address_emoji: String, +} + +#[derive(Debug, Serialize, Clone)] +pub struct BaseNodeStatus { + block_height: u64, + block_time: u64, + is_synced: bool, + is_connected: bool, + connected_peers: Vec, +} +#[derive(Debug, Serialize, Clone)] +pub struct CpuMinerStatus { + pub is_mining: bool, + pub hash_rate: f64, + pub estimated_earnings: u64, + pub connection: CpuMinerConnectionStatus, +} + +#[derive(Debug, Serialize, Clone)] +pub struct CpuMinerConnectionStatus { + pub is_connected: bool, + // pub error: Option, +} + #[tauri::command] pub async fn close_splashscreen(window: tauri::Window) { let splashscreen_window = window @@ -455,13 +524,10 @@ pub async fn get_p2pool_stats( return Err("Already getting p2pool stats".to_string()); } state.is_getting_p2pool_stats.store(true, Ordering::SeqCst); - let p2pool_stats = match state.p2pool_manager.get_stats().await { - Ok(s) => s, - Err(e) => { - warn!(target: LOG_TARGET, "Error getting p2pool stats: {}", e); - None - } - }; + let p2pool_stats = state.p2pool_manager.get_stats().await.unwrap_or_else(|e| { + warn!(target: LOG_TARGET, "Error getting p2pool stats: {}", e); + None + }); if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { warn!(target: LOG_TARGET, "get_p2pool_stats took too long: {:?}", timer.elapsed()); @@ -614,15 +680,16 @@ pub async fn get_transaction_history( state .is_getting_transaction_history .store(true, Ordering::SeqCst); - let transactions = match state.wallet_manager.get_transaction_history().await { - Ok(t) => t, - Err(e) => { + let transactions = state + .wallet_manager + .get_transaction_history() + .await + .unwrap_or_else(|e| { if !matches!(e, WalletManagerError::WalletNotStarted) { warn!(target: LOG_TARGET, "Error getting transaction history: {}", e); } vec![] - } - }; + }); if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { warn!(target: LOG_TARGET, "get_transaction_history took too long: {:?}", timer.elapsed()); diff --git a/src-tauri/src/cpu_miner.rs b/src-tauri/src/cpu_miner.rs index 209f4c73d..838691f19 100644 --- a/src-tauri/src/cpu_miner.rs +++ b/src-tauri/src/cpu_miner.rs @@ -1,8 +1,9 @@ use crate::app_config::MiningMode; use crate::binaries::Binaries; +use crate::commands::{CpuMinerConnection, CpuMinerConnectionStatus, CpuMinerStatus}; use crate::process_watcher::ProcessWatcher; use crate::xmrig_adapter::{XmrigAdapter, XmrigNodeConnection}; -use crate::{CpuMinerConfig, CpuMinerConnection, CpuMinerConnectionStatus, CpuMinerStatus}; +use crate::CpuMinerConfig; use log::{debug, error, warn}; use std::path::PathBuf; use std::sync::Arc; diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index ba9a5f8ff..c9c62bbbb 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -4,7 +4,7 @@ use auto_launcher::AutoLauncher; #[allow(unused_imports)] use external_dependencies::RequiredExternalDependency; -use hardware::hardware_status_monitor::{HardwareStatusMonitor, PublicDeviceProperties}; +use hardware::hardware_status_monitor::HardwareStatusMonitor; use log::trace; use log::{debug, error, info, warn}; @@ -23,10 +23,10 @@ use tokio::sync::{Mutex, RwLock}; use tokio::time; use utils::logging_utils::setup_logging; -use app_config::{AppConfig, GpuThreads}; +use app_config::AppConfig; use app_in_memory_config::AppInMemoryConfig; use binaries::{binaries_list::Binaries, binaries_resolver::BinaryResolver}; -use gpu_miner_adapter::GpuMinerStatus; + use node_manager::NodeManagerError; use progress_tracker::ProgressTracker; use setup_status_event::SetupStatusEvent; @@ -36,6 +36,7 @@ use telemetry_manager::TelemetryManager; use crate::cpu_miner::CpuMiner; use crate::app_config::WindowSettings; +use crate::commands::{CpuMinerConnection, MinerMetrics, TariWalletDetails}; use crate::feedback::Feedback; use crate::gpu_miner::GpuMiner; use crate::internal_wallet::InternalWallet; @@ -45,7 +46,7 @@ use crate::p2pool::models::Stats; use crate::p2pool_manager::{P2poolConfig, P2poolManager}; use crate::tor_manager::TorManager; use crate::utils::auto_rollback::AutoRollback; -use crate::wallet_adapter::WalletBalance; + use crate::wallet_manager::WalletManager; use utils::shutdown_utils::stop_all_processes; @@ -93,8 +94,6 @@ mod wallet_manager; mod xmrig; mod xmrig_adapter; -const MAX_ACCEPTABLE_COMMAND_TIME: Duration = Duration::from_secs(1); - const LOG_TARGET: &str = "tari::universe::main"; #[cfg(not(any(feature = "release-ci", feature = "release-ci-beta")))] const APPLICATION_FOLDER_ID: &str = "com.tari.universe.alpha"; @@ -105,10 +104,14 @@ const APPLICATION_FOLDER_ID: &str = "com.tari.universe"; #[cfg(all(feature = "release-ci-beta", not(feature = "release-ci")))] const APPLICATION_FOLDER_ID: &str = "com.tari.universe.beta"; -#[derive(Debug, Serialize, Clone)] -struct MaxUsageLevels { - max_cpu_threads: i32, - max_gpus_threads: Vec, +pub struct CpuMinerConfig { + node_connection: CpuMinerConnection, + tari_address: TariAddress, + eco_mode_xmrig_options: Vec, + ludicrous_mode_xmrig_options: Vec, + custom_mode_xmrig_options: Vec, + eco_mode_cpu_percentage: Option, + ludicrous_mode_cpu_percentage: Option, } #[derive(Debug, Serialize, Clone)] @@ -472,81 +475,6 @@ async fn setup_inner( Ok(()) } -#[derive(Debug, Serialize, Clone)] -pub struct CpuMinerMetrics { - // hardware: Vec, - mining: CpuMinerStatus, -} - -#[derive(Debug, Serialize, Clone)] -pub struct GpuMinerMetrics { - hardware: Vec, - mining: GpuMinerStatus, -} - -#[derive(Debug, Serialize, Clone)] -pub struct MinerMetrics { - sha_network_hash_rate: u64, - randomx_network_hash_rate: u64, - cpu: CpuMinerMetrics, - gpu: GpuMinerMetrics, - base_node: BaseNodeStatus, -} - -#[derive(Debug, Serialize, Clone)] -pub struct TariWalletDetails { - wallet_balance: Option, - tari_address_base58: String, - tari_address_emoji: String, -} - -#[derive(Debug, Serialize)] -pub struct ApplicationsVersions { - tari_universe: String, - xmrig: String, - minotari_node: String, - mm_proxy: String, - wallet: String, - sha_p2pool: String, - xtrgpuminer: String, -} - -#[derive(Debug, Serialize, Clone)] -pub struct BaseNodeStatus { - block_height: u64, - block_time: u64, - is_synced: bool, - is_connected: bool, - connected_peers: Vec, -} -#[derive(Debug, Serialize, Clone)] -pub struct CpuMinerStatus { - pub is_mining: bool, - pub hash_rate: f64, - pub estimated_earnings: u64, - pub connection: CpuMinerConnectionStatus, -} - -#[derive(Debug, Serialize, Clone)] -pub struct CpuMinerConnectionStatus { - pub is_connected: bool, - // pub error: Option, -} - -pub enum CpuMinerConnection { - BuiltInProxy, -} - -struct CpuMinerConfig { - node_connection: CpuMinerConnection, - tari_address: TariAddress, - eco_mode_xmrig_options: Vec, - ludicrous_mode_xmrig_options: Vec, - custom_mode_xmrig_options: Vec, - eco_mode_cpu_percentage: Option, - ludicrous_mode_cpu_percentage: Option, -} - #[derive(Clone)] struct UniverseAppState { stop_start_mutex: Arc>, From bd5ec7bad2b42bc225114abc424e8e0312b937ac Mon Sep 17 00:00:00 2001 From: Shannon Tenner Date: Mon, 2 Dec 2024 15:30:07 +0200 Subject: [PATCH 14/34] fixes after merge --- src-tauri/Cargo.toml | 2 +- src-tauri/src/main.rs | 13 +++++++++++-- .../CriticalProblemDialog/CriticalProblemDialog.tsx | 3 ++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index e7bb81074..d02e8c138 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -10,7 +10,7 @@ version = "0.8.2" [build-dependencies] embed-resource = "2.5.0" -tauri-build = { version = "2" } +tauri-build = { version = "2", features = [] } [dependencies] anyhow = "1" diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 5309d6022..89faef671 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -19,13 +19,13 @@ use tari_common::configuration::Network; use tari_common_types::tari_address::TariAddress; use tari_shutdown::Shutdown; use tauri::async_runtime::{block_on, JoinHandle}; -use tauri::{Emitter, Manager, RunEvent, WindowEvent}; +use tauri::{Emitter, Manager, PhysicalPosition, PhysicalSize, RunEvent, WindowEvent}; use tauri_plugin_sentry::{minidump, sentry}; use tokio::sync::{Mutex, RwLock}; use tokio::time; use utils::logging_utils::setup_logging; -use app_config::{AppConfig, GpuThreads}; +use app_config::AppConfig; use app_in_memory_config::AppInMemoryConfig; use binaries::{binaries_list::Binaries, binaries_resolver::BinaryResolver}; @@ -698,6 +698,15 @@ fn main() { cpu_conf.ludicrous_mode_xmrig_options = app_conf.ludicrous_mode_cpu_options().clone(); cpu_conf.custom_mode_xmrig_options = app_conf.custom_mode_cpu_options().clone(); + + // Set splashscreen windows position and size here so it won't jump around + if let Some(w_settings) = app_conf.window_settings() { + let window_position = PhysicalPosition::new(w_settings.x, w_settings.y); + let window_size = PhysicalSize::new(w_settings.width, w_settings.height); + if let Err(e) = splash_window.set_position(window_position).and_then(|_| splash_window.set_size(window_size)) { + error!(target: LOG_TARGET, "Could not set splashscreen window position or size: {:?}", e); + } + } Ok(()) }); diff --git a/src/containers/floating/CriticalProblemDialog/CriticalProblemDialog.tsx b/src/containers/floating/CriticalProblemDialog/CriticalProblemDialog.tsx index 631ee97e7..c6c2f2d9d 100644 --- a/src/containers/floating/CriticalProblemDialog/CriticalProblemDialog.tsx +++ b/src/containers/floating/CriticalProblemDialog/CriticalProblemDialog.tsx @@ -4,7 +4,8 @@ import { Dialog, DialogContent } from '@app/components/elements/dialog/Dialog'; import { Stack } from '@app/components/elements/Stack'; import { Typography } from '@app/components/elements/Typography'; import { useAppStateStore } from '@app/store/appStateStore'; -import { invoke } from '@tauri-apps/api'; +import { invoke } from '@tauri-apps/api/core'; + import { useCallback, useState } from 'react'; import { useTranslation } from 'react-i18next'; From b323dfdab78b261e904fb8b7d2677bd0e463a35f Mon Sep 17 00:00:00 2001 From: Shannon Tenner Date: Mon, 2 Dec 2024 16:33:07 +0200 Subject: [PATCH 15/34] update shutdown + fix import --- src-tauri/src/commands.rs | 17 +++++------------ src-tauri/src/main.rs | 6 +++--- src-tauri/src/utils/shutdown_utils.rs | 19 ++++++++++--------- src/hooks/app/useShuttingDown.ts | 5 +++-- src/hooks/mining/useTransactions.ts | 7 ++++--- 5 files changed, 25 insertions(+), 29 deletions(-) diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 23fc80fb4..85e0fc439 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -163,12 +163,8 @@ pub async fn download_and_start_installer( } #[tauri::command] -pub async fn exit_application( - _window: tauri::Window, - state: tauri::State<'_, UniverseAppState>, - app: tauri::AppHandle, -) -> Result<(), String> { - stop_all_processes(app.clone(), state.inner().clone(), true).await?; +pub async fn exit_application(_window: tauri::Window, app: tauri::AppHandle) -> Result<(), String> { + stop_all_processes(app.clone(), true).await?; app.exit(0); Ok(()) @@ -676,7 +672,6 @@ pub async fn get_transaction_history( pub async fn import_seed_words( seed_words: Vec, _window: tauri::Window, - state: tauri::State<'_, UniverseAppState>, app: tauri::AppHandle, ) -> Result<(), String> { let timer = Instant::now(); @@ -689,7 +684,7 @@ pub async fn import_seed_words( .app_local_data_dir() .expect("Could not get data dir"); - stop_all_processes(app.clone(), state.inner().clone(), false).await?; + stop_all_processes(app.clone(), false).await?; tauri::async_runtime::spawn(async move { match InternalWallet::create_from_seed(config_path, seed_words).await { @@ -735,10 +730,9 @@ pub fn open_log_dir(app: tauri::AppHandle) { pub async fn reset_settings<'r>( reset_wallet: bool, _window: tauri::Window, - state: tauri::State<'_, UniverseAppState>, app: tauri::AppHandle, ) -> Result<(), String> { - stop_all_processes(app.clone(), state.inner().clone(), true).await?; + stop_all_processes(app.clone(), true).await?; let network = Network::get_current_or_user_setting_or_default().as_key_str(); let app_config_dir = app.path().app_config_dir(); @@ -846,11 +840,10 @@ pub async fn resolve_application_language( pub async fn restart_application( should_stop_miners: bool, _window: tauri::Window, - state: tauri::State<'_, UniverseAppState>, app: tauri::AppHandle, ) -> Result<(), String> { if should_stop_miners { - stop_all_processes(app.clone(), state.inner().clone(), true).await?; + stop_all_processes(app.clone(), true).await?; } app.restart(); diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index efbd32ed5..d78bed9f6 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -3,7 +3,7 @@ use auto_launcher::AutoLauncher; #[allow(unused_imports)] -use external_dependencies::RequiredExternalDependency; +use external_dependencies::{ExternalDependencies, RequiredExternalDependency}; use hardware::hardware_status_monitor::HardwareStatusMonitor; use log::trace; use log::{debug, error, info, warn}; @@ -825,12 +825,12 @@ fn main() { app.run(move |app_handle, event| match event { tauri::RunEvent::ExitRequested { api: _, .. } => { info!(target: LOG_TARGET, "App shutdown request caught"); - let _unused = block_on(stop_all_processes(app_handle.clone(), app_state.clone(), true)); + let _unused = block_on(stop_all_processes(app_handle.clone(), true)); info!(target: LOG_TARGET, "App shutdown complete"); } tauri::RunEvent::Exit => { info!(target: LOG_TARGET, "App shutdown caught"); - let _unused = block_on(stop_all_processes(app_handle.clone(), app_state.clone(), true)); + let _unused = block_on(stop_all_processes(app_handle.clone(), true)); info!(target: LOG_TARGET, "Tari Universe v{} shut down successfully", app_handle.package_info().version); } RunEvent::MainEventsCleared => { diff --git a/src-tauri/src/utils/shutdown_utils.rs b/src-tauri/src/utils/shutdown_utils.rs index 943d77f47..7953f715a 100644 --- a/src-tauri/src/utils/shutdown_utils.rs +++ b/src-tauri/src/utils/shutdown_utils.rs @@ -1,17 +1,18 @@ use crate::{UniverseAppState, APPLICATION_FOLDER_ID}; use log::info; -use tauri::{AppHandle, Manager}; +use tauri::Manager; static LOG_TARGET: &str = "tari::universe::shutdown_utils"; pub async fn stop_all_processes( - app_handle: AppHandle, - state: UniverseAppState, + app_handle: tauri::AppHandle, should_shutdown: bool, ) -> Result<(), String> { info!(target: LOG_TARGET, "Stopping all miners"); - info!(target: LOG_TARGET, "Entering shutdown sequence"); + + let state = app_handle.state::().inner(); + if should_shutdown { state.shutdown.clone().trigger(); } @@ -44,7 +45,7 @@ pub async fn stop_all_processes( drop(gpu_miner); } - let wallet_manager = state.wallet_manager; + let wallet_manager = state.wallet_manager.clone(); let wallet_manager_is_running = wallet_manager.is_running().await; let wallet_manager_pid_file_exists = wallet_manager.is_pid_file_exists(base_path.clone()).await; @@ -54,7 +55,7 @@ pub async fn stop_all_processes( wallet_manager.stop().await.map_err(|e| e.to_string())?; } - let node_manager = state.node_manager; + let node_manager = state.node_manager.clone(); let node_manager_is_running = node_manager.is_running().await; let node_manager_pid_file_exists = node_manager.is_pid_file_exists(base_path.clone()).await; @@ -64,7 +65,7 @@ pub async fn stop_all_processes( node_manager.stop().await.map_err(|e| e.to_string())?; } - let mm_proxy_manager = state.mm_proxy_manager; + let mm_proxy_manager = state.mm_proxy_manager.clone(); let mm_proxy_manager_is_running = mm_proxy_manager.is_running().await; let mm_proxy_manager_pid_file_exists = mm_proxy_manager.is_pid_file_exists(base_path.clone()).await; @@ -75,7 +76,7 @@ pub async fn stop_all_processes( mm_proxy_manager.stop().await.map_err(|e| e.to_string())?; } - let p2pool_manager = state.p2pool_manager; + let p2pool_manager = state.p2pool_manager.clone(); let p2pool_manager_is_running = p2pool_manager.is_running().await; let p2pool_manager_pid_file_exists = p2pool_manager.is_pid_file_exists(base_path.clone()).await; @@ -85,7 +86,7 @@ pub async fn stop_all_processes( p2pool_manager.stop().await.map_err(|e| e.to_string())?; } - let tor_manager = state.tor_manager; + let tor_manager = state.tor_manager.clone(); let tor_manager_is_running = tor_manager.is_running().await; let tor_manager_pid_file_exists = tor_manager.is_pid_file_exists(base_path.clone()).await; diff --git a/src/hooks/app/useShuttingDown.ts b/src/hooks/app/useShuttingDown.ts index cdeea738a..298c2d059 100644 --- a/src/hooks/app/useShuttingDown.ts +++ b/src/hooks/app/useShuttingDown.ts @@ -2,6 +2,7 @@ import { tray } from '@app/utils'; import { useEffect, useState } from 'react'; import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow'; import { resetAllStores } from '@app/store/create.ts'; +import { invoke } from '@tauri-apps/api/core'; const appWindow = getCurrentWebviewWindow(); export function useShuttingDown() { @@ -21,10 +22,10 @@ export function useShuttingDown() { useEffect(() => { if (isShuttingDown) { - setTimeout(() => { + setTimeout(async () => { tray?.close(); resetAllStores(); - appWindow.close(); + await invoke('exit_application'); }, 250); } }, [isShuttingDown]); diff --git a/src/hooks/mining/useTransactions.ts b/src/hooks/mining/useTransactions.ts index 229ad151e..3e7bfaec5 100644 --- a/src/hooks/mining/useTransactions.ts +++ b/src/hooks/mining/useTransactions.ts @@ -11,7 +11,6 @@ export default function useFetchTx() { const setTransactionsLoading = useWalletStore((s) => s.setTransactionsLoading); const setupProgress = useAppStateStore((s) => s.setupProgress); const setTransactions = useWalletStore((s) => s.setTransactions); - const setError = useAppStateStore((s) => s.setError); const setItems = useCallback( async (newTx: Transaction[]) => { @@ -48,10 +47,12 @@ export default function useFetchTx() { setTransactionsLoading(false); } catch (error) { setTransactionsLoading(false); - setError('Could not get transaction history'); + console.debug(error); if (error !== ALREADY_FETCHING.HISTORY) { console.error('Could not get transaction history: ', error); } + } finally { + setTransactionsLoading(false); } - }, [isTransactionLoading, setError, setItems, setTransactionsLoading, setupProgress]); + }, [isTransactionLoading, setItems, setTransactionsLoading, setupProgress]); } From 27756b9271b1ce84ad0888b5e9913c6339dcaca5 Mon Sep 17 00:00:00 2001 From: Shannon Tenner Date: Mon, 2 Dec 2024 16:34:21 +0200 Subject: [PATCH 16/34] remove borked version str --- .github/workflows/release.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6fb1e2550..e0a96d5b9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -71,10 +71,10 @@ jobs: cd "${GITHUB_WORKSPACE}/src-tauri" echo "releaseName=Tari Universe ${{ env.BETA_STRING }} v__VERSION__-${BETA_DATE}" >> $GITHUB_ENV # Don't mess with the double quotes and inner escaped quotes - yq eval ".productName = \"Tari Universe ${{ env.BETA_STRING }} v__VERSION__-${BETA_DATE} \"" -i tauri.conf.json - yq eval ".mainBinaryName = \"Tari Universe ${{ env.BETA_STRING }} v__VERSION__-${BETA_DATE} \"" -i tauri.conf.json - yq eval ".app.windows[0].title = \"Tari Universe ${{ env.BETA_STRING }} v__VERSION__-${BETA_DATE} | Testnet\"" -i tauri.conf.json - yq eval ".app.windows[1].title = \"Tari Universe ${{ env.BETA_STRING }} v__VERSION__-${BETA_DATE} | Testnet\"" -i tauri.conf.json + yq eval ".productName = \"Tari Universe ${{ env.BETA_STRING }} - ${BETA_DATE} \"" -i tauri.conf.json + yq eval ".mainBinaryName = \"Tari Universe ${{ env.BETA_STRING }} - ${BETA_DATE} \"" -i tauri.conf.json + yq eval ".app.windows[0].title = \"Tari Universe ${{ env.BETA_STRING }} - ${BETA_DATE} | Testnet\"" -i tauri.conf.json + yq eval ".app.windows[1].title = \"Tari Universe ${{ env.BETA_STRING }} - ${BETA_DATE} | Testnet\"" -i tauri.conf.json yq eval ".identifier = \"com.tari.universe.beta\"" -i tauri.conf.json yq eval ".plugins.updater.endpoints = [\"https://raw.githubusercontent.com/tari-project/universe/main/.updater/beta-latest.json\"]" \ -i tauri.conf.json From 559e321673a33687694844420a5cd695f22f75d8 Mon Sep 17 00:00:00 2001 From: Shannon Tenner Date: Mon, 2 Dec 2024 17:00:23 +0200 Subject: [PATCH 17/34] fix again --- src-tauri/src/commands.rs | 1 - src-tauri/src/main.rs | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 85e0fc439..46e2103e5 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -3,7 +3,6 @@ use crate::app_in_memory_config::AirdropInMemoryConfig; use crate::auto_launcher::AutoLauncher; use crate::binaries::{Binaries, BinaryResolver}; use crate::credential_manager::{CredentialError, CredentialManager}; -#[allow(unused_imports)] use crate::external_dependencies::{ ExternalDependencies, ExternalDependency, RequiredExternalDependency, }; diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index d78bed9f6..da7168f98 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -2,8 +2,7 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] use auto_launcher::AutoLauncher; -#[allow(unused_imports)] -use external_dependencies::{ExternalDependencies, RequiredExternalDependency}; + use hardware::hardware_status_monitor::HardwareStatusMonitor; use log::trace; use log::{debug, error, info, warn}; @@ -38,6 +37,8 @@ use crate::cpu_miner::CpuMiner; use crate::app_config::WindowSettings; use crate::commands::{CpuMinerConnection, MinerMetrics, TariWalletDetails}; +#[allow(unused_imports)] +use crate::external_dependencies::ExternalDependencies; use crate::feedback::Feedback; use crate::gpu_miner::GpuMiner; use crate::internal_wallet::InternalWallet; From 567c9f2107b6e2ed296a1e6eb632d557a4e2b0d0 Mon Sep 17 00:00:00 2001 From: Shannon Tenner Date: Mon, 2 Dec 2024 17:20:46 +0200 Subject: [PATCH 18/34] fix reference windows --- src-tauri/src/commands.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 46e2103e5..3d87c7aef 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -143,7 +143,7 @@ pub async fn download_and_start_installer( #[cfg(target_os = "windows")] if cfg!(target_os = "windows") { - external_dependencies::ExternalDependencies::current() + ExternalDependencies::current() .install_missing_dependencies(_missing_dependency) .await .map_err(|e| { From 9abf30bf684f7902eb9c186f3a2be3393e800227 Mon Sep 17 00:00:00 2001 From: Shannon Tenner Date: Tue, 3 Dec 2024 10:25:11 +0200 Subject: [PATCH 19/34] fix: webview ref | restart after seedwords | more safeguards on tx history --- src-tauri/src/commands.rs | 7 ++++--- src-tauri/src/main.rs | 2 +- .../wallet/SeedWordsMarkup/SeedWordsEdit.tsx | 4 ++-- src/hooks/mining/useMiningMetricsUpdater.ts | 13 +++++++++++-- src/hooks/mining/useTransactions.ts | 2 +- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 3d87c7aef..77fe4e5a0 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -688,9 +688,10 @@ pub async fn import_seed_words( tauri::async_runtime::spawn(async move { match InternalWallet::create_from_seed(config_path, seed_words).await { Ok(_wallet) => { - InternalWallet::clear_wallet_local_data(data_dir).await?; - info!(target: LOG_TARGET, "[import_seed_words] Restarting the app"); - // app.restart(); + if let Ok(..) = InternalWallet::clear_wallet_local_data(data_dir).await { + info!(target: LOG_TARGET, "[import_seed_words] Restarting the app"); + app.restart(); + } Ok(()) } Err(e) => { diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index ca918d8d5..9df44e9e6 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -839,7 +839,7 @@ fn main() { RunEvent::WindowEvent { label, event, .. } => { trace!(target: LOG_TARGET, "Window event: {:?} {:?}", label, event); if let WindowEvent::CloseRequested { .. } = event { - if let Some(window) = app_handle.get_window(&label) { + if let Some(window) = app_handle.get_webview_window(&label) { if let (Ok(window_position), Ok(window_size)) = (window.outer_position(), window.outer_size()) { let window_settings = WindowSettings { x: window_position.x, diff --git a/src/containers/floating/Settings/sections/wallet/SeedWordsMarkup/SeedWordsEdit.tsx b/src/containers/floating/Settings/sections/wallet/SeedWordsMarkup/SeedWordsEdit.tsx index 6dba8ff8c..bc0417d90 100644 --- a/src/containers/floating/Settings/sections/wallet/SeedWordsMarkup/SeedWordsEdit.tsx +++ b/src/containers/floating/Settings/sections/wallet/SeedWordsMarkup/SeedWordsEdit.tsx @@ -95,7 +95,7 @@ export const SeedWordsEdit = ({ seedWords, seedWordsFetching, toggleEdit }: Seed [hasChanges] ); - const handleConfrimed = useCallback(async () => { + const handleConfirmed = useCallback(async () => { if (hasChanges && newSeedWords) { setShowConfirm(false); await importSeedWords(newSeedWords); @@ -174,7 +174,7 @@ export const SeedWordsEdit = ({ seedWords, seedWordsFetching, toggleEdit }: Seed setShowConfirm(false)}>{t('cancel')} - + {t('yes')} diff --git a/src/hooks/mining/useMiningMetricsUpdater.ts b/src/hooks/mining/useMiningMetricsUpdater.ts index 077c8342a..128f0193e 100644 --- a/src/hooks/mining/useMiningMetricsUpdater.ts +++ b/src/hooks/mining/useMiningMetricsUpdater.ts @@ -29,8 +29,17 @@ export default function useMiningMetricsUpdater() { const blockHeight = metrics.base_node.block_height; if (blockHeight > 0 && currentBlockHeight > 0 && blockHeight > currentBlockHeight) { - await fetchTx(); - await handleNewBlock(blockHeight, isMining); + try { + fetchTx() + .then(async () => { + await handleNewBlock(blockHeight, isMining); + }) + .catch(() => { + setDisplayBlockHeight(blockHeight); + }); + } catch (_) { + setDisplayBlockHeight(blockHeight); + } } else { if (blockHeight && !displayBlockHeight) { setDisplayBlockHeight(blockHeight); diff --git a/src/hooks/mining/useTransactions.ts b/src/hooks/mining/useTransactions.ts index 3e7bfaec5..cddf30a08 100644 --- a/src/hooks/mining/useTransactions.ts +++ b/src/hooks/mining/useTransactions.ts @@ -47,7 +47,7 @@ export default function useFetchTx() { setTransactionsLoading(false); } catch (error) { setTransactionsLoading(false); - console.debug(error); + if (error !== ALREADY_FETCHING.HISTORY) { console.error('Could not get transaction history: ', error); } From 134929f09beec99a3a678660b7b4fa09d98aaac0 Mon Sep 17 00:00:00 2001 From: Shannon Tenner Date: Tue, 3 Dec 2024 10:33:35 +0200 Subject: [PATCH 20/34] fix: clippy --- src-tauri/src/commands.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 77fe4e5a0..e2bcd54b3 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -688,7 +688,10 @@ pub async fn import_seed_words( tauri::async_runtime::spawn(async move { match InternalWallet::create_from_seed(config_path, seed_words).await { Ok(_wallet) => { - if let Ok(..) = InternalWallet::clear_wallet_local_data(data_dir).await { + if InternalWallet::clear_wallet_local_data(data_dir) + .await + .is_ok() + { info!(target: LOG_TARGET, "[import_seed_words] Restarting the app"); app.restart(); } From 03b27c4148f2b5b737ddcf9c1610c406e345a410 Mon Sep 17 00:00:00 2001 From: Shannon Tenner Date: Tue, 3 Dec 2024 14:11:38 +0200 Subject: [PATCH 21/34] review: changes requested --- src-tauri/src/commands.rs | 13 +++++-------- src-tauri/src/hardware/hardware_status_monitor.rs | 10 ++++------ src-tauri/src/main.rs | 4 +--- src/App/App.tsx | 13 +++---------- 4 files changed, 13 insertions(+), 27 deletions(-) diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index e2bcd54b3..6f1b35703 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -688,18 +688,15 @@ pub async fn import_seed_words( tauri::async_runtime::spawn(async move { match InternalWallet::create_from_seed(config_path, seed_words).await { Ok(_wallet) => { - if InternalWallet::clear_wallet_local_data(data_dir) + InternalWallet::clear_wallet_local_data(data_dir) .await - .is_ok() - { - info!(target: LOG_TARGET, "[import_seed_words] Restarting the app"); - app.restart(); - } - Ok(()) + .map_err(|e| e.to_string())?; + info!(target: LOG_TARGET, "[import_seed_words] Restarting the app"); + app.restart(); } Err(e) => { error!(target: LOG_TARGET, "Error loading internal wallet: {:?}", e); - Err(e) + Err::<(), std::string::String>(e.to_string()) } } }); diff --git a/src-tauri/src/hardware/hardware_status_monitor.rs b/src-tauri/src/hardware/hardware_status_monitor.rs index e7c75ce7c..7522e6bca 100644 --- a/src-tauri/src/hardware/hardware_status_monitor.rs +++ b/src-tauri/src/hardware/hardware_status_monitor.rs @@ -174,10 +174,8 @@ impl HardwareStatusMonitor { } } - async fn initialize_gpu_devices( - &self, - config_dir: PathBuf, - ) -> Result, Error> { + async fn initialize_gpu_devices(&self) -> Result, Error> { + let config_dir = dirs::config_dir().expect("Could not get config dir"); let gpu_status_file_content = self.load_gpu_devices_from_status_file(config_dir).await?; let mut platform_devices = Vec::new(); @@ -266,8 +264,8 @@ impl HardwareStatusMonitor { Ok(cpu_devices) } - pub async fn initialize(&self, config_dir: PathBuf) -> Result<(), Error> { - let gpu_devices = self.initialize_gpu_devices(config_dir).await?; + pub async fn initialize(&self) -> Result<(), Error> { + let gpu_devices = self.initialize_gpu_devices().await?; let cpu_devices = self.initialize_cpu_devices().await?; let mut gpu_devices_lock = self.gpu_devices.write().await; diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 9df44e9e6..8fe1d0459 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -312,9 +312,7 @@ async fn setup_inner( .await .inspect_err(|e| error!(target: LOG_TARGET, "Could not detect gpu miner: {:?}", e)); - HardwareStatusMonitor::current() - .initialize(config_dir.clone()) - .await?; + HardwareStatusMonitor::current().initialize().await?; let mut tor_control_port = None; if use_tor && !cfg!(target_os = "macos") { diff --git a/src/App/App.tsx b/src/App/App.tsx index 829f8daa9..fe0fa1d7b 100644 --- a/src/App/App.tsx +++ b/src/App/App.tsx @@ -1,7 +1,7 @@ +import * as Sentry from '@sentry/react'; +import { useEffect } from 'react'; import { AppContentContainer } from '@app/App/App.styles'; import { useShuttingDown } from '@app/hooks'; -import * as Sentry from '@sentry/react'; -import { useEffect, useRef } from 'react'; import { useAppStateStore } from '@app/store/appStateStore'; import { LazyMotion, domMax, MotionConfig, AnimatePresence } from 'framer-motion'; @@ -19,15 +19,8 @@ import ThemeProvider from '../theme/ThemeProvider.tsx'; export default function App() { const isShuttingDown = useShuttingDown(); const isSettingUp = useAppStateStore((s) => s.isSettingUp); - const hasCompletedSetup = useRef(false); - - useEffect(() => { - if (!isSettingUp) { - hasCompletedSetup.current = true; - } - }, [isSettingUp]); - const showSetup = isSettingUp && !hasCompletedSetup.current && !isShuttingDown; + const showSetup = isSettingUp && !isShuttingDown; const setError = useAppStateStore((s) => s.setError); const setIsWebglNotSupported = useUIStore((s) => s.setIsWebglNotSupported); From 217c2c617f866e9e686ef033fa791993f0ecf5e0 Mon Sep 17 00:00:00 2001 From: Shannon Tenner Date: Tue, 3 Dec 2024 14:45:08 +0200 Subject: [PATCH 22/34] check: remove features arr from cargo toml --- src-tauri/tauri.conf.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index dcfeb3feb..93e0e30a9 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,5 +1,5 @@ { - "version": "0.8.3", + "version": "0.8.4", "productName": "Tari Universe (Alpha)", "mainBinaryName": "Tari Universe (Alpha)", "identifier": "com.tari.universe.alpha", From 18f10add31b29872162af1423ac51cc123daf2e1 Mon Sep 17 00:00:00 2001 From: Shannon Tenner Date: Wed, 4 Dec 2024 10:30:53 +0200 Subject: [PATCH 23/34] wip: fix sentry init --- package-lock.json | 26 ++++++++++++++++ package.json | 3 +- src-tauri/Cargo.lock | 24 +++------------ src-tauri/Cargo.toml | 3 +- src-tauri/src/commands.rs | 10 +++++-- src-tauri/src/main.rs | 5 +++- src-tauri/src/node_manager.rs | 3 +- src/App/AppWrapper.tsx | 6 ++-- .../main/Dashboard/MiningView/MiningView.tsx | 11 ++++++- vite.config.ts | 30 +++++++++++++++++-- 10 files changed, 88 insertions(+), 33 deletions(-) diff --git a/package-lock.json b/package-lock.json index c3b39a8d9..80570d817 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "react-icons": "^5.3.0", "socket.io-client": "^4.8.1", "styled-components": "^6.1.12", + "tauri-plugin-sentry-api": "^0.2.0", "use-sync-external-store": "^1.2.2", "uuid": "^10.0.0", "vite-tsconfig-paths": "^5.1.3", @@ -6896,6 +6897,31 @@ "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", "license": "MIT" }, + "node_modules/tauri-plugin-sentry-api": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/tauri-plugin-sentry-api/-/tauri-plugin-sentry-api-0.2.0.tgz", + "integrity": "sha512-HnIbCVnq7jjrj8aRyzP5hfU8GwfSIkl65BH7MHj0Vbx1X4fqrKNc2lzzP/wjjrJ1hsXJCg5bRKF26HshPmgw8g==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@tauri-apps/api": "2.0.0-beta.8", + "tslib": "^2.6.0" + } + }, + "node_modules/tauri-plugin-sentry-api/node_modules/@tauri-apps/api": { + "version": "2.0.0-beta.8", + "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.0.0-beta.8.tgz", + "integrity": "sha512-fN5u+9HsSfhRaXGOdD2kPGbqDgyX+nkm1XF/4d/LNuM4WiNfvHjjRAqWQYBhQsg1aF9nsTPmSW+tmy+Yn5T5+A==", + "license": "Apache-2.0 OR MIT", + "engines": { + "node": ">= 18", + "npm": ">= 6.6.0", + "yarn": ">= 1.19.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/tauri" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", diff --git a/package.json b/package.json index 5e3e086b3..77af0868b 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "react-icons": "^5.3.0", "socket.io-client": "^4.8.1", "styled-components": "^6.1.12", + "tauri-plugin-sentry-api": "^0.2.0", "use-sync-external-store": "^1.2.2", "uuid": "^10.0.0", "vite-tsconfig-paths": "^5.1.3", @@ -68,4 +69,4 @@ "typescript-eslint": "^8.16.0", "vite": "^5.4.11" } -} \ No newline at end of file +} diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 186e1f4cf..b125ed4bf 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -145,9 +145,6 @@ name = "anyhow" version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" -dependencies = [ - "backtrace", -] [[package]] name = "arbitrary" @@ -5932,7 +5929,6 @@ dependencies = [ "httpdate", "native-tls", "reqwest", - "sentry-anyhow", "sentry-backtrace", "sentry-contexts", "sentry-core", @@ -5943,17 +5939,6 @@ dependencies = [ "ureq", ] -[[package]] -name = "sentry-anyhow" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d672bfd1ed4e90978435f3c0704edb71a7a9d86403657839d518cd6aa278aff5" -dependencies = [ - "anyhow", - "sentry-backtrace", - "sentry-core", -] - [[package]] name = "sentry-backtrace" version = "0.34.0" @@ -6811,7 +6796,6 @@ dependencies = [ "reqwest", "sanitize-filename", "semver", - "sentry", "serde", "serde_cbor", "serde_json", @@ -8093,9 +8077,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "tracing-core", ] @@ -8314,9 +8298,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.10.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" +checksum = "3193f92e105038f98ae68af40c008e3c94f2f046926e0f95e6c835dc6459bac8" dependencies = [ "base64 0.22.1", "log", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 56b01527d..80cc83e34 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -51,7 +51,6 @@ regex = "1.10.5" reqwest = { version = "0.12.5", features = ["stream", "json", "multipart"] } sanitize-filename = "0.5" semver = "1.0.23" -sentry = { version = "0.34.0", features = ["anyhow"] } serde = { version = "1", features = ["derive"] } serde_cbor = "0.11.2" serde_json = "1" @@ -82,7 +81,7 @@ tauri = { version = "2", features = [ ] } tauri-plugin-os = "2" -tauri-plugin-sentry = "=0.2.0" +tauri-plugin-sentry = "0.2.0" tauri-plugin-shell = "2" tauri-plugin-single-instance = "^2" tauri-plugin-updater = "^2" diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 6f1b35703..8b781f5c2 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -21,7 +21,6 @@ use keyring::Entry; use log::{debug, error, info, warn}; use monero_address_creator::Seed as MoneroSeed; use regex::Regex; -use sentry::integrations::anyhow::capture_anyhow; use serde::Serialize; use std::fs::{read_dir, remove_dir_all, remove_file, File}; use std::sync::atomic::Ordering; @@ -30,6 +29,8 @@ use std::time::{Duration, Instant, SystemTime}; use tari_common::configuration::Network; use tari_core::transactions::tari_amount::MicroMinotari; use tauri::{Manager, PhysicalPosition, PhysicalSize}; +use tauri_plugin_sentry::sentry; +use tauri_plugin_sentry::sentry::protocol::Event; const MAX_ACCEPTABLE_COMMAND_TIME: Duration = Duration::from_secs(1); const LOG_TARGET: &str = "tari::universe::commands"; @@ -1315,7 +1316,12 @@ pub async fn setup_application( rollback.set_value(true, Duration::from_millis(1000)).await; setup_inner(window, state.clone(), app).await.map_err(|e| { warn!(target: LOG_TARGET, "Error setting up application: {:?}", e); - capture_anyhow(&e); + sentry::capture_event(Event { + level: sentry::Level::Error, + message: Some(e.to_string()), + culprit: Some("setup-inner".to_string()), + ..Default::default() + }); e.to_string() })?; diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 8fe1d0459..09f277500 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -537,10 +537,13 @@ fn main() { let _unused = fix_path_env::fix(); // TODO: Integrate sentry into logs. Because we are using Tari's logging infrastructure, log4rs // sets the logger and does not expose a way to add sentry into it. + let client = sentry::init(( "https://edd6b9c1494eb7fda6ee45590b80bcee@o4504839079002112.ingest.us.sentry.io/4507979991285760", sentry::ClientOptions { release: sentry::release_name!(), + debug: true, + attach_stacktrace: true, ..Default::default() }, )); @@ -617,8 +620,8 @@ fn main() { }; let app = tauri::Builder::default() - .plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_sentry::init_with_no_injection(&client)) + .plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_single_instance::init(|app, argv, cwd| { println!("{}, {argv:?}, {cwd}", app.package_info().name); diff --git a/src-tauri/src/node_manager.rs b/src-tauri/src/node_manager.rs index 0cc4d312b..6aab07be2 100644 --- a/src-tauri/src/node_manager.rs +++ b/src-tauri/src/node_manager.rs @@ -5,12 +5,13 @@ use std::time::SystemTime; use chrono::{NaiveDateTime, TimeZone, Utc}; use log::{error, info}; use minotari_node_grpc_client::grpc::Peer; -use sentry::protocol::Event; use tari_common::configuration::Network; use tari_core::transactions::tari_amount::MicroMinotari; use tari_crypto::ristretto::RistrettoPublicKey; use tari_shutdown::ShutdownSignal; use tari_utilities::hex::Hex; +use tauri_plugin_sentry::sentry; +use tauri_plugin_sentry::sentry::protocol::Event; use tokio::fs; use tokio::sync::RwLock; diff --git a/src/App/AppWrapper.tsx b/src/App/AppWrapper.tsx index d5d0db18b..72ee3c7a0 100644 --- a/src/App/AppWrapper.tsx +++ b/src/App/AppWrapper.tsx @@ -1,7 +1,7 @@ +import { useEffect } from 'react'; +import * as Sentry from '@sentry/react'; import { IGNORE_FETCHING } from '@app/App/sentryIgnore'; import { initSystray } from '@app/utils'; -import * as Sentry from '@sentry/react'; -import { useEffect } from 'react'; import { useDetectMode, @@ -32,7 +32,7 @@ const sentryOptions = { attachStacktrace: true, autoSessionTracking: false, ignoreErrors: [...IGNORE_FETCHING], - enabled: environment !== 'development', + // enabled: environment !== 'development', }; setupLogger(); diff --git a/src/containers/main/Dashboard/MiningView/MiningView.tsx b/src/containers/main/Dashboard/MiningView/MiningView.tsx index 82d2eb1d5..251293a43 100644 --- a/src/containers/main/Dashboard/MiningView/MiningView.tsx +++ b/src/containers/main/Dashboard/MiningView/MiningView.tsx @@ -1,16 +1,25 @@ +import * as Sentry from '@sentry/react'; import { LayoutGroup } from 'framer-motion'; - import { BlockHeightAccent } from './components/BlockHeightAccent'; import { Ruler } from './components/Ruler'; import Earnings from './components/Earnings'; import BlockTime from './components/BlockTime'; import { MiningViewContainer } from './MiningView.styles.ts'; +import { Button } from '@app/components/elements/buttons/Button.tsx'; export default function MiningView() { + function handleErr() { + console.error('V2 sentry: test console capture'); + Sentry.captureException('V2 sentry: test capture exception'); + Sentry.captureMessage('V2 sentry: test capture message'); + } return ( + diff --git a/vite.config.ts b/vite.config.ts index e57b214de..f52d8e919 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -36,7 +36,33 @@ const devOptions: UserConfig = { export default defineConfig(({ command, mode }) => { if (command === 'serve') { - return { ...devOptions, ...baseOptions }; + return { + ...devOptions, + ...baseOptions, + plugins: [ + ...plugins, + sentryVitePlugin({ + org: 'tari-labs', + project: 'tari-universe', + release: { + name: packageInfo.version, + }, + reactComponentAnnotation: { enabled: true }, + authToken: process.env.SENTRY_AUTH_TOKEN, + // disable: mode === 'development', + telemetry: false, + sourcemaps: { + assets: ['./dist/**'], + ignore: [ + 'node_modules', + './dist/assets/textures/**', + './dist/assets/models/**', + './dist/assets/glApp.js', + ], + }, + }), + ], + }; } return { ...baseOptions, @@ -53,7 +79,7 @@ export default defineConfig(({ command, mode }) => { }, reactComponentAnnotation: { enabled: true }, authToken: process.env.SENTRY_AUTH_TOKEN, - disable: mode === 'development', + // disable: mode === 'development', telemetry: false, sourcemaps: { assets: ['./dist/**'], From f3fa2dcbbc20473bb3dadf95b44d0b314c94feb7 Mon Sep 17 00:00:00 2001 From: Shannon Tenner Date: Wed, 4 Dec 2024 11:38:13 +0200 Subject: [PATCH 24/34] fix: dedupe sentry x plugin --- src-tauri/src/main.rs | 1 - src/App/AppWrapper.tsx | 5 +++- .../main/Dashboard/MiningView/MiningView.tsx | 11 +------ vite.config.ts | 30 ++----------------- 4 files changed, 7 insertions(+), 40 deletions(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 09f277500..38fce6845 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -542,7 +542,6 @@ fn main() { "https://edd6b9c1494eb7fda6ee45590b80bcee@o4504839079002112.ingest.us.sentry.io/4507979991285760", sentry::ClientOptions { release: sentry::release_name!(), - debug: true, attach_stacktrace: true, ..Default::default() }, diff --git a/src/App/AppWrapper.tsx b/src/App/AppWrapper.tsx index 72ee3c7a0..f1575eff0 100644 --- a/src/App/AppWrapper.tsx +++ b/src/App/AppWrapper.tsx @@ -1,4 +1,5 @@ import { useEffect } from 'react'; +import { defaultOptions } from 'tauri-plugin-sentry-api'; import * as Sentry from '@sentry/react'; import { IGNORE_FETCHING } from '@app/App/sentryIgnore'; import { initSystray } from '@app/utils'; @@ -22,6 +23,7 @@ import { useMiningStore } from '@app/store/useMiningStore.ts'; const environment = import.meta.env.MODE; const sentryOptions = { + ...defaultOptions, dsn: 'https://edd6b9c1494eb7fda6ee45590b80bcee@o4504839079002112.ingest.us.sentry.io/4507979991285760', integrations: [Sentry.captureConsoleIntegration({ levels: ['warn', 'error'] }), Sentry.extraErrorDataIntegration()], release: packageInfo.version, @@ -32,7 +34,7 @@ const sentryOptions = { attachStacktrace: true, autoSessionTracking: false, ignoreErrors: [...IGNORE_FETCHING], - // enabled: environment !== 'development', + enabled: environment !== 'development', }; setupLogger(); @@ -48,6 +50,7 @@ export default function AppWrapper() { useLangaugeResolver(); useListenForExternalDependencies(); useListenForCriticalProblem(); + useEffect(() => { async function initialize() { await fetchAppConfig(); diff --git a/src/containers/main/Dashboard/MiningView/MiningView.tsx b/src/containers/main/Dashboard/MiningView/MiningView.tsx index 251293a43..82d2eb1d5 100644 --- a/src/containers/main/Dashboard/MiningView/MiningView.tsx +++ b/src/containers/main/Dashboard/MiningView/MiningView.tsx @@ -1,25 +1,16 @@ -import * as Sentry from '@sentry/react'; import { LayoutGroup } from 'framer-motion'; + import { BlockHeightAccent } from './components/BlockHeightAccent'; import { Ruler } from './components/Ruler'; import Earnings from './components/Earnings'; import BlockTime from './components/BlockTime'; import { MiningViewContainer } from './MiningView.styles.ts'; -import { Button } from '@app/components/elements/buttons/Button.tsx'; export default function MiningView() { - function handleErr() { - console.error('V2 sentry: test console capture'); - Sentry.captureException('V2 sentry: test capture exception'); - Sentry.captureMessage('V2 sentry: test capture message'); - } return ( - diff --git a/vite.config.ts b/vite.config.ts index f52d8e919..e57b214de 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -36,33 +36,7 @@ const devOptions: UserConfig = { export default defineConfig(({ command, mode }) => { if (command === 'serve') { - return { - ...devOptions, - ...baseOptions, - plugins: [ - ...plugins, - sentryVitePlugin({ - org: 'tari-labs', - project: 'tari-universe', - release: { - name: packageInfo.version, - }, - reactComponentAnnotation: { enabled: true }, - authToken: process.env.SENTRY_AUTH_TOKEN, - // disable: mode === 'development', - telemetry: false, - sourcemaps: { - assets: ['./dist/**'], - ignore: [ - 'node_modules', - './dist/assets/textures/**', - './dist/assets/models/**', - './dist/assets/glApp.js', - ], - }, - }), - ], - }; + return { ...devOptions, ...baseOptions }; } return { ...baseOptions, @@ -79,7 +53,7 @@ export default defineConfig(({ command, mode }) => { }, reactComponentAnnotation: { enabled: true }, authToken: process.env.SENTRY_AUTH_TOKEN, - // disable: mode === 'development', + disable: mode === 'development', telemetry: false, sourcemaps: { assets: ['./dist/**'], From fc33480a9fbc24fb811405f60e3d6144869dda40 Mon Sep 17 00:00:00 2001 From: Misieq01 Date: Thu, 21 Nov 2024 16:56:58 +0100 Subject: [PATCH 25/34] include openssl as dependencies --- src-tauri/Cargo.toml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 80cc83e34..aa2ce289c 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -64,11 +64,16 @@ tari_common_types = { git = "https://github.com/tari-project/tari.git", branch = tari_core = { git = "https://github.com/tari-project/tari.git", branch = "development", features = [ "transactions", ] } + +# This crates are temporary fix to solve issue with building tari app hickory-client = { version = "=0.25.0-alpha.2", features = [ "dns-over-rustls", "dnssec-openssl", ] } hickory-proto = { version = "=0.25.0-alpha.2" } +openssl = { version = "0.10", features = ["vendored"] } +#======================================================================= + tari_crypto = "0.21.0" tari_key_manager = { git = "https://github.com/tari-project/tari.git", branch = "development" } tari_shutdown = { git = "https://github.com/tari-project/tari.git", branch = "development" } @@ -118,9 +123,9 @@ release-ci-beta = ["tauri/custom-protocol"] ignored = [ "hickory-client", "hickory-proto", + "openssl", "libsqlite3-sys", "log4rs", "minotari_wallet_grpc_client", - "openssl", "xz2", ] From 00b3908436e4204f652e2c198a4c1f16f64a2851 Mon Sep 17 00:00:00 2001 From: shan <47271333+shanimal08@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:12:01 +0200 Subject: [PATCH 26/34] fix: autoupdate on V2 (#1188) Description --- - set up `tauri-plugin-process` correctly for relaunch after install - adjusted the check for updates - adjusted the update handler Motivation and Context --- autoupdate didn't work properly in V2 branch How Has This Been Tested? --- locally. painstakingly. --- .updater/alpha-latest.json | 42 +++---- .updater/latest.json | 2 +- package-lock.json | 4 +- package.json | 2 +- src-tauri/Cargo.lock | 11 ++ src-tauri/Cargo.toml | 1 + src-tauri/capabilities/default.json | 38 +++--- src-tauri/src/main.rs | 1 + src/App/AppWrapper.tsx | 10 +- .../AutoUpdateDialog/AutoUpdateDialog.tsx | 22 +++- .../AutoUpdateDialog/UpdatedStatus.tsx | 4 +- src/hooks/app/useUpdateStatus.ts | 118 +++++++++--------- 12 files changed, 145 insertions(+), 110 deletions(-) diff --git a/.updater/alpha-latest.json b/.updater/alpha-latest.json index 9fe1ee5cf..985988009 100644 --- a/.updater/alpha-latest.json +++ b/.updater/alpha-latest.json @@ -1,23 +1,23 @@ { - "version": "0.1.0", - "notes": "Tari Universe - See the assets to download this version and install", - "pub_date": "2024-10-01T10:21:09.614Z", - "platforms": { - "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVRbUtvKzlyYWhiOGJtelJoWTkrQVpxS3NkRHZpaTgwaGc0K0ZleTEwb2RwQWlyNmRhRnNDaVBFMDI0OUhmUFEwNmtvV2dyRGRlOUlINmlERXlJNTduY2NpdU9XQytqWHdJPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI3Nzc3MzY5CWZpbGU6dGFyaS11bml2ZXJzZV8wLjUuNl9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKZEN5ODMrREZycHlEaTZqN2pQM090Uk5lWHZkMnlEWXhYUFgwSDV2bjRuaVlGWHBzMW53WHFvYXY5b2ptSUUvUkUzU0IydXp2aHVGRWtKVUpscW9PQmc9PQo=", - "url": "https://github.com/tari-project/universe/releases/download/v0.5.6/tari-universe_0.5.6_amd64.AppImage.tar.gz" - }, - "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVRbUtvKzlyYWhiOFZkV2ZmdG1ZSFE1WGFPWVVSUm5SOG1Nb0hpU2ZvckZzaStEZEtsWlQ4RVQwMWRCc1l0QTFjNVNpb2x4MnJVWmtZVVJqbDlaZHVCNTE1M2t3Wkg4MkFrPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI3Nzc3NTI3CWZpbGU6VGFyaSBVbml2ZXJzZS5hcHAudGFyLmd6CnRLU3NOT202VU5xQUNvUWgxVzRqNlNwZ3lKbUIxZ3I2Ukd2R3hianlRazcvU3docWllNmUxa01JUUNkcnUzeWxIK0xIN3RlQmJkdllCM05yTGswWUNnPT0K", - "url": "https://github.com/tari-project/universe/releases/download/v0.5.6/Tari.Universe_universal.app.tar.gz" - }, - "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVRbUtvKzlyYWhiOFZkV2ZmdG1ZSFE1WGFPWVVSUm5SOG1Nb0hpU2ZvckZzaStEZEtsWlQ4RVQwMWRCc1l0QTFjNVNpb2x4MnJVWmtZVVJqbDlaZHVCNTE1M2t3Wkg4MkFrPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI3Nzc3NTI3CWZpbGU6VGFyaSBVbml2ZXJzZS5hcHAudGFyLmd6CnRLU3NOT202VU5xQUNvUWgxVzRqNlNwZ3lKbUIxZ3I2Ukd2R3hianlRazcvU3docWllNmUxa01JUUNkcnUzeWxIK0xIN3RlQmJkdllCM05yTGswWUNnPT0K", - "url": "https://github.com/tari-project/universe/releases/download/v0.5.6/Tari.Universe_universal.app.tar.gz" - }, - "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVRbUtvKzlyYWhiOGY5RHBGU0lPVC9vL092TzF2Z1hPNEkwUnltVEJabW1JWGpwUi9EaFN6WkJydW9HMXFQQlVGYit5dmhMemQzOXA1V3BPQlNsaEpvNEl5bnhqangwS2dFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI3Nzc4MDY2CWZpbGU6VGFyaSBVbml2ZXJzZV8wLjUuNl94NjRfZW4tVVMubXNpLnppcApobm4yNGM2VDhlUjRibnl0THpZTEl1ajhzQm54dllwLzcxbzNVeU5UU2FmSXVpTVlCUmNrWWdZUDN6QjhVWVhDZGcrVDB2ekZPemFLdGFVOXNYMW5Cdz09Cg==", - "url": "https://github.com/tari-project/universe/releases/download/v0.5.6/Tari.Universe_0.5.6_x64_en-US.msi.zip" + "version": "0.1.0", + "notes": "Tari Universe - See the assets to download this version and install", + "pub_date": "2024-10-01T10:21:09.614Z", + "platforms": { + "linux-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVRbUtvKzlyYWhiOGJtelJoWTkrQVpxS3NkRHZpaTgwaGc0K0ZleTEwb2RwQWlyNmRhRnNDaVBFMDI0OUhmUFEwNmtvV2dyRGRlOUlINmlERXlJNTduY2NpdU9XQytqWHdJPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI3Nzc3MzY5CWZpbGU6dGFyaS11bml2ZXJzZV8wLjUuNl9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKZEN5ODMrREZycHlEaTZqN2pQM090Uk5lWHZkMnlEWXhYUFgwSDV2bjRuaVlGWHBzMW53WHFvYXY5b2ptSUUvUkUzU0IydXp2aHVGRWtKVUpscW9PQmc9PQo=", + "url": "https://github.com/tari-project/universe/releases/download/v0.5.6/tari-universe_0.5.6_amd64.AppImage.tar.gz" + }, + "darwin-aarch64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVRbUtvKzlyYWhiOFZkV2ZmdG1ZSFE1WGFPWVVSUm5SOG1Nb0hpU2ZvckZzaStEZEtsWlQ4RVQwMWRCc1l0QTFjNVNpb2x4MnJVWmtZVVJqbDlaZHVCNTE1M2t3Wkg4MkFrPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI3Nzc3NTI3CWZpbGU6VGFyaSBVbml2ZXJzZS5hcHAudGFyLmd6CnRLU3NOT202VU5xQUNvUWgxVzRqNlNwZ3lKbUIxZ3I2Ukd2R3hianlRazcvU3docWllNmUxa01JUUNkcnUzeWxIK0xIN3RlQmJkdllCM05yTGswWUNnPT0K", + "url": "https://github.com/tari-project/universe/releases/download/v0.5.6/Tari.Universe_universal.app.tar.gz" + }, + "darwin-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVRbUtvKzlyYWhiOFZkV2ZmdG1ZSFE1WGFPWVVSUm5SOG1Nb0hpU2ZvckZzaStEZEtsWlQ4RVQwMWRCc1l0QTFjNVNpb2x4MnJVWmtZVVJqbDlaZHVCNTE1M2t3Wkg4MkFrPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI3Nzc3NTI3CWZpbGU6VGFyaSBVbml2ZXJzZS5hcHAudGFyLmd6CnRLU3NOT202VU5xQUNvUWgxVzRqNlNwZ3lKbUIxZ3I2Ukd2R3hianlRazcvU3docWllNmUxa01JUUNkcnUzeWxIK0xIN3RlQmJkdllCM05yTGswWUNnPT0K", + "url": "https://github.com/tari-project/universe/releases/download/v0.5.6/Tari.Universe_universal.app.tar.gz" + }, + "windows-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVRbUtvKzlyYWhiOGY5RHBGU0lPVC9vL092TzF2Z1hPNEkwUnltVEJabW1JWGpwUi9EaFN6WkJydW9HMXFQQlVGYit5dmhMemQzOXA1V3BPQlNsaEpvNEl5bnhqangwS2dFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI3Nzc4MDY2CWZpbGU6VGFyaSBVbml2ZXJzZV8wLjUuNl94NjRfZW4tVVMubXNpLnppcApobm4yNGM2VDhlUjRibnl0THpZTEl1ajhzQm54dllwLzcxbzNVeU5UU2FmSXVpTVlCUmNrWWdZUDN6QjhVWVhDZGcrVDB2ekZPemFLdGFVOXNYMW5Cdz09Cg==", + "url": "https://github.com/tari-project/universe/releases/download/v0.5.6/Tari.Universe_0.5.6_x64_en-US.msi.zip" + } } - } -} \ No newline at end of file +} diff --git a/.updater/latest.json b/.updater/latest.json index f4ef9fc02..e0b8d8b8f 100644 --- a/.updater/latest.json +++ b/.updater/latest.json @@ -20,4 +20,4 @@ "url": "https://github.com/tari-project/universe/releases/download/v0.8.2/Tari.Universe_0.8.2_x64_en-US.msi.zip" } } -} \ No newline at end of file +} diff --git a/package-lock.json b/package-lock.json index 80570d817..6907a2087 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "tari-universe", - "version": "0.8.4", + "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "tari-universe", - "version": "0.8.4", + "version": "0.0.1", "dependencies": { "@floating-ui/react": "^0.26.28", "@lottiefiles/dotlottie-react": "^0.10.1", diff --git a/package.json b/package.json index 77af0868b..bfca0bcf6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "tari-universe", "private": true, - "version": "0.8.4", + "version": "0.8.0", "type": "module", "scripts": { "dev": "vite dev --mode development", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index b125ed4bf..e878657f8 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -6814,6 +6814,7 @@ dependencies = [ "tauri", "tauri-build", "tauri-plugin-os", + "tauri-plugin-process", "tauri-plugin-sentry", "tauri-plugin-shell", "tauri-plugin-single-instance", @@ -7431,6 +7432,16 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "tauri-plugin-process" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae06a00087c148962a52814a2d7265b1a0505bced5ffb74f8c284a5f96a4d03d" +dependencies = [ + "tauri", + "tauri-plugin", +] + [[package]] name = "tauri-plugin-sentry" version = "0.2.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 80cc83e34..1ee054fe0 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -91,6 +91,7 @@ tokio-util = { version = "0.7.11", features = ["compat"] } xz2 = { version = "0.1.7", features = ["static"] } # static bind lzma zip = "2.2.0" dirs = "5.0.1" +tauri-plugin-process = "2" [target.'cfg(windows)'.dependencies] winreg = "0.52.0" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 463e35da9..540160433 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -1,19 +1,21 @@ { - "identifier": "default", - "windows": ["main"], - "permissions": [ - "core:path:default", - "core:event:default", - "core:window:default", - "core:app:default", - "core:resources:default", - "core:menu:default", - "core:tray:default", - "core:window:allow-close", - "core:window:allow-destroy", - "core:window:allow-minimize", - "core:window:allow-unminimize", - "shell:allow-open", - "sentry:default" - ] -} \ No newline at end of file + "identifier": "default", + "windows": ["main"], + "permissions": [ + "core:path:default", + "core:event:default", + "core:window:default", + "core:app:default", + "core:resources:default", + "core:menu:default", + "core:tray:default", + "core:window:allow-close", + "core:window:allow-destroy", + "core:window:allow-minimize", + "core:window:allow-unminimize", + "shell:allow-open", + "sentry:default", + "process:allow-restart", + "process:default" + ] +} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 38fce6845..f721dfd9d 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -619,6 +619,7 @@ fn main() { }; let app = tauri::Builder::default() + .plugin(tauri_plugin_process::init()) .plugin(tauri_plugin_sentry::init_with_no_injection(&client)) .plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_shell::init()) diff --git a/src/App/AppWrapper.tsx b/src/App/AppWrapper.tsx index f1575eff0..015ff18e2 100644 --- a/src/App/AppWrapper.tsx +++ b/src/App/AppWrapper.tsx @@ -5,11 +5,12 @@ import { IGNORE_FETCHING } from '@app/App/sentryIgnore'; import { initSystray } from '@app/utils'; import { + useCheckUpdate, useDetectMode, useDisableRefresh, + useInterval, useLangaugeResolver, useListenForExternalDependencies, - useUpdateListener, } from '@app/hooks'; import packageInfo from '../../package.json'; @@ -39,14 +40,16 @@ const sentryOptions = { setupLogger(); +const UPDATE_CHECK_INTERVAL = 1000 * 60 * 60; // 1 hour + export default function AppWrapper() { const allowTelemetry = useAppConfigStore((s) => s.allow_telemetry); const fetchAppConfig = useAppConfigStore((s) => s.fetchAppConfig); const setMiningNetwork = useMiningStore((s) => s.setMiningNetwork); + const checkUpdateTariUniverse = useCheckUpdate(); useDetectMode(); useDisableRefresh(); - useUpdateListener(); useLangaugeResolver(); useListenForExternalDependencies(); useListenForCriticalProblem(); @@ -54,6 +57,7 @@ export default function AppWrapper() { useEffect(() => { async function initialize() { await fetchAppConfig(); + checkUpdateTariUniverse(); // first check await initSystray(); await setMiningNetwork(); } @@ -69,5 +73,7 @@ export default function AppWrapper() { } }, [allowTelemetry]); + useInterval(() => checkUpdateTariUniverse(), UPDATE_CHECK_INTERVAL); + return ; } diff --git a/src/containers/floating/AutoUpdateDialog/AutoUpdateDialog.tsx b/src/containers/floating/AutoUpdateDialog/AutoUpdateDialog.tsx index be4196bd2..0188ba249 100644 --- a/src/containers/floating/AutoUpdateDialog/AutoUpdateDialog.tsx +++ b/src/containers/floating/AutoUpdateDialog/AutoUpdateDialog.tsx @@ -9,22 +9,36 @@ import { Typography } from '@app/components/elements/Typography'; import { UpdatedStatus } from './UpdatedStatus'; import { ButtonsWrapper } from './AutoUpdateDialog.styles'; +import { useEffect, useRef } from 'react'; export default function AutoUpdateDialog() { + const hasFetched = useRef(false); + const { handleUpdate, fetchUpdate, updateData, isLoading, contentLength, downloaded, handleClose } = + useHandleUpdate(); const { t } = useTranslation('setup-view', { useSuspense: false }); - const { latestVersion, contentLength, downloaded, handleUpdate, handleClose, isLoading } = useHandleUpdate(); + const open = useUIStore((s) => s.dialogToShow === 'autoUpdate'); - const subtitle = isLoading ? 'installing-latest-version' : 'would-you-like-to-install'; + useEffect(() => { + if (hasFetched.current) return; + fetchUpdate().then(() => { + hasFetched.current = true; + }); + }, [fetchUpdate]); + const subtitle = isLoading ? 'installing-latest-version' : 'would-you-like-to-install'; return ( {t('new-tari-version-available')} - {t(subtitle, { version: latestVersion })} + {t(subtitle, { version: updateData?.version })} {isLoading && } + + {downloaded > 0 && downloaded === contentLength ? ( + {`Update downloaded: Restarting Tari Universe`} + ) : null} - {!isLoading && ( + {!isLoading && updateData && ( <> handleClose()} color="warning"> {t('no')} diff --git a/src/containers/floating/AutoUpdateDialog/UpdatedStatus.tsx b/src/containers/floating/AutoUpdateDialog/UpdatedStatus.tsx index 356851c6f..f93d8f4b8 100644 --- a/src/containers/floating/AutoUpdateDialog/UpdatedStatus.tsx +++ b/src/containers/floating/AutoUpdateDialog/UpdatedStatus.tsx @@ -19,9 +19,9 @@ export function UpdatedStatus({ contentLength, downloaded }: UpdatedStatusProps) const shouldShowProgress = contentLength > 0; return ( - + - + {shouldShowProgress && ( {`${formatSize(downloaded)} / ${formatSize(contentLength)}`} diff --git a/src/hooks/app/useUpdateStatus.ts b/src/hooks/app/useUpdateStatus.ts index aa90092fb..af53e6811 100644 --- a/src/hooks/app/useUpdateStatus.ts +++ b/src/hooks/app/useUpdateStatus.ts @@ -1,23 +1,19 @@ -import * as Sentry from '@sentry/react'; -import { useCallback, useEffect, useRef, useState } from 'react'; +import { useCallback, useState } from 'react'; import { check, Update } from '@tauri-apps/plugin-updater'; import { relaunch } from '@tauri-apps/plugin-process'; import { useAppStateStore } from '@app/store/appStateStore'; import { useAppConfigStore } from '@app/store/useAppConfigStore'; import { useUIStore } from '@app/store/useUIStore'; -import { useInterval } from '../helpers/useInterval'; - -const UPDATE_CHECK_INTERVAL = 1000 * 60 * 60; // 1 hour export const useHandleUpdate = () => { const setIsAfterAutoUpdate = useAppStateStore((s) => s.setIsAfterAutoUpdate); + const setError = useAppStateStore((s) => s.setError); const auto_update = useAppConfigStore((s) => s.auto_update); - const [latestVersion, setLatestVersion] = useState(); + const [updateData, setUpdateData] = useState(); const [isLoading, setIsLoading] = useState(false); const [contentLength, setContentLength] = useState(0); const [downloaded, setDownloaded] = useState(0); - const [update, setUpdate] = useState(); const setDialogToShow = useUIStore((s) => s.setDialogToShow); const handleClose = useCallback(() => { @@ -26,65 +22,69 @@ export const useHandleUpdate = () => { }, [setIsAfterAutoUpdate, setDialogToShow]); const handleUpdate = useCallback(async () => { - if (!update) { - return; - } + if (!updateData) return; setIsLoading(true); console.info('Installing latest version of Tari Universe'); - await update.downloadAndInstall((event) => { - switch (event.event) { - case 'Started': - setContentLength(event.data.contentLength || 0); - break; - case 'Progress': - setDownloaded((c) => c + event.data.chunkLength); - break; - case 'Finished': - console.info('download finished'); - break; - } - }); - handleClose(); - await relaunch(); - }, [handleClose, update]); - - const checkUpdateTariUniverse = useCallback(async () => { - try { - const updateRes = await check(); - if (updateRes?.available) { - setUpdate(updateRes); - console.info(`New Tari Universe version: ${updateRes.version} available`); - console.info(`Release notes: ${updateRes.body}`); - setLatestVersion(updateRes.version); - if (auto_update) { - console.info('Proceed with auto-update'); - await handleUpdate(); + updateData + .downloadAndInstall(async (event) => { + switch (event.event) { + case 'Started': + setContentLength(event.data.contentLength || 0); + break; + case 'Progress': + setDownloaded((c) => c + event.data.chunkLength); + break; + case 'Finished': + console.info('download finished'); + break; } - setDialogToShow('autoUpdate'); - } else { - setIsAfterAutoUpdate(true); + }) + .then(async () => { + handleClose(); + await relaunch(); + }) + .catch((e) => { + console.error(e); + setError(e); + }); + }, [handleClose, setError, updateData]); + + const fetchUpdate = useCallback(async () => { + const update = await check(); + if (update) { + setUpdateData(update); + + if (auto_update) { + await handleUpdate(); } - } catch (error) { - Sentry.captureException(error); - console.error('AutoUpdate error:', error); - setIsAfterAutoUpdate(true); } - }, [auto_update, handleUpdate, setIsAfterAutoUpdate, setDialogToShow]); + }, [auto_update, handleUpdate]); - return { checkUpdateTariUniverse, handleUpdate, isLoading, handleClose, latestVersion, contentLength, downloaded }; + return { + fetchUpdate, + handleUpdate, + updateData, + isLoading, + contentLength, + handleClose, + downloaded, + }; }; -export function useUpdateListener() { - const { checkUpdateTariUniverse } = useHandleUpdate(); - const hasDoneInitialCheck = useRef(false); - - useInterval(() => checkUpdateTariUniverse(), UPDATE_CHECK_INTERVAL); +export const useCheckUpdate = () => { + const setIsAfterAutoUpdate = useAppStateStore((s) => s.setIsAfterAutoUpdate); + const setDialogToShow = useUIStore((s) => s.setDialogToShow); - useEffect(() => { - if (hasDoneInitialCheck.current) return; - checkUpdateTariUniverse().then(() => { - hasDoneInitialCheck.current = true; - }); - }, [checkUpdateTariUniverse]); -} + return useCallback(() => { + check() + .then((updateRes) => { + if (updateRes && updateRes.available) { + setDialogToShow('autoUpdate'); + } else { + setIsAfterAutoUpdate(true); + } + }) + .catch(() => setIsAfterAutoUpdate(true)); + }, [setDialogToShow, setIsAfterAutoUpdate]); +}; From b36da7455f911617ef4496c032ef115d69fe7ad1 Mon Sep 17 00:00:00 2001 From: Shannon Tenner Date: Thu, 5 Dec 2024 11:37:40 +0200 Subject: [PATCH 27/34] fixes after merge --- .../floating/Settings/sections/experimental/P2poolMarkup.tsx | 2 +- .../floating/Settings/sections/releaseNotes/ReleaseNotes.tsx | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/containers/floating/Settings/sections/experimental/P2poolMarkup.tsx b/src/containers/floating/Settings/sections/experimental/P2poolMarkup.tsx index 627af6e0c..3d162d3e7 100644 --- a/src/containers/floating/Settings/sections/experimental/P2poolMarkup.tsx +++ b/src/containers/floating/Settings/sections/experimental/P2poolMarkup.tsx @@ -16,7 +16,7 @@ import { SettingsGroupTitle, SettingsGroupAction, } from '../../components/SettingsGroup.styles'; -import { invoke } from '@tauri-apps/api/tauri'; +import { invoke } from '@tauri-apps/api/core'; export const ErrorTypography = styled(Typography)(({ theme }) => ({ color: theme.palette.error.main, diff --git a/src/containers/floating/Settings/sections/releaseNotes/ReleaseNotes.tsx b/src/containers/floating/Settings/sections/releaseNotes/ReleaseNotes.tsx index af5107f10..47c8488a9 100644 --- a/src/containers/floating/Settings/sections/releaseNotes/ReleaseNotes.tsx +++ b/src/containers/floating/Settings/sections/releaseNotes/ReleaseNotes.tsx @@ -16,7 +16,7 @@ import tariIcon from './tari-icon.png'; import packageInfo from '../../../../../../package.json'; import { useTranslation } from 'react-i18next'; import { useUIStore } from '@app/store/useUIStore'; -import { checkUpdate } from '@tauri-apps/api/updater'; +import { check } from '@tauri-apps/plugin-updater'; const appVersion = packageInfo.version; const versionString = `v${appVersion}`; @@ -77,7 +77,8 @@ export const ReleaseNotes = () => { useEffect(() => { const checkForUpdates = async () => { - const { shouldUpdate } = await checkUpdate(); + const update = await check(); + const shouldUpdate = !!update?.available; setNeedsUpgrade(shouldUpdate); }; From 3588ae05a6efaae1f269c252785fc8b83bf05675 Mon Sep 17 00:00:00 2001 From: Misieq01 Date: Thu, 5 Dec 2024 11:32:10 +0100 Subject: [PATCH 28/34] fix wallet creation crash --- src-tauri/Cargo.toml | 1 - src-tauri/src/internal_wallet.rs | 10 +++++++++- src-tauri/src/node_adapter.rs | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index aa2ce289c..be1fe9157 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -44,7 +44,6 @@ monero-address-creator = { git = "https://github.com/tari-project/monero-address nix = { version = "0.29.0", features = ["signal"] } nvml-wrapper = "0.10.0" open = "5" -openssl = { version = "0.10", features = ["vendored"] } phraze = "0.3.15" rand = "0.8.5" regex = "1.10.5" diff --git a/src-tauri/src/internal_wallet.rs b/src-tauri/src/internal_wallet.rs index 3b8d63e63..14de53cde 100644 --- a/src-tauri/src/internal_wallet.rs +++ b/src-tauri/src/internal_wallet.rs @@ -25,7 +25,7 @@ use tari_key_manager::mnemonic_wordlists::MNEMONIC_ENGLISH_WORDS; use tari_key_manager::SeedWords; use tari_utilities::hex::Hex; -use crate::credential_manager::CredentialManager; +use crate::credential_manager::{Credential, CredentialError, CredentialManager}; const KEY_MANAGER_COMMS_SECRET_KEY_BRANCH_KEY: &str = "comms"; const LOG_TARGET: &str = "tari::universe::internal_wallet"; @@ -163,6 +163,14 @@ impl InternalWallet { creds.tari_seed_passphrase } }, + Err(CredentialError::NoEntry(_)) => { + let credentials = Credential { + tari_seed_passphrase: Some(SafePassword::from(generate_password(32))), + monero_seed: None, + }; + cm.set_credentials(&credentials)?; + credentials.tari_seed_passphrase + } Err(_) => { return Err(anyhow!( "Credentials didn't exist, and this shouldn't happen" diff --git a/src-tauri/src/node_adapter.rs b/src-tauri/src/node_adapter.rs index 9554f20d6..725b256bd 100644 --- a/src-tauri/src/node_adapter.rs +++ b/src-tauri/src/node_adapter.rs @@ -502,6 +502,7 @@ impl MinotariNodeStatusMonitor { } pub async fn list_connected_peers(&self) -> Result, Error> { + info!(target: LOG_TARGET, "Listing connected peers"); let mut client = BaseNodeGrpcClient::connect(format!("http://127.0.0.1:{}", self.grpc_port)).await?; let connected_peers = client.list_connected_peers(Empty {}).await?; From 1759140e533291028d4bde0820c146942d28e63e Mon Sep 17 00:00:00 2001 From: Misieq01 Date: Thu, 5 Dec 2024 12:41:40 +0100 Subject: [PATCH 29/34] Fix longer shutdowns --- src-tauri/src/main.rs | 14 +++++++++++--- src-tauri/src/utils/shutdown_utils.rs | 10 +++++----- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 38fce6845..ffb1e056e 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -456,8 +456,13 @@ async fn setup_inner( tauri::async_runtime::spawn(async move { let mut interval: time::Interval = time::interval(Duration::from_secs(1)); loop { - interval.tick().await; let app_state = move_handle.state::().clone(); + + if app_state.shutdown.is_triggered() { + break; + } + + interval.tick().await; if let Ok(metrics_ret) = commands::get_miner_metrics(app_state).await { drop(move_handle.clone().emit("miner_metrics", metrics_ret)); } @@ -470,9 +475,12 @@ async fn setup_inner( let mut has_send_error = false; loop { - interval.tick().await; - let state = app_handle_clone.state::().inner(); + if state.shutdown.is_triggered() { + break; + } + + interval.tick().await; let check_if_orphan = state .node_manager .check_if_is_orphan_chain(!has_send_error) diff --git a/src-tauri/src/utils/shutdown_utils.rs b/src-tauri/src/utils/shutdown_utils.rs index 7953f715a..8046d7a49 100644 --- a/src-tauri/src/utils/shutdown_utils.rs +++ b/src-tauri/src/utils/shutdown_utils.rs @@ -9,11 +9,11 @@ pub async fn stop_all_processes( should_shutdown: bool, ) -> Result<(), String> { info!(target: LOG_TARGET, "Stopping all miners"); - info!(target: LOG_TARGET, "Entering shutdown sequence"); let state = app_handle.state::().inner(); - if should_shutdown { + if should_shutdown && !state.shutdown.is_triggered() { + info!(target: LOG_TARGET, "Entering shutdown sequence"); state.shutdown.clone().trigger(); } @@ -31,8 +31,8 @@ pub async fn stop_all_processes( if cpu_miner_is_running || cpu_miner_pid_file_exists { cpu_miner.stop().await.map_err(|e| e.to_string())?; - drop(cpu_miner); } + drop(cpu_miner); let gpu_miner = state.gpu_miner.read().await; let gpu_miner_pid_file_exists = gpu_miner.is_pid_file_exists(base_path.clone()).await; @@ -42,8 +42,8 @@ pub async fn stop_all_processes( if gpu_miner_is_running || gpu_miner_pid_file_exists { gpu_miner.stop().await.map_err(|e| e.to_string())?; - drop(gpu_miner); } + drop(gpu_miner); let wallet_manager = state.wallet_manager.clone(); let wallet_manager_is_running = wallet_manager.is_running().await; @@ -96,7 +96,7 @@ pub async fn stop_all_processes( tor_manager.stop().await.map_err(|e| e.to_string())?; } - if should_shutdown { + if should_shutdown && !state.shutdown.is_triggered() { state.shutdown.clone().trigger(); } From 69749bb8c1fd4c893cb4a71ba92b6b5a0818549e Mon Sep 17 00:00:00 2001 From: Misieq01 Date: Thu, 5 Dec 2024 12:42:02 +0100 Subject: [PATCH 30/34] remove unnecessary thread spawn --- src-tauri/src/commands.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 8b781f5c2..e36e258cb 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -686,21 +686,19 @@ pub async fn import_seed_words( stop_all_processes(app.clone(), false).await?; - tauri::async_runtime::spawn(async move { - match InternalWallet::create_from_seed(config_path, seed_words).await { - Ok(_wallet) => { - InternalWallet::clear_wallet_local_data(data_dir) - .await - .map_err(|e| e.to_string())?; - info!(target: LOG_TARGET, "[import_seed_words] Restarting the app"); - app.restart(); - } - Err(e) => { - error!(target: LOG_TARGET, "Error loading internal wallet: {:?}", e); - Err::<(), std::string::String>(e.to_string()) - } + match InternalWallet::create_from_seed(config_path, seed_words).await { + Ok(_wallet) => { + InternalWallet::clear_wallet_local_data(data_dir) + .await + .map_err(|e| e.to_string())?; + info!(target: LOG_TARGET, "[import_seed_words] Restarting the app"); + app.restart(); } - }); + Err(e) => { + error!(target: LOG_TARGET, "Error loading internal wallet: {:?}", e); + e.to_string() + } + }; if timer.elapsed() > MAX_ACCEPTABLE_COMMAND_TIME { warn!(target: LOG_TARGET, "import_seed_words took too long: {:?}", timer.elapsed()); From 2f8011de444c75a147f393963b97b0a98bf7db0c Mon Sep 17 00:00:00 2001 From: Misieq01 Date: Thu, 5 Dec 2024 12:59:05 +0100 Subject: [PATCH 31/34] remove log --- src-tauri/src/node_adapter.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src-tauri/src/node_adapter.rs b/src-tauri/src/node_adapter.rs index 725b256bd..9554f20d6 100644 --- a/src-tauri/src/node_adapter.rs +++ b/src-tauri/src/node_adapter.rs @@ -502,7 +502,6 @@ impl MinotariNodeStatusMonitor { } pub async fn list_connected_peers(&self) -> Result, Error> { - info!(target: LOG_TARGET, "Listing connected peers"); let mut client = BaseNodeGrpcClient::connect(format!("http://127.0.0.1:{}", self.grpc_port)).await?; let connected_peers = client.list_connected_peers(Empty {}).await?; From 00d55e4caf0fb53799bf7444a5d2b617961192cc Mon Sep 17 00:00:00 2001 From: Misieq01 Date: Thu, 5 Dec 2024 13:30:36 +0100 Subject: [PATCH 32/34] fix gpu_detection and gpu_status generation --- src-tauri/src/gpu_miner.rs | 10 +++++++--- src-tauri/src/hardware/hardware_status_monitor.rs | 6 +++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src-tauri/src/gpu_miner.rs b/src-tauri/src/gpu_miner.rs index 4098c8896..850ce9bc6 100644 --- a/src-tauri/src/gpu_miner.rs +++ b/src-tauri/src/gpu_miner.rs @@ -163,16 +163,20 @@ impl GpuMiner { pub async fn detect(&mut self, config_dir: PathBuf) -> Result<(), anyhow::Error> { info!(target: LOG_TARGET, "Verify if gpu miner can work on the system"); - let output_file = config_dir + let config_file = config_dir.join("gpuminer").join("config.json").to_string_lossy().to_string(); + let gpu_status_file = config_dir .join("gpuminer") .join("gpu_status.json") .to_string_lossy() .to_string(); + let args: Vec = vec![ "--detect".to_string(), "true".to_string(), + "--config".to_string(), + config_file.clone(), "--gpu-status-file".to_string(), - output_file.clone(), + gpu_status_file.clone(), ]; let gpuminer_bin = BinaryResolver::current() .read() @@ -184,7 +188,7 @@ impl GpuMiner { let child = process_utils::launch_child_process(&gpuminer_bin, &config_dir, None, &args)?; let output = child.wait_with_output().await?; info!(target: LOG_TARGET, "Gpu detect exit code: {:?}", output.status.code().unwrap_or_default()); - let gpu_settings = std::fs::read_to_string(output_file)?; + let gpu_settings = std::fs::read_to_string(gpu_status_file)?; let gpu_settings: GpuStatusJson = serde_json::from_str(&gpu_settings)?; self.gpu_devices = gpu_settings.gpu_devices; match output.status.code() { diff --git a/src-tauri/src/hardware/hardware_status_monitor.rs b/src-tauri/src/hardware/hardware_status_monitor.rs index 7522e6bca..41ee37547 100644 --- a/src-tauri/src/hardware/hardware_status_monitor.rs +++ b/src-tauri/src/hardware/hardware_status_monitor.rs @@ -1,8 +1,8 @@ use std::{path::PathBuf, sync::LazyLock}; -use crate::hardware::{ +use crate::{hardware::{ cpu_readers::DefaultCpuParametersReader, gpu_readers::DefaultGpuParametersReader, -}; +}, APPLICATION_FOLDER_ID}; use super::{ cpu_readers::{ @@ -175,7 +175,7 @@ impl HardwareStatusMonitor { } async fn initialize_gpu_devices(&self) -> Result, Error> { - let config_dir = dirs::config_dir().expect("Could not get config dir"); + let config_dir = dirs::config_dir().expect("Could not get config dir").join(APPLICATION_FOLDER_ID); let gpu_status_file_content = self.load_gpu_devices_from_status_file(config_dir).await?; let mut platform_devices = Vec::new(); From 40f6af9f5d1935a7ee89d7ee018483ad5d087bb8 Mon Sep 17 00:00:00 2001 From: Misieq01 Date: Thu, 5 Dec 2024 15:34:57 +0100 Subject: [PATCH 33/34] cargo fmt --- src-tauri/src/gpu_miner.rs | 6 +++++- src-tauri/src/hardware/hardware_status_monitor.rs | 11 +++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src-tauri/src/gpu_miner.rs b/src-tauri/src/gpu_miner.rs index 850ce9bc6..29ce41f57 100644 --- a/src-tauri/src/gpu_miner.rs +++ b/src-tauri/src/gpu_miner.rs @@ -163,7 +163,11 @@ impl GpuMiner { pub async fn detect(&mut self, config_dir: PathBuf) -> Result<(), anyhow::Error> { info!(target: LOG_TARGET, "Verify if gpu miner can work on the system"); - let config_file = config_dir.join("gpuminer").join("config.json").to_string_lossy().to_string(); + let config_file = config_dir + .join("gpuminer") + .join("config.json") + .to_string_lossy() + .to_string(); let gpu_status_file = config_dir .join("gpuminer") .join("gpu_status.json") diff --git a/src-tauri/src/hardware/hardware_status_monitor.rs b/src-tauri/src/hardware/hardware_status_monitor.rs index 41ee37547..124689e15 100644 --- a/src-tauri/src/hardware/hardware_status_monitor.rs +++ b/src-tauri/src/hardware/hardware_status_monitor.rs @@ -1,8 +1,9 @@ use std::{path::PathBuf, sync::LazyLock}; -use crate::{hardware::{ - cpu_readers::DefaultCpuParametersReader, gpu_readers::DefaultGpuParametersReader, -}, APPLICATION_FOLDER_ID}; +use crate::{ + hardware::{cpu_readers::DefaultCpuParametersReader, gpu_readers::DefaultGpuParametersReader}, + APPLICATION_FOLDER_ID, +}; use super::{ cpu_readers::{ @@ -175,7 +176,9 @@ impl HardwareStatusMonitor { } async fn initialize_gpu_devices(&self) -> Result, Error> { - let config_dir = dirs::config_dir().expect("Could not get config dir").join(APPLICATION_FOLDER_ID); + let config_dir = dirs::config_dir() + .expect("Could not get config dir") + .join(APPLICATION_FOLDER_ID); let gpu_status_file_content = self.load_gpu_devices_from_status_file(config_dir).await?; let mut platform_devices = Vec::new(); From 38c88082e057ac2a501b58378c9f5d0c9449de3a Mon Sep 17 00:00:00 2001 From: Shannon Tenner Date: Thu, 5 Dec 2024 17:29:28 +0200 Subject: [PATCH 34/34] fix pubkey --- src-tauri/tauri.conf.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index e902df6b2..05a79b851 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -71,7 +71,7 @@ }, "plugins": { "updater": { - "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDM1MjBFNkFCQUZGOUFGODEKUldTQnIvbXZxK1lnTmN5QlVrYWpkMnRDQXp5Z3pqVWl6L0lTZGlNY0E5dm51QkhUQXBNQ0haWXQK", + "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEYxNUJBOEFEQkQ4RjJBMjYKUldRbUtvKzlyYWhiOFJIUmFFditENVV3d3hRbjNlZm1DMi9aMjluRUpVdHhQTytadTV3ODN3bUMK", "endpoints": ["https://raw.githubusercontent.com/tari-project/universe/main/.updater/alpha-latest.json"], "windows": { "installMode": "passive"