1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 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.
15 #include "utilmoneystr.h"
21 #include <boost/assign/list_of.hpp>
22 #include "json/json_spirit_utils.h"
23 #include "json/json_spirit_value.h"
26 using namespace boost;
27 using namespace boost::assign;
28 using namespace json_spirit;
30 int64_t nWalletUnlockTime;
31 static CCriticalSection cs_nWalletUnlockTime;
33 std::string HelpRequiringPassphrase()
35 return pwalletMain && pwalletMain->IsCrypted()
36 ? "\nRequires wallet passphrase to be set with walletpassphrase call."
40 void EnsureWalletIsUnlocked()
42 if (pwalletMain->IsLocked())
43 throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
46 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
48 int confirms = wtx.GetDepthInMainChain();
49 entry.push_back(Pair("confirmations", confirms));
51 entry.push_back(Pair("generated", true));
54 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
55 entry.push_back(Pair("blockindex", wtx.nIndex));
56 entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
58 uint256 hash = wtx.GetHash();
59 entry.push_back(Pair("txid", hash.GetHex()));
61 BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
62 conflicts.push_back(conflict.GetHex());
63 entry.push_back(Pair("walletconflicts", conflicts));
64 entry.push_back(Pair("time", wtx.GetTxTime()));
65 entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived));
66 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
67 entry.push_back(Pair(item.first, item.second));
70 string AccountFromValue(const Value& value)
72 string strAccount = value.get_str();
73 if (strAccount == "*")
74 throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Invalid account name");
78 Value getnewaddress(const Array& params, bool fHelp)
80 if (fHelp || params.size() > 1)
82 "getnewaddress ( \"account\" )\n"
83 "\nReturns a new Bitcoin address for receiving payments.\n"
84 "If 'account' is specified (recommended), it is added to the address book \n"
85 "so payments received with the address will be credited to 'account'.\n"
87 "1. \"account\" (string, optional) 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"
89 "\"bitcoinaddress\" (string) The new bitcoin address\n"
91 + HelpExampleCli("getnewaddress", "")
92 + HelpExampleCli("getnewaddress", "\"\"")
93 + HelpExampleCli("getnewaddress", "\"myaccount\"")
94 + HelpExampleRpc("getnewaddress", "\"myaccount\"")
97 // Parse the account first so we don't generate a key if there's an error
99 if (params.size() > 0)
100 strAccount = AccountFromValue(params[0]);
102 if (!pwalletMain->IsLocked())
103 pwalletMain->TopUpKeyPool();
105 // Generate a new key that is added to wallet
107 if (!pwalletMain->GetKeyFromPool(newKey))
108 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
109 CKeyID keyID = newKey.GetID();
111 pwalletMain->SetAddressBook(keyID, strAccount, "receive");
113 return CBitcoinAddress(keyID).ToString();
117 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
119 CWalletDB walletdb(pwalletMain->strWalletFile);
122 walletdb.ReadAccount(strAccount, account);
124 bool bKeyUsed = false;
126 // Check if the current key has been used
127 if (account.vchPubKey.IsValid())
129 CScript scriptPubKey = GetScriptForDestination(account.vchPubKey.GetID());
130 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
131 it != pwalletMain->mapWallet.end() && account.vchPubKey.IsValid();
134 const CWalletTx& wtx = (*it).second;
135 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
136 if (txout.scriptPubKey == scriptPubKey)
141 // Generate a new key
142 if (!account.vchPubKey.IsValid() || bForceNew || bKeyUsed)
144 if (!pwalletMain->GetKeyFromPool(account.vchPubKey))
145 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
147 pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, "receive");
148 walletdb.WriteAccount(strAccount, account);
151 return CBitcoinAddress(account.vchPubKey.GetID());
154 Value getaccountaddress(const Array& params, bool fHelp)
156 if (fHelp || params.size() != 1)
158 "getaccountaddress \"account\"\n"
159 "\nReturns the current Bitcoin address for receiving payments to this account.\n"
161 "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"
163 "\"bitcoinaddress\" (string) The account bitcoin address\n"
165 + HelpExampleCli("getaccountaddress", "")
166 + HelpExampleCli("getaccountaddress", "\"\"")
167 + HelpExampleCli("getaccountaddress", "\"myaccount\"")
168 + HelpExampleRpc("getaccountaddress", "\"myaccount\"")
171 // Parse the account first so we don't generate a key if there's an error
172 string strAccount = AccountFromValue(params[0]);
176 ret = GetAccountAddress(strAccount).ToString();
182 Value getrawchangeaddress(const Array& params, bool fHelp)
184 if (fHelp || params.size() > 1)
186 "getrawchangeaddress\n"
187 "\nReturns a new Bitcoin address, for receiving change.\n"
188 "This is for use with raw transactions, NOT normal use.\n"
190 "\"address\" (string) The address\n"
192 + HelpExampleCli("getrawchangeaddress", "")
193 + HelpExampleRpc("getrawchangeaddress", "")
196 if (!pwalletMain->IsLocked())
197 pwalletMain->TopUpKeyPool();
199 CReserveKey reservekey(pwalletMain);
201 if (!reservekey.GetReservedKey(vchPubKey))
202 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
204 reservekey.KeepKey();
206 CKeyID keyID = vchPubKey.GetID();
208 return CBitcoinAddress(keyID).ToString();
212 Value setaccount(const Array& params, bool fHelp)
214 if (fHelp || params.size() < 1 || params.size() > 2)
216 "setaccount \"bitcoinaddress\" \"account\"\n"
217 "\nSets the account associated with the given address.\n"
219 "1. \"bitcoinaddress\" (string, required) The bitcoin address to be associated with an account.\n"
220 "2. \"account\" (string, required) The account to assign the address to.\n"
222 + HelpExampleCli("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"tabby\"")
223 + HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"tabby\"")
226 CBitcoinAddress address(params[0].get_str());
227 if (!address.IsValid())
228 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
232 if (params.size() > 1)
233 strAccount = AccountFromValue(params[1]);
235 // Only add the account if the address is yours.
236 if (IsMine(*pwalletMain, address.Get()))
238 // Detect when changing the account of an address that is the 'unused current key' of another account:
239 if (pwalletMain->mapAddressBook.count(address.Get()))
241 string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name;
242 if (address == GetAccountAddress(strOldAccount))
243 GetAccountAddress(strOldAccount, true);
245 pwalletMain->SetAddressBook(address.Get(), strAccount, "receive");
248 throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
254 Value getaccount(const Array& params, bool fHelp)
256 if (fHelp || params.size() != 1)
258 "getaccount \"bitcoinaddress\"\n"
259 "\nReturns the account associated with the given address.\n"
261 "1. \"bitcoinaddress\" (string, required) The bitcoin address for account lookup.\n"
263 "\"accountname\" (string) the account address\n"
265 + HelpExampleCli("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
266 + HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
269 CBitcoinAddress address(params[0].get_str());
270 if (!address.IsValid())
271 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
274 map<CTxDestination, CAddressBookData>::iterator mi = pwalletMain->mapAddressBook.find(address.Get());
275 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty())
276 strAccount = (*mi).second.name;
281 Value getaddressesbyaccount(const Array& params, bool fHelp)
283 if (fHelp || params.size() != 1)
285 "getaddressesbyaccount \"account\"\n"
286 "\nReturns the list of addresses for the given account.\n"
288 "1. \"account\" (string, required) The account name.\n"
290 "[ (json array of string)\n"
291 " \"bitcoinaddress\" (string) a bitcoin address associated with the given account\n"
295 + HelpExampleCli("getaddressesbyaccount", "\"tabby\"")
296 + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
299 string strAccount = AccountFromValue(params[0]);
301 // Find all addresses that have the given account
303 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
305 const CBitcoinAddress& address = item.first;
306 const string& strName = item.second.name;
307 if (strName == strAccount)
308 ret.push_back(address.ToString());
313 void SendMoney(const CTxDestination &address, CAmount nValue, CWalletTx& wtxNew)
317 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid amount");
319 if (nValue > pwalletMain->GetBalance())
320 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
323 if (pwalletMain->IsLocked())
325 strError = "Error: Wallet locked, unable to create transaction!";
326 LogPrintf("SendMoney() : %s", strError);
327 throw JSONRPCError(RPC_WALLET_ERROR, strError);
330 // Parse Bitcoin address
331 CScript scriptPubKey = GetScriptForDestination(address);
333 // Create and send the transaction
334 CReserveKey reservekey(pwalletMain);
335 CAmount nFeeRequired;
336 if (!pwalletMain->CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError))
338 if (nValue + nFeeRequired > pwalletMain->GetBalance())
339 strError = strprintf("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!", FormatMoney(nFeeRequired));
340 LogPrintf("SendMoney() : %s\n", strError);
341 throw JSONRPCError(RPC_WALLET_ERROR, strError);
343 if (!pwalletMain->CommitTransaction(wtxNew, reservekey))
344 throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
347 Value sendtoaddress(const Array& params, bool fHelp)
349 if (fHelp || params.size() < 2 || params.size() > 4)
351 "sendtoaddress \"bitcoinaddress\" amount ( \"comment\" \"comment-to\" )\n"
352 "\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n"
353 + HelpRequiringPassphrase() +
355 "1. \"bitcoinaddress\" (string, required) The bitcoin address to send to.\n"
356 "2. \"amount\" (numeric, required) The amount in btc to send. eg 0.1\n"
357 "3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
358 " This is not part of the transaction, just kept in your wallet.\n"
359 "4. \"comment-to\" (string, optional) A comment to store the name of the person or organization \n"
360 " to which you're sending the transaction. This is not part of the \n"
361 " transaction, just kept in your wallet.\n"
363 "\"transactionid\" (string) The transaction id.\n"
365 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
366 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
367 + HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
370 CBitcoinAddress address(params[0].get_str());
371 if (!address.IsValid())
372 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
375 CAmount nAmount = AmountFromValue(params[1]);
379 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
380 wtx.mapValue["comment"] = params[2].get_str();
381 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
382 wtx.mapValue["to"] = params[3].get_str();
384 EnsureWalletIsUnlocked();
386 SendMoney(address.Get(), nAmount, wtx);
388 return wtx.GetHash().GetHex();
391 Value listaddressgroupings(const Array& params, bool fHelp)
395 "listaddressgroupings\n"
396 "\nLists groups of addresses which have had their common ownership\n"
397 "made public by common use as inputs or as the resulting change\n"
398 "in past transactions\n"
403 " \"bitcoinaddress\", (string) The bitcoin address\n"
404 " amount, (numeric) The amount in btc\n"
405 " \"account\" (string, optional) The account\n"
412 + HelpExampleCli("listaddressgroupings", "")
413 + HelpExampleRpc("listaddressgroupings", "")
417 map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
418 BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
421 BOOST_FOREACH(CTxDestination address, grouping)
424 addressInfo.push_back(CBitcoinAddress(address).ToString());
425 addressInfo.push_back(ValueFromAmount(balances[address]));
427 LOCK(pwalletMain->cs_wallet);
428 if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end())
429 addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second.name);
431 jsonGrouping.push_back(addressInfo);
433 jsonGroupings.push_back(jsonGrouping);
435 return jsonGroupings;
438 Value signmessage(const Array& params, bool fHelp)
440 if (fHelp || params.size() != 2)
442 "signmessage \"bitcoinaddress\" \"message\"\n"
443 "\nSign a message with the private key of an address"
444 + HelpRequiringPassphrase() + "\n"
446 "1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the private key.\n"
447 "2. \"message\" (string, required) The message to create a signature of.\n"
449 "\"signature\" (string) The signature of the message encoded in base 64\n"
451 "\nUnlock the wallet for 30 seconds\n"
452 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
453 "\nCreate the signature\n"
454 + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
455 "\nVerify the signature\n"
456 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
458 + HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"my message\"")
461 EnsureWalletIsUnlocked();
463 string strAddress = params[0].get_str();
464 string strMessage = params[1].get_str();
466 CBitcoinAddress addr(strAddress);
468 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
471 if (!addr.GetKeyID(keyID))
472 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
475 if (!pwalletMain->GetKey(keyID, key))
476 throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
478 CHashWriter ss(SER_GETHASH, 0);
479 ss << strMessageMagic;
482 vector<unsigned char> vchSig;
483 if (!key.SignCompact(ss.GetHash(), vchSig))
484 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
486 return EncodeBase64(&vchSig[0], vchSig.size());
489 Value getreceivedbyaddress(const Array& params, bool fHelp)
491 if (fHelp || params.size() < 1 || params.size() > 2)
493 "getreceivedbyaddress \"bitcoinaddress\" ( minconf )\n"
494 "\nReturns the total amount received by the given bitcoinaddress in transactions with at least minconf confirmations.\n"
496 "1. \"bitcoinaddress\" (string, required) The bitcoin address for transactions.\n"
497 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
499 "amount (numeric) The total amount in btc received at this address.\n"
501 "\nThe amount from transactions with at least 1 confirmation\n"
502 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"") +
503 "\nThe amount including unconfirmed transactions, zero confirmations\n"
504 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 0") +
505 "\nThe amount with at least 6 confirmation, very safe\n"
506 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 6") +
507 "\nAs a json rpc call\n"
508 + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", 6")
512 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
513 if (!address.IsValid())
514 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
515 CScript scriptPubKey = GetScriptForDestination(address.Get());
516 if (!IsMine(*pwalletMain,scriptPubKey))
519 // Minimum confirmations
521 if (params.size() > 1)
522 nMinDepth = params[1].get_int();
526 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
528 const CWalletTx& wtx = (*it).second;
529 if (wtx.IsCoinBase() || !IsFinalTx(wtx))
532 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
533 if (txout.scriptPubKey == scriptPubKey)
534 if (wtx.GetDepthInMainChain() >= nMinDepth)
535 nAmount += txout.nValue;
538 return ValueFromAmount(nAmount);
542 Value getreceivedbyaccount(const Array& params, bool fHelp)
544 if (fHelp || params.size() < 1 || params.size() > 2)
546 "getreceivedbyaccount \"account\" ( minconf )\n"
547 "\nReturns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
549 "1. \"account\" (string, required) The selected account, may be the default account using \"\".\n"
550 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
552 "amount (numeric) The total amount in btc received for this account.\n"
554 "\nAmount received by the default account with at least 1 confirmation\n"
555 + HelpExampleCli("getreceivedbyaccount", "\"\"") +
556 "\nAmount received at the tabby account including unconfirmed amounts with zero confirmations\n"
557 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 0") +
558 "\nThe amount with at least 6 confirmation, very safe\n"
559 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 6") +
560 "\nAs a json rpc call\n"
561 + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
564 // Minimum confirmations
566 if (params.size() > 1)
567 nMinDepth = params[1].get_int();
569 // Get the set of pub keys assigned to account
570 string strAccount = AccountFromValue(params[0]);
571 set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount);
575 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
577 const CWalletTx& wtx = (*it).second;
578 if (wtx.IsCoinBase() || !IsFinalTx(wtx))
581 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
583 CTxDestination address;
584 if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
585 if (wtx.GetDepthInMainChain() >= nMinDepth)
586 nAmount += txout.nValue;
590 return (double)nAmount / (double)COIN;
594 CAmount GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter)
596 CAmount nBalance = 0;
598 // Tally wallet transactions
599 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
601 const CWalletTx& wtx = (*it).second;
602 if (!IsFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
605 CAmount nReceived, nSent, nFee;
606 wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter);
608 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
609 nBalance += nReceived;
610 nBalance -= nSent + nFee;
613 // Tally internal accounting entries
614 nBalance += walletdb.GetAccountCreditDebit(strAccount);
619 CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter)
621 CWalletDB walletdb(pwalletMain->strWalletFile);
622 return GetAccountBalance(walletdb, strAccount, nMinDepth, filter);
626 Value getbalance(const Array& params, bool fHelp)
628 if (fHelp || params.size() > 3)
630 "getbalance ( \"account\" minconf includeWatchonly )\n"
631 "\nIf account is not specified, returns the server's total available balance.\n"
632 "If account is specified, returns the balance in the account.\n"
633 "Note that the account \"\" is not the same as leaving the parameter out.\n"
634 "The server total may be different to the balance in the default \"\" account.\n"
636 "1. \"account\" (string, optional) The selected account, or \"*\" for entire wallet. It may be the default account using \"\".\n"
637 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
638 "3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n"
640 "amount (numeric) The total amount in btc received for this account.\n"
642 "\nThe total amount in the server across all accounts\n"
643 + HelpExampleCli("getbalance", "") +
644 "\nThe total amount in the server across all accounts, with at least 5 confirmations\n"
645 + HelpExampleCli("getbalance", "\"*\" 6") +
646 "\nThe total amount in the default account with at least 1 confirmation\n"
647 + HelpExampleCli("getbalance", "\"\"") +
648 "\nThe total amount in the account named tabby with at least 6 confirmations\n"
649 + HelpExampleCli("getbalance", "\"tabby\" 6") +
650 "\nAs a json rpc call\n"
651 + HelpExampleRpc("getbalance", "\"tabby\", 6")
654 if (params.size() == 0)
655 return ValueFromAmount(pwalletMain->GetBalance());
658 if (params.size() > 1)
659 nMinDepth = params[1].get_int();
660 isminefilter filter = ISMINE_SPENDABLE;
661 if(params.size() > 2)
662 if(params[2].get_bool())
663 filter = filter | ISMINE_WATCH_ONLY;
665 if (params[0].get_str() == "*") {
666 // Calculate total balance a different way from GetBalance()
667 // (GetBalance() sums up all unspent TxOuts)
668 // getbalance and getbalance '*' 0 should return the same number
669 CAmount nBalance = 0;
670 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
672 const CWalletTx& wtx = (*it).second;
673 if (!wtx.IsTrusted() || wtx.GetBlocksToMaturity() > 0)
677 string strSentAccount;
678 list<COutputEntry> listReceived;
679 list<COutputEntry> listSent;
680 wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
681 if (wtx.GetDepthInMainChain() >= nMinDepth)
683 BOOST_FOREACH(const COutputEntry& r, listReceived)
684 nBalance += r.amount;
686 BOOST_FOREACH(const COutputEntry& s, listSent)
687 nBalance -= s.amount;
690 return ValueFromAmount(nBalance);
693 string strAccount = AccountFromValue(params[0]);
695 CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, filter);
697 return ValueFromAmount(nBalance);
700 Value getunconfirmedbalance(const Array ¶ms, bool fHelp)
702 if (fHelp || params.size() > 0)
704 "getunconfirmedbalance\n"
705 "Returns the server's total unconfirmed balance\n");
706 return ValueFromAmount(pwalletMain->GetUnconfirmedBalance());
710 Value movecmd(const Array& params, bool fHelp)
712 if (fHelp || params.size() < 3 || params.size() > 5)
714 "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
715 "\nMove a specified amount from one account in your wallet to another.\n"
717 "1. \"fromaccount\" (string, required) The name of the account to move funds from. May be the default account using \"\".\n"
718 "2. \"toaccount\" (string, required) The name of the account to move funds to. May be the default account using \"\".\n"
719 "3. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
720 "4. \"comment\" (string, optional) An optional comment, stored in the wallet only.\n"
722 "true|false (boolean) true if successfull.\n"
724 "\nMove 0.01 btc from the default account to the account named tabby\n"
725 + HelpExampleCli("move", "\"\" \"tabby\" 0.01") +
726 "\nMove 0.01 btc timotei to akiko with a comment and funds have 6 confirmations\n"
727 + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") +
728 "\nAs a json rpc call\n"
729 + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
732 string strFrom = AccountFromValue(params[0]);
733 string strTo = AccountFromValue(params[1]);
734 CAmount nAmount = AmountFromValue(params[2]);
735 if (params.size() > 3)
736 // unused parameter, used to be nMinDepth, keep type-checking it though
737 (void)params[3].get_int();
739 if (params.size() > 4)
740 strComment = params[4].get_str();
742 CWalletDB walletdb(pwalletMain->strWalletFile);
743 if (!walletdb.TxnBegin())
744 throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
746 int64_t nNow = GetAdjustedTime();
749 CAccountingEntry debit;
750 debit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
751 debit.strAccount = strFrom;
752 debit.nCreditDebit = -nAmount;
754 debit.strOtherAccount = strTo;
755 debit.strComment = strComment;
756 walletdb.WriteAccountingEntry(debit);
759 CAccountingEntry credit;
760 credit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
761 credit.strAccount = strTo;
762 credit.nCreditDebit = nAmount;
764 credit.strOtherAccount = strFrom;
765 credit.strComment = strComment;
766 walletdb.WriteAccountingEntry(credit);
768 if (!walletdb.TxnCommit())
769 throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
775 Value sendfrom(const Array& params, bool fHelp)
777 if (fHelp || params.size() < 3 || params.size() > 6)
779 "sendfrom \"fromaccount\" \"tobitcoinaddress\" amount ( minconf \"comment\" \"comment-to\" )\n"
780 "\nSent an amount from an account to a bitcoin address.\n"
781 "The amount is a real and is rounded to the nearest 0.00000001."
782 + HelpRequiringPassphrase() + "\n"
784 "1. \"fromaccount\" (string, required) The name of the account to send funds from. May be the default account using \"\".\n"
785 "2. \"tobitcoinaddress\" (string, required) The bitcoin address to send funds to.\n"
786 "3. amount (numeric, required) The amount in btc. (transaction fee is added on top).\n"
787 "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
788 "5. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
789 " This is not part of the transaction, just kept in your wallet.\n"
790 "6. \"comment-to\" (string, optional) An optional comment to store the name of the person or organization \n"
791 " to which you're sending the transaction. This is not part of the transaction, \n"
792 " it is just kept in your wallet.\n"
794 "\"transactionid\" (string) The transaction id.\n"
796 "\nSend 0.01 btc from the default account to the address, must have at least 1 confirmation\n"
797 + HelpExampleCli("sendfrom", "\"\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") +
798 "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
799 + HelpExampleCli("sendfrom", "\"tabby\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01 6 \"donation\" \"seans outpost\"") +
800 "\nAs a json rpc call\n"
801 + HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
804 string strAccount = AccountFromValue(params[0]);
805 CBitcoinAddress address(params[1].get_str());
806 if (!address.IsValid())
807 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
808 CAmount nAmount = AmountFromValue(params[2]);
810 if (params.size() > 3)
811 nMinDepth = params[3].get_int();
814 wtx.strFromAccount = strAccount;
815 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
816 wtx.mapValue["comment"] = params[4].get_str();
817 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
818 wtx.mapValue["to"] = params[5].get_str();
820 EnsureWalletIsUnlocked();
823 CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
824 if (nAmount > nBalance)
825 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
827 SendMoney(address.Get(), nAmount, wtx);
829 return wtx.GetHash().GetHex();
833 Value sendmany(const Array& params, bool fHelp)
835 if (fHelp || params.size() < 2 || params.size() > 4)
837 "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" )\n"
838 "\nSend multiple times. Amounts are double-precision floating point numbers."
839 + HelpRequiringPassphrase() + "\n"
841 "1. \"fromaccount\" (string, required) The account to send the funds from, can be \"\" for the default account\n"
842 "2. \"amounts\" (string, required) A json object with addresses and amounts\n"
844 " \"address\":amount (numeric) The bitcoin address is the key, the numeric amount in btc is the value\n"
847 "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
848 "4. \"comment\" (string, optional) A comment\n"
850 "\"transactionid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
851 " the number of addresses.\n"
853 "\nSend two amounts to two different addresses:\n"
854 + HelpExampleCli("sendmany", "\"tabby\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
855 "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
856 + HelpExampleCli("sendmany", "\"tabby\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
857 "\nAs a json rpc call\n"
858 + HelpExampleRpc("sendmany", "\"tabby\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
861 string strAccount = AccountFromValue(params[0]);
862 Object sendTo = params[1].get_obj();
864 if (params.size() > 2)
865 nMinDepth = params[2].get_int();
868 wtx.strFromAccount = strAccount;
869 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
870 wtx.mapValue["comment"] = params[3].get_str();
872 set<CBitcoinAddress> setAddress;
873 vector<pair<CScript, CAmount> > vecSend;
875 CAmount totalAmount = 0;
876 BOOST_FOREACH(const Pair& s, sendTo)
878 CBitcoinAddress address(s.name_);
879 if (!address.IsValid())
880 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_);
882 if (setAddress.count(address))
883 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
884 setAddress.insert(address);
886 CScript scriptPubKey = GetScriptForDestination(address.Get());
887 CAmount nAmount = AmountFromValue(s.value_);
888 totalAmount += nAmount;
890 vecSend.push_back(make_pair(scriptPubKey, nAmount));
893 EnsureWalletIsUnlocked();
896 CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
897 if (totalAmount > nBalance)
898 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
901 CReserveKey keyChange(pwalletMain);
902 CAmount nFeeRequired = 0;
903 string strFailReason;
904 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, strFailReason);
906 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
907 if (!pwalletMain->CommitTransaction(wtx, keyChange))
908 throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed");
910 return wtx.GetHash().GetHex();
913 // Defined in rpcmisc.cpp
914 extern CScript _createmultisig_redeemScript(const Array& params);
916 Value addmultisigaddress(const Array& params, bool fHelp)
918 if (fHelp || params.size() < 2 || params.size() > 3)
920 string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
921 "\nAdd a nrequired-to-sign multisignature address to the wallet.\n"
922 "Each key is a Bitcoin address or hex-encoded public key.\n"
923 "If 'account' is specified, assign address to that account.\n"
926 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
927 "2. \"keysobject\" (string, required) A json array of bitcoin addresses or hex-encoded public keys\n"
929 " \"address\" (string) bitcoin address or hex-encoded public key\n"
932 "3. \"account\" (string, optional) An account to assign the addresses to.\n"
935 "\"bitcoinaddress\" (string) A bitcoin address associated with the keys.\n"
938 "\nAdd a multisig address from 2 addresses\n"
939 + HelpExampleCli("addmultisigaddress", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
940 "\nAs json rpc call\n"
941 + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
943 throw runtime_error(msg);
947 if (params.size() > 2)
948 strAccount = AccountFromValue(params[2]);
950 // Construct using pay-to-script-hash:
951 CScript inner = _createmultisig_redeemScript(params);
952 CScriptID innerID(inner);
953 pwalletMain->AddCScript(inner);
955 pwalletMain->SetAddressBook(innerID, strAccount, "send");
956 return CBitcoinAddress(innerID).ToString();
964 vector<uint256> txids;
969 nConf = std::numeric_limits<int>::max();
970 fIsWatchonly = false;
974 Value ListReceived(const Array& params, bool fByAccounts)
976 // Minimum confirmations
978 if (params.size() > 0)
979 nMinDepth = params[0].get_int();
981 // Whether to include empty accounts
982 bool fIncludeEmpty = false;
983 if (params.size() > 1)
984 fIncludeEmpty = params[1].get_bool();
986 isminefilter filter = ISMINE_SPENDABLE;
987 if(params.size() > 2)
988 if(params[2].get_bool())
989 filter = filter | ISMINE_WATCH_ONLY;
992 map<CBitcoinAddress, tallyitem> mapTally;
993 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
995 const CWalletTx& wtx = (*it).second;
997 if (wtx.IsCoinBase() || !IsFinalTx(wtx))
1000 int nDepth = wtx.GetDepthInMainChain();
1001 if (nDepth < nMinDepth)
1004 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1006 CTxDestination address;
1007 if (!ExtractDestination(txout.scriptPubKey, address))
1010 isminefilter mine = IsMine(*pwalletMain, address);
1011 if(!(mine & filter))
1014 tallyitem& item = mapTally[address];
1015 item.nAmount += txout.nValue;
1016 item.nConf = min(item.nConf, nDepth);
1017 item.txids.push_back(wtx.GetHash());
1018 if (mine & ISMINE_WATCH_ONLY)
1019 item.fIsWatchonly = true;
1025 map<string, tallyitem> mapAccountTally;
1026 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
1028 const CBitcoinAddress& address = item.first;
1029 const string& strAccount = item.second.name;
1030 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1031 if (it == mapTally.end() && !fIncludeEmpty)
1034 CAmount nAmount = 0;
1035 int nConf = std::numeric_limits<int>::max();
1036 bool fIsWatchonly = false;
1037 if (it != mapTally.end())
1039 nAmount = (*it).second.nAmount;
1040 nConf = (*it).second.nConf;
1041 fIsWatchonly = (*it).second.fIsWatchonly;
1046 tallyitem& item = mapAccountTally[strAccount];
1047 item.nAmount += nAmount;
1048 item.nConf = min(item.nConf, nConf);
1049 item.fIsWatchonly = fIsWatchonly;
1055 obj.push_back(Pair("involvesWatchonly", true));
1056 obj.push_back(Pair("address", address.ToString()));
1057 obj.push_back(Pair("account", strAccount));
1058 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1059 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1061 if (it != mapTally.end())
1063 BOOST_FOREACH(const uint256& item, (*it).second.txids)
1065 transactions.push_back(item.GetHex());
1068 obj.push_back(Pair("txids", transactions));
1075 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1077 CAmount nAmount = (*it).second.nAmount;
1078 int nConf = (*it).second.nConf;
1080 if((*it).second.fIsWatchonly)
1081 obj.push_back(Pair("involvesWatchonly", true));
1082 obj.push_back(Pair("account", (*it).first));
1083 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1084 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1092 Value listreceivedbyaddress(const Array& params, bool fHelp)
1094 if (fHelp || params.size() > 3)
1095 throw runtime_error(
1096 "listreceivedbyaddress ( minconf includeempty includeWatchonly)\n"
1097 "\nList balances by receiving address.\n"
1099 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1100 "2. includeempty (numeric, optional, default=false) Whether to include addresses that haven't received any payments.\n"
1101 "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1106 " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
1107 " \"address\" : \"receivingaddress\", (string) The receiving address\n"
1108 " \"account\" : \"accountname\", (string) The account of the receiving address. The default account is \"\".\n"
1109 " \"amount\" : x.xxx, (numeric) The total amount in btc received by the address\n"
1110 " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
1116 + HelpExampleCli("listreceivedbyaddress", "")
1117 + HelpExampleCli("listreceivedbyaddress", "6 true")
1118 + HelpExampleRpc("listreceivedbyaddress", "6, true, true")
1121 return ListReceived(params, false);
1124 Value listreceivedbyaccount(const Array& params, bool fHelp)
1126 if (fHelp || params.size() > 3)
1127 throw runtime_error(
1128 "listreceivedbyaccount ( minconf includeempty includeWatchonly)\n"
1129 "\nList balances by account.\n"
1131 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1132 "2. includeempty (boolean, optional, default=false) Whether to include accounts that haven't received any payments.\n"
1133 "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1138 " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
1139 " \"account\" : \"accountname\", (string) The account name of the receiving account\n"
1140 " \"amount\" : x.xxx, (numeric) The total amount received by addresses with this account\n"
1141 " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
1147 + HelpExampleCli("listreceivedbyaccount", "")
1148 + HelpExampleCli("listreceivedbyaccount", "6 true")
1149 + HelpExampleRpc("listreceivedbyaccount", "6, true, true")
1152 return ListReceived(params, true);
1155 static void MaybePushAddress(Object & entry, const CTxDestination &dest)
1157 CBitcoinAddress addr;
1159 entry.push_back(Pair("address", addr.ToString()));
1162 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret, const isminefilter& filter)
1165 string strSentAccount;
1166 list<COutputEntry> listReceived;
1167 list<COutputEntry> listSent;
1169 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter);
1171 bool fAllAccounts = (strAccount == string("*"));
1172 bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
1175 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1177 BOOST_FOREACH(const COutputEntry& s, listSent)
1180 if(involvesWatchonly || (::IsMine(*pwalletMain, s.destination) & ISMINE_WATCH_ONLY))
1181 entry.push_back(Pair("involvesWatchonly", true));
1182 entry.push_back(Pair("account", strSentAccount));
1183 MaybePushAddress(entry, s.destination);
1184 entry.push_back(Pair("category", "send"));
1185 entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
1186 entry.push_back(Pair("vout", s.vout));
1187 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1189 WalletTxToJSON(wtx, entry);
1190 ret.push_back(entry);
1195 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1197 BOOST_FOREACH(const COutputEntry& r, listReceived)
1200 if (pwalletMain->mapAddressBook.count(r.destination))
1201 account = pwalletMain->mapAddressBook[r.destination].name;
1202 if (fAllAccounts || (account == strAccount))
1205 if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
1206 entry.push_back(Pair("involvesWatchonly", true));
1207 entry.push_back(Pair("account", account));
1208 MaybePushAddress(entry, r.destination);
1209 if (wtx.IsCoinBase())
1211 if (wtx.GetDepthInMainChain() < 1)
1212 entry.push_back(Pair("category", "orphan"));
1213 else if (wtx.GetBlocksToMaturity() > 0)
1214 entry.push_back(Pair("category", "immature"));
1216 entry.push_back(Pair("category", "generate"));
1220 entry.push_back(Pair("category", "receive"));
1222 entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
1223 entry.push_back(Pair("vout", r.vout));
1225 WalletTxToJSON(wtx, entry);
1226 ret.push_back(entry);
1232 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1234 bool fAllAccounts = (strAccount == string("*"));
1236 if (fAllAccounts || acentry.strAccount == strAccount)
1239 entry.push_back(Pair("account", acentry.strAccount));
1240 entry.push_back(Pair("category", "move"));
1241 entry.push_back(Pair("time", acentry.nTime));
1242 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1243 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1244 entry.push_back(Pair("comment", acentry.strComment));
1245 ret.push_back(entry);
1249 Value listtransactions(const Array& params, bool fHelp)
1251 if (fHelp || params.size() > 4)
1252 throw runtime_error(
1253 "listtransactions ( \"account\" count from includeWatchonly)\n"
1254 "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n"
1256 "1. \"account\" (string, optional) The account name. If not included, it will list all transactions for all accounts.\n"
1257 " If \"\" is set, it will list transactions for the default account.\n"
1258 "2. count (numeric, optional, default=10) The number of transactions to return\n"
1259 "3. from (numeric, optional, default=0) The number of transactions to skip\n"
1260 "4. includeWatchonly (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')\n"
1264 " \"account\":\"accountname\", (string) The account name associated with the transaction. \n"
1265 " It will be \"\" for the default account.\n"
1266 " \"address\":\"bitcoinaddress\", (string) The bitcoin address of the transaction. Not present for \n"
1267 " move transactions (category = move).\n"
1268 " \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n"
1269 " transaction between accounts, and not associated with an address,\n"
1270 " transaction id or block. 'send' and 'receive' transactions are \n"
1271 " associated with an address, transaction id and block details\n"
1272 " \"amount\": x.xxx, (numeric) The amount in btc. This is negative for the 'send' category, and for the\n"
1273 " 'move' category for moves outbound. It is positive for the 'receive' category,\n"
1274 " and for the 'move' category for inbound funds.\n"
1275 " \"vout\" : n, (numeric) the vout value\n"
1276 " \"fee\": x.xxx, (numeric) The amount of the fee in btc. This is negative and only available for the \n"
1277 " 'send' category of transactions.\n"
1278 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
1279 " 'receive' category of transactions.\n"
1280 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
1281 " category of transactions.\n"
1282 " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n"
1283 " category of transactions.\n"
1284 " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1285 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
1286 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
1287 " for 'send' and 'receive' category of transactions.\n"
1288 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1289 " \"otheraccount\": \"accountname\", (string) For the 'move' category of transactions, the account the funds came \n"
1290 " from (for receiving funds, positive amounts), or went to (for sending funds,\n"
1291 " negative amounts).\n"
1296 "\nList the most recent 10 transactions in the systems\n"
1297 + HelpExampleCli("listtransactions", "") +
1298 "\nList the most recent 10 transactions for the tabby account\n"
1299 + HelpExampleCli("listtransactions", "\"tabby\"") +
1300 "\nList transactions 100 to 120 from the tabby account\n"
1301 + HelpExampleCli("listtransactions", "\"tabby\" 20 100") +
1302 "\nAs a json rpc call\n"
1303 + HelpExampleRpc("listtransactions", "\"tabby\", 20, 100")
1306 string strAccount = "*";
1307 if (params.size() > 0)
1308 strAccount = params[0].get_str();
1310 if (params.size() > 1)
1311 nCount = params[1].get_int();
1313 if (params.size() > 2)
1314 nFrom = params[2].get_int();
1315 isminefilter filter = ISMINE_SPENDABLE;
1316 if(params.size() > 3)
1317 if(params[3].get_bool())
1318 filter = filter | ISMINE_WATCH_ONLY;
1321 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
1323 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
1327 std::list<CAccountingEntry> acentries;
1328 CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount);
1330 // iterate backwards until we have nCount items to return:
1331 for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
1333 CWalletTx *const pwtx = (*it).second.first;
1335 ListTransactions(*pwtx, strAccount, 0, true, ret, filter);
1336 CAccountingEntry *const pacentry = (*it).second.second;
1338 AcentryToJSON(*pacentry, strAccount, ret);
1340 if ((int)ret.size() >= (nCount+nFrom)) break;
1342 // ret is newest to oldest
1344 if (nFrom > (int)ret.size())
1346 if ((nFrom + nCount) > (int)ret.size())
1347 nCount = ret.size() - nFrom;
1348 Array::iterator first = ret.begin();
1349 std::advance(first, nFrom);
1350 Array::iterator last = ret.begin();
1351 std::advance(last, nFrom+nCount);
1353 if (last != ret.end()) ret.erase(last, ret.end());
1354 if (first != ret.begin()) ret.erase(ret.begin(), first);
1356 std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1361 Value listaccounts(const Array& params, bool fHelp)
1363 if (fHelp || params.size() > 2)
1364 throw runtime_error(
1365 "listaccounts ( minconf includeWatchonly)\n"
1366 "\nReturns Object that has account names as keys, account balances as values.\n"
1368 "1. minconf (numeric, optional, default=1) Only include transactions with at least this many confirmations\n"
1369 "2. includeWatchonly (bool, optional, default=false) Include balances in watchonly addresses (see 'importaddress')\n"
1371 "{ (json object where keys are account names, and values are numeric balances\n"
1372 " \"account\": x.xxx, (numeric) The property name is the account name, and the value is the total balance for the account.\n"
1376 "\nList account balances where there at least 1 confirmation\n"
1377 + HelpExampleCli("listaccounts", "") +
1378 "\nList account balances including zero confirmation transactions\n"
1379 + HelpExampleCli("listaccounts", "0") +
1380 "\nList account balances for 6 or more confirmations\n"
1381 + HelpExampleCli("listaccounts", "6") +
1382 "\nAs json rpc call\n"
1383 + HelpExampleRpc("listaccounts", "6")
1387 if (params.size() > 0)
1388 nMinDepth = params[0].get_int();
1389 isminefilter includeWatchonly = ISMINE_SPENDABLE;
1390 if(params.size() > 1)
1391 if(params[1].get_bool())
1392 includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY;
1394 map<string, CAmount> mapAccountBalances;
1395 BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) {
1396 if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me
1397 mapAccountBalances[entry.second.name] = 0;
1400 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1402 const CWalletTx& wtx = (*it).second;
1404 string strSentAccount;
1405 list<COutputEntry> listReceived;
1406 list<COutputEntry> listSent;
1407 int nDepth = wtx.GetDepthInMainChain();
1408 if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
1410 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
1411 mapAccountBalances[strSentAccount] -= nFee;
1412 BOOST_FOREACH(const COutputEntry& s, listSent)
1413 mapAccountBalances[strSentAccount] -= s.amount;
1414 if (nDepth >= nMinDepth)
1416 BOOST_FOREACH(const COutputEntry& r, listReceived)
1417 if (pwalletMain->mapAddressBook.count(r.destination))
1418 mapAccountBalances[pwalletMain->mapAddressBook[r.destination].name] += r.amount;
1420 mapAccountBalances[""] += r.amount;
1424 list<CAccountingEntry> acentries;
1425 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1426 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1427 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1430 BOOST_FOREACH(const PAIRTYPE(string, CAmount)& accountBalance, mapAccountBalances) {
1431 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1436 Value listsinceblock(const Array& params, bool fHelp)
1439 throw runtime_error(
1440 "listsinceblock ( \"blockhash\" target-confirmations includeWatchonly)\n"
1441 "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n"
1443 "1. \"blockhash\" (string, optional) The block hash to list transactions since\n"
1444 "2. target-confirmations: (numeric, optional) The confirmations required, must be 1 or more\n"
1445 "3. includeWatchonly: (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')"
1448 " \"transactions\": [\n"
1449 " \"account\":\"accountname\", (string) The account name associated with the transaction. Will be \"\" for the default account.\n"
1450 " \"address\":\"bitcoinaddress\", (string) The bitcoin address of the transaction. Not present for move transactions (category = move).\n"
1451 " \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
1452 " \"amount\": x.xxx, (numeric) The amount in btc. This is negative for the 'send' category, and for the 'move' category for moves \n"
1453 " outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
1454 " \"vout\" : n, (numeric) the vout value\n"
1455 " \"fee\": x.xxx, (numeric) The amount of the fee in btc. This is negative and only available for the 'send' category of transactions.\n"
1456 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
1457 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1458 " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1459 " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
1460 " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1461 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
1462 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
1463 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1464 " \"to\": \"...\", (string) If a comment to is associated with the transaction.\n"
1466 " \"lastblock\": \"lastblockhash\" (string) The hash of the last block\n"
1469 + HelpExampleCli("listsinceblock", "")
1470 + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
1471 + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
1474 CBlockIndex *pindex = NULL;
1475 int target_confirms = 1;
1476 isminefilter filter = ISMINE_SPENDABLE;
1478 if (params.size() > 0)
1480 uint256 blockId = 0;
1482 blockId.SetHex(params[0].get_str());
1483 BlockMap::iterator it = mapBlockIndex.find(blockId);
1484 if (it != mapBlockIndex.end())
1485 pindex = it->second;
1488 if (params.size() > 1)
1490 target_confirms = params[1].get_int();
1492 if (target_confirms < 1)
1493 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
1496 if(params.size() > 2)
1497 if(params[2].get_bool())
1498 filter = filter | ISMINE_WATCH_ONLY;
1500 int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
1504 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1506 CWalletTx tx = (*it).second;
1508 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1509 ListTransactions(tx, "*", 0, true, transactions, filter);
1512 CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
1513 uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : 0;
1516 ret.push_back(Pair("transactions", transactions));
1517 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1522 Value gettransaction(const Array& params, bool fHelp)
1524 if (fHelp || params.size() < 1 || params.size() > 2)
1525 throw runtime_error(
1526 "gettransaction \"txid\" ( includeWatchonly )\n"
1527 "\nGet detailed information about in-wallet transaction <txid>\n"
1529 "1. \"txid\" (string, required) The transaction id\n"
1530 "2. \"includeWatchonly\" (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n"
1533 " \"amount\" : x.xxx, (numeric) The transaction amount in btc\n"
1534 " \"confirmations\" : n, (numeric) The number of confirmations\n"
1535 " \"blockhash\" : \"hash\", (string) The block hash\n"
1536 " \"blockindex\" : xx, (numeric) The block index\n"
1537 " \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
1538 " \"txid\" : \"transactionid\", (string) The transaction id.\n"
1539 " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
1540 " \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
1541 " \"details\" : [\n"
1543 " \"account\" : \"accountname\", (string) The account name involved in the transaction, can be \"\" for the default account.\n"
1544 " \"address\" : \"bitcoinaddress\", (string) The bitcoin address involved in the transaction\n"
1545 " \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n"
1546 " \"amount\" : x.xxx (numeric) The amount in btc\n"
1547 " \"vout\" : n, (numeric) the vout value\n"
1551 " \"hex\" : \"data\" (string) Raw data for transaction\n"
1555 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1556 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
1557 + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1561 hash.SetHex(params[0].get_str());
1563 isminefilter filter = ISMINE_SPENDABLE;
1564 if(params.size() > 1)
1565 if(params[1].get_bool())
1566 filter = filter | ISMINE_WATCH_ONLY;
1569 if (!pwalletMain->mapWallet.count(hash))
1570 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
1571 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1573 CAmount nCredit = wtx.GetCredit(filter);
1574 CAmount nDebit = wtx.GetDebit(filter);
1575 CAmount nNet = nCredit - nDebit;
1576 CAmount nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0);
1578 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1579 if (wtx.IsFromMe(filter))
1580 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1582 WalletTxToJSON(wtx, entry);
1585 ListTransactions(wtx, "*", 0, false, details, filter);
1586 entry.push_back(Pair("details", details));
1588 string strHex = EncodeHexTx(static_cast<CTransaction>(wtx));
1589 entry.push_back(Pair("hex", strHex));
1595 Value backupwallet(const Array& params, bool fHelp)
1597 if (fHelp || params.size() != 1)
1598 throw runtime_error(
1599 "backupwallet \"destination\"\n"
1600 "\nSafely copies wallet.dat to destination, which can be a directory or a path with filename.\n"
1602 "1. \"destination\" (string) The destination directory or file\n"
1604 + HelpExampleCli("backupwallet", "\"backup.dat\"")
1605 + HelpExampleRpc("backupwallet", "\"backup.dat\"")
1608 string strDest = params[0].get_str();
1609 if (!BackupWallet(*pwalletMain, strDest))
1610 throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
1616 Value keypoolrefill(const Array& params, bool fHelp)
1618 if (fHelp || params.size() > 1)
1619 throw runtime_error(
1620 "keypoolrefill ( newsize )\n"
1621 "\nFills the keypool."
1622 + HelpRequiringPassphrase() + "\n"
1624 "1. newsize (numeric, optional, default=100) The new keypool size\n"
1626 + HelpExampleCli("keypoolrefill", "")
1627 + HelpExampleRpc("keypoolrefill", "")
1630 // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
1631 unsigned int kpSize = 0;
1632 if (params.size() > 0) {
1633 if (params[0].get_int() < 0)
1634 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
1635 kpSize = (unsigned int)params[0].get_int();
1638 EnsureWalletIsUnlocked();
1639 pwalletMain->TopUpKeyPool(kpSize);
1641 if (pwalletMain->GetKeyPoolSize() < kpSize)
1642 throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
1648 static void LockWallet(CWallet* pWallet)
1650 LOCK(cs_nWalletUnlockTime);
1651 nWalletUnlockTime = 0;
1655 Value walletpassphrase(const Array& params, bool fHelp)
1657 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1658 throw runtime_error(
1659 "walletpassphrase \"passphrase\" timeout\n"
1660 "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
1661 "This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
1663 "1. \"passphrase\" (string, required) The wallet passphrase\n"
1664 "2. timeout (numeric, required) The time to keep the decryption key in seconds.\n"
1666 "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
1667 "time that overrides the old one.\n"
1669 "\nunlock the wallet for 60 seconds\n"
1670 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
1671 "\nLock the wallet again (before 60 seconds)\n"
1672 + HelpExampleCli("walletlock", "") +
1673 "\nAs json rpc call\n"
1674 + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
1679 if (!pwalletMain->IsCrypted())
1680 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1682 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1683 SecureString strWalletPass;
1684 strWalletPass.reserve(100);
1685 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1686 // Alternately, find a way to make params[0] mlock()'d to begin with.
1687 strWalletPass = params[0].get_str().c_str();
1689 if (strWalletPass.length() > 0)
1691 if (!pwalletMain->Unlock(strWalletPass))
1692 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1695 throw runtime_error(
1696 "walletpassphrase <passphrase> <timeout>\n"
1697 "Stores the wallet decryption key in memory for <timeout> seconds.");
1699 pwalletMain->TopUpKeyPool();
1701 int64_t nSleepTime = params[1].get_int64();
1702 LOCK(cs_nWalletUnlockTime);
1703 nWalletUnlockTime = GetTime() + nSleepTime;
1704 RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
1710 Value walletpassphrasechange(const Array& params, bool fHelp)
1712 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1713 throw runtime_error(
1714 "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
1715 "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
1717 "1. \"oldpassphrase\" (string) The current passphrase\n"
1718 "2. \"newpassphrase\" (string) The new passphrase\n"
1720 + HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
1721 + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
1726 if (!pwalletMain->IsCrypted())
1727 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1729 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1730 // Alternately, find a way to make params[0] mlock()'d to begin with.
1731 SecureString strOldWalletPass;
1732 strOldWalletPass.reserve(100);
1733 strOldWalletPass = params[0].get_str().c_str();
1735 SecureString strNewWalletPass;
1736 strNewWalletPass.reserve(100);
1737 strNewWalletPass = params[1].get_str().c_str();
1739 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1740 throw runtime_error(
1741 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1742 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1744 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1745 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1751 Value walletlock(const Array& params, bool fHelp)
1753 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1754 throw runtime_error(
1756 "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
1757 "After calling this method, you will need to call walletpassphrase again\n"
1758 "before being able to call any methods which require the wallet to be unlocked.\n"
1760 "\nSet the passphrase for 2 minutes to perform a transaction\n"
1761 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
1762 "\nPerform a send (requires passphrase set)\n"
1763 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 1.0") +
1764 "\nClear the passphrase since we are done before 2 minutes is up\n"
1765 + HelpExampleCli("walletlock", "") +
1766 "\nAs json rpc call\n"
1767 + HelpExampleRpc("walletlock", "")
1772 if (!pwalletMain->IsCrypted())
1773 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
1776 LOCK(cs_nWalletUnlockTime);
1777 pwalletMain->Lock();
1778 nWalletUnlockTime = 0;
1785 Value encryptwallet(const Array& params, bool fHelp)
1787 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1788 throw runtime_error(
1789 "encryptwallet \"passphrase\"\n"
1790 "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
1791 "After this, any calls that interact with private keys such as sending or signing \n"
1792 "will require the passphrase to be set prior the making these calls.\n"
1793 "Use the walletpassphrase call for this, and then walletlock call.\n"
1794 "If the wallet is already encrypted, use the walletpassphrasechange call.\n"
1795 "Note that this will shutdown the server.\n"
1797 "1. \"passphrase\" (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n"
1799 "\nEncrypt you wallet\n"
1800 + HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
1801 "\nNow set the passphrase to use the wallet, such as for signing or sending bitcoin\n"
1802 + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
1803 "\nNow we can so something like sign\n"
1804 + HelpExampleCli("signmessage", "\"bitcoinaddress\" \"test message\"") +
1805 "\nNow lock the wallet again by removing the passphrase\n"
1806 + HelpExampleCli("walletlock", "") +
1807 "\nAs a json rpc call\n"
1808 + HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
1813 if (pwalletMain->IsCrypted())
1814 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
1816 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1817 // Alternately, find a way to make params[0] mlock()'d to begin with.
1818 SecureString strWalletPass;
1819 strWalletPass.reserve(100);
1820 strWalletPass = params[0].get_str().c_str();
1822 if (strWalletPass.length() < 1)
1823 throw runtime_error(
1824 "encryptwallet <passphrase>\n"
1825 "Encrypts the wallet with <passphrase>.");
1827 if (!pwalletMain->EncryptWallet(strWalletPass))
1828 throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
1830 // BDB seems to have a bad habit of writing old data into
1831 // slack space in .dat files; that is bad if the old data is
1832 // unencrypted private keys. So:
1834 return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
1837 Value lockunspent(const Array& params, bool fHelp)
1839 if (fHelp || params.size() < 1 || params.size() > 2)
1840 throw runtime_error(
1841 "lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n"
1842 "\nUpdates list of temporarily unspendable outputs.\n"
1843 "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
1844 "A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
1845 "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
1846 "is always cleared (by virtue of process exit) when a node stops or fails.\n"
1847 "Also see the listunspent call\n"
1849 "1. unlock (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
1850 "2. \"transactions\" (string, required) A json array of objects. Each object the txid (string) vout (numeric)\n"
1851 " [ (json array of json objects)\n"
1853 " \"txid\":\"id\", (string) The transaction id\n"
1854 " \"vout\": n (numeric) The output number\n"
1860 "true|false (boolean) Whether the command was successful or not\n"
1863 "\nList the unspent transactions\n"
1864 + HelpExampleCli("listunspent", "") +
1865 "\nLock an unspent transaction\n"
1866 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1867 "\nList the locked transactions\n"
1868 + HelpExampleCli("listlockunspent", "") +
1869 "\nUnlock the transaction again\n"
1870 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1871 "\nAs a json rpc call\n"
1872 + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
1875 if (params.size() == 1)
1876 RPCTypeCheck(params, list_of(bool_type));
1878 RPCTypeCheck(params, list_of(bool_type)(array_type));
1880 bool fUnlock = params[0].get_bool();
1882 if (params.size() == 1) {
1884 pwalletMain->UnlockAllCoins();
1888 Array outputs = params[1].get_array();
1889 BOOST_FOREACH(Value& output, outputs)
1891 if (output.type() != obj_type)
1892 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
1893 const Object& o = output.get_obj();
1895 RPCTypeCheck(o, map_list_of("txid", str_type)("vout", int_type));
1897 string txid = find_value(o, "txid").get_str();
1899 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
1901 int nOutput = find_value(o, "vout").get_int();
1903 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
1905 COutPoint outpt(uint256(txid), nOutput);
1908 pwalletMain->UnlockCoin(outpt);
1910 pwalletMain->LockCoin(outpt);
1916 Value listlockunspent(const Array& params, bool fHelp)
1918 if (fHelp || params.size() > 0)
1919 throw runtime_error(
1921 "\nReturns list of temporarily unspendable outputs.\n"
1922 "See the lockunspent call to lock and unlock transactions for spending.\n"
1926 " \"txid\" : \"transactionid\", (string) The transaction id locked\n"
1927 " \"vout\" : n (numeric) The vout value\n"
1932 "\nList the unspent transactions\n"
1933 + HelpExampleCli("listunspent", "") +
1934 "\nLock an unspent transaction\n"
1935 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1936 "\nList the locked transactions\n"
1937 + HelpExampleCli("listlockunspent", "") +
1938 "\nUnlock the transaction again\n"
1939 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1940 "\nAs a json rpc call\n"
1941 + HelpExampleRpc("listlockunspent", "")
1944 vector<COutPoint> vOutpts;
1945 pwalletMain->ListLockedCoins(vOutpts);
1949 BOOST_FOREACH(COutPoint &outpt, vOutpts) {
1952 o.push_back(Pair("txid", outpt.hash.GetHex()));
1953 o.push_back(Pair("vout", (int)outpt.n));
1960 Value settxfee(const Array& params, bool fHelp)
1962 if (fHelp || params.size() < 1 || params.size() > 1)
1963 throw runtime_error(
1965 "\nSet the transaction fee per kB.\n"
1967 "1. amount (numeric, required) The transaction fee in BTC/kB rounded to the nearest 0.00000001\n"
1969 "true|false (boolean) Returns true if successful\n"
1971 + HelpExampleCli("settxfee", "0.00001")
1972 + HelpExampleRpc("settxfee", "0.00001")
1976 CAmount nAmount = 0;
1977 if (params[0].get_real() != 0.0)
1978 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
1980 payTxFee = CFeeRate(nAmount, 1000);
1984 Value getwalletinfo(const Array& params, bool fHelp)
1986 if (fHelp || params.size() != 0)
1987 throw runtime_error(
1989 "Returns an object containing various wallet state info.\n"
1992 " \"walletversion\": xxxxx, (numeric) the wallet version\n"
1993 " \"balance\": xxxxxxx, (numeric) the total bitcoin balance of the wallet\n"
1994 " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
1995 " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
1996 " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
1997 " \"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"
2000 + HelpExampleCli("getwalletinfo", "")
2001 + HelpExampleRpc("getwalletinfo", "")
2005 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
2006 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
2007 obj.push_back(Pair("txcount", (int)pwalletMain->mapWallet.size()));
2008 obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
2009 obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
2010 if (pwalletMain->IsCrypted())
2011 obj.push_back(Pair("unlocked_until", nWalletUnlockTime));