mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-11 20:32:35 -03:00
rpc: Add getbalances RPC
This commit is contained in:
parent
fad13e925e
commit
999931cf8f
2 changed files with 83 additions and 7 deletions
|
@ -1,5 +1,5 @@
|
||||||
// Copyright (c) 2010 Satoshi Nakamoto
|
// Copyright (c) 2010 Satoshi Nakamoto
|
||||||
// Copyright (c) 2009-2018 The Bitcoin Core developers
|
// Copyright (c) 2009-2019 The Bitcoin Core developers
|
||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@
|
||||||
#include <core_io.h>
|
#include <core_io.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
#include <interfaces/chain.h>
|
#include <interfaces/chain.h>
|
||||||
#include <validation.h>
|
|
||||||
#include <key_io.h>
|
#include <key_io.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
#include <node/transaction.h>
|
#include <node/transaction.h>
|
||||||
|
@ -27,10 +26,11 @@
|
||||||
#include <timedata.h>
|
#include <timedata.h>
|
||||||
#include <util/bip32.h>
|
#include <util/bip32.h>
|
||||||
#include <util/fees.h>
|
#include <util/fees.h>
|
||||||
#include <util/system.h>
|
|
||||||
#include <util/moneystr.h>
|
#include <util/moneystr.h>
|
||||||
|
#include <util/system.h>
|
||||||
#include <util/url.h>
|
#include <util/url.h>
|
||||||
#include <util/validation.h>
|
#include <util/validation.h>
|
||||||
|
#include <validation.h>
|
||||||
#include <wallet/coincontrol.h>
|
#include <wallet/coincontrol.h>
|
||||||
#include <wallet/feebumper.h>
|
#include <wallet/feebumper.h>
|
||||||
#include <wallet/psbtwallet.h>
|
#include <wallet/psbtwallet.h>
|
||||||
|
@ -2373,6 +2373,68 @@ static UniValue settxfee(const JSONRPCRequest& request)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UniValue getbalances(const JSONRPCRequest& request)
|
||||||
|
{
|
||||||
|
std::shared_ptr<CWallet> const rpc_wallet = GetWalletForJSONRPCRequest(request);
|
||||||
|
if (!EnsureWalletIsAvailable(rpc_wallet.get(), request.fHelp)) {
|
||||||
|
return NullUniValue;
|
||||||
|
}
|
||||||
|
CWallet& wallet = *rpc_wallet;
|
||||||
|
|
||||||
|
const RPCHelpMan help{
|
||||||
|
"getbalances",
|
||||||
|
"Returns an object with all balances in " + CURRENCY_UNIT + ".\n",
|
||||||
|
{},
|
||||||
|
RPCResult{
|
||||||
|
"{\n"
|
||||||
|
" \"mine\": { (object) balances from outputs that the wallet can sign\n"
|
||||||
|
" \"trusted\": xxx (numeric) trusted balance (outputs created by the wallet or confirmed outputs)\n"
|
||||||
|
" \"untrusted_pending\": xxx (numeric) untrusted pending balance (outputs created by others that are in the mempool)\n"
|
||||||
|
" \"immature\": xxx (numeric) balance from immature coinbase outputs\n"
|
||||||
|
" },\n"
|
||||||
|
" \"watchonly\": { (object) watchonly balances (not present if wallet does not watch anything)\n"
|
||||||
|
" \"trusted\": xxx (numeric) trusted balance (outputs created by the wallet or confirmed outputs)\n"
|
||||||
|
" \"untrusted_pending\": xxx (numeric) untrusted pending balance (outputs created by others that are in the mempool)\n"
|
||||||
|
" \"immature\": xxx (numeric) balance from immature coinbase outputs\n"
|
||||||
|
" },\n"
|
||||||
|
"}\n"},
|
||||||
|
RPCExamples{
|
||||||
|
HelpExampleCli("getbalances", "") +
|
||||||
|
HelpExampleRpc("getbalances", "")},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (request.fHelp || !help.IsValidNumArgs(request.params.size())) {
|
||||||
|
throw std::runtime_error(help.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the results are valid at least up to the most recent block
|
||||||
|
// the user could have gotten from another RPC command prior to now
|
||||||
|
wallet.BlockUntilSyncedToCurrentChain();
|
||||||
|
|
||||||
|
auto locked_chain = wallet.chain().lock();
|
||||||
|
LOCK(wallet.cs_wallet);
|
||||||
|
|
||||||
|
UniValue obj(UniValue::VOBJ);
|
||||||
|
|
||||||
|
const auto bal = wallet.GetBalance();
|
||||||
|
UniValue balances{UniValue::VOBJ};
|
||||||
|
{
|
||||||
|
UniValue balances_mine{UniValue::VOBJ};
|
||||||
|
balances_mine.pushKV("trusted", ValueFromAmount(bal.m_mine_trusted));
|
||||||
|
balances_mine.pushKV("untrusted_pending", ValueFromAmount(bal.m_mine_untrusted_pending));
|
||||||
|
balances_mine.pushKV("immature", ValueFromAmount(bal.m_mine_immature));
|
||||||
|
balances.pushKV("mine", balances_mine);
|
||||||
|
}
|
||||||
|
if (wallet.HaveWatchOnly()) {
|
||||||
|
UniValue balances_watchonly{UniValue::VOBJ};
|
||||||
|
balances_watchonly.pushKV("trusted", ValueFromAmount(bal.m_watchonly_trusted));
|
||||||
|
balances_watchonly.pushKV("untrusted_pending", ValueFromAmount(bal.m_watchonly_untrusted_pending));
|
||||||
|
balances_watchonly.pushKV("immature", ValueFromAmount(bal.m_watchonly_immature));
|
||||||
|
balances.pushKV("watchonly", balances_watchonly);
|
||||||
|
}
|
||||||
|
return balances;
|
||||||
|
}
|
||||||
|
|
||||||
static UniValue getwalletinfo(const JSONRPCRequest& request)
|
static UniValue getwalletinfo(const JSONRPCRequest& request)
|
||||||
{
|
{
|
||||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||||
|
@ -2389,9 +2451,9 @@ static UniValue getwalletinfo(const JSONRPCRequest& request)
|
||||||
"{\n"
|
"{\n"
|
||||||
" \"walletname\": xxxxx, (string) the wallet name\n"
|
" \"walletname\": xxxxx, (string) the wallet name\n"
|
||||||
" \"walletversion\": xxxxx, (numeric) the wallet version\n"
|
" \"walletversion\": xxxxx, (numeric) the wallet version\n"
|
||||||
" \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
|
" \"balance\": xxxxxxx, (numeric) Identical to getbalances().mine.trusted\n"
|
||||||
" \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
|
" \"unconfirmed_balance\": xxx, (numeric) Identical to getbalances().mine.untrusted_pending\n"
|
||||||
" \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + CURRENCY_UNIT + "\n"
|
" \"immature_balance\": xxxxxx, (numeric) Identical to getbalances().mine.immature\n"
|
||||||
" \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
|
" \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
|
||||||
" \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since Unix epoch) of the oldest pre-generated key in the key pool\n"
|
" \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since Unix epoch) of the oldest pre-generated key in the key pool\n"
|
||||||
" \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated (only counts external keys)\n"
|
" \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated (only counts external keys)\n"
|
||||||
|
@ -4075,6 +4137,7 @@ static const CRPCCommand commands[] =
|
||||||
{ "wallet", "getreceivedbylabel", &getreceivedbylabel, {"label","minconf"} },
|
{ "wallet", "getreceivedbylabel", &getreceivedbylabel, {"label","minconf"} },
|
||||||
{ "wallet", "gettransaction", &gettransaction, {"txid","include_watchonly"} },
|
{ "wallet", "gettransaction", &gettransaction, {"txid","include_watchonly"} },
|
||||||
{ "wallet", "getunconfirmedbalance", &getunconfirmedbalance, {} },
|
{ "wallet", "getunconfirmedbalance", &getunconfirmedbalance, {} },
|
||||||
|
{ "wallet", "getbalances", &getbalances, {} },
|
||||||
{ "wallet", "getwalletinfo", &getwalletinfo, {} },
|
{ "wallet", "getwalletinfo", &getwalletinfo, {} },
|
||||||
{ "wallet", "importaddress", &importaddress, {"address","label","rescan","p2sh"} },
|
{ "wallet", "importaddress", &importaddress, {"address","label","rescan","p2sh"} },
|
||||||
{ "wallet", "importmulti", &importmulti, {"requests","options"} },
|
{ "wallet", "importmulti", &importmulti, {"requests","options"} },
|
||||||
|
|
|
@ -59,14 +59,24 @@ class WalletTest(BitcoinTestFramework):
|
||||||
assert_equal(len(self.nodes[0].listunspent()), 0)
|
assert_equal(len(self.nodes[0].listunspent()), 0)
|
||||||
assert_equal(len(self.nodes[1].listunspent()), 0)
|
assert_equal(len(self.nodes[1].listunspent()), 0)
|
||||||
|
|
||||||
self.log.info("Mining blocks ...")
|
self.log.info("Check that only node 0 is watching an address")
|
||||||
|
assert 'watchonly' in self.nodes[0].getbalances()
|
||||||
|
assert 'watchonly' not in self.nodes[1].getbalances()
|
||||||
|
|
||||||
|
self.log.info("Mining blocks ...")
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
self.nodes[1].generate(1)
|
self.nodes[1].generate(1)
|
||||||
self.nodes[1].generatetoaddress(101, ADDRESS_WATCHONLY)
|
self.nodes[1].generatetoaddress(101, ADDRESS_WATCHONLY)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
|
assert_equal(self.nodes[0].getbalances()['mine']['trusted'], 50)
|
||||||
|
assert_equal(self.nodes[0].getwalletinfo()['balance'], 50)
|
||||||
|
assert_equal(self.nodes[1].getbalances()['mine']['trusted'], 50)
|
||||||
|
|
||||||
|
assert_equal(self.nodes[0].getbalances()['watchonly']['immature'], 5000)
|
||||||
|
assert 'watchonly' not in self.nodes[1].getbalances()
|
||||||
|
|
||||||
assert_equal(self.nodes[0].getbalance(), 50)
|
assert_equal(self.nodes[0].getbalance(), 50)
|
||||||
assert_equal(self.nodes[1].getbalance(), 50)
|
assert_equal(self.nodes[1].getbalance(), 50)
|
||||||
|
|
||||||
|
@ -107,8 +117,11 @@ class WalletTest(BitcoinTestFramework):
|
||||||
assert_equal(self.nodes[1].getbalance(minconf=1), Decimal('0'))
|
assert_equal(self.nodes[1].getbalance(minconf=1), Decimal('0'))
|
||||||
# getunconfirmedbalance
|
# getunconfirmedbalance
|
||||||
assert_equal(self.nodes[0].getunconfirmedbalance(), Decimal('60')) # output of node 1's spend
|
assert_equal(self.nodes[0].getunconfirmedbalance(), Decimal('60')) # output of node 1's spend
|
||||||
|
assert_equal(self.nodes[0].getbalances()['mine']['untrusted_pending'], Decimal('60'))
|
||||||
assert_equal(self.nodes[0].getwalletinfo()["unconfirmed_balance"], Decimal('60'))
|
assert_equal(self.nodes[0].getwalletinfo()["unconfirmed_balance"], Decimal('60'))
|
||||||
|
|
||||||
assert_equal(self.nodes[1].getunconfirmedbalance(), Decimal('0')) # Doesn't include output of node 0's send since it was spent
|
assert_equal(self.nodes[1].getunconfirmedbalance(), Decimal('0')) # Doesn't include output of node 0's send since it was spent
|
||||||
|
assert_equal(self.nodes[1].getbalances()['mine']['untrusted_pending'], Decimal('0'))
|
||||||
assert_equal(self.nodes[1].getwalletinfo()["unconfirmed_balance"], Decimal('0'))
|
assert_equal(self.nodes[1].getwalletinfo()["unconfirmed_balance"], Decimal('0'))
|
||||||
|
|
||||||
test_balances(fee_node_1=Decimal('0.01'))
|
test_balances(fee_node_1=Decimal('0.01'))
|
||||||
|
|
Loading…
Reference in a new issue