From 9cccbdb946364bf8da10a2c8d96608c560a77044 Mon Sep 17 00:00:00 2001 From: Hansie Odendaal Date: Tue, 28 Sep 2021 13:11:31 +0200 Subject: [PATCH] As per PR #3389 --- .../src/ui/components/transactions_tab.rs | 36 ++------ .../src/ui/state/app_state.rs | 87 ++++++++++++++++--- 2 files changed, 82 insertions(+), 41 deletions(-) diff --git a/applications/tari_console_wallet/src/ui/components/transactions_tab.rs b/applications/tari_console_wallet/src/ui/components/transactions_tab.rs index b3ca589452..7303f97935 100644 --- a/applications/tari_console_wallet/src/ui/components/transactions_tab.rs +++ b/applications/tari_console_wallet/src/ui/components/transactions_tab.rs @@ -2,17 +2,12 @@ use std::collections::HashMap; use crate::ui::{ components::{balance::Balance, Component}, - state::AppState, + state::{AppState, CompletedTransactionInfo}, widgets::{draw_dialog, MultiColumnList, WindowedListState}, MAX_WIDTH, }; use chrono::{DateTime, Local}; -use tari_crypto::tari_utilities::hex::Hex; -use tari_wallet::transaction_service::storage::models::{ - CompletedTransaction, - TransactionDirection, - TransactionStatus, -}; +use tari_wallet::transaction_service::storage::models::{TransactionDirection, TransactionStatus}; use tokio::runtime::Handle; use tui::{ backend::Backend, @@ -28,7 +23,7 @@ pub struct TransactionsTab { selected_tx_list: SelectedTransactionList, pending_list_state: WindowedListState, completed_list_state: WindowedListState, - detailed_transaction: Option, + detailed_transaction: Option, error_message: Option, confirmation_dialog: bool, } @@ -197,16 +192,11 @@ impl TransactionsTab { app_state.get_alias(&t.source_public_key), Style::default().fg(text_color), ))); - let maturity = if let Some(output) = t.transaction.body.outputs().first() { - output.features.maturity - } else { - 0 - }; let color = match (t.cancelled, chain_height) { // cancelled (true, _) => Color::DarkGray, // not mature yet - (_, Some(height)) if maturity > height => Color::Yellow, + (_, Some(height)) if t.maturity > height => Color::Yellow, // default _ => Color::Green, }; @@ -341,12 +331,7 @@ impl TransactionsTab { format!("{}", local_time.format("%Y-%m-%d %H:%M:%S")), Style::default().fg(Color::White), ); - let excess_hex = if tx.transaction.body.kernels().is_empty() { - "".to_string() - } else { - tx.transaction.body.kernels()[0].excess_sig.get_signature().to_hex() - }; - let excess = Span::styled(excess_hex.as_str(), Style::default().fg(Color::White)); + let excess = Span::styled(tx.excess_signature.as_str(), Style::default().fg(Color::White)); let confirmation_count = app_state.get_confirmations(&tx.tx_id); let confirmations_msg = if tx.status == TransactionStatus::MinedConfirmed && !tx.cancelled { format!("{} required confirmations met", required_confirmations) @@ -366,15 +351,8 @@ impl TransactionsTab { .unwrap_or_else(|| "N/A".to_string()), Style::default().fg(Color::White), ); - let maturity = tx - .transaction - .body - .outputs() - .first() - .map(|o| o.features.maturity) - .unwrap_or_else(|| 0); - let maturity = if maturity > 0 { - format!("Spendable at Block #{}", maturity) + let maturity = if tx.maturity > 0 { + format!("Spendable at Block #{}", tx.maturity) } else { "N/A".to_string() }; diff --git a/applications/tari_console_wallet/src/ui/state/app_state.rs b/applications/tari_console_wallet/src/ui/state/app_state.rs index 55dba3a4ae..6e121c8d7e 100644 --- a/applications/tari_console_wallet/src/ui/state/app_state.rs +++ b/applications/tari_console_wallet/src/ui/state/app_state.rs @@ -27,7 +27,7 @@ use std::{ }; use bitflags::bitflags; -use chrono::{DateTime, Local}; +use chrono::{DateTime, Local, NaiveDateTime}; use log::*; use qrcode::{render::unicode, QrCode}; use tari_crypto::{ristretto::RistrettoPublicKey, tari_utilities::hex::Hex}; @@ -75,7 +75,10 @@ use crate::{ utils::db::{CUSTOM_BASE_NODE_ADDRESS_KEY, CUSTOM_BASE_NODE_PUBLIC_KEY_KEY}, wallet_modes::PeerConfig, }; -use tari_wallet::output_manager_service::handle::OutputManagerHandle; +use tari_wallet::{ + output_manager_service::handle::OutputManagerHandle, + transaction_service::storage::models::TransactionDirection, +}; const LOG_TARGET: &str = "wallet::console_wallet::app_state"; @@ -320,11 +323,11 @@ impl AppState { &self.cached_data.contacts[start..end] } - pub fn get_pending_txs(&self) -> &Vec { + pub fn get_pending_txs(&self) -> &Vec { &self.cached_data.pending_txs } - pub fn get_pending_txs_slice(&self, start: usize, end: usize) -> &[CompletedTransaction] { + pub fn get_pending_txs_slice(&self, start: usize, end: usize) -> &[CompletedTransactionInfo] { if self.cached_data.pending_txs.is_empty() || start > end || end > self.cached_data.pending_txs.len() { return &[]; } @@ -332,7 +335,7 @@ impl AppState { &self.cached_data.pending_txs[start..end] } - pub fn get_pending_tx(&self, index: usize) -> Option<&CompletedTransaction> { + pub fn get_pending_tx(&self, index: usize) -> Option<&CompletedTransactionInfo> { if index < self.cached_data.pending_txs.len() { Some(&self.cached_data.pending_txs[index]) } else { @@ -340,7 +343,7 @@ impl AppState { } } - pub fn get_completed_txs(&self) -> Vec<&CompletedTransaction> { + pub fn get_completed_txs(&self) -> Vec<&CompletedTransactionInfo> { if self .completed_tx_filter .contains(TransactionFilter::ABANDONED_COINBASES) @@ -359,7 +362,7 @@ impl AppState { (&self.cached_data.confirmations).get(tx_id) } - pub fn get_completed_tx(&self, index: usize) -> Option<&CompletedTransaction> { + pub fn get_completed_tx(&self, index: usize) -> Option<&CompletedTransactionInfo> { let filtered_completed_txs = self.get_completed_txs(); if index < filtered_completed_txs.len() { Some(filtered_completed_txs[index]) @@ -519,7 +522,10 @@ impl AppStateInner { pending_transactions.sort_by(|a: &CompletedTransaction, b: &CompletedTransaction| { b.timestamp.partial_cmp(&a.timestamp).unwrap() }); - self.data.pending_txs = pending_transactions; + self.data.pending_txs = pending_transactions + .iter() + .map(|tx| CompletedTransactionInfo::from(tx.clone())) + .collect(); let mut completed_transactions: Vec = Vec::new(); completed_transactions.extend( @@ -548,7 +554,10 @@ impl AppStateInner { .expect("Should be able to compare timestamps") }); - self.data.completed_txs = completed_transactions; + self.data.completed_txs = completed_transactions + .iter() + .map(|tx| CompletedTransactionInfo::from(tx.clone())) + .collect(); self.updated = true; Ok(()) } @@ -590,7 +599,7 @@ impl AppStateInner { }); }, Some(tx) => { - let tx = CompletedTransaction::from(tx); + let tx = CompletedTransactionInfo::from(CompletedTransaction::from(tx)); if let Some(index) = self.data.pending_txs.iter().position(|i| i.tx_id == tx_id) { if tx.status == TransactionStatus::Pending && !tx.cancelled { self.data.pending_txs[index] = tx; @@ -860,10 +869,64 @@ impl AppStateInner { } } +#[derive(Clone)] +pub struct CompletedTransactionInfo { + pub tx_id: TxId, + pub source_public_key: CommsPublicKey, + pub destination_public_key: CommsPublicKey, + pub amount: MicroTari, + pub fee: MicroTari, + pub excess_signature: String, + pub maturity: u64, + pub status: TransactionStatus, + pub message: String, + pub timestamp: NaiveDateTime, + pub cancelled: bool, + pub direction: TransactionDirection, + pub valid: bool, + pub mined_height: Option, +} + +impl From for CompletedTransactionInfo { + fn from(completed_transaction: CompletedTransaction) -> Self { + let excess_signature = if completed_transaction.transaction.body.kernels().is_empty() { + "".to_string() + } else { + completed_transaction.transaction.body.kernels()[0] + .excess_sig + .get_signature() + .to_hex() + }; + + Self { + tx_id: completed_transaction.tx_id, + source_public_key: completed_transaction.source_public_key, + destination_public_key: completed_transaction.destination_public_key, + amount: completed_transaction.amount, + fee: completed_transaction.fee, + excess_signature, + maturity: completed_transaction + .transaction + .body + .outputs() + .first() + .map(|o| o.features.maturity) + .unwrap_or_else(|| 0), + status: completed_transaction.status, + message: completed_transaction.message, + timestamp: completed_transaction.timestamp, + cancelled: completed_transaction.cancelled, + direction: completed_transaction.direction, + valid: completed_transaction.valid, + mined_height: completed_transaction.mined_height, + } + } +} + #[derive(Clone)] struct AppStateData { - pending_txs: Vec, - completed_txs: Vec, + pending_txs: Vec, + completed_txs: Vec, confirmations: HashMap, my_identity: MyIdentity, contacts: Vec,