Merge #12062: Increment MIT Licence copyright header year on files modified in 2017
[bitcoinplatinum.git] / src / wallet / rpcwallet.cpp
blob873fbd1babcf4d3aeb06eb5cde79b97cc912fe93
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2017 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 #include <amount.h>
7 #include <base58.h>
8 #include <chain.h>
9 #include <consensus/validation.h>
10 #include <core_io.h>
11 #include <httpserver.h>
12 #include <validation.h>
13 #include <net.h>
14 #include <policy/feerate.h>
15 #include <policy/fees.h>
16 #include <policy/policy.h>
17 #include <policy/rbf.h>
18 #include <rpc/mining.h>
19 #include <rpc/safemode.h>
20 #include <rpc/server.h>
21 #include <script/sign.h>
22 #include <timedata.h>
23 #include <util.h>
24 #include <utilmoneystr.h>
25 #include <wallet/coincontrol.h>
26 #include <wallet/feebumper.h>
27 #include <wallet/wallet.h>
28 #include <wallet/walletdb.h>
29 #include <wallet/walletutil.h>
31 #include <init.h> // For StartShutdown
33 #include <stdint.h>
35 #include <univalue.h>
37 static const std::string WALLET_ENDPOINT_BASE = "/wallet/";
39 CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
41 if (request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) {
42 // wallet endpoint was used
43 std::string requestedWallet = urlDecode(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
44 for (CWalletRef pwallet : ::vpwallets) {
45 if (pwallet->GetName() == requestedWallet) {
46 return pwallet;
49 throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
51 return ::vpwallets.size() == 1 || (request.fHelp && ::vpwallets.size() > 0) ? ::vpwallets[0] : nullptr;
54 std::string HelpRequiringPassphrase(CWallet * const pwallet)
56 return pwallet && pwallet->IsCrypted()
57 ? "\nRequires wallet passphrase to be set with walletpassphrase call."
58 : "";
61 bool EnsureWalletIsAvailable(CWallet * const pwallet, bool avoidException)
63 if (pwallet) return true;
64 if (avoidException) return false;
65 if (::vpwallets.empty()) {
66 // Note: It isn't currently possible to trigger this error because
67 // wallet RPC methods aren't registered unless a wallet is loaded. But
68 // this error is being kept as a precaution, because it's possible in
69 // the future that wallet RPC methods might get or remain registered
70 // when no wallets are loaded.
71 throw JSONRPCError(
72 RPC_METHOD_NOT_FOUND, "Method not found (wallet method is disabled because no wallet is loaded)");
74 throw JSONRPCError(RPC_WALLET_NOT_SPECIFIED,
75 "Wallet file not specified (must request wallet RPC through /wallet/<filename> uri-path).");
78 void EnsureWalletIsUnlocked(CWallet * const pwallet)
80 if (pwallet->IsLocked()) {
81 throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
85 void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
87 int confirms = wtx.GetDepthInMainChain();
88 entry.push_back(Pair("confirmations", confirms));
89 if (wtx.IsCoinBase())
90 entry.push_back(Pair("generated", true));
91 if (confirms > 0)
93 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
94 entry.push_back(Pair("blockindex", wtx.nIndex));
95 entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
96 } else {
97 entry.push_back(Pair("trusted", wtx.IsTrusted()));
99 uint256 hash = wtx.GetHash();
100 entry.push_back(Pair("txid", hash.GetHex()));
101 UniValue conflicts(UniValue::VARR);
102 for (const uint256& conflict : wtx.GetConflicts())
103 conflicts.push_back(conflict.GetHex());
104 entry.push_back(Pair("walletconflicts", conflicts));
105 entry.push_back(Pair("time", wtx.GetTxTime()));
106 entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived));
108 // Add opt-in RBF status
109 std::string rbfStatus = "no";
110 if (confirms <= 0) {
111 LOCK(mempool.cs);
112 RBFTransactionState rbfState = IsRBFOptIn(*wtx.tx, mempool);
113 if (rbfState == RBF_TRANSACTIONSTATE_UNKNOWN)
114 rbfStatus = "unknown";
115 else if (rbfState == RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125)
116 rbfStatus = "yes";
118 entry.push_back(Pair("bip125-replaceable", rbfStatus));
120 for (const std::pair<std::string, std::string>& item : wtx.mapValue)
121 entry.push_back(Pair(item.first, item.second));
124 std::string AccountFromValue(const UniValue& value)
126 std::string strAccount = value.get_str();
127 if (strAccount == "*")
128 throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Invalid account name");
129 return strAccount;
132 UniValue getnewaddress(const JSONRPCRequest& request)
134 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
135 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
136 return NullUniValue;
139 if (request.fHelp || request.params.size() > 1)
140 throw std::runtime_error(
141 "getnewaddress ( \"account\" )\n"
142 "\nReturns a new Bitcoin address for receiving payments.\n"
143 "If 'account' is specified (DEPRECATED), it is added to the address book \n"
144 "so payments received with the address will be credited to 'account'.\n"
145 "\nArguments:\n"
146 "1. \"account\" (string, optional) DEPRECATED. The account name for the address to be linked to. If not provided, the default account \"\" is used. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created if there is no account by the given name.\n"
147 "\nResult:\n"
148 "\"address\" (string) The new bitcoin address\n"
149 "\nExamples:\n"
150 + HelpExampleCli("getnewaddress", "")
151 + HelpExampleRpc("getnewaddress", "")
154 LOCK2(cs_main, pwallet->cs_wallet);
156 // Parse the account first so we don't generate a key if there's an error
157 std::string strAccount;
158 if (!request.params[0].isNull())
159 strAccount = AccountFromValue(request.params[0]);
161 if (!pwallet->IsLocked()) {
162 pwallet->TopUpKeyPool();
165 // Generate a new key that is added to wallet
166 CPubKey newKey;
167 if (!pwallet->GetKeyFromPool(newKey)) {
168 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
170 CKeyID keyID = newKey.GetID();
172 pwallet->SetAddressBook(keyID, strAccount, "receive");
174 return EncodeDestination(keyID);
178 CTxDestination GetAccountAddress(CWallet* const pwallet, std::string strAccount, bool bForceNew=false)
180 CPubKey pubKey;
181 if (!pwallet->GetAccountPubkey(pubKey, strAccount, bForceNew)) {
182 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
185 return pubKey.GetID();
188 UniValue getaccountaddress(const JSONRPCRequest& request)
190 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
191 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
192 return NullUniValue;
195 if (request.fHelp || request.params.size() != 1)
196 throw std::runtime_error(
197 "getaccountaddress \"account\"\n"
198 "\nDEPRECATED. Returns the current Bitcoin address for receiving payments to this account.\n"
199 "\nArguments:\n"
200 "1. \"account\" (string, required) The account name for the address. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created and a new address created if there is no account by the given name.\n"
201 "\nResult:\n"
202 "\"address\" (string) The account bitcoin address\n"
203 "\nExamples:\n"
204 + HelpExampleCli("getaccountaddress", "")
205 + HelpExampleCli("getaccountaddress", "\"\"")
206 + HelpExampleCli("getaccountaddress", "\"myaccount\"")
207 + HelpExampleRpc("getaccountaddress", "\"myaccount\"")
210 LOCK2(cs_main, pwallet->cs_wallet);
212 // Parse the account first so we don't generate a key if there's an error
213 std::string strAccount = AccountFromValue(request.params[0]);
215 UniValue ret(UniValue::VSTR);
217 ret = EncodeDestination(GetAccountAddress(pwallet, strAccount));
218 return ret;
222 UniValue getrawchangeaddress(const JSONRPCRequest& request)
224 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
225 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
226 return NullUniValue;
229 if (request.fHelp || request.params.size() > 0)
230 throw std::runtime_error(
231 "getrawchangeaddress\n"
232 "\nReturns a new Bitcoin address, for receiving change.\n"
233 "This is for use with raw transactions, NOT normal use.\n"
234 "\nResult:\n"
235 "\"address\" (string) The address\n"
236 "\nExamples:\n"
237 + HelpExampleCli("getrawchangeaddress", "")
238 + HelpExampleRpc("getrawchangeaddress", "")
241 LOCK2(cs_main, pwallet->cs_wallet);
243 if (!pwallet->IsLocked()) {
244 pwallet->TopUpKeyPool();
247 CReserveKey reservekey(pwallet);
248 CPubKey vchPubKey;
249 if (!reservekey.GetReservedKey(vchPubKey, true))
250 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
252 reservekey.KeepKey();
254 CKeyID keyID = vchPubKey.GetID();
256 return EncodeDestination(keyID);
260 UniValue setaccount(const JSONRPCRequest& request)
262 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
263 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
264 return NullUniValue;
267 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
268 throw std::runtime_error(
269 "setaccount \"address\" \"account\"\n"
270 "\nDEPRECATED. Sets the account associated with the given address.\n"
271 "\nArguments:\n"
272 "1. \"address\" (string, required) The bitcoin address to be associated with an account.\n"
273 "2. \"account\" (string, required) The account to assign the address to.\n"
274 "\nExamples:\n"
275 + HelpExampleCli("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"tabby\"")
276 + HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"tabby\"")
279 LOCK2(cs_main, pwallet->cs_wallet);
281 CTxDestination dest = DecodeDestination(request.params[0].get_str());
282 if (!IsValidDestination(dest)) {
283 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
286 std::string strAccount;
287 if (!request.params[1].isNull())
288 strAccount = AccountFromValue(request.params[1]);
290 // Only add the account if the address is yours.
291 if (IsMine(*pwallet, dest)) {
292 // Detect when changing the account of an address that is the 'unused current key' of another account:
293 if (pwallet->mapAddressBook.count(dest)) {
294 std::string strOldAccount = pwallet->mapAddressBook[dest].name;
295 if (dest == GetAccountAddress(pwallet, strOldAccount)) {
296 GetAccountAddress(pwallet, strOldAccount, true);
299 pwallet->SetAddressBook(dest, strAccount, "receive");
301 else
302 throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
304 return NullUniValue;
308 UniValue getaccount(const JSONRPCRequest& request)
310 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
311 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
312 return NullUniValue;
315 if (request.fHelp || request.params.size() != 1)
316 throw std::runtime_error(
317 "getaccount \"address\"\n"
318 "\nDEPRECATED. Returns the account associated with the given address.\n"
319 "\nArguments:\n"
320 "1. \"address\" (string, required) The bitcoin address for account lookup.\n"
321 "\nResult:\n"
322 "\"accountname\" (string) the account address\n"
323 "\nExamples:\n"
324 + HelpExampleCli("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"")
325 + HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"")
328 LOCK2(cs_main, pwallet->cs_wallet);
330 CTxDestination dest = DecodeDestination(request.params[0].get_str());
331 if (!IsValidDestination(dest)) {
332 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
335 std::string strAccount;
336 std::map<CTxDestination, CAddressBookData>::iterator mi = pwallet->mapAddressBook.find(dest);
337 if (mi != pwallet->mapAddressBook.end() && !(*mi).second.name.empty()) {
338 strAccount = (*mi).second.name;
340 return strAccount;
344 UniValue getaddressesbyaccount(const JSONRPCRequest& request)
346 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
347 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
348 return NullUniValue;
351 if (request.fHelp || request.params.size() != 1)
352 throw std::runtime_error(
353 "getaddressesbyaccount \"account\"\n"
354 "\nDEPRECATED. Returns the list of addresses for the given account.\n"
355 "\nArguments:\n"
356 "1. \"account\" (string, required) The account name.\n"
357 "\nResult:\n"
358 "[ (json array of string)\n"
359 " \"address\" (string) a bitcoin address associated with the given account\n"
360 " ,...\n"
361 "]\n"
362 "\nExamples:\n"
363 + HelpExampleCli("getaddressesbyaccount", "\"tabby\"")
364 + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
367 LOCK2(cs_main, pwallet->cs_wallet);
369 std::string strAccount = AccountFromValue(request.params[0]);
371 // Find all addresses that have the given account
372 UniValue ret(UniValue::VARR);
373 for (const std::pair<CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
374 const CTxDestination& dest = item.first;
375 const std::string& strName = item.second.name;
376 if (strName == strAccount) {
377 ret.push_back(EncodeDestination(dest));
380 return ret;
383 static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew, const CCoinControl& coin_control)
385 CAmount curBalance = pwallet->GetBalance();
387 // Check amount
388 if (nValue <= 0)
389 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid amount");
391 if (nValue > curBalance)
392 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
394 if (pwallet->GetBroadcastTransactions() && !g_connman) {
395 throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
398 // Parse Bitcoin address
399 CScript scriptPubKey = GetScriptForDestination(address);
401 // Create and send the transaction
402 CReserveKey reservekey(pwallet);
403 CAmount nFeeRequired;
404 std::string strError;
405 std::vector<CRecipient> vecSend;
406 int nChangePosRet = -1;
407 CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
408 vecSend.push_back(recipient);
409 if (!pwallet->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError, coin_control)) {
410 if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
411 strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired));
412 throw JSONRPCError(RPC_WALLET_ERROR, strError);
414 CValidationState state;
415 if (!pwallet->CommitTransaction(wtxNew, reservekey, g_connman.get(), state)) {
416 strError = strprintf("Error: The transaction was rejected! Reason given: %s", state.GetRejectReason());
417 throw JSONRPCError(RPC_WALLET_ERROR, strError);
421 UniValue sendtoaddress(const JSONRPCRequest& request)
423 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
424 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
425 return NullUniValue;
428 if (request.fHelp || request.params.size() < 2 || request.params.size() > 8)
429 throw std::runtime_error(
430 "sendtoaddress \"address\" amount ( \"comment\" \"comment_to\" subtractfeefromamount replaceable conf_target \"estimate_mode\")\n"
431 "\nSend an amount to a given address.\n"
432 + HelpRequiringPassphrase(pwallet) +
433 "\nArguments:\n"
434 "1. \"address\" (string, required) The bitcoin address to send to.\n"
435 "2. \"amount\" (numeric or string, required) The amount in " + CURRENCY_UNIT + " to send. eg 0.1\n"
436 "3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
437 " This is not part of the transaction, just kept in your wallet.\n"
438 "4. \"comment_to\" (string, optional) A comment to store the name of the person or organization \n"
439 " to which you're sending the transaction. This is not part of the \n"
440 " transaction, just kept in your wallet.\n"
441 "5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
442 " The recipient will receive less bitcoins than you enter in the amount field.\n"
443 "6. replaceable (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees via BIP 125\n"
444 "7. conf_target (numeric, optional) Confirmation target (in blocks)\n"
445 "8. \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n"
446 " \"UNSET\"\n"
447 " \"ECONOMICAL\"\n"
448 " \"CONSERVATIVE\"\n"
449 "\nResult:\n"
450 "\"txid\" (string) The transaction id.\n"
451 "\nExamples:\n"
452 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
453 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
454 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true")
455 + HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
458 ObserveSafeMode();
460 // Make sure the results are valid at least up to the most recent block
461 // the user could have gotten from another RPC command prior to now
462 pwallet->BlockUntilSyncedToCurrentChain();
464 LOCK2(cs_main, pwallet->cs_wallet);
466 CTxDestination dest = DecodeDestination(request.params[0].get_str());
467 if (!IsValidDestination(dest)) {
468 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
471 // Amount
472 CAmount nAmount = AmountFromValue(request.params[1]);
473 if (nAmount <= 0)
474 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
476 // Wallet comments
477 CWalletTx wtx;
478 if (!request.params[2].isNull() && !request.params[2].get_str().empty())
479 wtx.mapValue["comment"] = request.params[2].get_str();
480 if (!request.params[3].isNull() && !request.params[3].get_str().empty())
481 wtx.mapValue["to"] = request.params[3].get_str();
483 bool fSubtractFeeFromAmount = false;
484 if (!request.params[4].isNull()) {
485 fSubtractFeeFromAmount = request.params[4].get_bool();
488 CCoinControl coin_control;
489 if (!request.params[5].isNull()) {
490 coin_control.signalRbf = request.params[5].get_bool();
493 if (!request.params[6].isNull()) {
494 coin_control.m_confirm_target = ParseConfirmTarget(request.params[6]);
497 if (!request.params[7].isNull()) {
498 if (!FeeModeFromString(request.params[7].get_str(), coin_control.m_fee_mode)) {
499 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter");
504 EnsureWalletIsUnlocked(pwallet);
506 SendMoney(pwallet, dest, nAmount, fSubtractFeeFromAmount, wtx, coin_control);
508 return wtx.GetHash().GetHex();
511 UniValue listaddressgroupings(const JSONRPCRequest& request)
513 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
514 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
515 return NullUniValue;
518 if (request.fHelp || request.params.size() != 0)
519 throw std::runtime_error(
520 "listaddressgroupings\n"
521 "\nLists groups of addresses which have had their common ownership\n"
522 "made public by common use as inputs or as the resulting change\n"
523 "in past transactions\n"
524 "\nResult:\n"
525 "[\n"
526 " [\n"
527 " [\n"
528 " \"address\", (string) The bitcoin address\n"
529 " amount, (numeric) The amount in " + CURRENCY_UNIT + "\n"
530 " \"account\" (string, optional) DEPRECATED. The account\n"
531 " ]\n"
532 " ,...\n"
533 " ]\n"
534 " ,...\n"
535 "]\n"
536 "\nExamples:\n"
537 + HelpExampleCli("listaddressgroupings", "")
538 + HelpExampleRpc("listaddressgroupings", "")
541 ObserveSafeMode();
543 // Make sure the results are valid at least up to the most recent block
544 // the user could have gotten from another RPC command prior to now
545 pwallet->BlockUntilSyncedToCurrentChain();
547 LOCK2(cs_main, pwallet->cs_wallet);
549 UniValue jsonGroupings(UniValue::VARR);
550 std::map<CTxDestination, CAmount> balances = pwallet->GetAddressBalances();
551 for (const std::set<CTxDestination>& grouping : pwallet->GetAddressGroupings()) {
552 UniValue jsonGrouping(UniValue::VARR);
553 for (const CTxDestination& address : grouping)
555 UniValue addressInfo(UniValue::VARR);
556 addressInfo.push_back(EncodeDestination(address));
557 addressInfo.push_back(ValueFromAmount(balances[address]));
559 if (pwallet->mapAddressBook.find(address) != pwallet->mapAddressBook.end()) {
560 addressInfo.push_back(pwallet->mapAddressBook.find(address)->second.name);
563 jsonGrouping.push_back(addressInfo);
565 jsonGroupings.push_back(jsonGrouping);
567 return jsonGroupings;
570 UniValue signmessage(const JSONRPCRequest& request)
572 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
573 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
574 return NullUniValue;
577 if (request.fHelp || request.params.size() != 2)
578 throw std::runtime_error(
579 "signmessage \"address\" \"message\"\n"
580 "\nSign a message with the private key of an address"
581 + HelpRequiringPassphrase(pwallet) + "\n"
582 "\nArguments:\n"
583 "1. \"address\" (string, required) The bitcoin address to use for the private key.\n"
584 "2. \"message\" (string, required) The message to create a signature of.\n"
585 "\nResult:\n"
586 "\"signature\" (string) The signature of the message encoded in base 64\n"
587 "\nExamples:\n"
588 "\nUnlock the wallet for 30 seconds\n"
589 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
590 "\nCreate the signature\n"
591 + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
592 "\nVerify the signature\n"
593 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
594 "\nAs json rpc\n"
595 + HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"my message\"")
598 LOCK2(cs_main, pwallet->cs_wallet);
600 EnsureWalletIsUnlocked(pwallet);
602 std::string strAddress = request.params[0].get_str();
603 std::string strMessage = request.params[1].get_str();
605 CTxDestination dest = DecodeDestination(strAddress);
606 if (!IsValidDestination(dest)) {
607 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
610 const CKeyID *keyID = boost::get<CKeyID>(&dest);
611 if (!keyID) {
612 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
615 CKey key;
616 if (!pwallet->GetKey(*keyID, key)) {
617 throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
620 CHashWriter ss(SER_GETHASH, 0);
621 ss << strMessageMagic;
622 ss << strMessage;
624 std::vector<unsigned char> vchSig;
625 if (!key.SignCompact(ss.GetHash(), vchSig))
626 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
628 return EncodeBase64(vchSig.data(), vchSig.size());
631 UniValue getreceivedbyaddress(const JSONRPCRequest& request)
633 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
634 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
635 return NullUniValue;
638 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
639 throw std::runtime_error(
640 "getreceivedbyaddress \"address\" ( minconf )\n"
641 "\nReturns the total amount received by the given address in transactions with at least minconf confirmations.\n"
642 "\nArguments:\n"
643 "1. \"address\" (string, required) The bitcoin address for transactions.\n"
644 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
645 "\nResult:\n"
646 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received at this address.\n"
647 "\nExamples:\n"
648 "\nThe amount from transactions with at least 1 confirmation\n"
649 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\"") +
650 "\nThe amount including unconfirmed transactions, zero confirmations\n"
651 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" 0") +
652 "\nThe amount with at least 6 confirmations\n"
653 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" 6") +
654 "\nAs a json rpc call\n"
655 + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", 6")
658 ObserveSafeMode();
660 // Make sure the results are valid at least up to the most recent block
661 // the user could have gotten from another RPC command prior to now
662 pwallet->BlockUntilSyncedToCurrentChain();
664 LOCK2(cs_main, pwallet->cs_wallet);
666 // Bitcoin address
667 CTxDestination dest = DecodeDestination(request.params[0].get_str());
668 if (!IsValidDestination(dest)) {
669 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
671 CScript scriptPubKey = GetScriptForDestination(dest);
672 if (!IsMine(*pwallet, scriptPubKey)) {
673 throw JSONRPCError(RPC_WALLET_ERROR, "Address not found in wallet");
676 // Minimum confirmations
677 int nMinDepth = 1;
678 if (!request.params[1].isNull())
679 nMinDepth = request.params[1].get_int();
681 // Tally
682 CAmount nAmount = 0;
683 for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
684 const CWalletTx& wtx = pairWtx.second;
685 if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
686 continue;
688 for (const CTxOut& txout : wtx.tx->vout)
689 if (txout.scriptPubKey == scriptPubKey)
690 if (wtx.GetDepthInMainChain() >= nMinDepth)
691 nAmount += txout.nValue;
694 return ValueFromAmount(nAmount);
698 UniValue getreceivedbyaccount(const JSONRPCRequest& request)
700 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
701 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
702 return NullUniValue;
705 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
706 throw std::runtime_error(
707 "getreceivedbyaccount \"account\" ( minconf )\n"
708 "\nDEPRECATED. Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
709 "\nArguments:\n"
710 "1. \"account\" (string, required) The selected account, may be the default account using \"\".\n"
711 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
712 "\nResult:\n"
713 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
714 "\nExamples:\n"
715 "\nAmount received by the default account with at least 1 confirmation\n"
716 + HelpExampleCli("getreceivedbyaccount", "\"\"") +
717 "\nAmount received at the tabby account including unconfirmed amounts with zero confirmations\n"
718 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 0") +
719 "\nThe amount with at least 6 confirmations\n"
720 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 6") +
721 "\nAs a json rpc call\n"
722 + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
725 ObserveSafeMode();
727 // Make sure the results are valid at least up to the most recent block
728 // the user could have gotten from another RPC command prior to now
729 pwallet->BlockUntilSyncedToCurrentChain();
731 LOCK2(cs_main, pwallet->cs_wallet);
733 // Minimum confirmations
734 int nMinDepth = 1;
735 if (!request.params[1].isNull())
736 nMinDepth = request.params[1].get_int();
738 // Get the set of pub keys assigned to account
739 std::string strAccount = AccountFromValue(request.params[0]);
740 std::set<CTxDestination> setAddress = pwallet->GetAccountAddresses(strAccount);
742 // Tally
743 CAmount nAmount = 0;
744 for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
745 const CWalletTx& wtx = pairWtx.second;
746 if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
747 continue;
749 for (const CTxOut& txout : wtx.tx->vout)
751 CTxDestination address;
752 if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwallet, address) && setAddress.count(address)) {
753 if (wtx.GetDepthInMainChain() >= nMinDepth)
754 nAmount += txout.nValue;
759 return ValueFromAmount(nAmount);
763 UniValue getbalance(const JSONRPCRequest& request)
765 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
766 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
767 return NullUniValue;
770 if (request.fHelp || request.params.size() > 3)
771 throw std::runtime_error(
772 "getbalance ( \"account\" minconf include_watchonly )\n"
773 "\nIf account is not specified, returns the server's total available balance.\n"
774 "The available balance is what the wallet considers currently spendable, and is\n"
775 "thus affected by options which limit spendability such as -spendzeroconfchange.\n"
776 "If account is specified (DEPRECATED), returns the balance in the account.\n"
777 "Note that the account \"\" is not the same as leaving the parameter out.\n"
778 "The server total may be different to the balance in the default \"\" account.\n"
779 "\nArguments:\n"
780 "1. \"account\" (string, optional) DEPRECATED. The account string may be given as a\n"
781 " specific account name to find the balance associated with wallet keys in\n"
782 " a named account, or as the empty string (\"\") to find the balance\n"
783 " associated with wallet keys not in any named account, or as \"*\" to find\n"
784 " the balance associated with all wallet keys regardless of account.\n"
785 " When this option is specified, it calculates the balance in a different\n"
786 " way than when it is not specified, and which can count spends twice when\n"
787 " there are conflicting pending transactions (such as those created by\n"
788 " the bumpfee command), temporarily resulting in low or even negative\n"
789 " balances. In general, account balance calculation is not considered\n"
790 " reliable and has resulted in confusing outcomes, so it is recommended to\n"
791 " avoid passing this argument.\n"
792 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
793 "3. include_watchonly (bool, optional, default=false) Also include balance in watch-only addresses (see 'importaddress')\n"
794 "\nResult:\n"
795 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
796 "\nExamples:\n"
797 "\nThe total amount in the wallet with 1 or more confirmations\n"
798 + HelpExampleCli("getbalance", "") +
799 "\nThe total amount in the wallet at least 6 blocks confirmed\n"
800 + HelpExampleCli("getbalance", "\"*\" 6") +
801 "\nAs a json rpc call\n"
802 + HelpExampleRpc("getbalance", "\"*\", 6")
805 ObserveSafeMode();
807 // Make sure the results are valid at least up to the most recent block
808 // the user could have gotten from another RPC command prior to now
809 pwallet->BlockUntilSyncedToCurrentChain();
811 LOCK2(cs_main, pwallet->cs_wallet);
813 const UniValue& account_value = request.params[0];
814 const UniValue& minconf = request.params[1];
815 const UniValue& include_watchonly = request.params[2];
817 if (account_value.isNull()) {
818 if (!minconf.isNull()) {
819 throw JSONRPCError(RPC_INVALID_PARAMETER,
820 "getbalance minconf option is only currently supported if an account is specified");
822 if (!include_watchonly.isNull()) {
823 throw JSONRPCError(RPC_INVALID_PARAMETER,
824 "getbalance include_watchonly option is only currently supported if an account is specified");
826 return ValueFromAmount(pwallet->GetBalance());
829 const std::string& account_param = account_value.get_str();
830 const std::string* account = account_param != "*" ? &account_param : nullptr;
832 int nMinDepth = 1;
833 if (!minconf.isNull())
834 nMinDepth = minconf.get_int();
835 isminefilter filter = ISMINE_SPENDABLE;
836 if(!include_watchonly.isNull())
837 if(include_watchonly.get_bool())
838 filter = filter | ISMINE_WATCH_ONLY;
840 return ValueFromAmount(pwallet->GetLegacyBalance(filter, nMinDepth, account));
843 UniValue getunconfirmedbalance(const JSONRPCRequest &request)
845 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
846 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
847 return NullUniValue;
850 if (request.fHelp || request.params.size() > 0)
851 throw std::runtime_error(
852 "getunconfirmedbalance\n"
853 "Returns the server's total unconfirmed balance\n");
855 ObserveSafeMode();
857 // Make sure the results are valid at least up to the most recent block
858 // the user could have gotten from another RPC command prior to now
859 pwallet->BlockUntilSyncedToCurrentChain();
861 LOCK2(cs_main, pwallet->cs_wallet);
863 return ValueFromAmount(pwallet->GetUnconfirmedBalance());
867 UniValue movecmd(const JSONRPCRequest& request)
869 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
870 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
871 return NullUniValue;
874 if (request.fHelp || request.params.size() < 3 || request.params.size() > 5)
875 throw std::runtime_error(
876 "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
877 "\nDEPRECATED. Move a specified amount from one account in your wallet to another.\n"
878 "\nArguments:\n"
879 "1. \"fromaccount\" (string, required) The name of the account to move funds from. May be the default account using \"\".\n"
880 "2. \"toaccount\" (string, required) The name of the account to move funds to. May be the default account using \"\".\n"
881 "3. amount (numeric) Quantity of " + CURRENCY_UNIT + " to move between accounts.\n"
882 "4. (dummy) (numeric, optional) Ignored. Remains for backward compatibility.\n"
883 "5. \"comment\" (string, optional) An optional comment, stored in the wallet only.\n"
884 "\nResult:\n"
885 "true|false (boolean) true if successful.\n"
886 "\nExamples:\n"
887 "\nMove 0.01 " + CURRENCY_UNIT + " from the default account to the account named tabby\n"
888 + HelpExampleCli("move", "\"\" \"tabby\" 0.01") +
889 "\nMove 0.01 " + CURRENCY_UNIT + " timotei to akiko with a comment and funds have 6 confirmations\n"
890 + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") +
891 "\nAs a json rpc call\n"
892 + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
895 ObserveSafeMode();
896 LOCK2(cs_main, pwallet->cs_wallet);
898 std::string strFrom = AccountFromValue(request.params[0]);
899 std::string strTo = AccountFromValue(request.params[1]);
900 CAmount nAmount = AmountFromValue(request.params[2]);
901 if (nAmount <= 0)
902 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
903 if (!request.params[3].isNull())
904 // unused parameter, used to be nMinDepth, keep type-checking it though
905 (void)request.params[3].get_int();
906 std::string strComment;
907 if (!request.params[4].isNull())
908 strComment = request.params[4].get_str();
910 if (!pwallet->AccountMove(strFrom, strTo, nAmount, strComment)) {
911 throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
914 return true;
918 UniValue sendfrom(const JSONRPCRequest& request)
920 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
921 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
922 return NullUniValue;
925 if (request.fHelp || request.params.size() < 3 || request.params.size() > 6)
926 throw std::runtime_error(
927 "sendfrom \"fromaccount\" \"toaddress\" amount ( minconf \"comment\" \"comment_to\" )\n"
928 "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a bitcoin address."
929 + HelpRequiringPassphrase(pwallet) + "\n"
930 "\nArguments:\n"
931 "1. \"fromaccount\" (string, required) The name of the account to send funds from. May be the default account using \"\".\n"
932 " Specifying an account does not influence coin selection, but it does associate the newly created\n"
933 " transaction with the account, so the account's balance computation and transaction history can reflect\n"
934 " the spend.\n"
935 "2. \"toaddress\" (string, required) The bitcoin address to send funds to.\n"
936 "3. amount (numeric or string, required) The amount in " + CURRENCY_UNIT + " (transaction fee is added on top).\n"
937 "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
938 "5. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
939 " This is not part of the transaction, just kept in your wallet.\n"
940 "6. \"comment_to\" (string, optional) An optional comment to store the name of the person or organization \n"
941 " to which you're sending the transaction. This is not part of the transaction, \n"
942 " it is just kept in your wallet.\n"
943 "\nResult:\n"
944 "\"txid\" (string) The transaction id.\n"
945 "\nExamples:\n"
946 "\nSend 0.01 " + CURRENCY_UNIT + " from the default account to the address, must have at least 1 confirmation\n"
947 + HelpExampleCli("sendfrom", "\"\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") +
948 "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
949 + HelpExampleCli("sendfrom", "\"tabby\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01 6 \"donation\" \"seans outpost\"") +
950 "\nAs a json rpc call\n"
951 + HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
954 ObserveSafeMode();
956 // Make sure the results are valid at least up to the most recent block
957 // the user could have gotten from another RPC command prior to now
958 pwallet->BlockUntilSyncedToCurrentChain();
960 LOCK2(cs_main, pwallet->cs_wallet);
962 std::string strAccount = AccountFromValue(request.params[0]);
963 CTxDestination dest = DecodeDestination(request.params[1].get_str());
964 if (!IsValidDestination(dest)) {
965 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
967 CAmount nAmount = AmountFromValue(request.params[2]);
968 if (nAmount <= 0)
969 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
970 int nMinDepth = 1;
971 if (!request.params[3].isNull())
972 nMinDepth = request.params[3].get_int();
974 CWalletTx wtx;
975 wtx.strFromAccount = strAccount;
976 if (!request.params[4].isNull() && !request.params[4].get_str().empty())
977 wtx.mapValue["comment"] = request.params[4].get_str();
978 if (!request.params[5].isNull() && !request.params[5].get_str().empty())
979 wtx.mapValue["to"] = request.params[5].get_str();
981 EnsureWalletIsUnlocked(pwallet);
983 // Check funds
984 CAmount nBalance = pwallet->GetLegacyBalance(ISMINE_SPENDABLE, nMinDepth, &strAccount);
985 if (nAmount > nBalance)
986 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
988 CCoinControl no_coin_control; // This is a deprecated API
989 SendMoney(pwallet, dest, nAmount, false, wtx, no_coin_control);
991 return wtx.GetHash().GetHex();
995 UniValue sendmany(const JSONRPCRequest& request)
997 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
998 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
999 return NullUniValue;
1002 if (request.fHelp || request.params.size() < 2 || request.params.size() > 8)
1003 throw std::runtime_error(
1004 "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] replaceable conf_target \"estimate_mode\")\n"
1005 "\nSend multiple times. Amounts are double-precision floating point numbers."
1006 + HelpRequiringPassphrase(pwallet) + "\n"
1007 "\nArguments:\n"
1008 "1. \"fromaccount\" (string, required) DEPRECATED. The account to send the funds from. Should be \"\" for the default account\n"
1009 "2. \"amounts\" (string, required) A json object with addresses and amounts\n"
1010 " {\n"
1011 " \"address\":amount (numeric or string) The bitcoin address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value\n"
1012 " ,...\n"
1013 " }\n"
1014 "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
1015 "4. \"comment\" (string, optional) A comment\n"
1016 "5. subtractfeefrom (array, optional) A json array with addresses.\n"
1017 " The fee will be equally deducted from the amount of each selected address.\n"
1018 " Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
1019 " If no addresses are specified here, the sender pays the fee.\n"
1020 " [\n"
1021 " \"address\" (string) Subtract fee from this address\n"
1022 " ,...\n"
1023 " ]\n"
1024 "6. replaceable (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees via BIP 125\n"
1025 "7. conf_target (numeric, optional) Confirmation target (in blocks)\n"
1026 "8. \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n"
1027 " \"UNSET\"\n"
1028 " \"ECONOMICAL\"\n"
1029 " \"CONSERVATIVE\"\n"
1030 "\nResult:\n"
1031 "\"txid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
1032 " the number of addresses.\n"
1033 "\nExamples:\n"
1034 "\nSend two amounts to two different addresses:\n"
1035 + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
1036 "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
1037 + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
1038 "\nSend two amounts to two different addresses, subtract fee from amount:\n"
1039 + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\",\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") +
1040 "\nAs a json rpc call\n"
1041 + HelpExampleRpc("sendmany", "\"\", {\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\":0.01,\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\":0.02}, 6, \"testing\"")
1044 ObserveSafeMode();
1046 // Make sure the results are valid at least up to the most recent block
1047 // the user could have gotten from another RPC command prior to now
1048 pwallet->BlockUntilSyncedToCurrentChain();
1050 LOCK2(cs_main, pwallet->cs_wallet);
1052 if (pwallet->GetBroadcastTransactions() && !g_connman) {
1053 throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
1056 std::string strAccount = AccountFromValue(request.params[0]);
1057 UniValue sendTo = request.params[1].get_obj();
1058 int nMinDepth = 1;
1059 if (!request.params[2].isNull())
1060 nMinDepth = request.params[2].get_int();
1062 CWalletTx wtx;
1063 wtx.strFromAccount = strAccount;
1064 if (!request.params[3].isNull() && !request.params[3].get_str().empty())
1065 wtx.mapValue["comment"] = request.params[3].get_str();
1067 UniValue subtractFeeFromAmount(UniValue::VARR);
1068 if (!request.params[4].isNull())
1069 subtractFeeFromAmount = request.params[4].get_array();
1071 CCoinControl coin_control;
1072 if (!request.params[5].isNull()) {
1073 coin_control.signalRbf = request.params[5].get_bool();
1076 if (!request.params[6].isNull()) {
1077 coin_control.m_confirm_target = ParseConfirmTarget(request.params[6]);
1080 if (!request.params[7].isNull()) {
1081 if (!FeeModeFromString(request.params[7].get_str(), coin_control.m_fee_mode)) {
1082 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter");
1086 std::set<CTxDestination> destinations;
1087 std::vector<CRecipient> vecSend;
1089 CAmount totalAmount = 0;
1090 std::vector<std::string> keys = sendTo.getKeys();
1091 for (const std::string& name_ : keys) {
1092 CTxDestination dest = DecodeDestination(name_);
1093 if (!IsValidDestination(dest)) {
1094 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + name_);
1097 if (destinations.count(dest)) {
1098 throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
1100 destinations.insert(dest);
1102 CScript scriptPubKey = GetScriptForDestination(dest);
1103 CAmount nAmount = AmountFromValue(sendTo[name_]);
1104 if (nAmount <= 0)
1105 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
1106 totalAmount += nAmount;
1108 bool fSubtractFeeFromAmount = false;
1109 for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
1110 const UniValue& addr = subtractFeeFromAmount[idx];
1111 if (addr.get_str() == name_)
1112 fSubtractFeeFromAmount = true;
1115 CRecipient recipient = {scriptPubKey, nAmount, fSubtractFeeFromAmount};
1116 vecSend.push_back(recipient);
1119 EnsureWalletIsUnlocked(pwallet);
1121 // Check funds
1122 CAmount nBalance = pwallet->GetLegacyBalance(ISMINE_SPENDABLE, nMinDepth, &strAccount);
1123 if (totalAmount > nBalance)
1124 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
1126 // Send
1127 CReserveKey keyChange(pwallet);
1128 CAmount nFeeRequired = 0;
1129 int nChangePosRet = -1;
1130 std::string strFailReason;
1131 bool fCreated = pwallet->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason, coin_control);
1132 if (!fCreated)
1133 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
1134 CValidationState state;
1135 if (!pwallet->CommitTransaction(wtx, keyChange, g_connman.get(), state)) {
1136 strFailReason = strprintf("Transaction commit failed:: %s", state.GetRejectReason());
1137 throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
1140 return wtx.GetHash().GetHex();
1143 // Defined in rpc/misc.cpp
1144 extern CScript _createmultisig_redeemScript(CWallet * const pwallet, const UniValue& params);
1146 UniValue addmultisigaddress(const JSONRPCRequest& request)
1148 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1149 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1150 return NullUniValue;
1153 if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
1155 std::string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
1156 "\nAdd a nrequired-to-sign multisignature address to the wallet. Requires a new wallet backup.\n"
1157 "Each key is a Bitcoin address or hex-encoded public key.\n"
1158 "If 'account' is specified (DEPRECATED), assign address to that account.\n"
1160 "\nArguments:\n"
1161 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
1162 "2. \"keys\" (string, required) A json array of bitcoin addresses or hex-encoded public keys\n"
1163 " [\n"
1164 " \"address\" (string) bitcoin address or hex-encoded public key\n"
1165 " ...,\n"
1166 " ]\n"
1167 "3. \"account\" (string, optional) DEPRECATED. An account to assign the addresses to.\n"
1169 "\nResult:\n"
1170 "\"address\" (string) A bitcoin address associated with the keys.\n"
1172 "\nExamples:\n"
1173 "\nAdd a multisig address from 2 addresses\n"
1174 + HelpExampleCli("addmultisigaddress", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
1175 "\nAs json rpc call\n"
1176 + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
1178 throw std::runtime_error(msg);
1181 LOCK2(cs_main, pwallet->cs_wallet);
1183 std::string strAccount;
1184 if (!request.params[2].isNull())
1185 strAccount = AccountFromValue(request.params[2]);
1187 // Construct using pay-to-script-hash:
1188 CScript inner = _createmultisig_redeemScript(pwallet, request.params);
1189 CScriptID innerID(inner);
1190 pwallet->AddCScript(inner);
1192 pwallet->SetAddressBook(innerID, strAccount, "send");
1193 return EncodeDestination(innerID);
1196 class Witnessifier : public boost::static_visitor<bool>
1198 public:
1199 CWallet * const pwallet;
1200 CTxDestination result;
1201 bool already_witness;
1203 explicit Witnessifier(CWallet *_pwallet) : pwallet(_pwallet), already_witness(false) {}
1205 bool operator()(const CKeyID &keyID) {
1206 if (pwallet) {
1207 CScript basescript = GetScriptForDestination(keyID);
1208 CScript witscript = GetScriptForWitness(basescript);
1209 SignatureData sigs;
1210 // This check is to make sure that the script we created can actually be solved for and signed by us
1211 // if we were to have the private keys. This is just to make sure that the script is valid and that,
1212 // if found in a transaction, we would still accept and relay that transaction.
1213 if (!ProduceSignature(DummySignatureCreator(pwallet), witscript, sigs) ||
1214 !VerifyScript(sigs.scriptSig, witscript, &sigs.scriptWitness, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, DummySignatureCreator(pwallet).Checker())) {
1215 return false;
1217 return ExtractDestination(witscript, result);
1219 return false;
1222 bool operator()(const CScriptID &scriptID) {
1223 CScript subscript;
1224 if (pwallet && pwallet->GetCScript(scriptID, subscript)) {
1225 int witnessversion;
1226 std::vector<unsigned char> witprog;
1227 if (subscript.IsWitnessProgram(witnessversion, witprog)) {
1228 ExtractDestination(subscript, result);
1229 already_witness = true;
1230 return true;
1232 CScript witscript = GetScriptForWitness(subscript);
1233 SignatureData sigs;
1234 // This check is to make sure that the script we created can actually be solved for and signed by us
1235 // if we were to have the private keys. This is just to make sure that the script is valid and that,
1236 // if found in a transaction, we would still accept and relay that transaction.
1237 if (!ProduceSignature(DummySignatureCreator(pwallet), witscript, sigs) ||
1238 !VerifyScript(sigs.scriptSig, witscript, &sigs.scriptWitness, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, DummySignatureCreator(pwallet).Checker())) {
1239 return false;
1241 return ExtractDestination(witscript, result);
1243 return false;
1246 bool operator()(const WitnessV0KeyHash& id)
1248 already_witness = true;
1249 result = id;
1250 return true;
1253 bool operator()(const WitnessV0ScriptHash& id)
1255 already_witness = true;
1256 result = id;
1257 return true;
1260 template<typename T>
1261 bool operator()(const T& dest) { return false; }
1264 UniValue addwitnessaddress(const JSONRPCRequest& request)
1266 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1267 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1268 return NullUniValue;
1271 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
1273 std::string msg = "addwitnessaddress \"address\" ( p2sh )\n"
1274 "\nAdd a witness address for a script (with pubkey or redeemscript known). Requires a new wallet backup.\n"
1275 "It returns the witness script.\n"
1277 "\nArguments:\n"
1278 "1. \"address\" (string, required) An address known to the wallet\n"
1279 "2. p2sh (bool, optional, default=true) Embed inside P2SH\n"
1281 "\nResult:\n"
1282 "\"witnessaddress\", (string) The value of the new address (P2SH or BIP173).\n"
1283 "}\n"
1285 throw std::runtime_error(msg);
1289 LOCK(cs_main);
1290 if (!IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus()) && !gArgs.GetBoolArg("-walletprematurewitness", false)) {
1291 throw JSONRPCError(RPC_WALLET_ERROR, "Segregated witness not enabled on network");
1295 CTxDestination dest = DecodeDestination(request.params[0].get_str());
1296 if (!IsValidDestination(dest)) {
1297 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
1300 bool p2sh = true;
1301 if (!request.params[1].isNull()) {
1302 p2sh = request.params[1].get_bool();
1305 Witnessifier w(pwallet);
1306 bool ret = boost::apply_visitor(w, dest);
1307 if (!ret) {
1308 throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet, or the key is uncompressed");
1311 CScript witprogram = GetScriptForDestination(w.result);
1313 if (p2sh) {
1314 w.result = CScriptID(witprogram);
1317 if (w.already_witness) {
1318 if (!(dest == w.result)) {
1319 throw JSONRPCError(RPC_WALLET_ERROR, "Cannot convert between witness address types");
1321 } else {
1322 pwallet->AddCScript(witprogram);
1323 pwallet->SetAddressBook(w.result, "", "receive");
1326 return EncodeDestination(w.result);
1329 struct tallyitem
1331 CAmount nAmount;
1332 int nConf;
1333 std::vector<uint256> txids;
1334 bool fIsWatchonly;
1335 tallyitem()
1337 nAmount = 0;
1338 nConf = std::numeric_limits<int>::max();
1339 fIsWatchonly = false;
1343 UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByAccounts)
1345 // Minimum confirmations
1346 int nMinDepth = 1;
1347 if (!params[0].isNull())
1348 nMinDepth = params[0].get_int();
1350 // Whether to include empty accounts
1351 bool fIncludeEmpty = false;
1352 if (!params[1].isNull())
1353 fIncludeEmpty = params[1].get_bool();
1355 isminefilter filter = ISMINE_SPENDABLE;
1356 if(!params[2].isNull())
1357 if(params[2].get_bool())
1358 filter = filter | ISMINE_WATCH_ONLY;
1360 // Tally
1361 std::map<CTxDestination, tallyitem> mapTally;
1362 for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
1363 const CWalletTx& wtx = pairWtx.second;
1365 if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
1366 continue;
1368 int nDepth = wtx.GetDepthInMainChain();
1369 if (nDepth < nMinDepth)
1370 continue;
1372 for (const CTxOut& txout : wtx.tx->vout)
1374 CTxDestination address;
1375 if (!ExtractDestination(txout.scriptPubKey, address))
1376 continue;
1378 isminefilter mine = IsMine(*pwallet, address);
1379 if(!(mine & filter))
1380 continue;
1382 tallyitem& item = mapTally[address];
1383 item.nAmount += txout.nValue;
1384 item.nConf = std::min(item.nConf, nDepth);
1385 item.txids.push_back(wtx.GetHash());
1386 if (mine & ISMINE_WATCH_ONLY)
1387 item.fIsWatchonly = true;
1391 // Reply
1392 UniValue ret(UniValue::VARR);
1393 std::map<std::string, tallyitem> mapAccountTally;
1394 for (const std::pair<CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
1395 const CTxDestination& dest = item.first;
1396 const std::string& strAccount = item.second.name;
1397 std::map<CTxDestination, tallyitem>::iterator it = mapTally.find(dest);
1398 if (it == mapTally.end() && !fIncludeEmpty)
1399 continue;
1401 CAmount nAmount = 0;
1402 int nConf = std::numeric_limits<int>::max();
1403 bool fIsWatchonly = false;
1404 if (it != mapTally.end())
1406 nAmount = (*it).second.nAmount;
1407 nConf = (*it).second.nConf;
1408 fIsWatchonly = (*it).second.fIsWatchonly;
1411 if (fByAccounts)
1413 tallyitem& _item = mapAccountTally[strAccount];
1414 _item.nAmount += nAmount;
1415 _item.nConf = std::min(_item.nConf, nConf);
1416 _item.fIsWatchonly = fIsWatchonly;
1418 else
1420 UniValue obj(UniValue::VOBJ);
1421 if(fIsWatchonly)
1422 obj.push_back(Pair("involvesWatchonly", true));
1423 obj.push_back(Pair("address", EncodeDestination(dest)));
1424 obj.push_back(Pair("account", strAccount));
1425 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1426 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1427 if (!fByAccounts)
1428 obj.push_back(Pair("label", strAccount));
1429 UniValue transactions(UniValue::VARR);
1430 if (it != mapTally.end())
1432 for (const uint256& _item : (*it).second.txids)
1434 transactions.push_back(_item.GetHex());
1437 obj.push_back(Pair("txids", transactions));
1438 ret.push_back(obj);
1442 if (fByAccounts)
1444 for (const auto& entry : mapAccountTally)
1446 CAmount nAmount = entry.second.nAmount;
1447 int nConf = entry.second.nConf;
1448 UniValue obj(UniValue::VOBJ);
1449 if (entry.second.fIsWatchonly)
1450 obj.push_back(Pair("involvesWatchonly", true));
1451 obj.push_back(Pair("account", entry.first));
1452 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1453 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1454 ret.push_back(obj);
1458 return ret;
1461 UniValue listreceivedbyaddress(const JSONRPCRequest& request)
1463 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1464 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1465 return NullUniValue;
1468 if (request.fHelp || request.params.size() > 3)
1469 throw std::runtime_error(
1470 "listreceivedbyaddress ( minconf include_empty include_watchonly)\n"
1471 "\nList balances by receiving address.\n"
1472 "\nArguments:\n"
1473 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1474 "2. include_empty (bool, optional, default=false) Whether to include addresses that haven't received any payments.\n"
1475 "3. include_watchonly (bool, optional, default=false) Whether to include watch-only addresses (see 'importaddress').\n"
1477 "\nResult:\n"
1478 "[\n"
1479 " {\n"
1480 " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
1481 " \"address\" : \"receivingaddress\", (string) The receiving address\n"
1482 " \"account\" : \"accountname\", (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n"
1483 " \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " received by the address\n"
1484 " \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
1485 " \"label\" : \"label\", (string) A comment for the address/transaction, if any\n"
1486 " \"txids\": [\n"
1487 " n, (numeric) The ids of transactions received with the address \n"
1488 " ...\n"
1489 " ]\n"
1490 " }\n"
1491 " ,...\n"
1492 "]\n"
1494 "\nExamples:\n"
1495 + HelpExampleCli("listreceivedbyaddress", "")
1496 + HelpExampleCli("listreceivedbyaddress", "6 true")
1497 + HelpExampleRpc("listreceivedbyaddress", "6, true, true")
1500 ObserveSafeMode();
1502 // Make sure the results are valid at least up to the most recent block
1503 // the user could have gotten from another RPC command prior to now
1504 pwallet->BlockUntilSyncedToCurrentChain();
1506 LOCK2(cs_main, pwallet->cs_wallet);
1508 return ListReceived(pwallet, request.params, false);
1511 UniValue listreceivedbyaccount(const JSONRPCRequest& request)
1513 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1514 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1515 return NullUniValue;
1518 if (request.fHelp || request.params.size() > 3)
1519 throw std::runtime_error(
1520 "listreceivedbyaccount ( minconf include_empty include_watchonly)\n"
1521 "\nDEPRECATED. List balances by account.\n"
1522 "\nArguments:\n"
1523 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1524 "2. include_empty (bool, optional, default=false) Whether to include accounts that haven't received any payments.\n"
1525 "3. include_watchonly (bool, optional, default=false) Whether to include watch-only addresses (see 'importaddress').\n"
1527 "\nResult:\n"
1528 "[\n"
1529 " {\n"
1530 " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
1531 " \"account\" : \"accountname\", (string) The account name of the receiving account\n"
1532 " \"amount\" : x.xxx, (numeric) The total amount received by addresses with this account\n"
1533 " \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
1534 " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
1535 " }\n"
1536 " ,...\n"
1537 "]\n"
1539 "\nExamples:\n"
1540 + HelpExampleCli("listreceivedbyaccount", "")
1541 + HelpExampleCli("listreceivedbyaccount", "6 true")
1542 + HelpExampleRpc("listreceivedbyaccount", "6, true, true")
1545 ObserveSafeMode();
1547 // Make sure the results are valid at least up to the most recent block
1548 // the user could have gotten from another RPC command prior to now
1549 pwallet->BlockUntilSyncedToCurrentChain();
1551 LOCK2(cs_main, pwallet->cs_wallet);
1553 return ListReceived(pwallet, request.params, true);
1556 static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
1558 if (IsValidDestination(dest)) {
1559 entry.push_back(Pair("address", EncodeDestination(dest)));
1564 * List transactions based on the given criteria.
1566 * @param pwallet The wallet.
1567 * @param wtx The wallet transaction.
1568 * @param strAccount The account, if any, or "*" for all.
1569 * @param nMinDepth The minimum confirmation depth.
1570 * @param fLong Whether to include the JSON version of the transaction.
1571 * @param ret The UniValue into which the result is stored.
1572 * @param filter The "is mine" filter bool.
1574 void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, const std::string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
1576 CAmount nFee;
1577 std::string strSentAccount;
1578 std::list<COutputEntry> listReceived;
1579 std::list<COutputEntry> listSent;
1581 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter);
1583 bool fAllAccounts = (strAccount == std::string("*"));
1584 bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
1586 // Sent
1587 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1589 for (const COutputEntry& s : listSent)
1591 UniValue entry(UniValue::VOBJ);
1592 if (involvesWatchonly || (::IsMine(*pwallet, s.destination) & ISMINE_WATCH_ONLY)) {
1593 entry.push_back(Pair("involvesWatchonly", true));
1595 entry.push_back(Pair("account", strSentAccount));
1596 MaybePushAddress(entry, s.destination);
1597 entry.push_back(Pair("category", "send"));
1598 entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
1599 if (pwallet->mapAddressBook.count(s.destination)) {
1600 entry.push_back(Pair("label", pwallet->mapAddressBook[s.destination].name));
1602 entry.push_back(Pair("vout", s.vout));
1603 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1604 if (fLong)
1605 WalletTxToJSON(wtx, entry);
1606 entry.push_back(Pair("abandoned", wtx.isAbandoned()));
1607 ret.push_back(entry);
1611 // Received
1612 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1614 for (const COutputEntry& r : listReceived)
1616 std::string account;
1617 if (pwallet->mapAddressBook.count(r.destination)) {
1618 account = pwallet->mapAddressBook[r.destination].name;
1620 if (fAllAccounts || (account == strAccount))
1622 UniValue entry(UniValue::VOBJ);
1623 if (involvesWatchonly || (::IsMine(*pwallet, r.destination) & ISMINE_WATCH_ONLY)) {
1624 entry.push_back(Pair("involvesWatchonly", true));
1626 entry.push_back(Pair("account", account));
1627 MaybePushAddress(entry, r.destination);
1628 if (wtx.IsCoinBase())
1630 if (wtx.GetDepthInMainChain() < 1)
1631 entry.push_back(Pair("category", "orphan"));
1632 else if (wtx.GetBlocksToMaturity() > 0)
1633 entry.push_back(Pair("category", "immature"));
1634 else
1635 entry.push_back(Pair("category", "generate"));
1637 else
1639 entry.push_back(Pair("category", "receive"));
1641 entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
1642 if (pwallet->mapAddressBook.count(r.destination)) {
1643 entry.push_back(Pair("label", account));
1645 entry.push_back(Pair("vout", r.vout));
1646 if (fLong)
1647 WalletTxToJSON(wtx, entry);
1648 ret.push_back(entry);
1654 void AcentryToJSON(const CAccountingEntry& acentry, const std::string& strAccount, UniValue& ret)
1656 bool fAllAccounts = (strAccount == std::string("*"));
1658 if (fAllAccounts || acentry.strAccount == strAccount)
1660 UniValue entry(UniValue::VOBJ);
1661 entry.push_back(Pair("account", acentry.strAccount));
1662 entry.push_back(Pair("category", "move"));
1663 entry.push_back(Pair("time", acentry.nTime));
1664 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1665 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1666 entry.push_back(Pair("comment", acentry.strComment));
1667 ret.push_back(entry);
1671 UniValue listtransactions(const JSONRPCRequest& request)
1673 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1674 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1675 return NullUniValue;
1678 if (request.fHelp || request.params.size() > 4)
1679 throw std::runtime_error(
1680 "listtransactions ( \"account\" count skip include_watchonly)\n"
1681 "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n"
1682 "\nArguments:\n"
1683 "1. \"account\" (string, optional) DEPRECATED. The account name. Should be \"*\".\n"
1684 "2. count (numeric, optional, default=10) The number of transactions to return\n"
1685 "3. skip (numeric, optional, default=0) The number of transactions to skip\n"
1686 "4. include_watchonly (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress')\n"
1687 "\nResult:\n"
1688 "[\n"
1689 " {\n"
1690 " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. \n"
1691 " It will be \"\" for the default account.\n"
1692 " \"address\":\"address\", (string) The bitcoin address of the transaction. Not present for \n"
1693 " move transactions (category = move).\n"
1694 " \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n"
1695 " transaction between accounts, and not associated with an address,\n"
1696 " transaction id or block. 'send' and 'receive' transactions are \n"
1697 " associated with an address, transaction id and block details\n"
1698 " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the\n"
1699 " 'move' category for moves outbound. It is positive for the 'receive' category,\n"
1700 " and for the 'move' category for inbound funds.\n"
1701 " \"label\": \"label\", (string) A comment for the address/transaction, if any\n"
1702 " \"vout\": n, (numeric) the vout value\n"
1703 " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
1704 " 'send' category of transactions.\n"
1705 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
1706 " 'receive' category of transactions. Negative confirmations indicate the\n"
1707 " transaction conflicts with the block chain\n"
1708 " \"trusted\": xxx, (bool) Whether we consider the outputs of this unconfirmed transaction safe to spend.\n"
1709 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
1710 " category of transactions.\n"
1711 " \"blockindex\": n, (numeric) The index of the transaction in the block that includes it. Available for 'send' and 'receive'\n"
1712 " category of transactions.\n"
1713 " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
1714 " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1715 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
1716 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
1717 " for 'send' and 'receive' category of transactions.\n"
1718 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1719 " \"otheraccount\": \"accountname\", (string) DEPRECATED. For the 'move' category of transactions, the account the funds came \n"
1720 " from (for receiving funds, positive amounts), or went to (for sending funds,\n"
1721 " negative amounts).\n"
1722 " \"bip125-replaceable\": \"yes|no|unknown\", (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
1723 " may be unknown for unconfirmed transactions not in the mempool\n"
1724 " \"abandoned\": xxx (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
1725 " 'send' category of transactions.\n"
1726 " }\n"
1727 "]\n"
1729 "\nExamples:\n"
1730 "\nList the most recent 10 transactions in the systems\n"
1731 + HelpExampleCli("listtransactions", "") +
1732 "\nList transactions 100 to 120\n"
1733 + HelpExampleCli("listtransactions", "\"*\" 20 100") +
1734 "\nAs a json rpc call\n"
1735 + HelpExampleRpc("listtransactions", "\"*\", 20, 100")
1738 ObserveSafeMode();
1740 // Make sure the results are valid at least up to the most recent block
1741 // the user could have gotten from another RPC command prior to now
1742 pwallet->BlockUntilSyncedToCurrentChain();
1744 LOCK2(cs_main, pwallet->cs_wallet);
1746 std::string strAccount = "*";
1747 if (!request.params[0].isNull())
1748 strAccount = request.params[0].get_str();
1749 int nCount = 10;
1750 if (!request.params[1].isNull())
1751 nCount = request.params[1].get_int();
1752 int nFrom = 0;
1753 if (!request.params[2].isNull())
1754 nFrom = request.params[2].get_int();
1755 isminefilter filter = ISMINE_SPENDABLE;
1756 if(!request.params[3].isNull())
1757 if(request.params[3].get_bool())
1758 filter = filter | ISMINE_WATCH_ONLY;
1760 if (nCount < 0)
1761 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
1762 if (nFrom < 0)
1763 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
1765 UniValue ret(UniValue::VARR);
1767 const CWallet::TxItems & txOrdered = pwallet->wtxOrdered;
1769 // iterate backwards until we have nCount items to return:
1770 for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
1772 CWalletTx *const pwtx = (*it).second.first;
1773 if (pwtx != nullptr)
1774 ListTransactions(pwallet, *pwtx, strAccount, 0, true, ret, filter);
1775 CAccountingEntry *const pacentry = (*it).second.second;
1776 if (pacentry != nullptr)
1777 AcentryToJSON(*pacentry, strAccount, ret);
1779 if ((int)ret.size() >= (nCount+nFrom)) break;
1781 // ret is newest to oldest
1783 if (nFrom > (int)ret.size())
1784 nFrom = ret.size();
1785 if ((nFrom + nCount) > (int)ret.size())
1786 nCount = ret.size() - nFrom;
1788 std::vector<UniValue> arrTmp = ret.getValues();
1790 std::vector<UniValue>::iterator first = arrTmp.begin();
1791 std::advance(first, nFrom);
1792 std::vector<UniValue>::iterator last = arrTmp.begin();
1793 std::advance(last, nFrom+nCount);
1795 if (last != arrTmp.end()) arrTmp.erase(last, arrTmp.end());
1796 if (first != arrTmp.begin()) arrTmp.erase(arrTmp.begin(), first);
1798 std::reverse(arrTmp.begin(), arrTmp.end()); // Return oldest to newest
1800 ret.clear();
1801 ret.setArray();
1802 ret.push_backV(arrTmp);
1804 return ret;
1807 UniValue listaccounts(const JSONRPCRequest& request)
1809 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1810 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1811 return NullUniValue;
1814 if (request.fHelp || request.params.size() > 2)
1815 throw std::runtime_error(
1816 "listaccounts ( minconf include_watchonly)\n"
1817 "\nDEPRECATED. Returns Object that has account names as keys, account balances as values.\n"
1818 "\nArguments:\n"
1819 "1. minconf (numeric, optional, default=1) Only include transactions with at least this many confirmations\n"
1820 "2. include_watchonly (bool, optional, default=false) Include balances in watch-only addresses (see 'importaddress')\n"
1821 "\nResult:\n"
1822 "{ (json object where keys are account names, and values are numeric balances\n"
1823 " \"account\": x.xxx, (numeric) The property name is the account name, and the value is the total balance for the account.\n"
1824 " ...\n"
1825 "}\n"
1826 "\nExamples:\n"
1827 "\nList account balances where there at least 1 confirmation\n"
1828 + HelpExampleCli("listaccounts", "") +
1829 "\nList account balances including zero confirmation transactions\n"
1830 + HelpExampleCli("listaccounts", "0") +
1831 "\nList account balances for 6 or more confirmations\n"
1832 + HelpExampleCli("listaccounts", "6") +
1833 "\nAs json rpc call\n"
1834 + HelpExampleRpc("listaccounts", "6")
1837 ObserveSafeMode();
1839 // Make sure the results are valid at least up to the most recent block
1840 // the user could have gotten from another RPC command prior to now
1841 pwallet->BlockUntilSyncedToCurrentChain();
1843 LOCK2(cs_main, pwallet->cs_wallet);
1845 int nMinDepth = 1;
1846 if (!request.params[0].isNull())
1847 nMinDepth = request.params[0].get_int();
1848 isminefilter includeWatchonly = ISMINE_SPENDABLE;
1849 if(!request.params[1].isNull())
1850 if(request.params[1].get_bool())
1851 includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY;
1853 std::map<std::string, CAmount> mapAccountBalances;
1854 for (const std::pair<CTxDestination, CAddressBookData>& entry : pwallet->mapAddressBook) {
1855 if (IsMine(*pwallet, entry.first) & includeWatchonly) { // This address belongs to me
1856 mapAccountBalances[entry.second.name] = 0;
1860 for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
1861 const CWalletTx& wtx = pairWtx.second;
1862 CAmount nFee;
1863 std::string strSentAccount;
1864 std::list<COutputEntry> listReceived;
1865 std::list<COutputEntry> listSent;
1866 int nDepth = wtx.GetDepthInMainChain();
1867 if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
1868 continue;
1869 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
1870 mapAccountBalances[strSentAccount] -= nFee;
1871 for (const COutputEntry& s : listSent)
1872 mapAccountBalances[strSentAccount] -= s.amount;
1873 if (nDepth >= nMinDepth)
1875 for (const COutputEntry& r : listReceived)
1876 if (pwallet->mapAddressBook.count(r.destination)) {
1877 mapAccountBalances[pwallet->mapAddressBook[r.destination].name] += r.amount;
1879 else
1880 mapAccountBalances[""] += r.amount;
1884 const std::list<CAccountingEntry>& acentries = pwallet->laccentries;
1885 for (const CAccountingEntry& entry : acentries)
1886 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1888 UniValue ret(UniValue::VOBJ);
1889 for (const std::pair<std::string, CAmount>& accountBalance : mapAccountBalances) {
1890 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1892 return ret;
1895 UniValue listsinceblock(const JSONRPCRequest& request)
1897 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
1898 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
1899 return NullUniValue;
1902 if (request.fHelp || request.params.size() > 4)
1903 throw std::runtime_error(
1904 "listsinceblock ( \"blockhash\" target_confirmations include_watchonly include_removed )\n"
1905 "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted.\n"
1906 "If \"blockhash\" is no longer a part of the main chain, transactions from the fork point onward are included.\n"
1907 "Additionally, if include_removed is set, transactions affecting the wallet which were removed are returned in the \"removed\" array.\n"
1908 "\nArguments:\n"
1909 "1. \"blockhash\" (string, optional) The block hash to list transactions since\n"
1910 "2. target_confirmations: (numeric, optional, default=1) Return the nth block hash from the main chain. e.g. 1 would mean the best block hash. Note: this is not used as a filter, but only affects [lastblock] in the return value\n"
1911 "3. include_watchonly: (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress')\n"
1912 "4. include_removed: (bool, optional, default=true) Show transactions that were removed due to a reorg in the \"removed\" array\n"
1913 " (not guaranteed to work on pruned nodes)\n"
1914 "\nResult:\n"
1915 "{\n"
1916 " \"transactions\": [\n"
1917 " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n"
1918 " \"address\":\"address\", (string) The bitcoin address of the transaction. Not present for move transactions (category = move).\n"
1919 " \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
1920 " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the 'move' category for moves \n"
1921 " outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
1922 " \"vout\" : n, (numeric) the vout value\n"
1923 " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the 'send' category of transactions.\n"
1924 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
1925 " When it's < 0, it means the transaction conflicted that many blocks ago.\n"
1926 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1927 " \"blockindex\": n, (numeric) The index of the transaction in the block that includes it. Available for 'send' and 'receive' category of transactions.\n"
1928 " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
1929 " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1930 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
1931 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
1932 " \"bip125-replaceable\": \"yes|no|unknown\", (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
1933 " may be unknown for unconfirmed transactions not in the mempool\n"
1934 " \"abandoned\": xxx, (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the 'send' category of transactions.\n"
1935 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1936 " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
1937 " \"to\": \"...\", (string) If a comment to is associated with the transaction.\n"
1938 " ],\n"
1939 " \"removed\": [\n"
1940 " <structure is the same as \"transactions\" above, only present if include_removed=true>\n"
1941 " Note: transactions that were readded in the active chain will appear as-is in this array, and may thus have a positive confirmation count.\n"
1942 " ],\n"
1943 " \"lastblock\": \"lastblockhash\" (string) The hash of the block (target_confirmations-1) from the best block on the main chain. This is typically used to feed back into listsinceblock the next time you call it. So you would generally use a target_confirmations of say 6, so you will be continually re-notified of transactions until they've reached 6 confirmations plus any new ones\n"
1944 "}\n"
1945 "\nExamples:\n"
1946 + HelpExampleCli("listsinceblock", "")
1947 + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
1948 + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
1951 ObserveSafeMode();
1953 // Make sure the results are valid at least up to the most recent block
1954 // the user could have gotten from another RPC command prior to now
1955 pwallet->BlockUntilSyncedToCurrentChain();
1957 LOCK2(cs_main, pwallet->cs_wallet);
1959 const CBlockIndex* pindex = nullptr; // Block index of the specified block or the common ancestor, if the block provided was in a deactivated chain.
1960 const CBlockIndex* paltindex = nullptr; // Block index of the specified block, even if it's in a deactivated chain.
1961 int target_confirms = 1;
1962 isminefilter filter = ISMINE_SPENDABLE;
1964 if (!request.params[0].isNull() && !request.params[0].get_str().empty()) {
1965 uint256 blockId;
1967 blockId.SetHex(request.params[0].get_str());
1968 BlockMap::iterator it = mapBlockIndex.find(blockId);
1969 if (it == mapBlockIndex.end()) {
1970 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1972 paltindex = pindex = it->second;
1973 if (chainActive[pindex->nHeight] != pindex) {
1974 // the block being asked for is a part of a deactivated chain;
1975 // we don't want to depend on its perceived height in the block
1976 // chain, we want to instead use the last common ancestor
1977 pindex = chainActive.FindFork(pindex);
1981 if (!request.params[1].isNull()) {
1982 target_confirms = request.params[1].get_int();
1984 if (target_confirms < 1) {
1985 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
1989 if (!request.params[2].isNull() && request.params[2].get_bool()) {
1990 filter = filter | ISMINE_WATCH_ONLY;
1993 bool include_removed = (request.params[3].isNull() || request.params[3].get_bool());
1995 int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
1997 UniValue transactions(UniValue::VARR);
1999 for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
2000 CWalletTx tx = pairWtx.second;
2002 if (depth == -1 || tx.GetDepthInMainChain() < depth) {
2003 ListTransactions(pwallet, tx, "*", 0, true, transactions, filter);
2007 // when a reorg'd block is requested, we also list any relevant transactions
2008 // in the blocks of the chain that was detached
2009 UniValue removed(UniValue::VARR);
2010 while (include_removed && paltindex && paltindex != pindex) {
2011 CBlock block;
2012 if (!ReadBlockFromDisk(block, paltindex, Params().GetConsensus())) {
2013 throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
2015 for (const CTransactionRef& tx : block.vtx) {
2016 auto it = pwallet->mapWallet.find(tx->GetHash());
2017 if (it != pwallet->mapWallet.end()) {
2018 // We want all transactions regardless of confirmation count to appear here,
2019 // even negative confirmation ones, hence the big negative.
2020 ListTransactions(pwallet, it->second, "*", -100000000, true, removed, filter);
2023 paltindex = paltindex->pprev;
2026 CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
2027 uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : uint256();
2029 UniValue ret(UniValue::VOBJ);
2030 ret.push_back(Pair("transactions", transactions));
2031 if (include_removed) ret.push_back(Pair("removed", removed));
2032 ret.push_back(Pair("lastblock", lastblock.GetHex()));
2034 return ret;
2037 UniValue gettransaction(const JSONRPCRequest& request)
2039 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2040 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2041 return NullUniValue;
2044 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
2045 throw std::runtime_error(
2046 "gettransaction \"txid\" ( include_watchonly )\n"
2047 "\nGet detailed information about in-wallet transaction <txid>\n"
2048 "\nArguments:\n"
2049 "1. \"txid\" (string, required) The transaction id\n"
2050 "2. \"include_watchonly\" (bool, optional, default=false) Whether to include watch-only addresses in balance calculation and details[]\n"
2051 "\nResult:\n"
2052 "{\n"
2053 " \"amount\" : x.xxx, (numeric) The transaction amount in " + CURRENCY_UNIT + "\n"
2054 " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
2055 " 'send' category of transactions.\n"
2056 " \"confirmations\" : n, (numeric) The number of confirmations\n"
2057 " \"blockhash\" : \"hash\", (string) The block hash\n"
2058 " \"blockindex\" : xx, (numeric) The index of the transaction in the block that includes it\n"
2059 " \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
2060 " \"txid\" : \"transactionid\", (string) The transaction id.\n"
2061 " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
2062 " \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
2063 " \"bip125-replaceable\": \"yes|no|unknown\", (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
2064 " may be unknown for unconfirmed transactions not in the mempool\n"
2065 " \"details\" : [\n"
2066 " {\n"
2067 " \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n"
2068 " \"address\" : \"address\", (string) The bitcoin address involved in the transaction\n"
2069 " \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n"
2070 " \"amount\" : x.xxx, (numeric) The amount in " + CURRENCY_UNIT + "\n"
2071 " \"label\" : \"label\", (string) A comment for the address/transaction, if any\n"
2072 " \"vout\" : n, (numeric) the vout value\n"
2073 " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
2074 " 'send' category of transactions.\n"
2075 " \"abandoned\": xxx (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
2076 " 'send' category of transactions.\n"
2077 " }\n"
2078 " ,...\n"
2079 " ],\n"
2080 " \"hex\" : \"data\" (string) Raw data for transaction\n"
2081 "}\n"
2083 "\nExamples:\n"
2084 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
2085 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
2086 + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
2089 ObserveSafeMode();
2091 // Make sure the results are valid at least up to the most recent block
2092 // the user could have gotten from another RPC command prior to now
2093 pwallet->BlockUntilSyncedToCurrentChain();
2095 LOCK2(cs_main, pwallet->cs_wallet);
2097 uint256 hash;
2098 hash.SetHex(request.params[0].get_str());
2100 isminefilter filter = ISMINE_SPENDABLE;
2101 if(!request.params[1].isNull())
2102 if(request.params[1].get_bool())
2103 filter = filter | ISMINE_WATCH_ONLY;
2105 UniValue entry(UniValue::VOBJ);
2106 auto it = pwallet->mapWallet.find(hash);
2107 if (it == pwallet->mapWallet.end()) {
2108 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
2110 const CWalletTx& wtx = it->second;
2112 CAmount nCredit = wtx.GetCredit(filter);
2113 CAmount nDebit = wtx.GetDebit(filter);
2114 CAmount nNet = nCredit - nDebit;
2115 CAmount nFee = (wtx.IsFromMe(filter) ? wtx.tx->GetValueOut() - nDebit : 0);
2117 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
2118 if (wtx.IsFromMe(filter))
2119 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
2121 WalletTxToJSON(wtx, entry);
2123 UniValue details(UniValue::VARR);
2124 ListTransactions(pwallet, wtx, "*", 0, false, details, filter);
2125 entry.push_back(Pair("details", details));
2127 std::string strHex = EncodeHexTx(*wtx.tx, RPCSerializationFlags());
2128 entry.push_back(Pair("hex", strHex));
2130 return entry;
2133 UniValue abandontransaction(const JSONRPCRequest& request)
2135 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2136 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2137 return NullUniValue;
2140 if (request.fHelp || request.params.size() != 1)
2141 throw std::runtime_error(
2142 "abandontransaction \"txid\"\n"
2143 "\nMark in-wallet transaction <txid> as abandoned\n"
2144 "This will mark this transaction and all its in-wallet descendants as abandoned which will allow\n"
2145 "for their inputs to be respent. It can be used to replace \"stuck\" or evicted transactions.\n"
2146 "It only works on transactions which are not included in a block and are not currently in the mempool.\n"
2147 "It has no effect on transactions which are already conflicted or abandoned.\n"
2148 "\nArguments:\n"
2149 "1. \"txid\" (string, required) The transaction id\n"
2150 "\nResult:\n"
2151 "\nExamples:\n"
2152 + HelpExampleCli("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
2153 + HelpExampleRpc("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
2156 ObserveSafeMode();
2158 // Make sure the results are valid at least up to the most recent block
2159 // the user could have gotten from another RPC command prior to now
2160 pwallet->BlockUntilSyncedToCurrentChain();
2162 LOCK2(cs_main, pwallet->cs_wallet);
2164 uint256 hash;
2165 hash.SetHex(request.params[0].get_str());
2167 if (!pwallet->mapWallet.count(hash)) {
2168 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
2170 if (!pwallet->AbandonTransaction(hash)) {
2171 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not eligible for abandonment");
2174 return NullUniValue;
2178 UniValue backupwallet(const JSONRPCRequest& request)
2180 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2181 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2182 return NullUniValue;
2185 if (request.fHelp || request.params.size() != 1)
2186 throw std::runtime_error(
2187 "backupwallet \"destination\"\n"
2188 "\nSafely copies current wallet file to destination, which can be a directory or a path with filename.\n"
2189 "\nArguments:\n"
2190 "1. \"destination\" (string) The destination directory or file\n"
2191 "\nExamples:\n"
2192 + HelpExampleCli("backupwallet", "\"backup.dat\"")
2193 + HelpExampleRpc("backupwallet", "\"backup.dat\"")
2196 // Make sure the results are valid at least up to the most recent block
2197 // the user could have gotten from another RPC command prior to now
2198 pwallet->BlockUntilSyncedToCurrentChain();
2200 LOCK2(cs_main, pwallet->cs_wallet);
2202 std::string strDest = request.params[0].get_str();
2203 if (!pwallet->BackupWallet(strDest)) {
2204 throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
2207 return NullUniValue;
2211 UniValue keypoolrefill(const JSONRPCRequest& request)
2213 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2214 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2215 return NullUniValue;
2218 if (request.fHelp || request.params.size() > 1)
2219 throw std::runtime_error(
2220 "keypoolrefill ( newsize )\n"
2221 "\nFills the keypool."
2222 + HelpRequiringPassphrase(pwallet) + "\n"
2223 "\nArguments\n"
2224 "1. newsize (numeric, optional, default=100) The new keypool size\n"
2225 "\nExamples:\n"
2226 + HelpExampleCli("keypoolrefill", "")
2227 + HelpExampleRpc("keypoolrefill", "")
2230 LOCK2(cs_main, pwallet->cs_wallet);
2232 // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
2233 unsigned int kpSize = 0;
2234 if (!request.params[0].isNull()) {
2235 if (request.params[0].get_int() < 0)
2236 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
2237 kpSize = (unsigned int)request.params[0].get_int();
2240 EnsureWalletIsUnlocked(pwallet);
2241 pwallet->TopUpKeyPool(kpSize);
2243 if (pwallet->GetKeyPoolSize() < kpSize) {
2244 throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
2247 return NullUniValue;
2251 static void LockWallet(CWallet* pWallet)
2253 LOCK(pWallet->cs_wallet);
2254 pWallet->nRelockTime = 0;
2255 pWallet->Lock();
2258 UniValue walletpassphrase(const JSONRPCRequest& request)
2260 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2261 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2262 return NullUniValue;
2265 if (request.fHelp || request.params.size() != 2) {
2266 throw std::runtime_error(
2267 "walletpassphrase \"passphrase\" timeout\n"
2268 "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
2269 "This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
2270 "\nArguments:\n"
2271 "1. \"passphrase\" (string, required) The wallet passphrase\n"
2272 "2. timeout (numeric, required) The time to keep the decryption key in seconds.\n"
2273 "\nNote:\n"
2274 "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
2275 "time that overrides the old one.\n"
2276 "\nExamples:\n"
2277 "\nUnlock the wallet for 60 seconds\n"
2278 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
2279 "\nLock the wallet again (before 60 seconds)\n"
2280 + HelpExampleCli("walletlock", "") +
2281 "\nAs json rpc call\n"
2282 + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
2286 LOCK2(cs_main, pwallet->cs_wallet);
2288 if (request.fHelp)
2289 return true;
2290 if (!pwallet->IsCrypted()) {
2291 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
2294 // Note that the walletpassphrase is stored in request.params[0] which is not mlock()ed
2295 SecureString strWalletPass;
2296 strWalletPass.reserve(100);
2297 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
2298 // Alternately, find a way to make request.params[0] mlock()'d to begin with.
2299 strWalletPass = request.params[0].get_str().c_str();
2301 if (strWalletPass.length() > 0)
2303 if (!pwallet->Unlock(strWalletPass)) {
2304 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
2307 else
2308 throw std::runtime_error(
2309 "walletpassphrase <passphrase> <timeout>\n"
2310 "Stores the wallet decryption key in memory for <timeout> seconds.");
2312 pwallet->TopUpKeyPool();
2314 int64_t nSleepTime = request.params[1].get_int64();
2315 pwallet->nRelockTime = GetTime() + nSleepTime;
2316 RPCRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), boost::bind(LockWallet, pwallet), nSleepTime);
2318 return NullUniValue;
2322 UniValue walletpassphrasechange(const JSONRPCRequest& request)
2324 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2325 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2326 return NullUniValue;
2329 if (request.fHelp || request.params.size() != 2) {
2330 throw std::runtime_error(
2331 "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
2332 "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
2333 "\nArguments:\n"
2334 "1. \"oldpassphrase\" (string) The current passphrase\n"
2335 "2. \"newpassphrase\" (string) The new passphrase\n"
2336 "\nExamples:\n"
2337 + HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
2338 + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
2342 LOCK2(cs_main, pwallet->cs_wallet);
2344 if (request.fHelp)
2345 return true;
2346 if (!pwallet->IsCrypted()) {
2347 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
2350 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
2351 // Alternately, find a way to make request.params[0] mlock()'d to begin with.
2352 SecureString strOldWalletPass;
2353 strOldWalletPass.reserve(100);
2354 strOldWalletPass = request.params[0].get_str().c_str();
2356 SecureString strNewWalletPass;
2357 strNewWalletPass.reserve(100);
2358 strNewWalletPass = request.params[1].get_str().c_str();
2360 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
2361 throw std::runtime_error(
2362 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
2363 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
2365 if (!pwallet->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass)) {
2366 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
2369 return NullUniValue;
2373 UniValue walletlock(const JSONRPCRequest& request)
2375 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2376 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2377 return NullUniValue;
2380 if (request.fHelp || request.params.size() != 0) {
2381 throw std::runtime_error(
2382 "walletlock\n"
2383 "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
2384 "After calling this method, you will need to call walletpassphrase again\n"
2385 "before being able to call any methods which require the wallet to be unlocked.\n"
2386 "\nExamples:\n"
2387 "\nSet the passphrase for 2 minutes to perform a transaction\n"
2388 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
2389 "\nPerform a send (requires passphrase set)\n"
2390 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 1.0") +
2391 "\nClear the passphrase since we are done before 2 minutes is up\n"
2392 + HelpExampleCli("walletlock", "") +
2393 "\nAs json rpc call\n"
2394 + HelpExampleRpc("walletlock", "")
2398 LOCK2(cs_main, pwallet->cs_wallet);
2400 if (request.fHelp)
2401 return true;
2402 if (!pwallet->IsCrypted()) {
2403 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
2406 pwallet->Lock();
2407 pwallet->nRelockTime = 0;
2409 return NullUniValue;
2413 UniValue encryptwallet(const JSONRPCRequest& request)
2415 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2416 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2417 return NullUniValue;
2420 if (request.fHelp || request.params.size() != 1) {
2421 throw std::runtime_error(
2422 "encryptwallet \"passphrase\"\n"
2423 "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
2424 "After this, any calls that interact with private keys such as sending or signing \n"
2425 "will require the passphrase to be set prior the making these calls.\n"
2426 "Use the walletpassphrase call for this, and then walletlock call.\n"
2427 "If the wallet is already encrypted, use the walletpassphrasechange call.\n"
2428 "Note that this will shutdown the server.\n"
2429 "\nArguments:\n"
2430 "1. \"passphrase\" (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n"
2431 "\nExamples:\n"
2432 "\nEncrypt your wallet\n"
2433 + HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
2434 "\nNow set the passphrase to use the wallet, such as for signing or sending bitcoin\n"
2435 + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
2436 "\nNow we can do something like sign\n"
2437 + HelpExampleCli("signmessage", "\"address\" \"test message\"") +
2438 "\nNow lock the wallet again by removing the passphrase\n"
2439 + HelpExampleCli("walletlock", "") +
2440 "\nAs a json rpc call\n"
2441 + HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
2445 LOCK2(cs_main, pwallet->cs_wallet);
2447 if (request.fHelp)
2448 return true;
2449 if (pwallet->IsCrypted()) {
2450 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
2453 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
2454 // Alternately, find a way to make request.params[0] mlock()'d to begin with.
2455 SecureString strWalletPass;
2456 strWalletPass.reserve(100);
2457 strWalletPass = request.params[0].get_str().c_str();
2459 if (strWalletPass.length() < 1)
2460 throw std::runtime_error(
2461 "encryptwallet <passphrase>\n"
2462 "Encrypts the wallet with <passphrase>.");
2464 if (!pwallet->EncryptWallet(strWalletPass)) {
2465 throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
2468 // BDB seems to have a bad habit of writing old data into
2469 // slack space in .dat files; that is bad if the old data is
2470 // unencrypted private keys. So:
2471 StartShutdown();
2472 return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed and a new HD seed was generated (if you are using HD). You need to make a new backup.";
2475 UniValue lockunspent(const JSONRPCRequest& request)
2477 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2478 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2479 return NullUniValue;
2482 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
2483 throw std::runtime_error(
2484 "lockunspent unlock ([{\"txid\":\"txid\",\"vout\":n},...])\n"
2485 "\nUpdates list of temporarily unspendable outputs.\n"
2486 "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
2487 "If no transaction outputs are specified when unlocking then all current locked transaction outputs are unlocked.\n"
2488 "A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
2489 "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
2490 "is always cleared (by virtue of process exit) when a node stops or fails.\n"
2491 "Also see the listunspent call\n"
2492 "\nArguments:\n"
2493 "1. unlock (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
2494 "2. \"transactions\" (string, optional) A json array of objects. Each object the txid (string) vout (numeric)\n"
2495 " [ (json array of json objects)\n"
2496 " {\n"
2497 " \"txid\":\"id\", (string) The transaction id\n"
2498 " \"vout\": n (numeric) The output number\n"
2499 " }\n"
2500 " ,...\n"
2501 " ]\n"
2503 "\nResult:\n"
2504 "true|false (boolean) Whether the command was successful or not\n"
2506 "\nExamples:\n"
2507 "\nList the unspent transactions\n"
2508 + HelpExampleCli("listunspent", "") +
2509 "\nLock an unspent transaction\n"
2510 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2511 "\nList the locked transactions\n"
2512 + HelpExampleCli("listlockunspent", "") +
2513 "\nUnlock the transaction again\n"
2514 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2515 "\nAs a json rpc call\n"
2516 + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
2519 // Make sure the results are valid at least up to the most recent block
2520 // the user could have gotten from another RPC command prior to now
2521 pwallet->BlockUntilSyncedToCurrentChain();
2523 LOCK2(cs_main, pwallet->cs_wallet);
2525 RPCTypeCheckArgument(request.params[0], UniValue::VBOOL);
2527 bool fUnlock = request.params[0].get_bool();
2529 if (request.params[1].isNull()) {
2530 if (fUnlock)
2531 pwallet->UnlockAllCoins();
2532 return true;
2535 RPCTypeCheckArgument(request.params[1], UniValue::VARR);
2537 const UniValue& output_params = request.params[1];
2539 // Create and validate the COutPoints first.
2541 std::vector<COutPoint> outputs;
2542 outputs.reserve(output_params.size());
2544 for (unsigned int idx = 0; idx < output_params.size(); idx++) {
2545 const UniValue& o = output_params[idx].get_obj();
2547 RPCTypeCheckObj(o,
2549 {"txid", UniValueType(UniValue::VSTR)},
2550 {"vout", UniValueType(UniValue::VNUM)},
2553 const std::string& txid = find_value(o, "txid").get_str();
2554 if (!IsHex(txid)) {
2555 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
2558 const int nOutput = find_value(o, "vout").get_int();
2559 if (nOutput < 0) {
2560 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
2563 const COutPoint outpt(uint256S(txid), nOutput);
2565 const auto it = pwallet->mapWallet.find(outpt.hash);
2566 if (it == pwallet->mapWallet.end()) {
2567 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, unknown transaction");
2570 const CWalletTx& trans = it->second;
2572 if (outpt.n >= trans.tx->vout.size()) {
2573 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout index out of bounds");
2576 if (pwallet->IsSpent(outpt.hash, outpt.n)) {
2577 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected unspent output");
2580 const bool is_locked = pwallet->IsLockedCoin(outpt.hash, outpt.n);
2582 if (fUnlock && !is_locked) {
2583 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected locked output");
2586 if (!fUnlock && is_locked) {
2587 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, output already locked");
2590 outputs.push_back(outpt);
2593 // Atomically set (un)locked status for the outputs.
2594 for (const COutPoint& outpt : outputs) {
2595 if (fUnlock) pwallet->UnlockCoin(outpt);
2596 else pwallet->LockCoin(outpt);
2599 return true;
2602 UniValue listlockunspent(const JSONRPCRequest& request)
2604 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2605 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2606 return NullUniValue;
2609 if (request.fHelp || request.params.size() > 0)
2610 throw std::runtime_error(
2611 "listlockunspent\n"
2612 "\nReturns list of temporarily unspendable outputs.\n"
2613 "See the lockunspent call to lock and unlock transactions for spending.\n"
2614 "\nResult:\n"
2615 "[\n"
2616 " {\n"
2617 " \"txid\" : \"transactionid\", (string) The transaction id locked\n"
2618 " \"vout\" : n (numeric) The vout value\n"
2619 " }\n"
2620 " ,...\n"
2621 "]\n"
2622 "\nExamples:\n"
2623 "\nList the unspent transactions\n"
2624 + HelpExampleCli("listunspent", "") +
2625 "\nLock an unspent transaction\n"
2626 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2627 "\nList the locked transactions\n"
2628 + HelpExampleCli("listlockunspent", "") +
2629 "\nUnlock the transaction again\n"
2630 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2631 "\nAs a json rpc call\n"
2632 + HelpExampleRpc("listlockunspent", "")
2635 ObserveSafeMode();
2636 LOCK2(cs_main, pwallet->cs_wallet);
2638 std::vector<COutPoint> vOutpts;
2639 pwallet->ListLockedCoins(vOutpts);
2641 UniValue ret(UniValue::VARR);
2643 for (COutPoint &outpt : vOutpts) {
2644 UniValue o(UniValue::VOBJ);
2646 o.push_back(Pair("txid", outpt.hash.GetHex()));
2647 o.push_back(Pair("vout", (int)outpt.n));
2648 ret.push_back(o);
2651 return ret;
2654 UniValue settxfee(const JSONRPCRequest& request)
2656 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2657 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2658 return NullUniValue;
2661 if (request.fHelp || request.params.size() < 1 || request.params.size() > 1)
2662 throw std::runtime_error(
2663 "settxfee amount\n"
2664 "\nSet the transaction fee per kB. Overwrites the paytxfee parameter.\n"
2665 "\nArguments:\n"
2666 "1. amount (numeric or string, required) The transaction fee in " + CURRENCY_UNIT + "/kB\n"
2667 "\nResult\n"
2668 "true|false (boolean) Returns true if successful\n"
2669 "\nExamples:\n"
2670 + HelpExampleCli("settxfee", "0.00001")
2671 + HelpExampleRpc("settxfee", "0.00001")
2674 LOCK2(cs_main, pwallet->cs_wallet);
2676 // Amount
2677 CAmount nAmount = AmountFromValue(request.params[0]);
2679 payTxFee = CFeeRate(nAmount, 1000);
2680 return true;
2683 UniValue getwalletinfo(const JSONRPCRequest& request)
2685 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2686 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2687 return NullUniValue;
2690 if (request.fHelp || request.params.size() != 0)
2691 throw std::runtime_error(
2692 "getwalletinfo\n"
2693 "Returns an object containing various wallet state info.\n"
2694 "\nResult:\n"
2695 "{\n"
2696 " \"walletname\": xxxxx, (string) the wallet name\n"
2697 " \"walletversion\": xxxxx, (numeric) the wallet version\n"
2698 " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
2699 " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
2700 " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + CURRENCY_UNIT + "\n"
2701 " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
2702 " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since Unix epoch) of the oldest pre-generated key in the key pool\n"
2703 " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated (only counts external keys)\n"
2704 " \"keypoolsize_hd_internal\": xxxx, (numeric) how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used)\n"
2705 " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
2706 " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n"
2707 " \"hdmasterkeyid\": \"<hash160>\" (string) the Hash160 of the HD master pubkey\n"
2708 "}\n"
2709 "\nExamples:\n"
2710 + HelpExampleCli("getwalletinfo", "")
2711 + HelpExampleRpc("getwalletinfo", "")
2714 ObserveSafeMode();
2716 // Make sure the results are valid at least up to the most recent block
2717 // the user could have gotten from another RPC command prior to now
2718 pwallet->BlockUntilSyncedToCurrentChain();
2720 LOCK2(cs_main, pwallet->cs_wallet);
2722 UniValue obj(UniValue::VOBJ);
2724 size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
2725 obj.push_back(Pair("walletname", pwallet->GetName()));
2726 obj.push_back(Pair("walletversion", pwallet->GetVersion()));
2727 obj.push_back(Pair("balance", ValueFromAmount(pwallet->GetBalance())));
2728 obj.push_back(Pair("unconfirmed_balance", ValueFromAmount(pwallet->GetUnconfirmedBalance())));
2729 obj.push_back(Pair("immature_balance", ValueFromAmount(pwallet->GetImmatureBalance())));
2730 obj.push_back(Pair("txcount", (int)pwallet->mapWallet.size()));
2731 obj.push_back(Pair("keypoololdest", pwallet->GetOldestKeyPoolTime()));
2732 obj.push_back(Pair("keypoolsize", (int64_t)kpExternalSize));
2733 CKeyID masterKeyID = pwallet->GetHDChain().masterKeyID;
2734 if (!masterKeyID.IsNull() && pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
2735 obj.push_back(Pair("keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize)));
2737 if (pwallet->IsCrypted()) {
2738 obj.push_back(Pair("unlocked_until", pwallet->nRelockTime));
2740 obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
2741 if (!masterKeyID.IsNull())
2742 obj.push_back(Pair("hdmasterkeyid", masterKeyID.GetHex()));
2743 return obj;
2746 UniValue listwallets(const JSONRPCRequest& request)
2748 if (request.fHelp || request.params.size() != 0)
2749 throw std::runtime_error(
2750 "listwallets\n"
2751 "Returns a list of currently loaded wallets.\n"
2752 "For full information on the wallet, use \"getwalletinfo\"\n"
2753 "\nResult:\n"
2754 "[ (json array of strings)\n"
2755 " \"walletname\" (string) the wallet name\n"
2756 " ...\n"
2757 "]\n"
2758 "\nExamples:\n"
2759 + HelpExampleCli("listwallets", "")
2760 + HelpExampleRpc("listwallets", "")
2763 UniValue obj(UniValue::VARR);
2765 for (CWalletRef pwallet : vpwallets) {
2767 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2768 return NullUniValue;
2771 LOCK(pwallet->cs_wallet);
2773 obj.push_back(pwallet->GetName());
2776 return obj;
2779 UniValue resendwallettransactions(const JSONRPCRequest& request)
2781 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2782 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2783 return NullUniValue;
2786 if (request.fHelp || request.params.size() != 0)
2787 throw std::runtime_error(
2788 "resendwallettransactions\n"
2789 "Immediately re-broadcast unconfirmed wallet transactions to all peers.\n"
2790 "Intended only for testing; the wallet code periodically re-broadcasts\n"
2791 "automatically.\n"
2792 "Returns an RPC error if -walletbroadcast is set to false.\n"
2793 "Returns array of transaction ids that were re-broadcast.\n"
2796 if (!g_connman)
2797 throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
2799 LOCK2(cs_main, pwallet->cs_wallet);
2801 if (!pwallet->GetBroadcastTransactions()) {
2802 throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet transaction broadcasting is disabled with -walletbroadcast");
2805 std::vector<uint256> txids = pwallet->ResendWalletTransactionsBefore(GetTime(), g_connman.get());
2806 UniValue result(UniValue::VARR);
2807 for (const uint256& txid : txids)
2809 result.push_back(txid.ToString());
2811 return result;
2814 UniValue listunspent(const JSONRPCRequest& request)
2816 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2817 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2818 return NullUniValue;
2821 if (request.fHelp || request.params.size() > 5)
2822 throw std::runtime_error(
2823 "listunspent ( minconf maxconf [\"addresses\",...] [include_unsafe] [query_options])\n"
2824 "\nReturns array of unspent transaction outputs\n"
2825 "with between minconf and maxconf (inclusive) confirmations.\n"
2826 "Optionally filter to only include txouts paid to specified addresses.\n"
2827 "\nArguments:\n"
2828 "1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n"
2829 "2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n"
2830 "3. \"addresses\" (string) A json array of bitcoin addresses to filter\n"
2831 " [\n"
2832 " \"address\" (string) bitcoin address\n"
2833 " ,...\n"
2834 " ]\n"
2835 "4. include_unsafe (bool, optional, default=true) Include outputs that are not safe to spend\n"
2836 " See description of \"safe\" attribute below.\n"
2837 "5. query_options (json, optional) JSON with query options\n"
2838 " {\n"
2839 " \"minimumAmount\" (numeric or string, default=0) Minimum value of each UTXO in " + CURRENCY_UNIT + "\n"
2840 " \"maximumAmount\" (numeric or string, default=unlimited) Maximum value of each UTXO in " + CURRENCY_UNIT + "\n"
2841 " \"maximumCount\" (numeric or string, default=unlimited) Maximum number of UTXOs\n"
2842 " \"minimumSumAmount\" (numeric or string, default=unlimited) Minimum sum value of all UTXOs in " + CURRENCY_UNIT + "\n"
2843 " }\n"
2844 "\nResult\n"
2845 "[ (array of json object)\n"
2846 " {\n"
2847 " \"txid\" : \"txid\", (string) the transaction id \n"
2848 " \"vout\" : n, (numeric) the vout value\n"
2849 " \"address\" : \"address\", (string) the bitcoin address\n"
2850 " \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n"
2851 " \"scriptPubKey\" : \"key\", (string) the script key\n"
2852 " \"amount\" : x.xxx, (numeric) the transaction output amount in " + CURRENCY_UNIT + "\n"
2853 " \"confirmations\" : n, (numeric) The number of confirmations\n"
2854 " \"redeemScript\" : n (string) The redeemScript if scriptPubKey is P2SH\n"
2855 " \"spendable\" : xxx, (bool) Whether we have the private keys to spend this output\n"
2856 " \"solvable\" : xxx, (bool) Whether we know how to spend this output, ignoring the lack of keys\n"
2857 " \"safe\" : xxx (bool) Whether this output is considered safe to spend. Unconfirmed transactions\n"
2858 " from outside keys and unconfirmed replacement transactions are considered unsafe\n"
2859 " and are not eligible for spending by fundrawtransaction and sendtoaddress.\n"
2860 " }\n"
2861 " ,...\n"
2862 "]\n"
2864 "\nExamples\n"
2865 + HelpExampleCli("listunspent", "")
2866 + HelpExampleCli("listunspent", "6 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
2867 + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
2868 + HelpExampleCli("listunspent", "6 9999999 '[]' true '{ \"minimumAmount\": 0.005 }'")
2869 + HelpExampleRpc("listunspent", "6, 9999999, [] , true, { \"minimumAmount\": 0.005 } ")
2872 ObserveSafeMode();
2874 int nMinDepth = 1;
2875 if (!request.params[0].isNull()) {
2876 RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
2877 nMinDepth = request.params[0].get_int();
2880 int nMaxDepth = 9999999;
2881 if (!request.params[1].isNull()) {
2882 RPCTypeCheckArgument(request.params[1], UniValue::VNUM);
2883 nMaxDepth = request.params[1].get_int();
2886 std::set<CTxDestination> destinations;
2887 if (!request.params[2].isNull()) {
2888 RPCTypeCheckArgument(request.params[2], UniValue::VARR);
2889 UniValue inputs = request.params[2].get_array();
2890 for (unsigned int idx = 0; idx < inputs.size(); idx++) {
2891 const UniValue& input = inputs[idx];
2892 CTxDestination dest = DecodeDestination(input.get_str());
2893 if (!IsValidDestination(dest)) {
2894 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + input.get_str());
2896 if (!destinations.insert(dest).second) {
2897 throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + input.get_str());
2902 bool include_unsafe = true;
2903 if (!request.params[3].isNull()) {
2904 RPCTypeCheckArgument(request.params[3], UniValue::VBOOL);
2905 include_unsafe = request.params[3].get_bool();
2908 CAmount nMinimumAmount = 0;
2909 CAmount nMaximumAmount = MAX_MONEY;
2910 CAmount nMinimumSumAmount = MAX_MONEY;
2911 uint64_t nMaximumCount = 0;
2913 if (!request.params[4].isNull()) {
2914 const UniValue& options = request.params[4].get_obj();
2916 if (options.exists("minimumAmount"))
2917 nMinimumAmount = AmountFromValue(options["minimumAmount"]);
2919 if (options.exists("maximumAmount"))
2920 nMaximumAmount = AmountFromValue(options["maximumAmount"]);
2922 if (options.exists("minimumSumAmount"))
2923 nMinimumSumAmount = AmountFromValue(options["minimumSumAmount"]);
2925 if (options.exists("maximumCount"))
2926 nMaximumCount = options["maximumCount"].get_int64();
2929 // Make sure the results are valid at least up to the most recent block
2930 // the user could have gotten from another RPC command prior to now
2931 pwallet->BlockUntilSyncedToCurrentChain();
2933 UniValue results(UniValue::VARR);
2934 std::vector<COutput> vecOutputs;
2935 LOCK2(cs_main, pwallet->cs_wallet);
2937 pwallet->AvailableCoins(vecOutputs, !include_unsafe, nullptr, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount, nMinDepth, nMaxDepth);
2938 for (const COutput& out : vecOutputs) {
2939 CTxDestination address;
2940 const CScript& scriptPubKey = out.tx->tx->vout[out.i].scriptPubKey;
2941 bool fValidAddress = ExtractDestination(scriptPubKey, address);
2943 if (destinations.size() && (!fValidAddress || !destinations.count(address)))
2944 continue;
2946 UniValue entry(UniValue::VOBJ);
2947 entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
2948 entry.push_back(Pair("vout", out.i));
2950 if (fValidAddress) {
2951 entry.push_back(Pair("address", EncodeDestination(address)));
2953 if (pwallet->mapAddressBook.count(address)) {
2954 entry.push_back(Pair("account", pwallet->mapAddressBook[address].name));
2957 if (scriptPubKey.IsPayToScriptHash()) {
2958 const CScriptID& hash = boost::get<CScriptID>(address);
2959 CScript redeemScript;
2960 if (pwallet->GetCScript(hash, redeemScript)) {
2961 entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
2966 entry.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
2967 entry.push_back(Pair("amount", ValueFromAmount(out.tx->tx->vout[out.i].nValue)));
2968 entry.push_back(Pair("confirmations", out.nDepth));
2969 entry.push_back(Pair("spendable", out.fSpendable));
2970 entry.push_back(Pair("solvable", out.fSolvable));
2971 entry.push_back(Pair("safe", out.fSafe));
2972 results.push_back(entry);
2975 return results;
2978 UniValue fundrawtransaction(const JSONRPCRequest& request)
2980 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
2981 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
2982 return NullUniValue;
2985 if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
2986 throw std::runtime_error(
2987 "fundrawtransaction \"hexstring\" ( options iswitness )\n"
2988 "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
2989 "This will not modify existing inputs, and will add at most one change output to the outputs.\n"
2990 "No existing outputs will be modified unless \"subtractFeeFromOutputs\" is specified.\n"
2991 "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
2992 "The inputs added will not be signed, use signrawtransaction for that.\n"
2993 "Note that all existing inputs must have their previous output transaction be in the wallet.\n"
2994 "Note that all inputs selected must be of standard form and P2SH scripts must be\n"
2995 "in the wallet using importaddress or addmultisigaddress (to calculate fees).\n"
2996 "You can see whether this is the case by checking the \"solvable\" field in the listunspent output.\n"
2997 "Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n"
2998 "\nArguments:\n"
2999 "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
3000 "2. options (object, optional)\n"
3001 " {\n"
3002 " \"changeAddress\" (string, optional, default pool address) The bitcoin address to receive the change\n"
3003 " \"changePosition\" (numeric, optional, default random) The index of the change output\n"
3004 " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n"
3005 " \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n"
3006 " \"feeRate\" (numeric, optional, default not set: makes wallet determine the fee) Set a specific fee rate in " + CURRENCY_UNIT + "/kB\n"
3007 " \"subtractFeeFromOutputs\" (array, optional) A json array of integers.\n"
3008 " The fee will be equally deducted from the amount of each specified output.\n"
3009 " The outputs are specified by their zero-based index, before any change output is added.\n"
3010 " Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
3011 " If no outputs are specified here, the sender pays the fee.\n"
3012 " [vout_index,...]\n"
3013 " \"replaceable\" (boolean, optional) Marks this transaction as BIP125 replaceable.\n"
3014 " Allows this transaction to be replaced by a transaction with higher fees\n"
3015 " \"conf_target\" (numeric, optional) Confirmation target (in blocks)\n"
3016 " \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n"
3017 " \"UNSET\"\n"
3018 " \"ECONOMICAL\"\n"
3019 " \"CONSERVATIVE\"\n"
3020 " }\n"
3021 " for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n"
3022 "3. iswitness (boolean, optional) Whether the transaction hex is a serialized witness transaction \n"
3023 " If iswitness is not present, heuristic tests will be used in decoding\n"
3025 "\nResult:\n"
3026 "{\n"
3027 " \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
3028 " \"fee\": n, (numeric) Fee in " + CURRENCY_UNIT + " the resulting transaction pays\n"
3029 " \"changepos\": n (numeric) The position of the added change output, or -1\n"
3030 "}\n"
3031 "\nExamples:\n"
3032 "\nCreate a transaction with no inputs\n"
3033 + HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") +
3034 "\nAdd sufficient unsigned inputs to meet the output value\n"
3035 + HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") +
3036 "\nSign the transaction\n"
3037 + HelpExampleCli("signrawtransaction", "\"fundedtransactionhex\"") +
3038 "\nSend the transaction\n"
3039 + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
3042 ObserveSafeMode();
3043 RPCTypeCheck(request.params, {UniValue::VSTR});
3045 // Make sure the results are valid at least up to the most recent block
3046 // the user could have gotten from another RPC command prior to now
3047 pwallet->BlockUntilSyncedToCurrentChain();
3049 CCoinControl coinControl;
3050 int changePosition = -1;
3051 bool lockUnspents = false;
3052 UniValue subtractFeeFromOutputs;
3053 std::set<int> setSubtractFeeFromOutputs;
3055 if (!request.params[1].isNull()) {
3056 if (request.params[1].type() == UniValue::VBOOL) {
3057 // backward compatibility bool only fallback
3058 coinControl.fAllowWatchOnly = request.params[1].get_bool();
3060 else {
3061 RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ, UniValue::VBOOL});
3063 UniValue options = request.params[1];
3065 RPCTypeCheckObj(options,
3067 {"changeAddress", UniValueType(UniValue::VSTR)},
3068 {"changePosition", UniValueType(UniValue::VNUM)},
3069 {"includeWatching", UniValueType(UniValue::VBOOL)},
3070 {"lockUnspents", UniValueType(UniValue::VBOOL)},
3071 {"reserveChangeKey", UniValueType(UniValue::VBOOL)}, // DEPRECATED (and ignored), should be removed in 0.16 or so.
3072 {"feeRate", UniValueType()}, // will be checked below
3073 {"subtractFeeFromOutputs", UniValueType(UniValue::VARR)},
3074 {"replaceable", UniValueType(UniValue::VBOOL)},
3075 {"conf_target", UniValueType(UniValue::VNUM)},
3076 {"estimate_mode", UniValueType(UniValue::VSTR)},
3078 true, true);
3080 if (options.exists("changeAddress")) {
3081 CTxDestination dest = DecodeDestination(options["changeAddress"].get_str());
3083 if (!IsValidDestination(dest)) {
3084 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "changeAddress must be a valid bitcoin address");
3087 coinControl.destChange = dest;
3090 if (options.exists("changePosition"))
3091 changePosition = options["changePosition"].get_int();
3093 if (options.exists("includeWatching"))
3094 coinControl.fAllowWatchOnly = options["includeWatching"].get_bool();
3096 if (options.exists("lockUnspents"))
3097 lockUnspents = options["lockUnspents"].get_bool();
3099 if (options.exists("feeRate"))
3101 coinControl.m_feerate = CFeeRate(AmountFromValue(options["feeRate"]));
3102 coinControl.fOverrideFeeRate = true;
3105 if (options.exists("subtractFeeFromOutputs"))
3106 subtractFeeFromOutputs = options["subtractFeeFromOutputs"].get_array();
3108 if (options.exists("replaceable")) {
3109 coinControl.signalRbf = options["replaceable"].get_bool();
3111 if (options.exists("conf_target")) {
3112 if (options.exists("feeRate")) {
3113 throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and feeRate");
3115 coinControl.m_confirm_target = ParseConfirmTarget(options["conf_target"]);
3117 if (options.exists("estimate_mode")) {
3118 if (options.exists("feeRate")) {
3119 throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both estimate_mode and feeRate");
3121 if (!FeeModeFromString(options["estimate_mode"].get_str(), coinControl.m_fee_mode)) {
3122 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter");
3128 // parse hex string from parameter
3129 CMutableTransaction tx;
3130 bool try_witness = request.params[2].isNull() ? true : request.params[2].get_bool();
3131 bool try_no_witness = request.params[2].isNull() ? true : !request.params[2].get_bool();
3132 if (!DecodeHexTx(tx, request.params[0].get_str(), try_no_witness, try_witness)) {
3133 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
3136 if (tx.vout.size() == 0)
3137 throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output");
3139 if (changePosition != -1 && (changePosition < 0 || (unsigned int)changePosition > tx.vout.size()))
3140 throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds");
3142 for (unsigned int idx = 0; idx < subtractFeeFromOutputs.size(); idx++) {
3143 int pos = subtractFeeFromOutputs[idx].get_int();
3144 if (setSubtractFeeFromOutputs.count(pos))
3145 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, duplicated position: %d", pos));
3146 if (pos < 0)
3147 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, negative position: %d", pos));
3148 if (pos >= int(tx.vout.size()))
3149 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, position too large: %d", pos));
3150 setSubtractFeeFromOutputs.insert(pos);
3153 CAmount nFeeOut;
3154 std::string strFailReason;
3156 if (!pwallet->FundTransaction(tx, nFeeOut, changePosition, strFailReason, lockUnspents, setSubtractFeeFromOutputs, coinControl)) {
3157 throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
3160 UniValue result(UniValue::VOBJ);
3161 result.push_back(Pair("hex", EncodeHexTx(tx)));
3162 result.push_back(Pair("changepos", changePosition));
3163 result.push_back(Pair("fee", ValueFromAmount(nFeeOut)));
3165 return result;
3168 UniValue bumpfee(const JSONRPCRequest& request)
3170 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3172 if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
3173 return NullUniValue;
3175 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
3176 throw std::runtime_error(
3177 "bumpfee \"txid\" ( options ) \n"
3178 "\nBumps the fee of an opt-in-RBF transaction T, replacing it with a new transaction B.\n"
3179 "An opt-in RBF transaction with the given txid must be in the wallet.\n"
3180 "The command will pay the additional fee by decreasing (or perhaps removing) its change output.\n"
3181 "If the change output is not big enough to cover the increased fee, the command will currently fail\n"
3182 "instead of adding new inputs to compensate. (A future implementation could improve this.)\n"
3183 "The command will fail if the wallet or mempool contains a transaction that spends one of T's outputs.\n"
3184 "By default, the new fee will be calculated automatically using estimatefee.\n"
3185 "The user can specify a confirmation target for estimatefee.\n"
3186 "Alternatively, the user can specify totalFee, or use RPC settxfee to set a higher fee rate.\n"
3187 "At a minimum, the new fee rate must be high enough to pay an additional new relay fee (incrementalfee\n"
3188 "returned by getnetworkinfo) to enter the node's mempool.\n"
3189 "\nArguments:\n"
3190 "1. txid (string, required) The txid to be bumped\n"
3191 "2. options (object, optional)\n"
3192 " {\n"
3193 " \"confTarget\" (numeric, optional) Confirmation target (in blocks)\n"
3194 " \"totalFee\" (numeric, optional) Total fee (NOT feerate) to pay, in satoshis.\n"
3195 " In rare cases, the actual fee paid might be slightly higher than the specified\n"
3196 " totalFee if the tx change output has to be removed because it is too close to\n"
3197 " the dust threshold.\n"
3198 " \"replaceable\" (boolean, optional, default true) Whether the new transaction should still be\n"
3199 " marked bip-125 replaceable. If true, the sequence numbers in the transaction will\n"
3200 " be left unchanged from the original. If false, any input sequence numbers in the\n"
3201 " original transaction that were less than 0xfffffffe will be increased to 0xfffffffe\n"
3202 " so the new transaction will not be explicitly bip-125 replaceable (though it may\n"
3203 " still be replaceable in practice, for example if it has unconfirmed ancestors which\n"
3204 " are replaceable).\n"
3205 " \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n"
3206 " \"UNSET\"\n"
3207 " \"ECONOMICAL\"\n"
3208 " \"CONSERVATIVE\"\n"
3209 " }\n"
3210 "\nResult:\n"
3211 "{\n"
3212 " \"txid\": \"value\", (string) The id of the new transaction\n"
3213 " \"origfee\": n, (numeric) Fee of the replaced transaction\n"
3214 " \"fee\": n, (numeric) Fee of the new transaction\n"
3215 " \"errors\": [ str... ] (json array of strings) Errors encountered during processing (may be empty)\n"
3216 "}\n"
3217 "\nExamples:\n"
3218 "\nBump the fee, get the new transaction\'s txid\n" +
3219 HelpExampleCli("bumpfee", "<txid>"));
3222 RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ});
3223 uint256 hash;
3224 hash.SetHex(request.params[0].get_str());
3226 // optional parameters
3227 CAmount totalFee = 0;
3228 CCoinControl coin_control;
3229 coin_control.signalRbf = true;
3230 if (!request.params[1].isNull()) {
3231 UniValue options = request.params[1];
3232 RPCTypeCheckObj(options,
3234 {"confTarget", UniValueType(UniValue::VNUM)},
3235 {"totalFee", UniValueType(UniValue::VNUM)},
3236 {"replaceable", UniValueType(UniValue::VBOOL)},
3237 {"estimate_mode", UniValueType(UniValue::VSTR)},
3239 true, true);
3241 if (options.exists("confTarget") && options.exists("totalFee")) {
3242 throw JSONRPCError(RPC_INVALID_PARAMETER, "confTarget and totalFee options should not both be set. Please provide either a confirmation target for fee estimation or an explicit total fee for the transaction.");
3243 } else if (options.exists("confTarget")) { // TODO: alias this to conf_target
3244 coin_control.m_confirm_target = ParseConfirmTarget(options["confTarget"]);
3245 } else if (options.exists("totalFee")) {
3246 totalFee = options["totalFee"].get_int64();
3247 if (totalFee <= 0) {
3248 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid totalFee %s (must be greater than 0)", FormatMoney(totalFee)));
3252 if (options.exists("replaceable")) {
3253 coin_control.signalRbf = options["replaceable"].get_bool();
3255 if (options.exists("estimate_mode")) {
3256 if (!FeeModeFromString(options["estimate_mode"].get_str(), coin_control.m_fee_mode)) {
3257 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter");
3262 // Make sure the results are valid at least up to the most recent block
3263 // the user could have gotten from another RPC command prior to now
3264 pwallet->BlockUntilSyncedToCurrentChain();
3266 LOCK2(cs_main, pwallet->cs_wallet);
3267 EnsureWalletIsUnlocked(pwallet);
3270 std::vector<std::string> errors;
3271 CAmount old_fee;
3272 CAmount new_fee;
3273 CMutableTransaction mtx;
3274 feebumper::Result res = feebumper::CreateTransaction(pwallet, hash, coin_control, totalFee, errors, old_fee, new_fee, mtx);
3275 if (res != feebumper::Result::OK) {
3276 switch(res) {
3277 case feebumper::Result::INVALID_ADDRESS_OR_KEY:
3278 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, errors[0]);
3279 break;
3280 case feebumper::Result::INVALID_REQUEST:
3281 throw JSONRPCError(RPC_INVALID_REQUEST, errors[0]);
3282 break;
3283 case feebumper::Result::INVALID_PARAMETER:
3284 throw JSONRPCError(RPC_INVALID_PARAMETER, errors[0]);
3285 break;
3286 case feebumper::Result::WALLET_ERROR:
3287 throw JSONRPCError(RPC_WALLET_ERROR, errors[0]);
3288 break;
3289 default:
3290 throw JSONRPCError(RPC_MISC_ERROR, errors[0]);
3291 break;
3295 // sign bumped transaction
3296 if (!feebumper::SignTransaction(pwallet, mtx)) {
3297 throw JSONRPCError(RPC_WALLET_ERROR, "Can't sign transaction.");
3299 // commit the bumped transaction
3300 uint256 txid;
3301 if (feebumper::CommitTransaction(pwallet, hash, std::move(mtx), errors, txid) != feebumper::Result::OK) {
3302 throw JSONRPCError(RPC_WALLET_ERROR, errors[0]);
3304 UniValue result(UniValue::VOBJ);
3305 result.push_back(Pair("txid", txid.GetHex()));
3306 result.push_back(Pair("origfee", ValueFromAmount(old_fee)));
3307 result.push_back(Pair("fee", ValueFromAmount(new_fee)));
3308 UniValue result_errors(UniValue::VARR);
3309 for (const std::string& error : errors) {
3310 result_errors.push_back(error);
3312 result.push_back(Pair("errors", result_errors));
3314 return result;
3317 UniValue generate(const JSONRPCRequest& request)
3319 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3321 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
3322 return NullUniValue;
3325 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
3326 throw std::runtime_error(
3327 "generate nblocks ( maxtries )\n"
3328 "\nMine up to nblocks blocks immediately (before the RPC call returns) to an address in the wallet.\n"
3329 "\nArguments:\n"
3330 "1. nblocks (numeric, required) How many blocks are generated immediately.\n"
3331 "2. maxtries (numeric, optional) How many iterations to try (default = 1000000).\n"
3332 "\nResult:\n"
3333 "[ blockhashes ] (array) hashes of blocks generated\n"
3334 "\nExamples:\n"
3335 "\nGenerate 11 blocks\n"
3336 + HelpExampleCli("generate", "11")
3340 int num_generate = request.params[0].get_int();
3341 uint64_t max_tries = 1000000;
3342 if (!request.params[1].isNull()) {
3343 max_tries = request.params[1].get_int();
3346 std::shared_ptr<CReserveScript> coinbase_script;
3347 pwallet->GetScriptForMining(coinbase_script);
3349 // If the keypool is exhausted, no script is returned at all. Catch this.
3350 if (!coinbase_script) {
3351 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
3354 //throw an error if no script was provided
3355 if (coinbase_script->reserveScript.empty()) {
3356 throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available");
3359 return generateBlocks(coinbase_script, num_generate, max_tries, true);
3362 UniValue rescanblockchain(const JSONRPCRequest& request)
3364 CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
3365 if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
3366 return NullUniValue;
3369 if (request.fHelp || request.params.size() > 2) {
3370 throw std::runtime_error(
3371 "rescanblockchain (\"start_height\") (\"stop_height\")\n"
3372 "\nRescan the local blockchain for wallet related transactions.\n"
3373 "\nArguments:\n"
3374 "1. \"start_height\" (numeric, optional) block height where the rescan should start\n"
3375 "2. \"stop_height\" (numeric, optional) the last block height that should be scanned\n"
3376 "\nResult:\n"
3377 "{\n"
3378 " \"start_height\" (numeric) The block height where the rescan has started. If omitted, rescan started from the genesis block.\n"
3379 " \"stop_height\" (numeric) The height of the last rescanned block. If omitted, rescan stopped at the chain tip.\n"
3380 "}\n"
3381 "\nExamples:\n"
3382 + HelpExampleCli("rescanblockchain", "100000 120000")
3383 + HelpExampleRpc("rescanblockchain", "100000, 120000")
3387 LOCK2(cs_main, pwallet->cs_wallet);
3389 CBlockIndex *pindexStart = chainActive.Genesis();
3390 CBlockIndex *pindexStop = nullptr;
3391 if (!request.params[0].isNull()) {
3392 pindexStart = chainActive[request.params[0].get_int()];
3393 if (!pindexStart) {
3394 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid start_height");
3398 if (!request.params[1].isNull()) {
3399 pindexStop = chainActive[request.params[1].get_int()];
3400 if (!pindexStop) {
3401 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid stop_height");
3403 else if (pindexStop->nHeight < pindexStart->nHeight) {
3404 throw JSONRPCError(RPC_INVALID_PARAMETER, "stop_height must be greater then start_height");
3408 // We can't rescan beyond non-pruned blocks, stop and throw an error
3409 if (fPruneMode) {
3410 CBlockIndex *block = pindexStop ? pindexStop : chainActive.Tip();
3411 while (block && block->nHeight >= pindexStart->nHeight) {
3412 if (!(block->nStatus & BLOCK_HAVE_DATA)) {
3413 throw JSONRPCError(RPC_MISC_ERROR, "Can't rescan beyond pruned data. Use RPC call getblockchaininfo to determine your pruned height.");
3415 block = block->pprev;
3419 CBlockIndex *stopBlock = pwallet->ScanForWalletTransactions(pindexStart, pindexStop, true);
3420 if (!stopBlock) {
3421 if (pwallet->IsAbortingRescan()) {
3422 throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted.");
3424 // if we got a nullptr returned, ScanForWalletTransactions did rescan up to the requested stopindex
3425 stopBlock = pindexStop ? pindexStop : chainActive.Tip();
3427 else {
3428 throw JSONRPCError(RPC_MISC_ERROR, "Rescan failed. Potentially corrupted data files.");
3431 UniValue response(UniValue::VOBJ);
3432 response.pushKV("start_height", pindexStart->nHeight);
3433 response.pushKV("stop_height", stopBlock->nHeight);
3434 return response;
3437 extern UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp
3438 extern UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
3439 extern UniValue importprivkey(const JSONRPCRequest& request);
3440 extern UniValue importaddress(const JSONRPCRequest& request);
3441 extern UniValue importpubkey(const JSONRPCRequest& request);
3442 extern UniValue dumpwallet(const JSONRPCRequest& request);
3443 extern UniValue importwallet(const JSONRPCRequest& request);
3444 extern UniValue importprunedfunds(const JSONRPCRequest& request);
3445 extern UniValue removeprunedfunds(const JSONRPCRequest& request);
3446 extern UniValue importmulti(const JSONRPCRequest& request);
3447 extern UniValue rescanblockchain(const JSONRPCRequest& request);
3449 static const CRPCCommand commands[] =
3450 { // category name actor (function) argNames
3451 // --------------------- ------------------------ ----------------------- ----------
3452 { "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options","iswitness"} },
3453 { "hidden", "resendwallettransactions", &resendwallettransactions, {} },
3454 { "wallet", "abandontransaction", &abandontransaction, {"txid"} },
3455 { "wallet", "abortrescan", &abortrescan, {} },
3456 { "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","account"} },
3457 { "wallet", "addwitnessaddress", &addwitnessaddress, {"address","p2sh"} },
3458 { "wallet", "backupwallet", &backupwallet, {"destination"} },
3459 { "wallet", "bumpfee", &bumpfee, {"txid", "options"} },
3460 { "wallet", "dumpprivkey", &dumpprivkey, {"address"} },
3461 { "wallet", "dumpwallet", &dumpwallet, {"filename"} },
3462 { "wallet", "encryptwallet", &encryptwallet, {"passphrase"} },
3463 { "wallet", "getaccountaddress", &getaccountaddress, {"account"} },
3464 { "wallet", "getaccount", &getaccount, {"address"} },
3465 { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, {"account"} },
3466 { "wallet", "getbalance", &getbalance, {"account","minconf","include_watchonly"} },
3467 { "wallet", "getnewaddress", &getnewaddress, {"account"} },
3468 { "wallet", "getrawchangeaddress", &getrawchangeaddress, {} },
3469 { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, {"account","minconf"} },
3470 { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, {"address","minconf"} },
3471 { "wallet", "gettransaction", &gettransaction, {"txid","include_watchonly"} },
3472 { "wallet", "getunconfirmedbalance", &getunconfirmedbalance, {} },
3473 { "wallet", "getwalletinfo", &getwalletinfo, {} },
3474 { "wallet", "importmulti", &importmulti, {"requests","options"} },
3475 { "wallet", "importprivkey", &importprivkey, {"privkey","label","rescan"} },
3476 { "wallet", "importwallet", &importwallet, {"filename"} },
3477 { "wallet", "importaddress", &importaddress, {"address","label","rescan","p2sh"} },
3478 { "wallet", "importprunedfunds", &importprunedfunds, {"rawtransaction","txoutproof"} },
3479 { "wallet", "importpubkey", &importpubkey, {"pubkey","label","rescan"} },
3480 { "wallet", "keypoolrefill", &keypoolrefill, {"newsize"} },
3481 { "wallet", "listaccounts", &listaccounts, {"minconf","include_watchonly"} },
3482 { "wallet", "listaddressgroupings", &listaddressgroupings, {} },
3483 { "wallet", "listlockunspent", &listlockunspent, {} },
3484 { "wallet", "listreceivedbyaccount", &listreceivedbyaccount, {"minconf","include_empty","include_watchonly"} },
3485 { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, {"minconf","include_empty","include_watchonly"} },
3486 { "wallet", "listsinceblock", &listsinceblock, {"blockhash","target_confirmations","include_watchonly","include_removed"} },
3487 { "wallet", "listtransactions", &listtransactions, {"account","count","skip","include_watchonly"} },
3488 { "wallet", "listunspent", &listunspent, {"minconf","maxconf","addresses","include_unsafe","query_options"} },
3489 { "wallet", "listwallets", &listwallets, {} },
3490 { "wallet", "lockunspent", &lockunspent, {"unlock","transactions"} },
3491 { "wallet", "move", &movecmd, {"fromaccount","toaccount","amount","minconf","comment"} },
3492 { "wallet", "sendfrom", &sendfrom, {"fromaccount","toaddress","amount","minconf","comment","comment_to"} },
3493 { "wallet", "sendmany", &sendmany, {"fromaccount","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode"} },
3494 { "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode"} },
3495 { "wallet", "setaccount", &setaccount, {"address","account"} },
3496 { "wallet", "settxfee", &settxfee, {"amount"} },
3497 { "wallet", "signmessage", &signmessage, {"address","message"} },
3498 { "wallet", "walletlock", &walletlock, {} },
3499 { "wallet", "walletpassphrasechange", &walletpassphrasechange, {"oldpassphrase","newpassphrase"} },
3500 { "wallet", "walletpassphrase", &walletpassphrase, {"passphrase","timeout"} },
3501 { "wallet", "removeprunedfunds", &removeprunedfunds, {"txid"} },
3502 { "wallet", "rescanblockchain", &rescanblockchain, {"start_height", "stop_height"} },
3504 { "generating", "generate", &generate, {"nblocks","maxtries"} },
3507 void RegisterWalletRPCCommands(CRPCTable &t)
3509 for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
3510 t.appendCommand(commands[vcidx].name, &commands[vcidx]);