@@ -321,36 +321,54 @@ static UniValue setlabel(const JSONRPCRequest& request)
321
321
return NullUniValue;
322
322
}
323
323
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
+ }
324
332
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);
328
337
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++]);
332
340
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
+ }
335
348
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);
338
357
339
- // Create and send the transaction
358
+ // Shuffle recipient list
359
+ std::shuffle (recipients.begin (), recipients.end (), FastRandomContext ());
360
+
361
+ // Send
340
362
CAmount nFeeRequired = 0 ;
341
- bilingual_str error;
342
- std::vector<CRecipient> vecSend;
343
363
int nChangePosRet = -1 ;
344
- CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount };
345
- vecSend.push_back (recipient);
364
+ bilingual_str error;
346
365
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 );
351
369
}
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 () ;
354
372
}
355
373
356
374
static UniValue sendtoaddress (const JSONRPCRequest& request)
@@ -398,16 +416,6 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
398
416
399
417
LOCK (pwallet->cs_wallet );
400
418
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
-
411
419
// Wallet comments
412
420
mapValue_t mapValue;
413
421
if (!request.params [2 ].isNull () && !request.params [2 ].get_str ().empty ())
@@ -441,8 +449,18 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
441
449
442
450
EnsureWalletIsUnlocked (pwallet);
443
451
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);
446
464
}
447
465
448
466
static UniValue listaddressgroupings (const JSONRPCRequest& request)
@@ -840,52 +858,10 @@ static UniValue sendmany(const JSONRPCRequest& request)
840
858
}
841
859
}
842
860
843
- std::set<CTxDestination> destinations ;
844
- std::vector<CRecipient> vecSend ;
861
+ std::vector<CRecipient> recipients ;
862
+ ParseRecipients (sendTo, subtractFeeFromAmount, recipients) ;
845
863
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));
889
865
}
890
866
891
867
static UniValue addmultisigaddress (const JSONRPCRequest& request)
0 commit comments