diff options
Diffstat (limited to 'src/simplewallet/simplewallet.cpp')
-rw-r--r-- | src/simplewallet/simplewallet.cpp | 218 |
1 files changed, 168 insertions, 50 deletions
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 70eb278d5..69c684097 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019, The Monero Project +// Copyright (c) 2014-2020, The Monero Project // // All rights reserved. // @@ -74,10 +74,12 @@ #include "version.h" #include <stdexcept> #include "wallet/message_store.h" +#include "QrCode.hpp" #ifdef WIN32 #include <boost/locale.hpp> #include <boost/filesystem.hpp> +#include <fcntl.h> #endif #ifdef HAVE_READLINE @@ -126,7 +128,7 @@ typedef cryptonote::simple_wallet sw; #define SCOPED_WALLET_UNLOCK() SCOPED_WALLET_UNLOCK_ON_BAD_PASSWORD(return true;) -#define PRINT_USAGE(usage_help_advanced) fail_msg_writer() << boost::format(tr("usage: %s")) % usage_help_advanced; +#define PRINT_USAGE(usage_help) fail_msg_writer() << boost::format(tr("usage: %s")) % usage_help; #define LONG_PAYMENT_ID_SUPPORT_CHECK() \ do { \ @@ -275,9 +277,10 @@ namespace const char* USAGE_RPC_PAYMENT_INFO("rpc_payment_info"); const char* USAGE_START_MINING_FOR_RPC("start_mining_for_rpc"); const char* USAGE_STOP_MINING_FOR_RPC("stop_mining_for_rpc"); + const char* USAGE_SHOW_QR_CODE("show_qr_code [<subaddress_index>]"); const char* USAGE_VERSION("version"); - const char* USAGE_HELP_ADVANCED("help_advanced [<command>]"); - const char* USAGE_HELP("help"); + const char* USAGE_HELP("help [<command> | all]"); + const char* USAGE_APROPOS("apropos <keyword> [<keyword> ...]"); std::string input_line(const std::string& prompt, bool yesno = false) { @@ -2314,7 +2317,7 @@ bool simple_wallet::on_unknown_command(const std::vector<std::string> &args) { if (args[0] == "exit" || args[0] == "q") // backward compat return false; - fail_msg_writer() << boost::format(tr("Unknown command '%s', try 'help_advanced'")) % args.front(); + fail_msg_writer() << boost::format(tr("Unknown command '%s', try 'help'")) % args.front(); return true; } @@ -2394,6 +2397,62 @@ bool simple_wallet::stop_mining_for_rpc(const std::vector<std::string> &args) return true; } +bool simple_wallet::show_qr_code(const std::vector<std::string> &args) +{ + uint32_t subaddress_index = 0; + if (args.size() >= 1) + { + if (!string_tools::get_xtype_from_string(subaddress_index, args[0])) + { + fail_msg_writer() << tr("invalid index: must be an unsigned integer"); + return true; + } + if (subaddress_index >= m_wallet->get_num_subaddresses(m_current_subaddress_account)) + { + fail_msg_writer() << tr("<subaddress_index> is out of bounds"); + return true; + } + } + +#ifdef _WIN32 +#define PRINT_UTF8(pre, x) std::wcout << pre ## x +#define WTEXTON() _setmode(_fileno(stdout), _O_WTEXT) +#define WTEXTOFF() _setmode(_fileno(stdout), _O_TEXT) +#else +#define PRINT_UTF8(pre, x) std::cout << x +#define WTEXTON() +#define WTEXTOFF() +#endif + + WTEXTON(); + try + { + const std::string address = "monero:" + m_wallet->get_subaddress_as_str({m_current_subaddress_account, subaddress_index}); + const qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(address.c_str(), qrcodegen::QrCode::Ecc::LOW); + for (int y = -2; y < qr.getSize() + 2; y+=2) + { + for (int x = -2; x < qr.getSize() + 2; x++) + { + if (qr.getModule(x, y) && qr.getModule(x, y + 1)) + PRINT_UTF8(L, "\u2588"); + else if (qr.getModule(x, y) && !qr.getModule(x, y + 1)) + PRINT_UTF8(L, "\u2580"); + else if (!qr.getModule(x, y) && qr.getModule(x, y + 1)) + PRINT_UTF8(L, "\u2584"); + else + PRINT_UTF8(L, " "); + } + PRINT_UTF8(, std::endl); + } + } + catch (const std::length_error&) + { + fail_msg_writer() << tr("Failed to generate QR code, input too large"); + } + WTEXTOFF(); + return true; +} + bool simple_wallet::set_always_confirm_transfers(const std::vector<std::string> &args/* = std::vector<std::string>()*/) { const auto pwd_container = get_and_verify_password(); @@ -3043,37 +3102,39 @@ bool simple_wallet::set_export_format(const std::vector<std::string> &args/* = s bool simple_wallet::help(const std::vector<std::string> &args/* = std::vector<std::string>()*/) { - message_writer() << ""; - message_writer() << tr("Commands:"); - message_writer() << ""; - message_writer() << tr("\"welcome\" - Read welcome message."); - message_writer() << tr("\"donate <amount>\" - Donate XMR to the development team."); - message_writer() << tr("\"balance\" - Show balance."); - message_writer() << tr("\"address new\" - Create new subaddress."); - message_writer() << tr("\"address all\" - Show all addresses."); - message_writer() << tr("\"transfer <address> <amount>\" - Send XMR to an address."); - message_writer() << tr("\"show_transfers [in|out|pending|failed|pool]\" - Show transactions."); - message_writer() << tr("\"sweep_all <address>\" - Send whole balance to another wallet."); - message_writer() << tr("\"seed\" - Show secret 25 words that can be used to recover this wallet."); - message_writer() << tr("\"refresh\" - Synchronize wallet with the Monero network."); - message_writer() << tr("\"status\" - Check current status of wallet."); - message_writer() << tr("\"version\" - Check software version."); - message_writer() << tr("\"help_advanced\" - Show list with more available commands."); - message_writer() << tr("\"save\" - Save wallet."); - message_writer() << tr("\"exit\" - Exit wallet."); - message_writer() << ""; - return true; -} - -bool simple_wallet::help_advanced(const std::vector<std::string> &args/* = std::vector<std::string>()*/) -{ if(args.empty()) { + message_writer() << ""; + message_writer() << tr("Important commands:"); + message_writer() << ""; + message_writer() << tr("\"welcome\" - Show welcome message."); + message_writer() << tr("\"help all\" - Show the list of all available commands."); + message_writer() << tr("\"help <command>\" - Show a command's documentation."); + message_writer() << tr("\"apropos <keyword>\" - Show commands related to a keyword."); + message_writer() << ""; + message_writer() << tr("\"wallet_info\" - Show wallet main address and other info."); + message_writer() << tr("\"balance\" - Show balance."); + message_writer() << tr("\"address all\" - Show all addresses."); + message_writer() << tr("\"address new\" - Create new subaddress."); + message_writer() << tr("\"transfer <address> <amount>\" - Send XMR to an address."); + message_writer() << tr("\"show_transfers [in|out|pending|failed|pool]\" - Show transactions."); + message_writer() << tr("\"sweep_all <address>\" - Send whole balance to another wallet."); + message_writer() << tr("\"seed\" - Show secret 25 words that can be used to recover this wallet."); + message_writer() << tr("\"refresh\" - Synchronize wallet with the Monero network."); + message_writer() << tr("\"status\" - Check current status of wallet."); + message_writer() << tr("\"version\" - Check software version."); + message_writer() << tr("\"exit\" - Exit wallet."); + message_writer() << ""; + message_writer() << tr("\"donate <amount>\" - Donate XMR to the development team."); + message_writer() << ""; + } + else if ((args.size() == 1) && (args.front() == "all")) + { success_msg_writer() << get_commands_str(); } else if ((args.size() == 2) && (args.front() == "mms")) { - // Little hack to be able to do "help_advanced mms <subcommand>" + // Little hack to be able to do "help mms <subcommand>" std::vector<std::string> mms_args(1, args.front() + " " + args.back()); success_msg_writer() << get_command_usage(mms_args); } @@ -3084,6 +3145,33 @@ bool simple_wallet::help_advanced(const std::vector<std::string> &args/* = std:: return true; } +bool simple_wallet::apropos(const std::vector<std::string> &args) +{ + if (args.empty()) + { + PRINT_USAGE(USAGE_APROPOS); + return true; + } + const std::vector<std::string>& command_list = m_cmd_binder.get_command_list(args); + if (command_list.empty()) + { + fail_msg_writer() << tr("No commands found mentioning keyword(s)"); + return true; + } + + success_msg_writer() << ""; + for(auto const& command:command_list) + { + std::vector<std::string> cmd; + cmd.push_back(command); + std::pair<std::string, std::string> documentation = m_cmd_binder.get_documentation(cmd); + success_msg_writer() << " " << documentation.first; + } + success_msg_writer() << ""; + + return true; +} + simple_wallet::simple_wallet() : m_allow_mismatched_daemon_version(false) , m_refresh_progress_reporter(*this) @@ -3150,10 +3238,10 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("sweep_unmixable", boost::bind(&simple_wallet::on_command, this, &simple_wallet::sweep_unmixable, _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), + m_cmd_binder.set_handler("sweep_all", boost::bind(&simple_wallet::on_command, this, &simple_wallet::sweep_all, _1), tr(USAGE_SWEEP_ALL), tr("Send all unlocked balance to an address. If the parameter \"index=<N1>[,<N2>,...]\" or \"index=all\" is specified, the wallet sweeps outputs received by those or all address indices, respectively. If omitted, the wallet randomly chooses an address index to be used. If the parameter \"outputs=<N>\" is specified and N > 0, wallet splits the transaction into N even outputs.")); - m_cmd_binder.set_handler("sweep_account", boost::bind(&simple_wallet::sweep_account, this, _1), + m_cmd_binder.set_handler("sweep_account", boost::bind(&simple_wallet::on_command, this, &simple_wallet::sweep_account, _1), tr(USAGE_SWEEP_ACCOUNT), tr("Send all unlocked balance from a given account to an address. If the parameter \"index=<N1>[,<N2>,...]\" or \"index=all\" is specified, the wallet sweeps outputs received by those or all address indices, respectively. If omitted, the wallet randomly chooses an address index to be used. If the parameter \"outputs=<N>\" is specified and N > 0, wallet splits the transaction into N even outputs.")); m_cmd_binder.set_handler("sweep_below", @@ -3217,7 +3305,7 @@ simple_wallet::simple_wallet() boost::bind(&simple_wallet::on_command, this, &simple_wallet::seed, _1), tr("Display the Electrum-style mnemonic seed")); m_cmd_binder.set_handler("restore_height", - boost::bind(&simple_wallet::restore_height, this, _1), + boost::bind(&simple_wallet::on_command, this, &simple_wallet::restore_height, _1), tr("Display the restore height")); m_cmd_binder.set_handler("set", boost::bind(&simple_wallet::on_command, this, &simple_wallet::set_variable, _1), @@ -3467,7 +3555,7 @@ simple_wallet::simple_wallet() "<subcommand> is one of:\n" " init, info, signer, list, next, sync, transfer, delete, send, receive, export, note, show, set, help\n" " send_signer_config, start_auto_config, stop_auto_config, auto_config, config_checksum\n" - "Get help about a subcommand with: help_advanced mms <subcommand>")); + "Get help about a subcommand with: help mms <subcommand>, or help mms <subcommand>")); m_cmd_binder.set_handler("mms init", boost::bind(&simple_wallet::on_command, this, &simple_wallet::mms, _1), tr(USAGE_MMS_INIT), @@ -3528,7 +3616,7 @@ simple_wallet::simple_wallet() "auto-send <1|0>\n " " Whether to automatically send newly generated messages right away.\n ")); m_cmd_binder.set_handler("mms send_signer_config", - boost::bind(&simple_wallet::mms, this, _1), + boost::bind(&simple_wallet::on_command, this, &simple_wallet::mms, _1), tr(USAGE_MMS_SEND_SIGNER_CONFIG), tr("Send completed signer config to all other authorized signers")); m_cmd_binder.set_handler("mms start_auto_config", @@ -3598,7 +3686,7 @@ simple_wallet::simple_wallet() tr(USAGE_NET_STATS), tr("Prints simple network stats")); m_cmd_binder.set_handler("public_nodes", - boost::bind(&simple_wallet::public_nodes, this, _1), + boost::bind(&simple_wallet::on_command, this, &simple_wallet::public_nodes, _1), tr(USAGE_PUBLIC_NODES), tr("Lists known public nodes")); m_cmd_binder.set_handler("welcome", @@ -3610,25 +3698,29 @@ simple_wallet::simple_wallet() tr(USAGE_VERSION), tr("Returns version information")); m_cmd_binder.set_handler("rpc_payment_info", - boost::bind(&simple_wallet::rpc_payment_info, this, _1), + boost::bind(&simple_wallet::on_command, this, &simple_wallet::rpc_payment_info, _1), tr(USAGE_RPC_PAYMENT_INFO), tr("Get info about RPC payments to current node")); m_cmd_binder.set_handler("start_mining_for_rpc", - boost::bind(&simple_wallet::start_mining_for_rpc, this, _1), + boost::bind(&simple_wallet::on_command, this, &simple_wallet::start_mining_for_rpc, _1), tr(USAGE_START_MINING_FOR_RPC), tr("Start mining to pay for RPC access")); m_cmd_binder.set_handler("stop_mining_for_rpc", - boost::bind(&simple_wallet::stop_mining_for_rpc, this, _1), + boost::bind(&simple_wallet::on_command, this, &simple_wallet::stop_mining_for_rpc, _1), tr(USAGE_STOP_MINING_FOR_RPC), tr("Stop mining to pay for RPC access")); - m_cmd_binder.set_handler("help_advanced", - boost::bind(&simple_wallet::on_command, this, &simple_wallet::help_advanced, _1), - tr(USAGE_HELP_ADVANCED), - tr("Show the help section or the documentation about a <command>.")); + m_cmd_binder.set_handler("show_qr_code", + boost::bind(&simple_wallet::on_command, this, &simple_wallet::show_qr_code, _1), + tr(USAGE_SHOW_QR_CODE), + tr("Show address as QR code")); m_cmd_binder.set_handler("help", boost::bind(&simple_wallet::on_command, this, &simple_wallet::help, _1), tr(USAGE_HELP), - tr("Show simplified list of available commands.")); + tr("Show the help section or the documentation about a <command>.")); + m_cmd_binder.set_handler("apropos", + boost::bind(&simple_wallet::on_command, this, &simple_wallet::apropos, _1), + tr(USAGE_APROPOS), + tr("Search all command descriptions for keyword(s)")); m_cmd_binder.set_unknown_command_handler(boost::bind(&simple_wallet::on_command, this, &simple_wallet::on_unknown_command, _1)); m_cmd_binder.set_empty_command_handler(boost::bind(&simple_wallet::on_empty_command, this)); m_cmd_binder.set_cancel_handler(boost::bind(&simple_wallet::on_cancelled_command, this)); @@ -4781,8 +4873,8 @@ boost::optional<epee::wipeable_string> simple_wallet::new_wallet(const boost::pr tr("Your wallet has been generated!\n" "To start synchronizing with the daemon, use the \"refresh\" command.\n" "Use the \"help\" command to see a simplified list of available commands.\n" - "Use the \"help_advanced\" command to see an advanced list of available commands.\n" - "Use \"help_advanced <command>\" to see a command's documentation.\n" + "Use \"help all\" command to see the list of all available commands.\n" + "Use \"help <command>\" to see a command's documentation.\n" "Always use the \"exit\" command when closing monero-wallet-cli to save \n" "your current session's state. Otherwise, you might need to synchronize \n" "your wallet again (your wallet keys are NOT at risk in any case).\n") @@ -5042,8 +5134,8 @@ boost::optional<epee::wipeable_string> simple_wallet::open_wallet(const boost::p success_msg_writer() << "**********************************************************************\n" << tr("Use the \"help\" command to see a simplified list of available commands.\n") << - tr("Use the \"help_advanced\" command to see an advanced list of available commands.\n") << - tr("Use \"help_advanced <command>\" to see a command's documentation.\n") << + tr("Use \"help all\" to see the list of all available commands.\n") << + tr("Use \"help <command>\" to see a command's documentation.\n") << "**********************************************************************"; return password; } @@ -6258,7 +6350,7 @@ void simple_wallet::check_for_inactivity_lock(bool user) m_in_command = true; if (!user) { - const std::string speech = tr("I locked your Monero wallet to protect you while you were away\nsee \"help_advanced set\" to configure/disable"); + const std::string speech = tr("I locked your Monero wallet to protect you while you were away\nsee \"help set\" to configure/disable"); std::vector<std::pair<std::string, size_t>> lines = tools::split_string_by_width(speech, 45); size_t max_len = 0; @@ -7376,6 +7468,32 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_) success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_monero_tx"; } } + else if (m_wallet->get_account().get_device().has_tx_cold_sign()) + { + try + { + tools::wallet2::signed_tx_set signed_tx; + std::vector<cryptonote::address_parse_info> dsts_info; + dsts_info.push_back(info); + + if (!cold_sign_tx(ptx_vector, signed_tx, dsts_info, [&](const tools::wallet2::signed_tx_set &tx){ return accept_loaded_tx(tx); })){ + fail_msg_writer() << tr("Failed to cold sign transaction with HW wallet"); + return true; + } + + commit_or_save(signed_tx.ptx, m_do_not_relay); + success_msg_writer(true) << tr("Money successfully sent, transaction: ") << get_transaction_hash(ptx_vector[0].tx); + } + catch (const std::exception& e) + { + handle_transfer_exception(std::current_exception(), m_wallet->is_trusted_daemon()); + } + catch (...) + { + LOG_ERROR("Unknown error"); + fail_msg_writer() << tr("unknown error"); + } + } else if (m_wallet->watch_only()) { bool r = m_wallet->save_tx(ptx_vector, "unsigned_monero_tx"); @@ -11143,7 +11261,7 @@ void simple_wallet::mms_help(const std::vector<std::string> &args) { if (args.size() > 1) { - fail_msg_writer() << tr("Usage: help_advanced mms [<subcommand>]"); + fail_msg_writer() << tr("Usage: help mms [<subcommand>]"); return; } std::vector<std::string> help_args; |