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