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