@@ -359,36 +359,54 @@ static UniValue setlabel(const JSONRPCRequest& request)
359359 return NullUniValue;
360360}
361361
362+ void ParseRecipients (const UniValue& address_amounts, const UniValue& subtract_fee_outputs, std::vector<CRecipient> &recipients) {
363+ std::set<CTxDestination> destinations;
364+ int i = 0 ;
365+ for (const std::string& address: address_amounts.getKeys ()) {
366+ CTxDestination dest = DecodeDestination (address);
367+ if (!IsValidDestination (dest)) {
368+ throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, std::string (" Invalid Bitcoin address: " ) + address);
369+ }
362370
363- static CTransactionRef SendMoney (CWallet* const pwallet, const CTxDestination& address, CAmount nValue, bool fSubtractFeeFromAmount , const CCoinControl& coin_control, mapValue_t mapValue)
364- {
365- CAmount curBalance = pwallet->GetBalance (0 , coin_control.m_avoid_address_reuse ).m_mine_trusted ;
371+ if (destinations.count (dest)) {
372+ throw JSONRPCError (RPC_INVALID_PARAMETER, std::string (" Invalid parameter, duplicated address: " ) + address);
373+ }
374+ destinations.insert (dest);
366375
367- // Check amount
368- if (nValue <= 0 )
369- throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid amount" );
376+ CScript script_pub_key = GetScriptForDestination (dest);
377+ CAmount amount = AmountFromValue (address_amounts[i++]);
370378
371- if (nValue > curBalance)
372- throw JSONRPCError (RPC_WALLET_INSUFFICIENT_FUNDS, " Insufficient funds" );
379+ bool subtract_fee = false ;
380+ for (unsigned int idx = 0 ; idx < subtract_fee_outputs.size (); idx++) {
381+ const UniValue& addr = subtract_fee_outputs[idx];
382+ if (addr.get_str () == address) {
383+ subtract_fee = true ;
384+ }
385+ }
373386
374- // Parse Bitcoin address
375- CScript scriptPubKey = GetScriptForDestination (address);
387+ CRecipient recipient = {script_pub_key, amount, subtract_fee};
388+ recipients.push_back (recipient);
389+ }
390+ }
391+
392+ UniValue SendMoney (CWallet* const pwallet, const CCoinControl &coin_control, std::vector<CRecipient> &recipients, mapValue_t map_value)
393+ {
394+ EnsureWalletIsUnlocked (pwallet);
376395
377- // Create and send the transaction
396+ // Shuffle recipient list
397+ std::shuffle (recipients.begin (), recipients.end (), FastRandomContext ());
398+
399+ // Send
378400 CAmount nFeeRequired = 0 ;
379- bilingual_str error;
380- std::vector<CRecipient> vecSend;
381401 int nChangePosRet = -1 ;
382- CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount };
383- vecSend.push_back (recipient);
402+ bilingual_str error;
384403 CTransactionRef tx;
385- if (!pwallet->CreateTransaction (vecSend, tx, nFeeRequired, nChangePosRet, error, coin_control)) {
386- if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
387- error = strprintf (Untranslated (" Error: This transaction requires a transaction fee of at least %s" ), FormatMoney (nFeeRequired));
388- throw JSONRPCError (RPC_WALLET_ERROR, error.original );
404+ bool fCreated = pwallet->CreateTransaction (recipients, tx, nFeeRequired, nChangePosRet, error, coin_control, !pwallet->IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS));
405+ if (!fCreated ) {
406+ throw JSONRPCError (RPC_WALLET_INSUFFICIENT_FUNDS, error.original );
389407 }
390- pwallet->CommitTransaction (tx, std::move (mapValue ), {} /* orderForm */ );
391- return tx;
408+ pwallet->CommitTransaction (tx, std::move (map_value ), {} /* orderForm */ );
409+ return tx-> GetHash (). GetHex () ;
392410}
393411
394412static UniValue sendtoaddress (const JSONRPCRequest& request)
@@ -436,16 +454,6 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
436454
437455 LOCK (pwallet->cs_wallet );
438456
439- CTxDestination dest = DecodeDestination (request.params [0 ].get_str ());
440- if (!IsValidDestination (dest)) {
441- throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, " Invalid address" );
442- }
443-
444- // Amount
445- CAmount nAmount = AmountFromValue (request.params [1 ]);
446- if (nAmount <= 0 )
447- throw JSONRPCError (RPC_TYPE_ERROR, " Invalid amount for send" );
448-
449457 // Wallet comments
450458 mapValue_t mapValue;
451459 if (!request.params [2 ].isNull () && !request.params [2 ].get_str ().empty ())
@@ -471,8 +479,18 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
471479
472480 EnsureWalletIsUnlocked (pwallet);
473481
474- CTransactionRef tx = SendMoney (pwallet, dest, nAmount, fSubtractFeeFromAmount , coin_control, std::move (mapValue));
475- return tx->GetHash ().GetHex ();
482+ UniValue address_amounts (UniValue::VOBJ);
483+ const std::string address = request.params [0 ].get_str ();
484+ address_amounts.pushKV (address, request.params [1 ]);
485+ UniValue subtractFeeFromAmount (UniValue::VARR);
486+ if (fSubtractFeeFromAmount ) {
487+ subtractFeeFromAmount.push_back (address);
488+ }
489+
490+ std::vector<CRecipient> recipients;
491+ ParseRecipients (address_amounts, subtractFeeFromAmount, recipients);
492+
493+ return SendMoney (pwallet, coin_control, recipients, mapValue);
476494}
477495
478496static UniValue listaddressgroupings (const JSONRPCRequest& request)
@@ -860,52 +878,10 @@ static UniValue sendmany(const JSONRPCRequest& request)
860878
861879 SetFeeEstimateMode (pwallet, coin_control, request.params [7 ], request.params [6 ]);
862880
863- std::set<CTxDestination> destinations ;
864- std::vector<CRecipient> vecSend ;
881+ std::vector<CRecipient> recipients ;
882+ ParseRecipients (sendTo, subtractFeeFromAmount, recipients) ;
865883
866- std::vector<std::string> keys = sendTo.getKeys ();
867- for (const std::string& name_ : keys) {
868- CTxDestination dest = DecodeDestination (name_);
869- if (!IsValidDestination (dest)) {
870- throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, std::string (" Invalid Bitcoin address: " ) + name_);
871- }
872-
873- if (destinations.count (dest)) {
874- throw JSONRPCError (RPC_INVALID_PARAMETER, std::string (" Invalid parameter, duplicated address: " ) + name_);
875- }
876- destinations.insert (dest);
877-
878- CScript scriptPubKey = GetScriptForDestination (dest);
879- CAmount nAmount = AmountFromValue (sendTo[name_]);
880- if (nAmount <= 0 )
881- throw JSONRPCError (RPC_TYPE_ERROR, " Invalid amount for send" );
882-
883- bool fSubtractFeeFromAmount = false ;
884- for (unsigned int idx = 0 ; idx < subtractFeeFromAmount.size (); idx++) {
885- const UniValue& addr = subtractFeeFromAmount[idx];
886- if (addr.get_str () == name_)
887- fSubtractFeeFromAmount = true ;
888- }
889-
890- CRecipient recipient = {scriptPubKey, nAmount, fSubtractFeeFromAmount };
891- vecSend.push_back (recipient);
892- }
893-
894- EnsureWalletIsUnlocked (pwallet);
895-
896- // Shuffle recipient list
897- std::shuffle (vecSend.begin (), vecSend.end (), FastRandomContext ());
898-
899- // Send
900- CAmount nFeeRequired = 0 ;
901- int nChangePosRet = -1 ;
902- bilingual_str error;
903- CTransactionRef tx;
904- bool fCreated = pwallet->CreateTransaction (vecSend, tx, nFeeRequired, nChangePosRet, error, coin_control);
905- if (!fCreated )
906- throw JSONRPCError (RPC_WALLET_INSUFFICIENT_FUNDS, error.original );
907- pwallet->CommitTransaction (tx, std::move (mapValue), {} /* orderForm */ );
908- return tx->GetHash ().GetHex ();
884+ return SendMoney (pwallet, coin_control, recipients, std::move (mapValue));
909885}
910886
911887static UniValue addmultisigaddress (const JSONRPCRequest& request)
0 commit comments