From cd3203be23b31fe0cb8f1a61a123c916ab32e7ae Mon Sep 17 00:00:00 2001 From: Yeastplume Date: Tue, 22 Nov 2022 13:25:44 +0000 Subject: [PATCH] update transaction api calls throughout --- api/src/owner.rs | 8 +++- api/src/owner_rpc.rs | 4 ++ controller/src/command.rs | 5 ++- controller/tests/accounts.rs | 14 +++--- controller/tests/check.rs | 4 +- controller/tests/invoice.rs | 4 +- controller/tests/no_change.rs | 8 ++-- controller/tests/payment_proofs.rs | 2 +- controller/tests/repost.rs | 4 +- controller/tests/revert.rs | 16 +++---- controller/tests/transaction.rs | 20 ++++----- controller/tests/ttl_cutoff.rs | 10 ++--- libwallet/src/api_impl/foreign.rs | 1 + libwallet/src/api_impl/owner.rs | 13 +++++- libwallet/src/api_impl/types.rs | 60 +++++++++++++++++++++++++- libwallet/src/internal/scan.rs | 1 + libwallet/src/internal/tx.rs | 20 +++++++-- libwallet/src/internal/updater.rs | 68 +++++++++++++++++------------- libwallet/src/lib.rs | 3 +- tests/cmd_line_basic.rs | 8 ++-- 20 files changed, 188 insertions(+), 85 deletions(-) diff --git a/api/src/owner.rs b/api/src/owner.rs index 12e54e04..01fbdd09 100644 --- a/api/src/owner.rs +++ b/api/src/owner.rs @@ -16,6 +16,7 @@ use chrono::prelude::*; use ed25519_dalek::SecretKey as DalekSecretKey; +use grin_wallet_libwallet::RetrieveTxQueryArgs; use uuid::Uuid; use crate::config::{TorConfig, WalletConfig}; @@ -447,6 +448,9 @@ where /// the transaction log entry of id `i`. /// * `tx_slate_id` - If `Some(uuid)`, only return transactions associated with /// the given [`Slate`](../grin_wallet_libwallet/slate/struct.Slate.html) uuid. + /// * `tx_query_args` - If provided, use advanced query arguments as documented in + /// (../grin_wallet_libwallet/types.struct.RetrieveTxQueryArgs.html). If either + /// `tx_id` or `tx_slate_id` is provided in the same call, this argument is ignored /// /// # Returns /// * `(bool, Vec, tx_slate_id: Option, + tx_query_args: Option, ) -> Result<(bool, Vec), Error> { let tx = { let t = self.status_tx.lock(); @@ -496,6 +501,7 @@ where refresh_from_node, tx_id, tx_slate_id, + tx_query_args, )?; if self.doctest_mode { res.1 = res diff --git a/api/src/owner_rpc.rs b/api/src/owner_rpc.rs index 2591577f..beeb6a66 100644 --- a/api/src/owner_rpc.rs +++ b/api/src/owner_rpc.rs @@ -13,6 +13,7 @@ // limitations under the License. //! JSON-RPC Stub generation for the Owner API +use grin_wallet_libwallet::RetrieveTxQueryArgs; use uuid::Uuid; use crate::config::{TorConfig, WalletConfig}; @@ -307,6 +308,7 @@ pub trait OwnerRpc { refresh_from_node: bool, tx_id: Option, tx_slate_id: Option, + tx_query_args: Option, ) -> Result<(bool, Vec), Error>; /** @@ -1912,6 +1914,7 @@ where refresh_from_node: bool, tx_id: Option, tx_slate_id: Option, + query_args: Option, ) -> Result<(bool, Vec), Error> { Owner::retrieve_txs( self, @@ -1919,6 +1922,7 @@ where refresh_from_node, tx_id, tx_slate_id, + query_args, ) } diff --git a/controller/src/command.rs b/controller/src/command.rs index 3c11bcd1..938eb829 100644 --- a/controller/src/command.rs +++ b/controller/src/command.rs @@ -1123,7 +1123,8 @@ where let updater_running = owner_api.updater_running.load(Ordering::Relaxed); controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| { let res = api.node_height(m)?; - let (validated, txs) = api.retrieve_txs(m, true, args.id, args.tx_slate_id)?; + // Note advanced query args not currently supported by command line client + let (validated, txs) = api.retrieve_txs(m, true, args.id, args.tx_slate_id, None)?; let include_status = !args.id.is_some() && !args.tx_slate_id.is_some(); // If view count is specified, restrict the TX list to `txs.len() - count` let first_tx = args @@ -1235,7 +1236,7 @@ where } Some(s) => s, }; - let (_, txs) = api.retrieve_txs(m, true, Some(args.id), None)?; + let (_, txs) = api.retrieve_txs(m, true, Some(args.id), None, None)?; match args.dump_file { None => { if txs[0].confirmed { diff --git a/controller/tests/accounts.rs b/controller/tests/accounts.rs index 88cbf576..744a5e14 100644 --- a/controller/tests/accounts.rs +++ b/controller/tests/accounts.rs @@ -135,7 +135,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { assert_eq!(wallet1_info.total, 5 * reward); assert_eq!(wallet1_info.amount_currently_spendable, (5 - cm) * reward); // check tx log as well - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; assert_eq!(txs.len(), 5); Ok(()) })?; @@ -159,7 +159,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { assert_eq!(wallet1_info.total, 7 * reward); assert_eq!(wallet1_info.amount_currently_spendable, 7 * reward); // check tx log as well - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; assert_eq!(txs.len(), 7); Ok(()) })?; @@ -178,7 +178,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { assert_eq!(wallet1_info.total, 0,); assert_eq!(wallet1_info.amount_currently_spendable, 0,); // check tx log as well - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; assert_eq!(txs.len(), 0); Ok(()) })?; @@ -210,7 +210,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?; assert!(wallet1_refreshed); assert_eq!(wallet1_info.last_confirmed_height, 13); - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; assert_eq!(txs.len(), 9); Ok(()) })?; @@ -225,7 +225,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { assert_eq!(wallet1_info.last_confirmed_height, 12); let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?; assert_eq!(wallet1_info.last_confirmed_height, 13); - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; println!("{:?}", txs); assert_eq!(txs.len(), 5); Ok(()) @@ -236,7 +236,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(m, true, 1)?; assert!(wallet2_refreshed); assert_eq!(wallet2_info.last_confirmed_height, 13); - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; assert_eq!(txs.len(), 1); Ok(()) })?; @@ -254,7 +254,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { assert_eq!(wallet2_info.total, 0,); assert_eq!(wallet2_info.amount_currently_spendable, 0,); // check tx log as well - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; assert_eq!(txs.len(), 0); Ok(()) })?; diff --git a/controller/tests/check.rs b/controller/tests/check.rs index 2034acc3..634cdd22 100644 --- a/controller/tests/check.rs +++ b/controller/tests/check.rs @@ -119,7 +119,7 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { assert_eq!(wallet1_info.total, bh * reward); assert_eq!(wallet1_info.amount_currently_spendable, (bh - cm) * reward); // check tx log as well - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; let (c, _) = libwallet::TxLogEntry::sum_confirmed(&txs); assert_eq!(wallet1_info.total, c); assert_eq!(txs.len(), bh as usize); @@ -150,7 +150,7 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { // check we have a problem now wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| { let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?; - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; let (c, _) = libwallet::TxLogEntry::sum_confirmed(&txs); assert!(wallet1_info.total != c); Ok(()) diff --git a/controller/tests/invoice.rs b/controller/tests/invoice.rs index 8faf8603..70511d32 100644 --- a/controller/tests/invoice.rs +++ b/controller/tests/invoice.rs @@ -146,7 +146,7 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { // Check transaction log for wallet 2 wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| { let (_, wallet2_info) = api.retrieve_summary_info(m, true, 1)?; - let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?; + let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?; assert!(refreshed); assert!(txs.len() == 1); println!( @@ -161,7 +161,7 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { // exists wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| { let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?; - let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?; + let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?; assert!(refreshed); assert_eq!(txs.len() as u64, bh + 1); println!( diff --git a/controller/tests/no_change.rs b/controller/tests/no_change.rs index b18fb25e..cefba915 100644 --- a/controller/tests/no_change.rs +++ b/controller/tests/no_change.rs @@ -104,7 +104,7 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { // Refresh and check transaction log for wallet 1 wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| { - let (refreshed, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?; + let (refreshed, txs) = api.retrieve_txs(m, true, None, Some(slate.id), None)?; assert!(refreshed); let tx = txs[0].clone(); println!("SIMPLE SEND - SENDING WALLET"); @@ -117,7 +117,7 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { // Refresh and check transaction log for wallet 2 wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| { - let (refreshed, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?; + let (refreshed, txs) = api.retrieve_txs(m, true, None, Some(slate.id), None)?; assert!(refreshed); let tx = txs[0].clone(); println!("SIMPLE SEND - RECEIVING WALLET"); @@ -170,7 +170,7 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { // check wallet 2's version wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| { - let (refreshed, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?; + let (refreshed, txs) = api.retrieve_txs(m, true, None, Some(slate.id), None)?; assert!(refreshed); for tx in txs { stored_excess = tx.kernel_excess; @@ -184,7 +184,7 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { // Refresh and check transaction log for wallet 1 wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| { - let (refreshed, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?; + let (refreshed, txs) = api.retrieve_txs(m, true, None, Some(slate.id), None)?; assert!(refreshed); for tx in txs { println!("Wallet 1: {:?}", tx); diff --git a/controller/tests/payment_proofs.rs b/controller/tests/payment_proofs.rs index 92f919e3..edb416f3 100644 --- a/controller/tests/payment_proofs.rs +++ b/controller/tests/payment_proofs.rs @@ -116,7 +116,7 @@ fn payment_proofs_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err sender_api.tx_lock_outputs(m, &slate)?; // Ensure what's stored in TX log for payment proof is correct - let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id))?; + let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id), None)?; assert!(txs[0].payment_proof.is_some()); let pp = txs[0].clone().payment_proof.unwrap(); assert_eq!( diff --git a/controller/tests/repost.rs b/controller/tests/repost.rs index b0aef3a8..283164cf 100644 --- a/controller/tests/repost.rs +++ b/controller/tests/repost.rs @@ -154,7 +154,7 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> // Now repost from cached wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| { - let (_, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?; + let (_, txs) = api.retrieve_txs(m, true, None, Some(slate.id), None)?; println!("TXS[0]: {:?}", txs[0]); let stored_tx = api.get_stored_tx(m, None, Some(&txs[0].tx_slate_id.unwrap()))?; println!("Stored tx: {:?}", stored_tx); @@ -224,7 +224,7 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> // Now repost from cached wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| { - let (_, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?; + let (_, txs) = api.retrieve_txs(m, true, None, Some(slate.id), None)?; let stored_tx_slate = api.get_stored_tx(m, Some(txs[0].id), None)?.unwrap(); api.post_tx(m, &stored_tx_slate, false)?; bh += 1; diff --git a/controller/tests/revert.rs b/controller/tests/revert.rs index 57e73ad1..ea6c0b2a 100644 --- a/controller/tests/revert.rs +++ b/controller/tests/revert.rs @@ -133,7 +133,7 @@ fn revert( assert_eq!(info.amount_currently_spendable, (bh - cm) * reward); assert_eq!(info.amount_reverted, 0); // check tx log as well - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; let (c, _) = libwallet::TxLogEntry::sum_confirmed(&txs); assert_eq!(info.total, c); assert_eq!(txs.len(), bh as usize); @@ -148,7 +148,7 @@ fn revert( assert_eq!(info.amount_currently_spendable, 0); assert_eq!(info.amount_reverted, 0); // check tx log as well - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; assert_eq!(txs.len(), 0); Ok(()) })?; @@ -188,7 +188,7 @@ fn revert( assert_eq!(info.amount_currently_spendable, 0); assert_eq!(info.amount_reverted, 0); // check tx log as well - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; assert_eq!(txs.len(), 1); let tx = &txs[0]; assert_eq!(tx.tx_type, libwallet::TxLogEntryType::TxReceived); @@ -230,7 +230,7 @@ fn revert( assert_eq!(info.amount_currently_spendable, sent); assert_eq!(info.amount_reverted, 0); // check tx log as well - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; assert_eq!(txs.len(), 1); let tx = &txs[0]; assert_eq!(tx.tx_type, libwallet::TxLogEntryType::TxReceived); @@ -266,7 +266,7 @@ fn revert( assert_eq!(info.amount_currently_spendable, 0); assert_eq!(info.amount_reverted, sent); // check tx log as well - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; assert_eq!(txs.len(), 1); let tx = &txs[0]; assert_eq!(tx.tx_type, libwallet::TxLogEntryType::TxReverted); @@ -300,7 +300,7 @@ fn revert_reconfirm_impl(test_dir: &'static str) -> Result<(), libwallet::Error> assert_eq!(info.amount_currently_spendable, sent); assert_eq!(info.amount_reverted, 0); // check tx log as well - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; assert_eq!(txs.len(), 1); let tx = &txs[0]; assert_eq!(tx.tx_type, libwallet::TxLogEntryType::TxReceived); @@ -329,7 +329,7 @@ fn revert_cancel_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { assert_eq!(info.amount_currently_spendable, 0); assert_eq!(info.amount_reverted, sent); - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; assert_eq!(txs.len(), 1); let tx = &txs[0]; @@ -345,7 +345,7 @@ fn revert_cancel_impl(test_dir: &'static str) -> Result<(), libwallet::Error> { assert_eq!(info.amount_reverted, 0); // Check updated tx log - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; assert_eq!(txs.len(), 1); let tx = &txs[0]; assert_eq!(tx.tx_type, libwallet::TxLogEntryType::TxReceivedCancelled); diff --git a/controller/tests/transaction.rs b/controller/tests/transaction.rs index 0293555b..fa34014b 100644 --- a/controller/tests/transaction.rs +++ b/controller/tests/transaction.rs @@ -145,7 +145,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error> // Check transaction log for wallet 1 wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| { let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?; - let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?; + let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?; assert!(refreshed); let fee = core::libtx::tx_fee( wallet1_info.last_confirmed_height as usize - cm as usize, @@ -166,7 +166,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error> // Check transaction log for wallet 2 wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| { - let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?; + let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?; assert!(refreshed); // we should have a transaction entry for this slate let tx = txs.iter().find(|t| t.tx_slate_id == Some(slate.id)); @@ -211,7 +211,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error> assert_eq!(wallet1_info.amount_immature, cm * reward + fee); // check tx log entry is confirmed - let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?; + let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?; assert!(refreshed); let tx = txs.iter().find(|t| t.tx_slate_id == Some(slate.id)); assert!(tx.is_some()); @@ -247,7 +247,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error> assert_eq!(wallet2_info.amount_currently_spendable, amount); // check tx log entry is confirmed - let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?; + let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?; assert!(refreshed); let tx = txs.iter().find(|t| t.tx_slate_id == Some(slate.id)); assert!(tx.is_some()); @@ -315,7 +315,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error> wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| { let (refreshed, _wallet1_info) = sender_api.retrieve_summary_info(m, true, 1)?; assert!(refreshed); - let (_, txs) = sender_api.retrieve_txs(m, true, None, None)?; + let (_, txs) = sender_api.retrieve_txs(m, true, None, None, None)?; // find the transaction let tx = txs .iter() @@ -344,7 +344,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error> assert_eq!(wallet2_info.amount_currently_spendable, amount * 3); // check tx log entry is confirmed - let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?; + let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?; assert!(refreshed); let tx = txs.iter().find(|t| t.tx_slate_id == Some(slate.id)); assert!(tx.is_some()); @@ -474,7 +474,7 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> { wallet1_info.last_confirmed_height ); assert!(refreshed); - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; // we should have a transaction entry for this slate let tx = txs.iter().find(|t| t.tx_slate_id == Some(slate.id)); assert!(tx.is_some()); @@ -499,7 +499,7 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> { // Check transaction log for wallet 2 wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| { - let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?; + let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?; assert!(refreshed); let mut unconfirmed_count = 0; let tx = txs.iter().find(|t| t.tx_slate_id == Some(slate.id)); @@ -529,7 +529,7 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> { // can't roll back coinbase let res = api.cancel_tx(m, Some(1), None); assert!(res.is_err()); - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; let tx = txs .iter() .find(|t| t.tx_slate_id == Some(slate.id)) @@ -556,7 +556,7 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> { // Wallet 2 rolls back wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| { - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; let tx = txs .iter() .find(|t| t.tx_slate_id == Some(slate.id)) diff --git a/controller/tests/ttl_cutoff.rs b/controller/tests/ttl_cutoff.rs index 47c66e9c..ec4340bc 100644 --- a/controller/tests/ttl_cutoff.rs +++ b/controller/tests/ttl_cutoff.rs @@ -95,7 +95,7 @@ fn ttl_cutoff_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> slate = client1.send_tx_slate_direct("wallet2", &slate_i)?; sender_api.tx_lock_outputs(m, &slate)?; - let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id))?; + let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id), None)?; let tx = txs[0].clone(); assert_eq!(tx.ttl_cutoff_height, Some(12)); @@ -106,7 +106,7 @@ fn ttl_cutoff_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 2, false); wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| { - let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id))?; + let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id), None)?; let tx = txs[0].clone(); assert_eq!(tx.ttl_cutoff_height, Some(12)); @@ -116,7 +116,7 @@ fn ttl_cutoff_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> // Should also be gone in wallet 2, and output gone wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |sender_api, m| { - let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id))?; + let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id), None)?; let tx = txs[0].clone(); let outputs = sender_api.retrieve_outputs(m, false, true, None)?.1; assert_eq!(outputs.len(), 0); @@ -144,7 +144,7 @@ fn ttl_cutoff_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> sender_api.tx_lock_outputs(m, &slate_i)?; slate = slate_i; - let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id))?; + let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id), None)?; let tx = txs[0].clone(); assert_eq!(tx.ttl_cutoff_height, Some(14)); @@ -156,7 +156,7 @@ fn ttl_cutoff_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> // Wallet 2 will need to have updated past the TTL wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |sender_api, m| { - let (_, _) = sender_api.retrieve_txs(m, true, None, Some(slate.id))?; + let (_, _) = sender_api.retrieve_txs(m, true, None, Some(slate.id), None)?; Ok(()) })?; diff --git a/libwallet/src/api_impl/foreign.rs b/libwallet/src/api_impl/foreign.rs index 7a21075c..be08950f 100644 --- a/libwallet/src/api_impl/foreign.rs +++ b/libwallet/src/api_impl/foreign.rs @@ -82,6 +82,7 @@ where &mut *w, None, Some(ret_slate.id), + None, Some(&parent_key_id), use_test_rng, )?; diff --git a/libwallet/src/api_impl/owner.rs b/libwallet/src/api_impl/owner.rs index 5e410ddc..0ab87e47 100644 --- a/libwallet/src/api_impl/owner.rs +++ b/libwallet/src/api_impl/owner.rs @@ -334,7 +334,14 @@ where wallet_lock!(wallet_inst, w); let parent_key_id = w.parent_key_id(); - let txs = updater::retrieve_txs(&mut **w, tx_id, tx_slate_id, Some(&parent_key_id), false)?; + let txs = updater::retrieve_txs( + &mut **w, + tx_id, + tx_slate_id, + query_args, + Some(&parent_key_id), + false, + )?; Ok((validated, txs)) } @@ -405,6 +412,7 @@ where refresh_from_node, tx_id, tx_slate_id, + None, )?; if txs.1.len() != 1 { return Err(Error::PaymentProofRetrieval( @@ -663,6 +671,7 @@ where &mut *w, None, Some(ret_slate.id), + None, Some(&parent_key_id), use_test_rng, )?; @@ -1123,7 +1132,7 @@ where // Step 2: Update outstanding transactions with no change outputs by kernel let mut txs = { wallet_lock!(wallet_inst, w); - updater::retrieve_txs(&mut **w, None, None, Some(&parent_key_id), true)? + updater::retrieve_txs(&mut **w, None, None, None, Some(&parent_key_id), true)? }; result = update_txs_via_kernel(wallet_inst.clone(), keychain_mask, &mut txs)?; if !result { diff --git a/libwallet/src/api_impl/types.rs b/libwallet/src/api_impl/types.rs index 362685e4..2cc81867 100644 --- a/libwallet/src/api_impl/types.rs +++ b/libwallet/src/api_impl/types.rs @@ -23,6 +23,7 @@ use crate::slate_versions::SlateVersion; use crate::types::OutputData; use crate::SlatepackAddress; +use chrono::prelude::*; use ed25519_dalek::Signature as DalekSignature; /// Type for storing amounts (in nanogrins). @@ -148,6 +149,32 @@ impl Default for IssueInvoiceTxArgs { } } +/// Sort tx retrieval order +#[derive(Clone, Serialize, Deserialize)] +pub enum RetrieveTxQuerySortOrder { + /// Ascending + Asc, + /// Descending + Desc, +} + +/// Valid sort fields for a transaction list retrieval query +#[derive(Clone, Serialize, Deserialize)] +pub enum RetrieveTxQuerySortField { + /// Transaction Id + Id, + /// Creation Timestamp + CreationTimestamp, + /// Confirmation Timestamp + ConfirmationTimestamp, + /// TotalAmount (AmountCredited-AmountDebited) + TotalAmount, + /// Amount Credited + AmountCredited, + /// Amount Debited + AmountDebited, +} + /// Retrieve Transaction List Pagination Arguments #[derive(Clone, Serialize, Deserialize)] pub struct RetrieveTxQueryArgs { @@ -163,6 +190,27 @@ pub struct RetrieveTxQueryArgs { pub limit: Option, /// whether to include cancelled transactions in the returned set pub include_cancelled: Option, + /// whether to only consider non-cancelled, outstanding transactions + pub include_outstanding_only: Option, + /// whether to only consider confirmed-only transactions + pub include_confirmed_only: Option, + /// lower bound on the total amount (amount_credited - amount_debited), inclusive + pub min_amount_inc: Option, + /// higher bound on the total amount (amount_credited - amount_debited), inclusive + pub max_amount_inc: Option, + /// lower bound on the creation timestamp, inclusive + pub min_creation_timestamp_inc: Option>, + /// higher bound on on the creation timestamp, inclusive + pub max_creation_timestamp_inc: Option>, + /// lower bound on the confirmation timestamp, inclusive + pub min_confirmed_timestamp_inc: Option>, + /// higher bound on the confirmation timestamp, inclusive + pub max_confirmed_timestamp_inc: Option>, + /// Field within the tranasction list on which to sort + /// defaults to ID if not present + pub sort_field: Option, + /// Sort order, defaults to DESC if not present (most recent is first) + pub sort_order: Option, } impl Default for RetrieveTxQueryArgs { @@ -171,7 +219,17 @@ impl Default for RetrieveTxQueryArgs { before_id_inc: None, after_id_inc: None, limit: None, - include_cancelled: None, + include_cancelled: Some(true), + include_outstanding_only: Some(false), + include_confirmed_only: Some(false), + min_amount_inc: None, + max_amount_inc: None, + min_creation_timestamp_inc: None, + max_creation_timestamp_inc: None, + min_confirmed_timestamp_inc: None, + max_confirmed_timestamp_inc: None, + sort_field: Some(RetrieveTxQuerySortField::Id), + sort_order: Some(RetrieveTxQuerySortOrder::Desc), } } } diff --git a/libwallet/src/internal/scan.rs b/libwallet/src/internal/scan.rs index f8d9f7f1..129e99ca 100644 --- a/libwallet/src/internal/scan.rs +++ b/libwallet/src/internal/scan.rs @@ -378,6 +378,7 @@ where &mut **w, output.tx_log_entry, None, + None, Some(&parent_key_id), false, )?; diff --git a/libwallet/src/internal/tx.rs b/libwallet/src/internal/tx.rs index a4a40c3e..a5dde1aa 100644 --- a/libwallet/src/internal/tx.rs +++ b/libwallet/src/internal/tx.rs @@ -351,7 +351,14 @@ where } else if let Some(tx_slate_id) = tx_slate_id { tx_id_string = tx_slate_id.to_string(); } - let tx_vec = updater::retrieve_txs(wallet, tx_id, tx_slate_id, Some(&parent_key_id), false)?; + let tx_vec = updater::retrieve_txs( + wallet, + tx_id, + tx_slate_id, + None, + Some(&parent_key_id), + false, + )?; if tx_vec.len() != 1 { return Err(Error::TransactionDoesntExist(tx_id_string)); } @@ -390,7 +397,7 @@ where K: Keychain + 'a, { // finalize command - let tx_vec = updater::retrieve_txs(wallet, None, Some(slate.id), None, false)?; + let tx_vec = updater::retrieve_txs(wallet, None, Some(slate.id), None, None, false)?; let mut tx = None; // don't want to assume this is the right tx, in case of self-sending for t in tx_vec { @@ -511,7 +518,14 @@ where C: NodeClient + 'a, K: Keychain + 'a, { - let tx_vec = updater::retrieve_txs(wallet, None, Some(slate.id), Some(parent_key_id), false)?; + let tx_vec = updater::retrieve_txs( + wallet, + None, + Some(slate.id), + None, + Some(parent_key_id), + false, + )?; if tx_vec.is_empty() { return Err(Error::PaymentProof( "TxLogEntry with original proof info not found (is account correct?)".to_owned(), diff --git a/libwallet/src/internal/updater.rs b/libwallet/src/internal/updater.rs index da2209e3..eb93ee3a 100644 --- a/libwallet/src/internal/updater.rs +++ b/libwallet/src/internal/updater.rs @@ -33,7 +33,7 @@ use crate::internal::keys; use crate::types::{ NodeClient, OutputData, OutputStatus, TxLogEntry, TxLogEntryType, WalletBackend, WalletInfo, }; -use crate::{BlockFees, CbData, OutputCommitMapping}; +use crate::{BlockFees, CbData, OutputCommitMapping, RetrieveTxQueryArgs}; /// Retrieve all of the outputs (doesn't attempt to update from node) pub fn retrieve_outputs<'a, T: ?Sized, C, K>( @@ -94,6 +94,7 @@ pub fn retrieve_txs<'a, T: ?Sized, C, K>( wallet: &mut T, tx_id: Option, tx_slate_id: Option, + query_args: Option, parent_key_id: Option<&Identifier>, outstanding_only: bool, ) -> Result, Error> @@ -102,34 +103,41 @@ where C: NodeClient + 'a, K: Keychain + 'a, { - let mut txs: Vec = wallet - .tx_log_iter() - .filter(|tx_entry| { - let f_pk = match parent_key_id { - Some(k) => tx_entry.parent_key_id == *k, - None => true, - }; - let f_tx_id = match tx_id { - Some(i) => tx_entry.id == i, - None => true, - }; - let f_txs = match tx_slate_id { - Some(t) => tx_entry.tx_slate_id == Some(t), - None => true, - }; - let f_outstanding = match outstanding_only { - true => { - !tx_entry.confirmed - && (tx_entry.tx_type == TxLogEntryType::TxReceived - || tx_entry.tx_type == TxLogEntryType::TxSent - || tx_entry.tx_type == TxLogEntryType::TxReverted) - } - false => true, - }; - f_pk && f_tx_id && f_txs && f_outstanding - }) - .collect(); - txs.sort_by_key(|tx| tx.creation_ts); + let mut txs: Vec = vec![]; + // Adding in new tranasction list query logic. If `tx_id` or `tx_slate_id` + // is provided, then `query_args` is ignored and old logic is followed. + if tx_id.is_some() || tx_slate_id.is_some() { + txs = wallet + .tx_log_iter() + .filter(|tx_entry| { + let f_pk = match parent_key_id { + Some(k) => tx_entry.parent_key_id == *k, + None => true, + }; + let f_tx_id = match tx_id { + Some(i) => tx_entry.id == i, + None => true, + }; + let f_txs = match tx_slate_id { + Some(t) => tx_entry.tx_slate_id == Some(t), + None => true, + }; + let f_outstanding = match outstanding_only { + true => { + !tx_entry.confirmed + && (tx_entry.tx_type == TxLogEntryType::TxReceived + || tx_entry.tx_type == TxLogEntryType::TxSent + || tx_entry.tx_type == TxLogEntryType::TxReverted) + } + false => true, + }; + f_pk && f_tx_id && f_txs && f_outstanding + }) + .collect(); + txs.sort_by_key(|tx| tx.creation_ts); + } else { + // TODO: Call Query Filter Function + } Ok(txs) } @@ -171,7 +179,7 @@ where .filter(|x| x.root_key_id == *parent_key_id && x.status != OutputStatus::Spent) .collect(); - let tx_entries = retrieve_txs(wallet, None, None, Some(&parent_key_id), true)?; + let tx_entries = retrieve_txs(wallet, None, None, None, Some(&parent_key_id), true)?; // Only select outputs that are actually involved in an outstanding transaction let unspents = match update_all { diff --git a/libwallet/src/lib.rs b/libwallet/src/lib.rs index ec17cd01..3c663a9c 100644 --- a/libwallet/src/lib.rs +++ b/libwallet/src/lib.rs @@ -65,7 +65,8 @@ pub use crate::slatepack::{ pub use api_impl::owner_updater::StatusMessage; pub use api_impl::types::{ Amount, BlockFees, BuiltOutput, InitTxArgs, InitTxSendArgs, IssueInvoiceTxArgs, - NodeHeightResult, OutputCommitMapping, PaymentProof, RetrieveTxQueryArgs, VersionInfo, + NodeHeightResult, OutputCommitMapping, PaymentProof, RetrieveTxQueryArgs, + RetrieveTxQuerySortField, RetrieveTxQuerySortOrder, VersionInfo, }; pub use internal::scan::scan; pub use slate_versions::ser as dalek_ser; diff --git a/tests/cmd_line_basic.rs b/tests/cmd_line_basic.rs index 56ecf2d0..bce4a8d0 100644 --- a/tests/cmd_line_basic.rs +++ b/tests/cmd_line_basic.rs @@ -238,7 +238,7 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller:: None, |api, m| { api.set_active_account(m, "mining")?; - let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?; + let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?; assert!(refreshed); assert_eq!(txs.len(), bh as usize); for t in txs { @@ -436,7 +436,7 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller:: None, |api, m| { api.set_active_account(m, "mining")?; - let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?; + let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?; assert!(refreshed); assert_eq!(txs.len(), bh as usize); Ok(()) @@ -509,7 +509,7 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller:: None, |api, m| { api.set_active_account(m, "mining")?; - let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?; + let (refreshed, txs) = api.retrieve_txs(m, true, None, None, None)?; assert!(refreshed); assert_eq!(txs.len(), bh as usize + 1); Ok(()) @@ -634,7 +634,7 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller:: None, |api, m| { api.set_active_account(m, "default")?; - let (_, txs) = api.retrieve_txs(m, true, None, None)?; + let (_, txs) = api.retrieve_txs(m, true, None, None, None)?; let some_tx_id = txs[0].tx_slate_id.clone(); assert!(some_tx_id.is_some()); tx_id = some_tx_id.unwrap().to_hyphenated().to_string().clone();