@@ -352,40 +352,55 @@ static RPCHelpMan setlabel()
352
352
};
353
353
}
354
354
355
+ void ParseRecipients (const UniValue& address_amounts, const UniValue& subtract_fee_outputs, std::vector<CRecipient> &recipients) {
356
+ std::set<CTxDestination> destinations;
357
+ int i = 0 ;
358
+ for (const std::string& address: address_amounts.getKeys ()) {
359
+ CTxDestination dest = DecodeDestination (address);
360
+ if (!IsValidDestination (dest)) {
361
+ throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, std::string (" Invalid Dash address: " ) + address);
362
+ }
355
363
356
- static CTransactionRef SendMoney (CWallet* const pwallet, const CTxDestination& address, CAmount nValue, bool fSubtractFeeFromAmount , const CCoinControl& coin_control, mapValue_t mapValue)
357
- {
358
- CAmount curBalance = pwallet->GetBalance (0 , coin_control.m_avoid_address_reuse ).m_mine_trusted ;
364
+ if (destinations.count (dest)) {
365
+ throw JSONRPCError (RPC_INVALID_PARAMETER, std::string (" Invalid parameter, duplicated address: " ) + address);
366
+ }
367
+ destinations.insert (dest);
359
368
360
- // Check amount
361
- if (nValue <= 0 )
362
- throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid amount" );
369
+ CScript script_pub_key = GetScriptForDestination (dest);
370
+ CAmount amount = AmountFromValue (address_amounts[i++]);
363
371
364
- if (nValue > curBalance)
365
- throw JSONRPCError (RPC_WALLET_INSUFFICIENT_FUNDS, " Insufficient funds" );
372
+ bool subtract_fee = false ;
373
+ for (unsigned int idx = 0 ; idx < subtract_fee_outputs.size (); idx++) {
374
+ const UniValue& addr = subtract_fee_outputs[idx];
375
+ if (addr.get_str () == address) {
376
+ subtract_fee = true ;
377
+ }
378
+ }
366
379
367
- if (coin_control. IsUsingCoinJoin ()) {
368
- mapValue[ " DS " ] = " 1 " ;
380
+ CRecipient recipient = {script_pub_key, amount, subtract_fee};
381
+ recipients. push_back (recipient) ;
369
382
}
383
+ }
370
384
371
- // Parse Dash address
372
- CScript scriptPubKey = GetScriptForDestination (address);
385
+ UniValue SendMoney (CWallet* const pwallet, const CCoinControl &coin_control, std::vector<CRecipient> &recipients, mapValue_t map_value)
386
+ {
387
+ EnsureWalletIsUnlocked (pwallet);
373
388
374
- // Create and send the transaction
389
+ if (coin_control.IsUsingCoinJoin ()) {
390
+ map_value[" DS" ] = " 1" ;
391
+ }
392
+
393
+ // Send
375
394
CAmount nFeeRequired = 0 ;
376
- bilingual_str error;
377
- std::vector<CRecipient> vecSend;
378
395
int nChangePosRet = -1 ;
379
- CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount };
380
- vecSend.push_back (recipient);
396
+ bilingual_str error;
381
397
CTransactionRef tx;
382
- if (!pwallet->CreateTransaction (vecSend, tx, nFeeRequired, nChangePosRet, error, coin_control)) {
383
- if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
384
- error = strprintf (Untranslated (" Error: This transaction requires a transaction fee of at least %s" ), FormatMoney (nFeeRequired));
385
- throw JSONRPCError (RPC_WALLET_ERROR, error.original );
398
+ bool fCreated = pwallet->CreateTransaction (recipients, tx, nFeeRequired, nChangePosRet, error, coin_control, !pwallet->IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS));
399
+ if (!fCreated ) {
400
+ throw JSONRPCError (RPC_WALLET_INSUFFICIENT_FUNDS, error.original );
386
401
}
387
- pwallet->CommitTransaction (tx, std::move (mapValue ), {} /* orderForm */ );
388
- return tx;
402
+ pwallet->CommitTransaction (tx, std::move (map_value ), {} /* orderForm */ );
403
+ return tx-> GetHash (). GetHex () ;
389
404
}
390
405
391
406
static RPCHelpMan sendtoaddress ()
@@ -434,16 +449,6 @@ static RPCHelpMan sendtoaddress()
434
449
435
450
LOCK (pwallet->cs_wallet );
436
451
437
- CTxDestination dest = DecodeDestination (request.params [0 ].get_str ());
438
- if (!IsValidDestination (dest)) {
439
- throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, " Invalid address" );
440
- }
441
-
442
- // Amount
443
- CAmount nAmount = AmountFromValue (request.params [1 ]);
444
- if (nAmount <= 0 )
445
- throw JSONRPCError (RPC_TYPE_ERROR, " Invalid amount for send" );
446
-
447
452
// Wallet comments
448
453
mapValue_t mapValue;
449
454
if (!request.params [2 ].isNull () && !request.params [2 ].get_str ().empty ())
@@ -471,8 +476,18 @@ static RPCHelpMan sendtoaddress()
471
476
472
477
EnsureWalletIsUnlocked (pwallet);
473
478
474
- CTransactionRef tx = SendMoney (pwallet, dest, nAmount, fSubtractFeeFromAmount , coin_control, std::move (mapValue));
475
- return tx->GetHash ().GetHex ();
479
+ UniValue address_amounts (UniValue::VOBJ);
480
+ const std::string address = request.params [0 ].get_str ();
481
+ address_amounts.pushKV (address, request.params [1 ]);
482
+ UniValue subtractFeeFromAmount (UniValue::VARR);
483
+ if (fSubtractFeeFromAmount ) {
484
+ subtractFeeFromAmount.push_back (address);
485
+ }
486
+
487
+ std::vector<CRecipient> recipients;
488
+ ParseRecipients (address_amounts, subtractFeeFromAmount, recipients);
489
+
490
+ return SendMoney (pwallet, coin_control, recipients, mapValue);
476
491
},
477
492
};
478
493
}
@@ -935,9 +950,9 @@ static RPCHelpMan sendmany()
935
950
if (!request.params [4 ].isNull () && !request.params [4 ].get_str ().empty ())
936
951
mapValue[" comment" ] = request.params [4 ].get_str ();
937
952
938
- UniValue subtractFeeFrom (UniValue::VARR);
953
+ UniValue subtractFeeFromAmount (UniValue::VARR);
939
954
if (!request.params [5 ].isNull ())
940
- subtractFeeFrom = request.params [5 ].get_array ();
955
+ subtractFeeFromAmount = request.params [5 ].get_array ();
941
956
942
957
// request.params[6] ("use_is") is deprecated and not used here
943
958
@@ -949,53 +964,10 @@ static RPCHelpMan sendmany()
949
964
950
965
SetFeeEstimateMode (pwallet, coin_control, request.params [9 ], request.params [8 ]);
951
966
952
- if (coin_control.IsUsingCoinJoin ()) {
953
- mapValue[" DS" ] = " 1" ;
954
- }
955
-
956
- std::set<CTxDestination> destinations;
957
- std::vector<CRecipient> vecSend;
958
-
959
- std::vector<std::string> keys = sendTo.getKeys ();
960
- for (const std::string& name_ : keys) {
961
- CTxDestination dest = DecodeDestination (name_);
962
- if (!IsValidDestination (dest)) {
963
- throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, std::string (" Invalid Dash address: " ) + name_);
964
- }
965
-
966
- if (destinations.count (dest)) {
967
- throw JSONRPCError (RPC_INVALID_PARAMETER, std::string (" Invalid parameter, duplicated address: " ) + name_);
968
- }
969
- destinations.insert (dest);
967
+ std::vector<CRecipient> recipients;
968
+ ParseRecipients (sendTo, subtractFeeFromAmount, recipients);
970
969
971
- CScript scriptPubKey = GetScriptForDestination (dest);
972
- CAmount nAmount = AmountFromValue (sendTo[name_]);
973
- if (nAmount <= 0 )
974
- throw JSONRPCError (RPC_TYPE_ERROR, " Invalid amount for send" );
975
-
976
- bool fSubtractFeeFromAmount = false ;
977
- for (unsigned int idx = 0 ; idx < subtractFeeFrom.size (); idx++) {
978
- const UniValue& addr = subtractFeeFrom[idx];
979
- if (addr.get_str () == name_)
980
- fSubtractFeeFromAmount = true ;
981
- }
982
-
983
- CRecipient recipient = {scriptPubKey, nAmount, fSubtractFeeFromAmount };
984
- vecSend.push_back (recipient);
985
- }
986
-
987
- EnsureWalletIsUnlocked (pwallet);
988
-
989
- // Send
990
- CAmount nFeeRequired = 0 ;
991
- int nChangePosRet = -1 ;
992
- bilingual_str error;
993
- CTransactionRef tx;
994
- bool fCreated = pwallet->CreateTransaction (vecSend, tx, nFeeRequired, nChangePosRet, error, coin_control);
995
- if (!fCreated )
996
- throw JSONRPCError (RPC_WALLET_INSUFFICIENT_FUNDS, error.original );
997
- pwallet->CommitTransaction (tx, std::move (mapValue), {} /* orderForm */ );
998
- return tx->GetHash ().GetHex ();
970
+ return SendMoney (pwallet, coin_control, recipients, std::move (mapValue));
999
971
},
1000
972
};
1001
973
}
0 commit comments