diff options
Diffstat (limited to 'src/simplewallet/simplewallet.cpp')
-rw-r--r-- | src/simplewallet/simplewallet.cpp | 267 |
1 files changed, 210 insertions, 57 deletions
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index b55b39236..24e7d54dd 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -107,10 +107,11 @@ enum TransferType { namespace { - const auto allowed_priority_strings = {"default", "unimportant", "normal", "elevated", "priority"}; + const std::array<const char* const, 5> allowed_priority_strings = {{"default", "unimportant", "normal", "elevated", "priority"}}; const auto arg_wallet_file = wallet_args::arg_wallet_file(); const command_line::arg_descriptor<std::string> arg_generate_new_wallet = {"generate-new-wallet", sw::tr("Generate new wallet and save it to <arg>"), ""}; const command_line::arg_descriptor<std::string> arg_generate_from_view_key = {"generate-from-view-key", sw::tr("Generate incoming-only wallet from view key"), ""}; + const command_line::arg_descriptor<std::string> arg_generate_from_spend_key = {"generate-from-spend-key", sw::tr("Generate deterministic wallet from spend key"), ""}; const command_line::arg_descriptor<std::string> arg_generate_from_keys = {"generate-from-keys", sw::tr("Generate wallet from private keys"), ""}; const command_line::arg_descriptor<std::string> arg_generate_from_multisig_keys = {"generate-from-multisig-keys", sw::tr("Generate a master wallet from multisig wallet keys"), ""}; const auto arg_generate_from_json = wallet_args::arg_generate_from_json(); @@ -161,20 +162,50 @@ namespace return tools::scoped_message_writer(console_color_red, true, sw::tr("Error: "), el::Level::Error); } - bool is_it_true(const std::string& s) + bool parse_bool(const std::string& s, bool& result) { if (s == "1" || command_line::is_yes(s)) + { + result = true; + return true; + } + if (s == "0" || command_line::is_no(s)) + { + result = false; return true; + } boost::algorithm::is_iequal ignore_case{}; - if (boost::algorithm::equals("true", s, ignore_case)) + if (boost::algorithm::equals("true", s, ignore_case) || boost::algorithm::equals(simple_wallet::tr("true"), s, ignore_case)) + { + result = true; return true; - if (boost::algorithm::equals(simple_wallet::tr("true"), s, ignore_case)) + } + if (boost::algorithm::equals("false", s, ignore_case) || boost::algorithm::equals(simple_wallet::tr("false"), s, ignore_case)) + { + result = false; return true; + } return false; } + template <typename F> + bool parse_bool_and_use(const std::string& s, F func) + { + bool r; + if (parse_bool(s, r)) + { + func(r); + return true; + } + else + { + fail_msg_writer() << tr("invalid argument: must be either 0/1, true/false, y/n, yes/no"); + return false; + } + } + const struct { const char *name; @@ -278,6 +309,18 @@ namespace } } +bool parse_priority(const std::string& arg, uint32_t& priority) +{ + auto priority_pos = std::find( + allowed_priority_strings.begin(), + allowed_priority_strings.end(), + arg); + if(priority_pos != allowed_priority_strings.end()) { + priority = std::distance(allowed_priority_strings.begin(), priority_pos); + return true; + } + return false; +} std::string simple_wallet::get_commands_str() { @@ -495,8 +538,10 @@ bool simple_wallet::set_always_confirm_transfers(const std::vector<std::string> const auto pwd_container = get_and_verify_password(); if (pwd_container) { - m_wallet->always_confirm_transfers(is_it_true(args[1])); - m_wallet->rewrite(m_wallet_file, pwd_container->password()); + parse_bool_and_use(args[1], [&](bool r) { + m_wallet->always_confirm_transfers(r); + m_wallet->rewrite(m_wallet_file, pwd_container->password()); + }); } return true; } @@ -506,8 +551,10 @@ bool simple_wallet::set_print_ring_members(const std::vector<std::string> &args/ const auto pwd_container = get_and_verify_password(); if (pwd_container) { - m_wallet->print_ring_members(is_it_true(args[1])); - m_wallet->rewrite(m_wallet_file, pwd_container->password()); + parse_bool_and_use(args[1], [&](bool r) { + m_wallet->print_ring_members(r); + m_wallet->rewrite(m_wallet_file, pwd_container->password()); + }); } return true; } @@ -523,8 +570,10 @@ bool simple_wallet::set_store_tx_info(const std::vector<std::string> &args/* = s const auto pwd_container = get_and_verify_password(); if (pwd_container) { - m_wallet->store_tx_info(is_it_true(args[1])); - m_wallet->rewrite(m_wallet_file, pwd_container->password()); + parse_bool_and_use(args[1], [&](bool r) { + m_wallet->store_tx_info(r); + m_wallet->rewrite(m_wallet_file, pwd_container->password()); + }); } return true; } @@ -619,14 +668,15 @@ bool simple_wallet::set_auto_refresh(const std::vector<std::string> &args/* = st const auto pwd_container = get_and_verify_password(); if (pwd_container) { - const bool auto_refresh = is_it_true(args[1]); - m_wallet->auto_refresh(auto_refresh); - m_idle_mutex.lock(); - m_auto_refresh_enabled.store(auto_refresh, std::memory_order_relaxed); - m_idle_cond.notify_one(); - m_idle_mutex.unlock(); + parse_bool_and_use(args[1], [&](bool auto_refresh) { + m_wallet->auto_refresh(auto_refresh); + m_idle_mutex.lock(); + m_auto_refresh_enabled.store(auto_refresh, std::memory_order_relaxed); + m_idle_cond.notify_one(); + m_idle_mutex.unlock(); - m_wallet->rewrite(m_wallet_file, pwd_container->password()); + m_wallet->rewrite(m_wallet_file, pwd_container->password()); + }); } return true; } @@ -653,8 +703,10 @@ bool simple_wallet::set_confirm_missing_payment_id(const std::vector<std::string const auto pwd_container = get_and_verify_password(); if (pwd_container) { - m_wallet->confirm_missing_payment_id(is_it_true(args[1])); - m_wallet->rewrite(m_wallet_file, pwd_container->password()); + parse_bool_and_use(args[1], [&](bool r) { + m_wallet->confirm_missing_payment_id(r); + m_wallet->rewrite(m_wallet_file, pwd_container->password()); + }); } return true; } @@ -664,8 +716,10 @@ bool simple_wallet::set_ask_password(const std::vector<std::string> &args/* = st const auto pwd_container = get_and_verify_password(); if (pwd_container) { - m_wallet->ask_password(is_it_true(args[1])); - m_wallet->rewrite(m_wallet_file, pwd_container->password()); + parse_bool_and_use(args[1], [&](bool r) { + m_wallet->ask_password(r); + m_wallet->rewrite(m_wallet_file, pwd_container->password()); + }); } return true; } @@ -741,8 +795,10 @@ bool simple_wallet::set_merge_destinations(const std::vector<std::string> &args/ const auto pwd_container = get_and_verify_password(); if (pwd_container) { - m_wallet->merge_destinations(is_it_true(args[1])); - m_wallet->rewrite(m_wallet_file, pwd_container->password()); + parse_bool_and_use(args[1], [&](bool r) { + m_wallet->merge_destinations(r); + m_wallet->rewrite(m_wallet_file, pwd_container->password()); + }); } return true; } @@ -752,8 +808,10 @@ bool simple_wallet::set_confirm_backlog(const std::vector<std::string> &args/* = const auto pwd_container = get_and_verify_password(); if (pwd_container) { - m_wallet->confirm_backlog(is_it_true(args[1])); - m_wallet->rewrite(m_wallet_file, pwd_container->password()); + parse_bool_and_use(args[1], [&](bool r) { + m_wallet->confirm_backlog(r); + m_wallet->rewrite(m_wallet_file, pwd_container->password()); + }); } return true; } @@ -820,8 +878,8 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer_new, this, _1), tr("transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> <amount> [<payment_id>] - Transfer <amount> to <address>. If the parameter \"index=<N1>[,<N2>,...]\" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the fee of the transaction. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command \"set priority\") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding <address_2> <amount_2> etcetera (before the payment ID, if it's included)")); m_cmd_binder.set_handler("locked_transfer", boost::bind(&simple_wallet::locked_transfer, this, _1), tr("locked_transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <addr> <amount> <lockblocks> [<payment_id>] - Same as transfer, but with number of blocks to lock the transaction for, max 1000000")); m_cmd_binder.set_handler("sweep_unmixable", boost::bind(&simple_wallet::sweep_unmixable, this, _1), tr("Send all unmixable outputs to yourself with ring_size 1")); - m_cmd_binder.set_handler("sweep_all", boost::bind(&simple_wallet::sweep_all, this, _1), tr("sweep_all [index=<N1>[,<N2>,...]] [<ring_size>] <address> [<payment_id>] - Send all unlocked balance to an address. If the parameter \"index<N1>[,<N2>,...]\" is specified, the wallet sweeps outputs received by those address indices. If omitted, the wallet randomly chooses an address index to be used.")); - m_cmd_binder.set_handler("sweep_below", boost::bind(&simple_wallet::sweep_below, this, _1), tr("sweep_below <amount_threshold> [index=<N1>[,<N2>,...]] [<ring_size>] <address> [<payment_id>] - Send all unlocked outputs below the threshold to an address")); + m_cmd_binder.set_handler("sweep_all", boost::bind(&simple_wallet::sweep_all, this, _1), tr("sweep_all [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> [<payment_id>] - Send all unlocked balance to an address. If the parameter \"index<N1>[,<N2>,...]\" is specified, the wallet sweeps outputs received by those address indices. If omitted, the wallet randomly chooses an address index to be used.")); + m_cmd_binder.set_handler("sweep_below", boost::bind(&simple_wallet::sweep_below, this, _1), tr("sweep_below <amount_threshold> [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> [<payment_id>] - Send all unlocked outputs below the threshold to an address")); m_cmd_binder.set_handler("donate", boost::bind(&simple_wallet::donate, this, _1), tr("donate [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <amount> [<payment_id>] - Donate <amount> to the development team (donate.getmonero.org)")); m_cmd_binder.set_handler("sign_transfer", boost::bind(&simple_wallet::sign_transfer, this, _1), tr("Sign a transaction from a file")); m_cmd_binder.set_handler("submit_transfer", boost::bind(&simple_wallet::submit_transfer, this, _1), tr("Submit a signed transaction from a file")); @@ -847,6 +905,8 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("rescan_bc", boost::bind(&simple_wallet::rescan_blockchain, this, _1), tr("Rescan blockchain from scratch")); m_cmd_binder.set_handler("set_tx_note", boost::bind(&simple_wallet::set_tx_note, this, _1), tr("Set an arbitrary string note for a txid")); m_cmd_binder.set_handler("get_tx_note", boost::bind(&simple_wallet::get_tx_note, this, _1), tr("Get a string note for a txid")); + m_cmd_binder.set_handler("set_description", boost::bind(&simple_wallet::set_description, this, _1), tr("Set an arbitrary description for the wallet")); + m_cmd_binder.set_handler("get_description", boost::bind(&simple_wallet::get_description, this, _1), tr("Get the description of the wallet ")); m_cmd_binder.set_handler("status", boost::bind(&simple_wallet::status, this, _1), tr("Show wallet status information")); m_cmd_binder.set_handler("wallet_info", boost::bind(&simple_wallet::wallet_info, this, _1), tr("Show wallet information")); m_cmd_binder.set_handler("sign", boost::bind(&simple_wallet::sign, this, _1), tr("Sign the contents of a file")); @@ -1063,12 +1123,12 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) if (!handle_command_line(vm)) return false; - if((!m_generate_new.empty()) + (!m_wallet_file.empty()) + (!m_generate_from_view_key.empty()) + (!m_generate_from_keys.empty()) + (!m_generate_from_multisig_keys.empty()) + (!m_generate_from_json.empty()) > 1) + if((!m_generate_new.empty()) + (!m_wallet_file.empty()) + (!m_generate_from_view_key.empty()) + (!m_generate_from_spend_key.empty()) + (!m_generate_from_keys.empty()) + (!m_generate_from_multisig_keys.empty()) + (!m_generate_from_json.empty()) > 1) { - fail_msg_writer() << tr("can't specify more than one of --generate-new-wallet=\"wallet_name\", --wallet-file=\"wallet_name\", --generate-from-view-key=\"wallet_name\", --generate-from-keys=\"wallet_name\", --generate-from-multisig-keys=\"wallet_name\" and --generate-from-json=\"jsonfilename\""); + fail_msg_writer() << tr("can't specify more than one of --generate-new-wallet=\"wallet_name\", --wallet-file=\"wallet_name\", --generate-from-view-key=\"wallet_name\", --generate-from-spend-key=\"wallet_name\", --generate-from-keys=\"wallet_name\", --generate-from-multisig-keys=\"wallet_name\" and --generate-from-json=\"jsonfilename\""); return false; } - else if (m_generate_new.empty() && m_wallet_file.empty() && m_generate_from_view_key.empty() && m_generate_from_keys.empty() && m_generate_from_multisig_keys.empty() && m_generate_from_json.empty()) + else if (m_generate_new.empty() && m_wallet_file.empty() && m_generate_from_view_key.empty() && m_generate_from_spend_key.empty() && m_generate_from_keys.empty() && m_generate_from_multisig_keys.empty() && m_generate_from_json.empty()) { if(!ask_wallet_create_if_needed()) return false; } @@ -1176,6 +1236,25 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) bool r = new_wallet(vm, info.address, boost::none, viewkey); CHECK_AND_ASSERT_MES(r, false, tr("account creation failed")); } + else if (!m_generate_from_spend_key.empty()) + { + m_wallet_file = m_generate_from_spend_key; + // parse spend secret key + std::string spendkey_string = command_line::input_line("Secret spend key: "); + if (std::cin.eof()) + return false; + if (spendkey_string.empty()) { + fail_msg_writer() << tr("No data supplied, cancelled"); + return false; + } + if (!epee::string_tools::hex_to_pod(spendkey_string, m_recovery_key)) + { + fail_msg_writer() << tr("failed to parse spend key secret key"); + return false; + } + bool r = new_wallet(vm, m_recovery_key, true, false, ""); + CHECK_AND_ASSERT_MES(r, false, tr("account creation failed")); + } else if (!m_generate_from_keys.empty()) { m_wallet_file = m_generate_from_keys; @@ -1517,6 +1596,7 @@ bool simple_wallet::handle_command_line(const boost::program_options::variables_ m_wallet_file = command_line::get_arg(vm, arg_wallet_file); m_generate_new = command_line::get_arg(vm, arg_generate_new_wallet); m_generate_from_view_key = command_line::get_arg(vm, arg_generate_from_view_key); + m_generate_from_spend_key = command_line::get_arg(vm, arg_generate_from_spend_key); m_generate_from_keys = command_line::get_arg(vm, arg_generate_from_keys); m_generate_from_multisig_keys = command_line::get_arg(vm, arg_generate_from_multisig_keys); m_generate_from_json = command_line::get_arg(vm, arg_generate_from_json); @@ -1529,6 +1609,7 @@ bool simple_wallet::handle_command_line(const boost::program_options::variables_ m_restore_height = command_line::get_arg(vm, arg_restore_height); m_do_not_relay = command_line::get_arg(vm, arg_do_not_relay); m_restoring = !m_generate_from_view_key.empty() || + !m_generate_from_spend_key.empty() || !m_generate_from_keys.empty() || !m_generate_from_multisig_keys.empty() || !m_generate_from_json.empty() || @@ -1890,8 +1971,16 @@ bool simple_wallet::start_mining(const std::vector<std::string>& args) bool ok = true; size_t max_mining_threads_count = (std::max)(tools::get_max_concurrency(), static_cast<unsigned>(2)); size_t arg_size = args.size(); - if(arg_size >= 3) req.ignore_battery = is_it_true(args[2]); - if(arg_size >= 2) req.do_background_mining = is_it_true(args[1]); + if(arg_size >= 3) + { + if (!parse_bool_and_use(args[2], [&](bool r) { req.ignore_battery = r; })) + return true; + } + if(arg_size >= 2) + { + if (!parse_bool_and_use(args[1], [&](bool r) { req.do_background_mining = r; })) + return true; + } if(arg_size >= 1) { uint16_t num = 1; @@ -1974,7 +2063,7 @@ void simple_wallet::on_money_received(uint64_t height, const crypto::hash &txid, message_writer(console_color_green, false) << "\r" << tr("Height ") << height << ", " << tr("txid ") << txid << ", " << - print_money(amount) << tr(" XMR, ") << + print_money(amount) << tr("idx ") << subaddr_index; if (m_auto_refresh_refreshing) m_cmd_binder.print_prompt(); @@ -2483,17 +2572,9 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri local_args.erase(local_args.begin()); } - int priority = 0; - if(local_args.size() > 0) { - auto priority_pos = std::find( - allowed_priority_strings.begin(), - allowed_priority_strings.end(), - local_args[0]); - if(priority_pos != allowed_priority_strings.end()) { - local_args.erase(local_args.begin()); - priority = std::distance(allowed_priority_strings.begin(), priority_pos); - } - } + uint32_t priority = 0; + if (local_args.size() > 0 && parse_priority(local_args[0], priority)) + local_args.erase(local_args.begin()); size_t fake_outs_count = 0; if(local_args.size() > 0) { @@ -2821,13 +2902,20 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri { fail_msg_writer() << tr("failed to get random outputs to mix: ") << e.what(); } - catch (const tools::error::not_enough_money& e) + catch (const tools::error::not_enough_unlocked_money& e) { LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, sent amount %s") % print_money(e.available()) % print_money(e.tx_amount())); fail_msg_writer() << tr("Not enough money in unlocked balance"); } + catch (const tools::error::not_enough_money& e) + { + LOG_PRINT_L0(boost::format("not enough money to transfer, overall balance only %s, sent amount %s") % + print_money(e.available()) % + print_money(e.tx_amount())); + fail_msg_writer() << tr("Not enough money in overall balance"); + } catch (const tools::error::tx_not_possible& e) { LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)") % @@ -2993,13 +3081,20 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_) { fail_msg_writer() << tr("failed to get random outputs to mix: ") << e.what(); } - catch (const tools::error::not_enough_money& e) + catch (const tools::error::not_enough_unlocked_money& e) { LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, sent amount %s") % print_money(e.available()) % print_money(e.tx_amount())); fail_msg_writer() << tr("Not enough money in unlocked balance"); } + catch (const tools::error::not_enough_money& e) + { + LOG_PRINT_L0(boost::format("not enough money to transfer, overall balance only %s, sent amount %s") % + print_money(e.available()) % + print_money(e.tx_amount())); + fail_msg_writer() << tr("Not enough money in overall balance"); + } catch (const tools::error::tx_not_possible& e) { LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)") % @@ -3082,6 +3177,10 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &a local_args.erase(local_args.begin()); } + uint32_t priority = 0; + if (local_args.size() > 0 && parse_priority(local_args[0], priority)) + local_args.erase(local_args.begin()); + size_t fake_outs_count = 0; if(local_args.size() > 0) { size_t ring_size; @@ -3186,7 +3285,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &a try { // figure out what tx will be necessary - auto ptx_vector = m_wallet->create_transactions_all(below, info.address, info.is_subaddress, fake_outs_count, 0 /* unlock_time */, 0 /* unused fee arg*/, extra, m_current_subaddress_account, subaddr_indices, m_trusted_daemon); + auto ptx_vector = m_wallet->create_transactions_all(below, info.address, info.is_subaddress, fake_outs_count, 0 /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, m_trusted_daemon); if (ptx_vector.empty()) { @@ -3273,13 +3372,20 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &a { fail_msg_writer() << tr("failed to get random outputs to mix: ") << e.what(); } - catch (const tools::error::not_enough_money& e) + catch (const tools::error::not_enough_unlocked_money& e) { LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, sent amount %s") % print_money(e.available()) % print_money(e.tx_amount())); fail_msg_writer() << tr("Not enough money in unlocked balance"); } + catch (const tools::error::not_enough_money& e) + { + LOG_PRINT_L0(boost::format("not enough money to transfer, overall balance only %s, sent amount %s") % + print_money(e.available()) % + print_money(e.tx_amount())); + fail_msg_writer() << tr("Not enough money in overall balance"); + } catch (const tools::error::tx_not_possible& e) { LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)") % @@ -3395,7 +3501,7 @@ bool simple_wallet::donate(const std::vector<std::string> &args_) local_args.push_back(amount_str); if (!payment_id_str.empty()) local_args.push_back(payment_id_str); - message_writer() << tr("Donating ") << amount_str << " XMR to The Monero Project (donate.getmonero.org/44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A)."; + message_writer() << tr("Donating ") << amount_str << " to The Monero Project (donate.getmonero.org/44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A)."; transfer_new(local_args); return true; } @@ -3623,13 +3729,20 @@ bool simple_wallet::submit_transfer(const std::vector<std::string> &args_) { fail_msg_writer() << tr("failed to get random outputs to mix: ") << e.what(); } - catch (const tools::error::not_enough_money& e) + catch (const tools::error::not_enough_unlocked_money& e) { LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, sent amount %s") % print_money(e.available()) % print_money(e.tx_amount())); fail_msg_writer() << tr("Not enough money in unlocked balance"); } + catch (const tools::error::not_enough_money& e) + { + LOG_PRINT_L0(boost::format("not enough money to transfer, overall balance only %s, sent amount %s") % + print_money(e.available()) % + print_money(e.tx_amount())); + fail_msg_writer() << tr("Not enough money in overall balance"); + } catch (const tools::error::tx_not_possible& e) { LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)") % @@ -4377,15 +4490,18 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_) try { m_wallet->update_pool_state(); - std::list<std::pair<crypto::hash, tools::wallet2::payment_details>> payments; + std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>> payments; m_wallet->get_unconfirmed_payments(payments, m_current_subaddress_account, subaddr_indices); - for (std::list<std::pair<crypto::hash, tools::wallet2::payment_details>>::const_iterator i = payments.begin(); i != payments.end(); ++i) { - const tools::wallet2::payment_details &pd = i->second; + for (std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>>::const_iterator i = payments.begin(); i != payments.end(); ++i) { + const tools::wallet2::payment_details &pd = i->second.m_pd; std::string payment_id = string_tools::pod_to_hex(i->first); if (payment_id.substr(16).find_first_not_of('0') == std::string::npos) payment_id = payment_id.substr(0,16); std::string note = m_wallet->get_tx_note(pd.m_tx_hash); - message_writer() << (boost::format("%8.8s %6.6s %16.16s %20.20s %s %s %d %s %s") % "pool" % "in" % get_human_readable_timestamp(pd.m_timestamp) % print_money(pd.m_amount) % string_tools::pod_to_hex(pd.m_tx_hash) % payment_id % pd.m_subaddr_index.minor % "-" % note).str(); + std::string double_spend_note; + if (i->second.m_double_spend_seen) + double_spend_note = tr("[Double spend seen on the network: this transaction may or may not end up being mined] "); + message_writer() << (boost::format("%8.8s %6.6s %16.16s %20.20s %s %s %d %s %s%s") % "pool" % "in" % get_human_readable_timestamp(pd.m_timestamp) % print_money(pd.m_amount) % string_tools::pod_to_hex(pd.m_tx_hash) % payment_id % pd.m_subaddr_index.minor % "-" % note % double_spend_note).str(); } } catch (const std::exception& e) @@ -4990,6 +5106,39 @@ bool simple_wallet::get_tx_note(const std::vector<std::string> &args) return true; } //---------------------------------------------------------------------------------------------------- +bool simple_wallet::set_description(const std::vector<std::string> &args) +{ + // 0 arguments allowed, for setting the description to empty string + + std::string description = ""; + for (size_t n = 0; n < args.size(); ++n) + { + if (n > 0) + description += " "; + description += args[n]; + } + m_wallet->set_description(description); + + return true; +} +//---------------------------------------------------------------------------------------------------- +bool simple_wallet::get_description(const std::vector<std::string> &args) +{ + if (args.size() != 0) + { + fail_msg_writer() << tr("usage: get_description"); + return true; + } + + std::string description = m_wallet->get_description(); + if (description.empty()) + success_msg_writer() << tr("no description found"); + else + success_msg_writer() << tr("description found: ") << description; + + return true; +} +//---------------------------------------------------------------------------------------------------- bool simple_wallet::status(const std::vector<std::string> &args) { uint64_t local_height = m_wallet->get_blockchain_current_height(); @@ -5018,6 +5167,7 @@ bool simple_wallet::status(const std::vector<std::string> &args) bool simple_wallet::wallet_info(const std::vector<std::string> &args) { message_writer() << tr("Filename: ") << m_wallet->get_wallet_file(); + message_writer() << tr("Description: ") << m_wallet->get_description(); message_writer() << tr("Address: ") << m_wallet->get_account().get_public_address_str(m_wallet->testnet()); message_writer() << tr("Watch only: ") << (m_wallet->watch_only() ? tr("Yes") : tr("No")); message_writer() << tr("Testnet: ") << (m_wallet->testnet() ? tr("Yes") : tr("No")); @@ -5367,10 +5517,10 @@ bool simple_wallet::show_transfer(const std::vector<std::string> &args) try { m_wallet->update_pool_state(); - std::list<std::pair<crypto::hash, tools::wallet2::payment_details>> pool_payments; + std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>> pool_payments; m_wallet->get_unconfirmed_payments(pool_payments); - for (std::list<std::pair<crypto::hash, tools::wallet2::payment_details>>::const_iterator i = pool_payments.begin(); i != pool_payments.end(); ++i) { - const tools::wallet2::payment_details &pd = i->second; + for (std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>>::const_iterator i = pool_payments.begin(); i != pool_payments.end(); ++i) { + const tools::wallet2::payment_details &pd = i->second.m_pd; if (pd.m_tx_hash == txid) { std::string payment_id = string_tools::pod_to_hex(i->first); @@ -5383,6 +5533,8 @@ bool simple_wallet::show_transfer(const std::vector<std::string> &args) success_msg_writer() << "Payment ID: " << payment_id; success_msg_writer() << "Address index: " << pd.m_subaddr_index.minor; success_msg_writer() << "Note: " << m_wallet->get_tx_note(txid); + if (i->second.m_double_spend_seen) + success_msg_writer() << tr("Double spend seen on the network: this transaction may or may not end up being mined"); return true; } } @@ -5474,6 +5626,7 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_params, arg_wallet_file); command_line::add_arg(desc_params, arg_generate_new_wallet); command_line::add_arg(desc_params, arg_generate_from_view_key); + command_line::add_arg(desc_params, arg_generate_from_spend_key); command_line::add_arg(desc_params, arg_generate_from_keys); command_line::add_arg(desc_params, arg_generate_from_multisig_keys); command_line::add_arg(desc_params, arg_generate_from_json); |