aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/release-notes-25934.md8
-rw-r--r--src/wallet/rpc/transactions.cpp24
-rwxr-xr-xtest/functional/wallet_listsinceblock.py15
3 files changed, 38 insertions, 9 deletions
diff --git a/doc/release-notes-25934.md b/doc/release-notes-25934.md
new file mode 100644
index 0000000000..b4f1ae0d3c
--- /dev/null
+++ b/doc/release-notes-25934.md
@@ -0,0 +1,8 @@
+Low-level changes
+=================
+
+RPC
+---
+
+- RPC `listsinceblock` now accepts an optional `label` argument
+ to fetch incoming transactions having the specified label. (#25934) \ No newline at end of file
diff --git a/src/wallet/rpc/transactions.cpp b/src/wallet/rpc/transactions.cpp
index 667cd929d1..02a1ac5ea1 100644
--- a/src/wallet/rpc/transactions.cpp
+++ b/src/wallet/rpc/transactions.cpp
@@ -316,7 +316,7 @@ static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
*/
template <class Vec>
static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nMinDepth, bool fLong,
- Vec& ret, const isminefilter& filter_ismine, const std::string* filter_label,
+ Vec& ret, const isminefilter& filter_ismine, const std::optional<std::string>& filter_label,
bool include_change = false)
EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{
@@ -329,7 +329,7 @@ static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nM
bool involvesWatchonly = CachedTxIsFromMe(wallet, wtx, ISMINE_WATCH_ONLY);
// Sent
- if (!filter_label)
+ if (!filter_label.has_value())
{
for (const COutputEntry& s : listSent)
{
@@ -362,7 +362,7 @@ static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nM
if (address_book_entry) {
label = address_book_entry->GetLabel();
}
- if (filter_label && label != *filter_label) {
+ if (filter_label.has_value() && label != filter_label.value()) {
continue;
}
UniValue entry(UniValue::VOBJ);
@@ -485,10 +485,10 @@ RPCHelpMan listtransactions()
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
- const std::string* filter_label = nullptr;
+ std::optional<std::string> filter_label;
if (!request.params[0].isNull() && request.params[0].get_str() != "*") {
- filter_label = &request.params[0].get_str();
- if (filter_label->empty()) {
+ filter_label = request.params[0].get_str();
+ if (filter_label.value().empty()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Label argument must be a valid label name or \"*\".");
}
}
@@ -552,6 +552,7 @@ RPCHelpMan listsinceblock()
{"include_removed", RPCArg::Type::BOOL, RPCArg::Default{true}, "Show transactions that were removed due to a reorg in the \"removed\" array\n"
"(not guaranteed to work on pruned nodes)"},
{"include_change", RPCArg::Type::BOOL, RPCArg::Default{false}, "Also add entries for change outputs.\n"},
+ {"label", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "Return only incoming transactions paying to addresses with the specified label.\n"},
},
RPCResult{
RPCResult::Type::OBJ, "", "",
@@ -634,6 +635,11 @@ RPCHelpMan listsinceblock()
bool include_removed = (request.params[3].isNull() || request.params[3].get_bool());
bool include_change = (!request.params[4].isNull() && request.params[4].get_bool());
+ std::optional<std::string> filter_label;
+ if (!request.params[5].isNull()) {
+ filter_label = request.params[5].get_str();
+ }
+
int depth = height ? wallet.GetLastBlockHeight() + 1 - *height : -1;
UniValue transactions(UniValue::VARR);
@@ -642,7 +648,7 @@ RPCHelpMan listsinceblock()
const CWalletTx& tx = pairWtx.second;
if (depth == -1 || abs(wallet.GetTxDepthInMainChain(tx)) < depth) {
- ListTransactions(wallet, tx, 0, true, transactions, filter, /*filter_label=*/nullptr, /*include_change=*/include_change);
+ ListTransactions(wallet, tx, 0, true, transactions, filter, filter_label, include_change);
}
}
@@ -659,7 +665,7 @@ RPCHelpMan listsinceblock()
if (it != wallet.mapWallet.end()) {
// We want all transactions regardless of confirmation count to appear here,
// even negative confirmation ones, hence the big negative.
- ListTransactions(wallet, it->second, -100000000, true, removed, filter, /*filter_label=*/nullptr, /*include_change=*/include_change);
+ ListTransactions(wallet, it->second, -100000000, true, removed, filter, filter_label, include_change);
}
}
blockId = block.hashPrevBlock;
@@ -777,7 +783,7 @@ RPCHelpMan gettransaction()
WalletTxToJSON(*pwallet, wtx, entry);
UniValue details(UniValue::VARR);
- ListTransactions(*pwallet, wtx, 0, false, details, filter, /*filter_label=*/nullptr);
+ ListTransactions(*pwallet, wtx, 0, false, details, filter, /*filter_label=*/std::nullopt);
entry.pushKV("details", details);
std::string strHex = EncodeHexTx(*wtx.tx, pwallet->chain().rpcSerializationFlags());
diff --git a/test/functional/wallet_listsinceblock.py b/test/functional/wallet_listsinceblock.py
index ecdfb7d0e3..62e9c5ba97 100755
--- a/test/functional/wallet_listsinceblock.py
+++ b/test/functional/wallet_listsinceblock.py
@@ -49,6 +49,7 @@ class ListSinceBlockTest(BitcoinTestFramework):
self.test_desc()
self.test_send_to_self()
self.test_op_return()
+ self.test_label()
def test_no_blockhash(self):
self.log.info("Test no blockhash")
@@ -465,6 +466,20 @@ class ListSinceBlockTest(BitcoinTestFramework):
assert 'address' not in op_ret_tx
+ def test_label(self):
+ self.log.info('Test passing "label" argument fetches incoming transactions having the specified label')
+ new_addr = self.nodes[1].getnewaddress(label="new_addr", address_type="bech32")
+
+ self.nodes[2].sendtoaddress(address=new_addr, amount="0.001")
+ self.generate(self.nodes[2], 1)
+
+ for label in ["new_addr", ""]:
+ new_addr_transactions = self.nodes[1].listsinceblock(label=label)["transactions"]
+ assert_equal(len(new_addr_transactions), 1)
+ assert_equal(new_addr_transactions[0]["label"], label)
+ if label == "new_addr":
+ assert_equal(new_addr_transactions[0]["address"], new_addr)
+
if __name__ == '__main__':
ListSinceBlockTest().main()