Add new rpc call: abandontransaction
[bitcoinplatinum.git] / src / wallet / rpcwallet.cpp
blob9e7d9cc98a95bc0d440dabc2be5dc242f02545e0
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2015 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 #include "amount.h"
7 #include "base58.h"
8 #include "chain.h"
9 #include "core_io.h"
10 #include "init.h"
11 #include "main.h"
12 #include "net.h"
13 #include "netbase.h"
14 #include "rpcserver.h"
15 #include "timedata.h"
16 #include "util.h"
17 #include "utilmoneystr.h"
18 #include "wallet.h"
19 #include "walletdb.h"
21 #include <stdint.h>
23 #include <boost/assign/list_of.hpp>
25 #include <univalue.h>
27 using namespace std;
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."
36 : "";
39 bool EnsureWalletIsAvailable(bool avoidException)
41 if (!pwalletMain)
43 if (!avoidException)
44 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
45 else
46 return false;
48 return true;
51 void EnsureWalletIsUnlocked()
53 if (pwalletMain->IsLocked())
54 throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
57 void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
59 int confirms = wtx.GetDepthInMainChain();
60 entry.push_back(Pair("confirmations", confirms));
61 if (wtx.IsCoinBase())
62 entry.push_back(Pair("generated", true));
63 if (confirms > 0)
65 entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
66 entry.push_back(Pair("blockindex", wtx.nIndex));
67 entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
68 } else {
69 entry.push_back(Pair("trusted", wtx.IsTrusted()));
71 uint256 hash = wtx.GetHash();
72 entry.push_back(Pair("txid", hash.GetHex()));
73 UniValue conflicts(UniValue::VARR);
74 BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
75 conflicts.push_back(conflict.GetHex());
76 entry.push_back(Pair("walletconflicts", conflicts));
77 entry.push_back(Pair("time", wtx.GetTxTime()));
78 entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived));
79 BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
80 entry.push_back(Pair(item.first, item.second));
83 string AccountFromValue(const UniValue& value)
85 string strAccount = value.get_str();
86 if (strAccount == "*")
87 throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Invalid account name");
88 return strAccount;
91 UniValue getnewaddress(const UniValue& params, bool fHelp)
93 if (!EnsureWalletIsAvailable(fHelp))
94 return NullUniValue;
96 if (fHelp || params.size() > 1)
97 throw runtime_error(
98 "getnewaddress ( \"account\" )\n"
99 "\nReturns a new Bitcoin address for receiving payments.\n"
100 "If 'account' is specified (DEPRECATED), it is added to the address book \n"
101 "so payments received with the address will be credited to 'account'.\n"
102 "\nArguments:\n"
103 "1. \"account\" (string, optional) DEPRECATED. The account name for the address to be linked to. If not provided, the default account \"\" is used. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created if there is no account by the given name.\n"
104 "\nResult:\n"
105 "\"bitcoinaddress\" (string) The new bitcoin address\n"
106 "\nExamples:\n"
107 + HelpExampleCli("getnewaddress", "")
108 + HelpExampleRpc("getnewaddress", "")
111 LOCK2(cs_main, pwalletMain->cs_wallet);
113 // Parse the account first so we don't generate a key if there's an error
114 string strAccount;
115 if (params.size() > 0)
116 strAccount = AccountFromValue(params[0]);
118 if (!pwalletMain->IsLocked())
119 pwalletMain->TopUpKeyPool();
121 // Generate a new key that is added to wallet
122 CPubKey newKey;
123 if (!pwalletMain->GetKeyFromPool(newKey))
124 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
125 CKeyID keyID = newKey.GetID();
127 pwalletMain->SetAddressBook(keyID, strAccount, "receive");
129 return CBitcoinAddress(keyID).ToString();
133 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
135 CWalletDB walletdb(pwalletMain->strWalletFile);
137 CAccount account;
138 walletdb.ReadAccount(strAccount, account);
140 bool bKeyUsed = false;
142 // Check if the current key has been used
143 if (account.vchPubKey.IsValid())
145 CScript scriptPubKey = GetScriptForDestination(account.vchPubKey.GetID());
146 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
147 it != pwalletMain->mapWallet.end() && account.vchPubKey.IsValid();
148 ++it)
150 const CWalletTx& wtx = (*it).second;
151 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
152 if (txout.scriptPubKey == scriptPubKey)
153 bKeyUsed = true;
157 // Generate a new key
158 if (!account.vchPubKey.IsValid() || bForceNew || bKeyUsed)
160 if (!pwalletMain->GetKeyFromPool(account.vchPubKey))
161 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
163 pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, "receive");
164 walletdb.WriteAccount(strAccount, account);
167 return CBitcoinAddress(account.vchPubKey.GetID());
170 UniValue getaccountaddress(const UniValue& params, bool fHelp)
172 if (!EnsureWalletIsAvailable(fHelp))
173 return NullUniValue;
175 if (fHelp || params.size() != 1)
176 throw runtime_error(
177 "getaccountaddress \"account\"\n"
178 "\nDEPRECATED. Returns the current Bitcoin address for receiving payments to this account.\n"
179 "\nArguments:\n"
180 "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"
181 "\nResult:\n"
182 "\"bitcoinaddress\" (string) The account bitcoin address\n"
183 "\nExamples:\n"
184 + HelpExampleCli("getaccountaddress", "")
185 + HelpExampleCli("getaccountaddress", "\"\"")
186 + HelpExampleCli("getaccountaddress", "\"myaccount\"")
187 + HelpExampleRpc("getaccountaddress", "\"myaccount\"")
190 LOCK2(cs_main, pwalletMain->cs_wallet);
192 // Parse the account first so we don't generate a key if there's an error
193 string strAccount = AccountFromValue(params[0]);
195 UniValue ret(UniValue::VSTR);
197 ret = GetAccountAddress(strAccount).ToString();
198 return ret;
202 UniValue getrawchangeaddress(const UniValue& params, bool fHelp)
204 if (!EnsureWalletIsAvailable(fHelp))
205 return NullUniValue;
207 if (fHelp || params.size() > 1)
208 throw runtime_error(
209 "getrawchangeaddress\n"
210 "\nReturns a new Bitcoin address, for receiving change.\n"
211 "This is for use with raw transactions, NOT normal use.\n"
212 "\nResult:\n"
213 "\"address\" (string) The address\n"
214 "\nExamples:\n"
215 + HelpExampleCli("getrawchangeaddress", "")
216 + HelpExampleRpc("getrawchangeaddress", "")
219 LOCK2(cs_main, pwalletMain->cs_wallet);
221 if (!pwalletMain->IsLocked())
222 pwalletMain->TopUpKeyPool();
224 CReserveKey reservekey(pwalletMain);
225 CPubKey vchPubKey;
226 if (!reservekey.GetReservedKey(vchPubKey))
227 throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
229 reservekey.KeepKey();
231 CKeyID keyID = vchPubKey.GetID();
233 return CBitcoinAddress(keyID).ToString();
237 UniValue setaccount(const UniValue& params, bool fHelp)
239 if (!EnsureWalletIsAvailable(fHelp))
240 return NullUniValue;
242 if (fHelp || params.size() < 1 || params.size() > 2)
243 throw runtime_error(
244 "setaccount \"bitcoinaddress\" \"account\"\n"
245 "\nDEPRECATED. Sets the account associated with the given address.\n"
246 "\nArguments:\n"
247 "1. \"bitcoinaddress\" (string, required) The bitcoin address to be associated with an account.\n"
248 "2. \"account\" (string, required) The account to assign the address to.\n"
249 "\nExamples:\n"
250 + HelpExampleCli("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"tabby\"")
251 + HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"tabby\"")
254 LOCK2(cs_main, pwalletMain->cs_wallet);
256 CBitcoinAddress address(params[0].get_str());
257 if (!address.IsValid())
258 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
260 string strAccount;
261 if (params.size() > 1)
262 strAccount = AccountFromValue(params[1]);
264 // Only add the account if the address is yours.
265 if (IsMine(*pwalletMain, address.Get()))
267 // Detect when changing the account of an address that is the 'unused current key' of another account:
268 if (pwalletMain->mapAddressBook.count(address.Get()))
270 string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name;
271 if (address == GetAccountAddress(strOldAccount))
272 GetAccountAddress(strOldAccount, true);
274 pwalletMain->SetAddressBook(address.Get(), strAccount, "receive");
276 else
277 throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
279 return NullUniValue;
283 UniValue getaccount(const UniValue& params, bool fHelp)
285 if (!EnsureWalletIsAvailable(fHelp))
286 return NullUniValue;
288 if (fHelp || params.size() != 1)
289 throw runtime_error(
290 "getaccount \"bitcoinaddress\"\n"
291 "\nDEPRECATED. Returns the account associated with the given address.\n"
292 "\nArguments:\n"
293 "1. \"bitcoinaddress\" (string, required) The bitcoin address for account lookup.\n"
294 "\nResult:\n"
295 "\"accountname\" (string) the account address\n"
296 "\nExamples:\n"
297 + HelpExampleCli("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
298 + HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
301 LOCK2(cs_main, pwalletMain->cs_wallet);
303 CBitcoinAddress address(params[0].get_str());
304 if (!address.IsValid())
305 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
307 string strAccount;
308 map<CTxDestination, CAddressBookData>::iterator mi = pwalletMain->mapAddressBook.find(address.Get());
309 if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty())
310 strAccount = (*mi).second.name;
311 return strAccount;
315 UniValue getaddressesbyaccount(const UniValue& params, bool fHelp)
317 if (!EnsureWalletIsAvailable(fHelp))
318 return NullUniValue;
320 if (fHelp || params.size() != 1)
321 throw runtime_error(
322 "getaddressesbyaccount \"account\"\n"
323 "\nDEPRECATED. Returns the list of addresses for the given account.\n"
324 "\nArguments:\n"
325 "1. \"account\" (string, required) The account name.\n"
326 "\nResult:\n"
327 "[ (json array of string)\n"
328 " \"bitcoinaddress\" (string) a bitcoin address associated with the given account\n"
329 " ,...\n"
330 "]\n"
331 "\nExamples:\n"
332 + HelpExampleCli("getaddressesbyaccount", "\"tabby\"")
333 + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
336 LOCK2(cs_main, pwalletMain->cs_wallet);
338 string strAccount = AccountFromValue(params[0]);
340 // Find all addresses that have the given account
341 UniValue ret(UniValue::VARR);
342 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
344 const CBitcoinAddress& address = item.first;
345 const string& strName = item.second.name;
346 if (strName == strAccount)
347 ret.push_back(address.ToString());
349 return ret;
352 static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew)
354 CAmount curBalance = pwalletMain->GetBalance();
356 // Check amount
357 if (nValue <= 0)
358 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid amount");
360 if (nValue > curBalance)
361 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
363 // Parse Bitcoin address
364 CScript scriptPubKey = GetScriptForDestination(address);
366 // Create and send the transaction
367 CReserveKey reservekey(pwalletMain);
368 CAmount nFeeRequired;
369 std::string strError;
370 vector<CRecipient> vecSend;
371 int nChangePosRet = -1;
372 CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
373 vecSend.push_back(recipient);
374 if (!pwalletMain->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError)) {
375 if (!fSubtractFeeFromAmount && nValue + nFeeRequired > pwalletMain->GetBalance())
376 strError = strprintf("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!", FormatMoney(nFeeRequired));
377 throw JSONRPCError(RPC_WALLET_ERROR, strError);
379 if (!pwalletMain->CommitTransaction(wtxNew, reservekey))
380 throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
383 UniValue sendtoaddress(const UniValue& params, bool fHelp)
385 if (!EnsureWalletIsAvailable(fHelp))
386 return NullUniValue;
388 if (fHelp || params.size() < 2 || params.size() > 5)
389 throw runtime_error(
390 "sendtoaddress \"bitcoinaddress\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n"
391 "\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n"
392 + HelpRequiringPassphrase() +
393 "\nArguments:\n"
394 "1. \"bitcoinaddress\" (string, required) The bitcoin address to send to.\n"
395 "2. \"amount\" (numeric, required) The amount in " + CURRENCY_UNIT + " to send. eg 0.1\n"
396 "3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
397 " This is not part of the transaction, just kept in your wallet.\n"
398 "4. \"comment-to\" (string, optional) A comment to store the name of the person or organization \n"
399 " to which you're sending the transaction. This is not part of the \n"
400 " transaction, just kept in your wallet.\n"
401 "5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
402 " The recipient will receive less bitcoins than you enter in the amount field.\n"
403 "\nResult:\n"
404 "\"transactionid\" (string) The transaction id.\n"
405 "\nExamples:\n"
406 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
407 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
408 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true")
409 + HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
412 LOCK2(cs_main, pwalletMain->cs_wallet);
414 CBitcoinAddress address(params[0].get_str());
415 if (!address.IsValid())
416 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
418 // Amount
419 CAmount nAmount = AmountFromValue(params[1]);
420 if (nAmount <= 0)
421 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
423 // Wallet comments
424 CWalletTx wtx;
425 if (params.size() > 2 && !params[2].isNull() && !params[2].get_str().empty())
426 wtx.mapValue["comment"] = params[2].get_str();
427 if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty())
428 wtx.mapValue["to"] = params[3].get_str();
430 bool fSubtractFeeFromAmount = false;
431 if (params.size() > 4)
432 fSubtractFeeFromAmount = params[4].get_bool();
434 EnsureWalletIsUnlocked();
436 SendMoney(address.Get(), nAmount, fSubtractFeeFromAmount, wtx);
438 return wtx.GetHash().GetHex();
441 UniValue listaddressgroupings(const UniValue& params, bool fHelp)
443 if (!EnsureWalletIsAvailable(fHelp))
444 return NullUniValue;
446 if (fHelp)
447 throw runtime_error(
448 "listaddressgroupings\n"
449 "\nLists groups of addresses which have had their common ownership\n"
450 "made public by common use as inputs or as the resulting change\n"
451 "in past transactions\n"
452 "\nResult:\n"
453 "[\n"
454 " [\n"
455 " [\n"
456 " \"bitcoinaddress\", (string) The bitcoin address\n"
457 " amount, (numeric) The amount in " + CURRENCY_UNIT + "\n"
458 " \"account\" (string, optional) The account (DEPRECATED)\n"
459 " ]\n"
460 " ,...\n"
461 " ]\n"
462 " ,...\n"
463 "]\n"
464 "\nExamples:\n"
465 + HelpExampleCli("listaddressgroupings", "")
466 + HelpExampleRpc("listaddressgroupings", "")
469 LOCK2(cs_main, pwalletMain->cs_wallet);
471 UniValue jsonGroupings(UniValue::VARR);
472 map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
473 BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
475 UniValue jsonGrouping(UniValue::VARR);
476 BOOST_FOREACH(CTxDestination address, grouping)
478 UniValue addressInfo(UniValue::VARR);
479 addressInfo.push_back(CBitcoinAddress(address).ToString());
480 addressInfo.push_back(ValueFromAmount(balances[address]));
482 if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end())
483 addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second.name);
485 jsonGrouping.push_back(addressInfo);
487 jsonGroupings.push_back(jsonGrouping);
489 return jsonGroupings;
492 UniValue signmessage(const UniValue& params, bool fHelp)
494 if (!EnsureWalletIsAvailable(fHelp))
495 return NullUniValue;
497 if (fHelp || params.size() != 2)
498 throw runtime_error(
499 "signmessage \"bitcoinaddress\" \"message\"\n"
500 "\nSign a message with the private key of an address"
501 + HelpRequiringPassphrase() + "\n"
502 "\nArguments:\n"
503 "1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the private key.\n"
504 "2. \"message\" (string, required) The message to create a signature of.\n"
505 "\nResult:\n"
506 "\"signature\" (string) The signature of the message encoded in base 64\n"
507 "\nExamples:\n"
508 "\nUnlock the wallet for 30 seconds\n"
509 + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
510 "\nCreate the signature\n"
511 + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
512 "\nVerify the signature\n"
513 + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
514 "\nAs json rpc\n"
515 + HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"my message\"")
518 LOCK2(cs_main, pwalletMain->cs_wallet);
520 EnsureWalletIsUnlocked();
522 string strAddress = params[0].get_str();
523 string strMessage = params[1].get_str();
525 CBitcoinAddress addr(strAddress);
526 if (!addr.IsValid())
527 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
529 CKeyID keyID;
530 if (!addr.GetKeyID(keyID))
531 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
533 CKey key;
534 if (!pwalletMain->GetKey(keyID, key))
535 throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
537 CHashWriter ss(SER_GETHASH, 0);
538 ss << strMessageMagic;
539 ss << strMessage;
541 vector<unsigned char> vchSig;
542 if (!key.SignCompact(ss.GetHash(), vchSig))
543 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
545 return EncodeBase64(&vchSig[0], vchSig.size());
548 UniValue getreceivedbyaddress(const UniValue& params, bool fHelp)
550 if (!EnsureWalletIsAvailable(fHelp))
551 return NullUniValue;
553 if (fHelp || params.size() < 1 || params.size() > 2)
554 throw runtime_error(
555 "getreceivedbyaddress \"bitcoinaddress\" ( minconf )\n"
556 "\nReturns the total amount received by the given bitcoinaddress in transactions with at least minconf confirmations.\n"
557 "\nArguments:\n"
558 "1. \"bitcoinaddress\" (string, required) The bitcoin address for transactions.\n"
559 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
560 "\nResult:\n"
561 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received at this address.\n"
562 "\nExamples:\n"
563 "\nThe amount from transactions with at least 1 confirmation\n"
564 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"") +
565 "\nThe amount including unconfirmed transactions, zero confirmations\n"
566 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 0") +
567 "\nThe amount with at least 6 confirmation, very safe\n"
568 + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 6") +
569 "\nAs a json rpc call\n"
570 + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", 6")
573 LOCK2(cs_main, pwalletMain->cs_wallet);
575 // Bitcoin address
576 CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
577 if (!address.IsValid())
578 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
579 CScript scriptPubKey = GetScriptForDestination(address.Get());
580 if (!IsMine(*pwalletMain,scriptPubKey))
581 return (double)0.0;
583 // Minimum confirmations
584 int nMinDepth = 1;
585 if (params.size() > 1)
586 nMinDepth = params[1].get_int();
588 // Tally
589 CAmount nAmount = 0;
590 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
592 const CWalletTx& wtx = (*it).second;
593 if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
594 continue;
596 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
597 if (txout.scriptPubKey == scriptPubKey)
598 if (wtx.GetDepthInMainChain() >= nMinDepth)
599 nAmount += txout.nValue;
602 return ValueFromAmount(nAmount);
606 UniValue getreceivedbyaccount(const UniValue& params, bool fHelp)
608 if (!EnsureWalletIsAvailable(fHelp))
609 return NullUniValue;
611 if (fHelp || params.size() < 1 || params.size() > 2)
612 throw runtime_error(
613 "getreceivedbyaccount \"account\" ( minconf )\n"
614 "\nDEPRECATED. Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
615 "\nArguments:\n"
616 "1. \"account\" (string, required) The selected account, may be the default account using \"\".\n"
617 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
618 "\nResult:\n"
619 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
620 "\nExamples:\n"
621 "\nAmount received by the default account with at least 1 confirmation\n"
622 + HelpExampleCli("getreceivedbyaccount", "\"\"") +
623 "\nAmount received at the tabby account including unconfirmed amounts with zero confirmations\n"
624 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 0") +
625 "\nThe amount with at least 6 confirmation, very safe\n"
626 + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 6") +
627 "\nAs a json rpc call\n"
628 + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
631 LOCK2(cs_main, pwalletMain->cs_wallet);
633 // Minimum confirmations
634 int nMinDepth = 1;
635 if (params.size() > 1)
636 nMinDepth = params[1].get_int();
638 // Get the set of pub keys assigned to account
639 string strAccount = AccountFromValue(params[0]);
640 set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount);
642 // Tally
643 CAmount nAmount = 0;
644 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
646 const CWalletTx& wtx = (*it).second;
647 if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
648 continue;
650 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
652 CTxDestination address;
653 if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
654 if (wtx.GetDepthInMainChain() >= nMinDepth)
655 nAmount += txout.nValue;
659 return (double)nAmount / (double)COIN;
663 CAmount GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter)
665 CAmount nBalance = 0;
667 // Tally wallet transactions
668 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
670 const CWalletTx& wtx = (*it).second;
671 if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
672 continue;
674 CAmount nReceived, nSent, nFee;
675 wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter);
677 if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
678 nBalance += nReceived;
679 nBalance -= nSent + nFee;
682 // Tally internal accounting entries
683 nBalance += walletdb.GetAccountCreditDebit(strAccount);
685 return nBalance;
688 CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter)
690 CWalletDB walletdb(pwalletMain->strWalletFile);
691 return GetAccountBalance(walletdb, strAccount, nMinDepth, filter);
695 UniValue getbalance(const UniValue& params, bool fHelp)
697 if (!EnsureWalletIsAvailable(fHelp))
698 return NullUniValue;
700 if (fHelp || params.size() > 3)
701 throw runtime_error(
702 "getbalance ( \"account\" minconf includeWatchonly )\n"
703 "\nIf account is not specified, returns the server's total available balance.\n"
704 "If account is specified (DEPRECATED), returns the balance in the account.\n"
705 "Note that the account \"\" is not the same as leaving the parameter out.\n"
706 "The server total may be different to the balance in the default \"\" account.\n"
707 "\nArguments:\n"
708 "1. \"account\" (string, optional) DEPRECATED. The selected account, or \"*\" for entire wallet. It may be the default account using \"\".\n"
709 "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
710 "3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n"
711 "\nResult:\n"
712 "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
713 "\nExamples:\n"
714 "\nThe total amount in the wallet\n"
715 + HelpExampleCli("getbalance", "") +
716 "\nThe total amount in the wallet at least 5 blocks confirmed\n"
717 + HelpExampleCli("getbalance", "\"*\" 6") +
718 "\nAs a json rpc call\n"
719 + HelpExampleRpc("getbalance", "\"*\", 6")
722 LOCK2(cs_main, pwalletMain->cs_wallet);
724 if (params.size() == 0)
725 return ValueFromAmount(pwalletMain->GetBalance());
727 int nMinDepth = 1;
728 if (params.size() > 1)
729 nMinDepth = params[1].get_int();
730 isminefilter filter = ISMINE_SPENDABLE;
731 if(params.size() > 2)
732 if(params[2].get_bool())
733 filter = filter | ISMINE_WATCH_ONLY;
735 if (params[0].get_str() == "*") {
736 // Calculate total balance a different way from GetBalance()
737 // (GetBalance() sums up all unspent TxOuts)
738 // getbalance and "getbalance * 1 true" should return the same number
739 CAmount nBalance = 0;
740 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
742 const CWalletTx& wtx = (*it).second;
743 if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
744 continue;
746 CAmount allFee;
747 string strSentAccount;
748 list<COutputEntry> listReceived;
749 list<COutputEntry> listSent;
750 wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
751 if (wtx.GetDepthInMainChain() >= nMinDepth)
753 BOOST_FOREACH(const COutputEntry& r, listReceived)
754 nBalance += r.amount;
756 BOOST_FOREACH(const COutputEntry& s, listSent)
757 nBalance -= s.amount;
758 nBalance -= allFee;
760 return ValueFromAmount(nBalance);
763 string strAccount = AccountFromValue(params[0]);
765 CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, filter);
767 return ValueFromAmount(nBalance);
770 UniValue getunconfirmedbalance(const UniValue &params, bool fHelp)
772 if (!EnsureWalletIsAvailable(fHelp))
773 return NullUniValue;
775 if (fHelp || params.size() > 0)
776 throw runtime_error(
777 "getunconfirmedbalance\n"
778 "Returns the server's total unconfirmed balance\n");
780 LOCK2(cs_main, pwalletMain->cs_wallet);
782 return ValueFromAmount(pwalletMain->GetUnconfirmedBalance());
786 UniValue movecmd(const UniValue& params, bool fHelp)
788 if (!EnsureWalletIsAvailable(fHelp))
789 return NullUniValue;
791 if (fHelp || params.size() < 3 || params.size() > 5)
792 throw runtime_error(
793 "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
794 "\nDEPRECATED. Move a specified amount from one account in your wallet to another.\n"
795 "\nArguments:\n"
796 "1. \"fromaccount\" (string, required) The name of the account to move funds from. May be the default account using \"\".\n"
797 "2. \"toaccount\" (string, required) The name of the account to move funds to. May be the default account using \"\".\n"
798 "3. amount (numeric) Quantity of " + CURRENCY_UNIT + " to move between accounts.\n"
799 "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
800 "5. \"comment\" (string, optional) An optional comment, stored in the wallet only.\n"
801 "\nResult:\n"
802 "true|false (boolean) true if successful.\n"
803 "\nExamples:\n"
804 "\nMove 0.01 " + CURRENCY_UNIT + " from the default account to the account named tabby\n"
805 + HelpExampleCli("move", "\"\" \"tabby\" 0.01") +
806 "\nMove 0.01 " + CURRENCY_UNIT + " timotei to akiko with a comment and funds have 6 confirmations\n"
807 + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") +
808 "\nAs a json rpc call\n"
809 + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
812 LOCK2(cs_main, pwalletMain->cs_wallet);
814 string strFrom = AccountFromValue(params[0]);
815 string strTo = AccountFromValue(params[1]);
816 CAmount nAmount = AmountFromValue(params[2]);
817 if (nAmount <= 0)
818 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
819 if (params.size() > 3)
820 // unused parameter, used to be nMinDepth, keep type-checking it though
821 (void)params[3].get_int();
822 string strComment;
823 if (params.size() > 4)
824 strComment = params[4].get_str();
826 CWalletDB walletdb(pwalletMain->strWalletFile);
827 if (!walletdb.TxnBegin())
828 throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
830 int64_t nNow = GetAdjustedTime();
832 // Debit
833 CAccountingEntry debit;
834 debit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
835 debit.strAccount = strFrom;
836 debit.nCreditDebit = -nAmount;
837 debit.nTime = nNow;
838 debit.strOtherAccount = strTo;
839 debit.strComment = strComment;
840 pwalletMain->AddAccountingEntry(debit, walletdb);
842 // Credit
843 CAccountingEntry credit;
844 credit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
845 credit.strAccount = strTo;
846 credit.nCreditDebit = nAmount;
847 credit.nTime = nNow;
848 credit.strOtherAccount = strFrom;
849 credit.strComment = strComment;
850 pwalletMain->AddAccountingEntry(credit, walletdb);
852 if (!walletdb.TxnCommit())
853 throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
855 return true;
859 UniValue sendfrom(const UniValue& params, bool fHelp)
861 if (!EnsureWalletIsAvailable(fHelp))
862 return NullUniValue;
864 if (fHelp || params.size() < 3 || params.size() > 6)
865 throw runtime_error(
866 "sendfrom \"fromaccount\" \"tobitcoinaddress\" amount ( minconf \"comment\" \"comment-to\" )\n"
867 "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a bitcoin address.\n"
868 "The amount is a real and is rounded to the nearest 0.00000001."
869 + HelpRequiringPassphrase() + "\n"
870 "\nArguments:\n"
871 "1. \"fromaccount\" (string, required) The name of the account to send funds from. May be the default account using \"\".\n"
872 "2. \"tobitcoinaddress\" (string, required) The bitcoin address to send funds to.\n"
873 "3. amount (numeric, required) The amount in " + CURRENCY_UNIT + " (transaction fee is added on top).\n"
874 "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
875 "5. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
876 " This is not part of the transaction, just kept in your wallet.\n"
877 "6. \"comment-to\" (string, optional) An optional comment to store the name of the person or organization \n"
878 " to which you're sending the transaction. This is not part of the transaction, \n"
879 " it is just kept in your wallet.\n"
880 "\nResult:\n"
881 "\"transactionid\" (string) The transaction id.\n"
882 "\nExamples:\n"
883 "\nSend 0.01 " + CURRENCY_UNIT + " from the default account to the address, must have at least 1 confirmation\n"
884 + HelpExampleCli("sendfrom", "\"\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") +
885 "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
886 + HelpExampleCli("sendfrom", "\"tabby\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01 6 \"donation\" \"seans outpost\"") +
887 "\nAs a json rpc call\n"
888 + HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
891 LOCK2(cs_main, pwalletMain->cs_wallet);
893 string strAccount = AccountFromValue(params[0]);
894 CBitcoinAddress address(params[1].get_str());
895 if (!address.IsValid())
896 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
897 CAmount nAmount = AmountFromValue(params[2]);
898 if (nAmount <= 0)
899 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
900 int nMinDepth = 1;
901 if (params.size() > 3)
902 nMinDepth = params[3].get_int();
904 CWalletTx wtx;
905 wtx.strFromAccount = strAccount;
906 if (params.size() > 4 && !params[4].isNull() && !params[4].get_str().empty())
907 wtx.mapValue["comment"] = params[4].get_str();
908 if (params.size() > 5 && !params[5].isNull() && !params[5].get_str().empty())
909 wtx.mapValue["to"] = params[5].get_str();
911 EnsureWalletIsUnlocked();
913 // Check funds
914 CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
915 if (nAmount > nBalance)
916 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
918 SendMoney(address.Get(), nAmount, false, wtx);
920 return wtx.GetHash().GetHex();
924 UniValue sendmany(const UniValue& params, bool fHelp)
926 if (!EnsureWalletIsAvailable(fHelp))
927 return NullUniValue;
929 if (fHelp || params.size() < 2 || params.size() > 5)
930 throw runtime_error(
931 "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] )\n"
932 "\nSend multiple times. Amounts are double-precision floating point numbers."
933 + HelpRequiringPassphrase() + "\n"
934 "\nArguments:\n"
935 "1. \"fromaccount\" (string, required) DEPRECATED. The account to send the funds from. Should be \"\" for the default account\n"
936 "2. \"amounts\" (string, required) A json object with addresses and amounts\n"
937 " {\n"
938 " \"address\":amount (numeric) The bitcoin address is the key, the numeric amount in " + CURRENCY_UNIT + " is the value\n"
939 " ,...\n"
940 " }\n"
941 "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
942 "4. \"comment\" (string, optional) A comment\n"
943 "5. subtractfeefromamount (string, optional) A json array with addresses.\n"
944 " The fee will be equally deducted from the amount of each selected address.\n"
945 " Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
946 " If no addresses are specified here, the sender pays the fee.\n"
947 " [\n"
948 " \"address\" (string) Subtract fee from this address\n"
949 " ,...\n"
950 " ]\n"
951 "\nResult:\n"
952 "\"transactionid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
953 " the number of addresses.\n"
954 "\nExamples:\n"
955 "\nSend two amounts to two different addresses:\n"
956 + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
957 "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
958 + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
959 "\nSend two amounts to two different addresses, subtract fee from amount:\n"
960 + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\",\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") +
961 "\nAs a json rpc call\n"
962 + HelpExampleRpc("sendmany", "\"\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
965 LOCK2(cs_main, pwalletMain->cs_wallet);
967 string strAccount = AccountFromValue(params[0]);
968 UniValue sendTo = params[1].get_obj();
969 int nMinDepth = 1;
970 if (params.size() > 2)
971 nMinDepth = params[2].get_int();
973 CWalletTx wtx;
974 wtx.strFromAccount = strAccount;
975 if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty())
976 wtx.mapValue["comment"] = params[3].get_str();
978 UniValue subtractFeeFromAmount(UniValue::VARR);
979 if (params.size() > 4)
980 subtractFeeFromAmount = params[4].get_array();
982 set<CBitcoinAddress> setAddress;
983 vector<CRecipient> vecSend;
985 CAmount totalAmount = 0;
986 vector<string> keys = sendTo.getKeys();
987 BOOST_FOREACH(const string& name_, keys)
989 CBitcoinAddress address(name_);
990 if (!address.IsValid())
991 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+name_);
993 if (setAddress.count(address))
994 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_);
995 setAddress.insert(address);
997 CScript scriptPubKey = GetScriptForDestination(address.Get());
998 CAmount nAmount = AmountFromValue(sendTo[name_]);
999 if (nAmount <= 0)
1000 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
1001 totalAmount += nAmount;
1003 bool fSubtractFeeFromAmount = false;
1004 for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
1005 const UniValue& addr = subtractFeeFromAmount[idx];
1006 if (addr.get_str() == name_)
1007 fSubtractFeeFromAmount = true;
1010 CRecipient recipient = {scriptPubKey, nAmount, fSubtractFeeFromAmount};
1011 vecSend.push_back(recipient);
1014 EnsureWalletIsUnlocked();
1016 // Check funds
1017 CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
1018 if (totalAmount > nBalance)
1019 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
1021 // Send
1022 CReserveKey keyChange(pwalletMain);
1023 CAmount nFeeRequired = 0;
1024 int nChangePosRet = -1;
1025 string strFailReason;
1026 bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason);
1027 if (!fCreated)
1028 throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
1029 if (!pwalletMain->CommitTransaction(wtx, keyChange))
1030 throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed");
1032 return wtx.GetHash().GetHex();
1035 // Defined in rpcmisc.cpp
1036 extern CScript _createmultisig_redeemScript(const UniValue& params);
1038 UniValue addmultisigaddress(const UniValue& params, bool fHelp)
1040 if (!EnsureWalletIsAvailable(fHelp))
1041 return NullUniValue;
1043 if (fHelp || params.size() < 2 || params.size() > 3)
1045 string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
1046 "\nAdd a nrequired-to-sign multisignature address to the wallet.\n"
1047 "Each key is a Bitcoin address or hex-encoded public key.\n"
1048 "If 'account' is specified (DEPRECATED), assign address to that account.\n"
1050 "\nArguments:\n"
1051 "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
1052 "2. \"keysobject\" (string, required) A json array of bitcoin addresses or hex-encoded public keys\n"
1053 " [\n"
1054 " \"address\" (string) bitcoin address or hex-encoded public key\n"
1055 " ...,\n"
1056 " ]\n"
1057 "3. \"account\" (string, optional) DEPRECATED. An account to assign the addresses to.\n"
1059 "\nResult:\n"
1060 "\"bitcoinaddress\" (string) A bitcoin address associated with the keys.\n"
1062 "\nExamples:\n"
1063 "\nAdd a multisig address from 2 addresses\n"
1064 + HelpExampleCli("addmultisigaddress", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
1065 "\nAs json rpc call\n"
1066 + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
1068 throw runtime_error(msg);
1071 LOCK2(cs_main, pwalletMain->cs_wallet);
1073 string strAccount;
1074 if (params.size() > 2)
1075 strAccount = AccountFromValue(params[2]);
1077 // Construct using pay-to-script-hash:
1078 CScript inner = _createmultisig_redeemScript(params);
1079 CScriptID innerID(inner);
1080 pwalletMain->AddCScript(inner);
1082 pwalletMain->SetAddressBook(innerID, strAccount, "send");
1083 return CBitcoinAddress(innerID).ToString();
1087 struct tallyitem
1089 CAmount nAmount;
1090 int nConf;
1091 vector<uint256> txids;
1092 bool fIsWatchonly;
1093 tallyitem()
1095 nAmount = 0;
1096 nConf = std::numeric_limits<int>::max();
1097 fIsWatchonly = false;
1101 UniValue ListReceived(const UniValue& params, bool fByAccounts)
1103 // Minimum confirmations
1104 int nMinDepth = 1;
1105 if (params.size() > 0)
1106 nMinDepth = params[0].get_int();
1108 // Whether to include empty accounts
1109 bool fIncludeEmpty = false;
1110 if (params.size() > 1)
1111 fIncludeEmpty = params[1].get_bool();
1113 isminefilter filter = ISMINE_SPENDABLE;
1114 if(params.size() > 2)
1115 if(params[2].get_bool())
1116 filter = filter | ISMINE_WATCH_ONLY;
1118 // Tally
1119 map<CBitcoinAddress, tallyitem> mapTally;
1120 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1122 const CWalletTx& wtx = (*it).second;
1124 if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
1125 continue;
1127 int nDepth = wtx.GetDepthInMainChain();
1128 if (nDepth < nMinDepth)
1129 continue;
1131 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
1133 CTxDestination address;
1134 if (!ExtractDestination(txout.scriptPubKey, address))
1135 continue;
1137 isminefilter mine = IsMine(*pwalletMain, address);
1138 if(!(mine & filter))
1139 continue;
1141 tallyitem& item = mapTally[address];
1142 item.nAmount += txout.nValue;
1143 item.nConf = min(item.nConf, nDepth);
1144 item.txids.push_back(wtx.GetHash());
1145 if (mine & ISMINE_WATCH_ONLY)
1146 item.fIsWatchonly = true;
1150 // Reply
1151 UniValue ret(UniValue::VARR);
1152 map<string, tallyitem> mapAccountTally;
1153 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
1155 const CBitcoinAddress& address = item.first;
1156 const string& strAccount = item.second.name;
1157 map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1158 if (it == mapTally.end() && !fIncludeEmpty)
1159 continue;
1161 CAmount nAmount = 0;
1162 int nConf = std::numeric_limits<int>::max();
1163 bool fIsWatchonly = false;
1164 if (it != mapTally.end())
1166 nAmount = (*it).second.nAmount;
1167 nConf = (*it).second.nConf;
1168 fIsWatchonly = (*it).second.fIsWatchonly;
1171 if (fByAccounts)
1173 tallyitem& item = mapAccountTally[strAccount];
1174 item.nAmount += nAmount;
1175 item.nConf = min(item.nConf, nConf);
1176 item.fIsWatchonly = fIsWatchonly;
1178 else
1180 UniValue obj(UniValue::VOBJ);
1181 if(fIsWatchonly)
1182 obj.push_back(Pair("involvesWatchonly", true));
1183 obj.push_back(Pair("address", address.ToString()));
1184 obj.push_back(Pair("account", strAccount));
1185 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1186 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1187 if (!fByAccounts)
1188 obj.push_back(Pair("label", strAccount));
1189 UniValue transactions(UniValue::VARR);
1190 if (it != mapTally.end())
1192 BOOST_FOREACH(const uint256& item, (*it).second.txids)
1194 transactions.push_back(item.GetHex());
1197 obj.push_back(Pair("txids", transactions));
1198 ret.push_back(obj);
1202 if (fByAccounts)
1204 for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1206 CAmount nAmount = (*it).second.nAmount;
1207 int nConf = (*it).second.nConf;
1208 UniValue obj(UniValue::VOBJ);
1209 if((*it).second.fIsWatchonly)
1210 obj.push_back(Pair("involvesWatchonly", true));
1211 obj.push_back(Pair("account", (*it).first));
1212 obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
1213 obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1214 ret.push_back(obj);
1218 return ret;
1221 UniValue listreceivedbyaddress(const UniValue& params, bool fHelp)
1223 if (!EnsureWalletIsAvailable(fHelp))
1224 return NullUniValue;
1226 if (fHelp || params.size() > 3)
1227 throw runtime_error(
1228 "listreceivedbyaddress ( minconf includeempty includeWatchonly)\n"
1229 "\nList balances by receiving address.\n"
1230 "\nArguments:\n"
1231 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1232 "2. includeempty (numeric, optional, default=false) Whether to include addresses that haven't received any payments.\n"
1233 "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1235 "\nResult:\n"
1236 "[\n"
1237 " {\n"
1238 " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
1239 " \"address\" : \"receivingaddress\", (string) The receiving address\n"
1240 " \"account\" : \"accountname\", (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n"
1241 " \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " received by the address\n"
1242 " \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
1243 " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
1244 " }\n"
1245 " ,...\n"
1246 "]\n"
1248 "\nExamples:\n"
1249 + HelpExampleCli("listreceivedbyaddress", "")
1250 + HelpExampleCli("listreceivedbyaddress", "6 true")
1251 + HelpExampleRpc("listreceivedbyaddress", "6, true, true")
1254 LOCK2(cs_main, pwalletMain->cs_wallet);
1256 return ListReceived(params, false);
1259 UniValue listreceivedbyaccount(const UniValue& params, bool fHelp)
1261 if (!EnsureWalletIsAvailable(fHelp))
1262 return NullUniValue;
1264 if (fHelp || params.size() > 3)
1265 throw runtime_error(
1266 "listreceivedbyaccount ( minconf includeempty includeWatchonly)\n"
1267 "\nDEPRECATED. List balances by account.\n"
1268 "\nArguments:\n"
1269 "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1270 "2. includeempty (boolean, optional, default=false) Whether to include accounts that haven't received any payments.\n"
1271 "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1273 "\nResult:\n"
1274 "[\n"
1275 " {\n"
1276 " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
1277 " \"account\" : \"accountname\", (string) The account name of the receiving account\n"
1278 " \"amount\" : x.xxx, (numeric) The total amount received by addresses with this account\n"
1279 " \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
1280 " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
1281 " }\n"
1282 " ,...\n"
1283 "]\n"
1285 "\nExamples:\n"
1286 + HelpExampleCli("listreceivedbyaccount", "")
1287 + HelpExampleCli("listreceivedbyaccount", "6 true")
1288 + HelpExampleRpc("listreceivedbyaccount", "6, true, true")
1291 LOCK2(cs_main, pwalletMain->cs_wallet);
1293 return ListReceived(params, true);
1296 static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
1298 CBitcoinAddress addr;
1299 if (addr.Set(dest))
1300 entry.push_back(Pair("address", addr.ToString()));
1303 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
1305 CAmount nFee;
1306 string strSentAccount;
1307 list<COutputEntry> listReceived;
1308 list<COutputEntry> listSent;
1310 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter);
1312 bool fAllAccounts = (strAccount == string("*"));
1313 bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
1315 // Sent
1316 if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1318 BOOST_FOREACH(const COutputEntry& s, listSent)
1320 UniValue entry(UniValue::VOBJ);
1321 if(involvesWatchonly || (::IsMine(*pwalletMain, s.destination) & ISMINE_WATCH_ONLY))
1322 entry.push_back(Pair("involvesWatchonly", true));
1323 entry.push_back(Pair("account", strSentAccount));
1324 MaybePushAddress(entry, s.destination);
1325 entry.push_back(Pair("category", "send"));
1326 entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
1327 if (pwalletMain->mapAddressBook.count(s.destination))
1328 entry.push_back(Pair("label", pwalletMain->mapAddressBook[s.destination].name));
1329 entry.push_back(Pair("vout", s.vout));
1330 entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1331 if (fLong)
1332 WalletTxToJSON(wtx, entry);
1333 ret.push_back(entry);
1337 // Received
1338 if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1340 BOOST_FOREACH(const COutputEntry& r, listReceived)
1342 string account;
1343 if (pwalletMain->mapAddressBook.count(r.destination))
1344 account = pwalletMain->mapAddressBook[r.destination].name;
1345 if (fAllAccounts || (account == strAccount))
1347 UniValue entry(UniValue::VOBJ);
1348 if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
1349 entry.push_back(Pair("involvesWatchonly", true));
1350 entry.push_back(Pair("account", account));
1351 MaybePushAddress(entry, r.destination);
1352 if (wtx.IsCoinBase())
1354 if (wtx.GetDepthInMainChain() < 1)
1355 entry.push_back(Pair("category", "orphan"));
1356 else if (wtx.GetBlocksToMaturity() > 0)
1357 entry.push_back(Pair("category", "immature"));
1358 else
1359 entry.push_back(Pair("category", "generate"));
1361 else
1363 entry.push_back(Pair("category", "receive"));
1365 entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
1366 if (pwalletMain->mapAddressBook.count(r.destination))
1367 entry.push_back(Pair("label", account));
1368 entry.push_back(Pair("vout", r.vout));
1369 if (fLong)
1370 WalletTxToJSON(wtx, entry);
1371 ret.push_back(entry);
1377 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, UniValue& ret)
1379 bool fAllAccounts = (strAccount == string("*"));
1381 if (fAllAccounts || acentry.strAccount == strAccount)
1383 UniValue entry(UniValue::VOBJ);
1384 entry.push_back(Pair("account", acentry.strAccount));
1385 entry.push_back(Pair("category", "move"));
1386 entry.push_back(Pair("time", acentry.nTime));
1387 entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1388 entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1389 entry.push_back(Pair("comment", acentry.strComment));
1390 ret.push_back(entry);
1394 UniValue listtransactions(const UniValue& params, bool fHelp)
1396 if (!EnsureWalletIsAvailable(fHelp))
1397 return NullUniValue;
1399 if (fHelp || params.size() > 4)
1400 throw runtime_error(
1401 "listtransactions ( \"account\" count from includeWatchonly)\n"
1402 "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n"
1403 "\nArguments:\n"
1404 "1. \"account\" (string, optional) DEPRECATED. The account name. Should be \"*\".\n"
1405 "2. count (numeric, optional, default=10) The number of transactions to return\n"
1406 "3. from (numeric, optional, default=0) The number of transactions to skip\n"
1407 "4. includeWatchonly (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')\n"
1408 "\nResult:\n"
1409 "[\n"
1410 " {\n"
1411 " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. \n"
1412 " It will be \"\" for the default account.\n"
1413 " \"address\":\"bitcoinaddress\", (string) The bitcoin address of the transaction. Not present for \n"
1414 " move transactions (category = move).\n"
1415 " \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n"
1416 " transaction between accounts, and not associated with an address,\n"
1417 " transaction id or block. 'send' and 'receive' transactions are \n"
1418 " associated with an address, transaction id and block details\n"
1419 " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the\n"
1420 " 'move' category for moves outbound. It is positive for the 'receive' category,\n"
1421 " and for the 'move' category for inbound funds.\n"
1422 " \"vout\": n, (numeric) the vout value\n"
1423 " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
1424 " 'send' category of transactions.\n"
1425 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
1426 " 'receive' category of transactions. Negative confirmations indicate the\n"
1427 " transation conflicts with the block chain\n"
1428 " \"trusted\": xxx (bool) Whether we consider the outputs of this unconfirmed transaction safe to spend.\n"
1429 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
1430 " category of transactions.\n"
1431 " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n"
1432 " category of transactions.\n"
1433 " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
1434 " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1435 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
1436 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
1437 " for 'send' and 'receive' category of transactions.\n"
1438 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1439 " \"label\": \"label\" (string) A comment for the address/transaction, if any\n"
1440 " \"otheraccount\": \"accountname\", (string) For the 'move' category of transactions, the account the funds came \n"
1441 " from (for receiving funds, positive amounts), or went to (for sending funds,\n"
1442 " negative amounts).\n"
1443 " }\n"
1444 "]\n"
1446 "\nExamples:\n"
1447 "\nList the most recent 10 transactions in the systems\n"
1448 + HelpExampleCli("listtransactions", "") +
1449 "\nList transactions 100 to 120\n"
1450 + HelpExampleCli("listtransactions", "\"*\" 20 100") +
1451 "\nAs a json rpc call\n"
1452 + HelpExampleRpc("listtransactions", "\"*\", 20, 100")
1455 LOCK2(cs_main, pwalletMain->cs_wallet);
1457 string strAccount = "*";
1458 if (params.size() > 0)
1459 strAccount = params[0].get_str();
1460 int nCount = 10;
1461 if (params.size() > 1)
1462 nCount = params[1].get_int();
1463 int nFrom = 0;
1464 if (params.size() > 2)
1465 nFrom = params[2].get_int();
1466 isminefilter filter = ISMINE_SPENDABLE;
1467 if(params.size() > 3)
1468 if(params[3].get_bool())
1469 filter = filter | ISMINE_WATCH_ONLY;
1471 if (nCount < 0)
1472 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
1473 if (nFrom < 0)
1474 throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
1476 UniValue ret(UniValue::VARR);
1478 const CWallet::TxItems & txOrdered = pwalletMain->wtxOrdered;
1480 // iterate backwards until we have nCount items to return:
1481 for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
1483 CWalletTx *const pwtx = (*it).second.first;
1484 if (pwtx != 0)
1485 ListTransactions(*pwtx, strAccount, 0, true, ret, filter);
1486 CAccountingEntry *const pacentry = (*it).second.second;
1487 if (pacentry != 0)
1488 AcentryToJSON(*pacentry, strAccount, ret);
1490 if ((int)ret.size() >= (nCount+nFrom)) break;
1492 // ret is newest to oldest
1494 if (nFrom > (int)ret.size())
1495 nFrom = ret.size();
1496 if ((nFrom + nCount) > (int)ret.size())
1497 nCount = ret.size() - nFrom;
1499 vector<UniValue> arrTmp = ret.getValues();
1501 vector<UniValue>::iterator first = arrTmp.begin();
1502 std::advance(first, nFrom);
1503 vector<UniValue>::iterator last = arrTmp.begin();
1504 std::advance(last, nFrom+nCount);
1506 if (last != arrTmp.end()) arrTmp.erase(last, arrTmp.end());
1507 if (first != arrTmp.begin()) arrTmp.erase(arrTmp.begin(), first);
1509 std::reverse(arrTmp.begin(), arrTmp.end()); // Return oldest to newest
1511 ret.clear();
1512 ret.setArray();
1513 ret.push_backV(arrTmp);
1515 return ret;
1518 UniValue listaccounts(const UniValue& params, bool fHelp)
1520 if (!EnsureWalletIsAvailable(fHelp))
1521 return NullUniValue;
1523 if (fHelp || params.size() > 2)
1524 throw runtime_error(
1525 "listaccounts ( minconf includeWatchonly)\n"
1526 "\nDEPRECATED. Returns Object that has account names as keys, account balances as values.\n"
1527 "\nArguments:\n"
1528 "1. minconf (numeric, optional, default=1) Only include transactions with at least this many confirmations\n"
1529 "2. includeWatchonly (bool, optional, default=false) Include balances in watchonly addresses (see 'importaddress')\n"
1530 "\nResult:\n"
1531 "{ (json object where keys are account names, and values are numeric balances\n"
1532 " \"account\": x.xxx, (numeric) The property name is the account name, and the value is the total balance for the account.\n"
1533 " ...\n"
1534 "}\n"
1535 "\nExamples:\n"
1536 "\nList account balances where there at least 1 confirmation\n"
1537 + HelpExampleCli("listaccounts", "") +
1538 "\nList account balances including zero confirmation transactions\n"
1539 + HelpExampleCli("listaccounts", "0") +
1540 "\nList account balances for 6 or more confirmations\n"
1541 + HelpExampleCli("listaccounts", "6") +
1542 "\nAs json rpc call\n"
1543 + HelpExampleRpc("listaccounts", "6")
1546 LOCK2(cs_main, pwalletMain->cs_wallet);
1548 int nMinDepth = 1;
1549 if (params.size() > 0)
1550 nMinDepth = params[0].get_int();
1551 isminefilter includeWatchonly = ISMINE_SPENDABLE;
1552 if(params.size() > 1)
1553 if(params[1].get_bool())
1554 includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY;
1556 map<string, CAmount> mapAccountBalances;
1557 BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) {
1558 if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me
1559 mapAccountBalances[entry.second.name] = 0;
1562 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1564 const CWalletTx& wtx = (*it).second;
1565 CAmount nFee;
1566 string strSentAccount;
1567 list<COutputEntry> listReceived;
1568 list<COutputEntry> listSent;
1569 int nDepth = wtx.GetDepthInMainChain();
1570 if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
1571 continue;
1572 wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
1573 mapAccountBalances[strSentAccount] -= nFee;
1574 BOOST_FOREACH(const COutputEntry& s, listSent)
1575 mapAccountBalances[strSentAccount] -= s.amount;
1576 if (nDepth >= nMinDepth)
1578 BOOST_FOREACH(const COutputEntry& r, listReceived)
1579 if (pwalletMain->mapAddressBook.count(r.destination))
1580 mapAccountBalances[pwalletMain->mapAddressBook[r.destination].name] += r.amount;
1581 else
1582 mapAccountBalances[""] += r.amount;
1586 const list<CAccountingEntry> & acentries = pwalletMain->laccentries;
1587 BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1588 mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1590 UniValue ret(UniValue::VOBJ);
1591 BOOST_FOREACH(const PAIRTYPE(string, CAmount)& accountBalance, mapAccountBalances) {
1592 ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1594 return ret;
1597 UniValue listsinceblock(const UniValue& params, bool fHelp)
1599 if (!EnsureWalletIsAvailable(fHelp))
1600 return NullUniValue;
1602 if (fHelp)
1603 throw runtime_error(
1604 "listsinceblock ( \"blockhash\" target-confirmations includeWatchonly)\n"
1605 "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n"
1606 "\nArguments:\n"
1607 "1. \"blockhash\" (string, optional) The block hash to list transactions since\n"
1608 "2. target-confirmations: (numeric, optional) The confirmations required, must be 1 or more\n"
1609 "3. includeWatchonly: (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')"
1610 "\nResult:\n"
1611 "{\n"
1612 " \"transactions\": [\n"
1613 " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n"
1614 " \"address\":\"bitcoinaddress\", (string) The bitcoin address of the transaction. Not present for move transactions (category = move).\n"
1615 " \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
1616 " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the 'move' category for moves \n"
1617 " outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
1618 " \"vout\" : n, (numeric) the vout value\n"
1619 " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the 'send' category of transactions.\n"
1620 " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
1621 " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1622 " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1623 " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
1624 " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1625 " \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
1626 " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
1627 " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
1628 " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
1629 " \"to\": \"...\", (string) If a comment to is associated with the transaction.\n"
1630 " ],\n"
1631 " \"lastblock\": \"lastblockhash\" (string) The hash of the last block\n"
1632 "}\n"
1633 "\nExamples:\n"
1634 + HelpExampleCli("listsinceblock", "")
1635 + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
1636 + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
1639 LOCK2(cs_main, pwalletMain->cs_wallet);
1641 CBlockIndex *pindex = NULL;
1642 int target_confirms = 1;
1643 isminefilter filter = ISMINE_SPENDABLE;
1645 if (params.size() > 0)
1647 uint256 blockId;
1649 blockId.SetHex(params[0].get_str());
1650 BlockMap::iterator it = mapBlockIndex.find(blockId);
1651 if (it != mapBlockIndex.end())
1652 pindex = it->second;
1655 if (params.size() > 1)
1657 target_confirms = params[1].get_int();
1659 if (target_confirms < 1)
1660 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
1663 if(params.size() > 2)
1664 if(params[2].get_bool())
1665 filter = filter | ISMINE_WATCH_ONLY;
1667 int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
1669 UniValue transactions(UniValue::VARR);
1671 for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1673 CWalletTx tx = (*it).second;
1675 if (depth == -1 || tx.GetDepthInMainChain() < depth)
1676 ListTransactions(tx, "*", 0, true, transactions, filter);
1679 CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
1680 uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : uint256();
1682 UniValue ret(UniValue::VOBJ);
1683 ret.push_back(Pair("transactions", transactions));
1684 ret.push_back(Pair("lastblock", lastblock.GetHex()));
1686 return ret;
1689 UniValue gettransaction(const UniValue& params, bool fHelp)
1691 if (!EnsureWalletIsAvailable(fHelp))
1692 return NullUniValue;
1694 if (fHelp || params.size() < 1 || params.size() > 2)
1695 throw runtime_error(
1696 "gettransaction \"txid\" ( includeWatchonly )\n"
1697 "\nGet detailed information about in-wallet transaction <txid>\n"
1698 "\nArguments:\n"
1699 "1. \"txid\" (string, required) The transaction id\n"
1700 "2. \"includeWatchonly\" (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n"
1701 "\nResult:\n"
1702 "{\n"
1703 " \"amount\" : x.xxx, (numeric) The transaction amount in " + CURRENCY_UNIT + "\n"
1704 " \"confirmations\" : n, (numeric) The number of confirmations\n"
1705 " \"blockhash\" : \"hash\", (string) The block hash\n"
1706 " \"blockindex\" : xx, (numeric) The block index\n"
1707 " \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
1708 " \"txid\" : \"transactionid\", (string) The transaction id.\n"
1709 " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
1710 " \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
1711 " \"details\" : [\n"
1712 " {\n"
1713 " \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n"
1714 " \"address\" : \"bitcoinaddress\", (string) The bitcoin address involved in the transaction\n"
1715 " \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n"
1716 " \"amount\" : x.xxx, (numeric) The amount in " + CURRENCY_UNIT + "\n"
1717 " \"label\" : \"label\", (string) A comment for the address/transaction, if any\n"
1718 " \"vout\" : n, (numeric) the vout value\n"
1719 " }\n"
1720 " ,...\n"
1721 " ],\n"
1722 " \"hex\" : \"data\" (string) Raw data for transaction\n"
1723 "}\n"
1725 "\nExamples:\n"
1726 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1727 + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
1728 + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1731 LOCK2(cs_main, pwalletMain->cs_wallet);
1733 uint256 hash;
1734 hash.SetHex(params[0].get_str());
1736 isminefilter filter = ISMINE_SPENDABLE;
1737 if(params.size() > 1)
1738 if(params[1].get_bool())
1739 filter = filter | ISMINE_WATCH_ONLY;
1741 UniValue entry(UniValue::VOBJ);
1742 if (!pwalletMain->mapWallet.count(hash))
1743 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
1744 const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1746 CAmount nCredit = wtx.GetCredit(filter);
1747 CAmount nDebit = wtx.GetDebit(filter);
1748 CAmount nNet = nCredit - nDebit;
1749 CAmount nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0);
1751 entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1752 if (wtx.IsFromMe(filter))
1753 entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1755 WalletTxToJSON(wtx, entry);
1757 UniValue details(UniValue::VARR);
1758 ListTransactions(wtx, "*", 0, false, details, filter);
1759 entry.push_back(Pair("details", details));
1761 string strHex = EncodeHexTx(static_cast<CTransaction>(wtx));
1762 entry.push_back(Pair("hex", strHex));
1764 return entry;
1767 UniValue abandontransaction(const UniValue& params, bool fHelp)
1769 if (!EnsureWalletIsAvailable(fHelp))
1770 return NullUniValue;
1772 if (fHelp || params.size() != 1)
1773 throw runtime_error(
1774 "abandontransaction \"txid\"\n"
1775 "\nMark in-wallet transaction <txid> as abandoned\n"
1776 "This will mark this transaction and all its in-wallet descendants as abandoned which will allow\n"
1777 "for their inputs to be respent. It can be used to replace \"stuck\" or evicted transactions.\n"
1778 "It only works on transactions which are not included in a block and are not currently in the mempool.\n"
1779 "It has no effect on transactions which are already conflicted or abandoned.\n"
1780 "\nArguments:\n"
1781 "1. \"txid\" (string, required) The transaction id\n"
1782 "\nResult:\n"
1783 "\nExamples:\n"
1784 + HelpExampleCli("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1785 + HelpExampleRpc("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1788 LOCK2(cs_main, pwalletMain->cs_wallet);
1790 uint256 hash;
1791 hash.SetHex(params[0].get_str());
1793 if (!pwalletMain->mapWallet.count(hash))
1794 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
1795 if (!pwalletMain->AbandonTransaction(hash))
1796 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not eligible for abandonment");
1798 return NullUniValue;
1802 UniValue backupwallet(const UniValue& params, bool fHelp)
1804 if (!EnsureWalletIsAvailable(fHelp))
1805 return NullUniValue;
1807 if (fHelp || params.size() != 1)
1808 throw runtime_error(
1809 "backupwallet \"destination\"\n"
1810 "\nSafely copies wallet.dat to destination, which can be a directory or a path with filename.\n"
1811 "\nArguments:\n"
1812 "1. \"destination\" (string) The destination directory or file\n"
1813 "\nExamples:\n"
1814 + HelpExampleCli("backupwallet", "\"backup.dat\"")
1815 + HelpExampleRpc("backupwallet", "\"backup.dat\"")
1818 LOCK2(cs_main, pwalletMain->cs_wallet);
1820 string strDest = params[0].get_str();
1821 if (!BackupWallet(*pwalletMain, strDest))
1822 throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
1824 return NullUniValue;
1828 UniValue keypoolrefill(const UniValue& params, bool fHelp)
1830 if (!EnsureWalletIsAvailable(fHelp))
1831 return NullUniValue;
1833 if (fHelp || params.size() > 1)
1834 throw runtime_error(
1835 "keypoolrefill ( newsize )\n"
1836 "\nFills the keypool."
1837 + HelpRequiringPassphrase() + "\n"
1838 "\nArguments\n"
1839 "1. newsize (numeric, optional, default=100) The new keypool size\n"
1840 "\nExamples:\n"
1841 + HelpExampleCli("keypoolrefill", "")
1842 + HelpExampleRpc("keypoolrefill", "")
1845 LOCK2(cs_main, pwalletMain->cs_wallet);
1847 // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
1848 unsigned int kpSize = 0;
1849 if (params.size() > 0) {
1850 if (params[0].get_int() < 0)
1851 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
1852 kpSize = (unsigned int)params[0].get_int();
1855 EnsureWalletIsUnlocked();
1856 pwalletMain->TopUpKeyPool(kpSize);
1858 if (pwalletMain->GetKeyPoolSize() < kpSize)
1859 throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
1861 return NullUniValue;
1865 static void LockWallet(CWallet* pWallet)
1867 LOCK(cs_nWalletUnlockTime);
1868 nWalletUnlockTime = 0;
1869 pWallet->Lock();
1872 UniValue walletpassphrase(const UniValue& params, bool fHelp)
1874 if (!EnsureWalletIsAvailable(fHelp))
1875 return NullUniValue;
1877 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1878 throw runtime_error(
1879 "walletpassphrase \"passphrase\" timeout\n"
1880 "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
1881 "This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
1882 "\nArguments:\n"
1883 "1. \"passphrase\" (string, required) The wallet passphrase\n"
1884 "2. timeout (numeric, required) The time to keep the decryption key in seconds.\n"
1885 "\nNote:\n"
1886 "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
1887 "time that overrides the old one.\n"
1888 "\nExamples:\n"
1889 "\nunlock the wallet for 60 seconds\n"
1890 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
1891 "\nLock the wallet again (before 60 seconds)\n"
1892 + HelpExampleCli("walletlock", "") +
1893 "\nAs json rpc call\n"
1894 + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
1897 LOCK2(cs_main, pwalletMain->cs_wallet);
1899 if (fHelp)
1900 return true;
1901 if (!pwalletMain->IsCrypted())
1902 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1904 // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1905 SecureString strWalletPass;
1906 strWalletPass.reserve(100);
1907 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1908 // Alternately, find a way to make params[0] mlock()'d to begin with.
1909 strWalletPass = params[0].get_str().c_str();
1911 if (strWalletPass.length() > 0)
1913 if (!pwalletMain->Unlock(strWalletPass))
1914 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1916 else
1917 throw runtime_error(
1918 "walletpassphrase <passphrase> <timeout>\n"
1919 "Stores the wallet decryption key in memory for <timeout> seconds.");
1921 pwalletMain->TopUpKeyPool();
1923 int64_t nSleepTime = params[1].get_int64();
1924 LOCK(cs_nWalletUnlockTime);
1925 nWalletUnlockTime = GetTime() + nSleepTime;
1926 RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
1928 return NullUniValue;
1932 UniValue walletpassphrasechange(const UniValue& params, bool fHelp)
1934 if (!EnsureWalletIsAvailable(fHelp))
1935 return NullUniValue;
1937 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1938 throw runtime_error(
1939 "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
1940 "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
1941 "\nArguments:\n"
1942 "1. \"oldpassphrase\" (string) The current passphrase\n"
1943 "2. \"newpassphrase\" (string) The new passphrase\n"
1944 "\nExamples:\n"
1945 + HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
1946 + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
1949 LOCK2(cs_main, pwalletMain->cs_wallet);
1951 if (fHelp)
1952 return true;
1953 if (!pwalletMain->IsCrypted())
1954 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1956 // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1957 // Alternately, find a way to make params[0] mlock()'d to begin with.
1958 SecureString strOldWalletPass;
1959 strOldWalletPass.reserve(100);
1960 strOldWalletPass = params[0].get_str().c_str();
1962 SecureString strNewWalletPass;
1963 strNewWalletPass.reserve(100);
1964 strNewWalletPass = params[1].get_str().c_str();
1966 if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1967 throw runtime_error(
1968 "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1969 "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1971 if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1972 throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1974 return NullUniValue;
1978 UniValue walletlock(const UniValue& params, bool fHelp)
1980 if (!EnsureWalletIsAvailable(fHelp))
1981 return NullUniValue;
1983 if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1984 throw runtime_error(
1985 "walletlock\n"
1986 "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
1987 "After calling this method, you will need to call walletpassphrase again\n"
1988 "before being able to call any methods which require the wallet to be unlocked.\n"
1989 "\nExamples:\n"
1990 "\nSet the passphrase for 2 minutes to perform a transaction\n"
1991 + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
1992 "\nPerform a send (requires passphrase set)\n"
1993 + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 1.0") +
1994 "\nClear the passphrase since we are done before 2 minutes is up\n"
1995 + HelpExampleCli("walletlock", "") +
1996 "\nAs json rpc call\n"
1997 + HelpExampleRpc("walletlock", "")
2000 LOCK2(cs_main, pwalletMain->cs_wallet);
2002 if (fHelp)
2003 return true;
2004 if (!pwalletMain->IsCrypted())
2005 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
2008 LOCK(cs_nWalletUnlockTime);
2009 pwalletMain->Lock();
2010 nWalletUnlockTime = 0;
2013 return NullUniValue;
2017 UniValue encryptwallet(const UniValue& params, bool fHelp)
2019 if (!EnsureWalletIsAvailable(fHelp))
2020 return NullUniValue;
2022 if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
2023 throw runtime_error(
2024 "encryptwallet \"passphrase\"\n"
2025 "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
2026 "After this, any calls that interact with private keys such as sending or signing \n"
2027 "will require the passphrase to be set prior the making these calls.\n"
2028 "Use the walletpassphrase call for this, and then walletlock call.\n"
2029 "If the wallet is already encrypted, use the walletpassphrasechange call.\n"
2030 "Note that this will shutdown the server.\n"
2031 "\nArguments:\n"
2032 "1. \"passphrase\" (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n"
2033 "\nExamples:\n"
2034 "\nEncrypt you wallet\n"
2035 + HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
2036 "\nNow set the passphrase to use the wallet, such as for signing or sending bitcoin\n"
2037 + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
2038 "\nNow we can so something like sign\n"
2039 + HelpExampleCli("signmessage", "\"bitcoinaddress\" \"test message\"") +
2040 "\nNow lock the wallet again by removing the passphrase\n"
2041 + HelpExampleCli("walletlock", "") +
2042 "\nAs a json rpc call\n"
2043 + HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
2046 LOCK2(cs_main, pwalletMain->cs_wallet);
2048 if (fHelp)
2049 return true;
2050 if (pwalletMain->IsCrypted())
2051 throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
2053 // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
2054 // Alternately, find a way to make params[0] mlock()'d to begin with.
2055 SecureString strWalletPass;
2056 strWalletPass.reserve(100);
2057 strWalletPass = params[0].get_str().c_str();
2059 if (strWalletPass.length() < 1)
2060 throw runtime_error(
2061 "encryptwallet <passphrase>\n"
2062 "Encrypts the wallet with <passphrase>.");
2064 if (!pwalletMain->EncryptWallet(strWalletPass))
2065 throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
2067 // BDB seems to have a bad habit of writing old data into
2068 // slack space in .dat files; that is bad if the old data is
2069 // unencrypted private keys. So:
2070 StartShutdown();
2071 return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
2074 UniValue lockunspent(const UniValue& params, bool fHelp)
2076 if (!EnsureWalletIsAvailable(fHelp))
2077 return NullUniValue;
2079 if (fHelp || params.size() < 1 || params.size() > 2)
2080 throw runtime_error(
2081 "lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n"
2082 "\nUpdates list of temporarily unspendable outputs.\n"
2083 "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
2084 "A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
2085 "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
2086 "is always cleared (by virtue of process exit) when a node stops or fails.\n"
2087 "Also see the listunspent call\n"
2088 "\nArguments:\n"
2089 "1. unlock (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
2090 "2. \"transactions\" (string, required) A json array of objects. Each object the txid (string) vout (numeric)\n"
2091 " [ (json array of json objects)\n"
2092 " {\n"
2093 " \"txid\":\"id\", (string) The transaction id\n"
2094 " \"vout\": n (numeric) The output number\n"
2095 " }\n"
2096 " ,...\n"
2097 " ]\n"
2099 "\nResult:\n"
2100 "true|false (boolean) Whether the command was successful or not\n"
2102 "\nExamples:\n"
2103 "\nList the unspent transactions\n"
2104 + HelpExampleCli("listunspent", "") +
2105 "\nLock an unspent transaction\n"
2106 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2107 "\nList the locked transactions\n"
2108 + HelpExampleCli("listlockunspent", "") +
2109 "\nUnlock the transaction again\n"
2110 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2111 "\nAs a json rpc call\n"
2112 + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
2115 LOCK2(cs_main, pwalletMain->cs_wallet);
2117 if (params.size() == 1)
2118 RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL));
2119 else
2120 RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL)(UniValue::VARR));
2122 bool fUnlock = params[0].get_bool();
2124 if (params.size() == 1) {
2125 if (fUnlock)
2126 pwalletMain->UnlockAllCoins();
2127 return true;
2130 UniValue outputs = params[1].get_array();
2131 for (unsigned int idx = 0; idx < outputs.size(); idx++) {
2132 const UniValue& output = outputs[idx];
2133 if (!output.isObject())
2134 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
2135 const UniValue& o = output.get_obj();
2137 RPCTypeCheckObj(o, boost::assign::map_list_of("txid", UniValue::VSTR)("vout", UniValue::VNUM));
2139 string txid = find_value(o, "txid").get_str();
2140 if (!IsHex(txid))
2141 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
2143 int nOutput = find_value(o, "vout").get_int();
2144 if (nOutput < 0)
2145 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
2147 COutPoint outpt(uint256S(txid), nOutput);
2149 if (fUnlock)
2150 pwalletMain->UnlockCoin(outpt);
2151 else
2152 pwalletMain->LockCoin(outpt);
2155 return true;
2158 UniValue listlockunspent(const UniValue& params, bool fHelp)
2160 if (!EnsureWalletIsAvailable(fHelp))
2161 return NullUniValue;
2163 if (fHelp || params.size() > 0)
2164 throw runtime_error(
2165 "listlockunspent\n"
2166 "\nReturns list of temporarily unspendable outputs.\n"
2167 "See the lockunspent call to lock and unlock transactions for spending.\n"
2168 "\nResult:\n"
2169 "[\n"
2170 " {\n"
2171 " \"txid\" : \"transactionid\", (string) The transaction id locked\n"
2172 " \"vout\" : n (numeric) The vout value\n"
2173 " }\n"
2174 " ,...\n"
2175 "]\n"
2176 "\nExamples:\n"
2177 "\nList the unspent transactions\n"
2178 + HelpExampleCli("listunspent", "") +
2179 "\nLock an unspent transaction\n"
2180 + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2181 "\nList the locked transactions\n"
2182 + HelpExampleCli("listlockunspent", "") +
2183 "\nUnlock the transaction again\n"
2184 + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
2185 "\nAs a json rpc call\n"
2186 + HelpExampleRpc("listlockunspent", "")
2189 LOCK2(cs_main, pwalletMain->cs_wallet);
2191 vector<COutPoint> vOutpts;
2192 pwalletMain->ListLockedCoins(vOutpts);
2194 UniValue ret(UniValue::VARR);
2196 BOOST_FOREACH(COutPoint &outpt, vOutpts) {
2197 UniValue o(UniValue::VOBJ);
2199 o.push_back(Pair("txid", outpt.hash.GetHex()));
2200 o.push_back(Pair("vout", (int)outpt.n));
2201 ret.push_back(o);
2204 return ret;
2207 UniValue settxfee(const UniValue& params, bool fHelp)
2209 if (!EnsureWalletIsAvailable(fHelp))
2210 return NullUniValue;
2212 if (fHelp || params.size() < 1 || params.size() > 1)
2213 throw runtime_error(
2214 "settxfee amount\n"
2215 "\nSet the transaction fee per kB. Overwrites the paytxfee parameter.\n"
2216 "\nArguments:\n"
2217 "1. amount (numeric, required) The transaction fee in " + CURRENCY_UNIT + "/kB rounded to the nearest 0.00000001\n"
2218 "\nResult\n"
2219 "true|false (boolean) Returns true if successful\n"
2220 "\nExamples:\n"
2221 + HelpExampleCli("settxfee", "0.00001")
2222 + HelpExampleRpc("settxfee", "0.00001")
2225 LOCK2(cs_main, pwalletMain->cs_wallet);
2227 // Amount
2228 CAmount nAmount = AmountFromValue(params[0]);
2230 payTxFee = CFeeRate(nAmount, 1000);
2231 return true;
2234 UniValue getwalletinfo(const UniValue& params, bool fHelp)
2236 if (!EnsureWalletIsAvailable(fHelp))
2237 return NullUniValue;
2239 if (fHelp || params.size() != 0)
2240 throw runtime_error(
2241 "getwalletinfo\n"
2242 "Returns an object containing various wallet state info.\n"
2243 "\nResult:\n"
2244 "{\n"
2245 " \"walletversion\": xxxxx, (numeric) the wallet version\n"
2246 " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
2247 " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
2248 " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + CURRENCY_UNIT + "\n"
2249 " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
2250 " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
2251 " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
2252 " \"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"
2253 " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n"
2254 "}\n"
2255 "\nExamples:\n"
2256 + HelpExampleCli("getwalletinfo", "")
2257 + HelpExampleRpc("getwalletinfo", "")
2260 LOCK2(cs_main, pwalletMain->cs_wallet);
2262 UniValue obj(UniValue::VOBJ);
2263 obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
2264 obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
2265 obj.push_back(Pair("unconfirmed_balance", ValueFromAmount(pwalletMain->GetUnconfirmedBalance())));
2266 obj.push_back(Pair("immature_balance", ValueFromAmount(pwalletMain->GetImmatureBalance())));
2267 obj.push_back(Pair("txcount", (int)pwalletMain->mapWallet.size()));
2268 obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
2269 obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
2270 if (pwalletMain->IsCrypted())
2271 obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
2272 obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
2273 return obj;
2276 UniValue resendwallettransactions(const UniValue& params, bool fHelp)
2278 if (!EnsureWalletIsAvailable(fHelp))
2279 return NullUniValue;
2281 if (fHelp || params.size() != 0)
2282 throw runtime_error(
2283 "resendwallettransactions\n"
2284 "Immediately re-broadcast unconfirmed wallet transactions to all peers.\n"
2285 "Intended only for testing; the wallet code periodically re-broadcasts\n"
2286 "automatically.\n"
2287 "Returns array of transaction ids that were re-broadcast.\n"
2290 LOCK2(cs_main, pwalletMain->cs_wallet);
2292 std::vector<uint256> txids = pwalletMain->ResendWalletTransactionsBefore(GetTime());
2293 UniValue result(UniValue::VARR);
2294 BOOST_FOREACH(const uint256& txid, txids)
2296 result.push_back(txid.ToString());
2298 return result;
2301 UniValue listunspent(const UniValue& params, bool fHelp)
2303 if (!EnsureWalletIsAvailable(fHelp))
2304 return NullUniValue;
2306 if (fHelp || params.size() > 3)
2307 throw runtime_error(
2308 "listunspent ( minconf maxconf [\"address\",...] )\n"
2309 "\nReturns array of unspent transaction outputs\n"
2310 "with between minconf and maxconf (inclusive) confirmations.\n"
2311 "Optionally filter to only include txouts paid to specified addresses.\n"
2312 "Results are an array of Objects, each of which has:\n"
2313 "{txid, vout, scriptPubKey, amount, confirmations}\n"
2314 "\nArguments:\n"
2315 "1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n"
2316 "2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n"
2317 "3. \"addresses\" (string) A json array of bitcoin addresses to filter\n"
2318 " [\n"
2319 " \"address\" (string) bitcoin address\n"
2320 " ,...\n"
2321 " ]\n"
2322 "\nResult\n"
2323 "[ (array of json object)\n"
2324 " {\n"
2325 " \"txid\" : \"txid\", (string) the transaction id \n"
2326 " \"vout\" : n, (numeric) the vout value\n"
2327 " \"address\" : \"address\", (string) the bitcoin address\n"
2328 " \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n"
2329 " \"scriptPubKey\" : \"key\", (string) the script key\n"
2330 " \"amount\" : x.xxx, (numeric) the transaction amount in " + CURRENCY_UNIT + "\n"
2331 " \"confirmations\" : n (numeric) The number of confirmations\n"
2332 " }\n"
2333 " ,...\n"
2334 "]\n"
2336 "\nExamples\n"
2337 + HelpExampleCli("listunspent", "")
2338 + HelpExampleCli("listunspent", "6 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
2339 + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
2342 RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)(UniValue::VNUM)(UniValue::VARR));
2344 int nMinDepth = 1;
2345 if (params.size() > 0)
2346 nMinDepth = params[0].get_int();
2348 int nMaxDepth = 9999999;
2349 if (params.size() > 1)
2350 nMaxDepth = params[1].get_int();
2352 set<CBitcoinAddress> setAddress;
2353 if (params.size() > 2) {
2354 UniValue inputs = params[2].get_array();
2355 for (unsigned int idx = 0; idx < inputs.size(); idx++) {
2356 const UniValue& input = inputs[idx];
2357 CBitcoinAddress address(input.get_str());
2358 if (!address.IsValid())
2359 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+input.get_str());
2360 if (setAddress.count(address))
2361 throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str());
2362 setAddress.insert(address);
2366 UniValue results(UniValue::VARR);
2367 vector<COutput> vecOutputs;
2368 assert(pwalletMain != NULL);
2369 LOCK2(cs_main, pwalletMain->cs_wallet);
2370 pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
2371 BOOST_FOREACH(const COutput& out, vecOutputs) {
2372 if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
2373 continue;
2375 if (setAddress.size()) {
2376 CTxDestination address;
2377 if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
2378 continue;
2380 if (!setAddress.count(address))
2381 continue;
2384 CAmount nValue = out.tx->vout[out.i].nValue;
2385 const CScript& pk = out.tx->vout[out.i].scriptPubKey;
2386 UniValue entry(UniValue::VOBJ);
2387 entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
2388 entry.push_back(Pair("vout", out.i));
2389 CTxDestination address;
2390 if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
2391 entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
2392 if (pwalletMain->mapAddressBook.count(address))
2393 entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name));
2395 entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end())));
2396 if (pk.IsPayToScriptHash()) {
2397 CTxDestination address;
2398 if (ExtractDestination(pk, address)) {
2399 const CScriptID& hash = boost::get<CScriptID>(address);
2400 CScript redeemScript;
2401 if (pwalletMain->GetCScript(hash, redeemScript))
2402 entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
2405 entry.push_back(Pair("amount",ValueFromAmount(nValue)));
2406 entry.push_back(Pair("confirmations",out.nDepth));
2407 entry.push_back(Pair("spendable", out.fSpendable));
2408 results.push_back(entry);
2411 return results;
2414 UniValue fundrawtransaction(const UniValue& params, bool fHelp)
2416 if (!EnsureWalletIsAvailable(fHelp))
2417 return NullUniValue;
2419 if (fHelp || params.size() < 1 || params.size() > 2)
2420 throw runtime_error(
2421 "fundrawtransaction \"hexstring\" includeWatching\n"
2422 "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
2423 "This will not modify existing inputs, and will add one change output to the outputs.\n"
2424 "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
2425 "The inputs added will not be signed, use signrawtransaction for that.\n"
2426 "Note that all existing inputs must have their previous output transaction be in the wallet.\n"
2427 "Note that all inputs selected must be of standard form and P2SH scripts must be"
2428 "in the wallet using importaddress or addmultisigaddress (to calculate fees).\n"
2429 "Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n"
2430 "\nArguments:\n"
2431 "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
2432 "2. includeWatching (boolean, optional, default false) Also select inputs which are watch only\n"
2433 "\nResult:\n"
2434 "{\n"
2435 " \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
2436 " \"fee\": n, (numeric) Fee the resulting transaction pays\n"
2437 " \"changepos\": n (numeric) The position of the added change output, or -1\n"
2438 "}\n"
2439 "\"hex\" \n"
2440 "\nExamples:\n"
2441 "\nCreate a transaction with no inputs\n"
2442 + HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") +
2443 "\nAdd sufficient unsigned inputs to meet the output value\n"
2444 + HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") +
2445 "\nSign the transaction\n"
2446 + HelpExampleCli("signrawtransaction", "\"fundedtransactionhex\"") +
2447 "\nSend the transaction\n"
2448 + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
2451 RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL));
2453 // parse hex string from parameter
2454 CTransaction origTx;
2455 if (!DecodeHexTx(origTx, params[0].get_str()))
2456 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
2458 if (origTx.vout.size() == 0)
2459 throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output");
2461 bool includeWatching = false;
2462 if (params.size() > 1)
2463 includeWatching = params[1].get_bool();
2465 CMutableTransaction tx(origTx);
2466 CAmount nFee;
2467 string strFailReason;
2468 int nChangePos = -1;
2469 if(!pwalletMain->FundTransaction(tx, nFee, nChangePos, strFailReason, includeWatching))
2470 throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
2472 UniValue result(UniValue::VOBJ);
2473 result.push_back(Pair("hex", EncodeHexTx(tx)));
2474 result.push_back(Pair("changepos", nChangePos));
2475 result.push_back(Pair("fee", ValueFromAmount(nFee)));
2477 return result;