aboutsummaryrefslogtreecommitdiff
path: root/src/simplewallet
diff options
context:
space:
mode:
Diffstat (limited to 'src/simplewallet')
-rw-r--r--src/simplewallet/simplewallet.cpp147
-rw-r--r--src/simplewallet/simplewallet.h1
2 files changed, 139 insertions, 9 deletions
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index ffe921ae7..608844b80 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -1575,8 +1575,20 @@ simple_wallet::simple_wallet()
tr("Change the current log detail (level must be <0-4>)."));
m_cmd_binder.set_handler("account",
boost::bind(&simple_wallet::account, this, _1),
- tr("account [new <label text with white spaces allowed> | switch <index> | label <index> <label text with white spaces allowed>]"),
- tr("If no arguments are specified, the wallet shows all the existing accounts along with their balances. If the \"new\" argument is specified, the wallet creates a new account with its label initialized by the provided label text (which can be empty). If the \"switch\" argument is specified, the wallet switches to the account specified by <index>. If the \"label\" argument is specified, the wallet sets the label of the account specified by <index> to the provided label text."));
+ tr("account\n"
+ " account new <label text with white spaces allowed>\n"
+ " account switch <index> \n"
+ " account label <index> <label text with white spaces allowed>\n"
+ " account tag <tag_name> <account_index_1> [<account_index_2> ...]\n"
+ " account untag <account_index_1> [<account_index_2> ...]\n"
+ " account tag_description <tag_name> <description>"),
+ tr("If no arguments are specified, the wallet shows all the existing accounts along with their balances.\n"
+ "If the \"new\" argument is specified, the wallet creates a new account with its label initialized by the provided label text (which can be empty).\n"
+ "If the \"switch\" argument is specified, the wallet switches to the account specified by <index>.\n"
+ "If the \"label\" argument is specified, the wallet sets the label of the account specified by <index> to the provided label text.\n"
+ "If the \"tag\" argument is specified, a tag <tag_name> is assigned to the specified accounts <account_index_1>, <account_index_2>, ....\n"
+ "If the \"untag\" argument is specified, the tags assigned to the specified accounts <account_index_1>, <account_index_2> ..., are removed.\n"
+ "If the \"tag_description\" argument is specified, the tag <tag_name> is assigned an arbitrary text <description>."));
m_cmd_binder.set_handler("address",
boost::bind(&simple_wallet::print_address, this, _1),
tr("address [ new <label text with white spaces allowed> | all | <index_min> [<index_max>] | label <index> <label text with white spaces allowed>]"),
@@ -3119,6 +3131,8 @@ bool simple_wallet::show_balance_unlocked(bool detailed)
if (m_wallet->has_multisig_partial_key_images())
extra = tr(" (Some owned outputs have partial key images - import_multisig_info needed)");
success_msg_writer() << tr("Currently selected account: [") << m_current_subaddress_account << tr("] ") << m_wallet->get_subaddress_label({m_current_subaddress_account, 0});
+ const std::string tag = m_wallet->get_account_tags().second[m_current_subaddress_account];
+ success_msg_writer() << tr("Tag: ") << (tag.empty() ? std::string{tr("(No tag assigned)")} : tag);
success_msg_writer() << tr("Balance: ") << print_money(m_wallet->balance(m_current_subaddress_account)) << ", "
<< tr("unlocked balance: ") << print_money(m_wallet->unlocked_balance(m_current_subaddress_account)) << extra;
std::map<uint32_t, uint64_t> balance_per_subaddress = m_wallet->balance_per_subaddress(m_current_subaddress_account);
@@ -4321,9 +4335,9 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
fail_msg_writer() << tr("Multiple transactions are created, which is not supposed to happen");
return true;
}
- if (ptx_vector[0].selected_transfers.size() > 1)
+ if (ptx_vector[0].selected_transfers.size() != 1)
{
- fail_msg_writer() << tr("The transaction uses multiple inputs, which is not supposed to happen");
+ fail_msg_writer() << tr("The transaction uses multiple or no inputs, which is not supposed to happen");
return true;
}
@@ -5094,7 +5108,7 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_)
try {
min_height = boost::lexical_cast<uint64_t>(local_args[0]);
}
- catch (boost::bad_lexical_cast &) {
+ catch (const boost::bad_lexical_cast &) {
fail_msg_writer() << tr("bad min_height parameter:") << " " << local_args[0];
return true;
}
@@ -5106,7 +5120,7 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_)
try {
max_height = boost::lexical_cast<uint64_t>(local_args[0]);
}
- catch (boost::bad_lexical_cast &) {
+ catch (const boost::bad_lexical_cast &) {
fail_msg_writer() << tr("bad max_height parameter:") << " " << local_args[0];
return true;
}
@@ -5269,7 +5283,7 @@ bool simple_wallet::unspent_outputs(const std::vector<std::string> &args_)
for (const auto& td : transfers)
{
uint64_t amount = td.amount();
- if (td.m_spent || amount < min_amount || amount > max_amount || td.m_subaddr_index.major != m_current_subaddress_account || subaddr_indices.count(td.m_subaddr_index.minor) == 0)
+ if (td.m_spent || amount < min_amount || amount > max_amount || td.m_subaddr_index.major != m_current_subaddress_account || (subaddr_indices.count(td.m_subaddr_index.minor) == 0 && !subaddr_indices.empty()))
continue;
amount_to_tds[amount].push_back(td);
if (min_height > td.m_block_height) min_height = td.m_block_height;
@@ -5432,6 +5446,9 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
// account new <label text with white spaces allowed>
// account switch <index>
// account label <index> <label text with white spaces allowed>
+ // account tag <tag_name> <account_index_1> [<account_index_2> ...]
+ // account untag <account_index_1> [<account_index_2> ...]
+ // account tag_description <tag_name> <description>
if (args.empty())
{
@@ -5496,18 +5513,128 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
fail_msg_writer() << e.what();
}
}
+ else if (command == "tag" && local_args.size() >= 2)
+ {
+ const std::string tag = local_args[0];
+ std::set<uint32_t> account_indices;
+ for (size_t i = 1; i < local_args.size(); ++i)
+ {
+ uint32_t account_index;
+ if (!epee::string_tools::get_xtype_from_string(account_index, local_args[i]))
+ {
+ fail_msg_writer() << tr("failed to parse index: ") << local_args[i];
+ return true;
+ }
+ account_indices.insert(account_index);
+ }
+ try
+ {
+ m_wallet->set_account_tag(account_indices, tag);
+ print_accounts(tag);
+ }
+ catch (const std::exception& e)
+ {
+ fail_msg_writer() << e.what();
+ }
+ }
+ else if (command == "untag" && local_args.size() >= 1)
+ {
+ std::set<uint32_t> account_indices;
+ for (size_t i = 0; i < local_args.size(); ++i)
+ {
+ uint32_t account_index;
+ if (!epee::string_tools::get_xtype_from_string(account_index, local_args[i]))
+ {
+ fail_msg_writer() << tr("failed to parse index: ") << local_args[i];
+ return true;
+ }
+ account_indices.insert(account_index);
+ }
+ try
+ {
+ m_wallet->set_account_tag(account_indices, "");
+ print_accounts();
+ }
+ catch (const std::exception& e)
+ {
+ fail_msg_writer() << e.what();
+ }
+ }
+ else if (command == "tag_description" && local_args.size() >= 1)
+ {
+ const std::string tag = local_args[0];
+ std::string description;
+ if (local_args.size() > 1)
+ {
+ local_args.erase(local_args.begin());
+ description = boost::join(local_args, " ");
+ }
+ try
+ {
+ m_wallet->set_account_tag_description(tag, description);
+ print_accounts(tag);
+ }
+ catch (const std::exception& e)
+ {
+ fail_msg_writer() << e.what();
+ }
+ }
else
{
- fail_msg_writer() << tr("usage: account [new <label text with white spaces allowed> | switch <index> | label <index> <label text with white spaces allowed>]");
+ fail_msg_writer() << tr("usage:\n"
+ " account\n"
+ " account new <label text with white spaces allowed>\n"
+ " account switch <index>\n"
+ " account label <index> <label text with white spaces allowed>\n"
+ " account tag <tag_name> <account_index_1> [<account_index_2> ...]\n"
+ " account untag <account_index_1> [<account_index_2> ...]\n"
+ " account tag_description <tag_name> <description>");
}
return true;
}
//----------------------------------------------------------------------------------------------------
void simple_wallet::print_accounts()
{
+ const std::pair<std::map<std::string, std::string>, std::vector<std::string>>& account_tags = m_wallet->get_account_tags();
+ size_t num_untagged_accounts = m_wallet->get_num_subaddress_accounts();
+ for (const std::pair<std::string, std::string>& p : account_tags.first)
+ {
+ const std::string& tag = p.first;
+ print_accounts(tag);
+ num_untagged_accounts -= std::count(account_tags.second.begin(), account_tags.second.end(), tag);
+ success_msg_writer() << "";
+ }
+
+ if (num_untagged_accounts > 0)
+ print_accounts("");
+
+ if (num_untagged_accounts < m_wallet->get_num_subaddress_accounts())
+ success_msg_writer() << tr("\nGrand total:\n Balance: ") << print_money(m_wallet->balance_all()) << tr(", unlocked balance: ") << print_money(m_wallet->unlocked_balance_all());
+}
+//----------------------------------------------------------------------------------------------------
+void simple_wallet::print_accounts(const std::string& tag)
+{
+ const std::pair<std::map<std::string, std::string>, std::vector<std::string>>& account_tags = m_wallet->get_account_tags();
+ if (tag.empty())
+ {
+ success_msg_writer() << tr("Untagged accounts:");
+ }
+ else
+ {
+ if (account_tags.first.count(tag) == 0)
+ {
+ fail_msg_writer() << boost::format(tr("Tag %s is unregistered.")) % tag;
+ return;
+ }
+ success_msg_writer() << tr("Accounts with tag: ") << tag;
+ success_msg_writer() << tr("Tag's description: ") << account_tags.first.find(tag)->second;
+ }
success_msg_writer() << boost::format(" %15s %21s %21s %21s") % tr("Account") % tr("Balance") % tr("Unlocked balance") % tr("Label");
+ uint64_t total_balance = 0, total_unlocked_balance = 0;
for (uint32_t account_index = 0; account_index < m_wallet->get_num_subaddress_accounts(); ++account_index)
{
+ if (account_tags.second[account_index] != tag)
+ continue;
success_msg_writer() << boost::format(tr(" %c%8u %6s %21s %21s %21s"))
% (m_current_subaddress_account == account_index ? '*' : ' ')
% account_index
@@ -5515,9 +5642,11 @@ void simple_wallet::print_accounts()
% print_money(m_wallet->balance(account_index))
% print_money(m_wallet->unlocked_balance(account_index))
% m_wallet->get_subaddress_label({account_index, 0});
+ total_balance += m_wallet->balance(account_index);
+ total_unlocked_balance += m_wallet->unlocked_balance(account_index);
}
success_msg_writer() << tr("----------------------------------------------------------------------------------");
- success_msg_writer() << boost::format(tr("%15s %21s %21s")) % "Total" % print_money(m_wallet->balance_all()) % print_money(m_wallet->unlocked_balance_all());
+ success_msg_writer() << boost::format(tr("%15s %21s %21s")) % "Total" % print_money(total_balance) % print_money(total_unlocked_balance);
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
index c0c33f6b8..e5c00e542 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -153,6 +153,7 @@ namespace cryptonote
);
bool account(const std::vector<std::string> &args = std::vector<std::string>());
void print_accounts();
+ void print_accounts(const std::string& tag);
bool print_address(const std::vector<std::string> &args = std::vector<std::string>());
bool print_integrated_address(const std::vector<std::string> &args = std::vector<std::string>());
bool address_book(const std::vector<std::string> &args = std::vector<std::string>());