New RPC command: listaccounts. New RPC setting -rpctimeout. And listtransactions '*'
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@203 1a98c847-1fd6-4fd8-948a-caf3550aa51b
This commit is contained in:
301
rpc.cpp
301
rpc.cpp
@@ -84,7 +84,13 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
|
||||
entry.push_back(Pair(item.first, item.second));
|
||||
}
|
||||
|
||||
|
||||
string AccountFromValue(const Value& value)
|
||||
{
|
||||
string strAccount = value.get_str();
|
||||
if (strAccount == "*")
|
||||
throw JSONRPCError(-11, "Invalid account name");
|
||||
return strAccount;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -296,7 +302,7 @@ Value getnewaddress(const Array& params, bool fHelp)
|
||||
// Parse the account first so we don't generate a key if there's an error
|
||||
string strAccount;
|
||||
if (params.size() > 0)
|
||||
strAccount = params[0].get_str();
|
||||
strAccount = AccountFromValue(params[0]);
|
||||
|
||||
// Generate a new key that is added to wallet
|
||||
string strAddress = PubKeyToAddress(GetKeyFromKeyPool());
|
||||
@@ -314,7 +320,7 @@ Value getaccountaddress(const Array& params, bool fHelp)
|
||||
"Returns the current bitcoin address for receiving payments to this account.");
|
||||
|
||||
// Parse the account first so we don't generate a key if there's an error
|
||||
string strAccount = params[0].get_str();
|
||||
string strAccount = AccountFromValue(params[0]);
|
||||
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
@@ -365,7 +371,7 @@ Value setaccount(const Array& params, bool fHelp)
|
||||
string strAddress = params[0].get_str();
|
||||
string strAccount;
|
||||
if (params.size() > 1)
|
||||
strAccount = params[1].get_str();
|
||||
strAccount = AccountFromValue(params[1]);
|
||||
|
||||
SetAddressBookName(strAddress, strAccount);
|
||||
return Value::null;
|
||||
@@ -399,7 +405,7 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
|
||||
"getaddressesbyaccount <account>\n"
|
||||
"Returns the list of addresses for the given account.");
|
||||
|
||||
string strAccount = params[0].get_str();
|
||||
string strAccount = AccountFromValue(params[0]);
|
||||
|
||||
// Find all addresses that have the given account
|
||||
Array ret;
|
||||
@@ -436,7 +442,7 @@ Value sendtoaddress(const Array& params, bool fHelp)
|
||||
// Wallet comments
|
||||
CWalletTx wtx;
|
||||
if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
|
||||
wtx.mapValue["message"] = params[2].get_str();
|
||||
wtx.mapValue["comment"] = params[2].get_str();
|
||||
if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
|
||||
wtx.mapValue["to"] = params[3].get_str();
|
||||
|
||||
@@ -522,7 +528,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
|
||||
nMinDepth = params[1].get_int();
|
||||
|
||||
// Get the set of pub keys that have the label
|
||||
string strAccount = params[0].get_str();
|
||||
string strAccount = AccountFromValue(params[0]);
|
||||
set<CScript> setPubKey;
|
||||
GetAccountPubKeys(strAccount, setPubKey);
|
||||
|
||||
@@ -549,9 +555,6 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
|
||||
|
||||
int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
|
||||
{
|
||||
set<CScript> setPubKey;
|
||||
GetAccountPubKeys(strAccount, setPubKey);
|
||||
|
||||
int64 nBalance = 0;
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
@@ -563,7 +566,7 @@ int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinD
|
||||
continue;
|
||||
|
||||
int64 nGenerated, nReceived, nSent, nFee;
|
||||
wtx.GetAccountAmounts(strAccount, setPubKey, nGenerated, nReceived, nSent, nFee);
|
||||
wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
|
||||
|
||||
if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
|
||||
nBalance += nReceived;
|
||||
@@ -595,7 +598,7 @@ Value getbalance(const Array& params, bool fHelp)
|
||||
if (params.size() == 0)
|
||||
return ((double)GetBalance() / (double)COIN);
|
||||
|
||||
string strAccount = params[0].get_str();
|
||||
string strAccount = AccountFromValue(params[0]);
|
||||
int nMinDepth = 1;
|
||||
if (params.size() > 1)
|
||||
nMinDepth = params[1].get_int();
|
||||
@@ -613,8 +616,8 @@ Value movecmd(const Array& params, bool fHelp)
|
||||
"move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
|
||||
"Move from one account in your wallet to another.");
|
||||
|
||||
string strFrom = params[0].get_str();
|
||||
string strTo = params[1].get_str();
|
||||
string strFrom = AccountFromValue(params[0]);
|
||||
string strTo = AccountFromValue(params[1]);
|
||||
int64 nAmount = AmountFromValue(params[2]);
|
||||
int nMinDepth = 1;
|
||||
if (params.size() > 3)
|
||||
@@ -647,19 +650,21 @@ Value movecmd(const Array& params, bool fHelp)
|
||||
|
||||
// Debit
|
||||
CAccountingEntry debit;
|
||||
debit.strAccount = strFrom;
|
||||
debit.nCreditDebit = -nAmount;
|
||||
debit.nTime = nNow;
|
||||
debit.strOtherAccount = strTo;
|
||||
debit.strComment = strComment;
|
||||
walletdb.WriteAccountingEntry(strFrom, debit);
|
||||
walletdb.WriteAccountingEntry(debit);
|
||||
|
||||
// Credit
|
||||
CAccountingEntry credit;
|
||||
credit.strAccount = strTo;
|
||||
credit.nCreditDebit = nAmount;
|
||||
credit.nTime = nNow;
|
||||
credit.strOtherAccount = strFrom;
|
||||
credit.strComment = strComment;
|
||||
walletdb.WriteAccountingEntry(strTo, credit);
|
||||
walletdb.WriteAccountingEntry(credit);
|
||||
|
||||
walletdb.TxnCommit();
|
||||
}
|
||||
@@ -674,7 +679,7 @@ Value sendfrom(const Array& params, bool fHelp)
|
||||
"sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
|
||||
"<amount> is a real and is rounded to the nearest 0.01");
|
||||
|
||||
string strAccount = params[0].get_str();
|
||||
string strAccount = AccountFromValue(params[0]);
|
||||
string strAddress = params[1].get_str();
|
||||
int64 nAmount = AmountFromValue(params[2]);
|
||||
int nMinDepth = 1;
|
||||
@@ -684,7 +689,7 @@ Value sendfrom(const Array& params, bool fHelp)
|
||||
CWalletTx wtx;
|
||||
wtx.strFromAccount = strAccount;
|
||||
if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
|
||||
wtx.mapValue["message"] = params[4].get_str();
|
||||
wtx.mapValue["comment"] = params[4].get_str();
|
||||
if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
|
||||
wtx.mapValue["to"] = params[5].get_str();
|
||||
|
||||
@@ -849,97 +854,180 @@ Value listreceivedbyaccount(const Array& params, bool fHelp)
|
||||
return ListReceived(params, true);
|
||||
}
|
||||
|
||||
void ListAccountTransactions(CWalletDB& walletdb, const string& strAccount, int nMinDepth, multimap<int64, Object>& ret)
|
||||
void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, Array& ret)
|
||||
{
|
||||
set<CScript> setPubKey;
|
||||
GetAccountPubKeys(strAccount, setPubKey);
|
||||
int64 nGenerated, nSent, nFee;
|
||||
string strSentAccount;
|
||||
list<pair<string, int64> > listReceived;
|
||||
wtx.GetAmounts(nGenerated, listReceived, nSent, nFee, strSentAccount);
|
||||
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
bool fAllAccounts = (strAccount == string("*"));
|
||||
|
||||
// Generated blocks assigned to account ""
|
||||
if (nGenerated != 0 && (fAllAccounts || strAccount == ""))
|
||||
{
|
||||
// Wallet: generate/send/receive transactions
|
||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||
Object entry;
|
||||
entry.push_back(Pair("account", string("")));
|
||||
entry.push_back(Pair("category", "generate"));
|
||||
entry.push_back(Pair("amount", ValueFromAmount(nGenerated)));
|
||||
WalletTxToJSON(wtx, entry);
|
||||
ret.push_back(entry);
|
||||
}
|
||||
|
||||
// Sent
|
||||
if ((nSent != 0 || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
|
||||
{
|
||||
Object entry;
|
||||
entry.push_back(Pair("account", strSentAccount));
|
||||
entry.push_back(Pair("category", "send"));
|
||||
entry.push_back(Pair("amount", ValueFromAmount(-nSent)));
|
||||
entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
|
||||
WalletTxToJSON(wtx, entry);
|
||||
ret.push_back(entry);
|
||||
}
|
||||
|
||||
// Received
|
||||
if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
{
|
||||
const CWalletTx& wtx = (*it).second;
|
||||
if (!wtx.IsFinal())
|
||||
continue;
|
||||
|
||||
int64 nGenerated, nReceived, nSent, nFee;
|
||||
wtx.GetAccountAmounts(strAccount, setPubKey, nGenerated, nReceived, nSent, nFee);
|
||||
|
||||
// Generated blocks count to account ""
|
||||
if (nGenerated != 0)
|
||||
{
|
||||
Object entry;
|
||||
entry.push_back(Pair("category", "generate"));
|
||||
entry.push_back(Pair("amount", ValueFromAmount(nGenerated)));
|
||||
WalletTxToJSON(wtx, entry);
|
||||
ret.insert(make_pair(wtx.GetTxTime(), entry));
|
||||
}
|
||||
|
||||
// Sent
|
||||
if (nSent != 0 || nFee != 0)
|
||||
{
|
||||
Object entry;
|
||||
entry.push_back(Pair("category", "send"));
|
||||
entry.push_back(Pair("amount", ValueFromAmount(-nSent)));
|
||||
entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
|
||||
WalletTxToJSON(wtx, entry);
|
||||
ret.insert(make_pair(wtx.GetTxTime(), entry));
|
||||
}
|
||||
|
||||
// Received
|
||||
if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
|
||||
{
|
||||
Object entry;
|
||||
entry.push_back(Pair("category", "receive"));
|
||||
entry.push_back(Pair("amount", ValueFromAmount(nReceived)));
|
||||
WalletTxToJSON(wtx, entry);
|
||||
ret.insert(make_pair(wtx.GetTxTime(), entry));
|
||||
}
|
||||
foreach(const PAIRTYPE(string, int64)& r, listReceived)
|
||||
if (mapAddressBook.count(r.first) && (fAllAccounts || r.first == strAccount))
|
||||
{
|
||||
Object entry;
|
||||
entry.push_back(Pair("account", r.first));
|
||||
entry.push_back(Pair("category", "receive"));
|
||||
entry.push_back(Pair("amount", ValueFromAmount(r.second)));
|
||||
WalletTxToJSON(wtx, entry);
|
||||
ret.push_back(entry);
|
||||
}
|
||||
}
|
||||
|
||||
// Internal accounting entries
|
||||
list<CAccountingEntry> acentries;
|
||||
walletdb.ListAccountCreditDebit(strAccount, acentries);
|
||||
foreach (const CAccountingEntry& acentry, acentries)
|
||||
{
|
||||
Object entry;
|
||||
entry.push_back(Pair("category", "move"));
|
||||
entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
|
||||
entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
|
||||
ret.insert(make_pair(acentry.nTime, entry));
|
||||
}
|
||||
}
|
||||
|
||||
void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
|
||||
{
|
||||
bool fAllAccounts = (strAccount == string("*"));
|
||||
|
||||
if (fAllAccounts || acentry.strAccount == strAccount)
|
||||
{
|
||||
Object entry;
|
||||
entry.push_back(Pair("account", acentry.strAccount));
|
||||
entry.push_back(Pair("category", "move"));
|
||||
entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
|
||||
entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
|
||||
entry.push_back(Pair("comment", acentry.strComment));
|
||||
ret.push_back(entry);
|
||||
}
|
||||
}
|
||||
|
||||
Value listtransactions(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||
if (fHelp || params.size() > 2)
|
||||
throw runtime_error(
|
||||
"listtransactions <account> [count=10]\n"
|
||||
"listtransactions [account] [count=10]\n"
|
||||
"Returns up to [count] most recent transactions for account <account>.");
|
||||
|
||||
string strAccount = params[0].get_str();
|
||||
string strAccount = "*";
|
||||
if (params.size() > 0)
|
||||
strAccount = params[0].get_str();
|
||||
int nCount = 10;
|
||||
if (params.size() > 1)
|
||||
nCount = params[1].get_int();
|
||||
|
||||
Array ret;
|
||||
CWalletDB walletdb;
|
||||
multimap<int64, Object> mapByTime; // keys are transaction time
|
||||
ListAccountTransactions(walletdb, strAccount, 0, mapByTime);
|
||||
|
||||
// Return only last nCount items:
|
||||
int nToErase = mapByTime.size()-nCount;
|
||||
if (nToErase > 0)
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
multimap<int64, Object>::iterator end = mapByTime.begin();
|
||||
std::advance(end, nToErase);
|
||||
mapByTime.erase(mapByTime.begin(), end);
|
||||
// Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
|
||||
typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
|
||||
typedef multimap<int64, TxPair > TxItems;
|
||||
TxItems txByTime;
|
||||
|
||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||
{
|
||||
CWalletTx* wtx = &((*it).second);
|
||||
txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, 0)));
|
||||
}
|
||||
list<CAccountingEntry> acentries;
|
||||
walletdb.ListAccountCreditDebit(strAccount, acentries);
|
||||
foreach(CAccountingEntry& entry, acentries)
|
||||
{
|
||||
txByTime.insert(make_pair(entry.nTime, TxPair(0, &entry)));
|
||||
}
|
||||
|
||||
// Now: iterate backwards until we have nCount items to return:
|
||||
for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
|
||||
{
|
||||
CWalletTx *const pwtx = (*it).second.first;
|
||||
if (pwtx != 0)
|
||||
ListTransactions(*pwtx, strAccount, 0, ret);
|
||||
CAccountingEntry *const pacentry = (*it).second.second;
|
||||
if (pacentry != 0)
|
||||
AcentryToJSON(*pacentry, strAccount, ret);
|
||||
|
||||
if (ret.size() >= nCount) break;
|
||||
}
|
||||
// ret is now newest to oldest
|
||||
}
|
||||
|
||||
// Make sure we return only last nCount items (sends-to-self might give us an extra):
|
||||
if (ret.size() > nCount)
|
||||
{
|
||||
Array::iterator last = ret.begin();
|
||||
std::advance(last, nCount);
|
||||
ret.erase(last, ret.end());
|
||||
}
|
||||
std::reverse(ret.begin(), ret.end()); // oldest to newest
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Value listaccounts(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() > 1)
|
||||
throw runtime_error(
|
||||
"listaccounts [minconf=1]\n"
|
||||
"Returns Object that has account names as keys, account balances as values.");
|
||||
|
||||
int nMinDepth = 1;
|
||||
if (params.size() > 1)
|
||||
nMinDepth = params[1].get_int();
|
||||
|
||||
map<string, int64> mapAccountBalances;
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||
{
|
||||
foreach(const PAIRTYPE(string, string)& entry, mapAddressBook)
|
||||
mapAccountBalances[entry.second] = 0;
|
||||
|
||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||
{
|
||||
const CWalletTx& wtx = (*it).second;
|
||||
int64 nGenerated, nSent, nFee;
|
||||
string strSentAccount;
|
||||
list<pair<string, int64> > listReceived;
|
||||
wtx.GetAmounts(nGenerated, listReceived, nSent, nFee, strSentAccount);
|
||||
mapAccountBalances[strSentAccount] -= nSent+nFee;
|
||||
if (wtx.GetDepthInMainChain() >= nMinDepth)
|
||||
{
|
||||
mapAccountBalances[""] += nGenerated;
|
||||
foreach(const PAIRTYPE(string, int64)& r, listReceived)
|
||||
if (mapAddressBook.count(r.first))
|
||||
mapAccountBalances[mapAddressBook[r.first]] += r.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Array ret;
|
||||
foreach(const PAIRTYPE(int64, Object)& item, mapByTime)
|
||||
ret.push_back(item.second);
|
||||
list<CAccountingEntry> acentries;
|
||||
CWalletDB().ListAccountCreditDebit("*", acentries);
|
||||
foreach(const CAccountingEntry& entry, acentries)
|
||||
mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
|
||||
|
||||
Object ret;
|
||||
foreach(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
|
||||
ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1175,6 +1263,7 @@ pair<string, rpcfn_type> pCallTable[] =
|
||||
make_pair("gettransaction", &gettransaction),
|
||||
make_pair("listtransactions", &listtransactions),
|
||||
make_pair("getwork", &getwork),
|
||||
make_pair("listaccounts", &listaccounts),
|
||||
};
|
||||
map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
|
||||
|
||||
@@ -1247,7 +1336,7 @@ string HTTPReply(int nStatus, const string& strMsg)
|
||||
"Server: bitcoin-json-rpc\r\n"
|
||||
"WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
|
||||
"Content-Type: text/html\r\n"
|
||||
"Content-Length: 311\r\n"
|
||||
"Content-Length: 296\r\n"
|
||||
"\r\n"
|
||||
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
|
||||
"\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
|
||||
@@ -1421,6 +1510,17 @@ string JSONRPCReply(const Value& result, const Value& error, const Value& id)
|
||||
return write_string(Value(reply), false) + "\n";
|
||||
}
|
||||
|
||||
void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
|
||||
{
|
||||
// Send error reply from json-rpc error object
|
||||
int nStatus = 500;
|
||||
int code = find_value(objError, "code").get_int();
|
||||
if (code == -32600) nStatus = 400;
|
||||
else if (code == -32601) nStatus = 404;
|
||||
string strReply = JSONRPCReply(Value::null, objError, id);
|
||||
stream << HTTPReply(nStatus, strReply) << std::flush;
|
||||
}
|
||||
|
||||
bool ClientAllowed(const string& strAddress)
|
||||
{
|
||||
if (strAddress == asio::ip::address_v4::loopback().to_string())
|
||||
@@ -1581,10 +1681,16 @@ void ThreadRPCServer2(void* parg)
|
||||
if (!ClientAllowed(peer.address().to_string()))
|
||||
continue;
|
||||
|
||||
// Receive request
|
||||
map<string, string> mapHeaders;
|
||||
string strRequest;
|
||||
ReadHTTP(stream, mapHeaders, strRequest);
|
||||
|
||||
boost::thread api_caller(ReadHTTP, ref(stream), ref(mapHeaders), ref(strRequest));
|
||||
if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
|
||||
{ // Timed out:
|
||||
acceptor.cancel();
|
||||
printf("ThreadRPCServer ReadHTTP timeout\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check authorization
|
||||
if (mapHeaders.count("Authorization") == 0)
|
||||
@@ -1656,26 +1762,16 @@ void ThreadRPCServer2(void* parg)
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
// Send error reply from method
|
||||
string strReply = JSONRPCReply(Value::null, JSONRPCError(-1, e.what()), id);
|
||||
stream << HTTPReply(500, strReply) << std::flush;
|
||||
ErrorReply(stream, JSONRPCError(-1, e.what()), id);
|
||||
}
|
||||
}
|
||||
catch (Object& objError)
|
||||
{
|
||||
// Send error reply from json-rpc error object
|
||||
int nStatus = 500;
|
||||
int code = find_value(objError, "code").get_int();
|
||||
if (code == -32600) nStatus = 400;
|
||||
else if (code == -32601) nStatus = 404;
|
||||
string strReply = JSONRPCReply(Value::null, objError, id);
|
||||
stream << HTTPReply(nStatus, strReply) << std::flush;
|
||||
ErrorReply(stream, objError, id);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
// Send error reply from other json-rpc parsing errors
|
||||
string strReply = JSONRPCReply(Value::null, JSONRPCError(-32700, e.what()), id);
|
||||
stream << HTTPReply(500, strReply) << std::flush;
|
||||
ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1812,6 +1908,7 @@ int CommandLineRPC(int argc, char *argv[])
|
||||
if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
|
||||
if (strMethod == "sendfrom" && n > 3) ConvertTo<boost::int64_t>(params[3]);
|
||||
if (strMethod == "listtransactions" && n > 1) ConvertTo<boost::int64_t>(params[1]);
|
||||
if (strMethod == "listaccounts" && n > 1) ConvertTo<boost::int64_t>(params[1]);
|
||||
|
||||
// Execute
|
||||
Object reply = CallRPC(strMethod, params);
|
||||
|
||||
Reference in New Issue
Block a user