From fc2b05b99876145208dbd222cabb35d89df8e96c Mon Sep 17 00:00:00 2001 From: Binarybaron Date: Wed, 20 Nov 2024 22:04:11 +0100 Subject: [PATCH] wip --- .../components/alert/DaemonStatusAlert.tsx | 90 ++++++++++--------- src-gui/src/store/features/rpcSlice.ts | 20 ++++- swap/src/cli/api.rs | 51 ++++++++++- swap/src/cli/api/tauri_bindings.rs | 40 ++++++--- swap/src/monero/wallet_rpc.rs | 29 +++--- 5 files changed, 161 insertions(+), 69 deletions(-) diff --git a/src-gui/src/renderer/components/alert/DaemonStatusAlert.tsx b/src-gui/src/renderer/components/alert/DaemonStatusAlert.tsx index 76f872c64..397635b70 100644 --- a/src-gui/src/renderer/components/alert/DaemonStatusAlert.tsx +++ b/src-gui/src/renderer/components/alert/DaemonStatusAlert.tsx @@ -1,6 +1,5 @@ import { Box, Button, LinearProgress, makeStyles } from "@material-ui/core"; import { Alert } from "@material-ui/lab"; -import { TauriContextInitializationProgress } from "models/tauriModel"; import { useNavigate } from "react-router-dom"; import { useAppSelector } from "store/hooks"; import { exhaustiveGuard } from "utils/typescriptUtils"; @@ -20,51 +19,60 @@ export default function DaemonStatusAlert() { const contextStatus = useAppSelector((s) => s.rpc.status); const navigate = useNavigate(); - if (contextStatus === null) { + if (contextStatus === null || contextStatus.type === "NotInitialized") { return Checking for available remote nodes; } switch (contextStatus.type) { case "Initializing": - switch (contextStatus.content.type) { - case "OpeningBitcoinWallet": - return ( - - Connecting to the Bitcoin network - - ); - case "DownloadingMoneroWalletRpc": - return ( - - - - Downloading and verifying the Monero wallet RPC ( - {bytesToMb(contextStatus.content.content.size).toFixed(2)} MB) - - - - - ); - case "OpeningMoneroWallet": - return ( - - Connecting to the Monero network - - ); - case "OpeningDatabase": - return ( - - Opening the local database - - ); - case "EstablishingTorCircuits": - return ( - - Connecting to the Tor network - - ); - } - break; + return contextStatus.content + .map((status) => { + if (status.progress.type === "Completed") { + return null; + } + + switch (status.componentName) { + case "OpeningBitcoinWallet": + return ( + + Syncing internal Bitcoin wallet + + ); + case "DownloadingMoneroWalletRpc": + return ( + + + + Downloading and verifying the Monero wallet RPC ( + {bytesToMb(status.progress.content.size).toFixed(2)} MB) + + + + + ); + case "OpeningMoneroWallet": + return ( + + Opening the Monero wallet + + ); + case "OpeningDatabase": + return ( + + Opening the local database + + ); + case "EstablishingTorCircuits": + return ( + + Establishing Tor circuits + + ) + default: + return exhaustiveGuard(status.componentName); + } + }) + .filter((s) => s !== null); case "Available": return The daemon is running; case "Failed": diff --git a/src-gui/src/store/features/rpcSlice.ts b/src-gui/src/store/features/rpcSlice.ts index 8eb612461..9fcc78146 100644 --- a/src-gui/src/store/features/rpcSlice.ts +++ b/src-gui/src/store/features/rpcSlice.ts @@ -69,10 +69,26 @@ export const rpcSlice = createSlice({ slice, action: PayloadAction, ) { - slice.status = action.payload; + // If we are already initializing, and we receive a new partial status, we update the existing status + if (slice.status?.type === "Initializing" && action.payload.type === "Initializing") { + for (const partialStatus of action.payload.content) { + // We find the existing status with the same type + const existingStatus = slice.status.content.find(s => s.componentName === partialStatus.componentName); + if (existingStatus) { + // If we find it, we update the content + existingStatus.progress = partialStatus.progress; + } else { + // Otherwise, we add the new partial status + slice.status.content.push(partialStatus); + } + } + } else { + // Otherwise, we replace the whole status + slice.status = action.payload; + } }, timelockChangeEventReceived( - slice, + slice: RPCSlice, action: PayloadAction ) { if (slice.state.swapInfos[action.payload.swap_id]) { diff --git a/swap/src/cli/api.rs b/swap/src/cli/api.rs index af87c8056..af80d4bf5 100644 --- a/swap/src/cli/api.rs +++ b/swap/src/cli/api.rs @@ -19,7 +19,7 @@ use std::future::Future; use std::path::PathBuf; use std::sync::{Arc, Mutex as SyncMutex, Once}; use tauri_bindings::{ - TauriContextInitializationProgress, TauriContextStatusEvent, TauriEmitter, TauriHandle, + PendingCompleted, TauriContextStatusEvent, TauriEmitter, TauriHandle, TauriPartialInitProgress, }; use tokio::sync::{broadcast, broadcast::Sender, Mutex as TokioMutex, RwLock}; use tokio::task::JoinHandle; @@ -315,10 +315,26 @@ impl ContextBuilder { Some(bitcoin) => { let (url, target_block) = bitcoin.apply_defaults(self.is_testnet)?; + self.tauri_handle.emit_context_init_progress_event( + TauriContextStatusEvent::Initializing(vec![ + TauriPartialInitProgress::OpeningBitcoinWallet( + PendingCompleted::Pending(()), + ), + ]), + ); + let wallet = init_bitcoin_wallet(url, &seed, data_dir.clone(), env_config, target_block) .await?; + self.tauri_handle.emit_context_init_progress_event( + TauriContextStatusEvent::Initializing(vec![ + TauriPartialInitProgress::OpeningBitcoinWallet( + PendingCompleted::Completed, + ), + ]), + ); + Ok::>, Error>(Some(Arc::new( wallet, ))) @@ -332,6 +348,14 @@ impl ContextBuilder { Some(monero) => { let monero_daemon_address = monero.apply_defaults(self.is_testnet); + self.tauri_handle.emit_context_init_progress_event( + TauriContextStatusEvent::Initializing(vec![ + TauriPartialInitProgress::OpeningMoneroWallet( + PendingCompleted::Pending(()), + ), + ]), + ); + let (wlt, prc) = init_monero_wallet( data_dir.clone(), monero_daemon_address, @@ -340,6 +364,14 @@ impl ContextBuilder { ) .await?; + self.tauri_handle.emit_context_init_progress_event( + TauriContextStatusEvent::Initializing(vec![ + TauriPartialInitProgress::OpeningMoneroWallet( + PendingCompleted::Completed, + ), + ]), + ); + Ok((Some(Arc::new(wlt)), Some(Arc::new(SyncMutex::new(prc))))) } None => Ok((None, None)), @@ -347,6 +379,14 @@ impl ContextBuilder { }; let initialize_tor_client = async { + self.tauri_handle.emit_context_init_progress_event( + TauriContextStatusEvent::Initializing(vec![ + TauriPartialInitProgress::EstablishingTorCircuits( + PendingCompleted::Pending(()), + ), + ]), + ); + let maybe_tor_client = init_tor_client(&data_dir) .await .inspect_err(|err| { @@ -354,6 +394,12 @@ impl ContextBuilder { }) .ok(); + self.tauri_handle.emit_context_init_progress_event( + TauriContextStatusEvent::Initializing(vec![ + TauriPartialInitProgress::EstablishingTorCircuits(PendingCompleted::Completed), + ]), + ); + Ok(maybe_tor_client) }; @@ -376,6 +422,9 @@ impl ContextBuilder { } } + self.tauri_handle + .emit_context_init_progress_event(TauriContextStatusEvent::Available); + let context = Context { db, bitcoin_wallet, diff --git a/swap/src/cli/api/tauri_bindings.rs b/swap/src/cli/api/tauri_bindings.rs index 9e2e4a523..0fe886886 100644 --- a/swap/src/cli/api/tauri_bindings.rs +++ b/swap/src/cli/api/tauri_bindings.rs @@ -111,19 +111,31 @@ impl TauriEmitter for Option { #[typeshare] #[derive(Display, Clone, Serialize)] #[serde(tag = "type", content = "content")] -pub enum TauriContextInitializationProgress { - OpeningBitcoinWallet, - DownloadingMoneroWalletRpc { - // Progress of the download in percent (0-100) - #[typeshare(serialized_as = "number")] - progress: u64, - // Size of the download file in bytes - #[typeshare(serialized_as = "number")] - size: u64, - }, - OpeningMoneroWallet, - OpeningDatabase, - EstablishingTorCircuits, +pub enum PendingCompleted

{ + Pending(P), + Completed, +} + +#[derive(Serialize, Clone)] +#[typeshare] +pub struct DownloadProgress { + // Progress of the download in percent (0-100) + #[typeshare(serialized_as = "number")] + pub progress: u64, + // Size of the download file in bytes + #[typeshare(serialized_as = "number")] + pub size: u64, +} + +#[typeshare] +#[derive(Display, Clone, Serialize)] +#[serde(tag = "componentName", content = "progress")] +pub enum TauriPartialInitProgress { + OpeningBitcoinWallet(PendingCompleted<()>), + DownloadingMoneroWalletRpc(PendingCompleted), + OpeningMoneroWallet(PendingCompleted<()>), + OpeningDatabase(PendingCompleted<()>), + EstablishingTorCircuits(PendingCompleted<()>), } #[typeshare] @@ -131,7 +143,7 @@ pub enum TauriContextInitializationProgress { #[serde(tag = "type", content = "content")] pub enum TauriContextStatusEvent { NotInitialized, - Initializing(TauriContextInitializationProgress), + Initializing(Vec), Available, Failed, } diff --git a/swap/src/monero/wallet_rpc.rs b/swap/src/monero/wallet_rpc.rs index 05e1633ca..1f7943c5b 100644 --- a/swap/src/monero/wallet_rpc.rs +++ b/swap/src/monero/wallet_rpc.rs @@ -22,7 +22,8 @@ use tokio_util::codec::{BytesCodec, FramedRead}; use tokio_util::io::StreamReader; use crate::cli::api::tauri_bindings::{ - TauriContextInitializationProgress, TauriContextStatusEvent, TauriEmitter, TauriHandle, + DownloadProgress, PendingCompleted, TauriPartialInitProgress, + TauriContextStatusEvent, TauriEmitter, TauriHandle, }; // See: https://www.moneroworld.com/#nodes, https://monero.fail @@ -264,10 +265,14 @@ impl WalletRpc { // Emit a tauri event to update the progress tauri_handle.emit_context_init_progress_event(TauriContextStatusEvent::Initializing( - TauriContextInitializationProgress::DownloadingMoneroWalletRpc { - progress: 0, - size: content_length, - }, + vec![ + TauriPartialInitProgress::DownloadingMoneroWalletRpc( + PendingCompleted::Pending(DownloadProgress { + progress: 0, + size: content_length, + }), + ), + ], )); let mut hasher = Sha256::new(); @@ -310,12 +315,14 @@ impl WalletRpc { // Emit a tauri event to update the progress tauri_handle.emit_context_init_progress_event( - TauriContextStatusEvent::Initializing( - TauriContextInitializationProgress::DownloadingMoneroWalletRpc { - progress: percent, - size: content_length, - }, - ), + TauriContextStatusEvent::Initializing(vec![ + TauriPartialInitProgress::DownloadingMoneroWalletRpc( + PendingCompleted::Pending(DownloadProgress { + progress: percent, + size: content_length, + }), + ), + ]), ); } file.write_all(&bytes).await?;