Account tagging
This commit is contained in:
parent
1cc7451130
commit
6b5bd129b4
|
@ -1575,8 +1575,20 @@ simple_wallet::simple_wallet()
|
||||||
tr("Change the current log detail (level must be <0-4>)."));
|
tr("Change the current log detail (level must be <0-4>)."));
|
||||||
m_cmd_binder.set_handler("account",
|
m_cmd_binder.set_handler("account",
|
||||||
boost::bind(&simple_wallet::account, this, _1),
|
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("account\n"
|
||||||
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."));
|
" 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",
|
m_cmd_binder.set_handler("address",
|
||||||
boost::bind(&simple_wallet::print_address, this, _1),
|
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>]"),
|
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())
|
if (m_wallet->has_multisig_partial_key_images())
|
||||||
extra = tr(" (Some owned outputs have partial key images - import_multisig_info needed)");
|
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});
|
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)) << ", "
|
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;
|
<< 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);
|
std::map<uint32_t, uint64_t> balance_per_subaddress = m_wallet->balance_per_subaddress(m_current_subaddress_account);
|
||||||
|
@ -5513,6 +5527,9 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
|
||||||
// account new <label text with white spaces allowed>
|
// account new <label text with white spaces allowed>
|
||||||
// account switch <index>
|
// account switch <index>
|
||||||
// account label <index> <label text with white spaces allowed>
|
// 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())
|
if (args.empty())
|
||||||
{
|
{
|
||||||
|
@ -5577,18 +5594,128 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
|
||||||
fail_msg_writer() << e.what();
|
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
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void simple_wallet::print_accounts()
|
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");
|
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)
|
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"))
|
success_msg_writer() << boost::format(tr(" %c%8u %6s %21s %21s %21s"))
|
||||||
% (m_current_subaddress_account == account_index ? '*' : ' ')
|
% (m_current_subaddress_account == account_index ? '*' : ' ')
|
||||||
% account_index
|
% account_index
|
||||||
|
@ -5596,9 +5723,11 @@ void simple_wallet::print_accounts()
|
||||||
% print_money(m_wallet->balance(account_index))
|
% print_money(m_wallet->balance(account_index))
|
||||||
% print_money(m_wallet->unlocked_balance(account_index))
|
% print_money(m_wallet->unlocked_balance(account_index))
|
||||||
% m_wallet->get_subaddress_label({account_index, 0});
|
% 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() << 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>()*/)
|
bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
|
||||||
|
|
|
@ -153,6 +153,7 @@ namespace cryptonote
|
||||||
);
|
);
|
||||||
bool account(const std::vector<std::string> &args = std::vector<std::string>());
|
bool account(const std::vector<std::string> &args = std::vector<std::string>());
|
||||||
void print_accounts();
|
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_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 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>());
|
bool address_book(const std::vector<std::string> &args = std::vector<std::string>());
|
||||||
|
|
|
@ -7818,6 +7818,46 @@ std::string wallet2::get_description() const
|
||||||
return get_attribute(ATTRIBUTE_DESCRIPTION);
|
return get_attribute(ATTRIBUTE_DESCRIPTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::pair<std::map<std::string, std::string>, std::vector<std::string>>& wallet2::get_account_tags()
|
||||||
|
{
|
||||||
|
// ensure consistency
|
||||||
|
if (m_account_tags.second.size() != get_num_subaddress_accounts())
|
||||||
|
m_account_tags.second.resize(get_num_subaddress_accounts(), "");
|
||||||
|
for (const std::string& tag : m_account_tags.second)
|
||||||
|
{
|
||||||
|
if (!tag.empty() && m_account_tags.first.count(tag) == 0)
|
||||||
|
m_account_tags.first.insert({tag, ""});
|
||||||
|
}
|
||||||
|
for (auto i = m_account_tags.first.begin(); i != m_account_tags.first.end(); )
|
||||||
|
{
|
||||||
|
if (std::find(m_account_tags.second.begin(), m_account_tags.second.end(), i->first) == m_account_tags.second.end())
|
||||||
|
i = m_account_tags.first.erase(i);
|
||||||
|
else
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return m_account_tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wallet2::set_account_tag(const std::set<uint32_t> account_indices, const std::string& tag)
|
||||||
|
{
|
||||||
|
for (uint32_t account_index : account_indices)
|
||||||
|
{
|
||||||
|
THROW_WALLET_EXCEPTION_IF(account_index >= get_num_subaddress_accounts(), error::wallet_internal_error, "Account index out of bound");
|
||||||
|
if (m_account_tags.second[account_index] == tag)
|
||||||
|
MDEBUG("This tag is already assigned to this account");
|
||||||
|
else
|
||||||
|
m_account_tags.second[account_index] = tag;
|
||||||
|
}
|
||||||
|
get_account_tags();
|
||||||
|
}
|
||||||
|
|
||||||
|
void wallet2::set_account_tag_description(const std::string& tag, const std::string& description)
|
||||||
|
{
|
||||||
|
THROW_WALLET_EXCEPTION_IF(tag.empty(), error::wallet_internal_error, "Tag must not be empty");
|
||||||
|
THROW_WALLET_EXCEPTION_IF(m_account_tags.first.count(tag) == 0, error::wallet_internal_error, "Tag is unregistered");
|
||||||
|
m_account_tags.first[tag] = description;
|
||||||
|
}
|
||||||
|
|
||||||
std::string wallet2::sign(const std::string &data) const
|
std::string wallet2::sign(const std::string &data) const
|
||||||
{
|
{
|
||||||
crypto::hash hash;
|
crypto::hash hash;
|
||||||
|
|
|
@ -767,6 +767,9 @@ namespace tools
|
||||||
if(ver < 22)
|
if(ver < 22)
|
||||||
return;
|
return;
|
||||||
a & m_unconfirmed_payments;
|
a & m_unconfirmed_payments;
|
||||||
|
if(ver < 23)
|
||||||
|
return;
|
||||||
|
a & m_account_tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -863,6 +866,24 @@ namespace tools
|
||||||
void set_description(const std::string &description);
|
void set_description(const std::string &description);
|
||||||
std::string get_description() const;
|
std::string get_description() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Get the list of registered account tags.
|
||||||
|
* \return first.Key=(tag's name), first.Value=(tag's label), second[i]=(i-th account's tag)
|
||||||
|
*/
|
||||||
|
const std::pair<std::map<std::string, std::string>, std::vector<std::string>>& get_account_tags();
|
||||||
|
/*!
|
||||||
|
* \brief Set a tag to the given accounts.
|
||||||
|
* \param account_indices Indices of accounts.
|
||||||
|
* \param tag Tag's name. If empty, the accounts become untagged.
|
||||||
|
*/
|
||||||
|
void set_account_tag(const std::set<uint32_t> account_indices, const std::string& tag);
|
||||||
|
/*!
|
||||||
|
* \brief Set the label of the given tag.
|
||||||
|
* \param tag Tag's name (which must be non-empty).
|
||||||
|
* \param label Tag's description.
|
||||||
|
*/
|
||||||
|
void set_account_tag_description(const std::string& tag, const std::string& description);
|
||||||
|
|
||||||
std::string sign(const std::string &data) const;
|
std::string sign(const std::string &data) const;
|
||||||
bool verify(const std::string &data, const cryptonote::account_public_address &address, const std::string &signature) const;
|
bool verify(const std::string &data, const cryptonote::account_public_address &address, const std::string &signature) const;
|
||||||
|
|
||||||
|
@ -1025,6 +1046,7 @@ namespace tools
|
||||||
std::unordered_map<crypto::hash, std::string> m_tx_notes;
|
std::unordered_map<crypto::hash, std::string> m_tx_notes;
|
||||||
std::unordered_map<std::string, std::string> m_attributes;
|
std::unordered_map<std::string, std::string> m_attributes;
|
||||||
std::vector<tools::wallet2::address_book_row> m_address_book;
|
std::vector<tools::wallet2::address_book_row> m_address_book;
|
||||||
|
std::pair<std::map<std::string, std::string>, std::vector<std::string>> m_account_tags;
|
||||||
uint64_t m_upper_transaction_size_limit; //TODO: auto-calc this value or request from daemon, now use some fixed value
|
uint64_t m_upper_transaction_size_limit; //TODO: auto-calc this value or request from daemon, now use some fixed value
|
||||||
const std::vector<std::vector<tools::wallet2::multisig_info>> *m_multisig_rescan_info;
|
const std::vector<std::vector<tools::wallet2::multisig_info>> *m_multisig_rescan_info;
|
||||||
const std::vector<std::vector<rct::key>> *m_multisig_rescan_k;
|
const std::vector<std::vector<rct::key>> *m_multisig_rescan_k;
|
||||||
|
@ -1077,7 +1099,7 @@ namespace tools
|
||||||
std::unordered_map<crypto::public_key, std::map<uint64_t, crypto::key_image> > m_key_image_cache;
|
std::unordered_map<crypto::public_key, std::map<uint64_t, crypto::key_image> > m_key_image_cache;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
BOOST_CLASS_VERSION(tools::wallet2, 22)
|
BOOST_CLASS_VERSION(tools::wallet2, 23)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 9)
|
BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 9)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::multisig_info, 1)
|
BOOST_CLASS_VERSION(tools::wallet2::multisig_info, 1)
|
||||||
BOOST_CLASS_VERSION(tools::wallet2::multisig_info::LR, 0)
|
BOOST_CLASS_VERSION(tools::wallet2::multisig_info::LR, 0)
|
||||||
|
|
|
@ -418,14 +418,24 @@ namespace tools
|
||||||
res.total_balance = 0;
|
res.total_balance = 0;
|
||||||
res.total_unlocked_balance = 0;
|
res.total_unlocked_balance = 0;
|
||||||
cryptonote::subaddress_index subaddr_index = {0,0};
|
cryptonote::subaddress_index subaddr_index = {0,0};
|
||||||
|
const std::pair<std::map<std::string, std::string>, std::vector<std::string>> account_tags = m_wallet->get_account_tags();
|
||||||
|
if (!req.tag.empty() && account_tags.first.count(req.tag) == 0)
|
||||||
|
{
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||||
|
er.message = (boost::format(tr("Tag %s is unregistered.")) % req.tag).str();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
for (; subaddr_index.major < m_wallet->get_num_subaddress_accounts(); ++subaddr_index.major)
|
for (; subaddr_index.major < m_wallet->get_num_subaddress_accounts(); ++subaddr_index.major)
|
||||||
{
|
{
|
||||||
|
if (!req.tag.empty() && req.tag != account_tags.second[subaddr_index.major])
|
||||||
|
continue;
|
||||||
wallet_rpc::COMMAND_RPC_GET_ACCOUNTS::subaddress_account_info info;
|
wallet_rpc::COMMAND_RPC_GET_ACCOUNTS::subaddress_account_info info;
|
||||||
info.account_index = subaddr_index.major;
|
info.account_index = subaddr_index.major;
|
||||||
info.base_address = m_wallet->get_subaddress_as_str(subaddr_index);
|
info.base_address = m_wallet->get_subaddress_as_str(subaddr_index);
|
||||||
info.balance = m_wallet->balance(subaddr_index.major);
|
info.balance = m_wallet->balance(subaddr_index.major);
|
||||||
info.unlocked_balance = m_wallet->unlocked_balance(subaddr_index.major);
|
info.unlocked_balance = m_wallet->unlocked_balance(subaddr_index.major);
|
||||||
info.label = m_wallet->get_subaddress_label(subaddr_index);
|
info.label = m_wallet->get_subaddress_label(subaddr_index);
|
||||||
|
info.tag = account_tags.second[subaddr_index.major];
|
||||||
res.subaddress_accounts.push_back(info);
|
res.subaddress_accounts.push_back(info);
|
||||||
res.total_balance += info.balance;
|
res.total_balance += info.balance;
|
||||||
res.total_unlocked_balance += info.unlocked_balance;
|
res.total_unlocked_balance += info.unlocked_balance;
|
||||||
|
@ -471,6 +481,66 @@ namespace tools
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
bool wallet_rpc_server::on_get_account_tags(const wallet_rpc::COMMAND_RPC_GET_ACCOUNT_TAGS::request& req, wallet_rpc::COMMAND_RPC_GET_ACCOUNT_TAGS::response& res, epee::json_rpc::error& er)
|
||||||
|
{
|
||||||
|
const std::pair<std::map<std::string, std::string>, std::vector<std::string>> account_tags = m_wallet->get_account_tags();
|
||||||
|
for (const std::pair<std::string, std::string>& p : account_tags.first)
|
||||||
|
{
|
||||||
|
res.account_tags.resize(res.account_tags.size() + 1);
|
||||||
|
auto& info = res.account_tags.back();
|
||||||
|
info.tag = p.first;
|
||||||
|
info.label = p.second;
|
||||||
|
for (size_t i = 0; i < account_tags.second.size(); ++i)
|
||||||
|
{
|
||||||
|
if (account_tags.second[i] == info.tag)
|
||||||
|
info.accounts.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
bool wallet_rpc_server::on_tag_accounts(const wallet_rpc::COMMAND_RPC_TAG_ACCOUNTS::request& req, wallet_rpc::COMMAND_RPC_TAG_ACCOUNTS::response& res, epee::json_rpc::error& er)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_wallet->set_account_tag(req.accounts, req.tag);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
bool wallet_rpc_server::on_untag_accounts(const wallet_rpc::COMMAND_RPC_UNTAG_ACCOUNTS::request& req, wallet_rpc::COMMAND_RPC_UNTAG_ACCOUNTS::response& res, epee::json_rpc::error& er)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_wallet->set_account_tag(req.accounts, "");
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
bool wallet_rpc_server::on_set_account_tag_description(const wallet_rpc::COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION::request& req, wallet_rpc::COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION::response& res, epee::json_rpc::error& er)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_wallet->set_account_tag_description(req.tag, req.description);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool wallet_rpc_server::on_getheight(const wallet_rpc::COMMAND_RPC_GET_HEIGHT::request& req, wallet_rpc::COMMAND_RPC_GET_HEIGHT::response& res, epee::json_rpc::error& er)
|
bool wallet_rpc_server::on_getheight(const wallet_rpc::COMMAND_RPC_GET_HEIGHT::request& req, wallet_rpc::COMMAND_RPC_GET_HEIGHT::response& res, epee::json_rpc::error& er)
|
||||||
{
|
{
|
||||||
if (!m_wallet) return not_open(er);
|
if (!m_wallet) return not_open(er);
|
||||||
|
|
|
@ -74,6 +74,10 @@ namespace tools
|
||||||
MAP_JON_RPC_WE("get_accounts", on_get_accounts, wallet_rpc::COMMAND_RPC_GET_ACCOUNTS)
|
MAP_JON_RPC_WE("get_accounts", on_get_accounts, wallet_rpc::COMMAND_RPC_GET_ACCOUNTS)
|
||||||
MAP_JON_RPC_WE("create_account", on_create_account, wallet_rpc::COMMAND_RPC_CREATE_ACCOUNT)
|
MAP_JON_RPC_WE("create_account", on_create_account, wallet_rpc::COMMAND_RPC_CREATE_ACCOUNT)
|
||||||
MAP_JON_RPC_WE("label_account", on_label_account, wallet_rpc::COMMAND_RPC_LABEL_ACCOUNT)
|
MAP_JON_RPC_WE("label_account", on_label_account, wallet_rpc::COMMAND_RPC_LABEL_ACCOUNT)
|
||||||
|
MAP_JON_RPC_WE("get_account_tags", on_get_account_tags, wallet_rpc::COMMAND_RPC_GET_ACCOUNT_TAGS)
|
||||||
|
MAP_JON_RPC_WE("tag_accounts", on_tag_accounts, wallet_rpc::COMMAND_RPC_TAG_ACCOUNTS)
|
||||||
|
MAP_JON_RPC_WE("untag_accounts", on_untag_accounts, wallet_rpc::COMMAND_RPC_UNTAG_ACCOUNTS)
|
||||||
|
MAP_JON_RPC_WE("set_account_tag_description", on_set_account_tag_description, wallet_rpc::COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION)
|
||||||
MAP_JON_RPC_WE("getheight", on_getheight, wallet_rpc::COMMAND_RPC_GET_HEIGHT)
|
MAP_JON_RPC_WE("getheight", on_getheight, wallet_rpc::COMMAND_RPC_GET_HEIGHT)
|
||||||
MAP_JON_RPC_WE("transfer", on_transfer, wallet_rpc::COMMAND_RPC_TRANSFER)
|
MAP_JON_RPC_WE("transfer", on_transfer, wallet_rpc::COMMAND_RPC_TRANSFER)
|
||||||
MAP_JON_RPC_WE("transfer_split", on_transfer_split, wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT)
|
MAP_JON_RPC_WE("transfer_split", on_transfer_split, wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT)
|
||||||
|
@ -136,6 +140,10 @@ namespace tools
|
||||||
bool on_get_accounts(const wallet_rpc::COMMAND_RPC_GET_ACCOUNTS::request& req, wallet_rpc::COMMAND_RPC_GET_ACCOUNTS::response& res, epee::json_rpc::error& er);
|
bool on_get_accounts(const wallet_rpc::COMMAND_RPC_GET_ACCOUNTS::request& req, wallet_rpc::COMMAND_RPC_GET_ACCOUNTS::response& res, epee::json_rpc::error& er);
|
||||||
bool on_create_account(const wallet_rpc::COMMAND_RPC_CREATE_ACCOUNT::request& req, wallet_rpc::COMMAND_RPC_CREATE_ACCOUNT::response& res, epee::json_rpc::error& er);
|
bool on_create_account(const wallet_rpc::COMMAND_RPC_CREATE_ACCOUNT::request& req, wallet_rpc::COMMAND_RPC_CREATE_ACCOUNT::response& res, epee::json_rpc::error& er);
|
||||||
bool on_label_account(const wallet_rpc::COMMAND_RPC_LABEL_ACCOUNT::request& req, wallet_rpc::COMMAND_RPC_LABEL_ACCOUNT::response& res, epee::json_rpc::error& er);
|
bool on_label_account(const wallet_rpc::COMMAND_RPC_LABEL_ACCOUNT::request& req, wallet_rpc::COMMAND_RPC_LABEL_ACCOUNT::response& res, epee::json_rpc::error& er);
|
||||||
|
bool on_get_account_tags(const wallet_rpc::COMMAND_RPC_GET_ACCOUNT_TAGS::request& req, wallet_rpc::COMMAND_RPC_GET_ACCOUNT_TAGS::response& res, epee::json_rpc::error& er);
|
||||||
|
bool on_tag_accounts(const wallet_rpc::COMMAND_RPC_TAG_ACCOUNTS::request& req, wallet_rpc::COMMAND_RPC_TAG_ACCOUNTS::response& res, epee::json_rpc::error& er);
|
||||||
|
bool on_untag_accounts(const wallet_rpc::COMMAND_RPC_UNTAG_ACCOUNTS::request& req, wallet_rpc::COMMAND_RPC_UNTAG_ACCOUNTS::response& res, epee::json_rpc::error& er);
|
||||||
|
bool on_set_account_tag_description(const wallet_rpc::COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION::request& req, wallet_rpc::COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION::response& res, epee::json_rpc::error& er);
|
||||||
bool on_getheight(const wallet_rpc::COMMAND_RPC_GET_HEIGHT::request& req, wallet_rpc::COMMAND_RPC_GET_HEIGHT::response& res, epee::json_rpc::error& er);
|
bool on_getheight(const wallet_rpc::COMMAND_RPC_GET_HEIGHT::request& req, wallet_rpc::COMMAND_RPC_GET_HEIGHT::response& res, epee::json_rpc::error& er);
|
||||||
bool validate_transfer(const std::list<wallet_rpc::transfer_destination>& destinations, const std::string& payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t>& extra, epee::json_rpc::error& er);
|
bool validate_transfer(const std::list<wallet_rpc::transfer_destination>& destinations, const std::string& payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t>& extra, epee::json_rpc::error& er);
|
||||||
bool on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er);
|
bool on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er);
|
||||||
|
|
|
@ -176,7 +176,10 @@ namespace wallet_rpc
|
||||||
{
|
{
|
||||||
struct request
|
struct request
|
||||||
{
|
{
|
||||||
|
std::string tag; // all accounts if empty, otherwise those accounts with this tag
|
||||||
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(tag)
|
||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -187,6 +190,7 @@ namespace wallet_rpc
|
||||||
uint64_t balance;
|
uint64_t balance;
|
||||||
uint64_t unlocked_balance;
|
uint64_t unlocked_balance;
|
||||||
std::string label;
|
std::string label;
|
||||||
|
std::string tag;
|
||||||
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
KV_SERIALIZE(account_index)
|
KV_SERIALIZE(account_index)
|
||||||
|
@ -194,6 +198,7 @@ namespace wallet_rpc
|
||||||
KV_SERIALIZE(balance)
|
KV_SERIALIZE(balance)
|
||||||
KV_SERIALIZE(unlocked_balance)
|
KV_SERIALIZE(unlocked_balance)
|
||||||
KV_SERIALIZE(label)
|
KV_SERIALIZE(label)
|
||||||
|
KV_SERIALIZE(tag)
|
||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -252,6 +257,95 @@ namespace wallet_rpc
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct COMMAND_RPC_GET_ACCOUNT_TAGS
|
||||||
|
{
|
||||||
|
struct request
|
||||||
|
{
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct account_tag_info
|
||||||
|
{
|
||||||
|
std::string tag;
|
||||||
|
std::string label;
|
||||||
|
std::vector<uint32_t> accounts;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(tag);
|
||||||
|
KV_SERIALIZE(label);
|
||||||
|
KV_SERIALIZE(accounts);
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct response
|
||||||
|
{
|
||||||
|
std::vector<account_tag_info> account_tags;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(account_tags)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct COMMAND_RPC_TAG_ACCOUNTS
|
||||||
|
{
|
||||||
|
struct request
|
||||||
|
{
|
||||||
|
std::string tag;
|
||||||
|
std::set<uint32_t> accounts;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(tag)
|
||||||
|
KV_SERIALIZE(accounts)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct response
|
||||||
|
{
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct COMMAND_RPC_UNTAG_ACCOUNTS
|
||||||
|
{
|
||||||
|
struct request
|
||||||
|
{
|
||||||
|
std::set<uint32_t> accounts;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(accounts)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct response
|
||||||
|
{
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION
|
||||||
|
{
|
||||||
|
struct request
|
||||||
|
{
|
||||||
|
std::string tag;
|
||||||
|
std::string description;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(tag)
|
||||||
|
KV_SERIALIZE(description)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct response
|
||||||
|
{
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
struct COMMAND_RPC_GET_HEIGHT
|
struct COMMAND_RPC_GET_HEIGHT
|
||||||
{
|
{
|
||||||
struct request
|
struct request
|
||||||
|
|
Loading…
Reference in New Issue