Skip to content

Commit bc63d0e

Browse files
pedrobrancolaanwj
authored andcommitted
Add query options to listunspent rpc call
1 parent 5411997 commit bc63d0e

File tree

4 files changed

+81
-18
lines changed

4 files changed

+81
-18
lines changed

src/rpc/client.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
7777
{ "listunspent", 0, "minconf" },
7878
{ "listunspent", 1, "maxconf" },
7979
{ "listunspent", 2, "addresses" },
80+
{ "listunspent", 4, "query_options" },
8081
{ "getblock", 1, "verbosity" },
8182
{ "getblockheader", 1, "verbose" },
8283
{ "getchaintxstats", 0, "nblocks" },

src/wallet/rpcwallet.cpp

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2470,22 +2470,29 @@ UniValue listunspent(const JSONRPCRequest& request)
24702470
return NullUniValue;
24712471
}
24722472

2473-
if (request.fHelp || request.params.size() > 4)
2473+
if (request.fHelp || request.params.size() > 5)
24742474
throw std::runtime_error(
2475-
"listunspent ( minconf maxconf [\"addresses\",...] [include_unsafe] )\n"
2475+
"listunspent ( minconf maxconf [\"addresses\",...] [include_unsafe] [query_options])\n"
24762476
"\nReturns array of unspent transaction outputs\n"
24772477
"with between minconf and maxconf (inclusive) confirmations.\n"
24782478
"Optionally filter to only include txouts paid to specified addresses.\n"
24792479
"\nArguments:\n"
24802480
"1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n"
24812481
"2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n"
2482-
"3. \"addresses\" (string) A json array of bitcoin addresses to filter\n"
2482+
"3. \"addresses\" (string) A json array of bitcoin addresses to filter\n"
24832483
" [\n"
2484-
" \"address\" (string) bitcoin address\n"
2484+
" \"address\" (string) bitcoin address\n"
24852485
" ,...\n"
24862486
" ]\n"
24872487
"4. include_unsafe (bool, optional, default=true) Include outputs that are not safe to spend\n"
24882488
" See description of \"safe\" attribute below.\n"
2489+
"5. query_options (json, optional) JSON with query options\n"
2490+
" {\n"
2491+
" \"minimumAmount\" (numeric or string, default=0) Minimum value of each UTXO in " + CURRENCY_UNIT + "\n"
2492+
" \"maximumAmount\" (numeric or string, default=unlimited) Maximum value of each UTXO in " + CURRENCY_UNIT + "\n"
2493+
" \"maximumCount\" (numeric or string, default=unlimited) Maximum number of UTXOs\n"
2494+
" \"minimumSumAmount\" (numeric or string, default=unlimited) Minimum sum value of all UTXOs in " + CURRENCY_UNIT + "\n"
2495+
" }\n"
24892496
"\nResult\n"
24902497
"[ (array of json object)\n"
24912498
" {\n"
@@ -2510,6 +2517,8 @@ UniValue listunspent(const JSONRPCRequest& request)
25102517
+ HelpExampleCli("listunspent", "")
25112518
+ HelpExampleCli("listunspent", "6 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
25122519
+ HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
2520+
+ HelpExampleCli("listunspent", "6 9999999 '[]' true '{ \"minimumAmount\": 0.005 }'")
2521+
+ HelpExampleRpc("listunspent", "6, 9999999, [] , true, { \"minimumAmount\": 0.005 } ")
25132522
);
25142523

25152524
int nMinDepth = 1;
@@ -2545,15 +2554,34 @@ UniValue listunspent(const JSONRPCRequest& request)
25452554
include_unsafe = request.params[3].get_bool();
25462555
}
25472556

2557+
CAmount nMinimumAmount = 0;
2558+
CAmount nMaximumAmount = MAX_MONEY;
2559+
CAmount nMinimumSumAmount = MAX_MONEY;
2560+
uint64_t nMaximumCount = 0;
2561+
2562+
if (request.params.size() > 4) {
2563+
const UniValue& options = request.params[4].get_obj();
2564+
2565+
if (options.exists("minimumAmount"))
2566+
nMinimumAmount = AmountFromValue(options["minimumAmount"]);
2567+
2568+
if (options.exists("maximumAmount"))
2569+
nMaximumAmount = AmountFromValue(options["maximumAmount"]);
2570+
2571+
if (options.exists("minimumSumAmount"))
2572+
nMinimumSumAmount = AmountFromValue(options["minimumSumAmount"]);
2573+
2574+
if (options.exists("maximumCount"))
2575+
nMaximumCount = options["maximumCount"].get_int64();
2576+
}
2577+
25482578
UniValue results(UniValue::VARR);
25492579
std::vector<COutput> vecOutputs;
25502580
assert(pwallet != NULL);
25512581
LOCK2(cs_main, pwallet->cs_wallet);
2552-
pwallet->AvailableCoins(vecOutputs, !include_unsafe, NULL, true);
2553-
BOOST_FOREACH(const COutput& out, vecOutputs) {
2554-
if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
2555-
continue;
25562582

2583+
pwallet->AvailableCoins(vecOutputs, !include_unsafe, NULL, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount, nMinDepth, nMaxDepth);
2584+
BOOST_FOREACH(const COutput& out, vecOutputs) {
25572585
CTxDestination address;
25582586
const CScript& scriptPubKey = out.tx->tx->vout[out.i].scriptPubKey;
25592587
bool fValidAddress = ExtractDestination(scriptPubKey, address);
@@ -2936,7 +2964,7 @@ static const CRPCCommand commands[] =
29362964
{ "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false, {"minconf","include_empty","include_watchonly"} },
29372965
{ "wallet", "listsinceblock", &listsinceblock, false, {"blockhash","target_confirmations","include_watchonly"} },
29382966
{ "wallet", "listtransactions", &listtransactions, false, {"account","count","skip","include_watchonly"} },
2939-
{ "wallet", "listunspent", &listunspent, false, {"minconf","maxconf","addresses","include_unsafe"} },
2967+
{ "wallet", "listunspent", &listunspent, false, {"minconf","maxconf","addresses","include_unsafe","query_options"} },
29402968
{ "wallet", "lockunspent", &lockunspent, true, {"unlock","transactions"} },
29412969
{ "wallet", "move", &movecmd, false, {"fromaccount","toaccount","amount","minconf","comment"} },
29422970
{ "wallet", "sendfrom", &sendfrom, false, {"fromaccount","toaddress","amount","minconf","comment","comment_to"} },

src/wallet/wallet.cpp

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1977,12 +1977,15 @@ CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth, cons
19771977
return balance;
19781978
}
19791979

1980-
void CWallet::AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe, const CCoinControl *coinControl, bool fIncludeZeroValue) const
1980+
void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const CCoinControl *coinControl, const CAmount &nMinimumAmount, const CAmount &nMaximumAmount, const CAmount &nMinimumSumAmount, const uint64_t &nMaximumCount, const int &nMinDepth, const int &nMaxDepth) const
19811981
{
19821982
vCoins.clear();
19831983

19841984
{
19851985
LOCK2(cs_main, cs_wallet);
1986+
1987+
CAmount nTotal = 0;
1988+
19861989
for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
19871990
{
19881991
const uint256& wtxid = it->first;
@@ -2040,15 +2043,46 @@ void CWallet::AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe, const
20402043
continue;
20412044
}
20422045

2046+
if (nDepth < nMinDepth || nDepth > nMaxDepth)
2047+
continue;
2048+
20432049
for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++) {
2050+
if (pcoin->tx->vout[i].nValue < nMinimumAmount || pcoin->tx->vout[i].nValue > nMaximumAmount)
2051+
continue;
2052+
2053+
if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(COutPoint((*it).first, i)))
2054+
continue;
2055+
2056+
if (IsLockedCoin((*it).first, i))
2057+
continue;
2058+
2059+
if (IsSpent(wtxid, i))
2060+
continue;
2061+
20442062
isminetype mine = IsMine(pcoin->tx->vout[i]);
2045-
if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO &&
2046-
!IsLockedCoin((*it).first, i) && (pcoin->tx->vout[i].nValue > 0 || fIncludeZeroValue) &&
2047-
(!coinControl || !coinControl->HasSelected() || coinControl->fAllowOtherInputs || coinControl->IsSelected(COutPoint((*it).first, i))))
2048-
vCoins.push_back(COutput(pcoin, i, nDepth,
2049-
((mine & ISMINE_SPENDABLE) != ISMINE_NO) ||
2050-
(coinControl && coinControl->fAllowWatchOnly && (mine & ISMINE_WATCH_SOLVABLE) != ISMINE_NO),
2051-
(mine & (ISMINE_SPENDABLE | ISMINE_WATCH_SOLVABLE)) != ISMINE_NO, safeTx));
2063+
2064+
if (mine == ISMINE_NO) {
2065+
continue;
2066+
}
2067+
2068+
bool fSpendableIn = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (coinControl && coinControl->fAllowWatchOnly && (mine & ISMINE_WATCH_SOLVABLE) != ISMINE_NO);
2069+
bool fSolvableIn = (mine & (ISMINE_SPENDABLE | ISMINE_WATCH_SOLVABLE)) != ISMINE_NO;
2070+
2071+
vCoins.push_back(COutput(pcoin, i, nDepth, fSpendableIn, fSolvableIn, safeTx));
2072+
2073+
// Checks the sum amount of all UTXO's.
2074+
if (nMinimumSumAmount != MAX_MONEY) {
2075+
nTotal += pcoin->tx->vout[i].nValue;
2076+
2077+
if (nTotal >= nMinimumSumAmount) {
2078+
return;
2079+
}
2080+
}
2081+
2082+
// Checks the maximum number of UTXO's.
2083+
if (nMaximumCount > 0 && vCoins.size() >= nMaximumCount) {
2084+
return;
2085+
}
20522086
}
20532087
}
20542088
}

src/wallet/wallet.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
818818
/**
819819
* populate vCoins with vector of available COutputs.
820820
*/
821-
void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = NULL, bool fIncludeZeroValue=false) const;
821+
void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = NULL, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t& nMaximumCount = 0, const int& nMinDepth = 0, const int& nMaxDepth = 9999999) const;
822822

823823
/**
824824
* Shuffle and select coins until nTargetValue is reached while avoiding

0 commit comments

Comments
 (0)