1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
20 #include <boost/assign/list_of.hpp>
21 #include "json/json_spirit_utils.h"
22 #include "json/json_spirit_value.h"
25 using namespace boost;
26 using namespace boost::assign;
27 using namespace json_spirit;
29 int64_t nWalletUnlockTime;
30 static CCriticalSection cs_nWalletUnlockTime;
32 std::string HelpRequiringPassphrase()
34 return pwalletMain && pwalletMain->IsCrypted()
35 ? "\nRequires wallet passphrase to be set with walletpassphrase call."
39 void EnsureWalletIsUnlocked()
41 if (pwalletMain->IsLocked())
42 throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
45 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
47 int confirms = wtx.GetDepthInMainChain();
48 entry.push_back(Pair("confirmations", confirms));
50 entry.push_back(Pair("generated", true));
53 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
54 entry.push_back(Pair("blockindex", wtx.nIndex));
55 entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
57 uint256 hash = wtx.GetHash();
58 entry.push_back(Pair("txid", hash.GetHex()));
60 BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
61 conflicts.push_back(conflict.GetHex());
62 entry.push_back(Pair("walletconflicts", conflicts));
63 entry.push_back(Pair("time", wtx.GetTxTime()));
64 entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived));
65 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
66 entry.push_back(Pair(item.first, item.second));
69 string AccountFromValue(const Value& value)
71 string strAccount = value.get_str();
72 if (strAccount == "*")
73 throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Invalid account name");
77 Value getnewaddress(const Array& params, bool fHelp)
79 if (fHelp || params.size() > 1)
81 "getnewaddress ( \"account\" )\n"
82 "\nReturns a new Bitcoin address for receiving payments.\n"
83 "If 'account' is specified (recommended), it is added to the address book \n"
84 "so payments received with the address will be credited to 'account'.\n"
86 "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"
88 "\"bitcoinaddress\" (string) The new bitcoin address\n"
90 + HelpExampleCli("getnewaddress", "")
91 + HelpExampleCli("getnewaddress", "\"\"")
92 + HelpExampleCli("getnewaddress", "\"myaccount\"")
93 + HelpExampleRpc("getnewaddress", "\"myaccount\"")
96 // Parse the account first so we don't generate a key if there's an error
98 if (params.size() > 0)
99 strAccount = AccountFromValue(params[0]);
101 if (!pwalletMain->IsLocked())
102 pwalletMain->TopUpKeyPool();
104 // Generate a new key that is added to wallet
106 if (!pwalletMain->GetKeyFromPool(newKey))
107 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
108 CKeyID keyID = newKey.GetID();
110 pwalletMain->SetAddressBook(keyID, strAccount, "receive");
112 return CBitcoinAddress(keyID).ToString();
116 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
118 CWalletDB walletdb(pwalletMain->strWalletFile);
121 walletdb.ReadAccount(strAccount, account);
123 bool bKeyUsed = false;
125 // Check if the current key has been used
126 if (account.vchPubKey.IsValid())
128 CScript scriptPubKey = GetScriptForDestination(account.vchPubKey.GetID());
129 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
130 it != pwalletMain->mapWallet.end() && account.vchPubKey.IsValid();
133 const CWalletTx& wtx = (*it).second;
134 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
135 if (txout.scriptPubKey == scriptPubKey)
140 // Generate a new key
141 if (!account.vchPubKey.IsValid() || bForceNew || bKeyUsed)
143 if (!pwalletMain->GetKeyFromPool(account.vchPubKey))
144 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
146 pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, "receive");
147 walletdb.WriteAccount(strAccount, account);
150 return CBitcoinAddress(account.vchPubKey.GetID());
153 Value getaccountaddress(const Array& params, bool fHelp)
155 if (fHelp || params.size() != 1)
157 "getaccountaddress \"account\"\n"
158 "\nReturns the current Bitcoin address for receiving payments to this account.\n"
160 "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"
162 "\"bitcoinaddress\" (string) The account bitcoin address\n"
164 + HelpExampleCli("getaccountaddress", "")
165 + HelpExampleCli("getaccountaddress", "\"\"")
166 + HelpExampleCli("getaccountaddress", "\"myaccount\"")
167 + HelpExampleRpc("getaccountaddress", "\"myaccount\"")
170 // Parse the account first so we don't generate a key if there's an error
171 string strAccount = AccountFromValue(params[0]);
175 ret = GetAccountAddress(strAccount).ToString();
181 Value getrawchangeaddress(const Array& params, bool fHelp)
183 if (fHelp || params.size() > 1)
185 "getrawchangeaddress\n"
186 "\nReturns a new Bitcoin address, for receiving change.\n"
187 "This is for use with raw transactions, NOT normal use.\n"
189 "\"address\" (string) The address\n"
191 + HelpExampleCli("getrawchangeaddress", "")
192 + HelpExampleRpc("getrawchangeaddress", "")
195 if (!pwalletMain->IsLocked())
196 pwalletMain->TopUpKeyPool();
198 CReserveKey reservekey(pwalletMain);
200 if (!reservekey.GetReservedKey(vchPubKey))
201 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
203 reservekey.KeepKey();
205 CKeyID keyID = vchPubKey.GetID();
207 return CBitcoinAddress(keyID).ToString();
211 Value setaccount(const Array& params, bool fHelp)
213 if (fHelp || params.size() < 1 || params.size() > 2)
215 "setaccount \"bitcoinaddress\" \"account\"\n"
216 "\nSets the account associated with the given address.\n"
218 "1. \"bitcoinaddress\" (string, required) The bitcoin address to be associated with an account.\n"
219 "2. \"account\" (string, required) The account to assign the address to.\n"
221 + HelpExampleCli("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"tabby\"")
222 + HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"tabby\"")
225 CBitcoinAddress address(params[0].get_str());
226 if (!address.IsValid())
227 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
231 if (params.size() > 1)
232 strAccount = AccountFromValue(params[1]);
234 // Only add the account if the address is yours.
235 if (IsMine(*pwalletMain, address.Get()))
237 // Detect when changing the account of an address that is the 'unused current key' of another account:
238 if (pwalletMain->mapAddressBook.count(address.Get()))
240 string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name;
241 if (address == GetAccountAddress(strOldAccount))
242 GetAccountAddress(strOldAccount, true);
244 pwalletMain->SetAddressBook(address.Get(), strAccount, "receive");
247 throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
253 Value getaccount(const Array& params, bool fHelp)
255 if (fHelp || params.size() != 1)
257 "getaccount \"bitcoinaddress\"\n"
258 "\nReturns the account associated with the given address.\n"
260 "1. \"bitcoinaddress\" (string, required) The bitcoin address for account lookup.\n"
262 "\"accountname\" (string) the account address\n"
264 + HelpExampleCli("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
265 + HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
268 CBitcoinAddress address(params[0].get_str());
269 if (!address.IsValid())
270 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
273 map<CTxDestination, CAddressBookData>::iterator mi = pwalletMain->mapAddressBook.find(address.Get());
274 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty())
275 strAccount = (*mi).second.name;
280 Value getaddressesbyaccount(const Array& params, bool fHelp)
282 if (fHelp || params.size() != 1)
284 "getaddressesbyaccount \"account\"\n"
285 "\nReturns the list of addresses for the given account.\n"
287 "1. \"account\" (string, required) The account name.\n"
289 "[ (json array of string)\n"
290 " \"bitcoinaddress\" (string) a bitcoin address associated with the given account\n"
294 + HelpExampleCli("getaddressesbyaccount", "\"tabby\"")
295 + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
298 string strAccount = AccountFromValue(params[0]);
300 // Find all addresses that have the given account
302 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
304 const CBitcoinAddress& address = item.first;
305 const string& strName = item.second.name;
306 if (strName == strAccount)
307 ret.push_back(address.ToString());
312 Value sendtoaddress(const Array& params, bool fHelp)
314 if (fHelp || params.size() < 2 || params.size() > 4)
316 "sendtoaddress \"bitcoinaddress\" amount ( \"comment\" \"comment-to\" )\n"
317 "\nSent an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n"
318 + HelpRequiringPassphrase() +
320 "1. \"bitcoinaddress\" (string, required) The bitcoin address to send to.\n"
321 "2. \"amount\" (numeric, required) The amount in btc to send. eg 0.1\n"
322 "3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
323 " This is not part of the transaction, just kept in your wallet.\n"
324 "4. \"comment-to\" (string, optional) A comment to store the name of the person or organization \n"
325 " to which you're sending the transaction. This is not part of the \n"
326 " transaction, just kept in your wallet.\n"
328 "\"transactionid\" (string) The transaction id.\n"
330 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
331 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
332 + HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
335 CBitcoinAddress address(params[0].get_str());
336 if (!address.IsValid())
337 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
340 CAmount nAmount = AmountFromValue(params[1]);
344 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
345 wtx.mapValue["comment"] = params[2].get_str();
346 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
347 wtx.mapValue["to"] = params[3].get_str();
349 EnsureWalletIsUnlocked();
351 string strError = pwalletMain->SendMoney(address.Get(), nAmount, wtx);
353 throw JSONRPCError(RPC_WALLET_ERROR, strError);
355 return wtx.GetHash().GetHex();
358 Value listaddressgroupings(const Array& params, bool fHelp)
362 "listaddressgroupings\n"
363 "\nLists groups of addresses which have had their common ownership\n"
364 "made public by common use as inputs or as the resulting change\n"
365 "in past transactions\n"
370 " \"bitcoinaddress\", (string) The bitcoin address\n"
371 " amount, (numeric) The amount in btc\n"
372 " \"account\" (string, optional) The account\n"
379 + HelpExampleCli("listaddressgroupings", "")
380 + HelpExampleRpc("listaddressgroupings", "")
384 map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
385 BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
388 BOOST_FOREACH(CTxDestination address, grouping)
391 addressInfo.push_back(CBitcoinAddress(address).ToString());
392 addressInfo.push_back(ValueFromAmount(balances[address]));
394 LOCK(pwalletMain->cs_wallet);
395 if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end())
396 addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second.name);
398 jsonGrouping.push_back(addressInfo);
400 jsonGroupings.push_back(jsonGrouping);
402 return jsonGroupings;
405 Value signmessage(const Array& params, bool fHelp)
407 if (fHelp || params.size() != 2)
409 "signmessage \"bitcoinaddress\" \"message\"\n"
410 "\nSign a message with the private key of an address"
411 + HelpRequiringPassphrase() + "\n"
413 "1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the private key.\n"
414 "2. \"message\" (string, required) The message to create a signature of.\n"
416 "\"signature\" (string) The signature of the message encoded in base 64\n"
418 "\nUnlock the wallet for 30 seconds\n"
419 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
420 "\nCreate the signature\n"
421 + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
422 "\nVerify the signature\n"
423 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
425 + HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"my message\"")
428 EnsureWalletIsUnlocked();
430 string strAddress = params[0].get_str();
431 string strMessage = params[1].get_str();
433 CBitcoinAddress addr(strAddress);
435 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
438 if (!addr.GetKeyID(keyID))
439 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
442 if (!pwalletMain->GetKey(keyID, key))
443 throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
445 CHashWriter ss(SER_GETHASH, 0);
446 ss << strMessageMagic;
449 vector<unsigned char> vchSig;
450 if (!key.SignCompact(ss.GetHash(), vchSig))
451 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
453 return EncodeBase64(&vchSig[0], vchSig.size());
456 Value getreceivedbyaddress(const Array& params, bool fHelp)
458 if (fHelp || params.size() < 1 || params.size() > 2)
460 "getreceivedbyaddress \"bitcoinaddress\" ( minconf )\n"
461 "\nReturns the total amount received by the given bitcoinaddress in transactions with at least minconf confirmations.\n"
463 "1. \"bitcoinaddress\" (string, required) The bitcoin address for transactions.\n"
464 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
466 "amount (numeric) The total amount in btc received at this address.\n"
468 "\nThe amount from transactions with at least 1 confirmation\n"
469 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"") +
470 "\nThe amount including unconfirmed transactions, zero confirmations\n"
471 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 0") +
472 "\nThe amount with at least 6 confirmation, very safe\n"
473 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 6") +
474 "\nAs a json rpc call\n"
475 + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", 6")
479 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
480 if (!address.IsValid())
481 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
482 CScript scriptPubKey = GetScriptForDestination(address.Get());
483 if (!IsMine(*pwalletMain,scriptPubKey))
486 // Minimum confirmations
488 if (params.size() > 1)
489 nMinDepth = params[1].get_int();
493 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
495 const CWalletTx& wtx = (*it).second;
496 if (wtx.IsCoinBase() || !IsFinalTx(wtx))
499 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
500 if (txout.scriptPubKey == scriptPubKey)
501 if (wtx.GetDepthInMainChain() >= nMinDepth)
502 nAmount += txout.nValue;
505 return ValueFromAmount(nAmount);
509 Value getreceivedbyaccount(const Array& params, bool fHelp)
511 if (fHelp || params.size() < 1 || params.size() > 2)
513 "getreceivedbyaccount \"account\" ( minconf )\n"
514 "\nReturns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
516 "1. \"account\" (string, required) The selected account, may be the default account using \"\".\n"
517 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
519 "amount (numeric) The total amount in btc received for this account.\n"
521 "\nAmount received by the default account with at least 1 confirmation\n"
522 + HelpExampleCli("getreceivedbyaccount", "\"\"") +
523 "\nAmount received at the tabby account including unconfirmed amounts with zero confirmations\n"
524 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 0") +
525 "\nThe amount with at least 6 confirmation, very safe\n"
526 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 6") +
527 "\nAs a json rpc call\n"
528 + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
531 // Minimum confirmations
533 if (params.size() > 1)
534 nMinDepth = params[1].get_int();
536 // Get the set of pub keys assigned to account
537 string strAccount = AccountFromValue(params[0]);
538 set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount);
542 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
544 const CWalletTx& wtx = (*it).second;
545 if (wtx.IsCoinBase() || !IsFinalTx(wtx))
548 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
550 CTxDestination address;
551 if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
552 if (wtx.GetDepthInMainChain() >= nMinDepth)
553 nAmount += txout.nValue;
557 return (double)nAmount / (double)COIN;
561 CAmount GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter)
563 CAmount nBalance = 0;
565 // Tally wallet transactions
566 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
568 const CWalletTx& wtx = (*it).second;
569 if (!IsFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
572 CAmount nReceived, nSent, nFee;
573 wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter);
575 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
576 nBalance += nReceived;
577 nBalance -= nSent + nFee;
580 // Tally internal accounting entries
581 nBalance += walletdb.GetAccountCreditDebit(strAccount);
586 CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter)
588 CWalletDB walletdb(pwalletMain->strWalletFile);
589 return GetAccountBalance(walletdb, strAccount, nMinDepth, filter);
593 Value getbalance(const Array& params, bool fHelp)
595 if (fHelp || params.size() > 3)
597 "getbalance ( \"account\" minconf includeWatchonly )\n"
598 "\nIf account is not specified, returns the server's total available balance.\n"
599 "If account is specified, returns the balance in the account.\n"
600 "Note that the account \"\" is not the same as leaving the parameter out.\n"
601 "The server total may be different to the balance in the default \"\" account.\n"
603 "1. \"account\" (string, optional) The selected account, or \"*\" for entire wallet. It may be the default account using \"\".\n"
604 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
605 "3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n"
607 "amount (numeric) The total amount in btc received for this account.\n"
609 "\nThe total amount in the server across all accounts\n"
610 + HelpExampleCli("getbalance", "") +
611 "\nThe total amount in the server across all accounts, with at least 5 confirmations\n"
612 + HelpExampleCli("getbalance", "\"*\" 6") +
613 "\nThe total amount in the default account with at least 1 confirmation\n"
614 + HelpExampleCli("getbalance", "\"\"") +
615 "\nThe total amount in the account named tabby with at least 6 confirmations\n"
616 + HelpExampleCli("getbalance", "\"tabby\" 6") +
617 "\nAs a json rpc call\n"
618 + HelpExampleRpc("getbalance", "\"tabby\", 6")
621 if (params.size() == 0)
622 return ValueFromAmount(pwalletMain->GetBalance());
625 if (params.size() > 1)
626 nMinDepth = params[1].get_int();
627 isminefilter filter = ISMINE_SPENDABLE;
628 if(params.size() > 2)
629 if(params[2].get_bool())
630 filter = filter | ISMINE_WATCH_ONLY;
632 if (params[0].get_str() == "*") {
633 // Calculate total balance a different way from GetBalance()
634 // (GetBalance() sums up all unspent TxOuts)
635 // getbalance and getbalance '*' 0 should return the same number
636 CAmount nBalance = 0;
637 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
639 const CWalletTx& wtx = (*it).second;
640 if (!wtx.IsTrusted() || wtx.GetBlocksToMaturity() > 0)
644 string strSentAccount;
645 list<COutputEntry> listReceived;
646 list<COutputEntry> listSent;
647 wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
648 if (wtx.GetDepthInMainChain() >= nMinDepth)
650 BOOST_FOREACH(const COutputEntry& r, listReceived)
651 nBalance += r.amount;
653 BOOST_FOREACH(const COutputEntry& s, listSent)
654 nBalance -= s.amount;
657 return ValueFromAmount(nBalance);
660 string strAccount = AccountFromValue(params[0]);
662 CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, filter);
664 return ValueFromAmount(nBalance);
667 Value getunconfirmedbalance(const Array ¶ms, bool fHelp)
669 if (fHelp || params.size() > 0)
671 "getunconfirmedbalance\n"
672 "Returns the server's total unconfirmed balance\n");
673 return ValueFromAmount(pwalletMain->GetUnconfirmedBalance());
677 Value movecmd(const Array& params, bool fHelp)
679 if (fHelp || params.size() < 3 || params.size() > 5)
681 "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
682 "\nMove a specified amount from one account in your wallet to another.\n"
684 "1. \"fromaccount\" (string, required) The name of the account to move funds from. May be the default account using \"\".\n"
685 "2. \"toaccount\" (string, required) The name of the account to move funds to. May be the default account using \"\".\n"
686 "3. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
687 "4. \"comment\" (string, optional) An optional comment, stored in the wallet only.\n"
689 "true|false (boolean) true if successfull.\n"
691 "\nMove 0.01 btc from the default account to the account named tabby\n"
692 + HelpExampleCli("move", "\"\" \"tabby\" 0.01") +
693 "\nMove 0.01 btc timotei to akiko with a comment and funds have 6 confirmations\n"
694 + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") +
695 "\nAs a json rpc call\n"
696 + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
699 string strFrom = AccountFromValue(params[0]);
700 string strTo = AccountFromValue(params[1]);
701 CAmount nAmount = AmountFromValue(params[2]);
702 if (params.size() > 3)
703 // unused parameter, used to be nMinDepth, keep type-checking it though
704 (void)params[3].get_int();
706 if (params.size() > 4)
707 strComment = params[4].get_str();
709 CWalletDB walletdb(pwalletMain->strWalletFile);
710 if (!walletdb.TxnBegin())
711 throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
713 int64_t nNow = GetAdjustedTime();
716 CAccountingEntry debit;
717 debit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
718 debit.strAccount = strFrom;
719 debit.nCreditDebit = -nAmount;
721 debit.strOtherAccount = strTo;
722 debit.strComment = strComment;
723 walletdb.WriteAccountingEntry(debit);
726 CAccountingEntry credit;
727 credit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
728 credit.strAccount = strTo;
729 credit.nCreditDebit = nAmount;
731 credit.strOtherAccount = strFrom;
732 credit.strComment = strComment;
733 walletdb.WriteAccountingEntry(credit);
735 if (!walletdb.TxnCommit())
736 throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
742 Value sendfrom(const Array& params, bool fHelp)
744 if (fHelp || params.size() < 3 || params.size() > 6)
746 "sendfrom \"fromaccount\" \"tobitcoinaddress\" amount ( minconf \"comment\" \"comment-to\" )\n"
747 "\nSent an amount from an account to a bitcoin address.\n"
748 "The amount is a real and is rounded to the nearest 0.00000001."
749 + HelpRequiringPassphrase() + "\n"
751 "1. \"fromaccount\" (string, required) The name of the account to send funds from. May be the default account using \"\".\n"
752 "2. \"tobitcoinaddress\" (string, required) The bitcoin address to send funds to.\n"
753 "3. amount (numeric, required) The amount in btc. (transaction fee is added on top).\n"
754 "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
755 "5. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
756 " This is not part of the transaction, just kept in your wallet.\n"
757 "6. \"comment-to\" (string, optional) An optional comment to store the name of the person or organization \n"
758 " to which you're sending the transaction. This is not part of the transaction, \n"
759 " it is just kept in your wallet.\n"
761 "\"transactionid\" (string) The transaction id.\n"
763 "\nSend 0.01 btc from the default account to the address, must have at least 1 confirmation\n"
764 + HelpExampleCli("sendfrom", "\"\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") +
765 "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
766 + HelpExampleCli("sendfrom", "\"tabby\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01 6 \"donation\" \"seans outpost\"") +
767 "\nAs a json rpc call\n"
768 + HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
771 string strAccount = AccountFromValue(params[0]);
772 CBitcoinAddress address(params[1].get_str());
773 if (!address.IsValid())
774 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
775 CAmount nAmount = AmountFromValue(params[2]);
777 if (params.size() > 3)
778 nMinDepth = params[3].get_int();
781 wtx.strFromAccount = strAccount;
782 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
783 wtx.mapValue["comment"] = params[4].get_str();
784 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
785 wtx.mapValue["to"] = params[5].get_str();
787 EnsureWalletIsUnlocked();
790 CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
791 if (nAmount > nBalance)
792 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
795 string strError = pwalletMain->SendMoney(address.Get(), nAmount, wtx);
797 throw JSONRPCError(RPC_WALLET_ERROR, strError);
799 return wtx.GetHash().GetHex();
803 Value sendmany(const Array& params, bool fHelp)
805 if (fHelp || params.size() < 2 || params.size() > 4)
807 "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" )\n"
808 "\nSend multiple times. Amounts are double-precision floating point numbers."
809 + HelpRequiringPassphrase() + "\n"
811 "1. \"fromaccount\" (string, required) The account to send the funds from, can be \"\" for the default account\n"
812 "2. \"amounts\" (string, required) A json object with addresses and amounts\n"
814 " \"address\":amount (numeric) The bitcoin address is the key, the numeric amount in btc is the value\n"
817 "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
818 "4. \"comment\" (string, optional) A comment\n"
820 "\"transactionid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
821 " the number of addresses.\n"
823 "\nSend two amounts to two different addresses:\n"
824 + HelpExampleCli("sendmany", "\"tabby\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
825 "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
826 + HelpExampleCli("sendmany", "\"tabby\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
827 "\nAs a json rpc call\n"
828 + HelpExampleRpc("sendmany", "\"tabby\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
831 string strAccount = AccountFromValue(params[0]);
832 Object sendTo = params[1].get_obj();
834 if (params.size() > 2)
835 nMinDepth = params[2].get_int();
838 wtx.strFromAccount = strAccount;
839 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
840 wtx.mapValue["comment"] = params[3].get_str();
842 set<CBitcoinAddress> setAddress;
843 vector<pair<CScript, CAmount> > vecSend;
845 CAmount totalAmount = 0;
846 BOOST_FOREACH(const Pair& s, sendTo)
848 CBitcoinAddress address(s.name_);
849 if (!address.IsValid())
850 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_);
852 if (setAddress.count(address))
853 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
854 setAddress.insert(address);
856 CScript scriptPubKey = GetScriptForDestination(address.Get());
857 CAmount nAmount = AmountFromValue(s.value_);
858 totalAmount += nAmount;
860 vecSend.push_back(make_pair(scriptPubKey, nAmount));
863 EnsureWalletIsUnlocked();
866 CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
867 if (totalAmount > nBalance)
868 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
871 CReserveKey keyChange(pwalletMain);
872 CAmount nFeeRequired = 0;
873 string strFailReason;
874 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, strFailReason);
876 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
877 if (!pwalletMain->CommitTransaction(wtx, keyChange))
878 throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed");
880 return wtx.GetHash().GetHex();
883 // Defined in rpcmisc.cpp
884 extern CScript _createmultisig_redeemScript(const Array& params);
886 Value addmultisigaddress(const Array& params, bool fHelp)
888 if (fHelp || params.size() < 2 || params.size() > 3)
890 string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
891 "\nAdd a nrequired-to-sign multisignature address to the wallet.\n"
892 "Each key is a Bitcoin address or hex-encoded public key.\n"
893 "If 'account' is specified, assign address to that account.\n"
896 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
897 "2. \"keysobject\" (string, required) A json array of bitcoin addresses or hex-encoded public keys\n"
899 " \"address\" (string) bitcoin address or hex-encoded public key\n"
902 "3. \"account\" (string, optional) An account to assign the addresses to.\n"
905 "\"bitcoinaddress\" (string) A bitcoin address associated with the keys.\n"
908 "\nAdd a multisig address from 2 addresses\n"
909 + HelpExampleCli("addmultisigaddress", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
910 "\nAs json rpc call\n"
911 + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
913 throw runtime_error(msg);
917 if (params.size() > 2)
918 strAccount = AccountFromValue(params[2]);
920 // Construct using pay-to-script-hash:
921 CScript inner = _createmultisig_redeemScript(params);
922 CScriptID innerID(inner);
923 pwalletMain->AddCScript(inner);
925 pwalletMain->SetAddressBook(innerID, strAccount, "send");
926 return CBitcoinAddress(innerID).ToString();
934 vector<uint256> txids;
939 nConf = std::numeric_limits<int>::max();
940 fIsWatchonly = false;
944 Value ListReceived(const Array& params, bool fByAccounts)
946 // Minimum confirmations
948 if (params.size() > 0)
949 nMinDepth = params[0].get_int();
951 // Whether to include empty accounts
952 bool fIncludeEmpty = false;
953 if (params.size() > 1)
954 fIncludeEmpty = params[1].get_bool();
956 isminefilter filter = ISMINE_SPENDABLE;
957 if(params.size() > 2)
958 if(params[2].get_bool())
959 filter = filter | ISMINE_WATCH_ONLY;
962 map<CBitcoinAddress, tallyitem> mapTally;
963 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
965 const CWalletTx& wtx = (*it).second;
967 if (wtx.IsCoinBase() || !IsFinalTx(wtx))
970 int nDepth = wtx.GetDepthInMainChain();
971 if (nDepth < nMinDepth)
974 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
976 CTxDestination address;
977 if (!ExtractDestination(txout.scriptPubKey, address))
980 isminefilter mine = IsMine(*pwalletMain, address);
984 tallyitem& item = mapTally[address];
985 item.nAmount += txout.nValue;
986 item.nConf = min(item.nConf, nDepth);
987 item.txids.push_back(wtx.GetHash());
988 if (mine & ISMINE_WATCH_ONLY)
989 item.fIsWatchonly = true;
995 map<string, tallyitem> mapAccountTally;
996 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
998 const CBitcoinAddress& address = item.first;
999 const string& strAccount = item.second.name;
1000 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1001 if (it == mapTally.end() && !fIncludeEmpty)
1004 CAmount nAmount = 0;
1005 int nConf = std::numeric_limits<int>::max();
1006 bool fIsWatchonly = false;
1007 if (it != mapTally.end())
1009 nAmount = (*it).second.nAmount;
1010 nConf = (*it).second.nConf;
1011 fIsWatchonly = (*it).second.fIsWatchonly;
1016 tallyitem& item = mapAccountTally[strAccount];
1017 item.nAmount += nAmount;
1018 item.nConf = min(item.nConf, nConf);
1019 item.fIsWatchonly = fIsWatchonly;
1025 obj.push_back(Pair("involvesWatchonly", true));
1026 obj.push_back(Pair("address", address.ToString()));
1027 obj.push_back(Pair("account", strAccount));
1028 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1029 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1031 if (it != mapTally.end())
1033 BOOST_FOREACH(const uint256& item, (*it).second.txids)
1035 transactions.push_back(item.GetHex());
1038 obj.push_back(Pair("txids", transactions));
1045 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1047 CAmount nAmount = (*it).second.nAmount;
1048 int nConf = (*it).second.nConf;
1050 if((*it).second.fIsWatchonly)
1051 obj.push_back(Pair("involvesWatchonly", true));
1052 obj.push_back(Pair("account", (*it).first));
1053 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1054 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1062 Value listreceivedbyaddress(const Array& params, bool fHelp)
1064 if (fHelp || params.size() > 3)
1065 throw runtime_error(
1066 "listreceivedbyaddress ( minconf includeempty includeWatchonly)\n"
1067 "\nList balances by receiving address.\n"
1069 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1070 "2. includeempty (numeric, optional, dafault=false) Whether to include addresses that haven't received any payments.\n"
1071 "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1076 " \"involvesWatchonly\" : \"true\", (bool) Only returned if imported addresses were involved in transaction\n"
1077 " \"address\" : \"receivingaddress\", (string) The receiving address\n"
1078 " \"account\" : \"accountname\", (string) The account of the receiving address. The default account is \"\".\n"
1079 " \"amount\" : x.xxx, (numeric) The total amount in btc received by the address\n"
1080 " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
1086 + HelpExampleCli("listreceivedbyaddress", "")
1087 + HelpExampleCli("listreceivedbyaddress", "6 true")
1088 + HelpExampleRpc("listreceivedbyaddress", "6, true, true")
1091 return ListReceived(params, false);
1094 Value listreceivedbyaccount(const Array& params, bool fHelp)
1096 if (fHelp || params.size() > 3)
1097 throw runtime_error(
1098 "listreceivedbyaccount ( minconf includeempty includeWatchonly)\n"
1099 "\nList balances by account.\n"
1101 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1102 "2. includeempty (boolean, optional, default=false) Whether to include accounts that haven't received any payments.\n"
1103 "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1108 " \"involvesWatchonly\" : \"true\", (bool) Only returned if imported addresses were involved in transaction\n"
1109 " \"account\" : \"accountname\", (string) The account name of the receiving account\n"
1110 " \"amount\" : x.xxx, (numeric) The total amount received by addresses with this account\n"
1111 " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
1117 + HelpExampleCli("listreceivedbyaccount", "")
1118 + HelpExampleCli("listreceivedbyaccount", "6 true")
1119 + HelpExampleRpc("listreceivedbyaccount", "6, true, true")
1122 return ListReceived(params, true);
1125 static void MaybePushAddress(Object & entry, const CTxDestination &dest)
1127 CBitcoinAddress addr;
1129 entry.push_back(Pair("address", addr.ToString()));
1132 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret, const isminefilter& filter)
1135 string strSentAccount;
1136 list<COutputEntry> listReceived;
1137 list<COutputEntry> listSent;
1139 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter);
1141 bool fAllAccounts = (strAccount == string("*"));
1142 bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
1145 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1147 BOOST_FOREACH(const COutputEntry& s, listSent)
1150 if(involvesWatchonly || (::IsMine(*pwalletMain, s.destination) & ISMINE_WATCH_ONLY))
1151 entry.push_back(Pair("involvesWatchonly", true));
1152 entry.push_back(Pair("account", strSentAccount));
1153 MaybePushAddress(entry, s.destination);
1154 entry.push_back(Pair("category", "send"));
1155 entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
1156 entry.push_back(Pair("vout", s.vout));
1157 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1159 WalletTxToJSON(wtx, entry);
1160 ret.push_back(entry);
1165 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1167 BOOST_FOREACH(const COutputEntry& r, listReceived)
1170 if (pwalletMain->mapAddressBook.count(r.destination))
1171 account = pwalletMain->mapAddressBook[r.destination].name;
1172 if (fAllAccounts || (account == strAccount))
1175 if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
1176 entry.push_back(Pair("involvesWatchonly", true));
1177 entry.push_back(Pair("account", account));
1178 MaybePushAddress(entry, r.destination);
1179 if (wtx.IsCoinBase())
1181 if (wtx.GetDepthInMainChain() < 1)
1182 entry.push_back(Pair("category", "orphan"));
1183 else if (wtx.GetBlocksToMaturity() > 0)
1184 entry.push_back(Pair("category", "immature"));
1186 entry.push_back(Pair("category", "generate"));
1190 entry.push_back(Pair("category", "receive"));
1192 entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
1193 entry.push_back(Pair("vout", r.vout));
1195 WalletTxToJSON(wtx, entry);
1196 ret.push_back(entry);
1202 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1204 bool fAllAccounts = (strAccount == string("*"));
1206 if (fAllAccounts || acentry.strAccount == strAccount)
1209 entry.push_back(Pair("account", acentry.strAccount));
1210 entry.push_back(Pair("category", "move"));
1211 entry.push_back(Pair("time", acentry.nTime));
1212 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1213 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1214 entry.push_back(Pair("comment", acentry.strComment));
1215 ret.push_back(entry);
1219 Value listtransactions(const Array& params, bool fHelp)
1221 if (fHelp || params.size() > 4)
1222 throw runtime_error(
1223 "listtransactions ( \"account\" count from includeWatchonly)\n"
1224 "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n"
1226 "1. \"account\" (string, optional) The account name. If not included, it will list all transactions for all accounts.\n"
1227 " If \"\" is set, it will list transactions for the default account.\n"
1228 "2. count (numeric, optional, default=10) The number of transactions to return\n"
1229 "3. from (numeric, optional, default=0) The number of transactions to skip\n"
1230 "4. includeWatchonly (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')\n"
1234 " \"account\":\"accountname\", (string) The account name associated with the transaction. \n"
1235 " It will be \"\" for the default account.\n"
1236 " \"address\":\"bitcoinaddress\", (string) The bitcoin address of the transaction. Not present for \n"
1237 " move transactions (category = move).\n"
1238 " \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n"
1239 " transaction between accounts, and not associated with an address,\n"
1240 " transaction id or block. 'send' and 'receive' transactions are \n"
1241 " associated with an address, transaction id and block details\n"
1242 " \"amount\": x.xxx, (numeric) The amount in btc. This is negative for the 'send' category, and for the\n"
1243 " 'move' category for moves outbound. It is positive for the 'receive' category,\n"
1244 " and for the 'move' category for inbound funds.\n"
1245 " \"vout\" : n, (numeric) the vout value\n"
1246 " \"fee\": x.xxx, (numeric) The amount of the fee in btc. This is negative and only available for the \n"
1247 " 'send' category of transactions.\n"
1248 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
1249 " 'receive' category of transactions.\n"
1250 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
1251 " category of transactions.\n"
1252 " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n"
1253 " category of transactions.\n"
1254 " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1255 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
1256 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
1257 " for 'send' and 'receive' category of transactions.\n"
1258 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1259 " \"otheraccount\": \"accountname\", (string) For the 'move' category of transactions, the account the funds came \n"
1260 " from (for receiving funds, positive amounts), or went to (for sending funds,\n"
1261 " negative amounts).\n"
1266 "\nList the most recent 10 transactions in the systems\n"
1267 + HelpExampleCli("listtransactions", "") +
1268 "\nList the most recent 10 transactions for the tabby account\n"
1269 + HelpExampleCli("listtransactions", "\"tabby\"") +
1270 "\nList transactions 100 to 120 from the tabby account\n"
1271 + HelpExampleCli("listtransactions", "\"tabby\" 20 100") +
1272 "\nAs a json rpc call\n"
1273 + HelpExampleRpc("listtransactions", "\"tabby\", 20, 100")
1276 string strAccount = "*";
1277 if (params.size() > 0)
1278 strAccount = params[0].get_str();
1280 if (params.size() > 1)
1281 nCount = params[1].get_int();
1283 if (params.size() > 2)
1284 nFrom = params[2].get_int();
1285 isminefilter filter = ISMINE_SPENDABLE;
1286 if(params.size() > 3)
1287 if(params[3].get_bool())
1288 filter = filter | ISMINE_WATCH_ONLY;
1291 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
1293 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
1297 std::list<CAccountingEntry> acentries;
1298 CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount);
1300 // iterate backwards until we have nCount items to return:
1301 for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
1303 CWalletTx *const pwtx = (*it).second.first;
1305 ListTransactions(*pwtx, strAccount, 0, true, ret, filter);
1306 CAccountingEntry *const pacentry = (*it).second.second;
1308 AcentryToJSON(*pacentry, strAccount, ret);
1310 if ((int)ret.size() >= (nCount+nFrom)) break;
1312 // ret is newest to oldest
1314 if (nFrom > (int)ret.size())
1316 if ((nFrom + nCount) > (int)ret.size())
1317 nCount = ret.size() - nFrom;
1318 Array::iterator first = ret.begin();
1319 std::advance(first, nFrom);
1320 Array::iterator last = ret.begin();
1321 std::advance(last, nFrom+nCount);
1323 if (last != ret.end()) ret.erase(last, ret.end());
1324 if (first != ret.begin()) ret.erase(ret.begin(), first);
1326 std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1331 Value listaccounts(const Array& params, bool fHelp)
1333 if (fHelp || params.size() > 2)
1334 throw runtime_error(
1335 "listaccounts ( minconf includeWatchonly)\n"
1336 "\nReturns Object that has account names as keys, account balances as values.\n"
1338 "1. minconf (numeric, optional, default=1) Only onclude transactions with at least this many confirmations\n"
1339 "2. includeWatchonly (bool, optional, default=false) Include balances in watchonly addresses (see 'importaddress')\n"
1341 "{ (json object where keys are account names, and values are numeric balances\n"
1342 " \"account\": x.xxx, (numeric) The property name is the account name, and the value is the total balance for the account.\n"
1346 "\nList account balances where there at least 1 confirmation\n"
1347 + HelpExampleCli("listaccounts", "") +
1348 "\nList account balances including zero confirmation transactions\n"
1349 + HelpExampleCli("listaccounts", "0") +
1350 "\nList account balances for 6 or more confirmations\n"
1351 + HelpExampleCli("listaccounts", "6") +
1352 "\nAs json rpc call\n"
1353 + HelpExampleRpc("listaccounts", "6")
1357 if (params.size() > 0)
1358 nMinDepth = params[0].get_int();
1359 isminefilter includeWatchonly = ISMINE_SPENDABLE;
1360 if(params.size() > 1)
1361 if(params[1].get_bool())
1362 includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY;
1364 map<string, CAmount> mapAccountBalances;
1365 BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) {
1366 if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me
1367 mapAccountBalances[entry.second.name] = 0;
1370 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1372 const CWalletTx& wtx = (*it).second;
1374 string strSentAccount;
1375 list<COutputEntry> listReceived;
1376 list<COutputEntry> listSent;
1377 int nDepth = wtx.GetDepthInMainChain();
1378 if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
1380 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
1381 mapAccountBalances[strSentAccount] -= nFee;
1382 BOOST_FOREACH(const COutputEntry& s, listSent)
1383 mapAccountBalances[strSentAccount] -= s.amount;
1384 if (nDepth >= nMinDepth)
1386 BOOST_FOREACH(const COutputEntry& r, listReceived)
1387 if (pwalletMain->mapAddressBook.count(r.destination))
1388 mapAccountBalances[pwalletMain->mapAddressBook[r.destination].name] += r.amount;
1390 mapAccountBalances[""] += r.amount;
1394 list<CAccountingEntry> acentries;
1395 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1396 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1397 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1400 BOOST_FOREACH(const PAIRTYPE(string, CAmount)& accountBalance, mapAccountBalances) {
1401 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1406 Value listsinceblock(const Array& params, bool fHelp)
1409 throw runtime_error(
1410 "listsinceblock ( \"blockhash\" target-confirmations includeWatchonly)\n"
1411 "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n"
1413 "1. \"blockhash\" (string, optional) The block hash to list transactions since\n"
1414 "2. target-confirmations: (numeric, optional) The confirmations required, must be 1 or more\n"
1415 "3. includeWatchonly: (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')"
1418 " \"transactions\": [\n"
1419 " \"account\":\"accountname\", (string) The account name associated with the transaction. Will be \"\" for the default account.\n"
1420 " \"address\":\"bitcoinaddress\", (string) The bitcoin address of the transaction. Not present for move transactions (category = move).\n"
1421 " \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
1422 " \"amount\": x.xxx, (numeric) The amount in btc. This is negative for the 'send' category, and for the 'move' category for moves \n"
1423 " outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
1424 " \"vout\" : n, (numeric) the vout value\n"
1425 " \"fee\": x.xxx, (numeric) The amount of the fee in btc. This is negative and only available for the 'send' category of transactions.\n"
1426 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
1427 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1428 " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1429 " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
1430 " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1431 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
1432 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
1433 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1434 " \"to\": \"...\", (string) If a comment to is associated with the transaction.\n"
1436 " \"lastblock\": \"lastblockhash\" (string) The hash of the last block\n"
1439 + HelpExampleCli("listsinceblock", "")
1440 + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
1441 + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
1444 CBlockIndex *pindex = NULL;
1445 int target_confirms = 1;
1446 isminefilter filter = ISMINE_SPENDABLE;
1448 if (params.size() > 0)
1450 uint256 blockId = 0;
1452 blockId.SetHex(params[0].get_str());
1453 BlockMap::iterator it = mapBlockIndex.find(blockId);
1454 if (it != mapBlockIndex.end())
1455 pindex = it->second;
1458 if (params.size() > 1)
1460 target_confirms = params[1].get_int();
1462 if (target_confirms < 1)
1463 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
1466 if(params.size() > 2)
1467 if(params[2].get_bool())
1468 filter = filter | ISMINE_WATCH_ONLY;
1470 int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
1474 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1476 CWalletTx tx = (*it).second;
1478 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1479 ListTransactions(tx, "*", 0, true, transactions, filter);
1482 CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
1483 uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : 0;
1486 ret.push_back(Pair("transactions", transactions));
1487 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1492 Value gettransaction(const Array& params, bool fHelp)
1494 if (fHelp || params.size() < 1 || params.size() > 2)
1495 throw runtime_error(
1496 "gettransaction \"txid\" ( includeWatchonly )\n"
1497 "\nGet detailed information about in-wallet transaction <txid>\n"
1499 "1. \"txid\" (string, required) The transaction id\n"
1500 "2. \"includeWatchonly\" (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n"
1503 " \"amount\" : x.xxx, (numeric) The transaction amount in btc\n"
1504 " \"confirmations\" : n, (numeric) The number of confirmations\n"
1505 " \"blockhash\" : \"hash\", (string) The block hash\n"
1506 " \"blockindex\" : xx, (numeric) The block index\n"
1507 " \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
1508 " \"txid\" : \"transactionid\", (string) The transaction id.\n"
1509 " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
1510 " \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
1511 " \"details\" : [\n"
1513 " \"account\" : \"accountname\", (string) The account name involved in the transaction, can be \"\" for the default account.\n"
1514 " \"address\" : \"bitcoinaddress\", (string) The bitcoin address involved in the transaction\n"
1515 " \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n"
1516 " \"amount\" : x.xxx (numeric) The amount in btc\n"
1517 " \"vout\" : n, (numeric) the vout value\n"
1521 " \"hex\" : \"data\" (string) Raw data for transaction\n"
1525 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1526 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
1527 + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1531 hash.SetHex(params[0].get_str());
1533 isminefilter filter = ISMINE_SPENDABLE;
1534 if(params.size() > 1)
1535 if(params[1].get_bool())
1536 filter = filter | ISMINE_WATCH_ONLY;
1539 if (!pwalletMain->mapWallet.count(hash))
1540 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
1541 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1543 CAmount nCredit = wtx.GetCredit(filter);
1544 CAmount nDebit = wtx.GetDebit(filter);
1545 CAmount nNet = nCredit - nDebit;
1546 CAmount nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0);
1548 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1549 if (wtx.IsFromMe(filter))
1550 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1552 WalletTxToJSON(wtx, entry);
1555 ListTransactions(wtx, "*", 0, false, details, filter);
1556 entry.push_back(Pair("details", details));
1558 string strHex = EncodeHexTx(static_cast<CTransaction>(wtx));
1559 entry.push_back(Pair("hex", strHex));
1565 Value backupwallet(const Array& params, bool fHelp)
1567 if (fHelp || params.size() != 1)
1568 throw runtime_error(
1569 "backupwallet \"destination\"\n"
1570 "\nSafely copies wallet.dat to destination, which can be a directory or a path with filename.\n"
1572 "1. \"destination\" (string) The destination directory or file\n"
1574 + HelpExampleCli("backupwallet", "\"backup.dat\"")
1575 + HelpExampleRpc("backupwallet", "\"backup.dat\"")
1578 string strDest = params[0].get_str();
1579 if (!BackupWallet(*pwalletMain, strDest))
1580 throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
1586 Value keypoolrefill(const Array& params, bool fHelp)
1588 if (fHelp || params.size() > 1)
1589 throw runtime_error(
1590 "keypoolrefill ( newsize )\n"
1591 "\nFills the keypool."
1592 + HelpRequiringPassphrase() + "\n"
1594 "1. newsize (numeric, optional, default=100) The new keypool size\n"
1596 + HelpExampleCli("keypoolrefill", "")
1597 + HelpExampleRpc("keypoolrefill", "")
1600 // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
1601 unsigned int kpSize = 0;
1602 if (params.size() > 0) {
1603 if (params[0].get_int() < 0)
1604 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
1605 kpSize = (unsigned int)params[0].get_int();
1608 EnsureWalletIsUnlocked();
1609 pwalletMain->TopUpKeyPool(kpSize);
1611 if (pwalletMain->GetKeyPoolSize() < kpSize)
1612 throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
1618 static void LockWallet(CWallet* pWallet)
1620 LOCK(cs_nWalletUnlockTime);
1621 nWalletUnlockTime = 0;
1625 Value walletpassphrase(const Array& params, bool fHelp)
1627 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1628 throw runtime_error(
1629 "walletpassphrase \"passphrase\" timeout\n"
1630 "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
1631 "This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
1633 "1. \"passphrase\" (string, required) The wallet passphrase\n"
1634 "2. timeout (numeric, required) The time to keep the decryption key in seconds.\n"
1636 "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
1637 "time that overrides the old one.\n"
1639 "\nunlock the wallet for 60 seconds\n"
1640 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
1641 "\nLock the wallet again (before 60 seconds)\n"
1642 + HelpExampleCli("walletlock", "") +
1643 "\nAs json rpc call\n"
1644 + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
1649 if (!pwalletMain->IsCrypted())
1650 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1652 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1653 SecureString strWalletPass;
1654 strWalletPass.reserve(100);
1655 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1656 // Alternately, find a way to make params[0] mlock()'d to begin with.
1657 strWalletPass = params[0].get_str().c_str();
1659 if (strWalletPass.length() > 0)
1661 if (!pwalletMain->Unlock(strWalletPass))
1662 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1665 throw runtime_error(
1666 "walletpassphrase <passphrase> <timeout>\n"
1667 "Stores the wallet decryption key in memory for <timeout> seconds.");
1669 pwalletMain->TopUpKeyPool();
1671 int64_t nSleepTime = params[1].get_int64();
1672 LOCK(cs_nWalletUnlockTime);
1673 nWalletUnlockTime = GetTime() + nSleepTime;
1674 RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
1680 Value walletpassphrasechange(const Array& params, bool fHelp)
1682 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1683 throw runtime_error(
1684 "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
1685 "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
1687 "1. \"oldpassphrase\" (string) The current passphrase\n"
1688 "2. \"newpassphrase\" (string) The new passphrase\n"
1690 + HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
1691 + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
1696 if (!pwalletMain->IsCrypted())
1697 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1699 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1700 // Alternately, find a way to make params[0] mlock()'d to begin with.
1701 SecureString strOldWalletPass;
1702 strOldWalletPass.reserve(100);
1703 strOldWalletPass = params[0].get_str().c_str();
1705 SecureString strNewWalletPass;
1706 strNewWalletPass.reserve(100);
1707 strNewWalletPass = params[1].get_str().c_str();
1709 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1710 throw runtime_error(
1711 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1712 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1714 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1715 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1721 Value walletlock(const Array& params, bool fHelp)
1723 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1724 throw runtime_error(
1726 "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
1727 "After calling this method, you will need to call walletpassphrase again\n"
1728 "before being able to call any methods which require the wallet to be unlocked.\n"
1730 "\nSet the passphrase for 2 minutes to perform a transaction\n"
1731 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
1732 "\nPerform a send (requires passphrase set)\n"
1733 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 1.0") +
1734 "\nClear the passphrase since we are done before 2 minutes is up\n"
1735 + HelpExampleCli("walletlock", "") +
1736 "\nAs json rpc call\n"
1737 + HelpExampleRpc("walletlock", "")
1742 if (!pwalletMain->IsCrypted())
1743 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
1746 LOCK(cs_nWalletUnlockTime);
1747 pwalletMain->Lock();
1748 nWalletUnlockTime = 0;
1755 Value encryptwallet(const Array& params, bool fHelp)
1757 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1758 throw runtime_error(
1759 "encryptwallet \"passphrase\"\n"
1760 "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
1761 "After this, any calls that interact with private keys such as sending or signing \n"
1762 "will require the passphrase to be set prior the making these calls.\n"
1763 "Use the walletpassphrase call for this, and then walletlock call.\n"
1764 "If the wallet is already encrypted, use the walletpassphrasechange call.\n"
1765 "Note that this will shutdown the server.\n"
1767 "1. \"passphrase\" (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n"
1769 "\nEncrypt you wallet\n"
1770 + HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
1771 "\nNow set the passphrase to use the wallet, such as for signing or sending bitcoin\n"
1772 + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
1773 "\nNow we can so something like sign\n"
1774 + HelpExampleCli("signmessage", "\"bitcoinaddress\" \"test message\"") +
1775 "\nNow lock the wallet again by removing the passphrase\n"
1776 + HelpExampleCli("walletlock", "") +
1777 "\nAs a json rpc call\n"
1778 + HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
1783 if (pwalletMain->IsCrypted())
1784 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
1786 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1787 // Alternately, find a way to make params[0] mlock()'d to begin with.
1788 SecureString strWalletPass;
1789 strWalletPass.reserve(100);
1790 strWalletPass = params[0].get_str().c_str();
1792 if (strWalletPass.length() < 1)
1793 throw runtime_error(
1794 "encryptwallet <passphrase>\n"
1795 "Encrypts the wallet with <passphrase>.");
1797 if (!pwalletMain->EncryptWallet(strWalletPass))
1798 throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
1800 // BDB seems to have a bad habit of writing old data into
1801 // slack space in .dat files; that is bad if the old data is
1802 // unencrypted private keys. So:
1804 return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
1807 Value lockunspent(const Array& params, bool fHelp)
1809 if (fHelp || params.size() < 1 || params.size() > 2)
1810 throw runtime_error(
1811 "lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n"
1812 "\nUpdates list of temporarily unspendable outputs.\n"
1813 "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
1814 "A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
1815 "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
1816 "is always cleared (by virtue of process exit) when a node stops or fails.\n"
1817 "Also see the listunspent call\n"
1819 "1. unlock (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
1820 "2. \"transactions\" (string, required) A json array of objects. Each object the txid (string) vout (numeric)\n"
1821 " [ (json array of json objects)\n"
1823 " \"txid\":\"id\", (string) The transaction id\n"
1824 " \"vout\": n (numeric) The output number\n"
1830 "true|false (boolean) Whether the command was successful or not\n"
1833 "\nList the unspent transactions\n"
1834 + HelpExampleCli("listunspent", "") +
1835 "\nLock an unspent transaction\n"
1836 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1837 "\nList the locked transactions\n"
1838 + HelpExampleCli("listlockunspent", "") +
1839 "\nUnlock the transaction again\n"
1840 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1841 "\nAs a json rpc call\n"
1842 + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
1845 if (params.size() == 1)
1846 RPCTypeCheck(params, list_of(bool_type));
1848 RPCTypeCheck(params, list_of(bool_type)(array_type));
1850 bool fUnlock = params[0].get_bool();
1852 if (params.size() == 1) {
1854 pwalletMain->UnlockAllCoins();
1858 Array outputs = params[1].get_array();
1859 BOOST_FOREACH(Value& output, outputs)
1861 if (output.type() != obj_type)
1862 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
1863 const Object& o = output.get_obj();
1865 RPCTypeCheck(o, map_list_of("txid", str_type)("vout", int_type));
1867 string txid = find_value(o, "txid").get_str();
1869 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
1871 int nOutput = find_value(o, "vout").get_int();
1873 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
1875 COutPoint outpt(uint256(txid), nOutput);
1878 pwalletMain->UnlockCoin(outpt);
1880 pwalletMain->LockCoin(outpt);
1886 Value listlockunspent(const Array& params, bool fHelp)
1888 if (fHelp || params.size() > 0)
1889 throw runtime_error(
1891 "\nReturns list of temporarily unspendable outputs.\n"
1892 "See the lockunspent call to lock and unlock transactions for spending.\n"
1896 " \"txid\" : \"transactionid\", (string) The transaction id locked\n"
1897 " \"vout\" : n (numeric) The vout value\n"
1902 "\nList the unspent transactions\n"
1903 + HelpExampleCli("listunspent", "") +
1904 "\nLock an unspent transaction\n"
1905 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1906 "\nList the locked transactions\n"
1907 + HelpExampleCli("listlockunspent", "") +
1908 "\nUnlock the transaction again\n"
1909 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1910 "\nAs a json rpc call\n"
1911 + HelpExampleRpc("listlockunspent", "")
1914 vector<COutPoint> vOutpts;
1915 pwalletMain->ListLockedCoins(vOutpts);
1919 BOOST_FOREACH(COutPoint &outpt, vOutpts) {
1922 o.push_back(Pair("txid", outpt.hash.GetHex()));
1923 o.push_back(Pair("vout", (int)outpt.n));
1930 Value settxfee(const Array& params, bool fHelp)
1932 if (fHelp || params.size() < 1 || params.size() > 1)
1933 throw runtime_error(
1935 "\nSet the transaction fee per kB.\n"
1937 "1. amount (numeric, required) The transaction fee in BTC/kB rounded to the nearest 0.00000001\n"
1939 "true|false (boolean) Returns true if successful\n"
1941 + HelpExampleCli("settxfee", "0.00001")
1942 + HelpExampleRpc("settxfee", "0.00001")
1946 CAmount nAmount = 0;
1947 if (params[0].get_real() != 0.0)
1948 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
1950 payTxFee = CFeeRate(nAmount, 1000);
1954 Value getwalletinfo(const Array& params, bool fHelp)
1956 if (fHelp || params.size() != 0)
1957 throw runtime_error(
1959 "Returns an object containing various wallet state info.\n"
1962 " \"walletversion\": xxxxx, (numeric) the wallet version\n"
1963 " \"balance\": xxxxxxx, (numeric) the total bitcoin balance of the wallet\n"
1964 " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
1965 " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
1966 " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
1967 " \"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"
1970 + HelpExampleCli("getwalletinfo", "")
1971 + HelpExampleRpc("getwalletinfo", "")
1975 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
1976 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
1977 obj.push_back(Pair("txcount", (int)pwalletMain->mapWallet.size()));
1978 obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
1979 obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
1980 if (pwalletMain->IsCrypted())
1981 obj.push_back(Pair("unlocked_until", nWalletUnlockTime));