Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gui): Display progress of monero-wallet-rpc download #170

Merged
merged 1 commit into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions src-gui/src/renderer/components/alert/DaemonStatusAlert.tsx
Original file line number Diff line number Diff line change
@@ -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();

Expand All @@ -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 (
<LoadingSpinnerAlert severity="warning">
Connecting to the Bitcoin network
</LoadingSpinnerAlert>
);
case TauriContextInitializationProgress.OpeningMoneroWallet:
case "DownloadingMoneroWalletRpc":
return (
<LoadingSpinnerAlert severity="warning">
<Box className={classes.innerAlert}>
<Box>
Downloading and verifying the Monero wallet RPC (
{bytesToMb(contextStatus.content.content.size).toFixed(2)} MB)
</Box>
<LinearProgress variant="determinate" value={contextStatus.content.content.progress} />
</Box>
</LoadingSpinnerAlert >
);
case "OpeningMoneroWallet":
return (
<LoadingSpinnerAlert severity="warning">
Connecting to the Monero network
</LoadingSpinnerAlert>
);
case TauriContextInitializationProgress.OpeningDatabase:
case "OpeningDatabase":
return (
<LoadingSpinnerAlert severity="warning">
Opening the local database
Expand Down
9 changes: 6 additions & 3 deletions src-gui/src/utils/conversionUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -67,3 +66,7 @@ export function rendezvousSellerToProviderStatus(
testnet: isTestnet(),
};
}

export function bytesToMb(bytes: number): number {
return bytes / (1024 * 1024);
}
12 changes: 9 additions & 3 deletions swap/src/cli/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -473,12 +478,13 @@ async fn init_monero_wallet(
data_dir: PathBuf,
monero_daemon_address: String,
env_config: EnvConfig,
tauri_handle: Option<TauriHandle>,
) -> 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,
Expand Down
9 changes: 9 additions & 0 deletions swap/src/cli/api/tauri_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,17 @@ impl TauriEmitter for Option<TauriHandle> {

#[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,
}
Expand Down
27 changes: 26 additions & 1 deletion swap/src/monero/wallet_rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(|| {
Expand Down Expand Up @@ -201,7 +205,10 @@ pub struct WalletRpc {
}

impl WalletRpc {
pub async fn new(working_dir: impl AsRef<Path>) -> Result<WalletRpc> {
pub async fn new(
working_dir: impl AsRef<Path>,
tauri_handle: Option<TauriHandle>,
) -> Result<WalletRpc> {
let working_dir = working_dir.as_ref();

if !working_dir.exists() {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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?;
}
Expand Down
Loading