@@ -355,7 +355,7 @@ UniValue getaddressesbyaccount(const JSONRPCRequest& request)
355355 return ret;
356356}
357357
358- static void SendMoney (CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount , CWalletTx& wtxNew)
358+ static void SendMoney (CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount , CWalletTx& wtxNew, CCoinControl *coin_control = nullptr )
359359{
360360 CAmount curBalance = pwallet->GetBalance ();
361361
@@ -381,7 +381,7 @@ static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CA
381381 int nChangePosRet = -1 ;
382382 CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount };
383383 vecSend.push_back (recipient);
384- if (!pwallet->CreateTransaction (vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError)) {
384+ if (!pwallet->CreateTransaction (vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError, coin_control )) {
385385 if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
386386 strError = strprintf (" Error: This transaction requires a transaction fee of at least %s" , FormatMoney (nFeeRequired));
387387 throw JSONRPCError (RPC_WALLET_ERROR, strError);
@@ -400,7 +400,7 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
400400 return NullUniValue;
401401 }
402402
403- if (request.fHelp || request.params .size () < 2 || request.params .size () > 5 )
403+ if (request.fHelp || request.params .size () < 2 || request.params .size () > 8 )
404404 throw std::runtime_error (
405405 " sendtoaddress \" address\" amount ( \" comment\" \" comment_to\" subtractfeefromamount )\n "
406406 " \n Send an amount to a given address.\n "
@@ -415,6 +415,12 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
415415 " transaction, just kept in your wallet.\n "
416416 " 5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n "
417417 " The recipient will receive less bitcoins than you enter in the amount field.\n "
418+ " 6. opt_in_rbf (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees\n "
419+ " 7. conf_target (numeric, optional) Confirmation target (in blocks)\n "
420+ " 8. \" estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n "
421+ " \" UNSET\"\n "
422+ " \" ECONOMICAL\"\n "
423+ " \" CONSERVATIVE\"\n "
418424 " \n Result:\n "
419425 " \" txid\" (string) The transaction id.\n "
420426 " \n Examples:\n "
@@ -443,12 +449,32 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
443449 wtx.mapValue [" to" ] = request.params [3 ].get_str ();
444450
445451 bool fSubtractFeeFromAmount = false ;
446- if (request.params .size () > 4 )
452+ if (request.params .size () > 4 && !request. params [ 4 ]. isNull ()) {
447453 fSubtractFeeFromAmount = request.params [4 ].get_bool ();
454+ }
455+
456+ CCoinControl coin_control;
457+ if (request.params .size () > 5 && !request.params [5 ].isNull ()) {
458+ coin_control.signalRbf = request.params [5 ].get_bool ();
459+ }
460+
461+ if (request.params .size () > 6 && !request.params [6 ].isNull ()) {
462+ coin_control.nConfirmTarget = request.params [6 ].get_int ();
463+ }
464+
465+ if (request.params .size () > 7 && !request.params [7 ].isNull ()) {
466+ if (boost::optional<FeeEstimateMode> fee_mode = FeeModeForString (request.params [7 ].get_str ())) {
467+ coin_control.m_fee_mode = *fee_mode;
468+ }
469+ else {
470+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid estimate_mode parameter" );
471+ }
472+ }
473+
448474
449475 EnsureWalletIsUnlocked (pwallet);
450476
451- SendMoney (pwallet, address.Get (), nAmount, fSubtractFeeFromAmount , wtx);
477+ SendMoney (pwallet, address.Get (), nAmount, fSubtractFeeFromAmount , wtx, &coin_control );
452478
453479 return wtx.GetHash ().GetHex ();
454480}
@@ -887,7 +913,7 @@ UniValue sendmany(const JSONRPCRequest& request)
887913 return NullUniValue;
888914 }
889915
890- if (request.fHelp || request.params .size () < 2 || request.params .size () > 5 )
916+ if (request.fHelp || request.params .size () < 2 || request.params .size () > 8 )
891917 throw std::runtime_error (
892918 " sendmany \" fromaccount\" {\" address\" :amount,...} ( minconf \" comment\" [\" address\" ,...] )\n "
893919 " \n Send multiple times. Amounts are double-precision floating point numbers."
@@ -909,7 +935,13 @@ UniValue sendmany(const JSONRPCRequest& request)
909935 " \" address\" (string) Subtract fee from this address\n "
910936 " ,...\n "
911937 " ]\n "
912- " \n Result:\n "
938+ " 6. opt_in_rbf (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees\n "
939+ " 7. conf_target (numeric, optional) Confirmation target (in blocks)\n "
940+ " 8. \" estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n "
941+ " \" UNSET\"\n "
942+ " \" ECONOMICAL\"\n "
943+ " \" CONSERVATIVE\"\n "
944+ " \n Result:\n "
913945 " \" txid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n "
914946 " the number of addresses.\n "
915947 " \n Examples:\n "
@@ -941,9 +973,27 @@ UniValue sendmany(const JSONRPCRequest& request)
941973 wtx.mapValue [" comment" ] = request.params [3 ].get_str ();
942974
943975 UniValue subtractFeeFromAmount (UniValue::VARR);
944- if (request.params .size () > 4 )
976+ if (request.params .size () > 4 && !request. params [ 4 ]. isNull () )
945977 subtractFeeFromAmount = request.params [4 ].get_array ();
946978
979+ CCoinControl coin_control;
980+ if (request.params .size () > 5 && !request.params [5 ].isNull ()) {
981+ coin_control.signalRbf = request.params [5 ].get_bool ();
982+ }
983+
984+ if (request.params .size () > 6 && !request.params [6 ].isNull ()) {
985+ coin_control.nConfirmTarget = request.params [6 ].get_int ();
986+ }
987+
988+ if (request.params .size () > 7 && !request.params [7 ].isNull ()) {
989+ if (boost::optional<FeeEstimateMode> fee_mode = FeeModeForString (request.params [7 ].get_str ())) {
990+ coin_control.m_fee_mode = *fee_mode;
991+ }
992+ else {
993+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid estimate_mode parameter" );
994+ }
995+ }
996+
947997 std::set<CBitcoinAddress> setAddress;
948998 std::vector<CRecipient> vecSend;
949999
@@ -988,7 +1038,7 @@ UniValue sendmany(const JSONRPCRequest& request)
9881038 CAmount nFeeRequired = 0 ;
9891039 int nChangePosRet = -1 ;
9901040 std::string strFailReason;
991- bool fCreated = pwallet->CreateTransaction (vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason);
1041+ bool fCreated = pwallet->CreateTransaction (vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason, &coin_control );
9921042 if (!fCreated )
9931043 throw JSONRPCError (RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
9941044 CValidationState state;
@@ -2657,6 +2707,11 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
26572707 " If no outputs are specified here, the sender pays the fee.\n "
26582708 " [vout_index,...]\n "
26592709 " \" optIntoRbf\" (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees\n "
2710+ " \" conf_target\" (numeric, optional) Confirmation target (in blocks)\n "
2711+ " \" estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n "
2712+ " \" UNSET\"\n "
2713+ " \" ECONOMICAL\"\n "
2714+ " \" CONSERVATIVE\"\n "
26602715 " }\n "
26612716 " for backward compatibility: passing in a true instead of an object will result in {\" includeWatching\" :true}\n "
26622717 " \n Result:\n "
@@ -2709,6 +2764,8 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
27092764 {" feeRate" , UniValueType ()}, // will be checked below
27102765 {" subtractFeeFromOutputs" , UniValueType (UniValue::VARR)},
27112766 {" optIntoRbf" , UniValueType (UniValue::VBOOL)},
2767+ {" conf_target" , UniValueType (UniValue::VNUM)},
2768+ {" estimate_mode" , UniValueType (UniValue::VSTR)},
27122769 },
27132770 true , true );
27142771
@@ -2745,6 +2802,17 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
27452802 if (options.exists (" optIntoRbf" )) {
27462803 coinControl.signalRbf = options[" optIntoRbf" ].get_bool ();
27472804 }
2805+ if (options.exists (" conf_target" )) {
2806+ coinControl.nConfirmTarget = options[" conf_target" ].get_int ();
2807+ }
2808+ if (options.exists (" estimate_mode" )) {
2809+ if (boost::optional<FeeEstimateMode> fee_mode = FeeModeForString (options[" estimate_mode" ].get_str ())) {
2810+ coinControl.m_fee_mode = *fee_mode;
2811+ }
2812+ else {
2813+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid estimate_mode parameter" );
2814+ }
2815+ }
27482816 }
27492817 }
27502818
@@ -2822,6 +2890,10 @@ UniValue bumpfee(const JSONRPCRequest& request)
28222890 " so the new transaction will not be explicitly bip-125 replaceable (though it may\n "
28232891 " still be replaceable in practice, for example if it has unconfirmed ancestors which\n "
28242892 " are replaceable).\n "
2893+ " \" estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n "
2894+ " \" UNSET\"\n "
2895+ " \" ECONOMICAL\"\n "
2896+ " \" CONSERVATIVE\"\n "
28252897 " }\n "
28262898 " \n Result:\n "
28272899 " {\n "
@@ -2844,13 +2916,15 @@ UniValue bumpfee(const JSONRPCRequest& request)
28442916 int newConfirmTarget = nTxConfirmTarget;
28452917 CAmount totalFee = 0 ;
28462918 bool replaceable = true ;
2919+ FeeEstimateMode fee_mode = FeeEstimateMode::UNSET;
28472920 if (request.params .size () > 1 ) {
28482921 UniValue options = request.params [1 ];
28492922 RPCTypeCheckObj (options,
28502923 {
28512924 {" confTarget" , UniValueType (UniValue::VNUM)},
28522925 {" totalFee" , UniValueType (UniValue::VNUM)},
28532926 {" replaceable" , UniValueType (UniValue::VBOOL)},
2927+ {" estimate_mode" , UniValueType (UniValue::VSTR)},
28542928 },
28552929 true , true );
28562930
@@ -2875,12 +2949,20 @@ UniValue bumpfee(const JSONRPCRequest& request)
28752949 if (options.exists (" replaceable" )) {
28762950 replaceable = options[" replaceable" ].get_bool ();
28772951 }
2952+ if (options.exists (" estimate_mode" )) {
2953+ if (boost::optional<FeeEstimateMode> desired_fee_mode = FeeModeForString (options[" estimate_mode" ].get_str ())) {
2954+ fee_mode = *desired_fee_mode;
2955+ }
2956+ else {
2957+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid estimate_mode parameter" );
2958+ }
2959+ }
28782960 }
28792961
28802962 LOCK2 (cs_main, pwallet->cs_wallet );
28812963 EnsureWalletIsUnlocked (pwallet);
28822964
2883- CFeeBumper feeBump (pwallet, hash, newConfirmTarget, ignoreGlobalPayTxFee, totalFee, replaceable);
2965+ CFeeBumper feeBump (pwallet, hash, newConfirmTarget, ignoreGlobalPayTxFee, totalFee, replaceable, fee_mode );
28842966 BumpFeeResult res = feeBump.getResult ();
28852967 if (res != BumpFeeResult::OK)
28862968 {
@@ -2977,8 +3059,8 @@ static const CRPCCommand commands[] =
29773059 { " wallet" , " lockunspent" , &lockunspent, true , {" unlock" ," transactions" } },
29783060 { " wallet" , " move" , &movecmd, false , {" fromaccount" ," toaccount" ," amount" ," minconf" ," comment" } },
29793061 { " wallet" , " sendfrom" , &sendfrom, false , {" fromaccount" ," toaddress" ," amount" ," minconf" ," comment" ," comment_to" } },
2980- { " wallet" , " sendmany" , &sendmany, false , {" fromaccount" ," amounts" ," minconf" ," comment" ," subtractfeefrom" } },
2981- { " wallet" , " sendtoaddress" , &sendtoaddress, false , {" address" ," amount" ," comment" ," comment_to" ," subtractfeefromamount" } },
3062+ { " wallet" , " sendmany" , &sendmany, false , {" fromaccount" ," amounts" ," minconf" ," comment" ," subtractfeefrom" , " opt_in_rbf " , " conf_target " , " estimate_mode " } },
3063+ { " wallet" , " sendtoaddress" , &sendtoaddress, false , {" address" ," amount" ," comment" ," comment_to" ," subtractfeefromamount" , " opt_in_rbf " , " conf_target " , " estimate_mode " } },
29823064 { " wallet" , " setaccount" , &setaccount, true , {" address" ," account" } },
29833065 { " wallet" , " settxfee" , &settxfee, true , {" amount" } },
29843066 { " wallet" , " signmessage" , &signmessage, true , {" address" ," message" } },
0 commit comments