@@ -359,36 +359,54 @@ static UniValue setlabel(const JSONRPCRequest& request)
359
359
return NullUniValue;
360
360
}
361
361
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
+ }
362
370
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);
366
375
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++]);
370
378
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
+ }
373
386
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);
376
395
377
- // Create and send the transaction
396
+ // Shuffle recipient list
397
+ std::shuffle (recipients.begin (), recipients.end (), FastRandomContext ());
398
+
399
+ // Send
378
400
CAmount nFeeRequired = 0 ;
379
- bilingual_str error;
380
- std::vector<CRecipient> vecSend;
381
401
int nChangePosRet = -1 ;
382
- CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount };
383
- vecSend.push_back (recipient);
402
+ bilingual_str error;
384
403
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 );
389
407
}
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 () ;
392
410
}
393
411
394
412
static UniValue sendtoaddress (const JSONRPCRequest& request)
@@ -436,16 +454,6 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
436
454
437
455
LOCK (pwallet->cs_wallet );
438
456
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
-
449
457
// Wallet comments
450
458
mapValue_t mapValue;
451
459
if (!request.params [2 ].isNull () && !request.params [2 ].get_str ().empty ())
@@ -471,8 +479,18 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
471
479
472
480
EnsureWalletIsUnlocked (pwallet);
473
481
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);
476
494
}
477
495
478
496
static UniValue listaddressgroupings (const JSONRPCRequest& request)
@@ -860,52 +878,10 @@ static UniValue sendmany(const JSONRPCRequest& request)
860
878
861
879
SetFeeEstimateMode (pwallet, coin_control, request.params [7 ], request.params [6 ]);
862
880
863
- std::set<CTxDestination> destinations ;
864
- std::vector<CRecipient> vecSend ;
881
+ std::vector<CRecipient> recipients ;
882
+ ParseRecipients (sendTo, subtractFeeFromAmount, recipients) ;
865
883
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));
909
885
}
910
886
911
887
static UniValue addmultisigaddress (const JSONRPCRequest& request)
0 commit comments