From 88616fd341980d4ef408ecd7cc38a52b0a65db41 Mon Sep 17 00:00:00 2001 From: Yeastplume Date: Wed, 13 Jun 2018 21:58:45 +0100 Subject: [PATCH] [WIP] Updates to support web-wallet (#1160) * updates to support web wallet workflow * rustfmt * functions to support wallet, error handling * rustfmt * rebase rustfmt * test fix --- api/src/handlers.rs | 2 +- chain/src/chain.rs | 4 +- core/src/core/transaction.rs | 6 +- p2p/src/peers.rs | 2 +- pool/tests/block_reconciliation.rs | 2 +- servers/src/common/adapters.rs | 2 +- servers/src/grin/sync.rs | 4 +- servers/tests/framework/mod.rs | 2 +- src/bin/grin.rs | 4 +- src/bin/tui/table.rs | 8 +- src/bin/tui/types.rs | 2 +- wallet/src/display.rs | 2 +- wallet/src/file_wallet.rs | 21 +- wallet/src/libtx/slate.rs | 2 +- wallet/src/libwallet/api.rs | 17 +- wallet/src/libwallet/controller.rs | 220 +++++++++++++++++---- wallet/src/libwallet/error.rs | 4 +- wallet/src/libwallet/internal/restore.rs | 2 +- wallet/src/libwallet/internal/selection.rs | 9 +- wallet/src/libwallet/internal/updater.rs | 15 +- wallet/src/libwallet/types.rs | 17 ++ wallet/tests/transaction.rs | 2 +- 22 files changed, 260 insertions(+), 89 deletions(-) diff --git a/api/src/handlers.rs b/api/src/handlers.rs index 590876768..4e72f9a81 100644 --- a/api/src/handlers.rs +++ b/api/src/handlers.rs @@ -201,7 +201,7 @@ impl OutputHandler { ); let mut return_vec = vec![]; - for i in start_height..end_height + 1 { + for i in (start_height..=end_height).rev() { let res = self.outputs_at_height(i, commitments.clone(), include_rp); if res.outputs.len() > 0 { return_vec.push(res); diff --git a/chain/src/chain.rs b/chain/src/chain.rs index da89ea295..fa54f93f7 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -20,10 +20,10 @@ use std::fs::File; use std::sync::{Arc, Mutex, RwLock}; use std::time::{Duration, Instant}; +use core::core::Committed; use core::core::hash::{Hash, Hashed}; use core::core::pmmr::MerkleProof; use core::core::target::Difficulty; -use core::core::Committed; use core::core::{Block, BlockHeader, Output, OutputIdentifier, Transaction, TxKernel}; use core::global; use grin_store::Error::NotFoundErr; @@ -31,8 +31,8 @@ use pipe; use store; use txhashset; use types::*; -use util::secp::pedersen::{Commitment, RangeProof}; use util::LOGGER; +use util::secp::pedersen::{Commitment, RangeProof}; /// Orphan pool size is limited by MAX_ORPHAN_SIZE pub const MAX_ORPHAN_SIZE: usize = 200; diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs index 99daea7a1..04d204d88 100644 --- a/core/src/core/transaction.rs +++ b/core/src/core/transaction.rs @@ -14,8 +14,8 @@ //! Transactions -use std::cmp::max; use std::cmp::Ordering; +use std::cmp::max; use std::collections::HashSet; use std::io::Cursor; use std::{error, fmt}; @@ -26,12 +26,12 @@ use util::{kernel_sig_msg, static_secp_instance}; use consensus; use consensus::VerifySortOrder; +use core::BlockHeader; +use core::Committed; use core::committed; use core::global; use core::hash::{Hash, Hashed, ZERO_HASH}; use core::pmmr::MerkleProof; -use core::BlockHeader; -use core::Committed; use keychain; use keychain::BlindingFactor; use ser::{self, read_and_verify_sorted, ser_vec, PMMRable, Readable, Reader, Writeable, diff --git a/p2p/src/peers.rs b/p2p/src/peers.rs index 722d6a558..58723c0b6 100644 --- a/p2p/src/peers.rs +++ b/p2p/src/peers.rs @@ -675,7 +675,7 @@ impl NetAdapter for Peers { fn peer_difficulty(&self, addr: SocketAddr, diff: Difficulty, height: u64) { if diff != self.total_difficulty() || height != self.total_height() { - debug!( + trace!( LOGGER, "ping/pong: {}: {} @ {} vs us: {} @ {}", addr, diff --git a/pool/tests/block_reconciliation.rs b/pool/tests/block_reconciliation.rs index a63a3bf70..d4cdb12d8 100644 --- a/pool/tests/block_reconciliation.rs +++ b/pool/tests/block_reconciliation.rs @@ -29,9 +29,9 @@ use std::sync::{Arc, RwLock}; use core::core::{Block, BlockHeader}; +use chain::ChainStore; use chain::txhashset; use chain::types::Tip; -use chain::ChainStore; use core::core::target::Difficulty; use keychain::{ExtKeychain, Keychain}; diff --git a/servers/src/common/adapters.rs b/servers/src/common/adapters.rs index 95bdd0103..459395f93 100644 --- a/servers/src/common/adapters.rs +++ b/servers/src/common/adapters.rs @@ -35,8 +35,8 @@ use core::core::transaction::Transaction; use p2p; use pool; use store; -use util::OneTime; use util::LOGGER; +use util::OneTime; // All adapters use `Weak` references instead of `Arc` to avoid cycles that // can never be destroyed. These 2 functions are simple helpers to reduce the diff --git a/servers/src/grin/sync.rs b/servers/src/grin/sync.rs index ab8021d71..890f7f3ae 100644 --- a/servers/src/grin/sync.rs +++ b/servers/src/grin/sync.rs @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; use std::{cmp, thread}; use time; @@ -457,7 +457,7 @@ mod test { assert_eq!( get_locator_heights(10000), vec![ - 10000, 9998, 9994, 9986, 9970, 9938, 9874, 9746, 9490, 8978, 7954, 5906, 1810, 0, + 10000, 9998, 9994, 9986, 9970, 9938, 9874, 9746, 9490, 8978, 7954, 5906, 1810, 0 ] ); } diff --git a/servers/tests/framework/mod.rs b/servers/tests/framework/mod.rs index 61505d0d2..8dc35c2ed 100644 --- a/servers/tests/framework/mod.rs +++ b/servers/tests/framework/mod.rs @@ -305,7 +305,7 @@ impl LocalServerContainer { let mut wallet = FileWallet::new(config.clone(), "") .unwrap_or_else(|e| panic!("Error creating wallet: {:?} Config: {:?}", e, config)); wallet.keychain = Some(keychain); - wallet::libwallet::internal::updater::retrieve_info(&mut wallet).unwrap() + wallet::libwallet::internal::updater::retrieve_info(&mut wallet, true).unwrap() } pub fn send_amount_to( diff --git a/src/bin/grin.rs b/src/bin/grin.rs index 3ee29eff5..7314f1d06 100644 --- a/src/bin/grin.rs +++ b/src/bin/grin.rs @@ -681,7 +681,7 @@ fn wallet_command(wallet_args: &ArgMatches, global_config: GlobalConfig) { Ok(()) } ("info", Some(_)) => { - let _res = wallet::display::info(&api.retrieve_summary_info()?.1) + let _res = wallet::display::info(&api.retrieve_summary_info(true)?) .unwrap_or_else(|e| { panic!( "Error getting wallet info: {:?} Config: {:?}", @@ -692,7 +692,7 @@ fn wallet_command(wallet_args: &ArgMatches, global_config: GlobalConfig) { } ("outputs", Some(_)) => { let (height, validated) = api.node_height()?; - let (_, outputs) = api.retrieve_outputs(show_spent)?; + let (_, outputs) = api.retrieve_outputs(show_spent, true)?; let _res = wallet::display::outputs(height, validated, outputs).unwrap_or_else(|e| { panic!( diff --git a/src/bin/tui/table.rs b/src/bin/tui/table.rs index 80bf01dd7..91e953d8c 100644 --- a/src/bin/tui/table.rs +++ b/src/bin/tui/table.rs @@ -41,10 +41,8 @@ //! Adapted from https://github.com/behnam/rust-cursive-table-view //! A basic table view implementation for [cursive](https://crates.io/crates/cursive). -#![deny( - missing_docs, missing_copy_implementations, trivial_casts, trivial_numeric_casts, unsafe_code, - unused_import_braces, unused_qualifications -)] +#![deny(missing_docs, missing_copy_implementations, trivial_casts, trivial_numeric_casts, + unsafe_code, unused_import_braces, unused_qualifications)] // Crate Dependencies --------------------------------------------------------- extern crate cursive; @@ -56,6 +54,7 @@ use std::hash::Hash; use std::rc::Rc; // External Dependencies ------------------------------------------------------ +use cursive::With; use cursive::align::HAlign; use cursive::direction::Direction; use cursive::event::{Callback, Event, EventResult, Key}; @@ -63,7 +62,6 @@ use cursive::theme::ColorStyle; use cursive::theme::PaletteColor::*; use cursive::vec::Vec2; use cursive::view::{ScrollBase, View}; -use cursive::With; use cursive::{Cursive, Printer}; /// A trait for displaying and sorting items inside a diff --git a/src/bin/tui/types.rs b/src/bin/tui/types.rs index 24ec4001a..f899b4dd6 100644 --- a/src/bin/tui/types.rs +++ b/src/bin/tui/types.rs @@ -14,8 +14,8 @@ //! Types specific to the UI module -use cursive::view::View; use cursive::Cursive; +use cursive::view::View; use servers::ServerStats; /// Main message struct to communicate between the UI and diff --git a/wallet/src/display.rs b/wallet/src/display.rs index 2a183f926..d07ce4718 100644 --- a/wallet/src/display.rs +++ b/wallet/src/display.rs @@ -14,8 +14,8 @@ use core::core; use core::core::amount_to_hr_string; -use libwallet::types::{OutputData, WalletInfo}; use libwallet::Error; +use libwallet::types::{OutputData, WalletInfo}; use prettytable; use std::io::prelude::*; use term; diff --git a/wallet/src/file_wallet.rs b/wallet/src/file_wallet.rs index b810e753c..8f2ec5144 100644 --- a/wallet/src/file_wallet.rs +++ b/wallet/src/file_wallet.rs @@ -414,15 +414,26 @@ impl WalletClient for FileWallet { dest: &str, block_fees: &BlockFees, ) -> Result { - let res = - client::create_coinbase(dest, block_fees).context(libwallet::ErrorKind::WalletComms)?; - Ok(res) + let res = client::create_coinbase(dest, block_fees); + match res { + Ok(r) => Ok(r), + Err(e) => { + let message = format!("{}", e.cause().unwrap()); + Err(libwallet::ErrorKind::WalletComms(message))? + } + } } /// Send a transaction slate to another listening wallet and return result fn send_tx_slate(&self, dest: &str, slate: &Slate) -> Result { - let res = client::send_tx_slate(dest, slate).context(libwallet::ErrorKind::WalletComms)?; - Ok(res) + let res = client::send_tx_slate(dest, slate); + match res { + Ok(r) => Ok(r), + Err(e) => { + let message = format!("{}", e.cause().unwrap()); + Err(libwallet::ErrorKind::WalletComms(message))? + } + } } /// Posts a tranaction to a grin node diff --git a/wallet/src/libtx/slate.rs b/wallet/src/libtx/slate.rs index b6bf23451..df4ccc591 100644 --- a/wallet/src/libtx/slate.rs +++ b/wallet/src/libtx/slate.rs @@ -23,8 +23,8 @@ use keychain::{BlindSum, BlindingFactor, Keychain}; use libtx::error::{Error, ErrorKind}; use libtx::{aggsig, build, tx_fee}; -use util::secp::key::{PublicKey, SecretKey}; use util::secp::Signature; +use util::secp::key::{PublicKey, SecretKey}; use util::{secp, LOGGER}; /// Public data for each participant in the slate diff --git a/wallet/src/libwallet/api.rs b/wallet/src/libwallet/api.rs index 39d21cdce..22c523328 100644 --- a/wallet/src/libwallet/api.rs +++ b/wallet/src/libwallet/api.rs @@ -60,8 +60,12 @@ where pub fn retrieve_outputs( &mut self, include_spent: bool, + refresh_from_node: bool, ) -> Result<(bool, Vec), Error> { - let validated = self.update_outputs(); + let mut validated = false; + if refresh_from_node { + validated = self.update_outputs(); + } Ok(( validated, updater::retrieve_outputs(self.wallet, include_spent)?, @@ -69,9 +73,12 @@ where } /// Retrieve summary info for wallet - pub fn retrieve_summary_info(&mut self) -> Result<(bool, WalletInfo), Error> { - let validated = self.update_outputs(); - Ok((validated, updater::retrieve_info(self.wallet)?)) + pub fn retrieve_summary_info(&mut self, refresh_from_node: bool) -> Result { + let mut validated = false; + if refresh_from_node { + validated = self.update_outputs(); + } + updater::retrieve_info(self.wallet, validated) } /// Issues a send transaction and sends to recipient @@ -139,7 +146,7 @@ where match self.wallet.get_chain_height(self.wallet.node_url()) { Ok(height) => Ok((height, true)), Err(_) => { - let outputs = self.retrieve_outputs(true)?; + let outputs = self.retrieve_outputs(true, false)?; let height = match outputs.1.iter().map(|out| out.height).max() { Some(height) => height, None => 0, diff --git a/wallet/src/libwallet/controller.rs b/wallet/src/libwallet/controller.rs index 5d33cfddf..de3905aec 100644 --- a/wallet/src/libwallet/controller.rs +++ b/wallet/src/libwallet/controller.rs @@ -21,17 +21,20 @@ use std::sync::{Arc, Mutex}; use bodyparser; use iron::Handler; +use iron::Headers; use iron::prelude::*; use iron::status; use serde::Serialize; use serde_json; +use urlencoded::UrlEncodedQuery; use failure::Fail; use keychain::Keychain; use libtx::slate::Slate; use libwallet::api::{APIForeign, APIOwner}; -use libwallet::types::{BlockFees, CbData, OutputData, WalletBackend, WalletClient, WalletInfo}; +use libwallet::types::{BlockFees, CbData, OutputData, SendTXArgs, WalletBackend, WalletClient, + WalletInfo}; use libwallet::{Error, ErrorKind}; use util::LOGGER; @@ -69,13 +72,19 @@ where pub fn owner_listener(wallet: T, addr: &str) -> Result<(), Error> where T: WalletBackend + WalletClient, - OwnerAPIHandler: Handler, + OwnerAPIGetHandler: Handler, + OwnerAPIPostHandler: Handler, K: Keychain, { - let api_handler = OwnerAPIHandler::new(Arc::new(Mutex::new(wallet))); + let wallet_arc = Arc::new(Mutex::new(wallet)); + let api_get_handler = OwnerAPIGetHandler::new(wallet_arc.clone()); + let api_post_handler = OwnerAPIPostHandler::new(wallet_arc); + let api_options_handler = OwnerAPIOptionsHandler {}; let router = router!( - receive_tx: get "/wallet/owner/*" => api_handler, + owner_options: options "/wallet/owner/*" => api_options_handler, + owner_get: get "/wallet/owner/*" => api_get_handler, + owner_post: post "/wallet/owner/*" => api_post_handler, ); let mut apis = ApiServer::new("/v1".to_string()); @@ -117,7 +126,7 @@ where } /// API Handler/Wrapper for owner functions -pub struct OwnerAPIHandler +pub struct OwnerAPIGetHandler where T: WalletBackend, K: Keychain, @@ -127,13 +136,13 @@ where phantom: PhantomData, } -impl OwnerAPIHandler +impl OwnerAPIGetHandler where T: WalletBackend + WalletClient, K: Keychain, { - pub fn new(wallet: Arc>) -> OwnerAPIHandler { - OwnerAPIHandler { + pub fn new(wallet: Arc>) -> OwnerAPIGetHandler { + OwnerAPIGetHandler { wallet, phantom: PhantomData, } @@ -143,9 +152,14 @@ where &self, req: &mut Request, api: &mut APIOwner, - ) -> Result, Error> { - let res = api.retrieve_outputs(false)?; - Ok(res.1) + ) -> Result<(bool, Vec), Error> { + let mut update_from_node = false; + if let Ok(params) = req.get_ref::() { + if let Some(_) = params.get("refresh") { + update_from_node = true; + } + } + api.retrieve_outputs(false, update_from_node) } fn retrieve_summary_info( @@ -153,31 +167,32 @@ where req: &mut Request, api: &mut APIOwner, ) -> Result { - let res = api.retrieve_summary_info()?; - Ok(res.1) + let mut update_from_node = false; + if let Ok(params) = req.get_ref::() { + if let Some(_) = params.get("refresh") { + update_from_node = true; + } + } + api.retrieve_summary_info(update_from_node) } - fn issue_send_tx(&self, req: &mut Request, api: &mut APIOwner) -> Result<(), Error> { - // TODO: Args - api.issue_send_tx(60, 10, "", 1000, true, true) - } - - fn issue_burn_tx(&self, req: &mut Request, api: &mut APIOwner) -> Result<(), Error> { - // TODO: Args - api.issue_burn_tx(60, 10, 1000) + fn node_height( + &self, + req: &mut Request, + api: &mut APIOwner, + ) -> Result<(u64, bool), Error> { + api.node_height() } fn handle_request(&self, req: &mut Request, api: &mut APIOwner) -> IronResult { let url = req.url.clone(); let path_elems = url.path(); match *path_elems.last().unwrap() { - "retrieve_outputs" => json_response_pretty(&self.retrieve_outputs(req, api) + "retrieve_outputs" => json_response(&self.retrieve_outputs(req, api) .map_err(|e| IronError::new(Fail::compat(e), status::BadRequest))?), - "retrieve_summary_info" => json_response_pretty(&self.retrieve_summary_info(req, api) + "retrieve_summary_info" => json_response(&self.retrieve_summary_info(req, api) .map_err(|e| IronError::new(Fail::compat(e), status::BadRequest))?), - "issue_send_tx" => json_response_pretty(&self.issue_send_tx(req, api) - .map_err(|e| IronError::new(Fail::compat(e), status::BadRequest))?), - "issue_burn_tx" => json_response_pretty(&self.issue_burn_tx(req, api) + "node_height" => json_response(&self.node_height(req, api) .map_err(|e| IronError::new(Fail::compat(e), status::BadRequest))?), _ => Err(IronError::new( Fail::compat(ErrorKind::Hyper), @@ -187,7 +202,7 @@ where } } -impl Handler for OwnerAPIHandler +impl Handler for OwnerAPIGetHandler where T: WalletBackend + WalletClient + Send + Sync + 'static, K: Keychain + 'static, @@ -203,11 +218,13 @@ where })?; let mut api = APIOwner::new(&mut *wallet); let mut resp_json = self.handle_request(req, &mut api); - resp_json - .as_mut() - .unwrap() - .headers - .set_raw("access-control-allow-origin", vec![b"*".to_vec()]); + if !resp_json.is_err() { + resp_json + .as_mut() + .unwrap() + .headers + .set_raw("access-control-allow-origin", vec![b"*".to_vec()]); + } api.wallet .close() .map_err(|e| IronError::new(Fail::compat(e), status::BadRequest))?; @@ -215,6 +232,138 @@ where } } +pub struct OwnerAPIPostHandler +where + T: WalletBackend, + K: Keychain, +{ + /// Wallet instance + pub wallet: Arc>, + phantom: PhantomData, +} + +impl OwnerAPIPostHandler +where + T: WalletBackend + WalletClient, + K: Keychain, +{ + pub fn new(wallet: Arc>) -> OwnerAPIPostHandler { + OwnerAPIPostHandler { + wallet, + phantom: PhantomData, + } + } + + fn issue_send_tx(&self, req: &mut Request, api: &mut APIOwner) -> Result<(), Error> { + let struct_body = req.get::>(); + match struct_body { + Ok(Some(args)) => api.issue_send_tx( + args.amount, + args.minimum_confirmations, + &args.dest, + args.max_outputs, + args.selection_strategy_is_use_all, + args.fluff, + ), + Ok(None) => { + error!(LOGGER, "Missing request body: issue_send_tx"); + Err(ErrorKind::GenericError( + "Invalid request body: issue_send_tx", + ))? + } + Err(e) => { + error!(LOGGER, "Invalid request body: issue_send_tx {:?}", e); + Err(ErrorKind::GenericError( + "Invalid request body: issue_send_tx", + ))? + } + } + } + + fn issue_burn_tx(&self, req: &mut Request, api: &mut APIOwner) -> Result<(), Error> { + // TODO: Args + api.issue_burn_tx(60, 10, 1000) + } + + fn handle_request(&self, req: &mut Request, api: &mut APIOwner) -> Result { + let url = req.url.clone(); + let path_elems = url.path(); + match *path_elems.last().unwrap() { + "issue_send_tx" => json_response_pretty(&self.issue_send_tx(req, api)?), + "issue_burn_tx" => json_response_pretty(&self.issue_burn_tx(req, api)?), + _ => Err(ErrorKind::GenericError( + "Unknown error handling post request", + ))?, + } + } + + fn create_error_response(&self, e: Error) -> IronResult { + let mut headers = Headers::new(); + headers.set_raw("access-control-allow-origin", vec![b"*".to_vec()]); + headers.set_raw( + "access-control-allow-headers", + vec![b"Content-Type".to_vec()], + ); + let message = format!("{}", e.kind()); + let mut r = Response::with((status::InternalServerError, message)); + r.headers = headers; + Ok(r) + } + + fn create_ok_response(&self, json: &str) -> IronResult { + let mut headers = Headers::new(); + headers.set_raw("access-control-allow-origin", vec![b"*".to_vec()]); + let mut r = Response::with((status::Ok, json)); + r.headers = headers; + Ok(r) + } +} + +impl Handler for OwnerAPIPostHandler +where + T: WalletBackend + WalletClient + Send + Sync + 'static, + K: Keychain + 'static, +{ + fn handle(&self, req: &mut Request) -> IronResult { + // every request should open with stored credentials, + // do its thing and then de-init whatever secrets have been + // stored + let mut wallet = self.wallet.lock().unwrap(); + wallet.open_with_credentials().map_err(|e| { + error!(LOGGER, "Error opening wallet: {:?}", e); + IronError::new(Fail::compat(e), status::BadRequest) + })?; + let mut api = APIOwner::new(&mut *wallet); + let resp = match self.handle_request(req, &mut api) { + Ok(r) => self.create_ok_response(&r), + Err(e) => { + error!(LOGGER, "Request Error: {:?}", e); + self.create_error_response(e) + } + }; + api.wallet + .close() + .map_err(|e| IronError::new(Fail::compat(e), status::BadRequest))?; + resp + } +} + +/// Options handler +pub struct OwnerAPIOptionsHandler {} + +impl Handler for OwnerAPIOptionsHandler where { + fn handle(&self, _req: &mut Request) -> IronResult { + let mut resp_json = Ok(Response::with((status::Ok, "{}"))); + let mut headers = Headers::new(); + headers.set_raw("access-control-allow-origin", vec![b"*".to_vec()]); + headers.set_raw( + "access-control-allow-headers", + vec![b"Content-Type".to_vec()], + ); + resp_json.as_mut().unwrap().headers = headers; + resp_json + } +} /// API Handler/Wrapper for foreign functions pub struct ForeignAPIHandler @@ -291,7 +440,6 @@ where } } } - impl Handler for ForeignAPIHandler where T: WalletBackend + WalletClient + Send + Sync + 'static, @@ -328,12 +476,12 @@ where } // pretty-printed version of above -fn json_response_pretty(s: &T) -> IronResult +fn json_response_pretty(s: &T) -> Result where T: Serialize, { match serde_json::to_string_pretty(s) { - Ok(json) => Ok(Response::with((status::Ok, json))), - Err(_) => Ok(Response::with((status::InternalServerError, ""))), + Ok(json) => Ok(json), + Err(_) => Err(ErrorKind::Format)?, } } diff --git a/wallet/src/libwallet/error.rs b/wallet/src/libwallet/error.rs index 8fc71980b..95cfa7862 100644 --- a/wallet/src/libwallet/error.rs +++ b/wallet/src/libwallet/error.rs @@ -94,8 +94,8 @@ pub enum ErrorKind { Node, /// Error contacting wallet API - #[fail(display = "Wallet communication error")] - WalletComms, + #[fail(display = "Wallet Communication Error: {}", _0)] + WalletComms(String), /// Error originating from hyper. #[fail(display = "Hyper error")] diff --git a/wallet/src/libwallet/internal/restore.rs b/wallet/src/libwallet/internal/restore.rs index 0ec629b92..01814b56c 100644 --- a/wallet/src/libwallet/internal/restore.rs +++ b/wallet/src/libwallet/internal/restore.rs @@ -24,8 +24,8 @@ use keychain::{Identifier, Keychain}; use libtx::proof; use libwallet::types::*; use util; -use util::secp::pedersen; use util::LOGGER; +use util::secp::pedersen; fn get_merkle_proof_for_commit(node_addr: &str, commit: &str) -> Result { let url = format!("{}/v1/txhashset/merkleproof?id={}", node_addr, commit); diff --git a/wallet/src/libwallet/internal/selection.rs b/wallet/src/libwallet/internal/selection.rs index fad0c3236..5adbfa9d9 100644 --- a/wallet/src/libwallet/internal/selection.rs +++ b/wallet/src/libwallet/internal/selection.rs @@ -15,7 +15,7 @@ //! Selection of inputs for building transactions use keychain::{Identifier, Keychain}; -use libtx::{build, slate::Slate, tx_fee}; +use libtx::{build, tx_fee, slate::Slate}; use libwallet::error::{Error, ErrorKind}; use libwallet::internal::{keys, sigcontext}; use libwallet::types::*; @@ -93,12 +93,7 @@ where let coin = wallet_data.get_output(&id).unwrap().clone(); wallet_data.lock_output(&coin); } - // probably just want to leave as unconfirmed for now - // or create a new status - /*for id in lock_outputs { - let coin = wallet_data.get_output(&id).unwrap().clone(); - wallet_data.lock_output(&coin); - }*/ }) + }) }; Ok((slate, context, update_sender_wallet_fn)) diff --git a/wallet/src/libwallet/internal/updater.rs b/wallet/src/libwallet/internal/updater.rs index e8152d17a..b8862b3cb 100644 --- a/wallet/src/libwallet/internal/updater.rs +++ b/wallet/src/libwallet/internal/updater.rs @@ -16,8 +16,8 @@ //! the wallet storage and update them. use failure::ResultExt; -use std::collections::hash_map::Entry; use std::collections::HashMap; +use std::collections::hash_map::Entry; use core::consensus::reward; use core::core::{Output, TxKernel}; @@ -29,8 +29,8 @@ use libwallet::error::{Error, ErrorKind}; use libwallet::internal::keys; use libwallet::types::*; use util; -use util::secp::pedersen; use util::LOGGER; +use util::secp::pedersen; /// Retrieve all of the outputs (doesn't attempt to update from node) pub fn retrieve_outputs(wallet: &mut T, show_spent: bool) -> Result, Error> @@ -241,13 +241,12 @@ where } /// Retrieve summary info about the wallet -pub fn retrieve_info(wallet: &mut T) -> Result +/// caller should refresh first if desired +pub fn retrieve_info(wallet: &mut T, refreshed: bool) -> Result where T: WalletBackend + WalletClient, K: Keychain, { - let result = refresh_outputs(wallet); - let height_res = wallet.get_chain_height(&wallet.node_url()); let ret_val = wallet.read_wallet(|wallet_data| { @@ -282,10 +281,6 @@ where } } - let mut data_confirmed = true; - if let Err(_) = result { - data_confirmed = false; - } Ok(WalletInfo { current_height: current_height, total: unspent_total + unconfirmed_total, @@ -293,7 +288,7 @@ where amount_confirmed_but_locked: unspent_but_locked_total, amount_currently_spendable: unspent_total - unspent_but_locked_total, amount_locked: locked_total, - data_confirmed: data_confirmed, + data_confirmed: refreshed, data_confirmed_from: String::from(from), }) }); diff --git a/wallet/src/libwallet/types.rs b/wallet/src/libwallet/types.rs index dc8efff6e..95eafa43c 100644 --- a/wallet/src/libwallet/types.rs +++ b/wallet/src/libwallet/types.rs @@ -423,3 +423,20 @@ pub struct TxWrapper { /// hex representation of transaction pub tx_hex: String, } + +/// Send TX API Args +#[derive(Clone, Serialize, Deserialize)] +pub struct SendTXArgs { + /// amount to send + pub amount: u64, + /// minimum confirmations + pub minimum_confirmations: u64, + /// destination url + pub dest: String, + /// Max number of outputs + pub max_outputs: usize, + /// whether to use all outputs (combine) + pub selection_strategy_is_use_all: bool, + /// dandelion control + pub fluff: bool, +} diff --git a/wallet/tests/transaction.rs b/wallet/tests/transaction.rs index e8c4504b7..82b239ea3 100644 --- a/wallet/tests/transaction.rs +++ b/wallet/tests/transaction.rs @@ -29,8 +29,8 @@ mod common; use std::fs; use std::sync::Arc; -use chain::types::*; use chain::Chain; +use chain::types::*; use core::global::ChainTypes; use core::{global, pow}; use util::LOGGER;