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