diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 6c544581..a69bed93 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -2572,7 +2572,7 @@ bool simple_wallet::sweep_bare_outs(const std::vector &args) } size_t i = 0, total_bare_outs = 0; - uint64_t total_mount = 0; + uint64_t total_amount = 0; std::stringstream details_ss; for(auto &g : groups) { @@ -2582,7 +2582,7 @@ bool simple_wallet::sweep_bare_outs(const std::vector &args) tools::transfer_details td{}; CHECK_AND_ASSERT_THROW_MES(m_wallet->get_transfer_info_by_index(tid, td), "get_transfer_info_by_index failed with index " << tid); details_ss << tid << " (" << print_money_brief(td.m_amount) << "), "; - total_mount += td.m_amount; + total_amount += td.m_amount; } if (g.additional_tid) @@ -2597,10 +2597,10 @@ bool simple_wallet::sweep_bare_outs(const std::vector &args) LOG_PRINT_L1("bare UTXO:" << ENDL << details_ss.str()); - success_msg_writer(true) << "This wallet contains " << total_bare_outs << " bare outputs with total amount of " << print_money_brief(total_mount) << + success_msg_writer(true) << "This wallet contains " << total_bare_outs << " bare outputs with total amount of " << print_money_brief(total_amount) << ". They can be converted in " << groups.size() << " transaction" << (groups.size() > 1 ? "s" : "") << ", with total fee = " << print_money_brief(TX_DEFAULT_FEE * i) << "."; if (target_address != m_wallet->get_account().get_public_address()) - message_writer(epee::log_space::console_color_yellow, false) << print_money_brief(total_mount) << " coins will be sent to address " << get_account_address_as_str(target_address); + message_writer(epee::log_space::console_color_yellow, false) << print_money_brief(total_amount) << " coins will be sent to address " << get_account_address_as_str(target_address); tools::password_container reader; if (!reader.read_input("Would you like to continue? (y/yes/n/no):\n") || (reader.get_input() != "y" && reader.get_input() != "yes")) diff --git a/src/wallet/view_iface.h b/src/wallet/view_iface.h index 16faf90e..dce4b5ee 100644 --- a/src/wallet/view_iface.h +++ b/src/wallet/view_iface.h @@ -201,11 +201,13 @@ public: std::list balances; uint64_t minied_total; + bool has_bare_unspent_outputs; BEGIN_KV_SERIALIZE_MAP() KV_CHAIN_BASE(wallet_status_info_base) KV_SERIALIZE(balances) KV_SERIALIZE(minied_total) + KV_SERIALIZE(has_bare_unspent_outputs) END_KV_SERIALIZE_MAP() }; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index c0e1f45b..ed88296c 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -2346,14 +2346,16 @@ bool wallet2::sweep_bare_unspent_outputs(const currency::account_public_address& } //---------------------------------------------------------------------------------------------------- bool wallet2::sweep_bare_unspent_outputs(const currency::account_public_address& target_address, const std::vector& tids_grouped_by_txs, - size_t& total_txs_sent, uint64_t& total_amount_sent, uint64_t& total_fee_spent) + size_t& total_txs_sent, uint64_t& total_amount_sent, uint64_t& total_fee_spent, uint64_t& total_bare_outs_sent) { total_txs_sent = 0; total_amount_sent = 0; total_fee_spent = 0; + total_bare_outs_sent = 0; auto on_tx_sent_callback = [&](size_t batch_index, const currency::transaction& tx, uint64_t amount, uint64_t fee, bool sent_ok, const std::string& err) { if (sent_ok) { + total_bare_outs_sent += count_type_in_variant_container(tx.vin); ++total_txs_sent; total_fee_spent += fee; total_amount_sent += amount; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 5907ed33..c10892ea 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -391,7 +391,7 @@ namespace tools bool sweep_bare_unspent_outputs(const currency::account_public_address& target_address, const std::vector& tids_grouped_by_txs, std::function on_tx_sent); bool sweep_bare_unspent_outputs(const currency::account_public_address& target_address, const std::vector& tids_grouped_by_txs, - size_t& total_txs_sent, uint64_t& total_amount_sent, uint64_t& total_fee); + size_t& total_txs_sent, uint64_t& total_amount_sent, uint64_t& total_fee, uint64_t& total_bare_outs_sent); void handle_unconfirmed_tx(process_transaction_context& ptc); void scan_tx_pool(bool& has_related_alias_in_unconfirmed); void refresh(); diff --git a/src/wallet/wallet_public_structs_defs.h b/src/wallet/wallet_public_structs_defs.h index d4b2a100..8089fa71 100644 --- a/src/wallet/wallet_public_structs_defs.h +++ b/src/wallet/wallet_public_structs_defs.h @@ -445,6 +445,7 @@ namespace wallet_public uint64_t transfers_count; uint64_t transfer_entries_count; bool is_whatch_only; + bool has_bare_unspent_outputs; std::vector utxo_distribution; uint64_t current_height; @@ -454,6 +455,7 @@ namespace wallet_public KV_SERIALIZE(transfers_count) KV_SERIALIZE(transfer_entries_count) KV_SERIALIZE(is_whatch_only) + KV_SERIALIZE(has_bare_unspent_outputs) KV_SERIALIZE(utxo_distribution) KV_SERIALIZE(current_height) END_KV_SERIALIZE_MAP() @@ -834,6 +836,54 @@ namespace wallet_public }; }; + struct COMMAND_RPC_GET_BARE_OUTS_STATS + { + struct request + { + BEGIN_KV_SERIALIZE_MAP() + END_KV_SERIALIZE_MAP() + }; + + struct response + { + uint64_t total_bare_outs; + uint64_t total_amount; + uint64_t expected_total_fee; + uint64_t txs_count; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(total_bare_outs) + KV_SERIALIZE(total_amount) + KV_SERIALIZE(expected_total_fee) + KV_SERIALIZE(txs_count) + END_KV_SERIALIZE_MAP() + }; + }; + + struct COMMAND_RPC_SWEEP_BARE_OUTS + { + struct request + { + BEGIN_KV_SERIALIZE_MAP() + END_KV_SERIALIZE_MAP() + }; + + struct response + { + uint64_t bare_outs_swept; + uint64_t amount_swept; + uint64_t fee_spent; + uint64_t txs_sent; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(bare_outs_swept) + KV_SERIALIZE(amount_swept) + KV_SERIALIZE(fee_spent) + KV_SERIALIZE(txs_sent) + END_KV_SERIALIZE_MAP() + }; + }; + struct COMMAND_SIGN_TRANSFER { struct request diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 5baf588d..9c80cb96 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -351,6 +351,7 @@ namespace tools res.utxo_distribution.push_back(currency::print_money_brief(ent.first) + ":" + std::to_string(ent.second)); res.current_height = w.get_wallet()->get_top_block_height(); + res.has_bare_unspent_outputs = w.get_wallet()->has_bare_unspent_outputs(); return true; WALLET_RPC_CATCH_TRY_ENTRY(); } @@ -752,6 +753,77 @@ namespace tools WALLET_RPC_CATCH_TRY_ENTRY(); } //------------------------------------------------------------------------------------------------------------------------------ + bool wallet_rpc_server::on_get_bare_outs_stats(const wallet_public::COMMAND_RPC_GET_BARE_OUTS_STATS ::request& req, wallet_public::COMMAND_RPC_GET_BARE_OUTS_STATS::response& res, epee::json_rpc::error& er, connection_context& cntx) + { + WALLET_RPC_BEGIN_TRY_ENTRY(); + + if (w.get_wallet()->is_watch_only()) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "operation cannot be performed in watch-only wallet"; + return false; + } + + std::vector groups; + if (!w.get_wallet()->get_bare_unspent_outputs_stats(groups)) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "get_bare_unspent_outputs_stats failed"; + return false; + } + + res.total_amount = 0; + res.total_bare_outs = 0; + res.expected_total_fee = 0; + res.txs_count = 0; + + for(auto &g : groups) + { + for (auto& tid: g.tids) + { + tools::transfer_details td{}; + CHECK_AND_ASSERT_THROW_MES(w.get_wallet()->get_transfer_info_by_index(tid, td), "get_transfer_info_by_index failed with index " << tid); + res.total_amount += td.m_amount; + } + ++res.txs_count; + res.total_bare_outs += g.tids.size(); + res.expected_total_fee += TX_DEFAULT_FEE; + } + + return true; + WALLET_RPC_CATCH_TRY_ENTRY(); + } + //------------------------------------------------------------------------------------------------------------------------------ + bool wallet_rpc_server::on_sweep_bare_outs(const wallet_public::COMMAND_RPC_SWEEP_BARE_OUTS::request& req, wallet_public::COMMAND_RPC_SWEEP_BARE_OUTS::response& res, epee::json_rpc::error& er, connection_context& cntx) + { + WALLET_RPC_BEGIN_TRY_ENTRY(); + + if (w.get_wallet()->is_watch_only()) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "operation cannot be performed in watch-only wallet"; + return false; + } + + std::vector groups; + if (!w.get_wallet()->get_bare_unspent_outputs_stats(groups)) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "get_bare_unspent_outputs_stats failed"; + return false; + } + + res.amount_swept = 0; + res.bare_outs_swept = 0; + res.fee_spent = 0; + res.txs_sent = 0; + + w.get_wallet()->sweep_bare_unspent_outputs(w.get_wallet()->get_account().get_public_address(), groups, res.txs_sent, res.amount_swept, res.fee_spent, res.bare_outs_swept); + + return true; + WALLET_RPC_CATCH_TRY_ENTRY(); + } + //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_sign_transfer(const wallet_public::COMMAND_SIGN_TRANSFER::request& req, wallet_public::COMMAND_SIGN_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx) { WALLET_RPC_BEGIN_TRY_ENTRY(); diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index 86faf178..7e8f4843 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -106,6 +106,8 @@ namespace tools MAP_JON_RPC_WE("make_integrated_address", on_make_integrated_address, wallet_public::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS) MAP_JON_RPC_WE("split_integrated_address", on_split_integrated_address, wallet_public::COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS) MAP_JON_RPC_WE("sweep_below", on_sweep_below, wallet_public::COMMAND_SWEEP_BELOW) + MAP_JON_RPC_WE("get_bare_outs_stats", on_get_bare_outs_stats, wallet_public::COMMAND_RPC_GET_BARE_OUTS_STATS) + MAP_JON_RPC_WE("sweep_bare_outs", on_sweep_bare_outs, wallet_public::COMMAND_RPC_SWEEP_BARE_OUTS) MAP_JON_RPC_WE("sign_transfer", on_sign_transfer, wallet_public::COMMAND_SIGN_TRANSFER) MAP_JON_RPC_WE("submit_transfer", on_submit_transfer, wallet_public::COMMAND_SUBMIT_TRANSFER) MAP_JON_RPC_WE("search_for_transactions", on_search_for_transactions, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS_LEGACY) @@ -172,6 +174,8 @@ namespace tools bool on_make_integrated_address(const wallet_public::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS::request& req, wallet_public::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS::response& res, epee::json_rpc::error& er, connection_context& cntx); bool on_split_integrated_address(const wallet_public::COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS::request& req, wallet_public::COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS::response& res, epee::json_rpc::error& er, connection_context& cntx); bool on_sweep_below(const wallet_public::COMMAND_SWEEP_BELOW::request& req, wallet_public::COMMAND_SWEEP_BELOW::response& res, epee::json_rpc::error& er, connection_context& cntx); + bool on_get_bare_outs_stats(const wallet_public::COMMAND_RPC_GET_BARE_OUTS_STATS ::request& req, wallet_public::COMMAND_RPC_GET_BARE_OUTS_STATS::response& res, epee::json_rpc::error& er, connection_context& cntx); + bool on_sweep_bare_outs(const wallet_public::COMMAND_RPC_SWEEP_BARE_OUTS::request& req, wallet_public::COMMAND_RPC_SWEEP_BARE_OUTS::response& res, epee::json_rpc::error& er, connection_context& cntx); bool on_sign_transfer(const wallet_public::COMMAND_SIGN_TRANSFER::request& req, wallet_public::COMMAND_SIGN_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx); bool on_submit_transfer(const wallet_public::COMMAND_SUBMIT_TRANSFER::request& req, wallet_public::COMMAND_SUBMIT_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx); bool on_search_for_transactions(const wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS_LEGACY::request& req, wallet_public::COMMAND_RPC_SEARCH_FOR_TRANSACTIONS_LEGACY::response& res, epee::json_rpc::error& er, connection_context& cntx); diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp index 6b867f7f..ba2635f5 100644 --- a/src/wallet/wallets_manager.cpp +++ b/src/wallet/wallets_manager.cpp @@ -1898,6 +1898,7 @@ void wallets_manager::prepare_wallet_status_info(wallet_vs_options& wo, view::wa wsi.wallet_id = wo.wallet_id; wsi.is_alias_operations_available = !wo.has_related_alias_in_unconfirmed; wo.w->get()->balance(wsi.balances, wsi.minied_total); + wsi.has_bare_unspent_outputs = wo.w->get()->has_bare_unspent_outputs(); } std::string wallets_manager::check_available_sources(uint64_t wallet_id, std::list& amounts) {