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