]> Git Repo - VerusCoin.git/blob - src/rpcwallet.cpp
MOVEONLY: Move CFeeRate and Amount constants to amount.o
[VerusCoin.git] / src / rpcwallet.cpp
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "amount.h"
7 #include "base58.h"
8 #include "core_io.h"
9 #include "rpcserver.h"
10 #include "init.h"
11 #include "net.h"
12 #include "netbase.h"
13 #include "timedata.h"
14 #include "util.h"
15 #include "wallet.h"
16 #include "walletdb.h"
17
18 #include <stdint.h>
19
20 #include <boost/assign/list_of.hpp>
21 #include "json/json_spirit_utils.h"
22 #include "json/json_spirit_value.h"
23
24 using namespace std;
25 using namespace boost;
26 using namespace boost::assign;
27 using namespace json_spirit;
28
29 int64_t nWalletUnlockTime;
30 static CCriticalSection cs_nWalletUnlockTime;
31
32 std::string HelpRequiringPassphrase()
33 {
34     return pwalletMain && pwalletMain->IsCrypted()
35         ? "\nRequires wallet passphrase to be set with walletpassphrase call."
36         : "";
37 }
38
39 void EnsureWalletIsUnlocked()
40 {
41     if (pwalletMain->IsLocked())
42         throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
43 }
44
45 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
46 {
47     int confirms = wtx.GetDepthInMainChain();
48     entry.push_back(Pair("confirmations", confirms));
49     if (wtx.IsCoinBase())
50         entry.push_back(Pair("generated", true));
51     if (confirms > 0)
52     {
53         entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
54         entry.push_back(Pair("blockindex", wtx.nIndex));
55         entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
56     }
57     uint256 hash = wtx.GetHash();
58     entry.push_back(Pair("txid", hash.GetHex()));
59     Array conflicts;
60     BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
61         conflicts.push_back(conflict.GetHex());
62     entry.push_back(Pair("walletconflicts", conflicts));
63     entry.push_back(Pair("time", wtx.GetTxTime()));
64     entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived));
65     BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
66         entry.push_back(Pair(item.first, item.second));
67 }
68
69 string AccountFromValue(const Value& value)
70 {
71     string strAccount = value.get_str();
72     if (strAccount == "*")
73         throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Invalid account name");
74     return strAccount;
75 }
76
77 Value getnewaddress(const Array& params, bool fHelp)
78 {
79     if (fHelp || params.size() > 1)
80         throw runtime_error(
81             "getnewaddress ( \"account\" )\n"
82             "\nReturns a new Bitcoin address for receiving payments.\n"
83             "If 'account' is specified (recommended), it is added to the address book \n"
84             "so payments received with the address will be credited to 'account'.\n"
85             "\nArguments:\n"
86             "1. \"account\"        (string, optional) The account name for the address to be linked to. if not provided, the default account \"\" is used. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created if there is no account by the given name.\n"
87             "\nResult:\n"
88             "\"bitcoinaddress\"    (string) The new bitcoin address\n"
89             "\nExamples:\n"
90             + HelpExampleCli("getnewaddress", "")
91             + HelpExampleCli("getnewaddress", "\"\"")
92             + HelpExampleCli("getnewaddress", "\"myaccount\"")
93             + HelpExampleRpc("getnewaddress", "\"myaccount\"")
94         );
95
96     // Parse the account first so we don't generate a key if there's an error
97     string strAccount;
98     if (params.size() > 0)
99         strAccount = AccountFromValue(params[0]);
100
101     if (!pwalletMain->IsLocked())
102         pwalletMain->TopUpKeyPool();
103
104     // Generate a new key that is added to wallet
105     CPubKey newKey;
106     if (!pwalletMain->GetKeyFromPool(newKey))
107         throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
108     CKeyID keyID = newKey.GetID();
109
110     pwalletMain->SetAddressBook(keyID, strAccount, "receive");
111
112     return CBitcoinAddress(keyID).ToString();
113 }
114
115
116 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
117 {
118     CWalletDB walletdb(pwalletMain->strWalletFile);
119
120     CAccount account;
121     walletdb.ReadAccount(strAccount, account);
122
123     bool bKeyUsed = false;
124
125     // Check if the current key has been used
126     if (account.vchPubKey.IsValid())
127     {
128         CScript scriptPubKey = GetScriptForDestination(account.vchPubKey.GetID());
129         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
130              it != pwalletMain->mapWallet.end() && account.vchPubKey.IsValid();
131              ++it)
132         {
133             const CWalletTx& wtx = (*it).second;
134             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
135                 if (txout.scriptPubKey == scriptPubKey)
136                     bKeyUsed = true;
137         }
138     }
139
140     // Generate a new key
141     if (!account.vchPubKey.IsValid() || bForceNew || bKeyUsed)
142     {
143         if (!pwalletMain->GetKeyFromPool(account.vchPubKey))
144             throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
145
146         pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, "receive");
147         walletdb.WriteAccount(strAccount, account);
148     }
149
150     return CBitcoinAddress(account.vchPubKey.GetID());
151 }
152
153 Value getaccountaddress(const Array& params, bool fHelp)
154 {
155     if (fHelp || params.size() != 1)
156         throw runtime_error(
157             "getaccountaddress \"account\"\n"
158             "\nReturns the current Bitcoin address for receiving payments to this account.\n"
159             "\nArguments:\n"
160             "1. \"account\"       (string, required) The account name for the address. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created and a new address created  if there is no account by the given name.\n"
161             "\nResult:\n"
162             "\"bitcoinaddress\"   (string) The account bitcoin address\n"
163             "\nExamples:\n"
164             + HelpExampleCli("getaccountaddress", "")
165             + HelpExampleCli("getaccountaddress", "\"\"")
166             + HelpExampleCli("getaccountaddress", "\"myaccount\"")
167             + HelpExampleRpc("getaccountaddress", "\"myaccount\"")
168         );
169
170     // Parse the account first so we don't generate a key if there's an error
171     string strAccount = AccountFromValue(params[0]);
172
173     Value ret;
174
175     ret = GetAccountAddress(strAccount).ToString();
176
177     return ret;
178 }
179
180
181 Value getrawchangeaddress(const Array& params, bool fHelp)
182 {
183     if (fHelp || params.size() > 1)
184         throw runtime_error(
185             "getrawchangeaddress\n"
186             "\nReturns a new Bitcoin address, for receiving change.\n"
187             "This is for use with raw transactions, NOT normal use.\n"
188             "\nResult:\n"
189             "\"address\"    (string) The address\n"
190             "\nExamples:\n"
191             + HelpExampleCli("getrawchangeaddress", "")
192             + HelpExampleRpc("getrawchangeaddress", "")
193        );
194
195     if (!pwalletMain->IsLocked())
196         pwalletMain->TopUpKeyPool();
197
198     CReserveKey reservekey(pwalletMain);
199     CPubKey vchPubKey;
200     if (!reservekey.GetReservedKey(vchPubKey))
201         throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
202
203     reservekey.KeepKey();
204
205     CKeyID keyID = vchPubKey.GetID();
206
207     return CBitcoinAddress(keyID).ToString();
208 }
209
210
211 Value setaccount(const Array& params, bool fHelp)
212 {
213     if (fHelp || params.size() < 1 || params.size() > 2)
214         throw runtime_error(
215             "setaccount \"bitcoinaddress\" \"account\"\n"
216             "\nSets the account associated with the given address.\n"
217             "\nArguments:\n"
218             "1. \"bitcoinaddress\"  (string, required) The bitcoin address to be associated with an account.\n"
219             "2. \"account\"         (string, required) The account to assign the address to.\n"
220             "\nExamples:\n"
221             + HelpExampleCli("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"tabby\"")
222             + HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"tabby\"")
223         );
224
225     CBitcoinAddress address(params[0].get_str());
226     if (!address.IsValid())
227         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
228
229
230     string strAccount;
231     if (params.size() > 1)
232         strAccount = AccountFromValue(params[1]);
233
234     // Only add the account if the address is yours.
235     if (IsMine(*pwalletMain, address.Get()))
236     {
237         // Detect when changing the account of an address that is the 'unused current key' of another account:
238         if (pwalletMain->mapAddressBook.count(address.Get()))
239         {
240             string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name;
241             if (address == GetAccountAddress(strOldAccount))
242                 GetAccountAddress(strOldAccount, true);
243         }
244         pwalletMain->SetAddressBook(address.Get(), strAccount, "receive");
245     }
246     else
247         throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
248
249     return Value::null;
250 }
251
252
253 Value getaccount(const Array& params, bool fHelp)
254 {
255     if (fHelp || params.size() != 1)
256         throw runtime_error(
257             "getaccount \"bitcoinaddress\"\n"
258             "\nReturns the account associated with the given address.\n"
259             "\nArguments:\n"
260             "1. \"bitcoinaddress\"  (string, required) The bitcoin address for account lookup.\n"
261             "\nResult:\n"
262             "\"accountname\"        (string) the account address\n"
263             "\nExamples:\n"
264             + HelpExampleCli("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
265             + HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
266         );
267
268     CBitcoinAddress address(params[0].get_str());
269     if (!address.IsValid())
270         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
271
272     string strAccount;
273     map<CTxDestination, CAddressBookData>::iterator mi = pwalletMain->mapAddressBook.find(address.Get());
274     if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty())
275         strAccount = (*mi).second.name;
276     return strAccount;
277 }
278
279
280 Value getaddressesbyaccount(const Array& params, bool fHelp)
281 {
282     if (fHelp || params.size() != 1)
283         throw runtime_error(
284             "getaddressesbyaccount \"account\"\n"
285             "\nReturns the list of addresses for the given account.\n"
286             "\nArguments:\n"
287             "1. \"account\"  (string, required) The account name.\n"
288             "\nResult:\n"
289             "[                     (json array of string)\n"
290             "  \"bitcoinaddress\"  (string) a bitcoin address associated with the given account\n"
291             "  ,...\n"
292             "]\n"
293             "\nExamples:\n"
294             + HelpExampleCli("getaddressesbyaccount", "\"tabby\"")
295             + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
296         );
297
298     string strAccount = AccountFromValue(params[0]);
299
300     // Find all addresses that have the given account
301     Array ret;
302     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
303     {
304         const CBitcoinAddress& address = item.first;
305         const string& strName = item.second.name;
306         if (strName == strAccount)
307             ret.push_back(address.ToString());
308     }
309     return ret;
310 }
311
312 Value sendtoaddress(const Array& params, bool fHelp)
313 {
314     if (fHelp || params.size() < 2 || params.size() > 4)
315         throw runtime_error(
316             "sendtoaddress \"bitcoinaddress\" amount ( \"comment\" \"comment-to\" )\n"
317             "\nSent an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n"
318             + HelpRequiringPassphrase() +
319             "\nArguments:\n"
320             "1. \"bitcoinaddress\"  (string, required) The bitcoin address to send to.\n"
321             "2. \"amount\"      (numeric, required) The amount in btc to send. eg 0.1\n"
322             "3. \"comment\"     (string, optional) A comment used to store what the transaction is for. \n"
323             "                             This is not part of the transaction, just kept in your wallet.\n"
324             "4. \"comment-to\"  (string, optional) A comment to store the name of the person or organization \n"
325             "                             to which you're sending the transaction. This is not part of the \n"
326             "                             transaction, just kept in your wallet.\n"
327             "\nResult:\n"
328             "\"transactionid\"  (string) The transaction id.\n"
329             "\nExamples:\n"
330             + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
331             + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
332             + HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
333         );
334
335     CBitcoinAddress address(params[0].get_str());
336     if (!address.IsValid())
337         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
338
339     // Amount
340     CAmount nAmount = AmountFromValue(params[1]);
341
342     // Wallet comments
343     CWalletTx wtx;
344     if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
345         wtx.mapValue["comment"] = params[2].get_str();
346     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
347         wtx.mapValue["to"]      = params[3].get_str();
348
349     EnsureWalletIsUnlocked();
350
351     string strError = pwalletMain->SendMoney(address.Get(), nAmount, wtx);
352     if (strError != "")
353         throw JSONRPCError(RPC_WALLET_ERROR, strError);
354
355     return wtx.GetHash().GetHex();
356 }
357
358 Value listaddressgroupings(const Array& params, bool fHelp)
359 {
360     if (fHelp)
361         throw runtime_error(
362             "listaddressgroupings\n"
363             "\nLists groups of addresses which have had their common ownership\n"
364             "made public by common use as inputs or as the resulting change\n"
365             "in past transactions\n"
366             "\nResult:\n"
367             "[\n"
368             "  [\n"
369             "    [\n"
370             "      \"bitcoinaddress\",     (string) The bitcoin address\n"
371             "      amount,                 (numeric) The amount in btc\n"
372             "      \"account\"             (string, optional) The account\n"
373             "    ]\n"
374             "    ,...\n"
375             "  ]\n"
376             "  ,...\n"
377             "]\n"
378             "\nExamples:\n"
379             + HelpExampleCli("listaddressgroupings", "")
380             + HelpExampleRpc("listaddressgroupings", "")
381         );
382
383     Array jsonGroupings;
384     map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
385     BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
386     {
387         Array jsonGrouping;
388         BOOST_FOREACH(CTxDestination address, grouping)
389         {
390             Array addressInfo;
391             addressInfo.push_back(CBitcoinAddress(address).ToString());
392             addressInfo.push_back(ValueFromAmount(balances[address]));
393             {
394                 LOCK(pwalletMain->cs_wallet);
395                 if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end())
396                     addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second.name);
397             }
398             jsonGrouping.push_back(addressInfo);
399         }
400         jsonGroupings.push_back(jsonGrouping);
401     }
402     return jsonGroupings;
403 }
404
405 Value signmessage(const Array& params, bool fHelp)
406 {
407     if (fHelp || params.size() != 2)
408         throw runtime_error(
409             "signmessage \"bitcoinaddress\" \"message\"\n"
410             "\nSign a message with the private key of an address"
411             + HelpRequiringPassphrase() + "\n"
412             "\nArguments:\n"
413             "1. \"bitcoinaddress\"  (string, required) The bitcoin address to use for the private key.\n"
414             "2. \"message\"         (string, required) The message to create a signature of.\n"
415             "\nResult:\n"
416             "\"signature\"          (string) The signature of the message encoded in base 64\n"
417             "\nExamples:\n"
418             "\nUnlock the wallet for 30 seconds\n"
419             + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
420             "\nCreate the signature\n"
421             + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
422             "\nVerify the signature\n"
423             + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
424             "\nAs json rpc\n"
425             + HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"my message\"")
426         );
427
428     EnsureWalletIsUnlocked();
429
430     string strAddress = params[0].get_str();
431     string strMessage = params[1].get_str();
432
433     CBitcoinAddress addr(strAddress);
434     if (!addr.IsValid())
435         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
436
437     CKeyID keyID;
438     if (!addr.GetKeyID(keyID))
439         throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
440
441     CKey key;
442     if (!pwalletMain->GetKey(keyID, key))
443         throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
444
445     CHashWriter ss(SER_GETHASH, 0);
446     ss << strMessageMagic;
447     ss << strMessage;
448
449     vector<unsigned char> vchSig;
450     if (!key.SignCompact(ss.GetHash(), vchSig))
451         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
452
453     return EncodeBase64(&vchSig[0], vchSig.size());
454 }
455
456 Value getreceivedbyaddress(const Array& params, bool fHelp)
457 {
458     if (fHelp || params.size() < 1 || params.size() > 2)
459         throw runtime_error(
460             "getreceivedbyaddress \"bitcoinaddress\" ( minconf )\n"
461             "\nReturns the total amount received by the given bitcoinaddress in transactions with at least minconf confirmations.\n"
462             "\nArguments:\n"
463             "1. \"bitcoinaddress\"  (string, required) The bitcoin address for transactions.\n"
464             "2. minconf             (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
465             "\nResult:\n"
466             "amount   (numeric) The total amount in btc received at this address.\n"
467             "\nExamples:\n"
468             "\nThe amount from transactions with at least 1 confirmation\n"
469             + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"") +
470             "\nThe amount including unconfirmed transactions, zero confirmations\n"
471             + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 0") +
472             "\nThe amount with at least 6 confirmation, very safe\n"
473             + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 6") +
474             "\nAs a json rpc call\n"
475             + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", 6")
476        );
477
478     // Bitcoin address
479     CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
480     if (!address.IsValid())
481         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
482     CScript scriptPubKey = GetScriptForDestination(address.Get());
483     if (!IsMine(*pwalletMain,scriptPubKey))
484         return (double)0.0;
485
486     // Minimum confirmations
487     int nMinDepth = 1;
488     if (params.size() > 1)
489         nMinDepth = params[1].get_int();
490
491     // Tally
492     CAmount nAmount = 0;
493     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
494     {
495         const CWalletTx& wtx = (*it).second;
496         if (wtx.IsCoinBase() || !IsFinalTx(wtx))
497             continue;
498
499         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
500             if (txout.scriptPubKey == scriptPubKey)
501                 if (wtx.GetDepthInMainChain() >= nMinDepth)
502                     nAmount += txout.nValue;
503     }
504
505     return  ValueFromAmount(nAmount);
506 }
507
508
509 Value getreceivedbyaccount(const Array& params, bool fHelp)
510 {
511     if (fHelp || params.size() < 1 || params.size() > 2)
512         throw runtime_error(
513             "getreceivedbyaccount \"account\" ( minconf )\n"
514             "\nReturns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
515             "\nArguments:\n"
516             "1. \"account\"      (string, required) The selected account, may be the default account using \"\".\n"
517             "2. minconf          (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
518             "\nResult:\n"
519             "amount              (numeric) The total amount in btc received for this account.\n"
520             "\nExamples:\n"
521             "\nAmount received by the default account with at least 1 confirmation\n"
522             + HelpExampleCli("getreceivedbyaccount", "\"\"") +
523             "\nAmount received at the tabby account including unconfirmed amounts with zero confirmations\n"
524             + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 0") +
525             "\nThe amount with at least 6 confirmation, very safe\n"
526             + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 6") +
527             "\nAs a json rpc call\n"
528             + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
529         );
530
531     // Minimum confirmations
532     int nMinDepth = 1;
533     if (params.size() > 1)
534         nMinDepth = params[1].get_int();
535
536     // Get the set of pub keys assigned to account
537     string strAccount = AccountFromValue(params[0]);
538     set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount);
539
540     // Tally
541     CAmount nAmount = 0;
542     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
543     {
544         const CWalletTx& wtx = (*it).second;
545         if (wtx.IsCoinBase() || !IsFinalTx(wtx))
546             continue;
547
548         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
549         {
550             CTxDestination address;
551             if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
552                 if (wtx.GetDepthInMainChain() >= nMinDepth)
553                     nAmount += txout.nValue;
554         }
555     }
556
557     return (double)nAmount / (double)COIN;
558 }
559
560
561 CAmount GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter)
562 {
563     CAmount nBalance = 0;
564
565     // Tally wallet transactions
566     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
567     {
568         const CWalletTx& wtx = (*it).second;
569         if (!IsFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
570             continue;
571
572         CAmount nReceived, nSent, nFee;
573         wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter);
574
575         if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
576             nBalance += nReceived;
577         nBalance -= nSent + nFee;
578     }
579
580     // Tally internal accounting entries
581     nBalance += walletdb.GetAccountCreditDebit(strAccount);
582
583     return nBalance;
584 }
585
586 CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter)
587 {
588     CWalletDB walletdb(pwalletMain->strWalletFile);
589     return GetAccountBalance(walletdb, strAccount, nMinDepth, filter);
590 }
591
592
593 Value getbalance(const Array& params, bool fHelp)
594 {
595     if (fHelp || params.size() > 3)
596         throw runtime_error(
597             "getbalance ( \"account\" minconf includeWatchonly )\n"
598             "\nIf account is not specified, returns the server's total available balance.\n"
599             "If account is specified, returns the balance in the account.\n"
600             "Note that the account \"\" is not the same as leaving the parameter out.\n"
601             "The server total may be different to the balance in the default \"\" account.\n"
602             "\nArguments:\n"
603             "1. \"account\"      (string, optional) The selected account, or \"*\" for entire wallet. It may be the default account using \"\".\n"
604             "2. minconf          (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
605             "3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n"
606             "\nResult:\n"
607             "amount              (numeric) The total amount in btc received for this account.\n"
608             "\nExamples:\n"
609             "\nThe total amount in the server across all accounts\n"
610             + HelpExampleCli("getbalance", "") +
611             "\nThe total amount in the server across all accounts, with at least 5 confirmations\n"
612             + HelpExampleCli("getbalance", "\"*\" 6") +
613             "\nThe total amount in the default account with at least 1 confirmation\n"
614             + HelpExampleCli("getbalance", "\"\"") +
615             "\nThe total amount in the account named tabby with at least 6 confirmations\n"
616             + HelpExampleCli("getbalance", "\"tabby\" 6") +
617             "\nAs a json rpc call\n"
618             + HelpExampleRpc("getbalance", "\"tabby\", 6")
619         );
620
621     if (params.size() == 0)
622         return  ValueFromAmount(pwalletMain->GetBalance());
623
624     int nMinDepth = 1;
625     if (params.size() > 1)
626         nMinDepth = params[1].get_int();
627     isminefilter filter = ISMINE_SPENDABLE;
628     if(params.size() > 2)
629         if(params[2].get_bool())
630             filter = filter | ISMINE_WATCH_ONLY;
631
632     if (params[0].get_str() == "*") {
633         // Calculate total balance a different way from GetBalance()
634         // (GetBalance() sums up all unspent TxOuts)
635         // getbalance and getbalance '*' 0 should return the same number
636         CAmount nBalance = 0;
637         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
638         {
639             const CWalletTx& wtx = (*it).second;
640             if (!wtx.IsTrusted() || wtx.GetBlocksToMaturity() > 0)
641                 continue;
642
643             CAmount allFee;
644             string strSentAccount;
645             list<COutputEntry> listReceived;
646             list<COutputEntry> listSent;
647             wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
648             if (wtx.GetDepthInMainChain() >= nMinDepth)
649             {
650                 BOOST_FOREACH(const COutputEntry& r, listReceived)
651                     nBalance += r.amount;
652             }
653             BOOST_FOREACH(const COutputEntry& s, listSent)
654                 nBalance -= s.amount;
655             nBalance -= allFee;
656         }
657         return  ValueFromAmount(nBalance);
658     }
659
660     string strAccount = AccountFromValue(params[0]);
661
662     CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, filter);
663
664     return ValueFromAmount(nBalance);
665 }
666
667 Value getunconfirmedbalance(const Array &params, bool fHelp)
668 {
669     if (fHelp || params.size() > 0)
670         throw runtime_error(
671                 "getunconfirmedbalance\n"
672                 "Returns the server's total unconfirmed balance\n");
673     return ValueFromAmount(pwalletMain->GetUnconfirmedBalance());
674 }
675
676
677 Value movecmd(const Array& params, bool fHelp)
678 {
679     if (fHelp || params.size() < 3 || params.size() > 5)
680         throw runtime_error(
681             "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
682             "\nMove a specified amount from one account in your wallet to another.\n"
683             "\nArguments:\n"
684             "1. \"fromaccount\"   (string, required) The name of the account to move funds from. May be the default account using \"\".\n"
685             "2. \"toaccount\"     (string, required) The name of the account to move funds to. May be the default account using \"\".\n"
686             "3. minconf           (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
687             "4. \"comment\"       (string, optional) An optional comment, stored in the wallet only.\n"
688             "\nResult:\n"
689             "true|false           (boolean) true if successfull.\n"
690             "\nExamples:\n"
691             "\nMove 0.01 btc from the default account to the account named tabby\n"
692             + HelpExampleCli("move", "\"\" \"tabby\" 0.01") +
693             "\nMove 0.01 btc timotei to akiko with a comment and funds have 6 confirmations\n"
694             + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") +
695             "\nAs a json rpc call\n"
696             + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
697         );
698
699     string strFrom = AccountFromValue(params[0]);
700     string strTo = AccountFromValue(params[1]);
701     CAmount nAmount = AmountFromValue(params[2]);
702     if (params.size() > 3)
703         // unused parameter, used to be nMinDepth, keep type-checking it though
704         (void)params[3].get_int();
705     string strComment;
706     if (params.size() > 4)
707         strComment = params[4].get_str();
708
709     CWalletDB walletdb(pwalletMain->strWalletFile);
710     if (!walletdb.TxnBegin())
711         throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
712
713     int64_t nNow = GetAdjustedTime();
714
715     // Debit
716     CAccountingEntry debit;
717     debit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
718     debit.strAccount = strFrom;
719     debit.nCreditDebit = -nAmount;
720     debit.nTime = nNow;
721     debit.strOtherAccount = strTo;
722     debit.strComment = strComment;
723     walletdb.WriteAccountingEntry(debit);
724
725     // Credit
726     CAccountingEntry credit;
727     credit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
728     credit.strAccount = strTo;
729     credit.nCreditDebit = nAmount;
730     credit.nTime = nNow;
731     credit.strOtherAccount = strFrom;
732     credit.strComment = strComment;
733     walletdb.WriteAccountingEntry(credit);
734
735     if (!walletdb.TxnCommit())
736         throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
737
738     return true;
739 }
740
741
742 Value sendfrom(const Array& params, bool fHelp)
743 {
744     if (fHelp || params.size() < 3 || params.size() > 6)
745         throw runtime_error(
746             "sendfrom \"fromaccount\" \"tobitcoinaddress\" amount ( minconf \"comment\" \"comment-to\" )\n"
747             "\nSent an amount from an account to a bitcoin address.\n"
748             "The amount is a real and is rounded to the nearest 0.00000001."
749             + HelpRequiringPassphrase() + "\n"
750             "\nArguments:\n"
751             "1. \"fromaccount\"       (string, required) The name of the account to send funds from. May be the default account using \"\".\n"
752             "2. \"tobitcoinaddress\"  (string, required) The bitcoin address to send funds to.\n"
753             "3. amount                (numeric, required) The amount in btc. (transaction fee is added on top).\n"
754             "4. minconf               (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
755             "5. \"comment\"           (string, optional) A comment used to store what the transaction is for. \n"
756             "                                     This is not part of the transaction, just kept in your wallet.\n"
757             "6. \"comment-to\"        (string, optional) An optional comment to store the name of the person or organization \n"
758             "                                     to which you're sending the transaction. This is not part of the transaction, \n"
759             "                                     it is just kept in your wallet.\n"
760             "\nResult:\n"
761             "\"transactionid\"        (string) The transaction id.\n"
762             "\nExamples:\n"
763             "\nSend 0.01 btc from the default account to the address, must have at least 1 confirmation\n"
764             + HelpExampleCli("sendfrom", "\"\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") +
765             "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
766             + HelpExampleCli("sendfrom", "\"tabby\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01 6 \"donation\" \"seans outpost\"") +
767             "\nAs a json rpc call\n"
768             + HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
769         );
770
771     string strAccount = AccountFromValue(params[0]);
772     CBitcoinAddress address(params[1].get_str());
773     if (!address.IsValid())
774         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
775     CAmount nAmount = AmountFromValue(params[2]);
776     int nMinDepth = 1;
777     if (params.size() > 3)
778         nMinDepth = params[3].get_int();
779
780     CWalletTx wtx;
781     wtx.strFromAccount = strAccount;
782     if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
783         wtx.mapValue["comment"] = params[4].get_str();
784     if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
785         wtx.mapValue["to"]      = params[5].get_str();
786
787     EnsureWalletIsUnlocked();
788
789     // Check funds
790     CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
791     if (nAmount > nBalance)
792         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
793
794     // Send
795     string strError = pwalletMain->SendMoney(address.Get(), nAmount, wtx);
796     if (strError != "")
797         throw JSONRPCError(RPC_WALLET_ERROR, strError);
798
799     return wtx.GetHash().GetHex();
800 }
801
802
803 Value sendmany(const Array& params, bool fHelp)
804 {
805     if (fHelp || params.size() < 2 || params.size() > 4)
806         throw runtime_error(
807             "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" )\n"
808             "\nSend multiple times. Amounts are double-precision floating point numbers."
809             + HelpRequiringPassphrase() + "\n"
810             "\nArguments:\n"
811             "1. \"fromaccount\"         (string, required) The account to send the funds from, can be \"\" for the default account\n"
812             "2. \"amounts\"             (string, required) A json object with addresses and amounts\n"
813             "    {\n"
814             "      \"address\":amount   (numeric) The bitcoin address is the key, the numeric amount in btc is the value\n"
815             "      ,...\n"
816             "    }\n"
817             "3. minconf                 (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
818             "4. \"comment\"             (string, optional) A comment\n"
819             "\nResult:\n"
820             "\"transactionid\"          (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
821             "                                    the number of addresses.\n"
822             "\nExamples:\n"
823             "\nSend two amounts to two different addresses:\n"
824             + HelpExampleCli("sendmany", "\"tabby\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
825             "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
826             + HelpExampleCli("sendmany", "\"tabby\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
827             "\nAs a json rpc call\n"
828             + HelpExampleRpc("sendmany", "\"tabby\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
829         );
830
831     string strAccount = AccountFromValue(params[0]);
832     Object sendTo = params[1].get_obj();
833     int nMinDepth = 1;
834     if (params.size() > 2)
835         nMinDepth = params[2].get_int();
836
837     CWalletTx wtx;
838     wtx.strFromAccount = strAccount;
839     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
840         wtx.mapValue["comment"] = params[3].get_str();
841
842     set<CBitcoinAddress> setAddress;
843     vector<pair<CScript, CAmount> > vecSend;
844
845     CAmount totalAmount = 0;
846     BOOST_FOREACH(const Pair& s, sendTo)
847     {
848         CBitcoinAddress address(s.name_);
849         if (!address.IsValid())
850             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_);
851
852         if (setAddress.count(address))
853             throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
854         setAddress.insert(address);
855
856         CScript scriptPubKey = GetScriptForDestination(address.Get());
857         CAmount nAmount = AmountFromValue(s.value_);
858         totalAmount += nAmount;
859
860         vecSend.push_back(make_pair(scriptPubKey, nAmount));
861     }
862
863     EnsureWalletIsUnlocked();
864
865     // Check funds
866     CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
867     if (totalAmount > nBalance)
868         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
869
870     // Send
871     CReserveKey keyChange(pwalletMain);
872     CAmount nFeeRequired = 0;
873     string strFailReason;
874     bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, strFailReason);
875     if (!fCreated)
876         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
877     if (!pwalletMain->CommitTransaction(wtx, keyChange))
878         throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed");
879
880     return wtx.GetHash().GetHex();
881 }
882
883 // Defined in rpcmisc.cpp
884 extern CScript _createmultisig_redeemScript(const Array& params);
885
886 Value addmultisigaddress(const Array& params, bool fHelp)
887 {
888     if (fHelp || params.size() < 2 || params.size() > 3)
889     {
890         string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
891             "\nAdd a nrequired-to-sign multisignature address to the wallet.\n"
892             "Each key is a Bitcoin address or hex-encoded public key.\n"
893             "If 'account' is specified, assign address to that account.\n"
894
895             "\nArguments:\n"
896             "1. nrequired        (numeric, required) The number of required signatures out of the n keys or addresses.\n"
897             "2. \"keysobject\"   (string, required) A json array of bitcoin addresses or hex-encoded public keys\n"
898             "     [\n"
899             "       \"address\"  (string) bitcoin address or hex-encoded public key\n"
900             "       ...,\n"
901             "     ]\n"
902             "3. \"account\"      (string, optional) An account to assign the addresses to.\n"
903
904             "\nResult:\n"
905             "\"bitcoinaddress\"  (string) A bitcoin address associated with the keys.\n"
906
907             "\nExamples:\n"
908             "\nAdd a multisig address from 2 addresses\n"
909             + HelpExampleCli("addmultisigaddress", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
910             "\nAs json rpc call\n"
911             + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
912         ;
913         throw runtime_error(msg);
914     }
915
916     string strAccount;
917     if (params.size() > 2)
918         strAccount = AccountFromValue(params[2]);
919
920     // Construct using pay-to-script-hash:
921     CScript inner = _createmultisig_redeemScript(params);
922     CScriptID innerID(inner);
923     pwalletMain->AddCScript(inner);
924
925     pwalletMain->SetAddressBook(innerID, strAccount, "send");
926     return CBitcoinAddress(innerID).ToString();
927 }
928
929
930 struct tallyitem
931 {
932     CAmount nAmount;
933     int nConf;
934     vector<uint256> txids;
935     bool fIsWatchonly;
936     tallyitem()
937     {
938         nAmount = 0;
939         nConf = std::numeric_limits<int>::max();
940         fIsWatchonly = false;
941     }
942 };
943
944 Value ListReceived(const Array& params, bool fByAccounts)
945 {
946     // Minimum confirmations
947     int nMinDepth = 1;
948     if (params.size() > 0)
949         nMinDepth = params[0].get_int();
950
951     // Whether to include empty accounts
952     bool fIncludeEmpty = false;
953     if (params.size() > 1)
954         fIncludeEmpty = params[1].get_bool();
955
956     isminefilter filter = ISMINE_SPENDABLE;
957     if(params.size() > 2)
958         if(params[2].get_bool())
959             filter = filter | ISMINE_WATCH_ONLY;
960
961     // Tally
962     map<CBitcoinAddress, tallyitem> mapTally;
963     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
964     {
965         const CWalletTx& wtx = (*it).second;
966
967         if (wtx.IsCoinBase() || !IsFinalTx(wtx))
968             continue;
969
970         int nDepth = wtx.GetDepthInMainChain();
971         if (nDepth < nMinDepth)
972             continue;
973
974         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
975         {
976             CTxDestination address;
977             if (!ExtractDestination(txout.scriptPubKey, address))
978                 continue;
979
980             isminefilter mine = IsMine(*pwalletMain, address);
981             if(!(mine & filter))
982                 continue;
983
984             tallyitem& item = mapTally[address];
985             item.nAmount += txout.nValue;
986             item.nConf = min(item.nConf, nDepth);
987             item.txids.push_back(wtx.GetHash());
988             if (mine & ISMINE_WATCH_ONLY)
989                 item.fIsWatchonly = true;
990         }
991     }
992
993     // Reply
994     Array ret;
995     map<string, tallyitem> mapAccountTally;
996     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
997     {
998         const CBitcoinAddress& address = item.first;
999         const string& strAccount = item.second.name;
1000         map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
1001         if (it == mapTally.end() && !fIncludeEmpty)
1002             continue;
1003
1004         CAmount nAmount = 0;
1005         int nConf = std::numeric_limits<int>::max();
1006         bool fIsWatchonly = false;
1007         if (it != mapTally.end())
1008         {
1009             nAmount = (*it).second.nAmount;
1010             nConf = (*it).second.nConf;
1011             fIsWatchonly = (*it).second.fIsWatchonly;
1012         }
1013
1014         if (fByAccounts)
1015         {
1016             tallyitem& item = mapAccountTally[strAccount];
1017             item.nAmount += nAmount;
1018             item.nConf = min(item.nConf, nConf);
1019             item.fIsWatchonly = fIsWatchonly;
1020         }
1021         else
1022         {
1023             Object obj;
1024             if(fIsWatchonly)
1025                 obj.push_back(Pair("involvesWatchonly", true));
1026             obj.push_back(Pair("address",       address.ToString()));
1027             obj.push_back(Pair("account",       strAccount));
1028             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1029             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1030             Array transactions;
1031             if (it != mapTally.end())
1032             {
1033                 BOOST_FOREACH(const uint256& item, (*it).second.txids)
1034                 {
1035                     transactions.push_back(item.GetHex());
1036                 }
1037             }
1038             obj.push_back(Pair("txids", transactions));
1039             ret.push_back(obj);
1040         }
1041     }
1042
1043     if (fByAccounts)
1044     {
1045         for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
1046         {
1047             CAmount nAmount = (*it).second.nAmount;
1048             int nConf = (*it).second.nConf;
1049             Object obj;
1050             if((*it).second.fIsWatchonly)
1051                 obj.push_back(Pair("involvesWatchonly", true));
1052             obj.push_back(Pair("account",       (*it).first));
1053             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
1054             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
1055             ret.push_back(obj);
1056         }
1057     }
1058
1059     return ret;
1060 }
1061
1062 Value listreceivedbyaddress(const Array& params, bool fHelp)
1063 {
1064     if (fHelp || params.size() > 3)
1065         throw runtime_error(
1066             "listreceivedbyaddress ( minconf includeempty includeWatchonly)\n"
1067             "\nList balances by receiving address.\n"
1068             "\nArguments:\n"
1069             "1. minconf       (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1070             "2. includeempty  (numeric, optional, dafault=false) Whether to include addresses that haven't received any payments.\n"
1071             "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1072
1073             "\nResult:\n"
1074             "[\n"
1075             "  {\n"
1076             "    \"involvesWatchonly\" : \"true\",    (bool) Only returned if imported addresses were involved in transaction\n"
1077             "    \"address\" : \"receivingaddress\",  (string) The receiving address\n"
1078             "    \"account\" : \"accountname\",       (string) The account of the receiving address. The default account is \"\".\n"
1079             "    \"amount\" : x.xxx,                  (numeric) The total amount in btc received by the address\n"
1080             "    \"confirmations\" : n                (numeric) The number of confirmations of the most recent transaction included\n"
1081             "  }\n"
1082             "  ,...\n"
1083             "]\n"
1084
1085             "\nExamples:\n"
1086             + HelpExampleCli("listreceivedbyaddress", "")
1087             + HelpExampleCli("listreceivedbyaddress", "6 true")
1088             + HelpExampleRpc("listreceivedbyaddress", "6, true, true")
1089         );
1090
1091     return ListReceived(params, false);
1092 }
1093
1094 Value listreceivedbyaccount(const Array& params, bool fHelp)
1095 {
1096     if (fHelp || params.size() > 3)
1097         throw runtime_error(
1098             "listreceivedbyaccount ( minconf includeempty includeWatchonly)\n"
1099             "\nList balances by account.\n"
1100             "\nArguments:\n"
1101             "1. minconf      (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
1102             "2. includeempty (boolean, optional, default=false) Whether to include accounts that haven't received any payments.\n"
1103             "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
1104
1105             "\nResult:\n"
1106             "[\n"
1107             "  {\n"
1108             "    \"involvesWatchonly\" : \"true\",    (bool) Only returned if imported addresses were involved in transaction\n"
1109             "    \"account\" : \"accountname\",  (string) The account name of the receiving account\n"
1110             "    \"amount\" : x.xxx,             (numeric) The total amount received by addresses with this account\n"
1111             "    \"confirmations\" : n           (numeric) The number of confirmations of the most recent transaction included\n"
1112             "  }\n"
1113             "  ,...\n"
1114             "]\n"
1115
1116             "\nExamples:\n"
1117             + HelpExampleCli("listreceivedbyaccount", "")
1118             + HelpExampleCli("listreceivedbyaccount", "6 true")
1119             + HelpExampleRpc("listreceivedbyaccount", "6, true, true")
1120         );
1121
1122     return ListReceived(params, true);
1123 }
1124
1125 static void MaybePushAddress(Object & entry, const CTxDestination &dest)
1126 {
1127     CBitcoinAddress addr;
1128     if (addr.Set(dest))
1129         entry.push_back(Pair("address", addr.ToString()));
1130 }
1131
1132 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret, const isminefilter& filter)
1133 {
1134     CAmount nFee;
1135     string strSentAccount;
1136     list<COutputEntry> listReceived;
1137     list<COutputEntry> listSent;
1138
1139     wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter);
1140
1141     bool fAllAccounts = (strAccount == string("*"));
1142     bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
1143
1144     // Sent
1145     if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1146     {
1147         BOOST_FOREACH(const COutputEntry& s, listSent)
1148         {
1149             Object entry;
1150             if(involvesWatchonly || (::IsMine(*pwalletMain, s.destination) & ISMINE_WATCH_ONLY))
1151                 entry.push_back(Pair("involvesWatchonly", true));
1152             entry.push_back(Pair("account", strSentAccount));
1153             MaybePushAddress(entry, s.destination);
1154             entry.push_back(Pair("category", "send"));
1155             entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
1156             entry.push_back(Pair("vout", s.vout));
1157             entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1158             if (fLong)
1159                 WalletTxToJSON(wtx, entry);
1160             ret.push_back(entry);
1161         }
1162     }
1163
1164     // Received
1165     if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1166     {
1167         BOOST_FOREACH(const COutputEntry& r, listReceived)
1168         {
1169             string account;
1170             if (pwalletMain->mapAddressBook.count(r.destination))
1171                 account = pwalletMain->mapAddressBook[r.destination].name;
1172             if (fAllAccounts || (account == strAccount))
1173             {
1174                 Object entry;
1175                 if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
1176                     entry.push_back(Pair("involvesWatchonly", true));
1177                 entry.push_back(Pair("account", account));
1178                 MaybePushAddress(entry, r.destination);
1179                 if (wtx.IsCoinBase())
1180                 {
1181                     if (wtx.GetDepthInMainChain() < 1)
1182                         entry.push_back(Pair("category", "orphan"));
1183                     else if (wtx.GetBlocksToMaturity() > 0)
1184                         entry.push_back(Pair("category", "immature"));
1185                     else
1186                         entry.push_back(Pair("category", "generate"));
1187                 }
1188                 else
1189                 {
1190                     entry.push_back(Pair("category", "receive"));
1191                 }
1192                 entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
1193                 entry.push_back(Pair("vout", r.vout));
1194                 if (fLong)
1195                     WalletTxToJSON(wtx, entry);
1196                 ret.push_back(entry);
1197             }
1198         }
1199     }
1200 }
1201
1202 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1203 {
1204     bool fAllAccounts = (strAccount == string("*"));
1205
1206     if (fAllAccounts || acentry.strAccount == strAccount)
1207     {
1208         Object entry;
1209         entry.push_back(Pair("account", acentry.strAccount));
1210         entry.push_back(Pair("category", "move"));
1211         entry.push_back(Pair("time", acentry.nTime));
1212         entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1213         entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1214         entry.push_back(Pair("comment", acentry.strComment));
1215         ret.push_back(entry);
1216     }
1217 }
1218
1219 Value listtransactions(const Array& params, bool fHelp)
1220 {
1221     if (fHelp || params.size() > 4)
1222         throw runtime_error(
1223             "listtransactions ( \"account\" count from includeWatchonly)\n"
1224             "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n"
1225             "\nArguments:\n"
1226             "1. \"account\"    (string, optional) The account name. If not included, it will list all transactions for all accounts.\n"
1227             "                                     If \"\" is set, it will list transactions for the default account.\n"
1228             "2. count          (numeric, optional, default=10) The number of transactions to return\n"
1229             "3. from           (numeric, optional, default=0) The number of transactions to skip\n"
1230             "4. includeWatchonly (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')\n"
1231             "\nResult:\n"
1232             "[\n"
1233             "  {\n"
1234             "    \"account\":\"accountname\",       (string) The account name associated with the transaction. \n"
1235             "                                                It will be \"\" for the default account.\n"
1236             "    \"address\":\"bitcoinaddress\",    (string) The bitcoin address of the transaction. Not present for \n"
1237             "                                                move transactions (category = move).\n"
1238             "    \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n"
1239             "                                                transaction between accounts, and not associated with an address,\n"
1240             "                                                transaction id or block. 'send' and 'receive' transactions are \n"
1241             "                                                associated with an address, transaction id and block details\n"
1242             "    \"amount\": x.xxx,          (numeric) The amount in btc. This is negative for the 'send' category, and for the\n"
1243             "                                         'move' category for moves outbound. It is positive for the 'receive' category,\n"
1244             "                                         and for the 'move' category for inbound funds.\n"
1245             "    \"vout\" : n,               (numeric) the vout value\n"
1246             "    \"fee\": x.xxx,             (numeric) The amount of the fee in btc. This is negative and only available for the \n"
1247             "                                         'send' category of transactions.\n"
1248             "    \"confirmations\": n,       (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
1249             "                                         'receive' category of transactions.\n"
1250             "    \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
1251             "                                          category of transactions.\n"
1252             "    \"blockindex\": n,          (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n"
1253             "                                          category of transactions.\n"
1254             "    \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1255             "    \"time\": xxx,              (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
1256             "    \"timereceived\": xxx,      (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
1257             "                                          for 'send' and 'receive' category of transactions.\n"
1258             "    \"comment\": \"...\",       (string) If a comment is associated with the transaction.\n"
1259             "    \"otheraccount\": \"accountname\",  (string) For the 'move' category of transactions, the account the funds came \n"
1260             "                                          from (for receiving funds, positive amounts), or went to (for sending funds,\n"
1261             "                                          negative amounts).\n"
1262             "  }\n"
1263             "]\n"
1264
1265             "\nExamples:\n"
1266             "\nList the most recent 10 transactions in the systems\n"
1267             + HelpExampleCli("listtransactions", "") +
1268             "\nList the most recent 10 transactions for the tabby account\n"
1269             + HelpExampleCli("listtransactions", "\"tabby\"") +
1270             "\nList transactions 100 to 120 from the tabby account\n"
1271             + HelpExampleCli("listtransactions", "\"tabby\" 20 100") +
1272             "\nAs a json rpc call\n"
1273             + HelpExampleRpc("listtransactions", "\"tabby\", 20, 100")
1274         );
1275
1276     string strAccount = "*";
1277     if (params.size() > 0)
1278         strAccount = params[0].get_str();
1279     int nCount = 10;
1280     if (params.size() > 1)
1281         nCount = params[1].get_int();
1282     int nFrom = 0;
1283     if (params.size() > 2)
1284         nFrom = params[2].get_int();
1285     isminefilter filter = ISMINE_SPENDABLE;
1286     if(params.size() > 3)
1287         if(params[3].get_bool())
1288             filter = filter | ISMINE_WATCH_ONLY;
1289
1290     if (nCount < 0)
1291         throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
1292     if (nFrom < 0)
1293         throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
1294
1295     Array ret;
1296
1297     std::list<CAccountingEntry> acentries;
1298     CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount);
1299
1300     // iterate backwards until we have nCount items to return:
1301     for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
1302     {
1303         CWalletTx *const pwtx = (*it).second.first;
1304         if (pwtx != 0)
1305             ListTransactions(*pwtx, strAccount, 0, true, ret, filter);
1306         CAccountingEntry *const pacentry = (*it).second.second;
1307         if (pacentry != 0)
1308             AcentryToJSON(*pacentry, strAccount, ret);
1309
1310         if ((int)ret.size() >= (nCount+nFrom)) break;
1311     }
1312     // ret is newest to oldest
1313
1314     if (nFrom > (int)ret.size())
1315         nFrom = ret.size();
1316     if ((nFrom + nCount) > (int)ret.size())
1317         nCount = ret.size() - nFrom;
1318     Array::iterator first = ret.begin();
1319     std::advance(first, nFrom);
1320     Array::iterator last = ret.begin();
1321     std::advance(last, nFrom+nCount);
1322
1323     if (last != ret.end()) ret.erase(last, ret.end());
1324     if (first != ret.begin()) ret.erase(ret.begin(), first);
1325
1326     std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1327
1328     return ret;
1329 }
1330
1331 Value listaccounts(const Array& params, bool fHelp)
1332 {
1333     if (fHelp || params.size() > 2)
1334         throw runtime_error(
1335             "listaccounts ( minconf includeWatchonly)\n"
1336             "\nReturns Object that has account names as keys, account balances as values.\n"
1337             "\nArguments:\n"
1338             "1. minconf          (numeric, optional, default=1) Only onclude transactions with at least this many confirmations\n"
1339             "2. includeWatchonly (bool, optional, default=false) Include balances in watchonly addresses (see 'importaddress')\n"
1340             "\nResult:\n"
1341             "{                      (json object where keys are account names, and values are numeric balances\n"
1342             "  \"account\": x.xxx,  (numeric) The property name is the account name, and the value is the total balance for the account.\n"
1343             "  ...\n"
1344             "}\n"
1345             "\nExamples:\n"
1346             "\nList account balances where there at least 1 confirmation\n"
1347             + HelpExampleCli("listaccounts", "") +
1348             "\nList account balances including zero confirmation transactions\n"
1349             + HelpExampleCli("listaccounts", "0") +
1350             "\nList account balances for 6 or more confirmations\n"
1351             + HelpExampleCli("listaccounts", "6") +
1352             "\nAs json rpc call\n"
1353             + HelpExampleRpc("listaccounts", "6")
1354         );
1355
1356     int nMinDepth = 1;
1357     if (params.size() > 0)
1358         nMinDepth = params[0].get_int();
1359     isminefilter includeWatchonly = ISMINE_SPENDABLE;
1360     if(params.size() > 1)
1361         if(params[1].get_bool())
1362             includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY;
1363
1364     map<string, CAmount> mapAccountBalances;
1365     BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) {
1366         if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me
1367             mapAccountBalances[entry.second.name] = 0;
1368     }
1369
1370     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1371     {
1372         const CWalletTx& wtx = (*it).second;
1373         CAmount nFee;
1374         string strSentAccount;
1375         list<COutputEntry> listReceived;
1376         list<COutputEntry> listSent;
1377         int nDepth = wtx.GetDepthInMainChain();
1378         if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
1379             continue;
1380         wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
1381         mapAccountBalances[strSentAccount] -= nFee;
1382         BOOST_FOREACH(const COutputEntry& s, listSent)
1383             mapAccountBalances[strSentAccount] -= s.amount;
1384         if (nDepth >= nMinDepth)
1385         {
1386             BOOST_FOREACH(const COutputEntry& r, listReceived)
1387                 if (pwalletMain->mapAddressBook.count(r.destination))
1388                     mapAccountBalances[pwalletMain->mapAddressBook[r.destination].name] += r.amount;
1389                 else
1390                     mapAccountBalances[""] += r.amount;
1391         }
1392     }
1393
1394     list<CAccountingEntry> acentries;
1395     CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1396     BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1397         mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1398
1399     Object ret;
1400     BOOST_FOREACH(const PAIRTYPE(string, CAmount)& accountBalance, mapAccountBalances) {
1401         ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1402     }
1403     return ret;
1404 }
1405
1406 Value listsinceblock(const Array& params, bool fHelp)
1407 {
1408     if (fHelp)
1409         throw runtime_error(
1410             "listsinceblock ( \"blockhash\" target-confirmations includeWatchonly)\n"
1411             "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n"
1412             "\nArguments:\n"
1413             "1. \"blockhash\"   (string, optional) The block hash to list transactions since\n"
1414             "2. target-confirmations:    (numeric, optional) The confirmations required, must be 1 or more\n"
1415             "3. includeWatchonly:        (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')"
1416             "\nResult:\n"
1417             "{\n"
1418             "  \"transactions\": [\n"
1419             "    \"account\":\"accountname\",       (string) The account name associated with the transaction. Will be \"\" for the default account.\n"
1420             "    \"address\":\"bitcoinaddress\",    (string) The bitcoin address of the transaction. Not present for move transactions (category = move).\n"
1421             "    \"category\":\"send|receive\",     (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
1422             "    \"amount\": x.xxx,          (numeric) The amount in btc. This is negative for the 'send' category, and for the 'move' category for moves \n"
1423             "                                          outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
1424             "    \"vout\" : n,               (numeric) the vout value\n"
1425             "    \"fee\": x.xxx,             (numeric) The amount of the fee in btc. This is negative and only available for the 'send' category of transactions.\n"
1426             "    \"confirmations\": n,       (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
1427             "    \"blockhash\": \"hashvalue\",     (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1428             "    \"blockindex\": n,          (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
1429             "    \"blocktime\": xxx,         (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
1430             "    \"txid\": \"transactionid\",  (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
1431             "    \"time\": xxx,              (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
1432             "    \"timereceived\": xxx,      (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
1433             "    \"comment\": \"...\",       (string) If a comment is associated with the transaction.\n"
1434             "    \"to\": \"...\",            (string) If a comment to is associated with the transaction.\n"
1435              "  ],\n"
1436             "  \"lastblock\": \"lastblockhash\"     (string) The hash of the last block\n"
1437             "}\n"
1438             "\nExamples:\n"
1439             + HelpExampleCli("listsinceblock", "")
1440             + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
1441             + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
1442         );
1443
1444     CBlockIndex *pindex = NULL;
1445     int target_confirms = 1;
1446     isminefilter filter = ISMINE_SPENDABLE;
1447
1448     if (params.size() > 0)
1449     {
1450         uint256 blockId = 0;
1451
1452         blockId.SetHex(params[0].get_str());
1453         BlockMap::iterator it = mapBlockIndex.find(blockId);
1454         if (it != mapBlockIndex.end())
1455             pindex = it->second;
1456     }
1457
1458     if (params.size() > 1)
1459     {
1460         target_confirms = params[1].get_int();
1461
1462         if (target_confirms < 1)
1463             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
1464     }
1465
1466     if(params.size() > 2)
1467         if(params[2].get_bool())
1468             filter = filter | ISMINE_WATCH_ONLY;
1469
1470     int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
1471
1472     Array transactions;
1473
1474     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1475     {
1476         CWalletTx tx = (*it).second;
1477
1478         if (depth == -1 || tx.GetDepthInMainChain() < depth)
1479             ListTransactions(tx, "*", 0, true, transactions, filter);
1480     }
1481
1482     CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
1483     uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : 0;
1484
1485     Object ret;
1486     ret.push_back(Pair("transactions", transactions));
1487     ret.push_back(Pair("lastblock", lastblock.GetHex()));
1488
1489     return ret;
1490 }
1491
1492 Value gettransaction(const Array& params, bool fHelp)
1493 {
1494     if (fHelp || params.size() < 1 || params.size() > 2)
1495         throw runtime_error(
1496             "gettransaction \"txid\" ( includeWatchonly )\n"
1497             "\nGet detailed information about in-wallet transaction <txid>\n"
1498             "\nArguments:\n"
1499             "1. \"txid\"    (string, required) The transaction id\n"
1500             "2. \"includeWatchonly\"    (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n"
1501             "\nResult:\n"
1502             "{\n"
1503             "  \"amount\" : x.xxx,        (numeric) The transaction amount in btc\n"
1504             "  \"confirmations\" : n,     (numeric) The number of confirmations\n"
1505             "  \"blockhash\" : \"hash\",  (string) The block hash\n"
1506             "  \"blockindex\" : xx,       (numeric) The block index\n"
1507             "  \"blocktime\" : ttt,       (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
1508             "  \"txid\" : \"transactionid\",   (string) The transaction id.\n"
1509             "  \"time\" : ttt,            (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
1510             "  \"timereceived\" : ttt,    (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
1511             "  \"details\" : [\n"
1512             "    {\n"
1513             "      \"account\" : \"accountname\",  (string) The account name involved in the transaction, can be \"\" for the default account.\n"
1514             "      \"address\" : \"bitcoinaddress\",   (string) The bitcoin address involved in the transaction\n"
1515             "      \"category\" : \"send|receive\",    (string) The category, either 'send' or 'receive'\n"
1516             "      \"amount\" : x.xxx                  (numeric) The amount in btc\n"
1517             "      \"vout\" : n,                       (numeric) the vout value\n"
1518             "    }\n"
1519             "    ,...\n"
1520             "  ],\n"
1521             "  \"hex\" : \"data\"         (string) Raw data for transaction\n"
1522             "}\n"
1523
1524             "\nExamples:\n"
1525             + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1526             + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
1527             + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
1528         );
1529
1530     uint256 hash;
1531     hash.SetHex(params[0].get_str());
1532
1533     isminefilter filter = ISMINE_SPENDABLE;
1534     if(params.size() > 1)
1535         if(params[1].get_bool())
1536             filter = filter | ISMINE_WATCH_ONLY;
1537
1538     Object entry;
1539     if (!pwalletMain->mapWallet.count(hash))
1540         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
1541     const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1542
1543     CAmount nCredit = wtx.GetCredit(filter);
1544     CAmount nDebit = wtx.GetDebit(filter);
1545     CAmount nNet = nCredit - nDebit;
1546     CAmount nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0);
1547
1548     entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1549     if (wtx.IsFromMe(filter))
1550         entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1551
1552     WalletTxToJSON(wtx, entry);
1553
1554     Array details;
1555     ListTransactions(wtx, "*", 0, false, details, filter);
1556     entry.push_back(Pair("details", details));
1557
1558     string strHex = EncodeHexTx(static_cast<CTransaction>(wtx));
1559     entry.push_back(Pair("hex", strHex));
1560
1561     return entry;
1562 }
1563
1564
1565 Value backupwallet(const Array& params, bool fHelp)
1566 {
1567     if (fHelp || params.size() != 1)
1568         throw runtime_error(
1569             "backupwallet \"destination\"\n"
1570             "\nSafely copies wallet.dat to destination, which can be a directory or a path with filename.\n"
1571             "\nArguments:\n"
1572             "1. \"destination\"   (string) The destination directory or file\n"
1573             "\nExamples:\n"
1574             + HelpExampleCli("backupwallet", "\"backup.dat\"")
1575             + HelpExampleRpc("backupwallet", "\"backup.dat\"")
1576         );
1577
1578     string strDest = params[0].get_str();
1579     if (!BackupWallet(*pwalletMain, strDest))
1580         throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
1581
1582     return Value::null;
1583 }
1584
1585
1586 Value keypoolrefill(const Array& params, bool fHelp)
1587 {
1588     if (fHelp || params.size() > 1)
1589         throw runtime_error(
1590             "keypoolrefill ( newsize )\n"
1591             "\nFills the keypool."
1592             + HelpRequiringPassphrase() + "\n"
1593             "\nArguments\n"
1594             "1. newsize     (numeric, optional, default=100) The new keypool size\n"
1595             "\nExamples:\n"
1596             + HelpExampleCli("keypoolrefill", "")
1597             + HelpExampleRpc("keypoolrefill", "")
1598         );
1599
1600     // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
1601     unsigned int kpSize = 0;
1602     if (params.size() > 0) {
1603         if (params[0].get_int() < 0)
1604             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
1605         kpSize = (unsigned int)params[0].get_int();
1606     }
1607
1608     EnsureWalletIsUnlocked();
1609     pwalletMain->TopUpKeyPool(kpSize);
1610
1611     if (pwalletMain->GetKeyPoolSize() < kpSize)
1612         throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
1613
1614     return Value::null;
1615 }
1616
1617
1618 static void LockWallet(CWallet* pWallet)
1619 {
1620     LOCK(cs_nWalletUnlockTime);
1621     nWalletUnlockTime = 0;
1622     pWallet->Lock();
1623 }
1624
1625 Value walletpassphrase(const Array& params, bool fHelp)
1626 {
1627     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1628         throw runtime_error(
1629             "walletpassphrase \"passphrase\" timeout\n"
1630             "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
1631             "This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
1632             "\nArguments:\n"
1633             "1. \"passphrase\"     (string, required) The wallet passphrase\n"
1634             "2. timeout            (numeric, required) The time to keep the decryption key in seconds.\n"
1635             "\nNote:\n"
1636             "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
1637             "time that overrides the old one.\n"
1638             "\nExamples:\n"
1639             "\nunlock the wallet for 60 seconds\n"
1640             + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
1641             "\nLock the wallet again (before 60 seconds)\n"
1642             + HelpExampleCli("walletlock", "") +
1643             "\nAs json rpc call\n"
1644             + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
1645         );
1646
1647     if (fHelp)
1648         return true;
1649     if (!pwalletMain->IsCrypted())
1650         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1651
1652     // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1653     SecureString strWalletPass;
1654     strWalletPass.reserve(100);
1655     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1656     // Alternately, find a way to make params[0] mlock()'d to begin with.
1657     strWalletPass = params[0].get_str().c_str();
1658
1659     if (strWalletPass.length() > 0)
1660     {
1661         if (!pwalletMain->Unlock(strWalletPass))
1662             throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1663     }
1664     else
1665         throw runtime_error(
1666             "walletpassphrase <passphrase> <timeout>\n"
1667             "Stores the wallet decryption key in memory for <timeout> seconds.");
1668
1669     pwalletMain->TopUpKeyPool();
1670
1671     int64_t nSleepTime = params[1].get_int64();
1672     LOCK(cs_nWalletUnlockTime);
1673     nWalletUnlockTime = GetTime() + nSleepTime;
1674     RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
1675
1676     return Value::null;
1677 }
1678
1679
1680 Value walletpassphrasechange(const Array& params, bool fHelp)
1681 {
1682     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1683         throw runtime_error(
1684             "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
1685             "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
1686             "\nArguments:\n"
1687             "1. \"oldpassphrase\"      (string) The current passphrase\n"
1688             "2. \"newpassphrase\"      (string) The new passphrase\n"
1689             "\nExamples:\n"
1690             + HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
1691             + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
1692         );
1693
1694     if (fHelp)
1695         return true;
1696     if (!pwalletMain->IsCrypted())
1697         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1698
1699     // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1700     // Alternately, find a way to make params[0] mlock()'d to begin with.
1701     SecureString strOldWalletPass;
1702     strOldWalletPass.reserve(100);
1703     strOldWalletPass = params[0].get_str().c_str();
1704
1705     SecureString strNewWalletPass;
1706     strNewWalletPass.reserve(100);
1707     strNewWalletPass = params[1].get_str().c_str();
1708
1709     if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1710         throw runtime_error(
1711             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1712             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1713
1714     if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1715         throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
1716
1717     return Value::null;
1718 }
1719
1720
1721 Value walletlock(const Array& params, bool fHelp)
1722 {
1723     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1724         throw runtime_error(
1725             "walletlock\n"
1726             "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
1727             "After calling this method, you will need to call walletpassphrase again\n"
1728             "before being able to call any methods which require the wallet to be unlocked.\n"
1729             "\nExamples:\n"
1730             "\nSet the passphrase for 2 minutes to perform a transaction\n"
1731             + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
1732             "\nPerform a send (requires passphrase set)\n"
1733             + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 1.0") +
1734             "\nClear the passphrase since we are done before 2 minutes is up\n"
1735             + HelpExampleCli("walletlock", "") +
1736             "\nAs json rpc call\n"
1737             + HelpExampleRpc("walletlock", "")
1738         );
1739
1740     if (fHelp)
1741         return true;
1742     if (!pwalletMain->IsCrypted())
1743         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
1744
1745     {
1746         LOCK(cs_nWalletUnlockTime);
1747         pwalletMain->Lock();
1748         nWalletUnlockTime = 0;
1749     }
1750
1751     return Value::null;
1752 }
1753
1754
1755 Value encryptwallet(const Array& params, bool fHelp)
1756 {
1757     if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1758         throw runtime_error(
1759             "encryptwallet \"passphrase\"\n"
1760             "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
1761             "After this, any calls that interact with private keys such as sending or signing \n"
1762             "will require the passphrase to be set prior the making these calls.\n"
1763             "Use the walletpassphrase call for this, and then walletlock call.\n"
1764             "If the wallet is already encrypted, use the walletpassphrasechange call.\n"
1765             "Note that this will shutdown the server.\n"
1766             "\nArguments:\n"
1767             "1. \"passphrase\"    (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n"
1768             "\nExamples:\n"
1769             "\nEncrypt you wallet\n"
1770             + HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
1771             "\nNow set the passphrase to use the wallet, such as for signing or sending bitcoin\n"
1772             + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
1773             "\nNow we can so something like sign\n"
1774             + HelpExampleCli("signmessage", "\"bitcoinaddress\" \"test message\"") +
1775             "\nNow lock the wallet again by removing the passphrase\n"
1776             + HelpExampleCli("walletlock", "") +
1777             "\nAs a json rpc call\n"
1778             + HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
1779         );
1780
1781     if (fHelp)
1782         return true;
1783     if (pwalletMain->IsCrypted())
1784         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
1785
1786     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1787     // Alternately, find a way to make params[0] mlock()'d to begin with.
1788     SecureString strWalletPass;
1789     strWalletPass.reserve(100);
1790     strWalletPass = params[0].get_str().c_str();
1791
1792     if (strWalletPass.length() < 1)
1793         throw runtime_error(
1794             "encryptwallet <passphrase>\n"
1795             "Encrypts the wallet with <passphrase>.");
1796
1797     if (!pwalletMain->EncryptWallet(strWalletPass))
1798         throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
1799
1800     // BDB seems to have a bad habit of writing old data into
1801     // slack space in .dat files; that is bad if the old data is
1802     // unencrypted private keys. So:
1803     StartShutdown();
1804     return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
1805 }
1806
1807 Value lockunspent(const Array& params, bool fHelp)
1808 {
1809     if (fHelp || params.size() < 1 || params.size() > 2)
1810         throw runtime_error(
1811             "lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n"
1812             "\nUpdates list of temporarily unspendable outputs.\n"
1813             "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
1814             "A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
1815             "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
1816             "is always cleared (by virtue of process exit) when a node stops or fails.\n"
1817             "Also see the listunspent call\n"
1818             "\nArguments:\n"
1819             "1. unlock            (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
1820             "2. \"transactions\"  (string, required) A json array of objects. Each object the txid (string) vout (numeric)\n"
1821             "     [           (json array of json objects)\n"
1822             "       {\n"
1823             "         \"txid\":\"id\",    (string) The transaction id\n"
1824             "         \"vout\": n         (numeric) The output number\n"
1825             "       }\n"
1826             "       ,...\n"
1827             "     ]\n"
1828
1829             "\nResult:\n"
1830             "true|false    (boolean) Whether the command was successful or not\n"
1831
1832             "\nExamples:\n"
1833             "\nList the unspent transactions\n"
1834             + HelpExampleCli("listunspent", "") +
1835             "\nLock an unspent transaction\n"
1836             + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1837             "\nList the locked transactions\n"
1838             + HelpExampleCli("listlockunspent", "") +
1839             "\nUnlock the transaction again\n"
1840             + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1841             "\nAs a json rpc call\n"
1842             + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
1843         );
1844
1845     if (params.size() == 1)
1846         RPCTypeCheck(params, list_of(bool_type));
1847     else
1848         RPCTypeCheck(params, list_of(bool_type)(array_type));
1849
1850     bool fUnlock = params[0].get_bool();
1851
1852     if (params.size() == 1) {
1853         if (fUnlock)
1854             pwalletMain->UnlockAllCoins();
1855         return true;
1856     }
1857
1858     Array outputs = params[1].get_array();
1859     BOOST_FOREACH(Value& output, outputs)
1860     {
1861         if (output.type() != obj_type)
1862             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
1863         const Object& o = output.get_obj();
1864
1865         RPCTypeCheck(o, map_list_of("txid", str_type)("vout", int_type));
1866
1867         string txid = find_value(o, "txid").get_str();
1868         if (!IsHex(txid))
1869             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
1870
1871         int nOutput = find_value(o, "vout").get_int();
1872         if (nOutput < 0)
1873             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
1874
1875         COutPoint outpt(uint256(txid), nOutput);
1876
1877         if (fUnlock)
1878             pwalletMain->UnlockCoin(outpt);
1879         else
1880             pwalletMain->LockCoin(outpt);
1881     }
1882
1883     return true;
1884 }
1885
1886 Value listlockunspent(const Array& params, bool fHelp)
1887 {
1888     if (fHelp || params.size() > 0)
1889         throw runtime_error(
1890             "listlockunspent\n"
1891             "\nReturns list of temporarily unspendable outputs.\n"
1892             "See the lockunspent call to lock and unlock transactions for spending.\n"
1893             "\nResult:\n"
1894             "[\n"
1895             "  {\n"
1896             "    \"txid\" : \"transactionid\",     (string) The transaction id locked\n"
1897             "    \"vout\" : n                      (numeric) The vout value\n"
1898             "  }\n"
1899             "  ,...\n"
1900             "]\n"
1901             "\nExamples:\n"
1902             "\nList the unspent transactions\n"
1903             + HelpExampleCli("listunspent", "") +
1904             "\nLock an unspent transaction\n"
1905             + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1906             "\nList the locked transactions\n"
1907             + HelpExampleCli("listlockunspent", "") +
1908             "\nUnlock the transaction again\n"
1909             + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
1910             "\nAs a json rpc call\n"
1911             + HelpExampleRpc("listlockunspent", "")
1912         );
1913
1914     vector<COutPoint> vOutpts;
1915     pwalletMain->ListLockedCoins(vOutpts);
1916
1917     Array ret;
1918
1919     BOOST_FOREACH(COutPoint &outpt, vOutpts) {
1920         Object o;
1921
1922         o.push_back(Pair("txid", outpt.hash.GetHex()));
1923         o.push_back(Pair("vout", (int)outpt.n));
1924         ret.push_back(o);
1925     }
1926
1927     return ret;
1928 }
1929
1930 Value settxfee(const Array& params, bool fHelp)
1931 {
1932     if (fHelp || params.size() < 1 || params.size() > 1)
1933         throw runtime_error(
1934             "settxfee amount\n"
1935             "\nSet the transaction fee per kB.\n"
1936             "\nArguments:\n"
1937             "1. amount         (numeric, required) The transaction fee in BTC/kB rounded to the nearest 0.00000001\n"
1938             "\nResult\n"
1939             "true|false        (boolean) Returns true if successful\n"
1940             "\nExamples:\n"
1941             + HelpExampleCli("settxfee", "0.00001")
1942             + HelpExampleRpc("settxfee", "0.00001")
1943         );
1944
1945     // Amount
1946     CAmount nAmount = 0;
1947     if (params[0].get_real() != 0.0)
1948         nAmount = AmountFromValue(params[0]);        // rejects 0.0 amounts
1949
1950     payTxFee = CFeeRate(nAmount, 1000);
1951     return true;
1952 }
1953
1954 Value getwalletinfo(const Array& params, bool fHelp)
1955 {
1956     if (fHelp || params.size() != 0)
1957         throw runtime_error(
1958             "getwalletinfo\n"
1959             "Returns an object containing various wallet state info.\n"
1960             "\nResult:\n"
1961             "{\n"
1962             "  \"walletversion\": xxxxx,     (numeric) the wallet version\n"
1963             "  \"balance\": xxxxxxx,         (numeric) the total bitcoin balance of the wallet\n"
1964             "  \"txcount\": xxxxxxx,         (numeric) the total number of transactions in the wallet\n"
1965             "  \"keypoololdest\": xxxxxx,    (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
1966             "  \"keypoolsize\": xxxx,        (numeric) how many new keys are pre-generated\n"
1967             "  \"unlocked_until\": ttt,      (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
1968             "}\n"
1969             "\nExamples:\n"
1970             + HelpExampleCli("getwalletinfo", "")
1971             + HelpExampleRpc("getwalletinfo", "")
1972         );
1973
1974     Object obj;
1975     obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
1976     obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
1977     obj.push_back(Pair("txcount",       (int)pwalletMain->mapWallet.size()));
1978     obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
1979     obj.push_back(Pair("keypoolsize",   (int)pwalletMain->GetKeyPoolSize()));
1980     if (pwalletMain->IsCrypted())
1981         obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
1982     return obj;
1983 }
This page took 0.142312 seconds and 4 git commands to generate.