1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2013 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.
17 #include <boost/assign/list_of.hpp>
18 #include "json/json_spirit_utils.h"
19 #include "json/json_spirit_value.h"
22 using namespace boost;
23 using namespace boost::assign;
24 using namespace json_spirit;
26 int64_t nWalletUnlockTime;
27 static CCriticalSection cs_nWalletUnlockTime;
29 std::string HelpRequiringPassphrase()
31 return pwalletMain && pwalletMain->IsCrypted()
32 ? "\nRequires wallet passphrase to be set with walletpassphrase call."
36 void EnsureWalletIsUnlocked()
38 if (pwalletMain->IsLocked())
39 throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
42 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
44 int confirms = wtx.GetDepthInMainChain();
45 entry.push_back(Pair("confirmations", confirms));
47 entry.push_back(Pair("generated", true));
50 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
51 entry.push_back(Pair("blockindex", wtx.nIndex));
52 entry.push_back(Pair("blocktime", (boost::int64_t)(mapBlockIndex[wtx.hashBlock]->nTime)));
54 entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
55 entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
56 entry.push_back(Pair("timereceived", (boost::int64_t)wtx.nTimeReceived));
57 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
58 entry.push_back(Pair(item.first, item.second));
61 string AccountFromValue(const Value& value)
63 string strAccount = value.get_str();
64 if (strAccount == "*")
65 throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Invalid account name");
69 Value getnewaddress(const Array& params, bool fHelp)
71 if (fHelp || params.size() > 1)
73 "getnewaddress ( \"account\" )\n"
74 "\nReturns a new Bitcoin address for receiving payments.\n"
75 "If 'account' is specified (recommended), it is added to the address book \n"
76 "so payments received with the address will be credited to 'account'.\n"
78 "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"
80 "\"bitcoinaddress\" (string) The new bitcoin address\n"
82 + HelpExampleCli("getnewaddress", "")
83 + HelpExampleCli("getnewaddress", "\"\"")
84 + HelpExampleCli("getnewaddress", "\"myaccount\"")
85 + HelpExampleRpc("getnewaddress", "\"myaccount\"")
88 // Parse the account first so we don't generate a key if there's an error
90 if (params.size() > 0)
91 strAccount = AccountFromValue(params[0]);
93 if (!pwalletMain->IsLocked())
94 pwalletMain->TopUpKeyPool();
96 // Generate a new key that is added to wallet
98 if (!pwalletMain->GetKeyFromPool(newKey))
99 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
100 CKeyID keyID = newKey.GetID();
102 pwalletMain->SetAddressBook(keyID, strAccount, "receive");
104 return CBitcoinAddress(keyID).ToString();
108 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
110 CWalletDB walletdb(pwalletMain->strWalletFile);
113 walletdb.ReadAccount(strAccount, account);
115 bool bKeyUsed = false;
117 // Check if the current key has been used
118 if (account.vchPubKey.IsValid())
120 CScript scriptPubKey;
121 scriptPubKey.SetDestination(account.vchPubKey.GetID());
122 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
123 it != pwalletMain->mapWallet.end() && account.vchPubKey.IsValid();
126 const CWalletTx& wtx = (*it).second;
127 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
128 if (txout.scriptPubKey == scriptPubKey)
133 // Generate a new key
134 if (!account.vchPubKey.IsValid() || bForceNew || bKeyUsed)
136 if (!pwalletMain->GetKeyFromPool(account.vchPubKey))
137 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
139 pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, "receive");
140 walletdb.WriteAccount(strAccount, account);
143 return CBitcoinAddress(account.vchPubKey.GetID());
146 Value getaccountaddress(const Array& params, bool fHelp)
148 if (fHelp || params.size() != 1)
150 "getaccountaddress \"account\"\n"
151 "\nReturns the current Bitcoin address for receiving payments to this account.\n"
153 "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"
155 "\"bitcoinaddress\" (string) The account bitcoin address\n"
157 + HelpExampleCli("getaccountaddress", "")
158 + HelpExampleCli("getaccountaddress", "\"\"")
159 + HelpExampleCli("getaccountaddress", "\"myaccount\"")
160 + HelpExampleRpc("getaccountaddress", "\"myaccount\"")
163 // Parse the account first so we don't generate a key if there's an error
164 string strAccount = AccountFromValue(params[0]);
168 ret = GetAccountAddress(strAccount).ToString();
174 Value getrawchangeaddress(const Array& params, bool fHelp)
176 if (fHelp || params.size() > 1)
178 "getrawchangeaddress\n"
179 "\nReturns a new Bitcoin address, for receiving change.\n"
180 "This is for use with raw transactions, NOT normal use.\n"
182 "\"address\" (string) The address\n"
184 + HelpExampleCli("getrawchangeaddress", "")
185 + HelpExampleRpc("getrawchangeaddress", "")
188 if (!pwalletMain->IsLocked())
189 pwalletMain->TopUpKeyPool();
191 CReserveKey reservekey(pwalletMain);
193 if (!reservekey.GetReservedKey(vchPubKey))
194 throw JSONRPCError(RPC_WALLET_ERROR, "Error: Unable to obtain key for change");
196 reservekey.KeepKey();
198 CKeyID keyID = vchPubKey.GetID();
200 return CBitcoinAddress(keyID).ToString();
204 Value setaccount(const Array& params, bool fHelp)
206 if (fHelp || params.size() < 1 || params.size() > 2)
208 "setaccount \"bitcoinaddress\" \"account\"\n"
209 "\nSets the account associated with the given address.\n"
211 "1. \"bitcoinaddress\" (string, required) The bitcoin address to be associated with an account.\n"
212 "2. \"account\" (string, required) The account to assign the address to.\n"
214 + HelpExampleCli("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"tabby\"")
215 + HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"tabby\"")
218 CBitcoinAddress address(params[0].get_str());
219 if (!address.IsValid())
220 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
224 if (params.size() > 1)
225 strAccount = AccountFromValue(params[1]);
227 // Detect when changing the account of an address that is the 'unused current key' of another account:
228 if (pwalletMain->mapAddressBook.count(address.Get()))
230 string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name;
231 if (address == GetAccountAddress(strOldAccount))
232 GetAccountAddress(strOldAccount, true);
235 pwalletMain->SetAddressBook(address.Get(), strAccount, "receive");
241 Value getaccount(const Array& params, bool fHelp)
243 if (fHelp || params.size() != 1)
245 "getaccount \"bitcoinaddress\"\n"
246 "\nReturns the account associated with the given address.\n"
248 "1. \"bitcoinaddress\" (string, required) The bitcoin address for account lookup.\n"
250 "\"accountname\" (string) the account address\n"
252 + HelpExampleCli("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
253 + HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
256 CBitcoinAddress address(params[0].get_str());
257 if (!address.IsValid())
258 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
261 map<CTxDestination, CAddressBookData>::iterator mi = pwalletMain->mapAddressBook.find(address.Get());
262 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty())
263 strAccount = (*mi).second.name;
268 Value getaddressesbyaccount(const Array& params, bool fHelp)
270 if (fHelp || params.size() != 1)
272 "getaddressesbyaccount \"account\"\n"
273 "\nReturns the list of addresses for the given account.\n"
275 "1. \"account\" (string, required) The account name.\n"
277 "[ (json array of string)\n"
278 " \"bitcoinaddress\" (string) a bitcoin address associated with the given account\n"
282 + HelpExampleCli("getaddressesbyaccount", "\"tabby\"")
283 + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
286 string strAccount = AccountFromValue(params[0]);
288 // Find all addresses that have the given account
290 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
292 const CBitcoinAddress& address = item.first;
293 const string& strName = item.second.name;
294 if (strName == strAccount)
295 ret.push_back(address.ToString());
300 Value sendtoaddress(const Array& params, bool fHelp)
302 if (fHelp || params.size() < 2 || params.size() > 4)
304 "sendtoaddress \"bitcoinaddress\" amount ( \"comment\" \"comment-to\" )\n"
305 "\nSent an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n"
306 + HelpRequiringPassphrase() +
308 "1. \"bitcoinaddress\" (string, required) The bitcoin address to send to.\n"
309 "2. \"amount\" (numeric, required) The amount in btc to send. eg 0.1\n"
310 "3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
311 " This is not part of the transaction, just kept in your wallet.\n"
312 "4. \"comment-to\" (string, optional) A comment to store the name of the person or organization \n"
313 " to which you're sending the transaction. This is not part of the \n"
314 " transaction, just kept in your wallet.\n"
316 "\"transactionid\" (string) The transaction id. (view at https://blockchain.info/tx/[transactionid])\n"
318 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
319 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
320 + HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
323 CBitcoinAddress address(params[0].get_str());
324 if (!address.IsValid())
325 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
328 int64_t nAmount = AmountFromValue(params[1]);
332 if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
333 wtx.mapValue["comment"] = params[2].get_str();
334 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
335 wtx.mapValue["to"] = params[3].get_str();
337 EnsureWalletIsUnlocked();
339 string strError = pwalletMain->SendMoneyToDestination(address.Get(), nAmount, wtx);
341 throw JSONRPCError(RPC_WALLET_ERROR, strError);
343 return wtx.GetHash().GetHex();
346 Value listaddressgroupings(const Array& params, bool fHelp)
350 "listaddressgroupings\n"
351 "\nLists groups of addresses which have had their common ownership\n"
352 "made public by common use as inputs or as the resulting change\n"
353 "in past transactions\n"
358 " \"bitcoinaddress\", (string) The bitcoin address\n"
359 " amount, (numeric) The amount in btc\n"
360 " \"account\" (string, optional) The account\n"
367 + HelpExampleCli("listaddressgroupings", "")
368 + HelpExampleRpc("listaddressgroupings", "")
372 map<CTxDestination, int64_t> balances = pwalletMain->GetAddressBalances();
373 BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
376 BOOST_FOREACH(CTxDestination address, grouping)
379 addressInfo.push_back(CBitcoinAddress(address).ToString());
380 addressInfo.push_back(ValueFromAmount(balances[address]));
382 LOCK(pwalletMain->cs_wallet);
383 if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end())
384 addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second.name);
386 jsonGrouping.push_back(addressInfo);
388 jsonGroupings.push_back(jsonGrouping);
390 return jsonGroupings;
393 Value signmessage(const Array& params, bool fHelp)
395 if (fHelp || params.size() != 2)
397 "signmessage \"bitcoinaddress\" \"message\"\n"
398 "\nSign a message with the private key of an address"
399 + HelpRequiringPassphrase() + "\n"
401 "1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the private key.\n"
402 "2. \"message\" (string, required) The message to create a signature of.\n"
404 "\"signature\" (string) The signature of the message encoded in base 64\n"
406 "\nUnlock the wallet for 30 seconds\n"
407 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
408 "\nCreate the signature\n"
409 + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
410 "\nVerify the signature\n"
411 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
413 + HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"my message\"")
416 EnsureWalletIsUnlocked();
418 string strAddress = params[0].get_str();
419 string strMessage = params[1].get_str();
421 CBitcoinAddress addr(strAddress);
423 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
426 if (!addr.GetKeyID(keyID))
427 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
430 if (!pwalletMain->GetKey(keyID, key))
431 throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
433 CHashWriter ss(SER_GETHASH, 0);
434 ss << strMessageMagic;
437 vector<unsigned char> vchSig;
438 if (!key.SignCompact(ss.GetHash(), vchSig))
439 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
441 return EncodeBase64(&vchSig[0], vchSig.size());
444 Value getreceivedbyaddress(const Array& params, bool fHelp)
446 if (fHelp || params.size() < 1 || params.size() > 2)
448 "getreceivedbyaddress \"bitcoinaddress\" ( minconf )\n"
449 "\nReturns the total amount received by the given bitcoinaddress in transactions with at least minconf confirmations.\n"
451 "1. \"bitcoinaddress\" (string, required) The bitcoin address for transactions.\n"
452 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
454 "amount (numeric) The total amount in btc received at this address.\n"
456 "\nThe amount from transactions with at least 1 confirmation\n"
457 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"") +
458 "\nThe amount including unconfirmed transactions, zero confirmations\n"
459 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 0") +
460 "\nThe amount with at least 6 confirmation, very safe\n"
461 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 6") +
462 "\nAs a json rpc call\n"
463 + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", 6")
467 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
468 CScript scriptPubKey;
469 if (!address.IsValid())
470 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
471 scriptPubKey.SetDestination(address.Get());
472 if (!IsMine(*pwalletMain,scriptPubKey))
475 // Minimum confirmations
477 if (params.size() > 1)
478 nMinDepth = params[1].get_int();
482 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
484 const CWalletTx& wtx = (*it).second;
485 if (wtx.IsCoinBase() || !IsFinalTx(wtx))
488 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
489 if (txout.scriptPubKey == scriptPubKey)
490 if (wtx.GetDepthInMainChain() >= nMinDepth)
491 nAmount += txout.nValue;
494 return ValueFromAmount(nAmount);
498 Value getreceivedbyaccount(const Array& params, bool fHelp)
500 if (fHelp || params.size() < 1 || params.size() > 2)
502 "getreceivedbyaccount \"account\" ( minconf )\n"
503 "\nReturns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
505 "1. \"account\" (string, required) The selected account, may be the default account using \"\".\n"
506 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
508 "amount (numeric) The total amount in btc received for this account.\n"
510 "\nAmount received by the default account with at least 1 confirmation\n"
511 + HelpExampleCli("getreceivedbyaccount", "\"\"") +
512 "\nAmount received at the tabby account including unconfirmed amounts with zero confirmations\n"
513 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 0") +
514 "\nThe amount with at least 6 confirmation, very safe\n"
515 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 6") +
516 "\nAs a json rpc call\n"
517 + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
520 // Minimum confirmations
522 if (params.size() > 1)
523 nMinDepth = params[1].get_int();
525 // Get the set of pub keys assigned to account
526 string strAccount = AccountFromValue(params[0]);
527 set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount);
531 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
533 const CWalletTx& wtx = (*it).second;
534 if (wtx.IsCoinBase() || !IsFinalTx(wtx))
537 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
539 CTxDestination address;
540 if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
541 if (wtx.GetDepthInMainChain() >= nMinDepth)
542 nAmount += txout.nValue;
546 return (double)nAmount / (double)COIN;
550 int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
552 int64_t nBalance = 0;
554 // Tally wallet transactions
555 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
557 const CWalletTx& wtx = (*it).second;
561 int64_t nReceived, nSent, nFee;
562 wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee);
564 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
565 nBalance += nReceived;
566 nBalance -= nSent + nFee;
569 // Tally internal accounting entries
570 nBalance += walletdb.GetAccountCreditDebit(strAccount);
575 int64_t GetAccountBalance(const string& strAccount, int nMinDepth)
577 CWalletDB walletdb(pwalletMain->strWalletFile);
578 return GetAccountBalance(walletdb, strAccount, nMinDepth);
582 Value getbalance(const Array& params, bool fHelp)
584 if (fHelp || params.size() > 2)
586 "getbalance ( \"account\" minconf )\n"
587 "\nIf account is not specified, returns the server's total available balance.\n"
588 "If account is specified, returns the balance in the account.\n"
589 "Note that the account \"\" is not the same as leaving the parameter out.\n"
590 "The server total may be different to the balance in the default \"\" account.\n"
592 "1. \"account\" (string, optional) The selected account, or \"*\" for entire wallet. It may be the default account using \"\".\n"
593 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
595 "amount (numeric) The total amount in btc received for this account.\n"
597 "\nThe total amount in the server across all accounts\n"
598 + HelpExampleCli("getbalance", "") +
599 "\nThe total amount in the server across all accounts, with at least 5 confirmations\n"
600 + HelpExampleCli("getbalance", "\"*\" 6") +
601 "\nThe total amount in the default account with at least 1 confirmation\n"
602 + HelpExampleCli("getbalance", "\"\"") +
603 "\nThe total amount in the account named tabby with at least 6 confirmations\n"
604 + HelpExampleCli("getbalance", "\"tabby\" 6") +
605 "\nAs a json rpc call\n"
606 + HelpExampleRpc("getbalance", "\"tabby\", 6")
609 if (params.size() == 0)
610 return ValueFromAmount(pwalletMain->GetBalance());
613 if (params.size() > 1)
614 nMinDepth = params[1].get_int();
616 if (params[0].get_str() == "*") {
617 // Calculate total balance a different way from GetBalance()
618 // (GetBalance() sums up all unspent TxOuts)
619 // getbalance and getbalance '*' 0 should return the same number
620 int64_t nBalance = 0;
621 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
623 const CWalletTx& wtx = (*it).second;
624 if (!wtx.IsConfirmed())
628 string strSentAccount;
629 list<pair<CTxDestination, int64_t> > listReceived;
630 list<pair<CTxDestination, int64_t> > listSent;
631 wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount);
632 if (wtx.GetDepthInMainChain() >= nMinDepth)
634 BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listReceived)
635 nBalance += r.second;
637 BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listSent)
638 nBalance -= r.second;
641 return ValueFromAmount(nBalance);
644 string strAccount = AccountFromValue(params[0]);
646 int64_t nBalance = GetAccountBalance(strAccount, nMinDepth);
648 return ValueFromAmount(nBalance);
651 Value getunconfirmedbalance(const Array ¶ms, bool fHelp)
653 if (fHelp || params.size() > 0)
655 "getunconfirmedbalance\n"
656 "Returns the server's total unconfirmed balance\n");
657 return ValueFromAmount(pwalletMain->GetUnconfirmedBalance());
661 Value movecmd(const Array& params, bool fHelp)
663 if (fHelp || params.size() < 3 || params.size() > 5)
665 "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
666 "\nMove a specified amount from one account in your wallet to another.\n"
668 "1. \"fromaccount\" (string, required) The name of the account to move funds from. May be the default account using \"\".\n"
669 "2. \"toaccount\" (string, required) The name of the account to move funds to. May be the default account using \"\".\n"
670 "3. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
671 "4. \"comment\" (string, optional) An optional comment, stored in the wallet only.\n"
673 "true|false (boolean) true if successfull.\n"
675 "\nMove 0.01 btc from the default account to the account named tabby\n"
676 + HelpExampleCli("move", "\"\" \"tabby\" 0.01") +
677 "\nMove 0.01 btc timotei to akiko with a comment and funds have 6 confirmations\n"
678 + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") +
679 "\nAs a json rpc call\n"
680 + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
683 string strFrom = AccountFromValue(params[0]);
684 string strTo = AccountFromValue(params[1]);
685 int64_t nAmount = AmountFromValue(params[2]);
686 if (params.size() > 3)
687 // unused parameter, used to be nMinDepth, keep type-checking it though
688 (void)params[3].get_int();
690 if (params.size() > 4)
691 strComment = params[4].get_str();
693 CWalletDB walletdb(pwalletMain->strWalletFile);
694 if (!walletdb.TxnBegin())
695 throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
697 int64_t nNow = GetAdjustedTime();
700 CAccountingEntry debit;
701 debit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
702 debit.strAccount = strFrom;
703 debit.nCreditDebit = -nAmount;
705 debit.strOtherAccount = strTo;
706 debit.strComment = strComment;
707 walletdb.WriteAccountingEntry(debit);
710 CAccountingEntry credit;
711 credit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
712 credit.strAccount = strTo;
713 credit.nCreditDebit = nAmount;
715 credit.strOtherAccount = strFrom;
716 credit.strComment = strComment;
717 walletdb.WriteAccountingEntry(credit);
719 if (!walletdb.TxnCommit())
720 throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
726 Value sendfrom(const Array& params, bool fHelp)
728 if (fHelp || params.size() < 3 || params.size() > 6)
730 "sendfrom \"fromaccount\" \"tobitcoinaddress\" amount ( minconf \"comment\" \"comment-to\" )\n"
731 "\nSent an amount from an account to a bitcoin address.\n"
732 "The amount is a real and is rounded to the nearest 0.00000001."
733 + HelpRequiringPassphrase() + "\n"
735 "1. \"fromaccount\" (string, required) The name of the account to send funds from. May be the default account using \"\".\n"
736 "2. \"tobitcoinaddress\" (string, required) The bitcoin address to send funds to.\n"
737 "3. amount (numeric, required) The amount in btc. (transaction fee is added on top).\n"
738 "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
739 "5. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
740 " This is not part of the transaction, just kept in your wallet.\n"
741 "6. \"comment-to\" (string, optional) An optional comment to store the name of the person or organization \n"
742 " to which you're sending the transaction. This is not part of the transaction, \n"
743 " it is just kept in your wallet.\n"
745 "\"transactionid\" (string) The transaction id. (view at https://blockchain.info/tx/[transactionid])\n"
747 "\nSend 0.01 btc from the default account to the address, must have at least 1 confirmation\n"
748 + HelpExampleCli("sendfrom", "\"\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") +
749 "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
750 + HelpExampleCli("sendfrom", "\"tabby\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01 6 \"donation\" \"seans outpost\"") +
751 "\nAs a json rpc call\n"
752 + HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
755 string strAccount = AccountFromValue(params[0]);
756 CBitcoinAddress address(params[1].get_str());
757 if (!address.IsValid())
758 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
759 int64_t nAmount = AmountFromValue(params[2]);
761 if (params.size() > 3)
762 nMinDepth = params[3].get_int();
765 wtx.strFromAccount = strAccount;
766 if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
767 wtx.mapValue["comment"] = params[4].get_str();
768 if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
769 wtx.mapValue["to"] = params[5].get_str();
771 EnsureWalletIsUnlocked();
774 int64_t nBalance = GetAccountBalance(strAccount, nMinDepth);
775 if (nAmount > nBalance)
776 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
779 string strError = pwalletMain->SendMoneyToDestination(address.Get(), nAmount, wtx);
781 throw JSONRPCError(RPC_WALLET_ERROR, strError);
783 return wtx.GetHash().GetHex();
787 Value sendmany(const Array& params, bool fHelp)
789 if (fHelp || params.size() < 2 || params.size() > 4)
791 "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" )\n"
792 "\nSend multiple times. Amounts are double-precision floating point numbers."
793 + HelpRequiringPassphrase() + "\n"
795 "1. \"fromaccount\" (string, required) The account to send the funds from, can be \"\" for the default account\n"
796 "2. \"amounts\" (string, required) A json object with addresses and amounts\n"
798 " \"address\":amount (numeric) The bitcoin address is the key, the numeric amount in btc is the value\n"
801 "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
802 "4. \"comment\" (string, optional) A comment\n"
804 "\"transactionid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
805 " the number of addresses. See https://blockchain.info/tx/[transactionid]\n"
807 "\nSend two amounts to two different addresses:\n"
808 + HelpExampleCli("sendmany", "\"tabby\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
809 "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
810 + HelpExampleCli("sendmany", "\"tabby\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
811 "\nAs a json rpc call\n"
812 + HelpExampleRpc("sendmany", "\"tabby\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
815 string strAccount = AccountFromValue(params[0]);
816 Object sendTo = params[1].get_obj();
818 if (params.size() > 2)
819 nMinDepth = params[2].get_int();
822 wtx.strFromAccount = strAccount;
823 if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
824 wtx.mapValue["comment"] = params[3].get_str();
826 set<CBitcoinAddress> setAddress;
827 vector<pair<CScript, int64_t> > vecSend;
829 int64_t totalAmount = 0;
830 BOOST_FOREACH(const Pair& s, sendTo)
832 CBitcoinAddress address(s.name_);
833 if (!address.IsValid())
834 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_);
836 if (setAddress.count(address))
837 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
838 setAddress.insert(address);
840 CScript scriptPubKey;
841 scriptPubKey.SetDestination(address.Get());
842 int64_t nAmount = AmountFromValue(s.value_);
843 totalAmount += nAmount;
845 vecSend.push_back(make_pair(scriptPubKey, nAmount));
848 EnsureWalletIsUnlocked();
851 int64_t nBalance = GetAccountBalance(strAccount, nMinDepth);
852 if (totalAmount > nBalance)
853 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
856 CReserveKey keyChange(pwalletMain);
857 int64_t nFeeRequired = 0;
858 string strFailReason;
859 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, strFailReason);
861 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
862 if (!pwalletMain->CommitTransaction(wtx, keyChange))
863 throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed");
865 return wtx.GetHash().GetHex();
868 // Defined in rpcmisc.cpp
869 extern CScript _createmultisig(const Array& params);
871 Value addmultisigaddress(const Array& params, bool fHelp)
873 if (fHelp || params.size() < 2 || params.size() > 3)
875 string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
876 "\nAdd a nrequired-to-sign multisignature address to the wallet.\n"
877 "Each key is a Bitcoin address or hex-encoded public key.\n"
878 "If 'account' is specified, assign address to that account.\n"
881 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
882 "2. \"keysobject\" (string, required) A json array of bitcoin addresses or hex-encoded public keys\n"
884 " \"address\" (string) bitcoin address or hex-encoded public key\n"
887 "3. \"account\" (string, optional) An account to assign the addresses to.\n"
890 "\"bitcoinaddress\" (string) A bitcoin address associated with the keys.\n"
893 "\nAdd a multisig address from 2 addresses\n"
894 + HelpExampleCli("addmultisigaddress", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
895 "\nAs json rpc call\n"
896 + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
898 throw runtime_error(msg);
902 if (params.size() > 2)
903 strAccount = AccountFromValue(params[2]);
905 // Construct using pay-to-script-hash:
906 CScript inner = _createmultisig(params);
907 CScriptID innerID = inner.GetID();
908 pwalletMain->AddCScript(inner);
910 pwalletMain->SetAddressBook(innerID, strAccount, "send");
911 return CBitcoinAddress(innerID).ToString();
919 vector<uint256> txids;
923 nConf = std::numeric_limits<int>::max();
927 Value ListReceived(const Array& params, bool fByAccounts)
929 // Minimum confirmations
931 if (params.size() > 0)
932 nMinDepth = params[0].get_int();
934 // Whether to include empty accounts
935 bool fIncludeEmpty = false;
936 if (params.size() > 1)
937 fIncludeEmpty = params[1].get_bool();
940 map<CBitcoinAddress, tallyitem> mapTally;
941 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
943 const CWalletTx& wtx = (*it).second;
945 if (wtx.IsCoinBase() || !IsFinalTx(wtx))
948 int nDepth = wtx.GetDepthInMainChain();
949 if (nDepth < nMinDepth)
952 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
954 CTxDestination address;
955 if (!ExtractDestination(txout.scriptPubKey, address) || !IsMine(*pwalletMain, address))
958 tallyitem& item = mapTally[address];
959 item.nAmount += txout.nValue;
960 item.nConf = min(item.nConf, nDepth);
961 item.txids.push_back(wtx.GetHash());
967 map<string, tallyitem> mapAccountTally;
968 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
970 const CBitcoinAddress& address = item.first;
971 const string& strAccount = item.second.name;
972 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
973 if (it == mapTally.end() && !fIncludeEmpty)
977 int nConf = std::numeric_limits<int>::max();
978 if (it != mapTally.end())
980 nAmount = (*it).second.nAmount;
981 nConf = (*it).second.nConf;
986 tallyitem& item = mapAccountTally[strAccount];
987 item.nAmount += nAmount;
988 item.nConf = min(item.nConf, nConf);
993 obj.push_back(Pair("address", address.ToString()));
994 obj.push_back(Pair("account", strAccount));
995 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
996 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
998 if (it != mapTally.end())
1000 BOOST_FOREACH(const uint256& item, (*it).second.txids)
1002 transactions.push_back(item.GetHex());
1005 obj.push_back(Pair("txids", transactions));
1012 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1014 int64_t nAmount = (*it).second.nAmount;
1015 int nConf = (*it).second.nConf;
1017 obj.push_back(Pair("account", (*it).first));
1018 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1019 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1027 Value listreceivedbyaddress(const Array& params, bool fHelp)
1029 if (fHelp || params.size() > 2)
1030 throw runtime_error(
1031 "listreceivedbyaddress ( minconf includeempty )\n"
1032 "\nList balances by receiving address.\n"
1034 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1035 "2. includeempty (numeric, optional, dafault=false) Whether to include addresses that haven't received any payments.\n"
1040 " \"address\" : \"receivingaddress\", (string) The receiving address\n"
1041 " \"account\" : \"accountname\", (string) The account of the receiving address. The default account is \"\".\n"
1042 " \"amount\" : x.xxx, (numeric) The total amount in btc received by the address\n"
1043 " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
1049 + HelpExampleCli("listreceivedbyaddress", "")
1050 + HelpExampleCli("listreceivedbyaddress", "6 true")
1051 + HelpExampleRpc("listreceivedbyaddress", "6, true")
1054 return ListReceived(params, false);
1057 Value listreceivedbyaccount(const Array& params, bool fHelp)
1059 if (fHelp || params.size() > 2)
1060 throw runtime_error(
1061 "listreceivedbyaccount ( minconf includeempty )\n"
1062 "\nList balances by account.\n"
1064 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1065 "2. includeempty (boolean, optional, default=false) Whether to include accounts that haven't received any payments.\n"
1070 " \"account\" : \"accountname\", (string) The account name of the receiving account\n"
1071 " \"amount\" : x.xxx, (numeric) The total amount received by addresses with this account\n"
1072 " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n"
1078 + HelpExampleCli("listreceivedbyaccount", "")
1079 + HelpExampleCli("listreceivedbyaccount", "6 true")
1080 + HelpExampleRpc("listreceivedbyaccount", "6, true")
1083 return ListReceived(params, true);
1086 static void MaybePushAddress(Object & entry, const CTxDestination &dest)
1088 CBitcoinAddress addr;
1090 entry.push_back(Pair("address", addr.ToString()));
1093 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1096 string strSentAccount;
1097 list<pair<CTxDestination, int64_t> > listReceived;
1098 list<pair<CTxDestination, int64_t> > listSent;
1100 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount);
1102 bool fAllAccounts = (strAccount == string("*"));
1105 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1107 BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& s, listSent)
1110 entry.push_back(Pair("account", strSentAccount));
1111 MaybePushAddress(entry, s.first);
1112 entry.push_back(Pair("category", "send"));
1113 entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1114 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1116 WalletTxToJSON(wtx, entry);
1117 ret.push_back(entry);
1122 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1124 BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& r, listReceived)
1127 if (pwalletMain->mapAddressBook.count(r.first))
1128 account = pwalletMain->mapAddressBook[r.first].name;
1129 if (fAllAccounts || (account == strAccount))
1132 entry.push_back(Pair("account", account));
1133 MaybePushAddress(entry, r.first);
1134 if (wtx.IsCoinBase())
1136 if (wtx.GetDepthInMainChain() < 1)
1137 entry.push_back(Pair("category", "orphan"));
1138 else if (wtx.GetBlocksToMaturity() > 0)
1139 entry.push_back(Pair("category", "immature"));
1141 entry.push_back(Pair("category", "generate"));
1144 entry.push_back(Pair("category", "receive"));
1145 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1147 WalletTxToJSON(wtx, entry);
1148 ret.push_back(entry);
1154 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1156 bool fAllAccounts = (strAccount == string("*"));
1158 if (fAllAccounts || acentry.strAccount == strAccount)
1161 entry.push_back(Pair("account", acentry.strAccount));
1162 entry.push_back(Pair("category", "move"));
1163 entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1164 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1165 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1166 entry.push_back(Pair("comment", acentry.strComment));
1167 ret.push_back(entry);
1171 Value listtransactions(const Array& params, bool fHelp)
1173 if (fHelp || params.size() > 3)
1174 throw runtime_error(
1175 "listtransactions ( \"account\" count from )\n"
1176 "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n"
1178 "1. \"account\" (string, optional) The account name. If not included, it will list all transactions for all accounts.\n"
1179 " If \"\" is set, it will list transactions for the default account.\n"
1180 "2. count (numeric, optional, default=10) The number of transactions to return\n"
1181 "3. from (numeric, optional, default=0) The number of transactions to skip\n"
1186 " \"account\":\"accountname\", (string) The account name associated with the transaction. \n"
1187 " It will be \"\" for the default account.\n"
1188 " \"address\":\"bitcoinaddress\", (string) The bitcoin address of the transaction. Not present for \n"
1189 " move transactions (category = move).\n"
1190 " \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n"
1191 " transaction between accounts, and not associated with an address,\n"
1192 " transaction id or block. 'send' and 'receive' transactions are \n"
1193 " associated with an address, transaction id and block details\n"
1194 " \"amount\": x.xxx, (numeric) The amount in btc. This is negative for the 'send' category, and for the\n"
1195 " 'move' category for moves outbound. It is positive for the 'receive' category,\n"
1196 " and for the 'move' category for inbound funds.\n"
1197 " \"fee\": x.xxx, (numeric) The amount of the fee in btc. This is negative and only available for the \n"
1198 " 'send' category of transactions.\n"
1199 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
1200 " 'receive' category of transactions.\n"
1201 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
1202 " category of transactions.\n"
1203 " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n"
1204 " category of transactions.\n"
1205 " \"txid\": \"transactionid\", (string) The transaction id (see https://blockchain.info/tx/[transactionid]. Available \n"
1206 " for 'send' and 'receive' category of transactions.\n"
1207 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
1208 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
1209 " for 'send' and 'receive' category of transactions.\n"
1210 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1211 " \"otheraccount\": \"accountname\", (string) For the 'move' category of transactions, the account the funds came \n"
1212 " from (for receiving funds, positive amounts), or went to (for sending funds,\n"
1213 " negative amounts).\n"
1218 "\nList the most recent 10 transactions in the systems\n"
1219 + HelpExampleCli("listtransactions", "") +
1220 "\nList the most recent 10 transactions for the tabby account\n"
1221 + HelpExampleCli("listtransactions", "\"tabby\"") +
1222 "\nList transactions 100 to 120 from the tabby account\n"
1223 + HelpExampleCli("listtransactions", "\"tabby\" 20 100") +
1224 "\nAs a json rpc call\n"
1225 + HelpExampleRpc("listtransactions", "\"tabby\", 20, 100")
1228 string strAccount = "*";
1229 if (params.size() > 0)
1230 strAccount = params[0].get_str();
1232 if (params.size() > 1)
1233 nCount = params[1].get_int();
1235 if (params.size() > 2)
1236 nFrom = params[2].get_int();
1239 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
1241 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
1245 std::list<CAccountingEntry> acentries;
1246 CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount);
1248 // iterate backwards until we have nCount items to return:
1249 for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
1251 CWalletTx *const pwtx = (*it).second.first;
1253 ListTransactions(*pwtx, strAccount, 0, true, ret);
1254 CAccountingEntry *const pacentry = (*it).second.second;
1256 AcentryToJSON(*pacentry, strAccount, ret);
1258 if ((int)ret.size() >= (nCount+nFrom)) break;
1260 // ret is newest to oldest
1262 if (nFrom > (int)ret.size())
1264 if ((nFrom + nCount) > (int)ret.size())
1265 nCount = ret.size() - nFrom;
1266 Array::iterator first = ret.begin();
1267 std::advance(first, nFrom);
1268 Array::iterator last = ret.begin();
1269 std::advance(last, nFrom+nCount);
1271 if (last != ret.end()) ret.erase(last, ret.end());
1272 if (first != ret.begin()) ret.erase(ret.begin(), first);
1274 std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1279 Value listaccounts(const Array& params, bool fHelp)
1281 if (fHelp || params.size() > 1)
1282 throw runtime_error(
1283 "listaccounts ( minconf )\n"
1284 "\nReturns Object that has account names as keys, account balances as values.\n"
1286 "1. minconf (numeric, optional, default=1) Only onclude transactions with at least this many confirmations\n"
1288 "{ (json object where keys are account names, and values are numeric balances\n"
1289 " \"account\": x.xxx, (numeric) The property name is the account name, and the value is the total balance for the account.\n"
1293 "\nList account balances where there at least 1 confirmation\n"
1294 + HelpExampleCli("listaccounts", "") +
1295 "\nList account balances including zero confirmation transactions\n"
1296 + HelpExampleCli("listaccounts", "0") +
1297 "\nList account balances for 6 or more confirmations\n"
1298 + HelpExampleCli("listaccounts", "6") +
1299 "\nAs json rpc call\n"
1300 + HelpExampleRpc("listaccounts", "6")
1304 if (params.size() > 0)
1305 nMinDepth = params[0].get_int();
1307 map<string, int64_t> mapAccountBalances;
1308 BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) {
1309 if (IsMine(*pwalletMain, entry.first)) // This address belongs to me
1310 mapAccountBalances[entry.second.name] = 0;
1313 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1315 const CWalletTx& wtx = (*it).second;
1317 string strSentAccount;
1318 list<pair<CTxDestination, int64_t> > listReceived;
1319 list<pair<CTxDestination, int64_t> > listSent;
1320 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount);
1321 mapAccountBalances[strSentAccount] -= nFee;
1322 BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& s, listSent)
1323 mapAccountBalances[strSentAccount] -= s.second;
1324 if (wtx.GetDepthInMainChain() >= nMinDepth)
1326 BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& r, listReceived)
1327 if (pwalletMain->mapAddressBook.count(r.first))
1328 mapAccountBalances[pwalletMain->mapAddressBook[r.first].name] += r.second;
1330 mapAccountBalances[""] += r.second;
1334 list<CAccountingEntry> acentries;
1335 CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1336 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1337 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1340 BOOST_FOREACH(const PAIRTYPE(string, int64_t)& accountBalance, mapAccountBalances) {
1341 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1346 Value listsinceblock(const Array& params, bool fHelp)
1349 throw runtime_error(
1350 "listsinceblock ( \"blockhash\" target-confirmations )\n"
1351 "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n"
1353 "1. \"blockhash\" (string, optional) The block hash to list transactions since\n"
1354 "2. target-confirmations: (numeric, optional) The confirmations required, must be 1 or more\n"
1357 " \"transactions\": [\n"
1358 " \"account\":\"accountname\", (string) The account name associated with the transaction. Will be \"\" for the default account.\n"
1359 " \"address\":\"bitcoinaddress\", (string) The bitcoin address of the transaction. Not present for move transactions (category = move).\n"
1360 " \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
1361 " \"amount\": x.xxx, (numeric) The amount in btc. This is negative for the 'send' category, and for the 'move' category for moves \n"
1362 " outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
1363 " \"fee\": x.xxx, (numeric) The amount of the fee in btc. This is negative and only available for the 'send' category of transactions.\n"
1364 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
1365 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1366 " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1367 " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
1368 " \"txid\": \"transactionid\", (string) The transaction id (see https://blockchain.info/tx/[transactionid]. Available for 'send' and 'receive' category of transactions.\n"
1369 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
1370 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
1371 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1372 " \"to\": \"...\", (string) If a comment to is associated with the transaction.\n"
1374 " \"lastblock\": \"lastblockhash\" (string) The hash of the last block\n"
1377 + HelpExampleCli("listsinceblock", "")
1378 + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
1379 + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
1382 CBlockIndex *pindex = NULL;
1383 int target_confirms = 1;
1385 if (params.size() > 0)
1387 uint256 blockId = 0;
1389 blockId.SetHex(params[0].get_str());
1390 std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(blockId);
1391 if (it != mapBlockIndex.end())
1392 pindex = it->second;
1395 if (params.size() > 1)
1397 target_confirms = params[1].get_int();
1399 if (target_confirms < 1)
1400 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
1403 int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
1407 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1409 CWalletTx tx = (*it).second;
1411 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1412 ListTransactions(tx, "*", 0, true, transactions);
1415 CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
1416 uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : 0;
1419 ret.push_back(Pair("transactions", transactions));
1420 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1425 Value gettransaction(const Array& params, bool fHelp)
1427 if (fHelp || params.size() != 1)
1428 throw runtime_error(
1429 "gettransaction \"txid\"\n"
1430 "\nGet detailed information about in-wallet transaction <txid>\n"
1432 "1. \"txid\" (string, required) The transaction id\n"
1435 " \"amount\" : x.xxx, (numeric) The transaction amount in btc\n"
1436 " \"confirmations\" : n, (numeric) The number of confirmations\n"
1437 " \"blockhash\" : \"hash\", (string) The block hash\n"
1438 " \"blockindex\" : xx, (numeric) The block index\n"
1439 " \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
1440 " \"txid\" : \"transactionid\", (string) The transaction id, see also https://blockchain.info/tx/[transactionid]\n"
1441 " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
1442 " \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
1443 " \"details\" : [\n"
1445 " \"account\" : \"accountname\", (string) The account name involved in the transaction, can be \"\" for the default account.\n"
1446 " \"address\" : \"bitcoinaddress\", (string) The bitcoin address involved in the transaction\n"
1447 " \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n"
1448 " \"amount\" : x.xxx (numeric) The amount in btc\n"
1455 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1456 + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1460 hash.SetHex(params[0].get_str());
1463 if (!pwalletMain->mapWallet.count(hash))
1464 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
1465 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1467 int64_t nCredit = wtx.GetCredit();
1468 int64_t nDebit = wtx.GetDebit();
1469 int64_t nNet = nCredit - nDebit;
1470 int64_t nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1472 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1474 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1476 WalletTxToJSON(wtx, entry);
1479 ListTransactions(wtx, "*", 0, false, details);
1480 entry.push_back(Pair("details", details));
1486 Value backupwallet(const Array& params, bool fHelp)
1488 if (fHelp || params.size() != 1)
1489 throw runtime_error(
1490 "backupwallet \"destination\"\n"
1491 "\nSafely copies wallet.dat to destination, which can be a directory or a path with filename.\n"
1493 "1. \"destination\" (string) The destination directory or file\n"
1495 + HelpExampleCli("backupwallet", "\"backup.dat\"")
1496 + HelpExampleRpc("backupwallet", "\"backup.dat\"")
1499 string strDest = params[0].get_str();
1500 if (!BackupWallet(*pwalletMain, strDest))
1501 throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
1507 Value keypoolrefill(const Array& params, bool fHelp)
1509 if (fHelp || params.size() > 1)
1510 throw runtime_error(
1511 "keypoolrefill ( newsize )\n"
1512 "\nFills the keypool."
1513 + HelpRequiringPassphrase() + "\n"
1515 "1. newsize (numeric, optional, default=100) The new keypool size\n"
1517 + HelpExampleCli("keypoolrefill", "")
1518 + HelpExampleRpc("keypoolrefill", "")
1521 // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
1522 unsigned int kpSize = 0;
1523 if (params.size() > 0) {
1524 if (params[0].get_int() < 0)
1525 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
1526 kpSize = (unsigned int)params[0].get_int();
1529 EnsureWalletIsUnlocked();
1530 pwalletMain->TopUpKeyPool(kpSize);
1532 if (pwalletMain->GetKeyPoolSize() < kpSize)
1533 throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
1539 static void LockWallet(CWallet* pWallet)
1541 LOCK(cs_nWalletUnlockTime);
1542 nWalletUnlockTime = 0;
1546 Value walletpassphrase(const Array& params, bool fHelp)
1548 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1549 throw runtime_error(
1550 "walletpassphrase \"passphrase\" timeout\n"
1551 "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
1552 "This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
1554 "1. \"passphrase\" (string, required) The wallet passphrase\n"
1555 "2. timeout (numeric, required) The time to keep the decryption key in seconds.\n"
1557 "\nunlock the wallet for 60 seconds\n"
1558 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
1559 "\nLock the wallet again (before 60 seconds)\n"
1560 + HelpExampleCli("walletlock", "") +
1561 "\nAs json rpc call\n"
1562 + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
1567 if (!pwalletMain->IsCrypted())
1568 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1570 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1571 SecureString strWalletPass;
1572 strWalletPass.reserve(100);
1573 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1574 // Alternately, find a way to make params[0] mlock()'d to begin with.
1575 strWalletPass = params[0].get_str().c_str();
1577 if (strWalletPass.length() > 0)
1579 if (!pwalletMain->Unlock(strWalletPass))
1580 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1583 throw runtime_error(
1584 "walletpassphrase <passphrase> <timeout>\n"
1585 "Stores the wallet decryption key in memory for <timeout> seconds.");
1587 pwalletMain->TopUpKeyPool();
1589 int64_t nSleepTime = params[1].get_int64();
1590 LOCK(cs_nWalletUnlockTime);
1591 nWalletUnlockTime = GetTime() + nSleepTime;
1592 RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
1598 Value walletpassphrasechange(const Array& params, bool fHelp)
1600 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1601 throw runtime_error(
1602 "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
1603 "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
1605 "1. \"oldpassphrase\" (string) The current passphrase\n"
1606 "2. \"newpassphrase\" (string) The new passphrase\n"
1608 + HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
1609 + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
1614 if (!pwalletMain->IsCrypted())
1615 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1617 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1618 // Alternately, find a way to make params[0] mlock()'d to begin with.
1619 SecureString strOldWalletPass;
1620 strOldWalletPass.reserve(100);
1621 strOldWalletPass = params[0].get_str().c_str();
1623 SecureString strNewWalletPass;
1624 strNewWalletPass.reserve(100);
1625 strNewWalletPass = params[1].get_str().c_str();
1627 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1628 throw runtime_error(
1629 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1630 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1632 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1633 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1639 Value walletlock(const Array& params, bool fHelp)
1641 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1642 throw runtime_error(
1644 "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
1645 "After calling this method, you will need to call walletpassphrase again\n"
1646 "before being able to call any methods which require the wallet to be unlocked.\n"
1648 "\nSet the passphrase for 2 minutes to perform a transaction\n"
1649 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
1650 "\nPerform a send (requires passphrase set)\n"
1651 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 1.0") +
1652 "\nClear the passphrase since we are done before 2 minutes is up\n"
1653 + HelpExampleCli("walletlock", "") +
1654 "\nAs json rpc call\n"
1655 + HelpExampleRpc("walletlock", "")
1660 if (!pwalletMain->IsCrypted())
1661 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
1664 LOCK(cs_nWalletUnlockTime);
1665 pwalletMain->Lock();
1666 nWalletUnlockTime = 0;
1673 Value encryptwallet(const Array& params, bool fHelp)
1675 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1676 throw runtime_error(
1677 "encryptwallet \"passphrase\"\n"
1678 "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
1679 "After this, any calls that interact with private keys such as sending or signing \n"
1680 "will require the passphrase to be set prior the making these calls.\n"
1681 "Use the walletpassphrase call for this, and then walletlock call.\n"
1682 "If the wallet is already encrypted, use the walletpassphrasechange call.\n"
1683 "Note that this will shutdown the server.\n"
1685 "1. \"passphrase\" (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n"
1687 "\nEncrypt you wallet\n"
1688 + HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
1689 "\nNow set the passphrase to use the wallet, such as for signing or sending bitcoin\n"
1690 + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
1691 "\nNow we can so something like sign\n"
1692 + HelpExampleCli("signmessage", "\"bitcoinaddress\" \"test message\"") +
1693 "\nNow lock the wallet again by removing the passphrase\n"
1694 + HelpExampleCli("walletlock", "") +
1695 "\nAs a json rpc call\n"
1696 + HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
1701 if (pwalletMain->IsCrypted())
1702 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
1704 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1705 // Alternately, find a way to make params[0] mlock()'d to begin with.
1706 SecureString strWalletPass;
1707 strWalletPass.reserve(100);
1708 strWalletPass = params[0].get_str().c_str();
1710 if (strWalletPass.length() < 1)
1711 throw runtime_error(
1712 "encryptwallet <passphrase>\n"
1713 "Encrypts the wallet with <passphrase>.");
1715 if (!pwalletMain->EncryptWallet(strWalletPass))
1716 throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
1718 // BDB seems to have a bad habit of writing old data into
1719 // slack space in .dat files; that is bad if the old data is
1720 // unencrypted private keys. So:
1722 return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
1725 Value lockunspent(const Array& params, bool fHelp)
1727 if (fHelp || params.size() < 1 || params.size() > 2)
1728 throw runtime_error(
1729 "lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n"
1730 "\nUpdates list of temporarily unspendable outputs.\n"
1731 "Temporarily lock (lock=true) or unlock (lock=false) specified transaction outputs.\n"
1732 "A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
1733 "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
1734 "is always cleared (by virtue of process exit) when a node stops or fails.\n"
1735 "Also see the listunspent call\n"
1737 "1. unlock (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
1738 "2. \"transactions\" (string, required) A json array of objects. Each object the txid (string) vout (numeric)\n"
1739 " [ (json array of json objects)\n"
1741 " \"txid\":\"id\", (string) The transaction id\n"
1742 " \"vout\": n (numeric) The output number\n"
1748 "true|false (boolean) Whether the command was successful or not\n"
1751 "\nList the unspent transactions\n"
1752 + HelpExampleCli("listunspent", "") +
1753 "\nLock an unspent transaction\n"
1754 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1755 "\nList the locked transactions\n"
1756 + HelpExampleCli("listlockunspent", "") +
1757 "\nUnlock the transaction again\n"
1758 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1759 "\nAs a json rpc call\n"
1760 + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
1763 if (params.size() == 1)
1764 RPCTypeCheck(params, list_of(bool_type));
1766 RPCTypeCheck(params, list_of(bool_type)(array_type));
1768 bool fUnlock = params[0].get_bool();
1770 if (params.size() == 1) {
1772 pwalletMain->UnlockAllCoins();
1776 Array outputs = params[1].get_array();
1777 BOOST_FOREACH(Value& output, outputs)
1779 if (output.type() != obj_type)
1780 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
1781 const Object& o = output.get_obj();
1783 RPCTypeCheck(o, map_list_of("txid", str_type)("vout", int_type));
1785 string txid = find_value(o, "txid").get_str();
1787 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
1789 int nOutput = find_value(o, "vout").get_int();
1791 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
1793 COutPoint outpt(uint256(txid), nOutput);
1796 pwalletMain->UnlockCoin(outpt);
1798 pwalletMain->LockCoin(outpt);
1804 Value listlockunspent(const Array& params, bool fHelp)
1806 if (fHelp || params.size() > 0)
1807 throw runtime_error(
1809 "\nReturns list of temporarily unspendable outputs.\n"
1810 "See the lockunspent call to lock and unlock transactions for spending.\n"
1814 " \"txid\" : \"transactionid\", (string) The transaction id locked\n"
1815 " \"vout\" : n (numeric) The vout value\n"
1820 "\nList the unspent transactions\n"
1821 + HelpExampleCli("listunspent", "") +
1822 "\nLock an unspent transaction\n"
1823 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1824 "\nList the locked transactions\n"
1825 + HelpExampleCli("listlockunspent", "") +
1826 "\nUnlock the transaction again\n"
1827 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1828 "\nAs a json rpc call\n"
1829 + HelpExampleRpc("listlockunspent", "")
1832 vector<COutPoint> vOutpts;
1833 pwalletMain->ListLockedCoins(vOutpts);
1837 BOOST_FOREACH(COutPoint &outpt, vOutpts) {
1840 o.push_back(Pair("txid", outpt.hash.GetHex()));
1841 o.push_back(Pair("vout", (int)outpt.n));
1848 Value settxfee(const Array& params, bool fHelp)
1850 if (fHelp || params.size() < 1 || params.size() > 1)
1851 throw runtime_error(
1853 "\nSet the transaction fee. 'amount' is a real and is rounded to the nearest 0.00000001\n"
1855 "1. amount (numeric, required) The transaction fee in btc rounded to the nearest 0.00000001\n"
1857 "true|false (boolean) Returns true if successful\n"
1859 + HelpExampleCli("settxfee", "0.00001")
1860 + HelpExampleRpc("settxfee", "0.00001")
1864 int64_t nAmount = 0;
1865 if (params[0].get_real() != 0.0)
1866 nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
1868 nTransactionFee = nAmount;