aboutsummaryrefslogtreecommitdiff
path: root/src/simplewallet/simplewallet.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/simplewallet/simplewallet.cpp129
1 files changed, 128 insertions, 1 deletions
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index e47938357..33224aa19 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -295,6 +295,7 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("payments", boost::bind(&simple_wallet::show_payments, this, _1), "payments <payment_id_1> [<payment_id_2> ... <payment_id_N>] - Show payments <payment_id_1>, ... <payment_id_N>");
m_cmd_binder.set_handler("bc_height", boost::bind(&simple_wallet::show_blockchain_height, this, _1), "Show blockchain height");
m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer, this, _1), "transfer [<mixin_count>] <addr_1> <amount_1> [<addr_2> <amount_2> ... <addr_N> <amount_N>] [payment_id] - Transfer <amount_1>,... <amount_N> to <address_1>,... <address_N>, respectively. <mixin_count> is the number of transactions yours is indistinguishable from (from 0 to maximum available)");
+ m_cmd_binder.set_handler("sweep_dust", boost::bind(&simple_wallet::sweep_dust, this, _1), "Send all dust outputs to the same address with mixin 0");
m_cmd_binder.set_handler("set_log", boost::bind(&simple_wallet::set_log, this, _1), "set_log <level> - Change current log detalization level, <level> is a number 0-4");
m_cmd_binder.set_handler("address", boost::bind(&simple_wallet::print_address, this, _1), "Show current wallet public address");
m_cmd_binder.set_handler("save", boost::bind(&simple_wallet::save, this, _1), "Save wallet synchronized data");
@@ -942,7 +943,8 @@ bool simple_wallet::refresh(const std::vector<std::string>& args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::show_balance(const std::vector<std::string>& args/* = std::vector<std::string>()*/)
{
- success_msg_writer() << "balance: " << print_money(m_wallet->balance()) << ", unlocked balance: " << print_money(m_wallet->unlocked_balance());
+ success_msg_writer() << "balance: " << print_money(m_wallet->balance()) << ", unlocked balance: " << print_money(m_wallet->unlocked_balance())
+ << ", including unlocked dust: " << print_money(m_wallet->unlocked_dust_balance(tools::tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD)));
return true;
}
//----------------------------------------------------------------------------------------------------
@@ -1307,6 +1309,131 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
return true;
}
+
+//----------------------------------------------------------------------------------------------------
+bool simple_wallet::sweep_dust(const std::vector<std::string> &args_)
+{
+ if (!try_connect_to_daemon())
+ return true;
+
+ try
+ {
+ uint64_t total_dust = m_wallet->unlocked_dust_balance(tools::tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD));
+
+ // figure out what tx will be necessary
+ auto ptx_vector = m_wallet->create_dust_sweep_transactions();
+
+ // give user total and fee, and prompt to confirm
+ uint64_t total_fee = 0;
+ for (size_t n = 0; n < ptx_vector.size(); ++n)
+ {
+ total_fee += ptx_vector[n].fee;
+ }
+
+ std::string prompt_str = "Sweeping " + print_money(total_dust);
+ if (ptx_vector.size() > 1) {
+ prompt_str += " in ";
+ prompt_str += std::to_string(ptx_vector.size());
+ prompt_str += " transactions";
+ }
+ prompt_str += " for a total fee of " + print_money(total_fee);
+ prompt_str += ". Is this okay? (Y/Yes/N/No)";
+ std::string accepted = command_line::input_line(prompt_str);
+ if (accepted != "Y" && accepted != "y" && accepted != "Yes" && accepted != "yes")
+ {
+ fail_msg_writer() << "Transaction cancelled.";
+
+ // would like to return false, because no tx made, but everything else returns true
+ // and I don't know what returning false might adversely affect. *sigh*
+ return true;
+ }
+
+ // actually commit the transactions
+ while (!ptx_vector.empty())
+ {
+ auto & ptx = ptx_vector.back();
+ m_wallet->commit_tx(ptx);
+ success_msg_writer(true) << "Money successfully sent, transaction " << get_transaction_hash(ptx.tx);
+
+ // if no exception, remove element from vector
+ ptx_vector.pop_back();
+ }
+ }
+ catch (const tools::error::daemon_busy&)
+ {
+ fail_msg_writer() << "daemon is busy. Please try later";
+ }
+ catch (const tools::error::no_connection_to_daemon&)
+ {
+ fail_msg_writer() << "no connection to daemon. Please, make sure daemon is running.";
+ }
+ catch (const tools::error::wallet_rpc_error& e)
+ {
+ LOG_ERROR("Unknown RPC error: " << e.to_string());
+ fail_msg_writer() << "RPC error \"" << e.what() << '"';
+ }
+ catch (const tools::error::get_random_outs_error&)
+ {
+ fail_msg_writer() << "failed to get random outputs to mix";
+ }
+ catch (const tools::error::not_enough_money& e)
+ {
+ fail_msg_writer() << "not enough money to transfer, available only " << print_money(e.available()) <<
+ ", transaction amount " << print_money(e.tx_amount() + e.fee()) << " = " << print_money(e.tx_amount()) <<
+ " + " << print_money(e.fee()) << " (fee)";
+ }
+ catch (const tools::error::not_enough_outs_to_mix& e)
+ {
+ auto writer = fail_msg_writer();
+ writer << "not enough outputs for specified mixin_count = " << e.mixin_count() << ":";
+ for (const cryptonote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& outs_for_amount : e.scanty_outs())
+ {
+ writer << "\noutput amount = " << print_money(outs_for_amount.amount) << ", fount outputs to mix = " << outs_for_amount.outs.size();
+ }
+ }
+ catch (const tools::error::tx_not_constructed&)
+ {
+ fail_msg_writer() << "transaction was not constructed";
+ }
+ catch (const tools::error::tx_rejected& e)
+ {
+ fail_msg_writer() << "transaction " << get_transaction_hash(e.tx()) << " was rejected by daemon with status \"" << e.status() << '"';
+ }
+ catch (const tools::error::tx_sum_overflow& e)
+ {
+ fail_msg_writer() << e.what();
+ }
+ catch (const tools::error::zero_destination&)
+ {
+ fail_msg_writer() << "one of destinations is zero";
+ }
+ catch (const tools::error::tx_too_big& e)
+ {
+ fail_msg_writer() << "Failed to find a suitable way to split transactions";
+ }
+ catch (const tools::error::transfer_error& e)
+ {
+ LOG_ERROR("unknown transfer error: " << e.to_string());
+ fail_msg_writer() << "unknown transfer error: " << e.what();
+ }
+ catch (const tools::error::wallet_internal_error& e)
+ {
+ LOG_ERROR("internal error: " << e.to_string());
+ fail_msg_writer() << "internal error: " << e.what();
+ }
+ catch (const std::exception& e)
+ {
+ LOG_ERROR("unexpected error: " << e.what());
+ fail_msg_writer() << "unexpected error: " << e.what();
+ }
+ catch (...)
+ {
+ LOG_ERROR("Unknown error");
+ fail_msg_writer() << "unknown error";
+ }
+
+ return true;
+}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::run()
{