Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
251LOCK(pwallet->cs_wallet);253return ListReceived(*pwallet, request.params, false, include_immature_coinbase);254},255};256}258RPCMethod listreceivedbylabel()259{260return RPCMethod{261"listreceivedbylabel",262"List received transactions by label.\n",263{264{"minconf", RPCArg::Type::NUM, RPCArg::Default{1}, "The minimum number of confirmations before payments are included."},265{"include_empty", RPCArg::Type::BOOL, RPCArg::Default{false}, "Whether to include labels that haven't received any payments."},266{"include_watchonly", RPCArg::Type::BOOL, RPCArg::Default{false}, "(DEPRECATED) No longer used"},267{"include_immature_coinbase", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include immature coinbase transactions."},268},269RPCResult{270RPCResult::Type::ARR, "", "",271{272{RPCResult::Type::OBJ, "", "",273{274{RPCResult::Type::STR_AMOUNT, "amount", "The total amount received by addresses with this label"},275{RPCResult::Type::NUM, "confirmations", "The number of confirmations of the most recent transaction included"},276{RPCResult::Type::STR, "label", "The label of the receiving address. The default label is \"\""},277}},278}279},280RPCExamples{281HelpExampleCli("listreceivedbylabel", "")282+ HelpExampleCli("listreceivedbylabel", "6 true")283+ HelpExampleRpc("listreceivedbylabel", "6, true, true, true")284},285[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue286{287const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);288if (!pwallet) return UniValue::VNULL;290// Make sure the results are valid at least up to the most recent block291// the user could have gotten from another RPC command prior to now292pwallet->BlockUntilSyncedToCurrentChain();294const bool include_immature_coinbase{request.params[3].isNull() ? false : request.params[3].get_bool()};296LOCK(pwallet->cs_wallet);298return ListReceived(*pwallet, request.params, true, include_immature_coinbase);299},300};301}303static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)304{305if (IsValidDestination(dest)) {306entry.pushKV("address", EncodeDestination(dest));307}308}310/**311* List transactions based on the given criteria.312*313* @param wallet The wallet.314* @param wtx The wallet transaction.315* @param nMinDepth The minimum confirmation depth.316* @param fLong Whether to include the JSON version of the transaction.317* @param ret The vector into which the result is stored.318* @param filter_label Optional label string to filter incoming transactions.319*/320template <class Vec>321static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nMinDepth, bool fLong,322Vec& ret, const std::optional<std::string>& filter_label,323bool include_change = false)324EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)325{326CAmount nFee;327std::list<COutputEntry> listReceived;328std::list<COutputEntry> listSent;330CachedTxGetAmounts(wallet, wtx, listReceived, listSent, nFee, include_change);332// Sent333if (!filter_label.has_value())334{335for (const COutputEntry& s : listSent)336{337UniValue entry(UniValue::VOBJ);338MaybePushAddress(entry, s.destination);339entry.pushKV("category", "send");340entry.pushKV("amount", ValueFromAmount(-s.amount));341const auto* address_book_entry = wallet.FindAddressBookEntry(s.destination);342if (address_book_entry) {343entry.pushKV("label", address_book_entry->GetLabel());344}345entry.pushKV("vout", s.vout);346entry.pushKV("fee", ValueFromAmount(-nFee));347if (fLong)348WalletTxToJSON(wallet, wtx, entry);349entry.pushKV("abandoned", wtx.isAbandoned());350ret.push_back(std::move(entry));351}352}354// Received355if (listReceived.size() > 0 && wallet.GetTxDepthInMainChain(wtx) >= nMinDepth) {356for (const COutputEntry& r : listReceived)357{358std::string label;359const auto* address_book_entry = wallet.FindAddressBookEntry(r.destination);360if (address_book_entry) {361label = address_book_entry->GetLabel();362}363if (filter_label.has_value() && label != filter_label.value()) {364continue;365}366UniValue entry(UniValue::VOBJ);367MaybePushAddress(entry, r.destination);368PushParentDescriptors(wallet, wtx.GetTx()->vout.at(r.vout).scriptPubKey, entry);369if (wtx.IsCoinBase())370{371if (wallet.GetTxDepthInMainChain(wtx) < 1)372entry.pushKV("category", "orphan");373else if (wallet.IsTxImmatureCoinBase(wtx))374entry.pushKV("category", "immature");375else376entry.pushKV("category", "generate");377}378else379{380entry.pushKV("category", "receive");381}382entry.pushKV("amount", ValueFromAmount(r.amount));383if (address_book_entry) {384entry.pushKV("label", label);385}386entry.pushKV("vout", r.vout);387entry.pushKV("abandoned", wtx.isAbandoned());388if (fLong)389WalletTxToJSON(wallet, wtx, entry);390ret.push_back(std::move(entry));391}392}393}396static std::vector<RPCResult> TransactionDescriptionString()397{398return{{RPCResult::Type::NUM, "confirmations", "The number of confirmations for the transaction. Negative confirmations means the\n"399"transaction conflicted that many blocks ago."},400{RPCResult::Type::BOOL, "generated", /*optional=*/true, "Only present if the transaction's only input is a coinbase one."},401{RPCResult::Type::BOOL, "trusted", /*optional=*/true, "Whether we consider the transaction to be trusted and safe to spend from.\n"402"Only present when the transaction has 0 confirmations (or negative confirmations, if conflicted)."},403{RPCResult::Type::STR_HEX, "blockhash", /*optional=*/true, "The block hash containing the transaction."},404{RPCResult::Type::NUM, "blockheight", /*optional=*/true, "The block height containing the transaction."},405{RPCResult::Type::NUM, "blockindex", /*optional=*/true, "The index of the transaction in the block that includes it."},406{RPCResult::Type::NUM_TIME, "blocktime", /*optional=*/true, "The block time expressed in " + UNIX_EPOCH_TIME + "."},407{RPCResult::Type::STR_HEX, "txid", "The transaction id."},408{RPCResult::Type::STR_HEX, "wtxid", "The hash of serialized transaction, including witness data."},409{RPCResult::Type::ARR, "alternate_wtxids", "The wtxids of transactions with different witness data but the same txid.",410{411{RPCResult::Type::STR_HEX, "wtxid", "The witness transaction id."},412}},413{RPCResult::Type::ARR, "walletconflicts", "Confirmed transactions that have been detected by the wallet to conflict with this transaction.",414{415{RPCResult::Type::STR_HEX, "txid", "The transaction id."},416}},417{RPCResult::Type::STR_HEX, "replaced_by_txid", /*optional=*/true, "Only if 'category' is 'send'. The txid if this tx was replaced."},418{RPCResult::Type::STR_HEX, "replaces_txid", /*optional=*/true, "Only if 'category' is 'send'. The txid if this tx replaces another."},419{RPCResult::Type::ARR, "mempoolconflicts", "Transactions in the mempool that directly conflict with either this transaction or an ancestor transaction",420{421{RPCResult::Type::STR_HEX, "txid", "The transaction id."},422}},423{RPCResult::Type::STR, "to", /*optional=*/true, "If a comment to is associated with the transaction."},424{RPCResult::Type::NUM_TIME, "time", "The transaction time expressed in " + UNIX_EPOCH_TIME + "."},425{RPCResult::Type::NUM_TIME, "timereceived", "The time received expressed in " + UNIX_EPOCH_TIME + "."},426{RPCResult::Type::STR, "comment", /*optional=*/true, "If a comment is associated with the transaction, only present if not empty."},427{RPCResult::Type::STR, "bip125-replaceable", /*optional=*/true, "(\"yes|no|unknown\") (DEPRECATED) Whether this transaction signals BIP125 replaceability or has an unconfirmed ancestor signaling BIP125 replaceability.\n"428"May be unknown for unconfirmed transactions not in the mempool because their unconfirmed ancestors are unknown."},429{RPCResult::Type::ARR, "parent_descs", /*optional=*/true, "Only if 'category' is 'receive'. List of parent descriptors for the output script of this coin.", {430{RPCResult::Type::STR, "desc", "The descriptor string."},431}},432};433}435RPCMethod listtransactions()436{437return RPCMethod{438"listtransactions",439"If a label name is provided, this will return only incoming transactions paying to addresses with the specified label.\n"440"Returns up to 'count' most recent transactions ordered from oldest to newest while skipping the first number of \n"441"transactions specified in the 'skip' argument. A transaction can have multiple entries in this RPC response. \n"442"For instance, a wallet transaction that pays three addresses — one wallet-owned and two external — will produce \n"443"four entries. The payment to the wallet-owned address appears both as a send entry and as a receive entry. \n"444"As a result, the RPC response will contain one entry in the receive category and three entries in the send category.\n",445{446{"label", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "If set, should be a valid label name to return only incoming transactions\n"447"with the specified label, or \"*\" to disable filtering and return all transactions."},448{"count", RPCArg::Type::NUM, RPCArg::Default{10}, "The number of transactions to return"},449{"skip", RPCArg::Type::NUM, RPCArg::Default{0}, "The number of transactions to skip"},450{"include_watchonly", RPCArg::Type::BOOL, RPCArg::Default{false}, "(DEPRECATED) No longer used"},451},452RPCResult{453RPCResult::Type::ARR, "", "",454{455{RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>(456{457{RPCResult::Type::STR, "address", /*optional=*/true, "The bitcoin address of the transaction (not returned if the output does not have an address, e.g. OP_RETURN null data)."},458{RPCResult::Type::STR, "category", "The transaction category.\n"459"\"send\" Transactions sent.\n"460"\"receive\" Non-coinbase transactions received.\n"461"\"generate\" Coinbase transactions received with more than 100 confirmations.\n"462"\"immature\" Coinbase transactions received with 100 or fewer confirmations.\n"463"\"orphan\" Orphaned coinbase transactions received."},464{RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n"465"for all other categories"},466{RPCResult::Type::STR, "label", /*optional=*/true, "A comment for the address/transaction, if any"},467{RPCResult::Type::NUM, "vout", "the vout value"},468{RPCResult::Type::STR_AMOUNT, "fee", /*optional=*/true, "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n"469"'send' category of transactions."},470},471TransactionDescriptionString()),472{473{RPCResult::Type::BOOL, "abandoned", "'true' if the transaction has been abandoned (inputs are respendable)."},474})},475}476},477RPCExamples{478"\nList the most recent 10 transactions in the systems\n"479+ HelpExampleCli("listtransactions", "") +480"\nList transactions 100 to 120\n"481+ HelpExampleCli("listtransactions", "\"*\" 20 100") +482"\nAs a JSON-RPC call\n"483+ HelpExampleRpc("listtransactions", "\"*\", 20, 100")484},485[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue486{487const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);488if (!pwallet) return UniValue::VNULL;490// Make sure the results are valid at least up to the most recent block491// the user could have gotten from another RPC command prior to now492pwallet->BlockUntilSyncedToCurrentChain();494std::optional<std::string> filter_label;495if (!request.params[0].isNull() && request.params[0].get_str() != "*") {496filter_label.emplace(LabelFromValue(request.params[0]));497if (filter_label.value().empty()) {498throw JSONRPCError(RPC_INVALID_PARAMETER, "Label argument must be a valid label name or \"*\".");499}500}