aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/rpcwallet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet/rpcwallet.cpp')
-rw-r--r--src/wallet/rpcwallet.cpp515
1 files changed, 406 insertions, 109 deletions
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 29f3eda15d..8d88933878 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -21,11 +21,9 @@
#include <boost/assign/list_of.hpp>
-#include "json/json_spirit_utils.h"
-#include "json/json_spirit_value.h"
+#include "univalue/univalue.h"
using namespace std;
-using namespace json_spirit;
int64_t nWalletUnlockTime;
static CCriticalSection cs_nWalletUnlockTime;
@@ -37,13 +35,25 @@ std::string HelpRequiringPassphrase()
: "";
}
+bool EnsureWalletIsAvailable(bool avoidException)
+{
+ if (!pwalletMain)
+ {
+ if (!avoidException)
+ throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
+ else
+ return false;
+ }
+ return true;
+}
+
void EnsureWalletIsUnlocked()
{
if (pwalletMain->IsLocked())
throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
}
-void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
+void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
{
int confirms = wtx.GetDepthInMainChain();
entry.push_back(Pair("confirmations", confirms));
@@ -57,7 +67,7 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
}
uint256 hash = wtx.GetHash();
entry.push_back(Pair("txid", hash.GetHex()));
- Array conflicts;
+ UniValue conflicts(UniValue::VARR);
BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
conflicts.push_back(conflict.GetHex());
entry.push_back(Pair("walletconflicts", conflicts));
@@ -67,7 +77,7 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
entry.push_back(Pair(item.first, item.second));
}
-string AccountFromValue(const Value& value)
+string AccountFromValue(const UniValue& value)
{
string strAccount = value.get_str();
if (strAccount == "*")
@@ -75,8 +85,11 @@ string AccountFromValue(const Value& value)
return strAccount;
}
-Value getnewaddress(const Array& params, bool fHelp)
+UniValue getnewaddress(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() > 1)
throw runtime_error(
"getnewaddress ( \"account\" )\n"
@@ -151,8 +164,11 @@ CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
return CBitcoinAddress(account.vchPubKey.GetID());
}
-Value getaccountaddress(const Array& params, bool fHelp)
+UniValue getaccountaddress(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() != 1)
throw runtime_error(
"getaccountaddress \"account\"\n"
@@ -173,15 +189,18 @@ Value getaccountaddress(const Array& params, bool fHelp)
// Parse the account first so we don't generate a key if there's an error
string strAccount = AccountFromValue(params[0]);
- Value ret;
+ UniValue ret(UniValue::VSTR);
ret = GetAccountAddress(strAccount).ToString();
return ret;
}
-Value getrawchangeaddress(const Array& params, bool fHelp)
+UniValue getrawchangeaddress(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() > 1)
throw runtime_error(
"getrawchangeaddress\n"
@@ -212,8 +231,11 @@ Value getrawchangeaddress(const Array& params, bool fHelp)
}
-Value setaccount(const Array& params, bool fHelp)
+UniValue setaccount(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
"setaccount \"bitcoinaddress\" \"account\"\n"
@@ -251,12 +273,15 @@ Value setaccount(const Array& params, bool fHelp)
else
throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
- return Value::null;
+ return NullUniValue;
}
-Value getaccount(const Array& params, bool fHelp)
+UniValue getaccount(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() != 1)
throw runtime_error(
"getaccount \"bitcoinaddress\"\n"
@@ -284,8 +309,11 @@ Value getaccount(const Array& params, bool fHelp)
}
-Value getaddressesbyaccount(const Array& params, bool fHelp)
+UniValue getaddressesbyaccount(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() != 1)
throw runtime_error(
"getaddressesbyaccount \"account\"\n"
@@ -307,7 +335,7 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
string strAccount = AccountFromValue(params[0]);
// Find all addresses that have the given account
- Array ret;
+ UniValue ret(UniValue::VARR);
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
{
const CBitcoinAddress& address = item.first;
@@ -349,8 +377,11 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr
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.");
}
-Value sendtoaddress(const Array& params, bool fHelp)
+UniValue sendtoaddress(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() < 2 || params.size() > 5)
throw runtime_error(
"sendtoaddress \"bitcoinaddress\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n"
@@ -383,12 +414,14 @@ Value sendtoaddress(const Array& params, bool fHelp)
// Amount
CAmount nAmount = AmountFromValue(params[1]);
+ if (nAmount <= 0)
+ throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
// Wallet comments
CWalletTx wtx;
- if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
+ if (params.size() > 2 && !params[2].isNull() && !params[2].get_str().empty())
wtx.mapValue["comment"] = params[2].get_str();
- if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
+ if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty())
wtx.mapValue["to"] = params[3].get_str();
bool fSubtractFeeFromAmount = false;
@@ -402,8 +435,11 @@ Value sendtoaddress(const Array& params, bool fHelp)
return wtx.GetHash().GetHex();
}
-Value listaddressgroupings(const Array& params, bool fHelp)
+UniValue listaddressgroupings(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp)
throw runtime_error(
"listaddressgroupings\n"
@@ -429,14 +465,14 @@ Value listaddressgroupings(const Array& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
- Array jsonGroupings;
+ UniValue jsonGroupings(UniValue::VARR);
map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
{
- Array jsonGrouping;
+ UniValue jsonGrouping(UniValue::VARR);
BOOST_FOREACH(CTxDestination address, grouping)
{
- Array addressInfo;
+ UniValue addressInfo(UniValue::VARR);
addressInfo.push_back(CBitcoinAddress(address).ToString());
addressInfo.push_back(ValueFromAmount(balances[address]));
{
@@ -451,8 +487,11 @@ Value listaddressgroupings(const Array& params, bool fHelp)
return jsonGroupings;
}
-Value signmessage(const Array& params, bool fHelp)
+UniValue signmessage(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() != 2)
throw runtime_error(
"signmessage \"bitcoinaddress\" \"message\"\n"
@@ -504,8 +543,11 @@ Value signmessage(const Array& params, bool fHelp)
return EncodeBase64(&vchSig[0], vchSig.size());
}
-Value getreceivedbyaddress(const Array& params, bool fHelp)
+UniValue getreceivedbyaddress(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
"getreceivedbyaddress \"bitcoinaddress\" ( minconf )\n"
@@ -546,7 +588,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !IsFinalTx(wtx))
+ if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
continue;
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
@@ -559,8 +601,11 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
}
-Value getreceivedbyaccount(const Array& params, bool fHelp)
+UniValue getreceivedbyaccount(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
"getreceivedbyaccount \"account\" ( minconf )\n"
@@ -597,7 +642,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !IsFinalTx(wtx))
+ if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
continue;
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
@@ -621,7 +666,7 @@ CAmount GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMi
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
- if (!IsFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
+ if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
continue;
CAmount nReceived, nSent, nFee;
@@ -645,8 +690,11 @@ CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminef
}
-Value getbalance(const Array& params, bool fHelp)
+UniValue getbalance(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() > 3)
throw runtime_error(
"getbalance ( \"account\" minconf includeWatchonly )\n"
@@ -685,12 +733,12 @@ Value getbalance(const Array& params, bool fHelp)
if (params[0].get_str() == "*") {
// Calculate total balance a different way from GetBalance()
// (GetBalance() sums up all unspent TxOuts)
- // getbalance and getbalance '*' 0 should return the same number
+ // getbalance and "getbalance * 1 true" should return the same number
CAmount nBalance = 0;
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
- if (!wtx.IsTrusted() || wtx.GetBlocksToMaturity() > 0)
+ if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
continue;
CAmount allFee;
@@ -717,8 +765,11 @@ Value getbalance(const Array& params, bool fHelp)
return ValueFromAmount(nBalance);
}
-Value getunconfirmedbalance(const Array &params, bool fHelp)
+UniValue getunconfirmedbalance(const UniValue &params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() > 0)
throw runtime_error(
"getunconfirmedbalance\n"
@@ -730,8 +781,11 @@ Value getunconfirmedbalance(const Array &params, bool fHelp)
}
-Value movecmd(const Array& params, bool fHelp)
+UniValue movecmd(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() < 3 || params.size() > 5)
throw runtime_error(
"move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
@@ -757,6 +811,8 @@ Value movecmd(const Array& params, bool fHelp)
string strFrom = AccountFromValue(params[0]);
string strTo = AccountFromValue(params[1]);
CAmount nAmount = AmountFromValue(params[2]);
+ if (nAmount <= 0)
+ throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
if (params.size() > 3)
// unused parameter, used to be nMinDepth, keep type-checking it though
(void)params[3].get_int();
@@ -797,8 +853,11 @@ Value movecmd(const Array& params, bool fHelp)
}
-Value sendfrom(const Array& params, bool fHelp)
+UniValue sendfrom(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() < 3 || params.size() > 6)
throw runtime_error(
"sendfrom \"fromaccount\" \"tobitcoinaddress\" amount ( minconf \"comment\" \"comment-to\" )\n"
@@ -833,15 +892,17 @@ Value sendfrom(const Array& params, bool fHelp)
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
CAmount nAmount = AmountFromValue(params[2]);
+ if (nAmount <= 0)
+ throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
int nMinDepth = 1;
if (params.size() > 3)
nMinDepth = params[3].get_int();
CWalletTx wtx;
wtx.strFromAccount = strAccount;
- if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
+ if (params.size() > 4 && !params[4].isNull() && !params[4].get_str().empty())
wtx.mapValue["comment"] = params[4].get_str();
- if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
+ if (params.size() > 5 && !params[5].isNull() && !params[5].get_str().empty())
wtx.mapValue["to"] = params[5].get_str();
EnsureWalletIsUnlocked();
@@ -857,8 +918,11 @@ Value sendfrom(const Array& params, bool fHelp)
}
-Value sendmany(const Array& params, bool fHelp)
+UniValue sendmany(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() < 2 || params.size() > 5)
throw runtime_error(
"sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] )\n"
@@ -898,17 +962,17 @@ Value sendmany(const Array& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
string strAccount = AccountFromValue(params[0]);
- Object sendTo = params[1].get_obj();
+ UniValue sendTo = params[1].get_obj();
int nMinDepth = 1;
if (params.size() > 2)
nMinDepth = params[2].get_int();
CWalletTx wtx;
wtx.strFromAccount = strAccount;
- if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
+ if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty())
wtx.mapValue["comment"] = params[3].get_str();
- Array subtractFeeFromAmount;
+ UniValue subtractFeeFromAmount(UniValue::VARR);
if (params.size() > 4)
subtractFeeFromAmount = params[4].get_array();
@@ -916,24 +980,29 @@ Value sendmany(const Array& params, bool fHelp)
vector<CRecipient> vecSend;
CAmount totalAmount = 0;
- BOOST_FOREACH(const Pair& s, sendTo)
+ vector<string> keys = sendTo.getKeys();
+ BOOST_FOREACH(const string& name_, keys)
{
- CBitcoinAddress address(s.name_);
+ CBitcoinAddress address(name_);
if (!address.IsValid())
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_);
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+name_);
if (setAddress.count(address))
- throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
+ throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_);
setAddress.insert(address);
CScript scriptPubKey = GetScriptForDestination(address.Get());
- CAmount nAmount = AmountFromValue(s.value_);
+ CAmount nAmount = AmountFromValue(sendTo[name_]);
+ if (nAmount <= 0)
+ throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
totalAmount += nAmount;
bool fSubtractFeeFromAmount = false;
- BOOST_FOREACH(const Value& addr, subtractFeeFromAmount)
- if (addr.get_str() == s.name_)
+ for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
+ const UniValue& addr = subtractFeeFromAmount[idx];
+ if (addr.get_str() == name_)
fSubtractFeeFromAmount = true;
+ }
CRecipient recipient = {scriptPubKey, nAmount, fSubtractFeeFromAmount};
vecSend.push_back(recipient);
@@ -961,10 +1030,13 @@ Value sendmany(const Array& params, bool fHelp)
}
// Defined in rpcmisc.cpp
-extern CScript _createmultisig_redeemScript(const Array& params);
+extern CScript _createmultisig_redeemScript(const UniValue& params);
-Value addmultisigaddress(const Array& params, bool fHelp)
+UniValue addmultisigaddress(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() < 2 || params.size() > 3)
{
string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
@@ -1023,7 +1095,7 @@ struct tallyitem
}
};
-Value ListReceived(const Array& params, bool fByAccounts)
+UniValue ListReceived(const UniValue& params, bool fByAccounts)
{
// Minimum confirmations
int nMinDepth = 1;
@@ -1046,7 +1118,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
{
const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !IsFinalTx(wtx))
+ if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
continue;
int nDepth = wtx.GetDepthInMainChain();
@@ -1073,7 +1145,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
}
// Reply
- Array ret;
+ UniValue ret(UniValue::VARR);
map<string, tallyitem> mapAccountTally;
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
{
@@ -1102,14 +1174,14 @@ Value ListReceived(const Array& params, bool fByAccounts)
}
else
{
- Object obj;
+ UniValue obj(UniValue::VOBJ);
if(fIsWatchonly)
obj.push_back(Pair("involvesWatchonly", true));
obj.push_back(Pair("address", address.ToString()));
obj.push_back(Pair("account", strAccount));
obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
- Array transactions;
+ UniValue transactions(UniValue::VARR);
if (it != mapTally.end())
{
BOOST_FOREACH(const uint256& item, (*it).second.txids)
@@ -1128,7 +1200,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
{
CAmount nAmount = (*it).second.nAmount;
int nConf = (*it).second.nConf;
- Object obj;
+ UniValue obj(UniValue::VOBJ);
if((*it).second.fIsWatchonly)
obj.push_back(Pair("involvesWatchonly", true));
obj.push_back(Pair("account", (*it).first));
@@ -1141,8 +1213,11 @@ Value ListReceived(const Array& params, bool fByAccounts)
return ret;
}
-Value listreceivedbyaddress(const Array& params, bool fHelp)
+UniValue listreceivedbyaddress(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() > 3)
throw runtime_error(
"listreceivedbyaddress ( minconf includeempty includeWatchonly)\n"
@@ -1175,8 +1250,11 @@ Value listreceivedbyaddress(const Array& params, bool fHelp)
return ListReceived(params, false);
}
-Value listreceivedbyaccount(const Array& params, bool fHelp)
+UniValue listreceivedbyaccount(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() > 3)
throw runtime_error(
"listreceivedbyaccount ( minconf includeempty includeWatchonly)\n"
@@ -1208,14 +1286,14 @@ Value listreceivedbyaccount(const Array& params, bool fHelp)
return ListReceived(params, true);
}
-static void MaybePushAddress(Object & entry, const CTxDestination &dest)
+static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
{
CBitcoinAddress addr;
if (addr.Set(dest))
entry.push_back(Pair("address", addr.ToString()));
}
-void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret, const isminefilter& filter)
+void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
{
CAmount nFee;
string strSentAccount;
@@ -1232,7 +1310,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
{
BOOST_FOREACH(const COutputEntry& s, listSent)
{
- Object entry;
+ UniValue entry(UniValue::VOBJ);
if(involvesWatchonly || (::IsMine(*pwalletMain, s.destination) & ISMINE_WATCH_ONLY))
entry.push_back(Pair("involvesWatchonly", true));
entry.push_back(Pair("account", strSentAccount));
@@ -1257,7 +1335,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
account = pwalletMain->mapAddressBook[r.destination].name;
if (fAllAccounts || (account == strAccount))
{
- Object entry;
+ UniValue entry(UniValue::VOBJ);
if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
entry.push_back(Pair("involvesWatchonly", true));
entry.push_back(Pair("account", account));
@@ -1285,13 +1363,13 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
}
}
-void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
+void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, UniValue& ret)
{
bool fAllAccounts = (strAccount == string("*"));
if (fAllAccounts || acentry.strAccount == strAccount)
{
- Object entry;
+ UniValue entry(UniValue::VOBJ);
entry.push_back(Pair("account", acentry.strAccount));
entry.push_back(Pair("category", "move"));
entry.push_back(Pair("time", acentry.nTime));
@@ -1302,8 +1380,11 @@ void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Ar
}
}
-Value listtransactions(const Array& params, bool fHelp)
+UniValue listtransactions(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() > 4)
throw runtime_error(
"listtransactions ( \"account\" count from includeWatchonly)\n"
@@ -1377,7 +1458,7 @@ Value listtransactions(const Array& params, bool fHelp)
if (nFrom < 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
- Array ret;
+ UniValue ret(UniValue::VARR);
std::list<CAccountingEntry> acentries;
CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount);
@@ -1400,21 +1481,31 @@ Value listtransactions(const Array& params, bool fHelp)
nFrom = ret.size();
if ((nFrom + nCount) > (int)ret.size())
nCount = ret.size() - nFrom;
- Array::iterator first = ret.begin();
+
+ vector<UniValue> arrTmp = ret.getValues();
+
+ vector<UniValue>::iterator first = arrTmp.begin();
std::advance(first, nFrom);
- Array::iterator last = ret.begin();
+ vector<UniValue>::iterator last = arrTmp.begin();
std::advance(last, nFrom+nCount);
- if (last != ret.end()) ret.erase(last, ret.end());
- if (first != ret.begin()) ret.erase(ret.begin(), first);
+ if (last != arrTmp.end()) arrTmp.erase(last, arrTmp.end());
+ if (first != arrTmp.begin()) arrTmp.erase(arrTmp.begin(), first);
+
+ std::reverse(arrTmp.begin(), arrTmp.end()); // Return oldest to newest
- std::reverse(ret.begin(), ret.end()); // Return oldest to newest
+ ret.clear();
+ ret.setArray();
+ ret.push_backV(arrTmp);
return ret;
}
-Value listaccounts(const Array& params, bool fHelp)
+UniValue listaccounts(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() > 2)
throw runtime_error(
"listaccounts ( minconf includeWatchonly)\n"
@@ -1483,15 +1574,18 @@ Value listaccounts(const Array& params, bool fHelp)
BOOST_FOREACH(const CAccountingEntry& entry, acentries)
mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
- Object ret;
+ UniValue ret(UniValue::VOBJ);
BOOST_FOREACH(const PAIRTYPE(string, CAmount)& accountBalance, mapAccountBalances) {
ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
}
return ret;
}
-Value listsinceblock(const Array& params, bool fHelp)
+UniValue listsinceblock(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp)
throw runtime_error(
"listsinceblock ( \"blockhash\" target-confirmations includeWatchonly)\n"
@@ -1558,7 +1652,7 @@ Value listsinceblock(const Array& params, bool fHelp)
int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
- Array transactions;
+ UniValue transactions(UniValue::VARR);
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
{
@@ -1571,15 +1665,18 @@ Value listsinceblock(const Array& params, bool fHelp)
CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : uint256();
- Object ret;
+ UniValue ret(UniValue::VOBJ);
ret.push_back(Pair("transactions", transactions));
ret.push_back(Pair("lastblock", lastblock.GetHex()));
return ret;
}
-Value gettransaction(const Array& params, bool fHelp)
+UniValue gettransaction(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
"gettransaction \"txid\" ( includeWatchonly )\n"
@@ -1626,7 +1723,7 @@ Value gettransaction(const Array& params, bool fHelp)
if(params[1].get_bool())
filter = filter | ISMINE_WATCH_ONLY;
- Object entry;
+ UniValue entry(UniValue::VOBJ);
if (!pwalletMain->mapWallet.count(hash))
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
const CWalletTx& wtx = pwalletMain->mapWallet[hash];
@@ -1642,7 +1739,7 @@ Value gettransaction(const Array& params, bool fHelp)
WalletTxToJSON(wtx, entry);
- Array details;
+ UniValue details(UniValue::VARR);
ListTransactions(wtx, "*", 0, false, details, filter);
entry.push_back(Pair("details", details));
@@ -1653,8 +1750,11 @@ Value gettransaction(const Array& params, bool fHelp)
}
-Value backupwallet(const Array& params, bool fHelp)
+UniValue backupwallet(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() != 1)
throw runtime_error(
"backupwallet \"destination\"\n"
@@ -1672,12 +1772,15 @@ Value backupwallet(const Array& params, bool fHelp)
if (!BackupWallet(*pwalletMain, strDest))
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
- return Value::null;
+ return NullUniValue;
}
-Value keypoolrefill(const Array& params, bool fHelp)
+UniValue keypoolrefill(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() > 1)
throw runtime_error(
"keypoolrefill ( newsize )\n"
@@ -1706,7 +1809,7 @@ Value keypoolrefill(const Array& params, bool fHelp)
if (pwalletMain->GetKeyPoolSize() < kpSize)
throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
- return Value::null;
+ return NullUniValue;
}
@@ -1717,8 +1820,11 @@ static void LockWallet(CWallet* pWallet)
pWallet->Lock();
}
-Value walletpassphrase(const Array& params, bool fHelp)
+UniValue walletpassphrase(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
throw runtime_error(
"walletpassphrase \"passphrase\" timeout\n"
@@ -1770,12 +1876,15 @@ Value walletpassphrase(const Array& params, bool fHelp)
nWalletUnlockTime = GetTime() + nSleepTime;
RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
- return Value::null;
+ return NullUniValue;
}
-Value walletpassphrasechange(const Array& params, bool fHelp)
+UniValue walletpassphrasechange(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
throw runtime_error(
"walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
@@ -1813,12 +1922,15 @@ Value walletpassphrasechange(const Array& params, bool fHelp)
if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
- return Value::null;
+ return NullUniValue;
}
-Value walletlock(const Array& params, bool fHelp)
+UniValue walletlock(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
throw runtime_error(
"walletlock\n"
@@ -1849,12 +1961,15 @@ Value walletlock(const Array& params, bool fHelp)
nWalletUnlockTime = 0;
}
- return Value::null;
+ return NullUniValue;
}
-Value encryptwallet(const Array& params, bool fHelp)
+UniValue encryptwallet(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
throw runtime_error(
"encryptwallet \"passphrase\"\n"
@@ -1907,8 +2022,11 @@ Value encryptwallet(const Array& params, bool fHelp)
return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
}
-Value lockunspent(const Array& params, bool fHelp)
+UniValue lockunspent(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
"lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n"
@@ -1948,9 +2066,9 @@ Value lockunspent(const Array& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
if (params.size() == 1)
- RPCTypeCheck(params, boost::assign::list_of(bool_type));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL));
else
- RPCTypeCheck(params, boost::assign::list_of(bool_type)(array_type));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VBOOL)(UniValue::VARR));
bool fUnlock = params[0].get_bool();
@@ -1960,14 +2078,14 @@ Value lockunspent(const Array& params, bool fHelp)
return true;
}
- Array outputs = params[1].get_array();
- BOOST_FOREACH(Value& output, outputs)
- {
- if (output.type() != obj_type)
+ UniValue outputs = params[1].get_array();
+ for (unsigned int idx = 0; idx < outputs.size(); idx++) {
+ const UniValue& output = outputs[idx];
+ if (!output.isObject())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
- const Object& o = output.get_obj();
+ const UniValue& o = output.get_obj();
- RPCTypeCheck(o, boost::assign::map_list_of("txid", str_type)("vout", int_type));
+ RPCTypeCheckObj(o, boost::assign::map_list_of("txid", UniValue::VSTR)("vout", UniValue::VNUM));
string txid = find_value(o, "txid").get_str();
if (!IsHex(txid))
@@ -1988,8 +2106,11 @@ Value lockunspent(const Array& params, bool fHelp)
return true;
}
-Value listlockunspent(const Array& params, bool fHelp)
+UniValue listlockunspent(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() > 0)
throw runtime_error(
"listlockunspent\n"
@@ -2021,10 +2142,10 @@ Value listlockunspent(const Array& params, bool fHelp)
vector<COutPoint> vOutpts;
pwalletMain->ListLockedCoins(vOutpts);
- Array ret;
+ UniValue ret(UniValue::VARR);
BOOST_FOREACH(COutPoint &outpt, vOutpts) {
- Object o;
+ UniValue o(UniValue::VOBJ);
o.push_back(Pair("txid", outpt.hash.GetHex()));
o.push_back(Pair("vout", (int)outpt.n));
@@ -2034,8 +2155,11 @@ Value listlockunspent(const Array& params, bool fHelp)
return ret;
}
-Value settxfee(const Array& params, bool fHelp)
+UniValue settxfee(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() < 1 || params.size() > 1)
throw runtime_error(
"settxfee amount\n"
@@ -2052,16 +2176,17 @@ Value settxfee(const Array& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
// Amount
- CAmount nAmount = 0;
- if (params[0].get_real() != 0.0)
- nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
+ CAmount nAmount = AmountFromValue(params[0]);
payTxFee = CFeeRate(nAmount, 1000);
return true;
}
-Value getwalletinfo(const Array& params, bool fHelp)
+UniValue getwalletinfo(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() != 0)
throw runtime_error(
"getwalletinfo\n"
@@ -2076,6 +2201,7 @@ Value getwalletinfo(const Array& params, bool fHelp)
" \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
" \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
" \"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"
+ " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in btc/kb\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getwalletinfo", "")
@@ -2084,7 +2210,7 @@ Value getwalletinfo(const Array& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
- Object obj;
+ UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
obj.push_back(Pair("unconfirmed_balance", ValueFromAmount(pwalletMain->GetUnconfirmedBalance())));
@@ -2094,11 +2220,15 @@ Value getwalletinfo(const Array& params, bool fHelp)
obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
if (pwalletMain->IsCrypted())
obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
+ obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
return obj;
}
-Value resendwallettransactions(const Array& params, bool fHelp)
+UniValue resendwallettransactions(const UniValue& params, bool fHelp)
{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
if (fHelp || params.size() != 0)
throw runtime_error(
"resendwallettransactions\n"
@@ -2111,10 +2241,177 @@ Value resendwallettransactions(const Array& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
std::vector<uint256> txids = pwalletMain->ResendWalletTransactionsBefore(GetTime());
- Array result;
+ UniValue result(UniValue::VARR);
BOOST_FOREACH(const uint256& txid, txids)
{
result.push_back(txid.ToString());
}
return result;
}
+
+UniValue listunspent(const UniValue& params, bool fHelp)
+{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
+ if (fHelp || params.size() > 3)
+ throw runtime_error(
+ "listunspent ( minconf maxconf [\"address\",...] )\n"
+ "\nReturns array of unspent transaction outputs\n"
+ "with between minconf and maxconf (inclusive) confirmations.\n"
+ "Optionally filter to only include txouts paid to specified addresses.\n"
+ "Results are an array of Objects, each of which has:\n"
+ "{txid, vout, scriptPubKey, amount, confirmations}\n"
+ "\nArguments:\n"
+ "1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n"
+ "2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n"
+ "3. \"addresses\" (string) A json array of bitcoin addresses to filter\n"
+ " [\n"
+ " \"address\" (string) bitcoin address\n"
+ " ,...\n"
+ " ]\n"
+ "\nResult\n"
+ "[ (array of json object)\n"
+ " {\n"
+ " \"txid\" : \"txid\", (string) the transaction id \n"
+ " \"vout\" : n, (numeric) the vout value\n"
+ " \"address\" : \"address\", (string) the bitcoin address\n"
+ " \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n"
+ " \"scriptPubKey\" : \"key\", (string) the script key\n"
+ " \"amount\" : x.xxx, (numeric) the transaction amount in btc\n"
+ " \"confirmations\" : n (numeric) The number of confirmations\n"
+ " }\n"
+ " ,...\n"
+ "]\n"
+
+ "\nExamples\n"
+ + HelpExampleCli("listunspent", "")
+ + HelpExampleCli("listunspent", "6 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
+ + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"")
+ );
+
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)(UniValue::VNUM)(UniValue::VARR));
+
+ int nMinDepth = 1;
+ if (params.size() > 0)
+ nMinDepth = params[0].get_int();
+
+ int nMaxDepth = 9999999;
+ if (params.size() > 1)
+ nMaxDepth = params[1].get_int();
+
+ set<CBitcoinAddress> setAddress;
+ if (params.size() > 2) {
+ UniValue inputs = params[2].get_array();
+ for (unsigned int idx = 0; idx < inputs.size(); idx++) {
+ const UniValue& input = inputs[idx];
+ CBitcoinAddress address(input.get_str());
+ if (!address.IsValid())
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+input.get_str());
+ if (setAddress.count(address))
+ throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str());
+ setAddress.insert(address);
+ }
+ }
+
+ UniValue results(UniValue::VARR);
+ vector<COutput> vecOutputs;
+ assert(pwalletMain != NULL);
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+ pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
+ BOOST_FOREACH(const COutput& out, vecOutputs) {
+ if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
+ continue;
+
+ if (setAddress.size()) {
+ CTxDestination address;
+ if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
+ continue;
+
+ if (!setAddress.count(address))
+ continue;
+ }
+
+ CAmount nValue = out.tx->vout[out.i].nValue;
+ const CScript& pk = out.tx->vout[out.i].scriptPubKey;
+ UniValue entry(UniValue::VOBJ);
+ entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
+ entry.push_back(Pair("vout", out.i));
+ CTxDestination address;
+ if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
+ entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
+ if (pwalletMain->mapAddressBook.count(address))
+ entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name));
+ }
+ entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end())));
+ if (pk.IsPayToScriptHash()) {
+ CTxDestination address;
+ if (ExtractDestination(pk, address)) {
+ const CScriptID& hash = boost::get<CScriptID>(address);
+ CScript redeemScript;
+ if (pwalletMain->GetCScript(hash, redeemScript))
+ entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
+ }
+ }
+ entry.push_back(Pair("amount",ValueFromAmount(nValue)));
+ entry.push_back(Pair("confirmations",out.nDepth));
+ entry.push_back(Pair("spendable", out.fSpendable));
+ results.push_back(entry);
+ }
+
+ return results;
+}
+
+UniValue fundrawtransaction(const UniValue& params, bool fHelp)
+{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
+ if (fHelp || params.size() != 1)
+ throw runtime_error(
+ "fundrawtransaction \"hexstring\"\n"
+ "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
+ "This will not modify existing inputs, and will add one change output to the outputs.\n"
+ "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
+ "The inputs added will not be signed, use signrawtransaction for that.\n"
+ "\nArguments:\n"
+ "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
+ "\nResult:\n"
+ "{\n"
+ " \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
+ " \"fee\": n, (numeric) The fee added to the transaction\n"
+ " \"changepos\": n (numeric) The position of the added change output, or -1\n"
+ "}\n"
+ "\"hex\" \n"
+ "\nExamples:\n"
+ "\nCreate a transaction with no inputs\n"
+ + HelpExampleCli("createrawtransaction", "\"[]\" \"{\\\"myaddress\\\":0.01}\"") +
+ "\nAdd sufficient unsigned inputs to meet the output value\n"
+ + HelpExampleCli("fundrawtransaction", "\"rawtransactionhex\"") +
+ "\nSign the transaction\n"
+ + HelpExampleCli("signrawtransaction", "\"fundedtransactionhex\"") +
+ "\nSend the transaction\n"
+ + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
+ );
+
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
+
+ // parse hex string from parameter
+ CTransaction origTx;
+ if (!DecodeHexTx(origTx, params[0].get_str()))
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
+
+ CMutableTransaction tx(origTx);
+ CAmount nFee;
+ string strFailReason;
+ int nChangePos = -1;
+ if(!pwalletMain->FundTransaction(tx, nFee, nChangePos, strFailReason))
+ throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
+
+ UniValue result(UniValue::VOBJ);
+ result.push_back(Pair("hex", EncodeHexTx(tx)));
+ result.push_back(Pair("changepos", nChangePos));
+ result.push_back(Pair("fee", ValueFromAmount(nFee)));
+
+ return result;
+}