[trivial] Fix recently introduced typos in comments
[bitcoinplatinum.git] / src / wallet / rpcwallet.cpp
blob01005bf3380c2c9bcb27474e975e5696ce70d8c9
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 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 "init.h"
12 #include "validation.h"
13 #include "net.h"
14 #include "policy/policy.h"
15 #include "policy/rbf.h"
16 #include "rpc/server.h"
17 #include "script/sign.h"
18 #include "timedata.h"
19 #include "util.h"
20 #include "utilmoneystr.h"
21 #include "wallet.h"
22 #include "walletdb.h"
24 #include <stdint.h>
26 #include <boost/assign/list_of.hpp>
28 #include <univalue.h>
30 using namespace std;
32 int64_t nWalletUnlockTime;
33 static CCriticalSection cs_nWalletUnlockTime;
35 std::string HelpRequiringPassphrase()
37 return pwalletMain && pwalletMain->IsCrypted()
38 ? "\nRequires wallet passphrase to be set with walletpassphrase call."
39 : "";
42 bool EnsureWalletIsAvailable(bool avoidException)
44 if (!pwalletMain)
46 if (!avoidException)
47 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
48 else
49 return false;
51 return true;
54 void EnsureWalletIsUnlocked()
56 if (pwalletMain->IsLocked())
57 throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
60 void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
62 int confirms = wtx.GetDepthInMainChain();
63 entry.push_back(Pair("confirmations", confirms));
64 if (wtx.IsCoinBase())
65 entry.push_back(Pair("generated", true));
66 if (confirms > 0)
68 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
69 entry.push_back(Pair("blockindex", wtx.nIndex));
70 entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
71 } else {
72 entry.push_back(Pair("trusted", wtx.IsTrusted()));
74 uint256 hash = wtx.GetHash();
75 entry.push_back(Pair("txid", hash.GetHex()));
76 UniValue conflicts(UniValue::VARR);
77 BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
78 conflicts.push_back(conflict.GetHex());
79 entry.push_back(Pair("walletconflicts", conflicts));
80 entry.push_back(Pair("time", wtx.GetTxTime()));
81 entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived));
83 // Add opt-in RBF status
84 std::string rbfStatus = "no";
85 if (confirms <= 0) {
86 LOCK(mempool.cs);
87 RBFTransactionState rbfState = IsRBFOptIn(wtx, mempool);
88 if (rbfState == RBF_TRANSACTIONSTATE_UNKNOWN)
89 rbfStatus = "unknown";
90 else if (rbfState == RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125)
91 rbfStatus = "yes";
93 entry.push_back(Pair("bip125-replaceable", rbfStatus));
95 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
96 entry.push_back(Pair(item.first, item.second));
99 string AccountFromValue(const UniValue& value)
101 string strAccount = value.get_str();
102 if (strAccount == "*")
103 throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Invalid account name");
104 return strAccount;
107 UniValue getnewaddress(const JSONRPCRequest& request)
109 if (!EnsureWalletIsAvailable(request.fHelp))
110 return NullUniValue;
112 if (request.fHelp || request.params.size() > 1)
113 throw runtime_error(
114 "getnewaddress ( \"account\" )\n"
115 "\nReturns a new Bitcoin address for receiving payments.\n"
116 "If 'account' is specified (DEPRECATED), it is added to the address book \n"
117 "so payments received with the address will be credited to 'account'.\n"
118 "\nArguments:\n"
119 "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"
120 "\nResult:\n"
121 "\"address\" (string) The new bitcoin address\n"
122 "\nExamples:\n"
123 + HelpExampleCli("getnewaddress", "")
124 + HelpExampleRpc("getnewaddress", "")
127 LOCK2(cs_main, pwalletMain->cs_wallet);
129 // Parse the account first so we don't generate a key if there's an error
130 string strAccount;
131 if (request.params.size() > 0)
132 strAccount = AccountFromValue(request.params[0]);
134 if (!pwalletMain->IsLocked())
135 pwalletMain->TopUpKeyPool();
137 // Generate a new key that is added to wallet
138 CPubKey newKey;
139 if (!pwalletMain->GetKeyFromPool(newKey))
140 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
141 CKeyID keyID = newKey.GetID();
143 pwalletMain->SetAddressBook(keyID, strAccount, "receive");
145 return CBitcoinAddress(keyID).ToString();
149 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
151 CPubKey pubKey;
152 if (!pwalletMain->GetAccountPubkey(pubKey, strAccount, bForceNew)) {
153 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
156 return CBitcoinAddress(pubKey.GetID());
159 UniValue getaccountaddress(const JSONRPCRequest& request)
161 if (!EnsureWalletIsAvailable(request.fHelp))
162 return NullUniValue;
164 if (request.fHelp || request.params.size() != 1)
165 throw runtime_error(
166 "getaccountaddress \"account\"\n"
167 "\nDEPRECATED. Returns the current Bitcoin address for receiving payments to this account.\n"
168 "\nArguments:\n"
169 "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"
170 "\nResult:\n"
171 "\"address\" (string) The account bitcoin address\n"
172 "\nExamples:\n"
173 + HelpExampleCli("getaccountaddress", "")
174 + HelpExampleCli("getaccountaddress", "\"\"")
175 + HelpExampleCli("getaccountaddress", "\"myaccount\"")
176 + HelpExampleRpc("getaccountaddress", "\"myaccount\"")
179 LOCK2(cs_main, pwalletMain->cs_wallet);
181 // Parse the account first so we don't generate a key if there's an error
182 string strAccount = AccountFromValue(request.params[0]);
184 UniValue ret(UniValue::VSTR);
186 ret = GetAccountAddress(strAccount).ToString();
187 return ret;
191 UniValue getrawchangeaddress(const JSONRPCRequest& request)
193 if (!EnsureWalletIsAvailable(request.fHelp))
194 return NullUniValue;
196 if (request.fHelp || request.params.size() > 1)
197 throw runtime_error(
198 "getrawchangeaddress\n"
199 "\nReturns a new Bitcoin address, for receiving change.\n"
200 "This is for use with raw transactions, NOT normal use.\n"
201 "\nResult:\n"
202 "\"address\" (string) The address\n"
203 "\nExamples:\n"
204 + HelpExampleCli("getrawchangeaddress", "")
205 + HelpExampleRpc("getrawchangeaddress", "")
208 LOCK2(cs_main, pwalletMain->cs_wallet);
210 if (!pwalletMain->IsLocked())
211 pwalletMain->TopUpKeyPool();
213 CReserveKey reservekey(pwalletMain);
214 CPubKey vchPubKey;
215 if (!reservekey.GetReservedKey(vchPubKey))
216 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
218 reservekey.KeepKey();
220 CKeyID keyID = vchPubKey.GetID();
222 return CBitcoinAddress(keyID).ToString();
226 UniValue setaccount(const JSONRPCRequest& request)
228 if (!EnsureWalletIsAvailable(request.fHelp))
229 return NullUniValue;
231 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
232 throw runtime_error(
233 "setaccount \"address\" \"account\"\n"
234 "\nDEPRECATED. Sets the account associated with the given address.\n"
235 "\nArguments:\n"
236 "1. \"address\" (string, required) The bitcoin address to be associated with an account.\n"
237 "2. \"account\" (string, required) The account to assign the address to.\n"
238 "\nExamples:\n"
239 + HelpExampleCli("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"tabby\"")
240 + HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"tabby\"")
243 LOCK2(cs_main, pwalletMain->cs_wallet);
245 CBitcoinAddress address(request.params[0].get_str());
246 if (!address.IsValid())
247 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
249 string strAccount;
250 if (request.params.size() > 1)
251 strAccount = AccountFromValue(request.params[1]);
253 // Only add the account if the address is yours.
254 if (IsMine(*pwalletMain, address.Get()))
256 // Detect when changing the account of an address that is the 'unused current key' of another account:
257 if (pwalletMain->mapAddressBook.count(address.Get()))
259 string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name;
260 if (address == GetAccountAddress(strOldAccount))
261 GetAccountAddress(strOldAccount, true);
263 pwalletMain->SetAddressBook(address.Get(), strAccount, "receive");
265 else
266 throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
268 return NullUniValue;
272 UniValue getaccount(const JSONRPCRequest& request)
274 if (!EnsureWalletIsAvailable(request.fHelp))
275 return NullUniValue;
277 if (request.fHelp || request.params.size() != 1)
278 throw runtime_error(
279 "getaccount \"address\"\n"
280 "\nDEPRECATED. Returns the account associated with the given address.\n"
281 "\nArguments:\n"
282 "1. \"address\" (string, required) The bitcoin address for account lookup.\n"
283 "\nResult:\n"
284 "\"accountname\" (string) the account address\n"
285 "\nExamples:\n"
286 + HelpExampleCli("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
287 + HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
290 LOCK2(cs_main, pwalletMain->cs_wallet);
292 CBitcoinAddress address(request.params[0].get_str());
293 if (!address.IsValid())
294 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
296 string strAccount;
297 map<CTxDestination, CAddressBookData>::iterator mi = pwalletMain->mapAddressBook.find(address.Get());
298 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty())
299 strAccount = (*mi).second.name;
300 return strAccount;
304 UniValue getaddressesbyaccount(const JSONRPCRequest& request)
306 if (!EnsureWalletIsAvailable(request.fHelp))
307 return NullUniValue;
309 if (request.fHelp || request.params.size() != 1)
310 throw runtime_error(
311 "getaddressesbyaccount \"account\"\n"
312 "\nDEPRECATED. Returns the list of addresses for the given account.\n"
313 "\nArguments:\n"
314 "1. \"account\" (string, required) The account name.\n"
315 "\nResult:\n"
316 "[ (json array of string)\n"
317 " \"address\" (string) a bitcoin address associated with the given account\n"
318 " ,...\n"
319 "]\n"
320 "\nExamples:\n"
321 + HelpExampleCli("getaddressesbyaccount", "\"tabby\"")
322 + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
325 LOCK2(cs_main, pwalletMain->cs_wallet);
327 string strAccount = AccountFromValue(request.params[0]);
329 // Find all addresses that have the given account
330 UniValue ret(UniValue::VARR);
331 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
333 const CBitcoinAddress& address = item.first;
334 const string& strName = item.second.name;
335 if (strName == strAccount)
336 ret.push_back(address.ToString());
338 return ret;
341 static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew)
343 CAmount curBalance = pwalletMain->GetBalance();
345 // Check amount
346 if (nValue <= 0)
347 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid amount");
349 if (nValue > curBalance)
350 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
352 if (pwalletMain->GetBroadcastTransactions() && !g_connman)
353 throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
355 // Parse Bitcoin address
356 CScript scriptPubKey = GetScriptForDestination(address);
358 // Create and send the transaction
359 CReserveKey reservekey(pwalletMain);
360 CAmount nFeeRequired;
361 std::string strError;
362 vector<CRecipient> vecSend;
363 int nChangePosRet = -1;
364 CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
365 vecSend.push_back(recipient);
366 if (!pwalletMain->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError)) {
367 if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
368 strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired));
369 throw JSONRPCError(RPC_WALLET_ERROR, strError);
371 CValidationState state;
372 if (!pwalletMain->CommitTransaction(wtxNew, reservekey, g_connman.get(), state)) {
373 strError = strprintf("Error: The transaction was rejected! Reason given: %s", state.GetRejectReason());
374 throw JSONRPCError(RPC_WALLET_ERROR, strError);
378 UniValue sendtoaddress(const JSONRPCRequest& request)
380 if (!EnsureWalletIsAvailable(request.fHelp))
381 return NullUniValue;
383 if (request.fHelp || request.params.size() < 2 || request.params.size() > 5)
384 throw runtime_error(
385 "sendtoaddress \"address\" amount ( \"comment\" \"comment_to\" subtractfeefromamount )\n"
386 "\nSend an amount to a given address.\n"
387 + HelpRequiringPassphrase() +
388 "\nArguments:\n"
389 "1. \"address\" (string, required) The bitcoin address to send to.\n"
390 "2. \"amount\" (numeric or string, required) The amount in " + CURRENCY_UNIT + " to send. eg 0.1\n"
391 "3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
392 " This is not part of the transaction, just kept in your wallet.\n"
393 "4. \"comment_to\" (string, optional) A comment to store the name of the person or organization \n"
394 " to which you're sending the transaction. This is not part of the \n"
395 " transaction, just kept in your wallet.\n"
396 "5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
397 " The recipient will receive less bitcoins than you enter in the amount field.\n"
398 "\nResult:\n"
399 "\"txid\" (string) The transaction id.\n"
400 "\nExamples:\n"
401 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
402 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
403 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true")
404 + HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
407 LOCK2(cs_main, pwalletMain->cs_wallet);
409 CBitcoinAddress address(request.params[0].get_str());
410 if (!address.IsValid())
411 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
413 // Amount
414 CAmount nAmount = AmountFromValue(request.params[1]);
415 if (nAmount <= 0)
416 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
418 // Wallet comments
419 CWalletTx wtx;
420 if (request.params.size() > 2 && !request.params[2].isNull() && !request.params[2].get_str().empty())
421 wtx.mapValue["comment"] = request.params[2].get_str();
422 if (request.params.size() > 3 && !request.params[3].isNull() && !request.params[3].get_str().empty())
423 wtx.mapValue["to"] = request.params[3].get_str();
425 bool fSubtractFeeFromAmount = false;
426 if (request.params.size() > 4)
427 fSubtractFeeFromAmount = request.params[4].get_bool();
429 EnsureWalletIsUnlocked();
431 SendMoney(address.Get(), nAmount, fSubtractFeeFromAmount, wtx);
433 return wtx.GetHash().GetHex();
436 UniValue listaddressgroupings(const JSONRPCRequest& request)
438 if (!EnsureWalletIsAvailable(request.fHelp))
439 return NullUniValue;
441 if (request.fHelp)
442 throw runtime_error(
443 "listaddressgroupings\n"
444 "\nLists groups of addresses which have had their common ownership\n"
445 "made public by common use as inputs or as the resulting change\n"
446 "in past transactions\n"
447 "\nResult:\n"
448 "[\n"
449 " [\n"
450 " [\n"
451 " \"address\", (string) The bitcoin address\n"
452 " amount, (numeric) The amount in " + CURRENCY_UNIT + "\n"
453 " \"account\" (string, optional) DEPRECATED. The account\n"
454 " ]\n"
455 " ,...\n"
456 " ]\n"
457 " ,...\n"
458 "]\n"
459 "\nExamples:\n"
460 + HelpExampleCli("listaddressgroupings", "")
461 + HelpExampleRpc("listaddressgroupings", "")
464 LOCK2(cs_main, pwalletMain->cs_wallet);
466 UniValue jsonGroupings(UniValue::VARR);
467 map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
468 BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
470 UniValue jsonGrouping(UniValue::VARR);
471 BOOST_FOREACH(CTxDestination address, grouping)
473 UniValue addressInfo(UniValue::VARR);
474 addressInfo.push_back(CBitcoinAddress(address).ToString());
475 addressInfo.push_back(ValueFromAmount(balances[address]));
477 if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end())
478 addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second.name);
480 jsonGrouping.push_back(addressInfo);
482 jsonGroupings.push_back(jsonGrouping);
484 return jsonGroupings;
487 UniValue signmessage(const JSONRPCRequest& request)
489 if (!EnsureWalletIsAvailable(request.fHelp))
490 return NullUniValue;
492 if (request.fHelp || request.params.size() != 2)
493 throw runtime_error(
494 "signmessage \"address\" \"message\"\n"
495 "\nSign a message with the private key of an address"
496 + HelpRequiringPassphrase() + "\n"
497 "\nArguments:\n"
498 "1. \"address\" (string, required) The bitcoin address to use for the private key.\n"
499 "2. \"message\" (string, required) The message to create a signature of.\n"
500 "\nResult:\n"
501 "\"signature\" (string) The signature of the message encoded in base 64\n"
502 "\nExamples:\n"
503 "\nUnlock the wallet for 30 seconds\n"
504 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
505 "\nCreate the signature\n"
506 + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
507 "\nVerify the signature\n"
508 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
509 "\nAs json rpc\n"
510 + HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"my message\"")
513 LOCK2(cs_main, pwalletMain->cs_wallet);
515 EnsureWalletIsUnlocked();
517 string strAddress = request.params[0].get_str();
518 string strMessage = request.params[1].get_str();
520 CBitcoinAddress addr(strAddress);
521 if (!addr.IsValid())
522 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
524 CKeyID keyID;
525 if (!addr.GetKeyID(keyID))
526 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
528 CKey key;
529 if (!pwalletMain->GetKey(keyID, key))
530 throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
532 CHashWriter ss(SER_GETHASH, 0);
533 ss << strMessageMagic;
534 ss << strMessage;
536 vector<unsigned char> vchSig;
537 if (!key.SignCompact(ss.GetHash(), vchSig))
538 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
540 return EncodeBase64(&vchSig[0], vchSig.size());
543 UniValue getreceivedbyaddress(const JSONRPCRequest& request)
545 if (!EnsureWalletIsAvailable(request.fHelp))
546 return NullUniValue;
548 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
549 throw runtime_error(
550 "getreceivedbyaddress \"address\" ( minconf )\n"
551 "\nReturns the total amount received by the given address in transactions with at least minconf confirmations.\n"
552 "\nArguments:\n"
553 "1. \"address\" (string, required) The bitcoin address for transactions.\n"
554 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
555 "\nResult:\n"
556 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received at this address.\n"
557 "\nExamples:\n"
558 "\nThe amount from transactions with at least 1 confirmation\n"
559 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"") +
560 "\nThe amount including unconfirmed transactions, zero confirmations\n"
561 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 0") +
562 "\nThe amount with at least 6 confirmation, very safe\n"
563 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 6") +
564 "\nAs a json rpc call\n"
565 + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", 6")
568 LOCK2(cs_main, pwalletMain->cs_wallet);
570 // Bitcoin address
571 CBitcoinAddress address = CBitcoinAddress(request.params[0].get_str());
572 if (!address.IsValid())
573 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
574 CScript scriptPubKey = GetScriptForDestination(address.Get());
575 if (!IsMine(*pwalletMain, scriptPubKey))
576 return ValueFromAmount(0);
578 // Minimum confirmations
579 int nMinDepth = 1;
580 if (request.params.size() > 1)
581 nMinDepth = request.params[1].get_int();
583 // Tally
584 CAmount nAmount = 0;
585 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
587 const CWalletTx& wtx = (*it).second;
588 if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
589 continue;
591 BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
592 if (txout.scriptPubKey == scriptPubKey)
593 if (wtx.GetDepthInMainChain() >= nMinDepth)
594 nAmount += txout.nValue;
597 return ValueFromAmount(nAmount);
601 UniValue getreceivedbyaccount(const JSONRPCRequest& request)
603 if (!EnsureWalletIsAvailable(request.fHelp))
604 return NullUniValue;
606 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
607 throw runtime_error(
608 "getreceivedbyaccount \"account\" ( minconf )\n"
609 "\nDEPRECATED. Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
610 "\nArguments:\n"
611 "1. \"account\" (string, required) The selected account, may be the default account using \"\".\n"
612 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
613 "\nResult:\n"
614 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
615 "\nExamples:\n"
616 "\nAmount received by the default account with at least 1 confirmation\n"
617 + HelpExampleCli("getreceivedbyaccount", "\"\"") +
618 "\nAmount received at the tabby account including unconfirmed amounts with zero confirmations\n"
619 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 0") +
620 "\nThe amount with at least 6 confirmation, very safe\n"
621 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 6") +
622 "\nAs a json rpc call\n"
623 + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
626 LOCK2(cs_main, pwalletMain->cs_wallet);
628 // Minimum confirmations
629 int nMinDepth = 1;
630 if (request.params.size() > 1)
631 nMinDepth = request.params[1].get_int();
633 // Get the set of pub keys assigned to account
634 string strAccount = AccountFromValue(request.params[0]);
635 set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount);
637 // Tally
638 CAmount nAmount = 0;
639 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
641 const CWalletTx& wtx = (*it).second;
642 if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
643 continue;
645 BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
647 CTxDestination address;
648 if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
649 if (wtx.GetDepthInMainChain() >= nMinDepth)
650 nAmount += txout.nValue;
654 return ValueFromAmount(nAmount);
658 UniValue getbalance(const JSONRPCRequest& request)
660 if (!EnsureWalletIsAvailable(request.fHelp))
661 return NullUniValue;
663 if (request.fHelp || request.params.size() > 3)
664 throw runtime_error(
665 "getbalance ( \"account\" minconf include_watchonly )\n"
666 "\nIf account is not specified, returns the server's total available balance.\n"
667 "If account is specified (DEPRECATED), returns the balance in the account.\n"
668 "Note that the account \"\" is not the same as leaving the parameter out.\n"
669 "The server total may be different to the balance in the default \"\" account.\n"
670 "\nArguments:\n"
671 "1. \"account\" (string, optional) DEPRECATED. The account string may be given as a\n"
672 " specific account name to find the balance associated with wallet keys in\n"
673 " a named account, or as the empty string (\"\") to find the balance\n"
674 " associated with wallet keys not in any named account, or as \"*\" to find\n"
675 " the balance associated with all wallet keys regardless of account.\n"
676 " When this option is specified, it calculates the balance in a different\n"
677 " way than when it is not specified, and which can count spends twice when\n"
678 " there are conflicting pending transactions (such as those created by\n"
679 " the bumpfee command), temporarily resulting in low or even negative\n"
680 " balances. In general, account balance calculation is not considered\n"
681 " reliable and has resulted in confusing outcomes, so it is recommended to\n"
682 " avoid passing this argument.\n"
683 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
684 "3. include_watchonly (bool, optional, default=false) Also include balance in watch-only addresses (see 'importaddress')\n"
685 "\nResult:\n"
686 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
687 "\nExamples:\n"
688 "\nThe total amount in the wallet\n"
689 + HelpExampleCli("getbalance", "") +
690 "\nThe total amount in the wallet at least 5 blocks confirmed\n"
691 + HelpExampleCli("getbalance", "\"*\" 6") +
692 "\nAs a json rpc call\n"
693 + HelpExampleRpc("getbalance", "\"*\", 6")
696 LOCK2(cs_main, pwalletMain->cs_wallet);
698 if (request.params.size() == 0)
699 return ValueFromAmount(pwalletMain->GetBalance());
701 int nMinDepth = 1;
702 if (request.params.size() > 1)
703 nMinDepth = request.params[1].get_int();
704 isminefilter filter = ISMINE_SPENDABLE;
705 if(request.params.size() > 2)
706 if(request.params[2].get_bool())
707 filter = filter | ISMINE_WATCH_ONLY;
709 if (request.params[0].get_str() == "*") {
710 // Calculate total balance in a very different way from GetBalance().
711 // The biggest difference is that GetBalance() sums up all unspent
712 // TxOuts paying to the wallet, while this sums up both spent and
713 // unspent TxOuts paying to the wallet, and then subtracts the values of
714 // TxIns spending from the wallet. This also has fewer restrictions on
715 // which unconfirmed transactions are considered trusted.
716 CAmount nBalance = 0;
717 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
719 const CWalletTx& wtx = (*it).second;
720 if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
721 continue;
723 CAmount allFee;
724 string strSentAccount;
725 list<COutputEntry> listReceived;
726 list<COutputEntry> listSent;
727 wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
728 if (wtx.GetDepthInMainChain() >= nMinDepth)
730 BOOST_FOREACH(const COutputEntry& r, listReceived)
731 nBalance += r.amount;
733 BOOST_FOREACH(const COutputEntry& s, listSent)
734 nBalance -= s.amount;
735 nBalance -= allFee;
737 return ValueFromAmount(nBalance);
740 string strAccount = AccountFromValue(request.params[0]);
742 CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, filter);
744 return ValueFromAmount(nBalance);
747 UniValue getunconfirmedbalance(const JSONRPCRequest &request)
749 if (!EnsureWalletIsAvailable(request.fHelp))
750 return NullUniValue;
752 if (request.fHelp || request.params.size() > 0)
753 throw runtime_error(
754 "getunconfirmedbalance\n"
755 "Returns the server's total unconfirmed balance\n");
757 LOCK2(cs_main, pwalletMain->cs_wallet);
759 return ValueFromAmount(pwalletMain->GetUnconfirmedBalance());
763 UniValue movecmd(const JSONRPCRequest& request)
765 if (!EnsureWalletIsAvailable(request.fHelp))
766 return NullUniValue;
768 if (request.fHelp || request.params.size() < 3 || request.params.size() > 5)
769 throw runtime_error(
770 "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
771 "\nDEPRECATED. Move a specified amount from one account in your wallet to another.\n"
772 "\nArguments:\n"
773 "1. \"fromaccount\" (string, required) The name of the account to move funds from. May be the default account using \"\".\n"
774 "2. \"toaccount\" (string, required) The name of the account to move funds to. May be the default account using \"\".\n"
775 "3. amount (numeric) Quantity of " + CURRENCY_UNIT + " to move between accounts.\n"
776 "4. (dummy) (numeric, optional) Ignored. Remains for backward compatibility.\n"
777 "5. \"comment\" (string, optional) An optional comment, stored in the wallet only.\n"
778 "\nResult:\n"
779 "true|false (boolean) true if successful.\n"
780 "\nExamples:\n"
781 "\nMove 0.01 " + CURRENCY_UNIT + " from the default account to the account named tabby\n"
782 + HelpExampleCli("move", "\"\" \"tabby\" 0.01") +
783 "\nMove 0.01 " + CURRENCY_UNIT + " timotei to akiko with a comment and funds have 6 confirmations\n"
784 + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") +
785 "\nAs a json rpc call\n"
786 + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
789 LOCK2(cs_main, pwalletMain->cs_wallet);
791 string strFrom = AccountFromValue(request.params[0]);
792 string strTo = AccountFromValue(request.params[1]);
793 CAmount nAmount = AmountFromValue(request.params[2]);
794 if (nAmount <= 0)
795 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
796 if (request.params.size() > 3)
797 // unused parameter, used to be nMinDepth, keep type-checking it though
798 (void)request.params[3].get_int();
799 string strComment;
800 if (request.params.size() > 4)
801 strComment = request.params[4].get_str();
803 if (!pwalletMain->AccountMove(strFrom, strTo, nAmount, strComment))
804 throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
806 return true;
810 UniValue sendfrom(const JSONRPCRequest& request)
812 if (!EnsureWalletIsAvailable(request.fHelp))
813 return NullUniValue;
815 if (request.fHelp || request.params.size() < 3 || request.params.size() > 6)
816 throw runtime_error(
817 "sendfrom \"fromaccount\" \"toaddress\" amount ( minconf \"comment\" \"comment_to\" )\n"
818 "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a bitcoin address."
819 + HelpRequiringPassphrase() + "\n"
820 "\nArguments:\n"
821 "1. \"fromaccount\" (string, required) The name of the account to send funds from. May be the default account using \"\".\n"
822 "2. \"toaddress\" (string, required) The bitcoin address to send funds to.\n"
823 "3. amount (numeric or string, required) The amount in " + CURRENCY_UNIT + " (transaction fee is added on top).\n"
824 "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
825 "5. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
826 " This is not part of the transaction, just kept in your wallet.\n"
827 "6. \"comment_to\" (string, optional) An optional comment to store the name of the person or organization \n"
828 " to which you're sending the transaction. This is not part of the transaction, \n"
829 " it is just kept in your wallet.\n"
830 "\nResult:\n"
831 "\"txid\" (string) The transaction id.\n"
832 "\nExamples:\n"
833 "\nSend 0.01 " + CURRENCY_UNIT + " from the default account to the address, must have at least 1 confirmation\n"
834 + HelpExampleCli("sendfrom", "\"\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") +
835 "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
836 + HelpExampleCli("sendfrom", "\"tabby\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01 6 \"donation\" \"seans outpost\"") +
837 "\nAs a json rpc call\n"
838 + HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
841 LOCK2(cs_main, pwalletMain->cs_wallet);
843 string strAccount = AccountFromValue(request.params[0]);
844 CBitcoinAddress address(request.params[1].get_str());
845 if (!address.IsValid())
846 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
847 CAmount nAmount = AmountFromValue(request.params[2]);
848 if (nAmount <= 0)
849 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
850 int nMinDepth = 1;
851 if (request.params.size() > 3)
852 nMinDepth = request.params[3].get_int();
854 CWalletTx wtx;
855 wtx.strFromAccount = strAccount;
856 if (request.params.size() > 4 && !request.params[4].isNull() && !request.params[4].get_str().empty())
857 wtx.mapValue["comment"] = request.params[4].get_str();
858 if (request.params.size() > 5 && !request.params[5].isNull() && !request.params[5].get_str().empty())
859 wtx.mapValue["to"] = request.params[5].get_str();
861 EnsureWalletIsUnlocked();
863 // Check funds
864 CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
865 if (nAmount > nBalance)
866 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
868 SendMoney(address.Get(), nAmount, false, wtx);
870 return wtx.GetHash().GetHex();
874 UniValue sendmany(const JSONRPCRequest& request)
876 if (!EnsureWalletIsAvailable(request.fHelp))
877 return NullUniValue;
879 if (request.fHelp || request.params.size() < 2 || request.params.size() > 5)
880 throw runtime_error(
881 "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] )\n"
882 "\nSend multiple times. Amounts are double-precision floating point numbers."
883 + HelpRequiringPassphrase() + "\n"
884 "\nArguments:\n"
885 "1. \"fromaccount\" (string, required) DEPRECATED. The account to send the funds from. Should be \"\" for the default account\n"
886 "2. \"amounts\" (string, required) A json object with addresses and amounts\n"
887 " {\n"
888 " \"address\":amount (numeric or string) The bitcoin address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value\n"
889 " ,...\n"
890 " }\n"
891 "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
892 "4. \"comment\" (string, optional) A comment\n"
893 "5. subtractfeefrom (array, optional) A json array with addresses.\n"
894 " The fee will be equally deducted from the amount of each selected address.\n"
895 " Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
896 " If no addresses are specified here, the sender pays the fee.\n"
897 " [\n"
898 " \"address\" (string) Subtract fee from this address\n"
899 " ,...\n"
900 " ]\n"
901 "\nResult:\n"
902 "\"txid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
903 " the number of addresses.\n"
904 "\nExamples:\n"
905 "\nSend two amounts to two different addresses:\n"
906 + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
907 "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
908 + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
909 "\nSend two amounts to two different addresses, subtract fee from amount:\n"
910 + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\",\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") +
911 "\nAs a json rpc call\n"
912 + HelpExampleRpc("sendmany", "\"\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
915 LOCK2(cs_main, pwalletMain->cs_wallet);
917 if (pwalletMain->GetBroadcastTransactions() && !g_connman)
918 throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
920 string strAccount = AccountFromValue(request.params[0]);
921 UniValue sendTo = request.params[1].get_obj();
922 int nMinDepth = 1;
923 if (request.params.size() > 2)
924 nMinDepth = request.params[2].get_int();
926 CWalletTx wtx;
927 wtx.strFromAccount = strAccount;
928 if (request.params.size() > 3 && !request.params[3].isNull() && !request.params[3].get_str().empty())
929 wtx.mapValue["comment"] = request.params[3].get_str();
931 UniValue subtractFeeFromAmount(UniValue::VARR);
932 if (request.params.size() > 4)
933 subtractFeeFromAmount = request.params[4].get_array();
935 set<CBitcoinAddress> setAddress;
936 vector<CRecipient> vecSend;
938 CAmount totalAmount = 0;
939 vector<string> keys = sendTo.getKeys();
940 BOOST_FOREACH(const string& name_, keys)
942 CBitcoinAddress address(name_);
943 if (!address.IsValid())
944 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+name_);
946 if (setAddress.count(address))
947 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_);
948 setAddress.insert(address);
950 CScript scriptPubKey = GetScriptForDestination(address.Get());
951 CAmount nAmount = AmountFromValue(sendTo[name_]);
952 if (nAmount <= 0)
953 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
954 totalAmount += nAmount;
956 bool fSubtractFeeFromAmount = false;
957 for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
958 const UniValue& addr = subtractFeeFromAmount[idx];
959 if (addr.get_str() == name_)
960 fSubtractFeeFromAmount = true;
963 CRecipient recipient = {scriptPubKey, nAmount, fSubtractFeeFromAmount};
964 vecSend.push_back(recipient);
967 EnsureWalletIsUnlocked();
969 // Check funds
970 CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
971 if (totalAmount > nBalance)
972 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
974 // Send
975 CReserveKey keyChange(pwalletMain);
976 CAmount nFeeRequired = 0;
977 int nChangePosRet = -1;
978 string strFailReason;
979 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason);
980 if (!fCreated)
981 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
982 CValidationState state;
983 if (!pwalletMain->CommitTransaction(wtx, keyChange, g_connman.get(), state)) {
984 strFailReason = strprintf("Transaction commit failed:: %s", state.GetRejectReason());
985 throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
988 return wtx.GetHash().GetHex();
991 // Defined in rpc/misc.cpp
992 extern CScript _createmultisig_redeemScript(const UniValue& params);
994 UniValue addmultisigaddress(const JSONRPCRequest& request)
996 if (!EnsureWalletIsAvailable(request.fHelp))
997 return NullUniValue;
999 if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
1001 string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
1002 "\nAdd a nrequired-to-sign multisignature address to the wallet.\n"
1003 "Each key is a Bitcoin address or hex-encoded public key.\n"
1004 "If 'account' is specified (DEPRECATED), assign address to that account.\n"
1006 "\nArguments:\n"
1007 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
1008 "2. \"keys\" (string, required) A json array of bitcoin addresses or hex-encoded public keys\n"
1009 " [\n"
1010 " \"address\" (string) bitcoin address or hex-encoded public key\n"
1011 " ...,\n"
1012 " ]\n"
1013 "3. \"account\" (string, optional) DEPRECATED. An account to assign the addresses to.\n"
1015 "\nResult:\n"
1016 "\"address\" (string) A bitcoin address associated with the keys.\n"
1018 "\nExamples:\n"
1019 "\nAdd a multisig address from 2 addresses\n"
1020 + HelpExampleCli("addmultisigaddress", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
1021 "\nAs json rpc call\n"
1022 + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
1024 throw runtime_error(msg);
1027 LOCK2(cs_main, pwalletMain->cs_wallet);
1029 string strAccount;
1030 if (request.params.size() > 2)
1031 strAccount = AccountFromValue(request.params[2]);
1033 // Construct using pay-to-script-hash:
1034 CScript inner = _createmultisig_redeemScript(request.params);
1035 CScriptID innerID(inner);
1036 pwalletMain->AddCScript(inner);
1038 pwalletMain->SetAddressBook(innerID, strAccount, "send");
1039 return CBitcoinAddress(innerID).ToString();
1042 class Witnessifier : public boost::static_visitor<bool>
1044 public:
1045 CScriptID result;
1047 bool operator()(const CNoDestination &dest) const { return false; }
1049 bool operator()(const CKeyID &keyID) {
1050 CPubKey pubkey;
1051 if (pwalletMain) {
1052 CScript basescript = GetScriptForDestination(keyID);
1053 isminetype typ;
1054 typ = IsMine(*pwalletMain, basescript, SIGVERSION_WITNESS_V0);
1055 if (typ != ISMINE_SPENDABLE && typ != ISMINE_WATCH_SOLVABLE)
1056 return false;
1057 CScript witscript = GetScriptForWitness(basescript);
1058 pwalletMain->AddCScript(witscript);
1059 result = CScriptID(witscript);
1060 return true;
1062 return false;
1065 bool operator()(const CScriptID &scriptID) {
1066 CScript subscript;
1067 if (pwalletMain && pwalletMain->GetCScript(scriptID, subscript)) {
1068 int witnessversion;
1069 std::vector<unsigned char> witprog;
1070 if (subscript.IsWitnessProgram(witnessversion, witprog)) {
1071 result = scriptID;
1072 return true;
1074 isminetype typ;
1075 typ = IsMine(*pwalletMain, subscript, SIGVERSION_WITNESS_V0);
1076 if (typ != ISMINE_SPENDABLE && typ != ISMINE_WATCH_SOLVABLE)
1077 return false;
1078 CScript witscript = GetScriptForWitness(subscript);
1079 pwalletMain->AddCScript(witscript);
1080 result = CScriptID(witscript);
1081 return true;
1083 return false;
1087 UniValue addwitnessaddress(const JSONRPCRequest& request)
1089 if (!EnsureWalletIsAvailable(request.fHelp))
1090 return NullUniValue;
1092 if (request.fHelp || request.params.size() < 1 || request.params.size() > 1)
1094 string msg = "addwitnessaddress \"address\"\n"
1095 "\nAdd a witness address for a script (with pubkey or redeemscript known).\n"
1096 "It returns the witness script.\n"
1098 "\nArguments:\n"
1099 "1. \"address\" (string, required) An address known to the wallet\n"
1101 "\nResult:\n"
1102 "\"witnessaddress\", (string) The value of the new address (P2SH of witness script).\n"
1103 "}\n"
1105 throw runtime_error(msg);
1109 LOCK(cs_main);
1110 if (!IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus()) && !GetBoolArg("-walletprematurewitness", false)) {
1111 throw JSONRPCError(RPC_WALLET_ERROR, "Segregated witness not enabled on network");
1115 CBitcoinAddress address(request.params[0].get_str());
1116 if (!address.IsValid())
1117 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
1119 Witnessifier w;
1120 CTxDestination dest = address.Get();
1121 bool ret = boost::apply_visitor(w, dest);
1122 if (!ret) {
1123 throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet, or the key is uncompressed");
1126 pwalletMain->SetAddressBook(w.result, "", "receive");
1128 return CBitcoinAddress(w.result).ToString();
1131 struct tallyitem
1133 CAmount nAmount;
1134 int nConf;
1135 vector<uint256> txids;
1136 bool fIsWatchonly;
1137 tallyitem()
1139 nAmount = 0;
1140 nConf = std::numeric_limits<int>::max();
1141 fIsWatchonly = false;
1145 UniValue ListReceived(const UniValue& params, bool fByAccounts)
1147 // Minimum confirmations
1148 int nMinDepth = 1;
1149 if (params.size() > 0)
1150 nMinDepth = params[0].get_int();
1152 // Whether to include empty accounts
1153 bool fIncludeEmpty = false;
1154 if (params.size() > 1)
1155 fIncludeEmpty = params[1].get_bool();
1157 isminefilter filter = ISMINE_SPENDABLE;
1158 if(params.size() > 2)
1159 if(params[2].get_bool())
1160 filter = filter | ISMINE_WATCH_ONLY;
1162 // Tally
1163 map<CBitcoinAddress, tallyitem> mapTally;
1164 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1166 const CWalletTx& wtx = (*it).second;
1168 if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
1169 continue;
1171 int nDepth = wtx.GetDepthInMainChain();
1172 if (nDepth < nMinDepth)
1173 continue;
1175 BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
1177 CTxDestination address;
1178 if (!ExtractDestination(txout.scriptPubKey, address))
1179 continue;
1181 isminefilter mine = IsMine(*pwalletMain, address);
1182 if(!(mine & filter))
1183 continue;
1185 tallyitem& item = mapTally[address];
1186 item.nAmount += txout.nValue;
1187 item.nConf = min(item.nConf, nDepth);
1188 item.txids.push_back(wtx.GetHash());
1189 if (mine & ISMINE_WATCH_ONLY)
1190 item.fIsWatchonly = true;
1194 // Reply
1195 UniValue ret(UniValue::VARR);
1196 map<string, tallyitem> mapAccountTally;
1197 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
1199 const CBitcoinAddress& address = item.first;
1200 const string& strAccount = item.second.name;
1201 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1202 if (it == mapTally.end() && !fIncludeEmpty)
1203 continue;
1205 CAmount nAmount = 0;
1206 int nConf = std::numeric_limits<int>::max();
1207 bool fIsWatchonly = false;
1208 if (it != mapTally.end())
1210 nAmount = (*it).second.nAmount;
1211 nConf = (*it).second.nConf;
1212 fIsWatchonly = (*it).second.fIsWatchonly;
1215 if (fByAccounts)
1217 tallyitem& _item = mapAccountTally[strAccount];
1218 _item.nAmount += nAmount;
1219 _item.nConf = min(_item.nConf, nConf);
1220 _item.fIsWatchonly = fIsWatchonly;
1222 else
1224 UniValue obj(UniValue::VOBJ);
1225 if(fIsWatchonly)
1226 obj.push_back(Pair("involvesWatchonly", true));
1227 obj.push_back(Pair("address", address.ToString()));
1228 obj.push_back(Pair("account", strAccount));
1229 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1230 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1231 if (!fByAccounts)
1232 obj.push_back(Pair("label", strAccount));
1233 UniValue transactions(UniValue::VARR);
1234 if (it != mapTally.end())
1236 BOOST_FOREACH(const uint256& _item, (*it).second.txids)
1238 transactions.push_back(_item.GetHex());
1241 obj.push_back(Pair("txids", transactions));
1242 ret.push_back(obj);
1246 if (fByAccounts)
1248 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1250 CAmount nAmount = (*it).second.nAmount;
1251 int nConf = (*it).second.nConf;
1252 UniValue obj(UniValue::VOBJ);
1253 if((*it).second.fIsWatchonly)
1254 obj.push_back(Pair("involvesWatchonly", true));
1255 obj.push_back(Pair("account", (*it).first));
1256 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1257 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1258 ret.push_back(obj);
1262 return ret;
1265 UniValue listreceivedbyaddress(const JSONRPCRequest& request)
1267 if (!EnsureWalletIsAvailable(request.fHelp))
1268 return NullUniValue;
1270 if (request.fHelp || request.params.size() > 3)
1271 throw runtime_error(
1272 "listreceivedbyaddress ( minconf include_empty include_watchonly)\n"
1273 "\nList balances by receiving address.\n"
1274 "\nArguments:\n"
1275 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1276 "2. include_empty (bool, optional, default=false) Whether to include addresses that haven't received any payments.\n"
1277 "3. include_watchonly (bool, optional, default=false) Whether to include watch-only addresses (see 'importaddress').\n"
1279 "\nResult:\n"
1280 "[\n"
1281 " {\n"
1282 " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
1283 " \"address\" : \"receivingaddress\", (string) The receiving address\n"
1284 " \"account\" : \"accountname\", (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n"
1285 " \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " received by the address\n"
1286 " \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
1287 " \"label\" : \"label\", (string) A comment for the address/transaction, if any\n"
1288 " \"txids\": [\n"
1289 " n, (numeric) The ids of transactions received with the address \n"
1290 " ...\n"
1291 " ]\n"
1292 " }\n"
1293 " ,...\n"
1294 "]\n"
1296 "\nExamples:\n"
1297 + HelpExampleCli("listreceivedbyaddress", "")
1298 + HelpExampleCli("listreceivedbyaddress", "6 true")
1299 + HelpExampleRpc("listreceivedbyaddress", "6, true, true")
1302 LOCK2(cs_main, pwalletMain->cs_wallet);
1304 return ListReceived(request.params, false);
1307 UniValue listreceivedbyaccount(const JSONRPCRequest& request)
1309 if (!EnsureWalletIsAvailable(request.fHelp))
1310 return NullUniValue;
1312 if (request.fHelp || request.params.size() > 3)
1313 throw runtime_error(
1314 "listreceivedbyaccount ( minconf include_empty include_watchonly)\n"
1315 "\nDEPRECATED. List balances by account.\n"
1316 "\nArguments:\n"
1317 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1318 "2. include_empty (bool, optional, default=false) Whether to include accounts that haven't received any payments.\n"
1319 "3. include_watchonly (bool, optional, default=false) Whether to include watch-only addresses (see 'importaddress').\n"
1321 "\nResult:\n"
1322 "[\n"
1323 " {\n"
1324 " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
1325 " \"account\" : \"accountname\", (string) The account name of the receiving account\n"
1326 " \"amount\" : x.xxx, (numeric) The total amount received by addresses with this account\n"
1327 " \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
1328 " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
1329 " }\n"
1330 " ,...\n"
1331 "]\n"
1333 "\nExamples:\n"
1334 + HelpExampleCli("listreceivedbyaccount", "")
1335 + HelpExampleCli("listreceivedbyaccount", "6 true")
1336 + HelpExampleRpc("listreceivedbyaccount", "6, true, true")
1339 LOCK2(cs_main, pwalletMain->cs_wallet);
1341 return ListReceived(request.params, true);
1344 static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
1346 CBitcoinAddress addr;
1347 if (addr.Set(dest))
1348 entry.push_back(Pair("address", addr.ToString()));
1351 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
1353 CAmount nFee;
1354 string strSentAccount;
1355 list<COutputEntry> listReceived;
1356 list<COutputEntry> listSent;
1358 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter);
1360 bool fAllAccounts = (strAccount == string("*"));
1361 bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
1363 // Sent
1364 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1366 BOOST_FOREACH(const COutputEntry& s, listSent)
1368 UniValue entry(UniValue::VOBJ);
1369 if(involvesWatchonly || (::IsMine(*pwalletMain, s.destination) & ISMINE_WATCH_ONLY))
1370 entry.push_back(Pair("involvesWatchonly", true));
1371 entry.push_back(Pair("account", strSentAccount));
1372 MaybePushAddress(entry, s.destination);
1373 entry.push_back(Pair("category", "send"));
1374 entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
1375 if (pwalletMain->mapAddressBook.count(s.destination))
1376 entry.push_back(Pair("label", pwalletMain->mapAddressBook[s.destination].name));
1377 entry.push_back(Pair("vout", s.vout));
1378 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1379 if (fLong)
1380 WalletTxToJSON(wtx, entry);
1381 entry.push_back(Pair("abandoned", wtx.isAbandoned()));
1382 ret.push_back(entry);
1386 // Received
1387 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1389 BOOST_FOREACH(const COutputEntry& r, listReceived)
1391 string account;
1392 if (pwalletMain->mapAddressBook.count(r.destination))
1393 account = pwalletMain->mapAddressBook[r.destination].name;
1394 if (fAllAccounts || (account == strAccount))
1396 UniValue entry(UniValue::VOBJ);
1397 if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
1398 entry.push_back(Pair("involvesWatchonly", true));
1399 entry.push_back(Pair("account", account));
1400 MaybePushAddress(entry, r.destination);
1401 if (wtx.IsCoinBase())
1403 if (wtx.GetDepthInMainChain() < 1)
1404 entry.push_back(Pair("category", "orphan"));
1405 else if (wtx.GetBlocksToMaturity() > 0)
1406 entry.push_back(Pair("category", "immature"));
1407 else
1408 entry.push_back(Pair("category", "generate"));
1410 else
1412 entry.push_back(Pair("category", "receive"));
1414 entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
1415 if (pwalletMain->mapAddressBook.count(r.destination))
1416 entry.push_back(Pair("label", account));
1417 entry.push_back(Pair("vout", r.vout));
1418 if (fLong)
1419 WalletTxToJSON(wtx, entry);
1420 ret.push_back(entry);
1426 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, UniValue& ret)
1428 bool fAllAccounts = (strAccount == string("*"));
1430 if (fAllAccounts || acentry.strAccount == strAccount)
1432 UniValue entry(UniValue::VOBJ);
1433 entry.push_back(Pair("account", acentry.strAccount));
1434 entry.push_back(Pair("category", "move"));
1435 entry.push_back(Pair("time", acentry.nTime));
1436 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1437 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1438 entry.push_back(Pair("comment", acentry.strComment));
1439 ret.push_back(entry);
1443 UniValue listtransactions(const JSONRPCRequest& request)
1445 if (!EnsureWalletIsAvailable(request.fHelp))
1446 return NullUniValue;
1448 if (request.fHelp || request.params.size() > 4)
1449 throw runtime_error(
1450 "listtransactions ( \"account\" count skip include_watchonly)\n"
1451 "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n"
1452 "\nArguments:\n"
1453 "1. \"account\" (string, optional) DEPRECATED. The account name. Should be \"*\".\n"
1454 "2. count (numeric, optional, default=10) The number of transactions to return\n"
1455 "3. skip (numeric, optional, default=0) The number of transactions to skip\n"
1456 "4. include_watchonly (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress')\n"
1457 "\nResult:\n"
1458 "[\n"
1459 " {\n"
1460 " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. \n"
1461 " It will be \"\" for the default account.\n"
1462 " \"address\":\"address\", (string) The bitcoin address of the transaction. Not present for \n"
1463 " move transactions (category = move).\n"
1464 " \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n"
1465 " transaction between accounts, and not associated with an address,\n"
1466 " transaction id or block. 'send' and 'receive' transactions are \n"
1467 " associated with an address, transaction id and block details\n"
1468 " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the\n"
1469 " 'move' category for moves outbound. It is positive for the 'receive' category,\n"
1470 " and for the 'move' category for inbound funds.\n"
1471 " \"label\": \"label\", (string) A comment for the address/transaction, if any\n"
1472 " \"vout\": n, (numeric) the vout value\n"
1473 " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
1474 " 'send' category of transactions.\n"
1475 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
1476 " 'receive' category of transactions. Negative confirmations indicate the\n"
1477 " transaction conflicts with the block chain\n"
1478 " \"trusted\": xxx, (bool) Whether we consider the outputs of this unconfirmed transaction safe to spend.\n"
1479 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
1480 " category of transactions.\n"
1481 " \"blockindex\": n, (numeric) The index of the transaction in the block that includes it. Available for 'send' and 'receive'\n"
1482 " category of transactions.\n"
1483 " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
1484 " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1485 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
1486 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
1487 " for 'send' and 'receive' category of transactions.\n"
1488 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1489 " \"otheraccount\": \"accountname\", (string) DEPRECATED. For the 'move' category of transactions, the account the funds came \n"
1490 " from (for receiving funds, positive amounts), or went to (for sending funds,\n"
1491 " negative amounts).\n"
1492 " \"bip125-replaceable\": \"yes|no|unknown\", (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
1493 " may be unknown for unconfirmed transactions not in the mempool\n"
1494 " \"abandoned\": xxx (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
1495 " 'send' category of transactions.\n"
1496 " }\n"
1497 "]\n"
1499 "\nExamples:\n"
1500 "\nList the most recent 10 transactions in the systems\n"
1501 + HelpExampleCli("listtransactions", "") +
1502 "\nList transactions 100 to 120\n"
1503 + HelpExampleCli("listtransactions", "\"*\" 20 100") +
1504 "\nAs a json rpc call\n"
1505 + HelpExampleRpc("listtransactions", "\"*\", 20, 100")
1508 LOCK2(cs_main, pwalletMain->cs_wallet);
1510 string strAccount = "*";
1511 if (request.params.size() > 0)
1512 strAccount = request.params[0].get_str();
1513 int nCount = 10;
1514 if (request.params.size() > 1)
1515 nCount = request.params[1].get_int();
1516 int nFrom = 0;
1517 if (request.params.size() > 2)
1518 nFrom = request.params[2].get_int();
1519 isminefilter filter = ISMINE_SPENDABLE;
1520 if(request.params.size() > 3)
1521 if(request.params[3].get_bool())
1522 filter = filter | ISMINE_WATCH_ONLY;
1524 if (nCount < 0)
1525 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
1526 if (nFrom < 0)
1527 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
1529 UniValue ret(UniValue::VARR);
1531 const CWallet::TxItems & txOrdered = pwalletMain->wtxOrdered;
1533 // iterate backwards until we have nCount items to return:
1534 for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
1536 CWalletTx *const pwtx = (*it).second.first;
1537 if (pwtx != 0)
1538 ListTransactions(*pwtx, strAccount, 0, true, ret, filter);
1539 CAccountingEntry *const pacentry = (*it).second.second;
1540 if (pacentry != 0)
1541 AcentryToJSON(*pacentry, strAccount, ret);
1543 if ((int)ret.size() >= (nCount+nFrom)) break;
1545 // ret is newest to oldest
1547 if (nFrom > (int)ret.size())
1548 nFrom = ret.size();
1549 if ((nFrom + nCount) > (int)ret.size())
1550 nCount = ret.size() - nFrom;
1552 vector<UniValue> arrTmp = ret.getValues();
1554 vector<UniValue>::iterator first = arrTmp.begin();
1555 std::advance(first, nFrom);
1556 vector<UniValue>::iterator last = arrTmp.begin();
1557 std::advance(last, nFrom+nCount);
1559 if (last != arrTmp.end()) arrTmp.erase(last, arrTmp.end());
1560 if (first != arrTmp.begin()) arrTmp.erase(arrTmp.begin(), first);
1562 std::reverse(arrTmp.begin(), arrTmp.end()); // Return oldest to newest
1564 ret.clear();
1565 ret.setArray();
1566 ret.push_backV(arrTmp);
1568 return ret;
1571 UniValue listaccounts(const JSONRPCRequest& request)
1573 if (!EnsureWalletIsAvailable(request.fHelp))
1574 return NullUniValue;
1576 if (request.fHelp || request.params.size() > 2)
1577 throw runtime_error(
1578 "listaccounts ( minconf include_watchonly)\n"
1579 "\nDEPRECATED. Returns Object that has account names as keys, account balances as values.\n"
1580 "\nArguments:\n"
1581 "1. minconf (numeric, optional, default=1) Only include transactions with at least this many confirmations\n"
1582 "2. include_watchonly (bool, optional, default=false) Include balances in watch-only addresses (see 'importaddress')\n"
1583 "\nResult:\n"
1584 "{ (json object where keys are account names, and values are numeric balances\n"
1585 " \"account\": x.xxx, (numeric) The property name is the account name, and the value is the total balance for the account.\n"
1586 " ...\n"
1587 "}\n"
1588 "\nExamples:\n"
1589 "\nList account balances where there at least 1 confirmation\n"
1590 + HelpExampleCli("listaccounts", "") +
1591 "\nList account balances including zero confirmation transactions\n"
1592 + HelpExampleCli("listaccounts", "0") +
1593 "\nList account balances for 6 or more confirmations\n"
1594 + HelpExampleCli("listaccounts", "6") +
1595 "\nAs json rpc call\n"
1596 + HelpExampleRpc("listaccounts", "6")
1599 LOCK2(cs_main, pwalletMain->cs_wallet);
1601 int nMinDepth = 1;
1602 if (request.params.size() > 0)
1603 nMinDepth = request.params[0].get_int();
1604 isminefilter includeWatchonly = ISMINE_SPENDABLE;
1605 if(request.params.size() > 1)
1606 if(request.params[1].get_bool())
1607 includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY;
1609 map<string, CAmount> mapAccountBalances;
1610 BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) {
1611 if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me
1612 mapAccountBalances[entry.second.name] = 0;
1615 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1617 const CWalletTx& wtx = (*it).second;
1618 CAmount nFee;
1619 string strSentAccount;
1620 list<COutputEntry> listReceived;
1621 list<COutputEntry> listSent;
1622 int nDepth = wtx.GetDepthInMainChain();
1623 if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
1624 continue;
1625 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
1626 mapAccountBalances[strSentAccount] -= nFee;
1627 BOOST_FOREACH(const COutputEntry& s, listSent)
1628 mapAccountBalances[strSentAccount] -= s.amount;
1629 if (nDepth >= nMinDepth)
1631 BOOST_FOREACH(const COutputEntry& r, listReceived)
1632 if (pwalletMain->mapAddressBook.count(r.destination))
1633 mapAccountBalances[pwalletMain->mapAddressBook[r.destination].name] += r.amount;
1634 else
1635 mapAccountBalances[""] += r.amount;
1639 const list<CAccountingEntry> & acentries = pwalletMain->laccentries;
1640 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1641 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1643 UniValue ret(UniValue::VOBJ);
1644 BOOST_FOREACH(const PAIRTYPE(string, CAmount)& accountBalance, mapAccountBalances) {
1645 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1647 return ret;
1650 UniValue listsinceblock(const JSONRPCRequest& request)
1652 if (!EnsureWalletIsAvailable(request.fHelp))
1653 return NullUniValue;
1655 if (request.fHelp)
1656 throw runtime_error(
1657 "listsinceblock ( \"blockhash\" target_confirmations include_watchonly)\n"
1658 "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n"
1659 "\nArguments:\n"
1660 "1. \"blockhash\" (string, optional) The block hash to list transactions since\n"
1661 "2. target_confirmations: (numeric, optional) The confirmations required, must be 1 or more\n"
1662 "3. include_watchonly: (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress')"
1663 "\nResult:\n"
1664 "{\n"
1665 " \"transactions\": [\n"
1666 " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n"
1667 " \"address\":\"address\", (string) The bitcoin address of the transaction. Not present for move transactions (category = move).\n"
1668 " \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
1669 " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the 'move' category for moves \n"
1670 " outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
1671 " \"vout\" : n, (numeric) the vout value\n"
1672 " \"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"
1673 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
1674 " When it's < 0, it means the transaction conflicted that many blocks ago.\n"
1675 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1676 " \"blockindex\": n, (numeric) The index of the transaction in the block that includes it. Available for 'send' and 'receive' category of transactions.\n"
1677 " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
1678 " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1679 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
1680 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
1681 " \"bip125-replaceable\": \"yes|no|unknown\", (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
1682 " may be unknown for unconfirmed transactions not in the mempool\n"
1683 " \"abandoned\": xxx, (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the 'send' category of transactions.\n"
1684 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1685 " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
1686 " \"to\": \"...\", (string) If a comment to is associated with the transaction.\n"
1687 " ],\n"
1688 " \"lastblock\": \"lastblockhash\" (string) The hash of the last block\n"
1689 "}\n"
1690 "\nExamples:\n"
1691 + HelpExampleCli("listsinceblock", "")
1692 + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
1693 + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
1696 LOCK2(cs_main, pwalletMain->cs_wallet);
1698 const CBlockIndex *pindex = NULL;
1699 int target_confirms = 1;
1700 isminefilter filter = ISMINE_SPENDABLE;
1702 if (request.params.size() > 0)
1704 uint256 blockId;
1706 blockId.SetHex(request.params[0].get_str());
1707 BlockMap::iterator it = mapBlockIndex.find(blockId);
1708 if (it != mapBlockIndex.end())
1710 pindex = it->second;
1711 if (chainActive[pindex->nHeight] != pindex)
1713 // the block being asked for is a part of a deactivated chain;
1714 // we don't want to depend on its perceived height in the block
1715 // chain, we want to instead use the last common ancestor
1716 pindex = chainActive.FindFork(pindex);
1721 if (request.params.size() > 1)
1723 target_confirms = request.params[1].get_int();
1725 if (target_confirms < 1)
1726 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
1729 if (request.params.size() > 2 && request.params[2].get_bool())
1731 filter = filter | ISMINE_WATCH_ONLY;
1734 int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
1736 UniValue transactions(UniValue::VARR);
1738 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1740 CWalletTx tx = (*it).second;
1742 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1743 ListTransactions(tx, "*", 0, true, transactions, filter);
1746 CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
1747 uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : uint256();
1749 UniValue ret(UniValue::VOBJ);
1750 ret.push_back(Pair("transactions", transactions));
1751 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1753 return ret;
1756 UniValue gettransaction(const JSONRPCRequest& request)
1758 if (!EnsureWalletIsAvailable(request.fHelp))
1759 return NullUniValue;
1761 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
1762 throw runtime_error(
1763 "gettransaction \"txid\" ( include_watchonly )\n"
1764 "\nGet detailed information about in-wallet transaction <txid>\n"
1765 "\nArguments:\n"
1766 "1. \"txid\" (string, required) The transaction id\n"
1767 "2. \"include_watchonly\" (bool, optional, default=false) Whether to include watch-only addresses in balance calculation and details[]\n"
1768 "\nResult:\n"
1769 "{\n"
1770 " \"amount\" : x.xxx, (numeric) The transaction amount in " + CURRENCY_UNIT + "\n"
1771 " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
1772 " 'send' category of transactions.\n"
1773 " \"confirmations\" : n, (numeric) The number of confirmations\n"
1774 " \"blockhash\" : \"hash\", (string) The block hash\n"
1775 " \"blockindex\" : xx, (numeric) The index of the transaction in the block that includes it\n"
1776 " \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
1777 " \"txid\" : \"transactionid\", (string) The transaction id.\n"
1778 " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
1779 " \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
1780 " \"bip125-replaceable\": \"yes|no|unknown\", (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
1781 " may be unknown for unconfirmed transactions not in the mempool\n"
1782 " \"details\" : [\n"
1783 " {\n"
1784 " \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n"
1785 " \"address\" : \"address\", (string) The bitcoin address involved in the transaction\n"
1786 " \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n"
1787 " \"amount\" : x.xxx, (numeric) The amount in " + CURRENCY_UNIT + "\n"
1788 " \"label\" : \"label\", (string) A comment for the address/transaction, if any\n"
1789 " \"vout\" : n, (numeric) the vout value\n"
1790 " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
1791 " 'send' category of transactions.\n"
1792 " \"abandoned\": xxx (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
1793 " 'send' category of transactions.\n"
1794 " }\n"
1795 " ,...\n"
1796 " ],\n"
1797 " \"hex\" : \"data\" (string) Raw data for transaction\n"
1798 "}\n"
1800 "\nExamples:\n"
1801 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1802 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
1803 + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1806 LOCK2(cs_main, pwalletMain->cs_wallet);
1808 uint256 hash;
1809 hash.SetHex(request.params[0].get_str());
1811 isminefilter filter = ISMINE_SPENDABLE;
1812 if(request.params.size() > 1)
1813 if(request.params[1].get_bool())
1814 filter = filter | ISMINE_WATCH_ONLY;
1816 UniValue entry(UniValue::VOBJ);
1817 if (!pwalletMain->mapWallet.count(hash))
1818 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
1819 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1821 CAmount nCredit = wtx.GetCredit(filter);
1822 CAmount nDebit = wtx.GetDebit(filter);
1823 CAmount nNet = nCredit - nDebit;
1824 CAmount nFee = (wtx.IsFromMe(filter) ? wtx.tx->GetValueOut() - nDebit : 0);
1826 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1827 if (wtx.IsFromMe(filter))
1828 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1830 WalletTxToJSON(wtx, entry);
1832 UniValue details(UniValue::VARR);
1833 ListTransactions(wtx, "*", 0, false, details, filter);
1834 entry.push_back(Pair("details", details));
1836 string strHex = EncodeHexTx(static_cast<CTransaction>(wtx), RPCSerializationFlags());
1837 entry.push_back(Pair("hex", strHex));
1839 return entry;
1842 UniValue abandontransaction(const JSONRPCRequest& request)
1844 if (!EnsureWalletIsAvailable(request.fHelp))
1845 return NullUniValue;
1847 if (request.fHelp || request.params.size() != 1)
1848 throw runtime_error(
1849 "abandontransaction \"txid\"\n"
1850 "\nMark in-wallet transaction <txid> as abandoned\n"
1851 "This will mark this transaction and all its in-wallet descendants as abandoned which will allow\n"
1852 "for their inputs to be respent. It can be used to replace \"stuck\" or evicted transactions.\n"
1853 "It only works on transactions which are not included in a block and are not currently in the mempool.\n"
1854 "It has no effect on transactions which are already conflicted or abandoned.\n"
1855 "\nArguments:\n"
1856 "1. \"txid\" (string, required) The transaction id\n"
1857 "\nResult:\n"
1858 "\nExamples:\n"
1859 + HelpExampleCli("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1860 + HelpExampleRpc("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1863 LOCK2(cs_main, pwalletMain->cs_wallet);
1865 uint256 hash;
1866 hash.SetHex(request.params[0].get_str());
1868 if (!pwalletMain->mapWallet.count(hash))
1869 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
1870 if (!pwalletMain->AbandonTransaction(hash))
1871 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not eligible for abandonment");
1873 return NullUniValue;
1877 UniValue backupwallet(const JSONRPCRequest& request)
1879 if (!EnsureWalletIsAvailable(request.fHelp))
1880 return NullUniValue;
1882 if (request.fHelp || request.params.size() != 1)
1883 throw runtime_error(
1884 "backupwallet \"destination\"\n"
1885 "\nSafely copies current wallet file to destination, which can be a directory or a path with filename.\n"
1886 "\nArguments:\n"
1887 "1. \"destination\" (string) The destination directory or file\n"
1888 "\nExamples:\n"
1889 + HelpExampleCli("backupwallet", "\"backup.dat\"")
1890 + HelpExampleRpc("backupwallet", "\"backup.dat\"")
1893 LOCK2(cs_main, pwalletMain->cs_wallet);
1895 string strDest = request.params[0].get_str();
1896 if (!pwalletMain->BackupWallet(strDest))
1897 throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
1899 return NullUniValue;
1903 UniValue keypoolrefill(const JSONRPCRequest& request)
1905 if (!EnsureWalletIsAvailable(request.fHelp))
1906 return NullUniValue;
1908 if (request.fHelp || request.params.size() > 1)
1909 throw runtime_error(
1910 "keypoolrefill ( newsize )\n"
1911 "\nFills the keypool."
1912 + HelpRequiringPassphrase() + "\n"
1913 "\nArguments\n"
1914 "1. newsize (numeric, optional, default=100) The new keypool size\n"
1915 "\nExamples:\n"
1916 + HelpExampleCli("keypoolrefill", "")
1917 + HelpExampleRpc("keypoolrefill", "")
1920 LOCK2(cs_main, pwalletMain->cs_wallet);
1922 // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
1923 unsigned int kpSize = 0;
1924 if (request.params.size() > 0) {
1925 if (request.params[0].get_int() < 0)
1926 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
1927 kpSize = (unsigned int)request.params[0].get_int();
1930 EnsureWalletIsUnlocked();
1931 pwalletMain->TopUpKeyPool(kpSize);
1933 if (pwalletMain->GetKeyPoolSize() < kpSize)
1934 throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
1936 return NullUniValue;
1940 static void LockWallet(CWallet* pWallet)
1942 LOCK(cs_nWalletUnlockTime);
1943 nWalletUnlockTime = 0;
1944 pWallet->Lock();
1947 UniValue walletpassphrase(const JSONRPCRequest& request)
1949 if (!EnsureWalletIsAvailable(request.fHelp))
1950 return NullUniValue;
1952 if (pwalletMain->IsCrypted() && (request.fHelp || request.params.size() != 2))
1953 throw runtime_error(
1954 "walletpassphrase \"passphrase\" timeout\n"
1955 "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
1956 "This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
1957 "\nArguments:\n"
1958 "1. \"passphrase\" (string, required) The wallet passphrase\n"
1959 "2. timeout (numeric, required) The time to keep the decryption key in seconds.\n"
1960 "\nNote:\n"
1961 "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
1962 "time that overrides the old one.\n"
1963 "\nExamples:\n"
1964 "\nunlock the wallet for 60 seconds\n"
1965 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
1966 "\nLock the wallet again (before 60 seconds)\n"
1967 + HelpExampleCli("walletlock", "") +
1968 "\nAs json rpc call\n"
1969 + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
1972 LOCK2(cs_main, pwalletMain->cs_wallet);
1974 if (request.fHelp)
1975 return true;
1976 if (!pwalletMain->IsCrypted())
1977 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1979 // Note that the walletpassphrase is stored in request.params[0] which is not mlock()ed
1980 SecureString strWalletPass;
1981 strWalletPass.reserve(100);
1982 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1983 // Alternately, find a way to make request.params[0] mlock()'d to begin with.
1984 strWalletPass = request.params[0].get_str().c_str();
1986 if (strWalletPass.length() > 0)
1988 if (!pwalletMain->Unlock(strWalletPass))
1989 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1991 else
1992 throw runtime_error(
1993 "walletpassphrase <passphrase> <timeout>\n"
1994 "Stores the wallet decryption key in memory for <timeout> seconds.");
1996 pwalletMain->TopUpKeyPool();
1998 int64_t nSleepTime = request.params[1].get_int64();
1999 LOCK(cs_nWalletUnlockTime);
2000 nWalletUnlockTime = GetTime() + nSleepTime;
2001 RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
2003 return NullUniValue;
2007 UniValue walletpassphrasechange(const JSONRPCRequest& request)
2009 if (!EnsureWalletIsAvailable(request.fHelp))
2010 return NullUniValue;
2012 if (pwalletMain->IsCrypted() && (request.fHelp || request.params.size() != 2))
2013 throw runtime_error(
2014 "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
2015 "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
2016 "\nArguments:\n"
2017 "1. \"oldpassphrase\" (string) The current passphrase\n"
2018 "2. \"newpassphrase\" (string) The new passphrase\n"
2019 "\nExamples:\n"
2020 + HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
2021 + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
2024 LOCK2(cs_main, pwalletMain->cs_wallet);
2026 if (request.fHelp)
2027 return true;
2028 if (!pwalletMain->IsCrypted())
2029 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
2031 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
2032 // Alternately, find a way to make request.params[0] mlock()'d to begin with.
2033 SecureString strOldWalletPass;
2034 strOldWalletPass.reserve(100);
2035 strOldWalletPass = request.params[0].get_str().c_str();
2037 SecureString strNewWalletPass;
2038 strNewWalletPass.reserve(100);
2039 strNewWalletPass = request.params[1].get_str().c_str();
2041 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
2042 throw runtime_error(
2043 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
2044 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
2046 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
2047 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
2049 return NullUniValue;
2053 UniValue walletlock(const JSONRPCRequest& request)
2055 if (!EnsureWalletIsAvailable(request.fHelp))
2056 return NullUniValue;
2058 if (pwalletMain->IsCrypted() && (request.fHelp || request.params.size() != 0))
2059 throw runtime_error(
2060 "walletlock\n"
2061 "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
2062 "After calling this method, you will need to call walletpassphrase again\n"
2063 "before being able to call any methods which require the wallet to be unlocked.\n"
2064 "\nExamples:\n"
2065 "\nSet the passphrase for 2 minutes to perform a transaction\n"
2066 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
2067 "\nPerform a send (requires passphrase set)\n"
2068 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 1.0") +
2069 "\nClear the passphrase since we are done before 2 minutes is up\n"
2070 + HelpExampleCli("walletlock", "") +
2071 "\nAs json rpc call\n"
2072 + HelpExampleRpc("walletlock", "")
2075 LOCK2(cs_main, pwalletMain->cs_wallet);
2077 if (request.fHelp)
2078 return true;
2079 if (!pwalletMain->IsCrypted())
2080 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
2083 LOCK(cs_nWalletUnlockTime);
2084 pwalletMain->Lock();
2085 nWalletUnlockTime = 0;
2088 return NullUniValue;
2092 UniValue encryptwallet(const JSONRPCRequest& request)
2094 if (!EnsureWalletIsAvailable(request.fHelp))
2095 return NullUniValue;
2097 if (!pwalletMain->IsCrypted() && (request.fHelp || request.params.size() != 1))
2098 throw runtime_error(
2099 "encryptwallet \"passphrase\"\n"
2100 "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
2101 "After this, any calls that interact with private keys such as sending or signing \n"
2102 "will require the passphrase to be set prior the making these calls.\n"
2103 "Use the walletpassphrase call for this, and then walletlock call.\n"
2104 "If the wallet is already encrypted, use the walletpassphrasechange call.\n"
2105 "Note that this will shutdown the server.\n"
2106 "\nArguments:\n"
2107 "1. \"passphrase\" (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n"
2108 "\nExamples:\n"
2109 "\nEncrypt you wallet\n"
2110 + HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
2111 "\nNow set the passphrase to use the wallet, such as for signing or sending bitcoin\n"
2112 + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
2113 "\nNow we can so something like sign\n"
2114 + HelpExampleCli("signmessage", "\"address\" \"test message\"") +
2115 "\nNow lock the wallet again by removing the passphrase\n"
2116 + HelpExampleCli("walletlock", "") +
2117 "\nAs a json rpc call\n"
2118 + HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
2121 LOCK2(cs_main, pwalletMain->cs_wallet);
2123 if (request.fHelp)
2124 return true;
2125 if (pwalletMain->IsCrypted())
2126 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
2128 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
2129 // Alternately, find a way to make request.params[0] mlock()'d to begin with.
2130 SecureString strWalletPass;
2131 strWalletPass.reserve(100);
2132 strWalletPass = request.params[0].get_str().c_str();
2134 if (strWalletPass.length() < 1)
2135 throw runtime_error(
2136 "encryptwallet <passphrase>\n"
2137 "Encrypts the wallet with <passphrase>.");
2139 if (!pwalletMain->EncryptWallet(strWalletPass))
2140 throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
2142 // BDB seems to have a bad habit of writing old data into
2143 // slack space in .dat files; that is bad if the old data is
2144 // unencrypted private keys. So:
2145 StartShutdown();
2146 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.";
2149 UniValue lockunspent(const JSONRPCRequest& request)
2151 if (!EnsureWalletIsAvailable(request.fHelp))
2152 return NullUniValue;
2154 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
2155 throw runtime_error(
2156 "lockunspent unlock ([{\"txid\":\"txid\",\"vout\":n},...])\n"
2157 "\nUpdates list of temporarily unspendable outputs.\n"
2158 "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
2159 "If no transaction outputs are specified when unlocking then all current locked transaction outputs are unlocked.\n"
2160 "A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
2161 "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
2162 "is always cleared (by virtue of process exit) when a node stops or fails.\n"
2163 "Also see the listunspent call\n"
2164 "\nArguments:\n"
2165 "1. unlock (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
2166 "2. \"transactions\" (string, optional) A json array of objects. Each object the txid (string) vout (numeric)\n"
2167 " [ (json array of json objects)\n"
2168 " {\n"
2169 " \"txid\":\"id\", (string) The transaction id\n"
2170 " \"vout\": n (numeric) The output number\n"
2171 " }\n"
2172 " ,...\n"
2173 " ]\n"
2175 "\nResult:\n"
2176 "true|false (boolean) Whether the command was successful or not\n"
2178 "\nExamples:\n"
2179 "\nList the unspent transactions\n"
2180 + HelpExampleCli("listunspent", "") +
2181 "\nLock an unspent transaction\n"
2182 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2183 "\nList the locked transactions\n"
2184 + HelpExampleCli("listlockunspent", "") +
2185 "\nUnlock the transaction again\n"
2186 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2187 "\nAs a json rpc call\n"
2188 + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
2191 LOCK2(cs_main, pwalletMain->cs_wallet);
2193 if (request.params.size() == 1)
2194 RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VBOOL));
2195 else
2196 RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VBOOL)(UniValue::VARR));
2198 bool fUnlock = request.params[0].get_bool();
2200 if (request.params.size() == 1) {
2201 if (fUnlock)
2202 pwalletMain->UnlockAllCoins();
2203 return true;
2206 UniValue outputs = request.params[1].get_array();
2207 for (unsigned int idx = 0; idx < outputs.size(); idx++) {
2208 const UniValue& output = outputs[idx];
2209 if (!output.isObject())
2210 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
2211 const UniValue& o = output.get_obj();
2213 RPCTypeCheckObj(o,
2215 {"txid", UniValueType(UniValue::VSTR)},
2216 {"vout", UniValueType(UniValue::VNUM)},
2219 string txid = find_value(o, "txid").get_str();
2220 if (!IsHex(txid))
2221 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
2223 int nOutput = find_value(o, "vout").get_int();
2224 if (nOutput < 0)
2225 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
2227 COutPoint outpt(uint256S(txid), nOutput);
2229 if (fUnlock)
2230 pwalletMain->UnlockCoin(outpt);
2231 else
2232 pwalletMain->LockCoin(outpt);
2235 return true;
2238 UniValue listlockunspent(const JSONRPCRequest& request)
2240 if (!EnsureWalletIsAvailable(request.fHelp))
2241 return NullUniValue;
2243 if (request.fHelp || request.params.size() > 0)
2244 throw runtime_error(
2245 "listlockunspent\n"
2246 "\nReturns list of temporarily unspendable outputs.\n"
2247 "See the lockunspent call to lock and unlock transactions for spending.\n"
2248 "\nResult:\n"
2249 "[\n"
2250 " {\n"
2251 " \"txid\" : \"transactionid\", (string) The transaction id locked\n"
2252 " \"vout\" : n (numeric) The vout value\n"
2253 " }\n"
2254 " ,...\n"
2255 "]\n"
2256 "\nExamples:\n"
2257 "\nList the unspent transactions\n"
2258 + HelpExampleCli("listunspent", "") +
2259 "\nLock an unspent transaction\n"
2260 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2261 "\nList the locked transactions\n"
2262 + HelpExampleCli("listlockunspent", "") +
2263 "\nUnlock the transaction again\n"
2264 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2265 "\nAs a json rpc call\n"
2266 + HelpExampleRpc("listlockunspent", "")
2269 LOCK2(cs_main, pwalletMain->cs_wallet);
2271 vector<COutPoint> vOutpts;
2272 pwalletMain->ListLockedCoins(vOutpts);
2274 UniValue ret(UniValue::VARR);
2276 BOOST_FOREACH(COutPoint &outpt, vOutpts) {
2277 UniValue o(UniValue::VOBJ);
2279 o.push_back(Pair("txid", outpt.hash.GetHex()));
2280 o.push_back(Pair("vout", (int)outpt.n));
2281 ret.push_back(o);
2284 return ret;
2287 UniValue settxfee(const JSONRPCRequest& request)
2289 if (!EnsureWalletIsAvailable(request.fHelp))
2290 return NullUniValue;
2292 if (request.fHelp || request.params.size() < 1 || request.params.size() > 1)
2293 throw runtime_error(
2294 "settxfee amount\n"
2295 "\nSet the transaction fee per kB. Overwrites the paytxfee parameter.\n"
2296 "\nArguments:\n"
2297 "1. amount (numeric or string, required) The transaction fee in " + CURRENCY_UNIT + "/kB\n"
2298 "\nResult\n"
2299 "true|false (boolean) Returns true if successful\n"
2300 "\nExamples:\n"
2301 + HelpExampleCli("settxfee", "0.00001")
2302 + HelpExampleRpc("settxfee", "0.00001")
2305 LOCK2(cs_main, pwalletMain->cs_wallet);
2307 // Amount
2308 CAmount nAmount = AmountFromValue(request.params[0]);
2310 payTxFee = CFeeRate(nAmount, 1000);
2311 return true;
2314 UniValue getwalletinfo(const JSONRPCRequest& request)
2316 if (!EnsureWalletIsAvailable(request.fHelp))
2317 return NullUniValue;
2319 if (request.fHelp || request.params.size() != 0)
2320 throw runtime_error(
2321 "getwalletinfo\n"
2322 "Returns an object containing various wallet state info.\n"
2323 "\nResult:\n"
2324 "{\n"
2325 " \"walletversion\": xxxxx, (numeric) the wallet version\n"
2326 " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
2327 " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
2328 " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + CURRENCY_UNIT + "\n"
2329 " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
2330 " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since Unix epoch) of the oldest pre-generated key in the key pool\n"
2331 " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
2332 " \"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"
2333 " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n"
2334 " \"hdmasterkeyid\": \"<hash160>\" (string) the Hash160 of the HD master pubkey\n"
2335 "}\n"
2336 "\nExamples:\n"
2337 + HelpExampleCli("getwalletinfo", "")
2338 + HelpExampleRpc("getwalletinfo", "")
2341 LOCK2(cs_main, pwalletMain->cs_wallet);
2343 UniValue obj(UniValue::VOBJ);
2344 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
2345 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
2346 obj.push_back(Pair("unconfirmed_balance", ValueFromAmount(pwalletMain->GetUnconfirmedBalance())));
2347 obj.push_back(Pair("immature_balance", ValueFromAmount(pwalletMain->GetImmatureBalance())));
2348 obj.push_back(Pair("txcount", (int)pwalletMain->mapWallet.size()));
2349 obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
2350 obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
2351 if (pwalletMain->IsCrypted())
2352 obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
2353 obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
2354 CKeyID masterKeyID = pwalletMain->GetHDChain().masterKeyID;
2355 if (!masterKeyID.IsNull())
2356 obj.push_back(Pair("hdmasterkeyid", masterKeyID.GetHex()));
2357 return obj;
2360 UniValue resendwallettransactions(const JSONRPCRequest& request)
2362 if (!EnsureWalletIsAvailable(request.fHelp))
2363 return NullUniValue;
2365 if (request.fHelp || request.params.size() != 0)
2366 throw runtime_error(
2367 "resendwallettransactions\n"
2368 "Immediately re-broadcast unconfirmed wallet transactions to all peers.\n"
2369 "Intended only for testing; the wallet code periodically re-broadcasts\n"
2370 "automatically.\n"
2371 "Returns array of transaction ids that were re-broadcast.\n"
2374 if (!g_connman)
2375 throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
2377 LOCK2(cs_main, pwalletMain->cs_wallet);
2379 std::vector<uint256> txids = pwalletMain->ResendWalletTransactionsBefore(GetTime(), g_connman.get());
2380 UniValue result(UniValue::VARR);
2381 BOOST_FOREACH(const uint256& txid, txids)
2383 result.push_back(txid.ToString());
2385 return result;
2388 UniValue listunspent(const JSONRPCRequest& request)
2390 if (!EnsureWalletIsAvailable(request.fHelp))
2391 return NullUniValue;
2393 if (request.fHelp || request.params.size() > 4)
2394 throw runtime_error(
2395 "listunspent ( minconf maxconf [\"addresses\",...] [include_unsafe] )\n"
2396 "\nReturns array of unspent transaction outputs\n"
2397 "with between minconf and maxconf (inclusive) confirmations.\n"
2398 "Optionally filter to only include txouts paid to specified addresses.\n"
2399 "\nArguments:\n"
2400 "1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n"
2401 "2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n"
2402 "3. \"addresses\" (string) A json array of bitcoin addresses to filter\n"
2403 " [\n"
2404 " \"address\" (string) bitcoin address\n"
2405 " ,...\n"
2406 " ]\n"
2407 "4. include_unsafe (bool, optional, default=true) Include outputs that are not safe to spend\n"
2408 " because they come from unconfirmed untrusted transactions or unconfirmed\n"
2409 " replacement transactions (cases where we are less sure that a conflicting\n"
2410 " transaction won't be mined).\n"
2411 "\nResult\n"
2412 "[ (array of json object)\n"
2413 " {\n"
2414 " \"txid\" : \"txid\", (string) the transaction id \n"
2415 " \"vout\" : n, (numeric) the vout value\n"
2416 " \"address\" : \"address\", (string) the bitcoin address\n"
2417 " \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n"
2418 " \"scriptPubKey\" : \"key\", (string) the script key\n"
2419 " \"amount\" : x.xxx, (numeric) the transaction output amount in " + CURRENCY_UNIT + "\n"
2420 " \"confirmations\" : n, (numeric) The number of confirmations\n"
2421 " \"redeemScript\" : n (string) The redeemScript if scriptPubKey is P2SH\n"
2422 " \"spendable\" : xxx, (bool) Whether we have the private keys to spend this output\n"
2423 " \"solvable\" : xxx (bool) Whether we know how to spend this output, ignoring the lack of keys\n"
2424 " }\n"
2425 " ,...\n"
2426 "]\n"
2428 "\nExamples\n"
2429 + HelpExampleCli("listunspent", "")
2430 + HelpExampleCli("listunspent", "6 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
2431 + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
2434 int nMinDepth = 1;
2435 if (request.params.size() > 0 && !request.params[0].isNull()) {
2436 RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
2437 nMinDepth = request.params[0].get_int();
2440 int nMaxDepth = 9999999;
2441 if (request.params.size() > 1 && !request.params[1].isNull()) {
2442 RPCTypeCheckArgument(request.params[1], UniValue::VNUM);
2443 nMaxDepth = request.params[1].get_int();
2446 set<CBitcoinAddress> setAddress;
2447 if (request.params.size() > 2 && !request.params[2].isNull()) {
2448 RPCTypeCheckArgument(request.params[2], UniValue::VARR);
2449 UniValue inputs = request.params[2].get_array();
2450 for (unsigned int idx = 0; idx < inputs.size(); idx++) {
2451 const UniValue& input = inputs[idx];
2452 CBitcoinAddress address(input.get_str());
2453 if (!address.IsValid())
2454 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+input.get_str());
2455 if (setAddress.count(address))
2456 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str());
2457 setAddress.insert(address);
2461 bool include_unsafe = true;
2462 if (request.params.size() > 3 && !request.params[3].isNull()) {
2463 RPCTypeCheckArgument(request.params[3], UniValue::VBOOL);
2464 include_unsafe = request.params[3].get_bool();
2467 UniValue results(UniValue::VARR);
2468 vector<COutput> vecOutputs;
2469 assert(pwalletMain != NULL);
2470 LOCK2(cs_main, pwalletMain->cs_wallet);
2471 pwalletMain->AvailableCoins(vecOutputs, !include_unsafe, NULL, true);
2472 BOOST_FOREACH(const COutput& out, vecOutputs) {
2473 if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
2474 continue;
2476 CTxDestination address;
2477 const CScript& scriptPubKey = out.tx->tx->vout[out.i].scriptPubKey;
2478 bool fValidAddress = ExtractDestination(scriptPubKey, address);
2480 if (setAddress.size() && (!fValidAddress || !setAddress.count(address)))
2481 continue;
2483 UniValue entry(UniValue::VOBJ);
2484 entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
2485 entry.push_back(Pair("vout", out.i));
2487 if (fValidAddress) {
2488 entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
2490 if (pwalletMain->mapAddressBook.count(address))
2491 entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name));
2493 if (scriptPubKey.IsPayToScriptHash()) {
2494 const CScriptID& hash = boost::get<CScriptID>(address);
2495 CScript redeemScript;
2496 if (pwalletMain->GetCScript(hash, redeemScript))
2497 entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
2501 entry.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
2502 entry.push_back(Pair("amount", ValueFromAmount(out.tx->tx->vout[out.i].nValue)));
2503 entry.push_back(Pair("confirmations", out.nDepth));
2504 entry.push_back(Pair("spendable", out.fSpendable));
2505 entry.push_back(Pair("solvable", out.fSolvable));
2506 results.push_back(entry);
2509 return results;
2512 UniValue fundrawtransaction(const JSONRPCRequest& request)
2514 if (!EnsureWalletIsAvailable(request.fHelp))
2515 return NullUniValue;
2517 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
2518 throw runtime_error(
2519 "fundrawtransaction \"hexstring\" ( options )\n"
2520 "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
2521 "This will not modify existing inputs, and will add at most one change output to the outputs.\n"
2522 "No existing outputs will be modified unless \"subtractFeeFromOutputs\" is specified.\n"
2523 "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
2524 "The inputs added will not be signed, use signrawtransaction for that.\n"
2525 "Note that all existing inputs must have their previous output transaction be in the wallet.\n"
2526 "Note that all inputs selected must be of standard form and P2SH scripts must be\n"
2527 "in the wallet using importaddress or addmultisigaddress (to calculate fees).\n"
2528 "You can see whether this is the case by checking the \"solvable\" field in the listunspent output.\n"
2529 "Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n"
2530 "\nArguments:\n"
2531 "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
2532 "2. options (object, optional)\n"
2533 " {\n"
2534 " \"changeAddress\" (string, optional, default pool address) The bitcoin address to receive the change\n"
2535 " \"changePosition\" (numeric, optional, default random) The index of the change output\n"
2536 " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n"
2537 " \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n"
2538 " \"reserveChangeKey\" (boolean, optional, default true) Reserves the change output key from the keypool\n"
2539 " \"feeRate\" (numeric, optional, default not set: makes wallet determine the fee) Set a specific feerate (" + CURRENCY_UNIT + " per KB)\n"
2540 " \"subtractFeeFromOutputs\" (array, optional) A json array of integers.\n"
2541 " The fee will be equally deducted from the amount of each specified output.\n"
2542 " The outputs are specified by their zero-based index, before any change output is added.\n"
2543 " Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
2544 " If no outputs are specified here, the sender pays the fee.\n"
2545 " [vout_index,...]\n"
2546 " }\n"
2547 " for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n"
2548 "\nResult:\n"
2549 "{\n"
2550 " \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
2551 " \"fee\": n, (numeric) Fee in " + CURRENCY_UNIT + " the resulting transaction pays\n"
2552 " \"changepos\": n (numeric) The position of the added change output, or -1\n"
2553 "}\n"
2554 "\nExamples:\n"
2555 "\nCreate a transaction with no inputs\n"
2556 + HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") +
2557 "\nAdd sufficient unsigned inputs to meet the output value\n"
2558 + HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") +
2559 "\nSign the transaction\n"
2560 + HelpExampleCli("signrawtransaction", "\"fundedtransactionhex\"") +
2561 "\nSend the transaction\n"
2562 + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
2565 RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR));
2567 CTxDestination changeAddress = CNoDestination();
2568 int changePosition = -1;
2569 bool includeWatching = false;
2570 bool lockUnspents = false;
2571 bool reserveChangeKey = true;
2572 CFeeRate feeRate = CFeeRate(0);
2573 bool overrideEstimatedFeerate = false;
2574 UniValue subtractFeeFromOutputs;
2575 set<int> setSubtractFeeFromOutputs;
2577 if (request.params.size() > 1) {
2578 if (request.params[1].type() == UniValue::VBOOL) {
2579 // backward compatibility bool only fallback
2580 includeWatching = request.params[1].get_bool();
2582 else {
2583 RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ));
2585 UniValue options = request.params[1];
2587 RPCTypeCheckObj(options,
2589 {"changeAddress", UniValueType(UniValue::VSTR)},
2590 {"changePosition", UniValueType(UniValue::VNUM)},
2591 {"includeWatching", UniValueType(UniValue::VBOOL)},
2592 {"lockUnspents", UniValueType(UniValue::VBOOL)},
2593 {"reserveChangeKey", UniValueType(UniValue::VBOOL)},
2594 {"feeRate", UniValueType()}, // will be checked below
2595 {"subtractFeeFromOutputs", UniValueType(UniValue::VARR)},
2597 true, true);
2599 if (options.exists("changeAddress")) {
2600 CBitcoinAddress address(options["changeAddress"].get_str());
2602 if (!address.IsValid())
2603 throw JSONRPCError(RPC_INVALID_PARAMETER, "changeAddress must be a valid bitcoin address");
2605 changeAddress = address.Get();
2608 if (options.exists("changePosition"))
2609 changePosition = options["changePosition"].get_int();
2611 if (options.exists("includeWatching"))
2612 includeWatching = options["includeWatching"].get_bool();
2614 if (options.exists("lockUnspents"))
2615 lockUnspents = options["lockUnspents"].get_bool();
2617 if (options.exists("reserveChangeKey"))
2618 reserveChangeKey = options["reserveChangeKey"].get_bool();
2620 if (options.exists("feeRate"))
2622 feeRate = CFeeRate(AmountFromValue(options["feeRate"]));
2623 overrideEstimatedFeerate = true;
2626 if (options.exists("subtractFeeFromOutputs"))
2627 subtractFeeFromOutputs = options["subtractFeeFromOutputs"].get_array();
2631 // parse hex string from parameter
2632 CMutableTransaction tx;
2633 if (!DecodeHexTx(tx, request.params[0].get_str(), true))
2634 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
2636 if (tx.vout.size() == 0)
2637 throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output");
2639 if (changePosition != -1 && (changePosition < 0 || (unsigned int)changePosition > tx.vout.size()))
2640 throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds");
2642 for (unsigned int idx = 0; idx < subtractFeeFromOutputs.size(); idx++) {
2643 int pos = subtractFeeFromOutputs[idx].get_int();
2644 if (setSubtractFeeFromOutputs.count(pos))
2645 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, duplicated position: %d", pos));
2646 if (pos < 0)
2647 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, negative position: %d", pos));
2648 if (pos >= int(tx.vout.size()))
2649 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid parameter, position too large: %d", pos));
2650 setSubtractFeeFromOutputs.insert(pos);
2653 CAmount nFeeOut;
2654 string strFailReason;
2656 if(!pwalletMain->FundTransaction(tx, nFeeOut, overrideEstimatedFeerate, feeRate, changePosition, strFailReason, includeWatching, lockUnspents, setSubtractFeeFromOutputs, reserveChangeKey, changeAddress))
2657 throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
2659 UniValue result(UniValue::VOBJ);
2660 result.push_back(Pair("hex", EncodeHexTx(tx)));
2661 result.push_back(Pair("changepos", changePosition));
2662 result.push_back(Pair("fee", ValueFromAmount(nFeeOut)));
2664 return result;
2667 // Calculate the size of the transaction assuming all signatures are max size
2668 // Use DummySignatureCreator, which inserts 72 byte signatures everywhere.
2669 // TODO: re-use this in CWallet::CreateTransaction (right now
2670 // CreateTransaction uses the constructed dummy-signed tx to do a priority
2671 // calculation, but we should be able to refactor after priority is removed).
2672 // NOTE: this requires that all inputs must be in mapWallet (eg the tx should
2673 // be IsAllFromMe).
2674 int64_t CalculateMaximumSignedTxSize(const CTransaction &tx)
2676 CMutableTransaction txNew(tx);
2677 std::vector<pair<CWalletTx *, unsigned int>> vCoins;
2678 // Look up the inputs. We should have already checked that this transaction
2679 // IsAllFromMe(ISMINE_SPENDABLE), so every input should already be in our
2680 // wallet, with a valid index into the vout array.
2681 for (auto& input : tx.vin) {
2682 const auto mi = pwalletMain->mapWallet.find(input.prevout.hash);
2683 assert(mi != pwalletMain->mapWallet.end() && input.prevout.n < mi->second.tx->vout.size());
2684 vCoins.emplace_back(make_pair(&(mi->second), input.prevout.n));
2686 if (!pwalletMain->DummySignTx(txNew, vCoins)) {
2687 // This should never happen, because IsAllFromMe(ISMINE_SPENDABLE)
2688 // implies that we can sign for every input.
2689 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction contains inputs that cannot be signed");
2691 return GetVirtualTransactionSize(txNew);
2694 UniValue bumpfee(const JSONRPCRequest& request)
2696 if (!EnsureWalletIsAvailable(request.fHelp)) {
2697 return NullUniValue;
2700 if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
2701 throw runtime_error(
2702 "bumpfee \"txid\" ( options ) \n"
2703 "\nBumps the fee of an opt-in-RBF transaction T, replacing it with a new transaction B.\n"
2704 "An opt-in RBF transaction with the given txid must be in the wallet.\n"
2705 "The command will pay the additional fee by decreasing (or perhaps removing) its change output.\n"
2706 "If the change output is not big enough to cover the increased fee, the command will currently fail\n"
2707 "instead of adding new inputs to compensate. (A future implementation could improve this.)\n"
2708 "The command will fail if the wallet or mempool contains a transaction that spends one of T's outputs.\n"
2709 "By default, the new fee will be calculated automatically using estimatefee.\n"
2710 "The user can specify a confirmation target for estimatefee.\n"
2711 "Alternatively, the user can specify totalFee, or use RPC setpaytxfee to set a higher fee rate.\n"
2712 "At a minimum, the new fee rate must be high enough to pay an additional new relay fee (incrementalfee\n"
2713 "returned by getnetworkinfo) to enter the node's mempool.\n"
2714 "\nArguments:\n"
2715 "1. txid (string, required) The txid to be bumped\n"
2716 "2. options (object, optional)\n"
2717 " {\n"
2718 " \"confTarget\" (numeric, optional) Confirmation target (in blocks)\n"
2719 " \"totalFee\" (numeric, optional) Total fee (NOT feerate) to pay, in satoshis.\n"
2720 " In rare cases, the actual fee paid might be slightly higher than the specified\n"
2721 " totalFee if the tx change output has to be removed because it is too close to\n"
2722 " the dust threshold.\n"
2723 " \"replaceable\" (boolean, optional, default true) Whether the new transaction should still be\n"
2724 " marked bip-125 replaceable. If true, the sequence numbers in the transaction will\n"
2725 " be left unchanged from the original. If false, any input sequence numbers in the\n"
2726 " original transaction that were less than 0xfffffffe will be increased to 0xfffffffe\n"
2727 " so the new transaction will not be explicitly bip-125 replaceable (though it may\n"
2728 " still be replaceable in practice, for example if it has unconfirmed ancestors which\n"
2729 " are replaceable).\n"
2730 " }\n"
2731 "\nResult:\n"
2732 "{\n"
2733 " \"txid\": \"value\", (string) The id of the new transaction\n"
2734 " \"origfee\": n, (numeric) Fee of the replaced transaction\n"
2735 " \"fee\": n, (numeric) Fee of the new transaction\n"
2736 " \"errors\": [ str... ] (json array of strings) Errors encountered during processing (may be empty)\n"
2737 "}\n"
2738 "\nExamples:\n"
2739 "\nBump the fee, get the new transaction\'s txid\n" +
2740 HelpExampleCli("bumpfee", "<txid>"));
2743 RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ));
2744 uint256 hash;
2745 hash.SetHex(request.params[0].get_str());
2747 // retrieve the original tx from the wallet
2748 LOCK2(cs_main, pwalletMain->cs_wallet);
2749 EnsureWalletIsUnlocked();
2750 if (!pwalletMain->mapWallet.count(hash)) {
2751 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
2753 CWalletTx& wtx = pwalletMain->mapWallet[hash];
2755 if (pwalletMain->HasWalletSpend(hash)) {
2756 throw JSONRPCError(RPC_MISC_ERROR, "Transaction has descendants in the wallet");
2760 LOCK(mempool.cs);
2761 auto it = mempool.mapTx.find(hash);
2762 if (it != mempool.mapTx.end() && it->GetCountWithDescendants() > 1) {
2763 throw JSONRPCError(RPC_MISC_ERROR, "Transaction has descendants in the mempool");
2767 if (wtx.GetDepthInMainChain() != 0) {
2768 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction has been mined, or is conflicted with a mined transaction");
2771 if (!SignalsOptInRBF(wtx)) {
2772 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction is not BIP 125 replaceable");
2775 if (wtx.mapValue.count("replaced_by_txid")) {
2776 throw JSONRPCError(RPC_INVALID_REQUEST, strprintf("Cannot bump transaction %s which was already bumped by transaction %s", hash.ToString(), wtx.mapValue.at("replaced_by_txid")));
2779 // check that original tx consists entirely of our inputs
2780 // if not, we can't bump the fee, because the wallet has no way of knowing the value of the other inputs (thus the fee)
2781 if (!pwalletMain->IsAllFromMe(wtx, ISMINE_SPENDABLE)) {
2782 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction contains inputs that don't belong to this wallet");
2785 // figure out which output was change
2786 // if there was no change output or multiple change outputs, fail
2787 int nOutput = -1;
2788 for (size_t i = 0; i < wtx.tx->vout.size(); ++i) {
2789 if (pwalletMain->IsChange(wtx.tx->vout[i])) {
2790 if (nOutput != -1) {
2791 throw JSONRPCError(RPC_MISC_ERROR, "Transaction has multiple change outputs");
2793 nOutput = i;
2796 if (nOutput == -1) {
2797 throw JSONRPCError(RPC_MISC_ERROR, "Transaction does not have a change output");
2800 // Calculate the expected size of the new transaction.
2801 int64_t txSize = GetVirtualTransactionSize(*(wtx.tx));
2802 const int64_t maxNewTxSize = CalculateMaximumSignedTxSize(*wtx.tx);
2804 // optional parameters
2805 bool specifiedConfirmTarget = false;
2806 int newConfirmTarget = nTxConfirmTarget;
2807 CAmount totalFee = 0;
2808 bool replaceable = true;
2809 if (request.params.size() > 1) {
2810 UniValue options = request.params[1];
2811 RPCTypeCheckObj(options,
2813 {"confTarget", UniValueType(UniValue::VNUM)},
2814 {"totalFee", UniValueType(UniValue::VNUM)},
2815 {"replaceable", UniValueType(UniValue::VBOOL)},
2817 true, true);
2819 if (options.exists("confTarget") && options.exists("totalFee")) {
2820 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.");
2821 } else if (options.exists("confTarget")) {
2822 specifiedConfirmTarget = true;
2823 newConfirmTarget = options["confTarget"].get_int();
2824 if (newConfirmTarget <= 0) { // upper-bound will be checked by estimatefee/smartfee
2825 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid confTarget (cannot be <= 0)");
2827 } else if (options.exists("totalFee")) {
2828 totalFee = options["totalFee"].get_int64();
2829 CAmount requiredFee = CWallet::GetRequiredFee(maxNewTxSize);
2830 if (totalFee < requiredFee ) {
2831 throw JSONRPCError(RPC_INVALID_PARAMETER,
2832 strprintf("Insufficient totalFee (cannot be less than required fee %s)",
2833 FormatMoney(requiredFee)));
2837 if (options.exists("replaceable")) {
2838 replaceable = options["replaceable"].get_bool();
2842 // calculate the old fee and fee-rate
2843 CAmount nOldFee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut();
2844 CFeeRate nOldFeeRate(nOldFee, txSize);
2845 CAmount nNewFee;
2846 CFeeRate nNewFeeRate;
2847 // The wallet uses a conservative WALLET_INCREMENTAL_RELAY_FEE value to
2848 // future proof against changes to network wide policy for incremental relay
2849 // fee that our node may not be aware of.
2850 CFeeRate walletIncrementalRelayFee = CFeeRate(WALLET_INCREMENTAL_RELAY_FEE);
2851 if (::incrementalRelayFee > walletIncrementalRelayFee) {
2852 walletIncrementalRelayFee = ::incrementalRelayFee;
2855 if (totalFee > 0) {
2856 CAmount minTotalFee = nOldFeeRate.GetFee(maxNewTxSize) + ::incrementalRelayFee.GetFee(maxNewTxSize);
2857 if (totalFee < minTotalFee) {
2858 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Insufficient totalFee, must be at least %s (oldFee %s + incrementalFee %s)",
2859 FormatMoney(minTotalFee), FormatMoney(nOldFeeRate.GetFee(maxNewTxSize)), FormatMoney(::incrementalRelayFee.GetFee(maxNewTxSize))));
2861 nNewFee = totalFee;
2862 nNewFeeRate = CFeeRate(totalFee, maxNewTxSize);
2863 } else {
2864 // if user specified a confirm target then don't consider any global payTxFee
2865 if (specifiedConfirmTarget) {
2866 nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool, CAmount(0));
2868 // otherwise use the regular wallet logic to select payTxFee or default confirm target
2869 else {
2870 nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool);
2873 nNewFeeRate = CFeeRate(nNewFee, maxNewTxSize);
2875 // New fee rate must be at least old rate + minimum incremental relay rate
2876 // walletIncrementalRelayFee.GetFeePerK() should be exact, because it's initialized
2877 // in that unit (fee per kb).
2878 // However, nOldFeeRate is a calculated value from the tx fee/size, so
2879 // add 1 satoshi to the result, because it may have been rounded down.
2880 if (nNewFeeRate.GetFeePerK() < nOldFeeRate.GetFeePerK() + 1 + walletIncrementalRelayFee.GetFeePerK()) {
2881 nNewFeeRate = CFeeRate(nOldFeeRate.GetFeePerK() + 1 + walletIncrementalRelayFee.GetFeePerK());
2882 nNewFee = nNewFeeRate.GetFee(maxNewTxSize);
2886 // Check that in all cases the new fee doesn't violate maxTxFee
2887 if (nNewFee > maxTxFee) {
2888 throw JSONRPCError(RPC_MISC_ERROR,
2889 strprintf("Specified or calculated fee %s is too high (cannot be higher than maxTxFee %s)",
2890 FormatMoney(nNewFee), FormatMoney(maxTxFee)));
2893 // check that fee rate is higher than mempool's minimum fee
2894 // (no point in bumping fee if we know that the new tx won't be accepted to the mempool)
2895 // This may occur if the user set TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps,
2896 // in a rare situation where the mempool minimum fee increased significantly since the fee estimation just a
2897 // moment earlier. In this case, we report an error to the user, who may use totalFee to make an adjustment.
2898 CFeeRate minMempoolFeeRate = mempool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
2899 if (nNewFeeRate.GetFeePerK() < minMempoolFeeRate.GetFeePerK()) {
2900 throw JSONRPCError(RPC_MISC_ERROR, strprintf("New fee rate (%s) is less than the minimum fee rate (%s) to get into the mempool. totalFee value should to be at least %s or settxfee value should be at least %s to add transaction.", FormatMoney(nNewFeeRate.GetFeePerK()), FormatMoney(minMempoolFeeRate.GetFeePerK()), FormatMoney(minMempoolFeeRate.GetFee(maxNewTxSize)), FormatMoney(minMempoolFeeRate.GetFeePerK())));
2903 // Now modify the output to increase the fee.
2904 // If the output is not large enough to pay the fee, fail.
2905 CAmount nDelta = nNewFee - nOldFee;
2906 assert(nDelta > 0);
2907 CMutableTransaction tx(*(wtx.tx));
2908 CTxOut* poutput = &(tx.vout[nOutput]);
2909 if (poutput->nValue < nDelta) {
2910 throw JSONRPCError(RPC_MISC_ERROR, "Change output is too small to bump the fee");
2913 // If the output would become dust, discard it (converting the dust to fee)
2914 poutput->nValue -= nDelta;
2915 if (poutput->nValue <= poutput->GetDustThreshold(::dustRelayFee)) {
2916 LogPrint("rpc", "Bumping fee and discarding dust output\n");
2917 nNewFee += poutput->nValue;
2918 tx.vout.erase(tx.vout.begin() + nOutput);
2921 // Mark new tx not replaceable, if requested.
2922 if (!replaceable) {
2923 for (auto& input : tx.vin) {
2924 if (input.nSequence < 0xfffffffe) input.nSequence = 0xfffffffe;
2928 // sign the new tx
2929 CTransaction txNewConst(tx);
2930 int nIn = 0;
2931 for (auto& input : tx.vin) {
2932 std::map<uint256, CWalletTx>::const_iterator mi = pwalletMain->mapWallet.find(input.prevout.hash);
2933 assert(mi != pwalletMain->mapWallet.end() && input.prevout.n < mi->second.tx->vout.size());
2934 const CScript& scriptPubKey = mi->second.tx->vout[input.prevout.n].scriptPubKey;
2935 const CAmount& amount = mi->second.tx->vout[input.prevout.n].nValue;
2936 SignatureData sigdata;
2937 if (!ProduceSignature(TransactionSignatureCreator(pwalletMain, &txNewConst, nIn, amount, SIGHASH_ALL), scriptPubKey, sigdata)) {
2938 throw JSONRPCError(RPC_WALLET_ERROR, "Can't sign transaction.");
2940 UpdateTransaction(tx, nIn, sigdata);
2941 nIn++;
2944 // commit/broadcast the tx
2945 CReserveKey reservekey(pwalletMain);
2946 CWalletTx wtxBumped(pwalletMain, MakeTransactionRef(std::move(tx)));
2947 wtxBumped.mapValue = wtx.mapValue;
2948 wtxBumped.mapValue["replaces_txid"] = hash.ToString();
2949 wtxBumped.vOrderForm = wtx.vOrderForm;
2950 wtxBumped.strFromAccount = wtx.strFromAccount;
2951 wtxBumped.fTimeReceivedIsTxTime = true;
2952 wtxBumped.fFromMe = true;
2953 CValidationState state;
2954 if (!pwalletMain->CommitTransaction(wtxBumped, reservekey, g_connman.get(), state)) {
2955 // NOTE: CommitTransaction never returns false, so this should never happen.
2956 throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Error: The transaction was rejected! Reason given: %s", state.GetRejectReason()));
2959 UniValue vErrors(UniValue::VARR);
2960 if (state.IsInvalid()) {
2961 // This can happen if the mempool rejected the transaction. Report
2962 // what happened in the "errors" response.
2963 vErrors.push_back(strprintf("Error: The transaction was rejected: %s", FormatStateMessage(state)));
2966 // mark the original tx as bumped
2967 if (!pwalletMain->MarkReplaced(wtx.GetHash(), wtxBumped.GetHash())) {
2968 // TODO: see if JSON-RPC has a standard way of returning a response
2969 // along with an exception. It would be good to return information about
2970 // wtxBumped to the caller even if marking the original transaction
2971 // replaced does not succeed for some reason.
2972 vErrors.push_back("Error: Created new bumpfee transaction but could not mark the original transaction as replaced.");
2975 UniValue result(UniValue::VOBJ);
2976 result.push_back(Pair("txid", wtxBumped.GetHash().GetHex()));
2977 result.push_back(Pair("origfee", ValueFromAmount(nOldFee)));
2978 result.push_back(Pair("fee", ValueFromAmount(nNewFee)));
2979 result.push_back(Pair("errors", vErrors));
2981 return result;
2984 extern UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
2985 extern UniValue importprivkey(const JSONRPCRequest& request);
2986 extern UniValue importaddress(const JSONRPCRequest& request);
2987 extern UniValue importpubkey(const JSONRPCRequest& request);
2988 extern UniValue dumpwallet(const JSONRPCRequest& request);
2989 extern UniValue importwallet(const JSONRPCRequest& request);
2990 extern UniValue importprunedfunds(const JSONRPCRequest& request);
2991 extern UniValue removeprunedfunds(const JSONRPCRequest& request);
2992 extern UniValue importmulti(const JSONRPCRequest& request);
2994 static const CRPCCommand commands[] =
2995 { // category name actor (function) okSafeMode
2996 // --------------------- ------------------------ ----------------------- ----------
2997 { "rawtransactions", "fundrawtransaction", &fundrawtransaction, false, {"hexstring","options"} },
2998 { "hidden", "resendwallettransactions", &resendwallettransactions, true, {} },
2999 { "wallet", "abandontransaction", &abandontransaction, false, {"txid"} },
3000 { "wallet", "addmultisigaddress", &addmultisigaddress, true, {"nrequired","keys","account"} },
3001 { "wallet", "addwitnessaddress", &addwitnessaddress, true, {"address"} },
3002 { "wallet", "backupwallet", &backupwallet, true, {"destination"} },
3003 { "wallet", "bumpfee", &bumpfee, true, {"txid", "options"} },
3004 { "wallet", "dumpprivkey", &dumpprivkey, true, {"address"} },
3005 { "wallet", "dumpwallet", &dumpwallet, true, {"filename"} },
3006 { "wallet", "encryptwallet", &encryptwallet, true, {"passphrase"} },
3007 { "wallet", "getaccountaddress", &getaccountaddress, true, {"account"} },
3008 { "wallet", "getaccount", &getaccount, true, {"address"} },
3009 { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true, {"account"} },
3010 { "wallet", "getbalance", &getbalance, false, {"account","minconf","include_watchonly"} },
3011 { "wallet", "getnewaddress", &getnewaddress, true, {"account"} },
3012 { "wallet", "getrawchangeaddress", &getrawchangeaddress, true, {} },
3013 { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false, {"account","minconf"} },
3014 { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false, {"address","minconf"} },
3015 { "wallet", "gettransaction", &gettransaction, false, {"txid","include_watchonly"} },
3016 { "wallet", "getunconfirmedbalance", &getunconfirmedbalance, false, {} },
3017 { "wallet", "getwalletinfo", &getwalletinfo, false, {} },
3018 { "wallet", "importmulti", &importmulti, true, {"requests","options"} },
3019 { "wallet", "importprivkey", &importprivkey, true, {"privkey","label","rescan"} },
3020 { "wallet", "importwallet", &importwallet, true, {"filename"} },
3021 { "wallet", "importaddress", &importaddress, true, {"address","label","rescan","p2sh"} },
3022 { "wallet", "importprunedfunds", &importprunedfunds, true, {"rawtransaction","txoutproof"} },
3023 { "wallet", "importpubkey", &importpubkey, true, {"pubkey","label","rescan"} },
3024 { "wallet", "keypoolrefill", &keypoolrefill, true, {"newsize"} },
3025 { "wallet", "listaccounts", &listaccounts, false, {"minconf","include_watchonly"} },
3026 { "wallet", "listaddressgroupings", &listaddressgroupings, false, {} },
3027 { "wallet", "listlockunspent", &listlockunspent, false, {} },
3028 { "wallet", "listreceivedbyaccount", &listreceivedbyaccount, false, {"minconf","include_empty","include_watchonly"} },
3029 { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false, {"minconf","include_empty","include_watchonly"} },
3030 { "wallet", "listsinceblock", &listsinceblock, false, {"blockhash","target_confirmations","include_watchonly"} },
3031 { "wallet", "listtransactions", &listtransactions, false, {"account","count","skip","include_watchonly"} },
3032 { "wallet", "listunspent", &listunspent, false, {"minconf","maxconf","addresses","include_unsafe"} },
3033 { "wallet", "lockunspent", &lockunspent, true, {"unlock","transactions"} },
3034 { "wallet", "move", &movecmd, false, {"fromaccount","toaccount","amount","minconf","comment"} },
3035 { "wallet", "sendfrom", &sendfrom, false, {"fromaccount","toaddress","amount","minconf","comment","comment_to"} },
3036 { "wallet", "sendmany", &sendmany, false, {"fromaccount","amounts","minconf","comment","subtractfeefrom"} },
3037 { "wallet", "sendtoaddress", &sendtoaddress, false, {"address","amount","comment","comment_to","subtractfeefromamount"} },
3038 { "wallet", "setaccount", &setaccount, true, {"address","account"} },
3039 { "wallet", "settxfee", &settxfee, true, {"amount"} },
3040 { "wallet", "signmessage", &signmessage, true, {"address","message"} },
3041 { "wallet", "walletlock", &walletlock, true, {} },
3042 { "wallet", "walletpassphrasechange", &walletpassphrasechange, true, {"oldpassphrase","newpassphrase"} },
3043 { "wallet", "walletpassphrase", &walletpassphrase, true, {"passphrase","timeout"} },
3044 { "wallet", "removeprunedfunds", &removeprunedfunds, true, {"txid"} },
3047 void RegisterWalletRPCCommands(CRPCTable &t)
3049 if (GetBoolArg("-disablewallet", false))
3050 return;
3052 for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
3053 t.appendCommand(commands[vcidx].name, &commands[vcidx]);