24
24
25
25
26
26
namespace 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)
28
28
{
29
29
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)};
54
33
recipients.push_back (recipient);
55
34
}
56
35
return recipients;
@@ -78,6 +57,27 @@ static void InterpretFeeEstimationInstructions(const UniValue& conf_target, cons
78
57
}
79
58
}
80
59
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
+
81
81
static UniValue FinishTransaction (const std::shared_ptr<CWallet> pwallet, const UniValue& options, const CMutableTransaction& rawTx)
82
82
{
83
83
// Make a blank psbt
@@ -277,11 +277,6 @@ RPCHelpMan sendtoaddress()
277
277
if (!request.params [3 ].isNull () && !request.params [3 ].get_str ().empty ())
278
278
mapValue[" to" ] = request.params [3 ].get_str ();
279
279
280
- bool fSubtractFeeFromAmount = false ;
281
- if (!request.params [4 ].isNull ()) {
282
- fSubtractFeeFromAmount = request.params [4 ].get_bool ();
283
- }
284
-
285
280
CCoinControl coin_control;
286
281
if (!request.params [5 ].isNull ()) {
287
282
coin_control.m_signal_bip125_rbf = request.params [5 ].get_bool ();
@@ -298,12 +293,10 @@ RPCHelpMan sendtoaddress()
298
293
UniValue address_amounts (UniValue::VOBJ);
299
294
const std::string address = request.params [0 ].get_str ();
300
295
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
+ );
307
300
const bool verbose{request.params [10 ].isNull () ? false : request.params [10 ].get_bool ()};
308
301
309
302
return SendMoney (*pwallet, coin_control, recipients, mapValue, verbose);
@@ -387,18 +380,17 @@ RPCHelpMan sendmany()
387
380
if (!request.params [3 ].isNull () && !request.params [3 ].get_str ().empty ())
388
381
mapValue[" comment" ] = request.params [3 ].get_str ();
389
382
390
- UniValue subtractFeeFromAmount (UniValue::VARR);
391
- if (!request.params [4 ].isNull ())
392
- subtractFeeFromAmount = request.params [4 ].get_array ();
393
-
394
383
CCoinControl coin_control;
395
384
if (!request.params [5 ].isNull ()) {
396
385
coin_control.m_signal_bip125_rbf = request.params [5 ].get_bool ();
397
386
}
398
387
399
388
SetFeeEstimateMode (*pwallet, coin_control, /* conf_target=*/ request.params [6 ], /* estimate_mode=*/ request.params [7 ], /* fee_rate=*/ request.params [8 ], /* override_min_fee=*/ false );
400
389
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
+ );
402
394
const bool verbose{request.params [9 ].isNull () ? false : request.params [9 ].get_bool ()};
403
395
404
396
return SendMoney (*pwallet, coin_control, recipients, std::move (mapValue), verbose);
0 commit comments