Avoid unnecessary panic of some wallet commands (#1893)

Replace wallet command panic with map_err or unwrap_or_else
This commit is contained in:
Gary Yu 2018-11-01 04:26:17 +08:00 committed by Ignotus Peverell
parent d51522a9cd
commit e8f4c47178

View file

@ -28,6 +28,7 @@ use clap::ArgMatches;
use api::TLSConfig; use api::TLSConfig;
use config::GlobalWalletConfig; use config::GlobalWalletConfig;
use core::{core, global}; use core::{core, global};
use grin_wallet::libwallet::ErrorKind;
use grin_wallet::{self, controller, display, libwallet}; use grin_wallet::{self, controller, display, libwallet};
use grin_wallet::{ use grin_wallet::{
HTTPWalletClient, LMDBBackend, WalletBackend, WalletConfig, WalletInst, WalletSeed, HTTPWalletClient, LMDBBackend, WalletBackend, WalletConfig, WalletInst, WalletSeed,
@ -123,13 +124,15 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) {
return; return;
} }
let passphrase = wallet_args let passphrase = wallet_args.value_of("pass").unwrap_or_else(|| {
.value_of("pass") error!("Failed to read passphrase.");
.expect("Failed to read passphrase."); exit(1);
});
let account = wallet_args let account = wallet_args.value_of("account").unwrap_or_else(|| {
.value_of("account") error!("Failed to read account.");
.expect("Failed to read account."); exit(1);
});
// Handle listener startup commands // Handle listener startup commands
{ {
@ -148,7 +151,10 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) {
wallet_config wallet_config
.tls_certificate_key .tls_certificate_key
.clone() .clone()
.expect("Private key for certificate is not set"), .unwrap_or_else(|| {
error!("Private key for certificate is not set");
exit(1);
}),
)), )),
}; };
match wallet_args.subcommand() { match wallet_args.subcommand() {
@ -158,20 +164,22 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) {
} }
controller::foreign_listener(wallet, &wallet_config.api_listen_addr(), tls_conf) controller::foreign_listener(wallet, &wallet_config.api_listen_addr(), tls_conf)
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
panic!( error!(
"Error creating wallet listener: {:?} Config: {:?}", "Error creating wallet listener: {:?} Config: {:?}",
e, wallet_config e, wallet_config
) );
exit(1);
}); });
} }
("owner_api", Some(_api_args)) => { ("owner_api", Some(_api_args)) => {
// TLS is disabled because we bind to localhost // TLS is disabled because we bind to localhost
controller::owner_listener(wallet, "127.0.0.1:13420", api_secret, None) controller::owner_listener(wallet, "127.0.0.1:13420", api_secret, None)
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
panic!( error!(
"Error creating wallet api listener: {:?} Config: {:?}", "Error creating wallet api listener: {:?} Config: {:?}",
e, wallet_config e, wallet_config
) );
exit(1);
}); });
} }
("web", Some(_api_args)) => { ("web", Some(_api_args)) => {
@ -179,10 +187,11 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) {
start_webwallet_server(); start_webwallet_server();
controller::owner_listener(wallet, "127.0.0.1:13420", api_secret, tls_conf) controller::owner_listener(wallet, "127.0.0.1:13420", api_secret, tls_conf)
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
panic!( error!(
"Error creating wallet api listener: {:?} Config: {:?}", "Error creating wallet api listener: {:?} Config: {:?}",
e, wallet_config e, wallet_config
) );
exit(1);
}); });
} }
_ => {} _ => {}
@ -209,7 +218,8 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) {
Ok(()) Ok(())
}); });
if res.is_err() { if res.is_err() {
panic!("Error listing accounts: {}", res.unwrap_err()); error!("Error listing accounts: {}", res.unwrap_err());
exit(1);
} }
} else { } else {
let label = create.unwrap(); let label = create.unwrap();
@ -228,30 +238,53 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) {
Ok(()) Ok(())
} }
("send", Some(send_args)) => { ("send", Some(send_args)) => {
let amount = send_args let amount = send_args.value_of("amount").unwrap_or_else(|| {
.value_of("amount") error!("Amount to send required");
.expect("Amount to send required"); exit(1);
let amount = core::amount_from_hr_string(amount) });
.expect("Could not parse amount as a number with optional decimal point."); let amount = core::amount_from_hr_string(amount).map_err(|e| {
ErrorKind::GenericError(format!(
"Could not parse amount as a number with optional decimal point. e={:?}",
e
))
})?;
let minimum_confirmations: u64 = send_args let minimum_confirmations: u64 = send_args
.value_of("minimum_confirmations") .value_of("minimum_confirmations")
.unwrap() .unwrap_or_else(|| {
.parse() error!("Minimum confirmations to send required");
.expect("Could not parse minimum_confirmations as a whole number."); exit(1);
let selection_strategy = send_args }).parse()
.value_of("selection_strategy") .map_err(|e| {
.expect("Selection strategy required"); ErrorKind::GenericError(format!(
let method = send_args "Could not parse minimum_confirmations as a whole number. e={:?}",
.value_of("method") e
.expect("Payment method required"); ))
let dest = send_args })?;
.value_of("dest") let selection_strategy =
.expect("Destination wallet address required"); send_args.value_of("selection_strategy").unwrap_or_else(|| {
error!("Selection strategy required");
exit(1);
});
let method = send_args.value_of("method").unwrap_or_else(|| {
error!("Payment method required");
exit(1);
});
let dest = send_args.value_of("dest").unwrap_or_else(|| {
error!("Destination wallet address required");
exit(1);
});
let change_outputs = send_args let change_outputs = send_args
.value_of("change_outputs") .value_of("change_outputs")
.unwrap() .unwrap_or_else(|| {
.parse() error!("Change outputs required");
.expect("Failed to parse number of change outputs."); exit(1);
}).parse()
.map_err(|e| {
ErrorKind::GenericError(format!(
"Failed to parse number of change outputs. e={:?}",
e
))
})?;
let fluff = send_args.is_present("fluff"); let fluff = send_args.is_present("fluff");
let max_outputs = 500; let max_outputs = 500;
if method == "http" { if method == "http" {
@ -286,7 +319,7 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) {
error!("Backtrace: {}", e.backtrace().unwrap()); error!("Backtrace: {}", e.backtrace().unwrap());
} }
}; };
panic!(); exit(1);
} }
}; };
let result = api.post_tx(&slate, fluff); let result = api.post_tx(&slate, fluff);
@ -305,7 +338,7 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) {
"HTTP Destination should start with http://: or https://: {}", "HTTP Destination should start with http://: or https://: {}",
dest dest
); );
panic!(); exit(1);
} }
} else if method == "file" { } else if method == "file" {
api.send_tx( api.send_tx(
@ -316,18 +349,19 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) {
max_outputs, max_outputs,
change_outputs, change_outputs,
selection_strategy == "all", selection_strategy == "all",
).expect("Send failed"); ).map_err(|e| ErrorKind::GenericError(format!("Send failed. e={:?}", e)))?;
Ok(()) Ok(())
} else { } else {
error!("unsupported payment method: {}", method); error!("unsupported payment method: {}", method);
panic!(); exit(1);
} }
} }
("receive", Some(send_args)) => { ("receive", Some(send_args)) => {
let mut receive_result: Result<(), grin_wallet::libwallet::Error> = Ok(()); let mut receive_result: Result<(), grin_wallet::libwallet::Error> = Ok(());
let tx_file = send_args let tx_file = send_args.value_of("input").unwrap_or_else(|| {
.value_of("input") error!("Transaction file required");
.expect("Transaction file required"); exit(1);
});
if !Path::new(tx_file).is_file() { if !Path::new(tx_file).is_file() {
error!("File {} not found.", { tx_file }); error!("File {} not found.", { tx_file });
exit(1); exit(1);
@ -348,9 +382,10 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) {
} }
("finalize", Some(send_args)) => { ("finalize", Some(send_args)) => {
let fluff = send_args.is_present("fluff"); let fluff = send_args.is_present("fluff");
let tx_file = send_args let tx_file = send_args.value_of("input").unwrap_or_else(|| {
.value_of("input") error!("Receiver's transaction file required");
.expect("Receiver's transaction file required"); exit(1);
});
if !Path::new(tx_file).is_file() { if !Path::new(tx_file).is_file() {
error!("File {} not found.", { tx_file }); error!("File {} not found.", { tx_file });
exit(1); exit(1);
@ -393,26 +428,24 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) {
Ok(()) Ok(())
} }
("info", Some(_)) => { ("info", Some(_)) => {
let (validated, wallet_info) = let (validated, wallet_info) = api.retrieve_summary_info(true).map_err(|e| {
api.retrieve_summary_info(true).unwrap_or_else(|e| { ErrorKind::GenericError(format!(
panic!( "Error getting wallet info: {:?} Config: {:?}",
"Error getting wallet info: {:?} Config: {:?}", e, wallet_config
e, wallet_config ))
) })?;
});
display::info(account, &wallet_info, validated); display::info(account, &wallet_info, validated);
Ok(()) Ok(())
} }
("outputs", Some(_)) => { ("outputs", Some(_)) => {
let (height, _) = api.node_height()?; let (height, _) = api.node_height()?;
let (validated, outputs) = api.retrieve_outputs(show_spent, true, None)?; let (validated, outputs) = api.retrieve_outputs(show_spent, true, None)?;
let _res = display::outputs(account, height, validated, outputs).map_err(|e| {
display::outputs(account, height, validated, outputs).unwrap_or_else(|e| { ErrorKind::GenericError(format!(
panic!( "Error getting wallet outputs: {:?} Config: {:?}",
"Error getting wallet outputs: {:?} Config: {:?}", e, wallet_config
e, wallet_config ))
) })?;
});
Ok(()) Ok(())
} }
("txs", Some(txs_args)) => { ("txs", Some(txs_args)) => {
@ -420,46 +453,48 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) {
None => None, None => None,
Some(tx) => match tx.parse() { Some(tx) => match tx.parse() {
Ok(t) => Some(t), Ok(t) => Some(t),
Err(_) => panic!("Unable to parse argument 'id' as a number"), Err(_) => {
error!("Unable to parse argument 'id' as a number");
exit(1);
}
}, },
}; };
let (height, _) = api.node_height()?; let (height, _) = api.node_height()?;
let (validated, txs) = api.retrieve_txs(true, tx_id)?; let (validated, txs) = api.retrieve_txs(true, tx_id)?;
let include_status = !tx_id.is_some(); let include_status = !tx_id.is_some();
let _res = display::txs(account, height, validated, txs, include_status) display::txs(account, height, validated, txs, include_status).map_err(|e| {
.unwrap_or_else(|e| { ErrorKind::GenericError(format!(
panic!( "Error getting wallet outputs: {} Config: {:?}",
"Error getting wallet outputs: {} Config: {:?}", e, wallet_config
e, wallet_config ))
) })?;
});
// if given a particular transaction id, also get and display associated // if given a particular transaction id, also get and display associated
// inputs/outputs // inputs/outputs
if tx_id.is_some() { if tx_id.is_some() {
let (_, outputs) = api.retrieve_outputs(true, false, tx_id)?; let (_, outputs) = api.retrieve_outputs(true, false, tx_id)?;
let _res = display::outputs(account, height, validated, outputs) display::outputs(account, height, validated, outputs).map_err(|e| {
.unwrap_or_else(|e| { ErrorKind::GenericError(format!(
panic!( "Error getting wallet outputs: {} Config: {:?}",
"Error getting wallet outputs: {} Config: {:?}", e, wallet_config
e, wallet_config ))
) })?;
});
}; };
Ok(()) Ok(())
} }
("repost", Some(repost_args)) => { ("repost", Some(repost_args)) => {
let tx_id: u32 = match repost_args.value_of("id") { let tx_id = repost_args
None => { .value_of("id")
.unwrap_or_else(|| {
error!("Transaction of a completed but unconfirmed transaction required (specify with --id=[id])"); error!("Transaction of a completed but unconfirmed transaction required (specify with --id=[id])");
panic!(); exit(1);
} })
Some(tx) => match tx.parse() { .parse().map_err(|e| {
Ok(t) => t, ErrorKind::GenericError(format!(
Err(_) => { "Unable to parse argument 'id' as a number. e={:?}",
panic!("Unable to parse argument 'id' as a number"); e
} ))
}, })?;
};
let dump_file = repost_args.value_of("dumpfile"); let dump_file = repost_args.value_of("dumpfile");
let fluff = repost_args.is_present("fluff"); let fluff = repost_args.is_present("fluff");
match dump_file { match dump_file {
@ -494,8 +529,13 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) {
("cancel", Some(tx_args)) => { ("cancel", Some(tx_args)) => {
let tx_id = tx_args let tx_id = tx_args
.value_of("id") .value_of("id")
.expect("'id' argument (-i) is required."); .unwrap_or_else(|| {
let tx_id = tx_id.parse().expect("Could not parse id parameter."); error!("'id' argument (-i) is required.");
exit(1);
}).parse()
.map_err(|e| {
ErrorKind::GenericError(format!("Could not parse id parameter. e={:?}", e))
})?;
let result = api.cancel_tx(tx_id); let result = api.cancel_tx(tx_id);
match result { match result {
Ok(_) => { Ok(_) => {
@ -522,7 +562,10 @@ pub fn wallet_command(wallet_args: &ArgMatches, config: GlobalWalletConfig) {
} }
} }
} }
_ => panic!("Unknown wallet command, use 'grin help wallet' for details"), _ => {
error!("Unknown wallet command, use 'grin help wallet' for details");
exit(1);
}
} }
}); });
// we need to give log output a chance to catch up before exiting // we need to give log output a chance to catch up before exiting