diff --git a/src-gui/src/renderer/components/pages/help/ExportDataBox.tsx b/src-gui/src/renderer/components/pages/help/ExportDataBox.tsx new file mode 100644 index 00000000..60f47abd --- /dev/null +++ b/src-gui/src/renderer/components/pages/help/ExportDataBox.tsx @@ -0,0 +1,115 @@ +import { + Box, + Typography, + makeStyles, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + Button, + Link, + DialogContentText, +} from "@material-ui/core"; +import InfoBox from "renderer/components/modal/swap/InfoBox"; +import { useState } from "react"; +import { getWalletDescriptor } from "renderer/rpc"; +import { ExportBitcoinWalletResponse } from "models/tauriModel"; +import PromiseInvokeButton from "renderer/components/PromiseInvokeButton"; +import ActionableMonospaceTextBox from "renderer/components/other/ActionableMonospaceTextBox"; + +const useStyles = makeStyles((theme) => ({ + content: { + display: "flex", + flexDirection: "column", + alignItems: "flex-start", + gap: theme.spacing(2), + } +})); + +export default function ExportDataBox() { + const classes = useStyles(); + const [walletDescriptor, setWalletDescriptor] = useState(null); + + const handleCloseDialog = () => { + setWalletDescriptor(null); + }; + + return ( + + + You can export the wallet descriptor of the interal Bitcoin wallet for backup or recovery purposes. Please make sure to store it securely. + + + } + additionalContent={ + <> + + Reveal Bitcoin Wallet Private Key + + {walletDescriptor !== null && ( + + )} + + } + /> + ); +} + +function WalletDescriptorModal({ + open, + onClose, + walletDescriptor, +}: { + open: boolean; + onClose: () => void; + walletDescriptor: ExportBitcoinWalletResponse; +}) { + const parsedDescriptor = JSON.parse(walletDescriptor.wallet_descriptor.descriptor); + const stringifiedDescriptor = JSON.stringify(parsedDescriptor, null, 4); + + return ( + + Bitcoin Wallet Descriptor + + +
    +
  • + The text below contains the wallet descriptor of the internal Bitcoin wallet. It contains your private key and can be used to derive your wallet. It should thus be stored securely. +
  • +
  • + It can be imported into other Bitcoin wallets or services that support the descriptor format. +
  • +
  • + For more information on what to do with the descriptor, see our + {" "}documentation +
  • +
+
+ +
+ + + +
+ ); +}; diff --git a/src-gui/src/renderer/components/pages/help/FeedbackInfoBox.tsx b/src-gui/src/renderer/components/pages/help/FeedbackInfoBox.tsx index 19614337..eb356edd 100644 --- a/src-gui/src/renderer/components/pages/help/FeedbackInfoBox.tsx +++ b/src-gui/src/renderer/components/pages/help/FeedbackInfoBox.tsx @@ -11,10 +11,9 @@ export default function FeedbackInfoBox() { title="Feedback" mainContent={ - The main goal of this project is to make Atomic Swaps easier to use, - and for that we need genuine users' input. Please leave some - feedback, it takes just two minutes. I'll read each and every - survey response and take your feedback into consideration. + Your input is crucial to us! We'd love to hear your thoughts on + Atomic Swaps. We personally read every response to improve the + project. Got two minutes to share? } additionalContent={ diff --git a/src-gui/src/renderer/components/pages/help/HelpPage.tsx b/src-gui/src/renderer/components/pages/help/HelpPage.tsx index 96d62007..a76d1222 100644 --- a/src-gui/src/renderer/components/pages/help/HelpPage.tsx +++ b/src-gui/src/renderer/components/pages/help/HelpPage.tsx @@ -4,7 +4,7 @@ import DonateInfoBox from "./DonateInfoBox"; import FeedbackInfoBox from "./FeedbackInfoBox"; import DaemonControlBox from "./DaemonControlBox"; import SettingsBox from "./SettingsBox"; - +import ExportDataBox from "./ExportDataBox"; const useStyles = makeStyles((theme) => ({ outer: { display: "flex", @@ -19,9 +19,10 @@ export default function HelpPage() { return ( + - + diff --git a/src-gui/src/renderer/rpc.ts b/src-gui/src/renderer/rpc.ts index f8c52260..2347d50d 100644 --- a/src-gui/src/renderer/rpc.ts +++ b/src-gui/src/renderer/rpc.ts @@ -21,6 +21,7 @@ import { TauriDatabaseStateEvent, TauriTimelockChangeEvent, GetSwapInfoArgs, + ExportBitcoinWalletResponse, } from "models/tauriModel"; import { contextStatusEventReceived, @@ -214,3 +215,7 @@ export async function initializeContext() { testnet, }); } + +export async function getWalletDescriptor() { + return await invokeNoArgs("get_wallet_descriptor"); +} \ No newline at end of file diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 39d4dc9c..7bbb3cf3 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -4,8 +4,8 @@ use std::sync::Arc; use swap::cli::{ api::{ request::{ - BalanceArgs, BuyXmrArgs, CancelAndRefundArgs, GetHistoryArgs, GetLogsArgs, - GetSwapInfoArgs, GetSwapInfosAllArgs, ListSellersArgs, MoneroRecoveryArgs, + BalanceArgs, BuyXmrArgs, CancelAndRefundArgs, ExportBitcoinWalletArgs, GetHistoryArgs, + GetLogsArgs, GetSwapInfoArgs, GetSwapInfosAllArgs, ListSellersArgs, MoneroRecoveryArgs, ResumeSwapArgs, SuspendCurrentSwapArgs, WithdrawBtcArgs, }, tauri_bindings::{TauriContextStatusEvent, TauriEmitter, TauriHandle, TauriSettings}, @@ -146,6 +146,7 @@ pub fn run() { cancel_and_refund, is_context_available, initialize_context, + get_wallet_descriptor, ]) .setup(setup) .build(tauri::generate_context!()) @@ -186,8 +187,8 @@ tauri_command!(monero_recovery, MoneroRecoveryArgs); tauri_command!(get_logs, GetLogsArgs); tauri_command!(list_sellers, ListSellersArgs); tauri_command!(cancel_and_refund, CancelAndRefundArgs); - // These commands require no arguments +tauri_command!(get_wallet_descriptor, ExportBitcoinWalletArgs, no_args); tauri_command!(suspend_current_swap, SuspendCurrentSwapArgs, no_args); tauri_command!(get_swap_info, GetSwapInfoArgs); tauri_command!(get_swap_infos_all, GetSwapInfosAllArgs, no_args); diff --git a/swap/src/cli/api/request.rs b/swap/src/cli/api/request.rs index 7282a82e..1dad5aed 100644 --- a/swap/src/cli/api/request.rs +++ b/swap/src/cli/api/request.rs @@ -346,13 +346,22 @@ impl Request for GetConfig { } } +#[typeshare] +#[derive(Serialize, Deserialize, Debug)] pub struct ExportBitcoinWalletArgs; +#[typeshare] +#[derive(Serialize, Deserialize, Debug)] +pub struct ExportBitcoinWalletResponse { + pub wallet_descriptor: serde_json::Value, +} + impl Request for ExportBitcoinWalletArgs { - type Response = serde_json::Value; + type Response = ExportBitcoinWalletResponse; async fn request(self, ctx: Arc) -> Result { - export_bitcoin_wallet(ctx).await + let wallet_descriptor = export_bitcoin_wallet(ctx).await?; + Ok(ExportBitcoinWalletResponse { wallet_descriptor }) } }