@@ -321,36 +321,54 @@ static UniValue setlabel(const JSONRPCRequest& request)
321321 return NullUniValue;
322322}
323323
324+ void ParseRecipients (const UniValue& address_amounts, const UniValue& subtract_fee_outputs, std::vector<CRecipient> &recipients) {
325+ std::set<CTxDestination> destinations;
326+ int i = 0 ;
327+ for (const std::string& address: address_amounts.getKeys ()) {
328+ CTxDestination dest = DecodeDestination (address);
329+ if (!IsValidDestination (dest)) {
330+ throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, std::string (" Invalid Bitcoin address: " ) + address);
331+ }
324332
325- static CTransactionRef SendMoney (CWallet* const pwallet, const CTxDestination& address, CAmount nValue, bool fSubtractFeeFromAmount , const CCoinControl& coin_control, mapValue_t mapValue)
326- {
327- CAmount curBalance = pwallet->GetBalance (0 , coin_control.m_avoid_address_reuse ).m_mine_trusted ;
333+ if (destinations.count (dest)) {
334+ throw JSONRPCError (RPC_INVALID_PARAMETER, std::string (" Invalid parameter, duplicated address: " ) + address);
335+ }
336+ destinations.insert (dest);
328337
329- // Check amount
330- if (nValue <= 0 )
331- throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid amount" );
338+ CScript script_pub_key = GetScriptForDestination (dest);
339+ CAmount amount = AmountFromValue (address_amounts[i++]);
332340
333- if (nValue > curBalance)
334- throw JSONRPCError (RPC_WALLET_INSUFFICIENT_FUNDS, " Insufficient funds" );
341+ bool subtract_fee = false ;
342+ for (unsigned int idx = 0 ; idx < subtract_fee_outputs.size (); idx++) {
343+ const UniValue& addr = subtract_fee_outputs[idx];
344+ if (addr.get_str () == address) {
345+ subtract_fee = true ;
346+ }
347+ }
335348
336- // Parse Bitcoin address
337- CScript scriptPubKey = GetScriptForDestination (address);
349+ CRecipient recipient = {script_pub_key, amount, subtract_fee};
350+ recipients.push_back (recipient);
351+ }
352+ }
353+
354+ UniValue SendMoney (CWallet* const pwallet, const CCoinControl &coin_control, std::vector<CRecipient> &recipients, mapValue_t map_value)
355+ {
356+ EnsureWalletIsUnlocked (pwallet);
338357
339- // Create and send the transaction
358+ // Shuffle recipient list
359+ std::shuffle (recipients.begin (), recipients.end (), FastRandomContext ());
360+
361+ // Send
340362 CAmount nFeeRequired = 0 ;
341- bilingual_str error;
342- std::vector<CRecipient> vecSend;
343363 int nChangePosRet = -1 ;
344- CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount };
345- vecSend.push_back (recipient);
364+ bilingual_str error;
346365 CTransactionRef tx;
347- if (!pwallet->CreateTransaction (vecSend, tx, nFeeRequired, nChangePosRet, error, coin_control)) {
348- if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
349- error = strprintf (Untranslated (" Error: This transaction requires a transaction fee of at least %s" ), FormatMoney (nFeeRequired));
350- throw JSONRPCError (RPC_WALLET_ERROR, error.original );
366+ bool fCreated = pwallet->CreateTransaction (recipients, tx, nFeeRequired, nChangePosRet, error, coin_control, !pwallet->IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS));
367+ if (!fCreated ) {
368+ throw JSONRPCError (RPC_WALLET_INSUFFICIENT_FUNDS, error.original );
351369 }
352- pwallet->CommitTransaction (tx, std::move (mapValue ), {} /* orderForm */ );
353- return tx;
370+ pwallet->CommitTransaction (tx, std::move (map_value ), {} /* orderForm */ );
371+ return tx-> GetHash (). GetHex () ;
354372}
355373
356374static UniValue sendtoaddress (const JSONRPCRequest& request)
@@ -398,16 +416,6 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
398416
399417 LOCK (pwallet->cs_wallet );
400418
401- CTxDestination dest = DecodeDestination (request.params [0 ].get_str ());
402- if (!IsValidDestination (dest)) {
403- throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, " Invalid address" );
404- }
405-
406- // Amount
407- CAmount nAmount = AmountFromValue (request.params [1 ]);
408- if (nAmount <= 0 )
409- throw JSONRPCError (RPC_TYPE_ERROR, " Invalid amount for send" );
410-
411419 // Wallet comments
412420 mapValue_t mapValue;
413421 if (!request.params [2 ].isNull () && !request.params [2 ].get_str ().empty ())
@@ -441,8 +449,18 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
441449
442450 EnsureWalletIsUnlocked (pwallet);
443451
444- CTransactionRef tx = SendMoney (pwallet, dest, nAmount, fSubtractFeeFromAmount , coin_control, std::move (mapValue));
445- return tx->GetHash ().GetHex ();
452+ UniValue address_amounts (UniValue::VOBJ);
453+ const std::string address = request.params [0 ].get_str ();
454+ address_amounts.pushKV (address, request.params [1 ]);
455+ UniValue subtractFeeFromAmount (UniValue::VARR);
456+ if (fSubtractFeeFromAmount ) {
457+ subtractFeeFromAmount.push_back (address);
458+ }
459+
460+ std::vector<CRecipient> recipients;
461+ ParseRecipients (address_amounts, subtractFeeFromAmount, recipients);
462+
463+ return SendMoney (pwallet, coin_control, recipients, mapValue);
446464}
447465
448466static UniValue listaddressgroupings (const JSONRPCRequest& request)
@@ -840,52 +858,10 @@ static UniValue sendmany(const JSONRPCRequest& request)
840858 }
841859 }
842860
843- std::set<CTxDestination> destinations ;
844- std::vector<CRecipient> vecSend ;
861+ std::vector<CRecipient> recipients ;
862+ ParseRecipients (sendTo, subtractFeeFromAmount, recipients) ;
845863
846- std::vector<std::string> keys = sendTo.getKeys ();
847- for (const std::string& name_ : keys) {
848- CTxDestination dest = DecodeDestination (name_);
849- if (!IsValidDestination (dest)) {
850- throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, std::string (" Invalid Bitcoin address: " ) + name_);
851- }
852-
853- if (destinations.count (dest)) {
854- throw JSONRPCError (RPC_INVALID_PARAMETER, std::string (" Invalid parameter, duplicated address: " ) + name_);
855- }
856- destinations.insert (dest);
857-
858- CScript scriptPubKey = GetScriptForDestination (dest);
859- CAmount nAmount = AmountFromValue (sendTo[name_]);
860- if (nAmount <= 0 )
861- throw JSONRPCError (RPC_TYPE_ERROR, " Invalid amount for send" );
862-
863- bool fSubtractFeeFromAmount = false ;
864- for (unsigned int idx = 0 ; idx < subtractFeeFromAmount.size (); idx++) {
865- const UniValue& addr = subtractFeeFromAmount[idx];
866- if (addr.get_str () == name_)
867- fSubtractFeeFromAmount = true ;
868- }
869-
870- CRecipient recipient = {scriptPubKey, nAmount, fSubtractFeeFromAmount };
871- vecSend.push_back (recipient);
872- }
873-
874- EnsureWalletIsUnlocked (pwallet);
875-
876- // Shuffle recipient list
877- std::shuffle (vecSend.begin (), vecSend.end (), FastRandomContext ());
878-
879- // Send
880- CAmount nFeeRequired = 0 ;
881- int nChangePosRet = -1 ;
882- bilingual_str error;
883- CTransactionRef tx;
884- bool fCreated = pwallet->CreateTransaction (vecSend, tx, nFeeRequired, nChangePosRet, error, coin_control);
885- if (!fCreated )
886- throw JSONRPCError (RPC_WALLET_INSUFFICIENT_FUNDS, error.original );
887- pwallet->CommitTransaction (tx, std::move (mapValue), {} /* orderForm */ );
888- return tx->GetHash ().GetHex ();
864+ return SendMoney (pwallet, coin_control, recipients, std::move (mapValue));
889865}
890866
891867static UniValue addmultisigaddress (const JSONRPCRequest& request)
0 commit comments