Skip to content

Commit

Permalink
[RPC] Add fSubtractFeeFromAmount to sendmany (transparent)
Browse files Browse the repository at this point in the history
and fix fIncludeDelegated (5-th parameter, index 4)
  • Loading branch information
random-zebra committed Jun 9, 2021
1 parent 7e30e3f commit 6fff9f5
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 8 deletions.
1 change: 1 addition & 0 deletions src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ static const CRPCConvertParam vRPCConvertParams[] = {
{ "rescanblockchain", 1, "stop_height"},
{ "sendmany", 1, "amounts" },
{ "sendmany", 2, "minconf" },
{ "sendmany", 5, "subtract_fee_from" },
{ "sendrawtransaction", 1, "allowhighfees" },
{ "sendtoaddress", 1, "amount" },
{ "sendtoaddress", 4, "subtract_fee" },
Expand Down
33 changes: 27 additions & 6 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2261,7 +2261,7 @@ UniValue getunconfirmedbalance(const JSONRPCRequest& request)
/*
* Only used for t->t transactions (via sendmany RPC)
*/
static UniValue legacy_sendmany(CWallet* const pwallet, const UniValue& sendTo, int nMinDepth, std::string comment, bool fIncludeDelegated)
static UniValue legacy_sendmany(CWallet* const pwallet, const UniValue& sendTo, int nMinDepth, std::string comment, bool fIncludeDelegated, const UniValue& subtractFeeFromAmount)
{
LOCK2(cs_main, pwallet->cs_wallet);

Expand Down Expand Up @@ -2290,7 +2290,16 @@ static UniValue legacy_sendmany(CWallet* const pwallet, const UniValue& sendTo,
CAmount nAmount = AmountFromValue(sendTo[name_]);
totalAmount += nAmount;

vecSend.emplace_back(scriptPubKey, nAmount, false);
bool fSubtractFeeFromAmount = false;
for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
const UniValue& addr = subtractFeeFromAmount[idx];
if (addr.get_str() == name_) {
fSubtractFeeFromAmount = true;
break;
}
}

vecSend.emplace_back(scriptPubKey, nAmount, fSubtractFeeFromAmount);
}

// Check funds
Expand Down Expand Up @@ -2334,7 +2343,7 @@ UniValue sendmany(const JSONRPCRequest& request)
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
return NullUniValue;

if (request.fHelp || request.params.size() < 2 || request.params.size() > 5)
if (request.fHelp || request.params.size() < 2 || request.params.size() > 6)
throw std::runtime_error(
"sendmany \"\" {\"address\":amount,...} ( minconf \"comment\" include_delegated )\n"
"\nSend to multiple destinations. Recipients are transparent or shield PIVX addresses.\n"
Expand All @@ -2352,6 +2361,14 @@ UniValue sendmany(const JSONRPCRequest& request)
"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. include_delegated (bool, optional, default=false) Also include balance delegated to cold stakers\n"
"6. subtract_fee_from (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 PIV 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"
"\"transactionid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
Expand Down Expand Up @@ -2382,7 +2399,11 @@ UniValue sendmany(const JSONRPCRequest& request)
const int nMinDepth = request.params.size() > 2 ? request.params[2].get_int() : 1;
const std::string comment = (request.params.size() > 3 && !request.params[3].isNull() && !request.params[3].get_str().empty()) ?
request.params[3].get_str() : "";
const bool fIncludeDelegated = (request.params.size() > 5 && request.params[5].get_bool());
const bool fIncludeDelegated = (request.params.size() > 4 && request.params[4].get_bool());

UniValue subtractFeeFromAmount(UniValue::VARR);
if (request.params.size() > 5 && !request.params[5].isNull())
subtractFeeFromAmount = request.params[5].get_array();

// Check if any recipient address is shield
bool fShieldSend = false;
Expand All @@ -2400,7 +2421,7 @@ UniValue sendmany(const JSONRPCRequest& request)
}

// All recipients are transparent: use Legacy sendmany t->t
return legacy_sendmany(pwallet, sendTo, nMinDepth, comment, fIncludeDelegated);
return legacy_sendmany(pwallet, sendTo, nMinDepth, comment, fIncludeDelegated, subtractFeeFromAmount);
}

// Defined in rpc/misc.cpp
Expand Down Expand Up @@ -4712,7 +4733,7 @@ static const CRPCCommand commands[] =
{ "wallet", "listwallets", &listwallets, true, {} },
{ "wallet", "lockunspent", &lockunspent, true, {"unlock","transactions"} },
{ "wallet", "rawdelegatestake", &rawdelegatestake, false, {"staking_addr","amount","owner_addr","ext_owner","include_delegated","from_shield","force"} },
{ "wallet", "sendmany", &sendmany, false, {"dummy","amounts","minconf","comment","include_delegated"} },
{ "wallet", "sendmany", &sendmany, false, {"dummy","amounts","minconf","comment","include_delegated","subtract_fee_from"} },
{ "wallet", "sendtoaddress", &sendtoaddress, false, {"address","amount","comment","comment-to","subtract_fee"} },
{ "wallet", "settxfee", &settxfee, true, {"amount"} },
{ "wallet", "setstakesplitthreshold", &setstakesplitthreshold, false, {"value"} },
Expand Down
22 changes: 20 additions & 2 deletions test/functional/wallet_listtransactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,9 @@ def run_test(self):
txs = [tx for tx in self.nodes[0].listtransactions("*", 100, 0, True) if "label" in tx and tx['label'] == 'watchonly']
assert_array_result(txs, {"category": "receive", "amount": Decimal("0.1")}, {"txid": txid})

# Send 10 PIV with subtract fee from amount
node_0_bal = self.nodes[0].getbalance()
node_1_bal = self.nodes[1].getbalance()

# Send 10 PIV with subtract fee from amount
self.log.info("test sendtoaddress with subtract-fee-from-amt")
txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 10, "", "", True)
node_0_bal -= Decimal('10')
Expand All @@ -115,6 +114,25 @@ def run_test(self):
{"txid": txid},
{"category": "receive", "amount": + Decimal('10') + fee, "confirmations": 1})

# Sendmany 10 PIV with subtract fee from amount
node_0_bal = self.nodes[0].getbalance()
node_1_bal = self.nodes[1].getbalance()
self.log.info("test sendmany with subtract-fee-from-amt")
address = self.nodes[1].getnewaddress()
txid = self.nodes[0].sendmany('', {address: 10}, 1, "", False, [address])
node_0_bal -= Decimal('10')
assert_equal(self.nodes[0].getbalance(), node_0_bal)
self.nodes[0].generate(1)
self.sync_all()
fee = self.nodes[0].gettransaction(txid)["fee"] # fee < 0
node_1_bal += (Decimal('10') + fee)
assert_equal(self.nodes[1].getbalance(), node_1_bal)
assert_array_result(self.nodes[0].listtransactions(),
{"txid": txid},
{"category": "send", "amount": - Decimal('10') - fee, "confirmations": 1})
assert_array_result(self.nodes[1].listtransactions(),
{"txid": txid},
{"category": "receive", "amount": + Decimal('10') + fee, "confirmations": 1})

if __name__ == '__main__':
ListTransactionsTest().main()

0 comments on commit 6fff9f5

Please sign in to comment.