2424
2525
2626namespace wallet {
27- std::vector<CRecipient> CreateRecipients (const UniValue& address_amounts , const UniValue & subtract_fee_outputs)
27+ std::vector<CRecipient> CreateRecipients (const std::vector<std::pair<CTxDestination, CAmount>>& outputs , const std::set< int > & subtract_fee_outputs)
2828{
2929 std::vector<CRecipient> recipients;
30- std::set<CTxDestination> destinations;
31- int i = 0 ;
32- for (const std::string& address: address_amounts.getKeys ()) {
33- CTxDestination dest = DecodeDestination (address);
34- if (!IsValidDestination (dest)) {
35- throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, std::string (" Invalid Bitcoin address: " ) + address);
36- }
37-
38- if (destinations.count (dest)) {
39- throw JSONRPCError (RPC_INVALID_PARAMETER, std::string (" Invalid parameter, duplicated address: " ) + address);
40- }
41- destinations.insert (dest);
42-
43- CAmount amount = AmountFromValue (address_amounts[i++]);
44-
45- bool subtract_fee = false ;
46- for (unsigned int idx = 0 ; idx < subtract_fee_outputs.size (); idx++) {
47- const UniValue& addr = subtract_fee_outputs[idx];
48- if (addr.get_str () == address) {
49- subtract_fee = true ;
50- }
51- }
52-
53- CRecipient recipient = {dest, amount, subtract_fee};
30+ for (size_t i = 0 ; i < outputs.size (); ++i) {
31+ const auto & [destination, amount] = outputs.at (i);
32+ CRecipient recipient{destination, amount, subtract_fee_outputs.contains (i)};
5433 recipients.push_back (recipient);
5534 }
5635 return recipients;
@@ -78,6 +57,27 @@ static void InterpretFeeEstimationInstructions(const UniValue& conf_target, cons
7857 }
7958}
8059
60+ std::set<int > InterpretSubtractFeeFromOutputInstructions (const UniValue& sffo_instructions, const std::vector<std::string>& destinations)
61+ {
62+ std::set<int > sffo_set;
63+ if (sffo_instructions.isNull ()) return sffo_set;
64+ if (sffo_instructions.isBool ()) {
65+ if (sffo_instructions.get_bool ()) sffo_set.insert (0 );
66+ return sffo_set;
67+ }
68+ for (const auto & sffo : sffo_instructions.getValues ()) {
69+ if (sffo.isStr ()) {
70+ for (size_t i = 0 ; i < destinations.size (); ++i) {
71+ if (sffo.get_str () == destinations.at (i)) {
72+ sffo_set.insert (i);
73+ break ;
74+ }
75+ }
76+ }
77+ }
78+ return sffo_set;
79+ }
80+
8181static UniValue FinishTransaction (const std::shared_ptr<CWallet> pwallet, const UniValue& options, const CMutableTransaction& rawTx)
8282{
8383 // Make a blank psbt
@@ -277,11 +277,6 @@ RPCHelpMan sendtoaddress()
277277 if (!request.params [3 ].isNull () && !request.params [3 ].get_str ().empty ())
278278 mapValue[" to" ] = request.params [3 ].get_str ();
279279
280- bool fSubtractFeeFromAmount = false ;
281- if (!request.params [4 ].isNull ()) {
282- fSubtractFeeFromAmount = request.params [4 ].get_bool ();
283- }
284-
285280 CCoinControl coin_control;
286281 if (!request.params [5 ].isNull ()) {
287282 coin_control.m_signal_bip125_rbf = request.params [5 ].get_bool ();
@@ -298,12 +293,10 @@ RPCHelpMan sendtoaddress()
298293 UniValue address_amounts (UniValue::VOBJ);
299294 const std::string address = request.params [0 ].get_str ();
300295 address_amounts.pushKV (address, request.params [1 ]);
301- UniValue subtractFeeFromAmount (UniValue::VARR);
302- if (fSubtractFeeFromAmount ) {
303- subtractFeeFromAmount.push_back (address);
304- }
305-
306- std::vector<CRecipient> recipients = CreateRecipients (address_amounts, subtractFeeFromAmount);
296+ std::vector<CRecipient> recipients = CreateRecipients (
297+ ParseOutputs (address_amounts),
298+ InterpretSubtractFeeFromOutputInstructions (request.params [4 ], address_amounts.getKeys ())
299+ );
307300 const bool verbose{request.params [10 ].isNull () ? false : request.params [10 ].get_bool ()};
308301
309302 return SendMoney (*pwallet, coin_control, recipients, mapValue, verbose);
@@ -387,18 +380,17 @@ RPCHelpMan sendmany()
387380 if (!request.params [3 ].isNull () && !request.params [3 ].get_str ().empty ())
388381 mapValue[" comment" ] = request.params [3 ].get_str ();
389382
390- UniValue subtractFeeFromAmount (UniValue::VARR);
391- if (!request.params [4 ].isNull ())
392- subtractFeeFromAmount = request.params [4 ].get_array ();
393-
394383 CCoinControl coin_control;
395384 if (!request.params [5 ].isNull ()) {
396385 coin_control.m_signal_bip125_rbf = request.params [5 ].get_bool ();
397386 }
398387
399388 SetFeeEstimateMode (*pwallet, coin_control, /* conf_target=*/ request.params [6 ], /* estimate_mode=*/ request.params [7 ], /* fee_rate=*/ request.params [8 ], /* override_min_fee=*/ false );
400389
401- std::vector<CRecipient> recipients = CreateRecipients (sendTo, subtractFeeFromAmount);
390+ std::vector<CRecipient> recipients = CreateRecipients (
391+ ParseOutputs (sendTo),
392+ InterpretSubtractFeeFromOutputInstructions (request.params [4 ], sendTo.getKeys ())
393+ );
402394 const bool verbose{request.params [9 ].isNull () ? false : request.params [9 ].get_bool ()};
403395
404396 return SendMoney (*pwallet, coin_control, recipients, std::move (mapValue), verbose);
0 commit comments