aboutsummaryrefslogtreecommitdiff
path: root/src/simplewallet/simplewallet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/simplewallet/simplewallet.cpp')
-rw-r--r--src/simplewallet/simplewallet.cpp163
1 files changed, 145 insertions, 18 deletions
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index a9c171f6b..919782ab6 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -64,6 +64,19 @@ namespace
return err;
}
+ bool parse_payment_id(const std::string& payment_id_str, crypto::hash& payment_id)
+ {
+ blobdata payment_id_data;
+ if(!string_tools::parse_hexstr_to_binbuff(payment_id_str, payment_id_data))
+ return false;
+
+ if(sizeof(crypto::hash) != payment_id_data.size())
+ return false;
+
+ payment_id = *reinterpret_cast<const crypto::hash*>(payment_id_data.data());
+ return true;
+ }
+
class message_writer
{
public:
@@ -83,7 +96,7 @@ namespace
, m_oss(std::move(rhs.m_oss))
#else
// GCC bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54316
- , m_oss(rhs.m_oss.str(), ios_base::out | ios_base::ate)
+ , m_oss(rhs.m_oss.str(), ios_base::out | ios_base::ate)
#endif
, m_color(std::move(rhs.m_color))
, m_log_level(std::move(rhs.m_log_level))
@@ -171,8 +184,9 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("refresh", boost::bind(&simple_wallet::refresh, this, _1), "Resynchronize transactions and balance");
m_cmd_binder.set_handler("balance", boost::bind(&simple_wallet::show_balance, this, _1), "Show current wallet balance");
m_cmd_binder.set_handler("incoming_transfers", boost::bind(&simple_wallet::show_incoming_transfers, this, _1), "incoming_transfers [available|unavailable] - Show incoming transfers - all of them or filter them by availability");
+ 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>] - 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("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("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");
@@ -181,7 +195,7 @@ simple_wallet::simple_wallet()
//----------------------------------------------------------------------------------------------------
bool simple_wallet::set_log(const std::vector<std::string> &args)
{
- if(args.size() != 1)
+ if(args.size() != 1)
{
fail_msg_writer() << "use: set_log <log_level_number_0-4>";
return true;
@@ -202,6 +216,43 @@ bool simple_wallet::set_log(const std::vector<std::string> &args)
return true;
}
//----------------------------------------------------------------------------------------------------
+bool simple_wallet::ask_wallet_create_if_needed()
+{
+ std::string wallet_path;
+
+ std::cout << "Specify wallet file name (e.g., wallet.bin). If the wallet doesn't exist, it will be created.\n";
+ std::cout << "Wallet file name: ";
+
+ std::getline(std::cin, wallet_path);
+
+ wallet_path = string_tools::trim(wallet_path);
+
+ bool keys_file_exists;
+ bool wallet_file_exitst;
+ tools::wallet2::wallet_exists(wallet_path, keys_file_exists, wallet_file_exitst);
+
+ bool r;
+ if(keys_file_exists)
+ {
+ m_wallet_file = wallet_path;
+ r = true;
+ }else
+ {
+ if(!wallet_file_exitst)
+ {
+ std::cout << "The wallet doesn't exist, generating new one" << std::endl;
+ m_generate_new = wallet_path;
+ r = true;
+ }else
+ {
+ fail_msg_writer() << "failed to open wallet \"" << wallet_path << "\". Keys file wasn't found";
+ r = false;
+ }
+ }
+
+ return r;
+}
+//----------------------------------------------------------------------------------------------------
bool simple_wallet::init(const boost::program_options::variables_map& vm)
{
handle_command_line(vm);
@@ -212,13 +263,13 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
return false;
}
- size_t c = 0;
+ size_t c = 0;
if(!m_generate_new.empty()) ++c;
if(!m_wallet_file.empty()) ++c;
if (1 != c)
{
- fail_msg_writer() << "you must specify --wallet-file or --generate-new-wallet params";
- return false;
+ if(!ask_wallet_create_if_needed())
+ return false;
}
if (m_daemon_host.empty())
@@ -463,6 +514,15 @@ void simple_wallet::on_money_spent(uint64_t height, const cryptonote::transactio
m_refresh_progress_reporter.update(height, true);
}
//----------------------------------------------------------------------------------------------------
+void simple_wallet::on_skip_transaction(uint64_t height, const cryptonote::transaction& tx)
+{
+ message_writer(epee::log_space::console_color_red, true) <<
+ "Height " << height <<
+ ", transaction " << get_transaction_hash(tx) <<
+ ", unsupported transaction format";
+ m_refresh_progress_reporter.update(height, true);
+}
+//----------------------------------------------------------------------------------------------------
bool simple_wallet::refresh(const std::vector<std::string>& args)
{
if (!try_connect_to_daemon())
@@ -587,6 +647,55 @@ bool simple_wallet::show_incoming_transfers(const std::vector<std::string>& args
return true;
}
//----------------------------------------------------------------------------------------------------
+bool simple_wallet::show_payments(const std::vector<std::string> &args)
+{
+ if(args.empty())
+ {
+ fail_msg_writer() << "expected at least one payment_id";
+ return true;
+ }
+
+ message_writer() << " payment \t" <<
+ " transaction \t" <<
+ " height\t amount \tunlock time";
+
+ bool payments_found = false;
+ for(std::string arg : args)
+ {
+ crypto::hash payment_id;
+ if(parse_payment_id(arg, payment_id))
+ {
+ std::list<tools::wallet2::payment_details> payments;
+ m_wallet->get_payments(payment_id, payments);
+ if(payments.empty())
+ {
+ success_msg_writer() << "No payments with id " << payment_id;
+ continue;
+ }
+
+ for (const tools::wallet2::payment_details& pd : payments)
+ {
+ if(!payments_found)
+ {
+ payments_found = true;
+ }
+ success_msg_writer(true) <<
+ payment_id << '\t' <<
+ pd.m_tx_hash << '\t' <<
+ std::setw(8) << pd.m_block_height << '\t' <<
+ std::setw(21) << print_money(pd.m_amount) << '\t' <<
+ pd.m_unlock_time;
+ }
+ }
+ else
+ {
+ fail_msg_writer() << "payment id has invalid format: \"" << arg << "\", expected 64-character string";
+ }
+ }
+
+ return true;
+}
+//----------------------------------------------------------------------------------------------------
uint64_t simple_wallet::get_daemon_blockchain_height(std::string& err)
{
COMMAND_RPC_GET_HEIGHT::request req;
@@ -628,20 +737,37 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
fail_msg_writer() << "mixin_count should be non-negative integer, got " << local_args[0];
return true;
}
+ local_args.erase(local_args.begin());
- vector<cryptonote::tx_destination_entry> dsts;
- for (size_t i = 1; i < local_args.size(); i += 2)
+ std::vector<uint8_t> extra;
+ if (1 == local_args.size() % 2)
{
- cryptonote::tx_destination_entry de;
- if(!get_account_address_from_str(de.addr, local_args[i]))
+ std::string payment_id_str = local_args.back();
+ local_args.pop_back();
+
+ crypto::hash payment_id;
+ bool r = parse_payment_id(payment_id_str, payment_id);
+ if(r)
{
- fail_msg_writer() << "wrong address: " << local_args[i];
+ std::string extra_nonce;
+ set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id);
+ r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
+ }
+
+ if(!r)
+ {
+ fail_msg_writer() << "payment id has invalid format: \"" << payment_id_str << "\", expected 64-character string";
return true;
}
+ }
- if (local_args.size() <= i + 1)
+ vector<cryptonote::tx_destination_entry> dsts;
+ for (size_t i = 0; i < local_args.size(); i += 2)
+ {
+ cryptonote::tx_destination_entry de;
+ if(!get_account_address_from_str(de.addr, local_args[i]))
{
- fail_msg_writer() << "amount for the last address " << local_args[i] << " is not specified";
+ fail_msg_writer() << "wrong address: " << local_args[i];
return true;
}
@@ -659,7 +785,7 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
try
{
cryptonote::transaction tx;
- m_wallet->transfer(dsts, fake_outs_count, 0, DEFAULT_FEE, tx);
+ m_wallet->transfer(dsts, fake_outs_count, 0, DEFAULT_FEE, extra, tx);
success_msg_writer(true) << "Money successfully sent, transaction " << get_transaction_hash(tx);
}
catch (const tools::error::daemon_busy&)
@@ -801,6 +927,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
+ success_msg_writer() << "bytecoin wallet v" << PROJECT_VERSION_LONG;
success_msg_writer() << "Usage: simplewallet [--wallet-file=<file>|--generate-new-wallet=<file>] [--daemon-address=<host>:<port>] [<COMMAND>]";
success_msg_writer() << desc_all << '\n' << w.get_commands_str();
return false;
@@ -833,11 +960,11 @@ int main(int argc, char* argv[])
LOG_PRINT_L0("Setting log level = " << command_line::get_arg(vm, arg_log_level));
log_space::get_set_log_detalisation_level(true, command_line::get_arg(vm, arg_log_level));
}
-
+
if(command_line::has_arg(vm, tools::wallet_rpc_server::arg_rpc_bind_port))
{
log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL, LOG_LEVEL_2);
- //runs wallet with rpc interface
+ //runs wallet with rpc interface
if(!command_line::has_arg(vm, arg_wallet_file) )
{
LOG_ERROR("Wallet file not set.");
@@ -854,7 +981,7 @@ int main(int argc, char* argv[])
return 1;
}
- std::string wallet_file = command_line::get_arg(vm, arg_wallet_file);
+ std::string wallet_file = command_line::get_arg(vm, arg_wallet_file);
std::string wallet_password = command_line::get_arg(vm, arg_password);
std::string daemon_address = command_line::get_arg(vm, arg_daemon_address);
std::string daemon_host = command_line::get_arg(vm, arg_daemon_host);
@@ -904,7 +1031,7 @@ int main(int argc, char* argv[])
}
}else
{
- //runs wallet with console interface
+ //runs wallet with console interface
r = w.init(vm);
CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize wallet");