// Copyright (c) 2011-2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include #include #include #include #include #include namespace wallet { static CAmount GetReceived(const CWallet& wallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet) { std::set address_set; if (by_label) { // Get the set of addresses assigned to label std::string label = LabelFromValue(params[0]); address_set = wallet.GetLabelAddresses(label); } else { // Get the address CTxDestination dest = DecodeDestination(params[0].get_str()); if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); } CScript script_pub_key = GetScriptForDestination(dest); if (!wallet.IsMine(script_pub_key)) { throw JSONRPCError(RPC_WALLET_ERROR, "Address not found in wallet"); } address_set.insert(dest); } // Minimum confirmations int min_depth = 1; if (!params[1].isNull()) min_depth = params[1].get_int(); const bool include_immature_coinbase{params[2].isNull() ? false : params[2].get_bool()}; // Excluding coinbase outputs is deprecated // It can be enabled by setting deprecatedrpc=exclude_coinbase const bool include_coinbase{!wallet.chain().rpcEnableDeprecated("exclude_coinbase")}; if (include_immature_coinbase && !include_coinbase) { throw JSONRPCError(RPC_INVALID_PARAMETER, "include_immature_coinbase is incompatible with deprecated exclude_coinbase"); } // Tally CAmount amount = 0; for (const std::pair& wtx_pair : wallet.mapWallet) { const CWalletTx& wtx = wtx_pair.second; int depth{wallet.GetTxDepthInMainChain(wtx)}; if (depth < min_depth // Coinbase with less than 1 confirmation is no longer in the main chain || (wtx.IsCoinBase() && (depth < 1 || !include_coinbase)) || (wallet.IsTxImmatureCoinBase(wtx) && !include_immature_coinbase) || !wallet.chain().checkFinalTx(*wtx.tx)) { continue; } for (const CTxOut& txout : wtx.tx->vout) { CTxDestination address; if (ExtractDestination(txout.scriptPubKey, address) && wallet.IsMine(address) && address_set.count(address)) { amount += txout.nValue; } } } return amount; } RPCHelpMan getreceivedbyaddress() { return RPCHelpMan{"getreceivedbyaddress", "\nReturns the total amount received by the given address in transactions with at least minconf confirmations.\n", { {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address for transactions."}, {"minconf", RPCArg::Type::NUM, RPCArg::Default{1}, "Only include transactions confirmed at least this many times."}, {"include_immature_coinbase", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include immature coinbase transactions."}, }, RPCResult{ RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " received at this address." }, RPCExamples{ "\nThe amount from transactions with at least 1 confirmation\n" + HelpExampleCli("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\"") + "\nThe amount including unconfirmed transactions, zero confirmations\n" + HelpExampleCli("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0") + "\nThe amount with at least 6 confirmations\n" + HelpExampleCli("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 6") + "\nThe amount with at least 6 confirmations including immature coinbase outputs\n" + HelpExampleCli("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 6 true") + "\nAs a JSON-RPC call\n" + HelpExampleRpc("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\", 6") }, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { const std::shared_ptr pwallet = GetWalletForJSONRPCRequest(request); if (!pwallet) return NullUniValue; // 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 pwallet->BlockUntilSyncedToCurrentChain(); LOCK(pwallet->cs_wallet); return ValueFromAmount(GetReceived(*pwallet, request.params, /* by_label */ false)); }, }; } RPCHelpMan getreceivedbylabel() { return RPCHelpMan{"getreceivedbylabel", "\nReturns the total amount received by addresses with