From d7ff2a8792aaf966d615b94c5f23b7fc54dc1c95 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Sat, 7 Sep 2019 15:25:50 -0700 Subject: [PATCH] Print transactions list --- rust-lightclient/src/lightclient.rs | 95 +++++++++++++++++++++-------- rust-lightclient/src/lightwallet.rs | 8 ++- 2 files changed, 78 insertions(+), 25 deletions(-) diff --git a/rust-lightclient/src/lightclient.rs b/rust-lightclient/src/lightclient.rs index cdf3c72..a296e1b 100644 --- a/rust-lightclient/src/lightclient.rs +++ b/rust-lightclient/src/lightclient.rs @@ -27,6 +27,14 @@ use crate::grpc_client::client::CompactTxStreamer; // Used below to return the grpc "Client" type to calling methods type Client = crate::grpc_client::client::CompactTxStreamer, tower_grpc::BoxBody>>; +#[derive(Debug)] +pub struct TransactionListItem { + pub block_height: i32, // Block height in which this transaction was confirmed + pub txid: String, + pub amount: i64, // Amount of this Tx. -ve values are spends, +ve are recieve + pub address: String, // for recieves, it is the incoming address. For sends, it is the address sent from + pub memo: Option, // Optional string +} pub struct LightClient { pub wallet : Arc, @@ -118,31 +126,70 @@ impl LightClient { } pub fn do_list_transactions(&self) { - // Go over all the transactions - self.wallet.txs.read().unwrap().iter().for_each( - | (k, v) | { - println!("Block {}", v.block); - println!("Txid {}", k); - v.notes.iter().for_each( |nd| { - println!("Spent in txid {}", match nd.spent { - Some(txid) => format!("{}", txid), - _ => "(not spent)".to_string() + // Create a list of TransactionItems + let mut tx_list = self.wallet.txs.read().unwrap().iter() + .flat_map(| (_k, v) | { + let mut txns = Vec::new(); + + if v.total_shielded_value_spent > 0 { + // If money was spent, create a transaction. For this, we'll subtract + // all the change notes. TODO: Add transparent change here to subtract it also + let total_change: u64 = v.notes.iter() + .filter( |nd| nd.is_change ) + .map( |nd| nd.note.value ) + .sum(); + + // TODO: What happens if change is > than sent ? + + txns.push(TransactionListItem { + block_height: v.block, + txid : format!("{}", v.txid), + amount : total_change as i64 - v.total_shielded_value_spent as i64, + address : "".to_string(), // TODO: For send, we don't have an address + memo : None }); - println!("Value {}", nd.note.value); - println!("Memo {}", match &nd.memo { - Some(memo) => { - match memo.to_utf8() { - Some(Ok(memo_str)) => memo_str, - _ => "".to_string() - } - } - _ => "".to_string() - }); - }); - - println!("Total spent: {}", v.total_shielded_value_spent); - } - ) + } + + // For each note that is not a change, add a Tx. + txns.extend(v.notes.iter() + .filter( |nd| !nd.is_change ) + .map ( |nd| + TransactionListItem { + block_height: v.block, + txid : format!("{}", v.txid), + amount : nd.note.value as i64, + address : nd.note_address().unwrap(), + memo : match &nd.memo { + Some(memo) => { + match memo.to_utf8() { + Some(Ok(memo_str)) => Some(memo_str), + _ => None + } + } + _ => None + } + }) + ); + + txns + }) + .collect::>(); + + tx_list.sort_by( |a, b| if a.block_height == b.block_height { + a.txid.cmp(&b.txid) + } else { + a.block_height.cmp(&b.block_height) + } + ); + + tx_list.iter().for_each(|tx| { + println!("height: {}", tx.block_height); + println!("txid: {}", tx.txid); + println!("amount: {}", tx.amount); + println!("address: {}", tx.address); + println!("memo: {}", tx.memo.as_ref().unwrap_or(&"".to_string())); + println!(""); + }); } pub fn do_sync(&self) { diff --git a/rust-lightclient/src/lightwallet.rs b/rust-lightclient/src/lightwallet.rs index f386a96..d71f4fa 100644 --- a/rust-lightclient/src/lightwallet.rs +++ b/rust-lightclient/src/lightwallet.rs @@ -90,7 +90,6 @@ impl BlockData { } } - pub struct SaplingNoteData { account: usize, extfvk: ExtendedFullViewingKey, // Technically, this should be recoverable from the account number, but we're going to refactor this in the future, so I'll write it again here. @@ -254,6 +253,13 @@ impl SaplingNoteData { Ok(()) } + + pub fn note_address(&self) -> Option { + match self.extfvk.fvk.vk.into_payment_address(self.diversifier, &JUBJUB) { + Some(pa) => Some(encode_payment_address(HRP_SAPLING_PAYMENT_ADDRESS, &pa)), + None => None + } + } } pub struct WalletTx {