@@ -356,7 +356,7 @@ UniValue getaddressesbyaccount(const JSONRPCRequest& request)
return ret;
}
-static void SendMoney (CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount , CWalletTx& wtxNew)
+static void SendMoney (CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount , CWalletTx& wtxNew, CCoinControl *coin_control = nullptr )
{
CAmount curBalance = pwallet->GetBalance ();
@@ -382,7 +382,7 @@ static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CA
int nChangePosRet = -1 ;
CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount };
vecSend.push_back (recipient);
- if (!pwallet->CreateTransaction (vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError)) {
+ if (!pwallet->CreateTransaction (vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError, coin_control )) {
if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
strError = strprintf (" Error: This transaction requires a transaction fee of at least %s" , FormatMoney (nFeeRequired));
throw JSONRPCError (RPC_WALLET_ERROR, strError);
@@ -401,9 +401,9 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
return NullUniValue;
}
- if (request.fHelp || request.params .size () < 2 || request.params .size () > 5 )
+ if (request.fHelp || request.params .size () < 2 || request.params .size () > 8 )
throw std::runtime_error (
- " sendtoaddress \" address\" amount ( \" comment\" \" comment_to\" subtractfeefromamount )\n "
+ " sendtoaddress \" address\" amount ( \" comment\" \" comment_to\" subtractfeefromamount replaceable conf_target \" estimate_mode \" )\n "
" \n Send an amount to a given address.\n "
+ HelpRequiringPassphrase (pwallet) +
" \n Arguments:\n "
@@ -416,6 +416,12 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
" transaction, just kept in your wallet.\n "
" 5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n "
" The recipient will receive less bitcoins than you enter in the amount field.\n "
+ " 6. replaceable (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees via BIP 125\n "
+ " 7. conf_target (numeric, optional) Confirmation target (in blocks)\n "
+ " 8. \" estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n "
+ " \" UNSET\"\n "
+ " \" ECONOMICAL\"\n "
+ " \" CONSERVATIVE\"\n "
" \n Result:\n "
" \" txid\" (string) The transaction id.\n "
" \n Examples:\n "
@@ -444,12 +450,29 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
wtx.mapValue [" to" ] = request.params [3 ].get_str ();
bool fSubtractFeeFromAmount = false ;
- if (request.params .size () > 4 )
+ if (request.params .size () > 4 && !request. params [ 4 ]. isNull ()) {
fSubtractFeeFromAmount = request.params [4 ].get_bool ();
+ }
+
+ CCoinControl coin_control;
+ if (request.params .size () > 5 && !request.params [5 ].isNull ()) {
+ coin_control.signalRbf = request.params [5 ].get_bool ();
+ }
+
+ if (request.params .size () > 6 && !request.params [6 ].isNull ()) {
+ coin_control.nConfirmTarget = request.params [6 ].get_int ();
+ }
+
+ if (request.params .size () > 7 && !request.params [7 ].isNull ()) {
+ if (!FeeModeFromString (request.params [7 ].get_str (), coin_control.m_fee_mode )) {
+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid estimate_mode parameter" );
+ }
+ }
+
EnsureWalletIsUnlocked (pwallet);
- SendMoney (pwallet, address.Get (), nAmount, fSubtractFeeFromAmount , wtx);
+ SendMoney (pwallet, address.Get (), nAmount, fSubtractFeeFromAmount , wtx, &coin_control );
return wtx.GetHash ().GetHex ();
}
@@ -888,9 +911,9 @@ UniValue sendmany(const JSONRPCRequest& request)
return NullUniValue;
}
- if (request.fHelp || request.params .size () < 2 || request.params .size () > 5 )
+ if (request.fHelp || request.params .size () < 2 || request.params .size () > 8 )
throw std::runtime_error (
- " sendmany \" fromaccount\" {\" address\" :amount,...} ( minconf \" comment\" [\" address\" ,...] )\n "
+ " sendmany \" fromaccount\" {\" address\" :amount,...} ( minconf \" comment\" [\" address\" ,...] replaceable conf_target \" estimate_mode \" )\n "
" \n Send multiple times. Amounts are double-precision floating point numbers."
+ HelpRequiringPassphrase (pwallet) + " \n "
" \n Arguments:\n "
@@ -910,7 +933,13 @@ UniValue sendmany(const JSONRPCRequest& request)
" \" address\" (string) Subtract fee from this address\n "
" ,...\n "
" ]\n "
- " \n Result:\n "
+ " 6. replaceable (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees via BIP 125\n "
+ " 7. conf_target (numeric, optional) Confirmation target (in blocks)\n "
+ " 8. \" estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n "
+ " \" UNSET\"\n "
+ " \" ECONOMICAL\"\n "
+ " \" CONSERVATIVE\"\n "
+ " \n Result:\n "
" \" txid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n "
" the number of addresses.\n "
" \n Examples:\n "
@@ -942,9 +971,24 @@ UniValue sendmany(const JSONRPCRequest& request)
wtx.mapValue [" comment" ] = request.params [3 ].get_str ();
UniValue subtractFeeFromAmount (UniValue::VARR);
- if (request.params .size () > 4 )
+ if (request.params .size () > 4 && !request. params [ 4 ]. isNull () )
subtractFeeFromAmount = request.params [4 ].get_array ();
+ CCoinControl coin_control;
+ if (request.params .size () > 5 && !request.params [5 ].isNull ()) {
+ coin_control.signalRbf = request.params [5 ].get_bool ();
+ }
+
+ if (request.params .size () > 6 && !request.params [6 ].isNull ()) {
+ coin_control.nConfirmTarget = request.params [6 ].get_int ();
+ }
+
+ if (request.params .size () > 7 && !request.params [7 ].isNull ()) {
+ if (!FeeModeFromString (request.params [7 ].get_str (), coin_control.m_fee_mode )) {
+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid estimate_mode parameter" );
+ }
+ }
+
std::set<CBitcoinAddress> setAddress;
std::vector<CRecipient> vecSend;
@@ -989,7 +1033,7 @@ UniValue sendmany(const JSONRPCRequest& request)
CAmount nFeeRequired = 0 ;
int nChangePosRet = -1 ;
std::string strFailReason;
- bool fCreated = pwallet->CreateTransaction (vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason);
+ bool fCreated = pwallet->CreateTransaction (vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason, &coin_control );
if (!fCreated )
throw JSONRPCError (RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
CValidationState state;
@@ -2658,6 +2702,11 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
" [vout_index,...]\n "
" \" replaceable\" (boolean, optional) Marks this transaction as BIP125 replaceable.\n "
" Allows this transaction to be replaced by a transaction with higher fees\n "
+ " \" conf_target\" (numeric, optional) Confirmation target (in blocks)\n "
+ " \" estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n "
+ " \" UNSET\"\n "
+ " \" ECONOMICAL\"\n "
+ " \" CONSERVATIVE\"\n "
" }\n "
" for backward compatibility: passing in a true instead of an object will result in {\" includeWatching\" :true}\n "
" \n Result:\n "
@@ -2710,6 +2759,8 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
{" feeRate" , UniValueType ()}, // will be checked below
{" subtractFeeFromOutputs" , UniValueType (UniValue::VARR)},
{" replaceable" , UniValueType (UniValue::VBOOL)},
+ {" conf_target" , UniValueType (UniValue::VNUM)},
+ {" estimate_mode" , UniValueType (UniValue::VSTR)},
},
true , true );
@@ -2746,6 +2797,14 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
if (options.exists (" replaceable" )) {
coinControl.signalRbf = options[" replaceable" ].get_bool ();
}
+ if (options.exists (" conf_target" )) {
+ coinControl.nConfirmTarget = options[" conf_target" ].get_int ();
+ }
+ if (options.exists (" estimate_mode" )) {
+ if (!FeeModeFromString (options[" estimate_mode" ].get_str (), coinControl.m_fee_mode )) {
+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid estimate_mode parameter" );
+ }
+ }
}
}
@@ -2823,6 +2882,10 @@ UniValue bumpfee(const JSONRPCRequest& request)
" so the new transaction will not be explicitly bip-125 replaceable (though it may\n "
" still be replaceable in practice, for example if it has unconfirmed ancestors which\n "
" are replaceable).\n "
+ " \" estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n "
+ " \" UNSET\"\n "
+ " \" ECONOMICAL\"\n "
+ " \" CONSERVATIVE\"\n "
" }\n "
" \n Result:\n "
" {\n "
@@ -2845,13 +2908,15 @@ UniValue bumpfee(const JSONRPCRequest& request)
int newConfirmTarget = nTxConfirmTarget;
CAmount totalFee = 0 ;
bool replaceable = true ;
+ FeeEstimateMode fee_mode = FeeEstimateMode::UNSET;
if (request.params .size () > 1 ) {
UniValue options = request.params [1 ];
RPCTypeCheckObj (options,
{
{" confTarget" , UniValueType (UniValue::VNUM)},
{" totalFee" , UniValueType (UniValue::VNUM)},
{" replaceable" , UniValueType (UniValue::VBOOL)},
+ {" estimate_mode" , UniValueType (UniValue::VSTR)},
},
true , true );
@@ -2876,12 +2941,17 @@ UniValue bumpfee(const JSONRPCRequest& request)
if (options.exists (" replaceable" )) {
replaceable = options[" replaceable" ].get_bool ();
}
+ if (options.exists (" estimate_mode" )) {
+ if (!FeeModeFromString (options[" estimate_mode" ].get_str (), fee_mode)) {
+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid estimate_mode parameter" );
+ }
+ }
}
LOCK2 (cs_main, pwallet->cs_wallet);
EnsureWalletIsUnlocked (pwallet);
- CFeeBumper feeBump (pwallet, hash, newConfirmTarget, ignoreGlobalPayTxFee, totalFee, replaceable);
+ CFeeBumper feeBump (pwallet, hash, newConfirmTarget, ignoreGlobalPayTxFee, totalFee, replaceable, fee_mode );
BumpFeeResult res = feeBump.getResult ();
if (res != BumpFeeResult::OK)
{
@@ -3023,8 +3093,8 @@ static const CRPCCommand commands[] =
{ " wallet" , " lockunspent" , &lockunspent, true , {" unlock" ," transactions" } },
{ " wallet" , " move" , &movecmd, false , {" fromaccount" ," toaccount" ," amount" ," minconf" ," comment" } },
{ " wallet" , " sendfrom" , &sendfrom, false , {" fromaccount" ," toaddress" ," amount" ," minconf" ," comment" ," comment_to" } },
- { " wallet" , " sendmany" , &sendmany, false , {" fromaccount" ," amounts" ," minconf" ," comment" ," subtractfeefrom" } },
- { " wallet" , " sendtoaddress" , &sendtoaddress, false , {" address" ," amount" ," comment" ," comment_to" ," subtractfeefromamount" } },
+ { " wallet" , " sendmany" , &sendmany, false , {" fromaccount" ," amounts" ," minconf" ," comment" ," subtractfeefrom" , " replaceable " , " conf_target " , " estimate_mode " } },
+ { " wallet" , " sendtoaddress" , &sendtoaddress, false , {" address" ," amount" ," comment" ," comment_to" ," subtractfeefromamount" , " replaceable " , " conf_target " , " estimate_mode " } },
{ " wallet" , " setaccount" , &setaccount, true , {" address" ," account" } },
{ " wallet" , " settxfee" , &settxfee, true , {" amount" } },
{ " wallet" , " signmessage" , &signmessage, true , {" address" ," message" } },
As suggested in another PR, the first condition can be removed since
UniValue::operator[]handles out of bounds. Same below.