Skip to content

Commit 6fff9f5

Browse files
committed
[RPC] Add fSubtractFeeFromAmount to sendmany (transparent)
and fix fIncludeDelegated (5-th parameter, index 4)
1 parent 7e30e3f commit 6fff9f5

File tree

3 files changed

+48
-8
lines changed

3 files changed

+48
-8
lines changed

src/rpc/client.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ static const CRPCConvertParam vRPCConvertParams[] = {
134134
{ "rescanblockchain", 1, "stop_height"},
135135
{ "sendmany", 1, "amounts" },
136136
{ "sendmany", 2, "minconf" },
137+
{ "sendmany", 5, "subtract_fee_from" },
137138
{ "sendrawtransaction", 1, "allowhighfees" },
138139
{ "sendtoaddress", 1, "amount" },
139140
{ "sendtoaddress", 4, "subtract_fee" },

src/wallet/rpcwallet.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2261,7 +2261,7 @@ UniValue getunconfirmedbalance(const JSONRPCRequest& request)
22612261
/*
22622262
* Only used for t->t transactions (via sendmany RPC)
22632263
*/
2264-
static UniValue legacy_sendmany(CWallet* const pwallet, const UniValue& sendTo, int nMinDepth, std::string comment, bool fIncludeDelegated)
2264+
static UniValue legacy_sendmany(CWallet* const pwallet, const UniValue& sendTo, int nMinDepth, std::string comment, bool fIncludeDelegated, const UniValue& subtractFeeFromAmount)
22652265
{
22662266
LOCK2(cs_main, pwallet->cs_wallet);
22672267

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

2293-
vecSend.emplace_back(scriptPubKey, nAmount, false);
2293+
bool fSubtractFeeFromAmount = false;
2294+
for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) {
2295+
const UniValue& addr = subtractFeeFromAmount[idx];
2296+
if (addr.get_str() == name_) {
2297+
fSubtractFeeFromAmount = true;
2298+
break;
2299+
}
2300+
}
2301+
2302+
vecSend.emplace_back(scriptPubKey, nAmount, fSubtractFeeFromAmount);
22942303
}
22952304

22962305
// Check funds
@@ -2334,7 +2343,7 @@ UniValue sendmany(const JSONRPCRequest& request)
23342343
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
23352344
return NullUniValue;
23362345

2337-
if (request.fHelp || request.params.size() < 2 || request.params.size() > 5)
2346+
if (request.fHelp || request.params.size() < 2 || request.params.size() > 6)
23382347
throw std::runtime_error(
23392348
"sendmany \"\" {\"address\":amount,...} ( minconf \"comment\" include_delegated )\n"
23402349
"\nSend to multiple destinations. Recipients are transparent or shield PIVX addresses.\n"
@@ -2352,6 +2361,14 @@ UniValue sendmany(const JSONRPCRequest& request)
23522361
"3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
23532362
"4. \"comment\" (string, optional) A comment\n"
23542363
"5. include_delegated (bool, optional, default=false) Also include balance delegated to cold stakers\n"
2364+
"6. subtract_fee_from (array, optional) A json array with addresses.\n"
2365+
" The fee will be equally deducted from the amount of each selected address.\n"
2366+
" Those recipients will receive less PIV than you enter in their corresponding amount field.\n"
2367+
" If no addresses are specified here, the sender pays the fee.\n"
2368+
" [\n"
2369+
" \"address\" (string) Subtract fee from this address\n"
2370+
" ,...\n"
2371+
" ]\n"
23552372

23562373
"\nResult:\n"
23572374
"\"transactionid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
@@ -2382,7 +2399,11 @@ UniValue sendmany(const JSONRPCRequest& request)
23822399
const int nMinDepth = request.params.size() > 2 ? request.params[2].get_int() : 1;
23832400
const std::string comment = (request.params.size() > 3 && !request.params[3].isNull() && !request.params[3].get_str().empty()) ?
23842401
request.params[3].get_str() : "";
2385-
const bool fIncludeDelegated = (request.params.size() > 5 && request.params[5].get_bool());
2402+
const bool fIncludeDelegated = (request.params.size() > 4 && request.params[4].get_bool());
2403+
2404+
UniValue subtractFeeFromAmount(UniValue::VARR);
2405+
if (request.params.size() > 5 && !request.params[5].isNull())
2406+
subtractFeeFromAmount = request.params[5].get_array();
23862407

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

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

24062427
// Defined in rpc/misc.cpp
@@ -4712,7 +4733,7 @@ static const CRPCCommand commands[] =
47124733
{ "wallet", "listwallets", &listwallets, true, {} },
47134734
{ "wallet", "lockunspent", &lockunspent, true, {"unlock","transactions"} },
47144735
{ "wallet", "rawdelegatestake", &rawdelegatestake, false, {"staking_addr","amount","owner_addr","ext_owner","include_delegated","from_shield","force"} },
4715-
{ "wallet", "sendmany", &sendmany, false, {"dummy","amounts","minconf","comment","include_delegated"} },
4736+
{ "wallet", "sendmany", &sendmany, false, {"dummy","amounts","minconf","comment","include_delegated","subtract_fee_from"} },
47164737
{ "wallet", "sendtoaddress", &sendtoaddress, false, {"address","amount","comment","comment-to","subtract_fee"} },
47174738
{ "wallet", "settxfee", &settxfee, true, {"amount"} },
47184739
{ "wallet", "setstakesplitthreshold", &setstakesplitthreshold, false, {"value"} },

test/functional/wallet_listtransactions.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,9 @@ def run_test(self):
9595
txs = [tx for tx in self.nodes[0].listtransactions("*", 100, 0, True) if "label" in tx and tx['label'] == 'watchonly']
9696
assert_array_result(txs, {"category": "receive", "amount": Decimal("0.1")}, {"txid": txid})
9797

98+
# Send 10 PIV with subtract fee from amount
9899
node_0_bal = self.nodes[0].getbalance()
99100
node_1_bal = self.nodes[1].getbalance()
100-
101-
# Send 10 PIV with subtract fee from amount
102101
self.log.info("test sendtoaddress with subtract-fee-from-amt")
103102
txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 10, "", "", True)
104103
node_0_bal -= Decimal('10')
@@ -115,6 +114,25 @@ def run_test(self):
115114
{"txid": txid},
116115
{"category": "receive", "amount": + Decimal('10') + fee, "confirmations": 1})
117116

117+
# Sendmany 10 PIV with subtract fee from amount
118+
node_0_bal = self.nodes[0].getbalance()
119+
node_1_bal = self.nodes[1].getbalance()
120+
self.log.info("test sendmany with subtract-fee-from-amt")
121+
address = self.nodes[1].getnewaddress()
122+
txid = self.nodes[0].sendmany('', {address: 10}, 1, "", False, [address])
123+
node_0_bal -= Decimal('10')
124+
assert_equal(self.nodes[0].getbalance(), node_0_bal)
125+
self.nodes[0].generate(1)
126+
self.sync_all()
127+
fee = self.nodes[0].gettransaction(txid)["fee"] # fee < 0
128+
node_1_bal += (Decimal('10') + fee)
129+
assert_equal(self.nodes[1].getbalance(), node_1_bal)
130+
assert_array_result(self.nodes[0].listtransactions(),
131+
{"txid": txid},
132+
{"category": "send", "amount": - Decimal('10') - fee, "confirmations": 1})
133+
assert_array_result(self.nodes[1].listtransactions(),
134+
{"txid": txid},
135+
{"category": "receive", "amount": + Decimal('10') + fee, "confirmations": 1})
118136

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

0 commit comments

Comments
 (0)