feat(gui): Approve dialog before publishing Bitcoin lock transaction (#291)

This diff introduces a new "approvals" mechanism that alters the swap flow by requiring explicit user intervention before the Bitcoin lock transaction is broadcast. Previously, the Bitcoin lock was executed automatically without any user prompt. Now, the backend defines `ApprovalRequestType` (e.g. a `PreBtcLock` variant with details like `btc_lock_amount`, `btc_network_fee`, and `xmr_receive_amount`) and `ApprovalEvent` (with statuses such as `Pending`, `Resolved`, and `Rejected`). The method `request_approval()` in the `TauriHandle` struct uses a oneshot channel and concurrent timeout handling via `tokio::select!` to wait for the user's decision. Based on the outcome—explicit approval or timeout/rejection—the approval event is emitted through the `emit_approval()` helper, thereby gating the subsequent broadcast of the Bitcoin lock transaction.

On the UI side, changes have been made to reflect the new flow; the modal (for example, in `SwapSetupInflightPage.tsx`) now displays the swap details along with explicit action buttons that call `resolveApproval()` via RPC when clicked. The Redux store, selectors, and hooks like `usePendingPreBtcLockApproval()` have been updated to track and display these approval events. As a result, the overall functionality now requires the user to explicitly approve the swap offer before proceeding, ensuring they are aware of the swap's key parameters and that the locking of funds occurs only after their confirmation.
This commit is contained in:
Mohan 2025-04-18 01:51:55 +02:00 committed by GitHub
parent ab5f93ff44
commit 9ddf2daafe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 613 additions and 65 deletions

View file

@ -28,6 +28,7 @@ tauri-plugin-shell = "^2.0.0"
tauri-plugin-store = "^2.0.0"
tauri-plugin-updater = "^2.1.0"
tracing = "0.1"
uuid = "1.16.0"
[target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies]
tauri-plugin-cli = "^2.0.0"

View file

@ -9,7 +9,8 @@ use swap::cli::{
CheckElectrumNodeResponse, CheckMoneroNodeArgs, CheckMoneroNodeResponse,
ExportBitcoinWalletArgs, GetDataDirArgs, GetHistoryArgs, GetLogsArgs,
GetMoneroAddressesArgs, GetSwapInfoArgs, GetSwapInfosAllArgs, ListSellersArgs,
MoneroRecoveryArgs, ResumeSwapArgs, SuspendCurrentSwapArgs, WithdrawBtcArgs,
MoneroRecoveryArgs, ResolveApprovalArgs, ResumeSwapArgs, SuspendCurrentSwapArgs,
WithdrawBtcArgs,
},
tauri_bindings::{TauriContextStatusEvent, TauriEmitter, TauriHandle, TauriSettings},
Context, ContextBuilder,
@ -17,6 +18,7 @@ use swap::cli::{
command::{Bitcoin, Monero},
};
use tauri::{async_runtime::RwLock, Manager, RunEvent};
use uuid::Uuid;
/// Trait to convert Result<T, E> to Result<T, String>
/// Tauri commands require the error type to be a string
@ -183,7 +185,8 @@ pub fn run() {
check_monero_node,
check_electrum_node,
get_wallet_descriptor,
get_data_dir
get_data_dir,
resolve_approval_request,
])
.setup(setup)
.build(tauri::generate_context!())
@ -224,6 +227,7 @@ tauri_command!(monero_recovery, MoneroRecoveryArgs);
tauri_command!(get_logs, GetLogsArgs);
tauri_command!(list_sellers, ListSellersArgs);
tauri_command!(cancel_and_refund, CancelAndRefundArgs);
tauri_command!(resolve_approval_request, ResolveApprovalArgs);
// These commands require no arguments
tauri_command!(get_wallet_descriptor, ExportBitcoinWalletArgs, no_args);