Improve api to estimatesmartfee
Change parameter for conservative estimates to be an estimate_mode string. Change to never return a -1 for failure but to instead omit the feerate and return an error string. Throw JSONRPC error on invalid nblocks parameter.
This commit is contained in:
parent
91edda8f3c
commit
439c4e8ad5
3 changed files with 43 additions and 27 deletions
|
@ -839,20 +839,20 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation
|
||||||
EstimationResult tempResult;
|
EstimationResult tempResult;
|
||||||
|
|
||||||
// Return failure if trying to analyze a target we're not tracking
|
// Return failure if trying to analyze a target we're not tracking
|
||||||
if (confTarget <= 0 || (unsigned int)confTarget > longStats->GetMaxConfirms())
|
if (confTarget <= 0 || (unsigned int)confTarget > longStats->GetMaxConfirms()) {
|
||||||
return CFeeRate(0);
|
return CFeeRate(0); // error conditon
|
||||||
|
}
|
||||||
|
|
||||||
// It's not possible to get reasonable estimates for confTarget of 1
|
// It's not possible to get reasonable estimates for confTarget of 1
|
||||||
if (confTarget == 1)
|
if (confTarget == 1) confTarget = 2;
|
||||||
confTarget = 2;
|
|
||||||
|
|
||||||
unsigned int maxUsableEstimate = MaxUsableEstimate();
|
unsigned int maxUsableEstimate = MaxUsableEstimate();
|
||||||
if (maxUsableEstimate <= 1)
|
|
||||||
return CFeeRate(0);
|
|
||||||
|
|
||||||
if ((unsigned int)confTarget > maxUsableEstimate) {
|
if ((unsigned int)confTarget > maxUsableEstimate) {
|
||||||
confTarget = maxUsableEstimate;
|
confTarget = maxUsableEstimate;
|
||||||
}
|
}
|
||||||
|
if (feeCalc) feeCalc->returnedTarget = confTarget;
|
||||||
|
|
||||||
|
if (confTarget <= 1) return CFeeRate(0); // error conditon
|
||||||
|
|
||||||
assert(confTarget > 0); //estimateCombinedFee and estimateConservativeFee take unsigned ints
|
assert(confTarget > 0); //estimateCombinedFee and estimateConservativeFee take unsigned ints
|
||||||
/** true is passed to estimateCombined fee for target/2 and target so
|
/** true is passed to estimateCombined fee for target/2 and target so
|
||||||
|
@ -899,10 +899,7 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (feeCalc) feeCalc->returnedTarget = confTarget;
|
if (median < 0) return CFeeRate(0); // error conditon
|
||||||
|
|
||||||
if (median < 0)
|
|
||||||
return CFeeRate(0);
|
|
||||||
|
|
||||||
return CFeeRate(median);
|
return CFeeRate(median);
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
||||||
{ "getrawmempool", 0, "verbose" },
|
{ "getrawmempool", 0, "verbose" },
|
||||||
{ "estimatefee", 0, "nblocks" },
|
{ "estimatefee", 0, "nblocks" },
|
||||||
{ "estimatesmartfee", 0, "nblocks" },
|
{ "estimatesmartfee", 0, "nblocks" },
|
||||||
{ "estimatesmartfee", 1, "conservative" },
|
|
||||||
{ "estimaterawfee", 0, "nblocks" },
|
{ "estimaterawfee", 0, "nblocks" },
|
||||||
{ "estimaterawfee", 1, "threshold" },
|
{ "estimaterawfee", 1, "threshold" },
|
||||||
{ "prioritisetransaction", 1, "dummy" },
|
{ "prioritisetransaction", 1, "dummy" },
|
||||||
|
|
|
@ -806,42 +806,62 @@ UniValue estimatesmartfee(const JSONRPCRequest& request)
|
||||||
{
|
{
|
||||||
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
|
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"estimatesmartfee nblocks (conservative)\n"
|
"estimatesmartfee nblocks (\"estimate_mode\")\n"
|
||||||
"\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
|
"\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
|
||||||
"confirmation within nblocks blocks if possible and return the number of blocks\n"
|
"confirmation within nblocks blocks if possible and return the number of blocks\n"
|
||||||
"for which the estimate is valid. Uses virtual transaction size as defined\n"
|
"for which the estimate is valid. Uses virtual transaction size as defined\n"
|
||||||
"in BIP 141 (witness data is discounted).\n"
|
"in BIP 141 (witness data is discounted).\n"
|
||||||
"\nArguments:\n"
|
"\nArguments:\n"
|
||||||
"1. nblocks (numeric)\n"
|
"1. nblocks (numeric) Confirmation target in blocks (1 - 1008)\n"
|
||||||
"2. conservative (bool, optional, default=true) Whether to return a more conservative estimate which\n"
|
"2. \"estimate_mode\" (string, optional, default=CONSERVATIVE) The fee estimate mode.\n"
|
||||||
" also satisfies a longer history. A conservative estimate potentially returns a higher\n"
|
" Whether to return a more conservative estimate which also satisfies\n"
|
||||||
" feerate and is more likely to be sufficient for the desired target, but is not as\n"
|
" a longer history. A conservative estimate potentially returns a\n"
|
||||||
" responsive to short term drops in the prevailing fee market\n"
|
" higher feerate and is more likely to be sufficient for the desired\n"
|
||||||
|
" target, but is not as responsive to short term drops in the\n"
|
||||||
|
" prevailing fee market. Must be one of:\n"
|
||||||
|
" \"UNSET\" (defaults to CONSERVATIVE)\n"
|
||||||
|
" \"ECONOMICAL\"\n"
|
||||||
|
" \"CONSERVATIVE\"\n"
|
||||||
"\nResult:\n"
|
"\nResult:\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" \"feerate\" : x.x, (numeric) estimate fee-per-kilobyte (in BTC)\n"
|
" \"feerate\" : x.x, (numeric, optional) estimate fee-per-kilobyte (in BTC)\n"
|
||||||
|
" \"errors\": [ str... ] (json array of strings, optional) Errors encountered during processing\n"
|
||||||
" \"blocks\" : n (numeric) block number where estimate was found\n"
|
" \"blocks\" : n (numeric) block number where estimate was found\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"A negative value is returned if not enough transactions and blocks\n"
|
"The request target will be clamped between 2 and the highest target\n"
|
||||||
|
"fee estimation is able to return based on how long it has been running.\n"
|
||||||
|
"An error is returned if not enough transactions and blocks\n"
|
||||||
"have been observed to make an estimate for any number of blocks.\n"
|
"have been observed to make an estimate for any number of blocks.\n"
|
||||||
"\nExample:\n"
|
"\nExample:\n"
|
||||||
+ HelpExampleCli("estimatesmartfee", "6")
|
+ HelpExampleCli("estimatesmartfee", "6")
|
||||||
);
|
);
|
||||||
|
|
||||||
RPCTypeCheck(request.params, {UniValue::VNUM});
|
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VSTR});
|
||||||
|
RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
|
||||||
int nBlocks = request.params[0].get_int();
|
int nBlocks = request.params[0].get_int();
|
||||||
|
if (nBlocks < 1 || (unsigned int)nBlocks > ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE)) {
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid nblocks");
|
||||||
|
}
|
||||||
bool conservative = true;
|
bool conservative = true;
|
||||||
if (request.params.size() > 1 && !request.params[1].isNull()) {
|
if (request.params.size() > 1 && !request.params[1].isNull()) {
|
||||||
RPCTypeCheckArgument(request.params[1], UniValue::VBOOL);
|
FeeEstimateMode fee_mode;
|
||||||
conservative = request.params[1].get_bool();
|
if (!FeeModeFromString(request.params[1].get_str(), fee_mode)) {
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter");
|
||||||
|
}
|
||||||
|
if (fee_mode == FeeEstimateMode::ECONOMICAL) conservative = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue result(UniValue::VOBJ);
|
UniValue result(UniValue::VOBJ);
|
||||||
|
UniValue errors(UniValue::VARR);
|
||||||
FeeCalculation feeCalc;
|
FeeCalculation feeCalc;
|
||||||
CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocks, &feeCalc, conservative);
|
CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocks, &feeCalc, conservative);
|
||||||
result.push_back(Pair("feerate", feeRate == CFeeRate(0) ? -1.0 : ValueFromAmount(feeRate.GetFeePerK())));
|
if (feeRate != CFeeRate(0)) {
|
||||||
|
result.push_back(Pair("feerate", ValueFromAmount(feeRate.GetFeePerK())));
|
||||||
|
} else {
|
||||||
|
errors.push_back("Insufficient data or no feerate found");
|
||||||
|
result.push_back(Pair("errors", errors));
|
||||||
|
}
|
||||||
result.push_back(Pair("blocks", feeCalc.returnedTarget));
|
result.push_back(Pair("blocks", feeCalc.returnedTarget));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -889,7 +909,7 @@ UniValue estimaterawfee(const JSONRPCRequest& request)
|
||||||
+ HelpExampleCli("estimaterawfee", "6 0.9")
|
+ HelpExampleCli("estimaterawfee", "6 0.9")
|
||||||
);
|
);
|
||||||
|
|
||||||
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM, UniValue::VNUM}, true);
|
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM}, true);
|
||||||
RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
|
RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
|
||||||
int nBlocks = request.params[0].get_int();
|
int nBlocks = request.params[0].get_int();
|
||||||
if (nBlocks < 1 || (unsigned int)nBlocks > ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE)) {
|
if (nBlocks < 1 || (unsigned int)nBlocks > ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE)) {
|
||||||
|
@ -963,7 +983,7 @@ static const CRPCCommand commands[] =
|
||||||
{ "generating", "generatetoaddress", &generatetoaddress, true, {"nblocks","address","maxtries"} },
|
{ "generating", "generatetoaddress", &generatetoaddress, true, {"nblocks","address","maxtries"} },
|
||||||
|
|
||||||
{ "util", "estimatefee", &estimatefee, true, {"nblocks"} },
|
{ "util", "estimatefee", &estimatefee, true, {"nblocks"} },
|
||||||
{ "util", "estimatesmartfee", &estimatesmartfee, true, {"nblocks", "conservative"} },
|
{ "util", "estimatesmartfee", &estimatesmartfee, true, {"nblocks", "estimate_mode"} },
|
||||||
|
|
||||||
{ "hidden", "estimaterawfee", &estimaterawfee, true, {"nblocks", "threshold"} },
|
{ "hidden", "estimaterawfee", &estimaterawfee, true, {"nblocks", "threshold"} },
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue