mirror of https://github.com/oxen-io/oxen-core.git
Adds batched amounts to wallet2 rpc and simplewallet
This adds detail to the balance command of the CLI wallet to show how much has been batched for each address and also summarises when the next payout is. It also includes additional fields to get_balance rpc endpoint on the oxen-wallet-rpc so the user can check on the status of their accrued funds.
This commit is contained in:
parent
e120075c37
commit
90cc745987
|
@ -53,6 +53,7 @@
|
|||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <oxenc/hex.h>
|
||||
#include "epee/console_handler.h"
|
||||
#include "common/i18n.h"
|
||||
|
@ -5059,18 +5060,34 @@ bool simple_wallet::show_balance_unlocked(bool detailed)
|
|||
<< tr("unlocked balance: ") << print_money(unlocked_balance) << unlock_time_message << extra;
|
||||
std::map<uint32_t, uint64_t> balance_per_subaddress = m_wallet->balance_per_subaddress(m_current_subaddress_account, false);
|
||||
std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> unlocked_balance_per_subaddress = m_wallet->unlocked_balance_per_subaddress(m_current_subaddress_account, false);
|
||||
address_parse_info info;
|
||||
const auto& conf = get_config(m_wallet->nettype());
|
||||
std::string current_address_str = m_wallet->get_subaddress_as_str({m_current_subaddress_account, 0});
|
||||
if(cryptonote::get_account_address_from_str(info, m_wallet->nettype(), current_address_str))
|
||||
{
|
||||
const uint64_t blockchain_height = m_wallet->get_blockchain_current_height();
|
||||
if(uint64_t batched_amount = m_wallet->get_batched_amount(current_address_str); batched_amount > 0)
|
||||
{
|
||||
uint64_t next_payout_block = info.address.next_payout_height(blockchain_height, conf.BATCHING_INTERVAL);
|
||||
std::string next_batch_payout = fmt::format(" (next payout: block {}, in about {})", next_payout_block, tools::get_human_readable_timespan(std::chrono::seconds((next_payout_block - blockchain_height) * TARGET_BLOCK_TIME)));
|
||||
success_msg_writer() << tr("Pending SN rewards: ")
|
||||
<< print_money(m_wallet->get_batched_amount(current_address_str)) << ", "
|
||||
<< next_batch_payout;
|
||||
}
|
||||
}
|
||||
if (!detailed || balance_per_subaddress.empty())
|
||||
return true;
|
||||
success_msg_writer() << tr("Balance per address:");
|
||||
success_msg_writer() << boost::format("%15s %21s %21s %7s %21s") % tr("Address") % tr("Balance") % tr("Unlocked balance") % tr("Outputs") % tr("Label");
|
||||
success_msg_writer() << boost::format("%15s %21s %21s %21s %7s %21s") % tr("Address") % tr("Balance") % tr("Unlocked balance") % tr("Batched Amount") % tr("Outputs") % tr("Label");
|
||||
std::vector<wallet::transfer_details> transfers;
|
||||
m_wallet->get_transfers(transfers);
|
||||
for (const auto& i : balance_per_subaddress)
|
||||
{
|
||||
cryptonote::subaddress_index subaddr_index = {m_current_subaddress_account, i.first};
|
||||
std::string address_str = m_wallet->get_subaddress_as_str(subaddr_index).substr(0, 6);
|
||||
uint64_t batched_amount = m_wallet->get_batched_amount(address_str);
|
||||
uint64_t num_unspent_outputs = std::count_if(transfers.begin(), transfers.end(), [&subaddr_index](const wallet::transfer_details& td) { return !td.m_spent && td.m_subaddr_index == subaddr_index; });
|
||||
success_msg_writer() << boost::format(tr("%8u %6s %21s %21s %7u %21s")) % i.first % address_str % print_money(i.second) % print_money(unlocked_balance_per_subaddress[i.first].first) % num_unspent_outputs % m_wallet->get_subaddress_label(subaddr_index);
|
||||
success_msg_writer() << boost::format(tr("%8u %6s %21s %21s %21s %7u %21s")) % i.first % address_str % print_money(i.second) % print_money(unlocked_balance_per_subaddress[i.first].first) % print_money(batched_amount) % num_unspent_outputs % m_wallet->get_subaddress_label(subaddr_index);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -9107,18 +9124,20 @@ void simple_wallet::print_accounts(const std::string& tag)
|
|||
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 %21s") % tr("Address") % tr("Balance") % tr("Unlocked balance") % tr("Batched Amount") % 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)
|
||||
{
|
||||
std::string address_str = m_wallet->get_subaddress_as_str({account_index, 0}).substr(0, 6);
|
||||
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 %21s"))
|
||||
% (m_current_subaddress_account == account_index ? '*' : ' ')
|
||||
% account_index
|
||||
% m_wallet->get_subaddress_as_str({account_index, 0}).substr(0, 6)
|
||||
% address_str
|
||||
% print_money(m_wallet->balance(account_index, false))
|
||||
% print_money(m_wallet->unlocked_balance(account_index, false))
|
||||
% print_money(m_wallet->get_batched_amount(address_str))
|
||||
% m_wallet->get_subaddress_label({account_index, 0});
|
||||
total_balance += m_wallet->balance(account_index, false);
|
||||
total_unlocked_balance += m_wallet->unlocked_balance(account_index, false);
|
||||
|
|
|
@ -1063,6 +1063,12 @@ uint64_t WalletImpl::unlockedBalance(uint32_t accountIndex) const
|
|||
return wallet()->unlocked_balance(accountIndex, false);
|
||||
}
|
||||
|
||||
EXPORT
|
||||
uint64_t WalletImpl::accruedBalance(const std::string& address) const
|
||||
{
|
||||
return wallet()->get_batched_amount(address);
|
||||
}
|
||||
|
||||
EXPORT
|
||||
std::vector<Wallet::stake_info>* WalletImpl::listCurrentStakes() const
|
||||
{
|
||||
|
|
|
@ -118,6 +118,7 @@ public:
|
|||
bool trustedDaemon() const override;
|
||||
uint64_t balance(uint32_t accountIndex = 0) const override;
|
||||
uint64_t unlockedBalance(uint32_t accountIndex = 0) const override;
|
||||
uint64_t accruedBalance(const std::string& address) const override;
|
||||
std::vector<Wallet::stake_info>* listCurrentStakes() const override;
|
||||
uint64_t blockChainHeight() const override;
|
||||
uint64_t approximateBlockChainHeight() const override;
|
||||
|
|
|
@ -609,6 +609,12 @@ struct Wallet
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief accruedBalance - returns the accounts balance that has been batched and yet to be paid.
|
||||
* @return
|
||||
*/
|
||||
virtual uint64_t accruedBalance(const std::string& address) const = 0;
|
||||
|
||||
// Information returned about stakes in listCurrentStakes()
|
||||
struct stake_info {
|
||||
std::string sn_pubkey;
|
||||
|
|
|
@ -3639,6 +3639,8 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
|
|||
LOG_PRINT_L1("Failed to check pending transactions");
|
||||
}
|
||||
|
||||
refresh_batching_cache();
|
||||
|
||||
m_first_refresh_done = true;
|
||||
|
||||
LOG_PRINT_L1("Refresh done, blocks received: " << blocks_fetched << ", balance (all accounts): " << print_money(balance_all(false)) << ", unlocked: " << print_money(unlocked_balance_all(false)));
|
||||
|
@ -12994,6 +12996,26 @@ std::unordered_map<std::string, wallet2::ons_detail> wallet2::get_ons_cache()
|
|||
return ons_records_cache;
|
||||
}
|
||||
|
||||
void wallet2::refresh_batching_cache()
|
||||
{
|
||||
rpc::GET_ACCRUED_BATCHED_EARNINGS::request req{};
|
||||
rpc::GET_ACCRUED_BATCHED_EARNINGS::response daemon_resp{};
|
||||
bool r = invoke_http<rpc::GET_ACCRUED_BATCHED_EARNINGS>(req, daemon_resp);
|
||||
if (r && daemon_resp.status == rpc::STATUS_OK)
|
||||
{
|
||||
batching_records_cache.clear();
|
||||
for (size_t i = 0; i < daemon_resp.addresses.size(); ++i)
|
||||
batching_records_cache.insert({std::move(daemon_resp.addresses[i]), std::move(daemon_resp.amounts[i])});
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t wallet2::get_batched_amount(const std::string& address) const
|
||||
{
|
||||
if (auto i = batching_records_cache.find(address); i != batching_records_cache.end())
|
||||
return i->second;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wallet2::set_tx_note(const crypto::hash &txid, const std::string ¬e)
|
||||
{
|
||||
m_tx_notes[txid] = note;
|
||||
|
|
|
@ -849,6 +849,11 @@ private:
|
|||
|
||||
std::unordered_map<std::string, ons_detail> get_ons_cache();
|
||||
|
||||
std::unordered_map<std::string, uint64_t> batching_records_cache;
|
||||
|
||||
void refresh_batching_cache();
|
||||
uint64_t get_batched_amount(const std::string& address) const;
|
||||
|
||||
// Returns the current height up to which the wallet has synchronized the blockchain. Thread
|
||||
// safe (though the value may be behind if another thread is in the middle of adding blocks).
|
||||
uint64_t get_blockchain_current_height() const { return m_cached_height; }
|
||||
|
|
|
@ -610,6 +610,18 @@ namespace tools
|
|||
res.balance = req.all_accounts ? m_wallet->balance_all(req.strict) : m_wallet->balance(req.account_index, req.strict);
|
||||
res.unlocked_balance = req.all_accounts ? m_wallet->unlocked_balance_all(req.strict, &res.blocks_to_unlock, &res.time_to_unlock) : m_wallet->unlocked_balance(req.account_index, req.strict, &res.blocks_to_unlock, &res.time_to_unlock);
|
||||
res.multisig_import_needed = m_wallet->multisig() && m_wallet->has_multisig_partial_key_images();
|
||||
std::string current_address_str = m_wallet->get_subaddress_as_str({(req.all_accounts ? 0 : req.account_index), 0});
|
||||
res.accrued_balance = m_wallet->get_batched_amount(current_address_str);
|
||||
if (res.accrued_balance > 0)
|
||||
{
|
||||
cryptonote::address_parse_info info;
|
||||
auto& conf = cryptonote::get_config(m_wallet->nettype());
|
||||
get_account_address_from_str(info, m_wallet->nettype(), current_address_str);
|
||||
res.accrued_balance_next_payout = info.address.next_payout_height(m_wallet->get_blockchain_current_height(), conf.BATCHING_INTERVAL);
|
||||
} else {
|
||||
res.accrued_balance_next_payout = 0;
|
||||
}
|
||||
|
||||
std::map<uint32_t, std::map<uint32_t, uint64_t>> balance_per_subaddress_per_account;
|
||||
std::map<uint32_t, std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>>> unlocked_balance_per_subaddress_per_account;
|
||||
if (req.all_accounts)
|
||||
|
|
|
@ -61,6 +61,8 @@ KV_SERIALIZE_MAP_CODE_END()
|
|||
KV_SERIALIZE_MAP_CODE_BEGIN(GET_BALANCE::response)
|
||||
KV_SERIALIZE(balance)
|
||||
KV_SERIALIZE(unlocked_balance)
|
||||
KV_SERIALIZE(accrued_balance)
|
||||
KV_SERIALIZE(accrued_balance_next_payout)
|
||||
KV_SERIALIZE(multisig_import_needed)
|
||||
KV_SERIALIZE(per_subaddress)
|
||||
KV_SERIALIZE(blocks_to_unlock)
|
||||
|
|
|
@ -121,6 +121,8 @@ namespace tools::wallet_rpc {
|
|||
{
|
||||
uint64_t balance; // The total balance (atomic units) of the currently opened wallet.
|
||||
uint64_t unlocked_balance; // Unlocked funds are those funds that are sufficiently deep enough in the oxen blockchain to be considered safe to spend.
|
||||
uint64_t accrued_balance; // The unpaid accrued service node rewards currently in the batching database for this currently opened wallet
|
||||
uint64_t accrued_balance_next_payout; // Height that the accrued service node rewards will be paid out
|
||||
bool multisig_import_needed; // True if importing multisig data is needed for returning a correct balance.
|
||||
std::vector<per_subaddress_info> per_subaddress; // Balance information for each subaddress in an account.
|
||||
uint64_t blocks_to_unlock; // The number of blocks remaining for the balance to unlock
|
||||
|
|
Loading…
Reference in New Issue