Skip to content

Commit

Permalink
Merge pull request bitcoin#220 from qtumproject/neil/add-sendmanywith…
Browse files Browse the repository at this point in the history
…dupes-rpc-call

Add sendmanywithdupes rpc call
  • Loading branch information
Earlz committed Jun 30, 2017
2 parents 2c15f54 + 064a578 commit 3f44ebf
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 4 deletions.
3 changes: 3 additions & 0 deletions src/rpc/client.cpp
Expand Up @@ -74,6 +74,9 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "sendmany", 1, "amounts" },
{ "sendmany", 2, "minconf" },
{ "sendmany", 4, "subtractfeefrom" },
{ "sendmanywithdupes", 1, "amounts" },
{ "sendmanywithdupes", 2, "minconf" },
{ "sendmanywithdupes", 4, "subtractfeefrom" },
{ "addmultisigaddress", 0, "nrequired" },
{ "addmultisigaddress", 1, "keys" },
{ "createmultisig", 0, "nrequired" },
Expand Down
122 changes: 118 additions & 4 deletions src/wallet/rpcwallet.cpp
Expand Up @@ -1269,13 +1269,13 @@ UniValue sendmany(const JSONRPCRequest& request)
" the number of addresses.\n"
"\nExamples:\n"
"\nSend two amounts to two different addresses:\n"
+ HelpExampleCli("sendmany", "\"\" \"{\\\"QD1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
+ HelpExampleCli("sendmany", "\"\" \"{\\\"QD1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"Q353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
"\nSend two amounts to two different addresses setting the confirmation and comment:\n"
+ HelpExampleCli("sendmany", "\"\" \"{\\\"QD1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
+ HelpExampleCli("sendmany", "\"\" \"{\\\"QD1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"Q353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
"\nSend two amounts to two different addresses, subtract fee from amount:\n"
+ HelpExampleCli("sendmany", "\"\" \"{\\\"QD1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"QD1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\",\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") +
+ HelpExampleCli("sendmany", "\"\" \"{\\\"QD1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"Q353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"QD1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\",\\\"Q353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") +
"\nAs a json rpc call\n"
+ HelpExampleRpc("sendmany", "\"\", \"{\\\"QD1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
+ HelpExampleRpc("sendmany", "\"\", \"{\\\"QD1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"Q353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
);

LOCK2(cs_main, pwalletMain->cs_wallet);
Expand Down Expand Up @@ -1353,7 +1353,120 @@ UniValue sendmany(const JSONRPCRequest& request)

return wtx.GetHash().GetHex();
}
UniValue sendmanywithdupes(const JSONRPCRequest& request)
{
if (!EnsureWalletIsAvailable(request.fHelp))
return NullUniValue;

if (request.fHelp || request.params.size() < 2 || request.params.size() > 5)
throw runtime_error(
"sendmanywithdupes \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] )\n"
"\nSend multiple times. Amounts are double-precision floating point numbers. Supports duplicate addresses"
+ HelpRequiringPassphrase() + "\n"
"\nArguments:\n"
"1. \"fromaccount\" (string, required) DEPRECATED. The account to send the funds from. Should be \"\" for the default account\n"
"2. \"amounts\" (string, required) A json object with addresses and amounts\n"
" {\n"
" \"address\":amount (numeric or string) The qtum address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value\n"
" ,...\n"
" }\n"
"3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
"4. \"comment\" (string, optional) A comment\n"
"5. subtractfeefrom (array, optional) A json array with addresses.\n"
" The fee will be equally deducted from the amount of each selected address.\n"
" Those recipients will receive less qtums than you enter in their corresponding amount field.\n"
" If no addresses are specified here, the sender pays the fee.\n"
" [\n"
" \"address\" (string) Subtract fee from this address\n"
" ,...\n"
" ]\n"
"\nResult:\n"
"\"txid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
" the number of addresses.\n"
"\nExamples:\n"
"\nSend two amounts to two different addresses:\n"
+ HelpExampleCli("sendmanywithdupes", "\"\" \"{\\\"QD1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"Q353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
"\nSend two amounts to two different addresses setting the confirmation and comment:\n"
+ HelpExampleCli("sendmanywithdupes", "\"\" \"{\\\"QD1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"Q353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
"\nSend two amounts to two different addresses, subtract fee from amount:\n"
+ HelpExampleCli("sendmanywithdupes", "\"\" \"{\\\"QD1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"Q353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"QD1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\",\\\"Q353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") +
"\nAs a json rpc call\n"
+ HelpExampleRpc("sendmanywithdupes", "\"\", \"{\\\"QD1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"Q353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
);

LOCK2(cs_main, pwalletMain->cs_wallet);

if (pwalletMain->GetBroadcastTransactions() && !g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");

string strAccount = AccountFromValue(request.params[0]);
UniValue sendTo = request.params[1].get_obj();
int nMinDepth = 1;
if (request.params.size() > 2)
nMinDepth = request.params[2].get_int();

CWalletTx wtx;
wtx.strFromAccount = strAccount;
if (request.params.size() > 3 && !request.params[3].isNull() && !request.params[3].get_str().empty())
wtx.mapValue["comment"] = request.params[3].get_str();

UniValue subtractFeeFromAmount(UniValue::VARR);
if (request.params.size() > 4)
subtractFeeFromAmount = request.params[4].get_array();

set<CBitcoinAddress> setAddress;
vector<CRecipient> vecSend;

CAmount totalAmount = 0;
vector<string> keys = sendTo.getKeys();
BOOST_FOREACH(const string& name_, keys)
{
CBitcoinAddress address(name_);
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Qtum address: ")+name_);

setAddress.insert(address);

CScript scriptPubKey = GetScriptForDestination(address.Get());
CAmount nAmount = AmountFromValue(sendTo[name_]);
if (nAmount <= 0)
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
totalAmount += nAmount;

bool fSubtractFeeFromAmount = false;
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);
}

EnsureWalletIsUnlocked();

// Check funds
CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
if (totalAmount > nBalance)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");

// Send
CReserveKey keyChange(pwalletMain);
CAmount nFeeRequired = 0;
int nChangePosRet = -1;
string strFailReason;
bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason);
if (!fCreated)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
CValidationState state;
if (!pwalletMain->CommitTransaction(wtx, keyChange, g_connman.get(), state)) {
strFailReason = strprintf("Transaction commit failed:: %s", state.GetRejectReason());
throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
}

return wtx.GetHash().GetHex();
}
// Defined in rpc/misc.cpp
extern CScript _createmultisig_redeemScript(const UniValue& params);

Expand Down Expand Up @@ -3448,6 +3561,7 @@ static const CRPCCommand commands[] =
{ "wallet", "reservebalance", &reservebalance, false, {"reserve", "amount"}},
{ "wallet", "sendfrom", &sendfrom, false, {"fromaccount","toaddress","amount","minconf","comment","comment_to"} },
{ "wallet", "sendmany", &sendmany, false, {"fromaccount","amounts","minconf","comment","subtractfeefrom"} },
{ "wallet", "sendmanywithdupes", &sendmanywithdupes, false, {"fromaccount","amounts","minconf","comment","subtractfeefrom"} },
{ "wallet", "sendtoaddress", &sendtoaddress, false, {"address","amount","comment","comment_to","subtractfeefromamount"} },
{ "wallet", "setaccount", &setaccount, true, {"address","account"} },
{ "wallet", "settxfee", &settxfee, true, {"amount"} },
Expand Down

0 comments on commit 3f44ebf

Please sign in to comment.