From fae1364f10f3634bca527c1dab3292d8625048ae Mon Sep 17 00:00:00 2001 From: ardocrat Date: Tue, 10 Jun 2025 22:03:49 +0300 Subject: [PATCH] wallet: tx response flag to show sharing controls --- src/gui/views/wallets/wallet/txs/tx.rs | 20 +++++--- src/wallet/types.rs | 2 + src/wallet/wallet.rs | 71 +++++++++++++++----------- 3 files changed, 56 insertions(+), 37 deletions(-) diff --git a/src/gui/views/wallets/wallet/txs/tx.rs b/src/gui/views/wallets/wallet/txs/tx.rs index 1950e6d2..d5cc5b74 100644 --- a/src/gui/views/wallets/wallet/txs/tx.rs +++ b/src/gui/views/wallets/wallet/txs/tx.rs @@ -133,7 +133,7 @@ impl WalletTransactionContent { self.info_ui(ui, modal, tx, wallet, cb); // Show transaction sharing content. - if tx.can_finalize { + if tx.can_finalize || tx.is_response { self.share_ui(ui, wallet, tx, cb); } @@ -158,10 +158,18 @@ impl WalletTransactionContent { tx: &WalletTransaction, cb: &dyn PlatformCallbacks) { let amount = amount_to_hr_string(tx.amount, true); - let desc_text = if tx.data.tx_type == TxLogEntryType::TxSent { - t!("wallets.send_request_desc", "amount" => amount) + let desc_text = if tx.can_finalize { + if tx.data.tx_type == TxLogEntryType::TxSent { + t!("wallets.send_request_desc", "amount" => amount) + } else { + t!("wallets.invoice_desc", "amount" => amount) + } } else { - t!("wallets.invoice_desc", "amount" => amount) + if tx.data.tx_type == TxLogEntryType::TxSent { + t!("wallets.parse_i1_slatepack_desc", "amount" => amount) + } else { + t!("wallets.parse_s1_slatepack_desc", "amount" => amount) + } }; ui.add_space(6.0); ui.vertical_centered(|ui| { @@ -177,7 +185,7 @@ impl WalletTransactionContent { // Draw button to show Slatepack message as QR code. let qr_text = format!("{} {}", QR_CODE, t!("qr_code")); View::button(ui, qr_text.clone(), Colors::white_or_black(false), || { - if let Some((_, d)) = wallet.read_slate_by_tx(tx) { + if let Some((_, d)) = wallet.read_slatepack_by_tx(tx) { self.qr_code_content = Some(QrCodeContent::new(d, true)); } }); @@ -189,7 +197,7 @@ impl WalletTransactionContent { share_text, Colors::blue(), Colors::white_or_black(false), || { - if let Some((s, d)) = wallet.read_slate_by_tx(tx) { + if let Some((s, d)) = wallet.read_slatepack_by_tx(tx) { let name = format!("{}.{}.slatepack", s.id, s.state); let data = d.as_bytes().to_vec(); cb.share_data(name, data).unwrap_or_default(); diff --git a/src/wallet/types.rs b/src/wallet/types.rs index 1fb1f14a..5a333f40 100644 --- a/src/wallet/types.rs +++ b/src/wallet/types.rs @@ -160,6 +160,8 @@ pub struct WalletTransaction { pub amount: u64, /// Flag to check if transaction is cancelling. pub cancelling: bool, + /// Flag to check if transaction can be sent back to initiator to finalize. + pub is_response: bool, /// Flag to check if transaction can be finalized based on Slatepack message state. pub can_finalize: bool, /// Flag to check if transaction is finalizing. diff --git a/src/wallet/wallet.rs b/src/wallet/wallet.rs index 73c1380e..745d99c5 100644 --- a/src/wallet/wallet.rs +++ b/src/wallet/wallet.rs @@ -13,19 +13,6 @@ // limitations under the License. use futures::channel::oneshot; -use parking_lot::RwLock; -use rand::Rng; -use serde_json::{json, Value}; -use std::fs::File; -use std::io::Write; -use std::net::{SocketAddr, TcpListener}; -use std::path::PathBuf; -use std::sync::atomic::{AtomicBool, AtomicU8, Ordering}; -use std::sync::{mpsc, Arc}; -use std::thread::Thread; -use std::time::Duration; -use std::{fs, thread}; - use grin_api::{ApiServer, Router}; use grin_chain::SyncStatus; use grin_keychain::{ExtKeychain, Identifier, Keychain}; @@ -40,6 +27,18 @@ use grin_wallet_impls::{DefaultLCProvider, DefaultWalletImpl, HTTPNodeClient, LM use grin_wallet_libwallet::api_impl::owner::{cancel_tx, retrieve_summary_info, retrieve_txs}; use grin_wallet_libwallet::{address, Error, InitTxArgs, IssueInvoiceTxArgs, NodeClient, RetrieveTxQueryArgs, RetrieveTxQuerySortField, RetrieveTxQuerySortOrder, Slate, SlateState, SlateVersion, SlatepackAddress, StatusMessage, TxLogEntry, TxLogEntryType, VersionedSlate, WalletBackend, WalletInitStatus, WalletInst, WalletLCProvider}; use grin_wallet_util::OnionV3Address; +use parking_lot::RwLock; +use rand::Rng; +use serde_json::{json, Value}; +use std::fs::File; +use std::io::Write; +use std::net::{SocketAddr, TcpListener}; +use std::path::PathBuf; +use std::sync::atomic::{AtomicBool, AtomicU8, Ordering}; +use std::sync::{mpsc, Arc}; +use std::thread::Thread; +use std::time::Duration; +use std::{fs, thread}; use crate::node::{Node, NodeConfig}; use crate::tor::Tor; @@ -673,8 +672,7 @@ impl Wallet { load.store(true, Ordering::Relaxed); if let Ok(slate) = w.parse_slatepack(&msg) { // Check if message with same id and state already exists. - let slatepack_path = w.get_config().get_slatepack_path(&slate); - let exists = fs::exists(slatepack_path).unwrap_or(false); + let exists = w.slatepack_exists(&slate); if exists { if let Some(tx) = w.tx_by_slate(&slate) { let mut w_res = res.write(); @@ -766,17 +764,14 @@ impl Wallet { Ok(message) } - /// Read slatepack from file. - pub fn read_slatepack(&self, slate: &Slate) -> Option { + /// Check if Slatepack file exists. + pub fn slatepack_exists(&self, slate: &Slate) -> bool { let slatepack_path = self.get_config().get_slatepack_path(slate); - match fs::read_to_string(slatepack_path) { - Ok(s) => Some(s), - Err(_) => None - } + fs::exists(slatepack_path).unwrap() } - /// Get last stored [`Slate`] for transaction. - pub fn read_slate_by_tx(&self, tx: &WalletTransaction) -> Option<(Slate, String)> { + /// Get last stored Slatepack message for transaction. + pub fn read_slatepack_by_tx(&self, tx: &WalletTransaction) -> Option<(Slate, String)> { let mut slate = None; if let Some(slate_id) = tx.data.tx_slate_id { // Get slate state based on tx state and status. @@ -803,7 +798,8 @@ impl Wallet { let mut s = Slate::blank(0, false); s.id = slate_id; s.state = st; - if let Some(m) = self.read_slatepack(&s) { + let slatepack_path = self.get_config().get_slatepack_path(&s); + if let Ok(m) = fs::read_to_string(slatepack_path) { if let Ok(s) = self.parse_slatepack(&m) { slate = Some((s, m)); } @@ -865,7 +861,7 @@ impl Wallet { addr: &SlatepackAddress) -> Result { // Initialize transaction. let tx = self.send(amount, Some(addr.clone()))?; - let slate_res = self.read_slate_by_tx(&tx); + let slate_res = self.read_slatepack_by_tx(&tx); if slate_res.is_none() { return Err(Error::GenericError("Slate not found".to_string())); } @@ -1445,6 +1441,7 @@ fn sync_wallet_data(wallet: &Wallet, from_node: bool) { let unconfirmed_sent_or_received = tx.tx_slate_id.is_some() && !tx.confirmed && (tx.tx_type == TxLogEntryType::TxSent || tx.tx_type == TxLogEntryType::TxReceived); + let mut is_response = false; let mut finalizing = false; let can_finalize = if unconfirmed_sent_or_received { let initial_state = { @@ -1454,18 +1451,29 @@ fn sync_wallet_data(wallet: &Wallet, from_node: bool) { TxLogEntryType::TxReceived => SlateState::Invoice1, _ => SlateState::Standard1 }; - wallet.read_slatepack(&slate).is_some() + wallet.slatepack_exists(&slate) }; - finalizing = { + is_response = { let mut slate = Slate::blank(1, false); slate.id = tx.tx_slate_id.unwrap(); slate.state = match tx.tx_type { - TxLogEntryType::TxReceived => SlateState::Invoice3, - _ => SlateState::Standard3 + TxLogEntryType::TxReceived => SlateState::Standard2, + _ => SlateState::Invoice2 }; - wallet.read_slatepack(&slate).is_some() + wallet.slatepack_exists(&slate) }; - initial_state && !finalizing + if !initial_state && !is_response { + finalizing = { + let mut slate = Slate::blank(1, false); + slate.id = tx.tx_slate_id.unwrap(); + slate.state = match tx.tx_type { + TxLogEntryType::TxReceived => SlateState::Invoice3, + _ => SlateState::Standard3 + }; + wallet.slatepack_exists(&slate) + }; + } + initial_state && !is_response && !finalizing } else { false }; @@ -1492,6 +1500,7 @@ fn sync_wallet_data(wallet: &Wallet, from_node: bool) { data: tx.clone(), amount, cancelling, + is_response, can_finalize, finalizing, height: conf_height,