aboutsummaryrefslogtreecommitdiff
path: root/rpc.cpp
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2010-12-16 15:48:04 -0500
committerGavin Andresen <gavinandresen@gmail.com>2011-03-13 17:11:49 -0400
commitb931ed8563eff9021ce3b1a05d8e6bc21117dc71 (patch)
tree7f9a4ce236cf5aafdd4c181ba04d09573b95a9f4 /rpc.cpp
parentf4f2987273a92c81a2e5c8b137010841e95687d0 (diff)
downloadbitcoin-b931ed8563eff9021ce3b1a05d8e6bc21117dc71.tar.xz
sendmany RPC command, to send to multiple recipients in one transaction.
Diffstat (limited to 'rpc.cpp')
-rw-r--r--rpc.cpp73
1 files changed, 73 insertions, 0 deletions
diff --git a/rpc.cpp b/rpc.cpp
index dd94acc050..97710ff6b8 100644
--- a/rpc.cpp
+++ b/rpc.cpp
@@ -768,6 +768,69 @@ Value sendfrom(const Array& params, bool fHelp)
return wtx.GetHash().GetHex();
}
+Value sendmany(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() < 2 || params.size() > 4)
+ throw runtime_error(
+ "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
+ "amounts are double-precision floating point numbers");
+
+ string strAccount = AccountFromValue(params[0]);
+ Object 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())
+ wtx.mapValue["comment"] = params[3].get_str();
+
+ set<string> setAddress;
+ vector<pair<CScript, int64> > vecSend;
+
+ int64 totalAmount = 0;
+ foreach(const Pair& s, sendTo)
+ {
+ uint160 hash160;
+ string strAddress = s.name_;
+
+ if (setAddress.count(strAddress))
+ throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+strAddress);
+ setAddress.insert(strAddress);
+
+ CScript scriptPubKey;
+ if (!scriptPubKey.SetBitcoinAddress(strAddress))
+ throw JSONRPCError(-5, string("Invalid bitcoin address:")+strAddress);
+ int64 nAmount = AmountFromValue(s.value_);
+ totalAmount += nAmount;
+
+ vecSend.push_back(make_pair(scriptPubKey, nAmount));
+ }
+
+ CRITICAL_BLOCK(cs_mapWallet)
+ {
+ // Check funds
+ int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
+ if (totalAmount > nBalance)
+ throw JSONRPCError(-6, "Account has insufficient funds");
+
+ // Send
+ CReserveKey keyChange;
+ int64 nFeeRequired = 0;
+ bool fCreated = CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
+ if (!fCreated)
+ {
+ if (totalAmount + nFeeRequired > GetBalance())
+ throw JSONRPCError(-6, "Insufficient funds");
+ throw JSONRPCError(-4, "Transaction creation failed");
+ }
+ if (!CommitTransaction(wtx, keyChange))
+ throw JSONRPCError(-4, "Transaction commit failed");
+ }
+
+ return wtx.GetHash().GetHex();
+}
struct tallyitem
@@ -1344,6 +1407,7 @@ pair<string, rpcfn_type> pCallTable[] =
make_pair("getbalance", &getbalance),
make_pair("move", &movecmd),
make_pair("sendfrom", &sendfrom),
+ make_pair("sendmany", &sendmany),
make_pair("gettransaction", &gettransaction),
make_pair("listtransactions", &listtransactions),
make_pair("getwork", &getwork),
@@ -1995,6 +2059,15 @@ int CommandLineRPC(int argc, char *argv[])
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 > 0) ConvertTo<boost::int64_t>(params[0]);
+ if (strMethod == "sendmany" && n > 1)
+ {
+ string s = params[1].get_str();
+ Value v;
+ if (!read_string(s, v) || v.type() != obj_type)
+ throw runtime_error("type mismatch");
+ params[1] = v.get_obj();
+ }
+ if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
// Execute
Object reply = CallRPC(strMethod, params);