From 6f0d0602633b274f63968d5cdc6e17c6fe986cb9 Mon Sep 17 00:00:00 2001
From: binarybaron <86064887+binarybaron@users.noreply.github.com>
Date: Thu, 14 Nov 2024 19:20:45 +0100
Subject: [PATCH] feat(gui): Display progress of monero-wallet-rpc download
(#170)
---
.../components/alert/DaemonStatusAlert.tsx | 32 ++++++++++++++++---
src-gui/src/utils/conversionUtils.ts | 9 ++++--
swap/src/cli/api.rs | 12 +++++--
swap/src/cli/api/tauri_bindings.rs | 9 ++++++
swap/src/monero/wallet_rpc.rs | 27 +++++++++++++++-
5 files changed, 77 insertions(+), 12 deletions(-)
diff --git a/src-gui/src/renderer/components/alert/DaemonStatusAlert.tsx b/src-gui/src/renderer/components/alert/DaemonStatusAlert.tsx
index 35d82a1ff..c99b4692d 100644
--- a/src-gui/src/renderer/components/alert/DaemonStatusAlert.tsx
+++ b/src-gui/src/renderer/components/alert/DaemonStatusAlert.tsx
@@ -1,12 +1,22 @@
-import { Button } from "@material-ui/core";
+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";
import { LoadingSpinnerAlert } from "./LoadingSpinnerAlert";
+import { bytesToMb } from "utils/conversionUtils";
+
+const useStyles = makeStyles((theme) => ({
+ innerAlert: {
+ display: "flex",
+ flexDirection: "column",
+ gap: theme.spacing(2),
+ },
+}));
export default function DaemonStatusAlert() {
+ const classes = useStyles();
const contextStatus = useAppSelector((s) => s.rpc.status);
const navigate = useNavigate();
@@ -16,20 +26,32 @@ export default function DaemonStatusAlert() {
switch (contextStatus.type) {
case "Initializing":
- switch (contextStatus.content) {
- case TauriContextInitializationProgress.OpeningBitcoinWallet:
+ switch (contextStatus.content.type) {
+ case "OpeningBitcoinWallet":
return (
Connecting to the Bitcoin network
);
- case TauriContextInitializationProgress.OpeningMoneroWallet:
+ 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 TauriContextInitializationProgress.OpeningDatabase:
+ case "OpeningDatabase":
return (
Opening the local database
diff --git a/src-gui/src/utils/conversionUtils.ts b/src-gui/src/utils/conversionUtils.ts
index 776a1a3a7..3648ad125 100644
--- a/src-gui/src/utils/conversionUtils.ts
+++ b/src-gui/src/utils/conversionUtils.ts
@@ -30,9 +30,8 @@ export function isBtcAddressValid(address: string, testnet: boolean) {
}
export function getBitcoinTxExplorerUrl(txid: string, testnet: boolean) {
- return `https://mempool.space/${
- testnet ? "/testnet" : ""
- }/tx/${txid}`;
+ return `https://mempool.space/${testnet ? "/testnet" : ""
+ }/tx/${txid}`;
}
export function getMoneroTxExplorerUrl(txid: string, stagenet: boolean) {
@@ -67,3 +66,7 @@ export function rendezvousSellerToProviderStatus(
testnet: isTestnet(),
};
}
+
+export function bytesToMb(bytes: number): number {
+ return bytes / (1024 * 1024);
+}
diff --git a/swap/src/cli/api.rs b/swap/src/cli/api.rs
index 6218fb98f..4ac4a573a 100644
--- a/swap/src/cli/api.rs
+++ b/swap/src/cli/api.rs
@@ -336,8 +336,13 @@ impl ContextBuilder {
let (monero_wallet, monero_rpc_process) = {
if let Some(monero) = self.monero {
let monero_daemon_address = monero.apply_defaults(self.is_testnet);
- let (wlt, prc) =
- init_monero_wallet(data_dir.clone(), monero_daemon_address, env_config).await?;
+ let (wlt, prc) = init_monero_wallet(
+ data_dir.clone(),
+ monero_daemon_address,
+ env_config,
+ self.tauri_handle.clone(),
+ )
+ .await?;
(Some(Arc::new(wlt)), Some(Arc::new(SyncMutex::new(prc))))
} else {
(None, None)
@@ -473,12 +478,13 @@ async fn init_monero_wallet(
data_dir: PathBuf,
monero_daemon_address: String,
env_config: EnvConfig,
+ tauri_handle: Option,
) -> Result<(monero::Wallet, monero::WalletRpcProcess)> {
let network = env_config.monero_network;
const MONERO_BLOCKCHAIN_MONITORING_WALLET_NAME: &str = "swap-tool-blockchain-monitoring-wallet";
- let monero_wallet_rpc = monero::WalletRpc::new(data_dir.join("monero")).await?;
+ let monero_wallet_rpc = monero::WalletRpc::new(data_dir.join("monero"), tauri_handle).await?;
tracing::debug!(
address = monero_daemon_address,
diff --git a/swap/src/cli/api/tauri_bindings.rs b/swap/src/cli/api/tauri_bindings.rs
index 28fd20511..576a3ee54 100644
--- a/swap/src/cli/api/tauri_bindings.rs
+++ b/swap/src/cli/api/tauri_bindings.rs
@@ -110,8 +110,17 @@ 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,
}
diff --git a/swap/src/monero/wallet_rpc.rs b/swap/src/monero/wallet_rpc.rs
index 7c4179004..05e1633ca 100644
--- a/swap/src/monero/wallet_rpc.rs
+++ b/swap/src/monero/wallet_rpc.rs
@@ -21,6 +21,10 @@ use tokio::process::{Child, Command};
use tokio_util::codec::{BytesCodec, FramedRead};
use tokio_util::io::StreamReader;
+use crate::cli::api::tauri_bindings::{
+ TauriContextInitializationProgress, TauriContextStatusEvent, TauriEmitter, TauriHandle,
+};
+
// See: https://www.moneroworld.com/#nodes, https://monero.fail
// We don't need any testnet nodes because we don't support testnet at all
const MONERO_DAEMONS: Lazy<[MoneroDaemon; 16]> = Lazy::new(|| {
@@ -201,7 +205,10 @@ pub struct WalletRpc {
}
impl WalletRpc {
- pub async fn new(working_dir: impl AsRef) -> Result {
+ pub async fn new(
+ working_dir: impl AsRef,
+ tauri_handle: Option,
+ ) -> Result {
let working_dir = working_dir.as_ref();
if !working_dir.exists() {
@@ -255,6 +262,14 @@ impl WalletRpc {
"Downloading monero-wallet-rpc",
);
+ // Emit a tauri event to update the progress
+ tauri_handle.emit_context_init_progress_event(TauriContextStatusEvent::Initializing(
+ TauriContextInitializationProgress::DownloadingMoneroWalletRpc {
+ progress: 0,
+ size: content_length,
+ },
+ ));
+
let mut hasher = Sha256::new();
let byte_stream = response
@@ -292,6 +307,16 @@ impl WalletRpc {
"Downloading monero-wallet-rpc",
);
notified = percent;
+
+ // Emit a tauri event to update the progress
+ tauri_handle.emit_context_init_progress_event(
+ TauriContextStatusEvent::Initializing(
+ TauriContextInitializationProgress::DownloadingMoneroWalletRpc {
+ progress: percent,
+ size: content_length,
+ },
+ ),
+ );
}
file.write_all(&bytes).await?;
}