@@ -849,71 +849,92 @@ UniValue estimaterawfee(const JSONRPCRequest& request)
849
849
" confirmation within nblocks blocks if possible. Uses virtual transaction size as defined\n "
850
850
" in BIP 141 (witness data is discounted).\n "
851
851
" \n Arguments:\n "
852
- " 1. nblocks (numeric)\n "
852
+ " 1. nblocks (numeric) Confirmation target in blocks (1 - 1008) \n "
853
853
" 2. threshold (numeric, optional) The proportion of transactions in a given feerate range that must have been\n "
854
854
" confirmed within nblocks in order to consider those feerates as high enough and proceed to check\n "
855
855
" lower buckets. Default: 0.95\n "
856
856
" \n Result:\n "
857
857
" {\n "
858
- " \" short\" : { (json object) estimate for short time horizon\n "
859
- " \" feerate\" : x.x, (numeric) estimate fee-per-kilobyte (in BTC)\n "
858
+ " \" short\" : { (json object, optional ) estimate for short time horizon\n "
859
+ " \" feerate\" : x.x, (numeric, optional ) estimate fee-per-kilobyte (in BTC)\n "
860
860
" \" decay\" : x.x, (numeric) exponential decay (per block) for historical moving average of confirmation data\n "
861
861
" \" scale\" : x, (numeric) The resolution of confirmation targets at this time horizon\n "
862
- " \" pass\" : { (json object) information about the lowest range of feerates to succeed in meeting the threshold\n "
862
+ " \" pass\" : { (json object, optional ) information about the lowest range of feerates to succeed in meeting the threshold\n "
863
863
" \" startrange\" : x.x, (numeric) start of feerate range\n "
864
864
" \" endrange\" : x.x, (numeric) end of feerate range\n "
865
865
" \" withintarget\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed within target\n "
866
866
" \" totalconfirmed\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed at any point\n "
867
867
" \" inmempool\" : x.x, (numeric) current number of txs in mempool in the feerate range unconfirmed for at least target blocks\n "
868
868
" \" leftmempool\" : x.x, (numeric) number of txs over history horizon in the feerate range that left mempool unconfirmed after target\n "
869
869
" },\n "
870
- " \" fail\" : { ... }, (json object) information about the highest range of feerates to fail to meet the threshold\n "
870
+ " \" fail\" : { ... }, (json object, optional) information about the highest range of feerates to fail to meet the threshold\n "
871
+ " \" errors\" : [ str... ] (json array of strings, optional) Errors encountered during processing\n "
871
872
" },\n "
872
- " \" medium\" : { ... }, (json object) estimate for medium time horizon\n "
873
- " \" long\" : { ... } (json object) estimate for long time horizon\n "
873
+ " \" medium\" : { ... }, (json object, optional ) estimate for medium time horizon\n "
874
+ " \" long\" : { ... } (json object) estimate for long time horizon\n "
874
875
" }\n "
875
876
" \n "
876
- " A negative feerate is returned if no answer can be given .\n "
877
+ " Results are returned for any horizon which tracks blocks up to the confirmation target .\n "
877
878
" \n Example:\n "
878
879
+ HelpExampleCli (" estimaterawfee" , " 6 0.9" )
879
880
);
880
881
881
882
RPCTypeCheck (request.params , {UniValue::VNUM, UniValue::VNUM, UniValue::VNUM}, true );
882
883
RPCTypeCheckArgument (request.params [0 ], UniValue::VNUM);
883
884
int nBlocks = request.params [0 ].get_int ();
885
+ if (nBlocks < 1 || (unsigned int )nBlocks > ::feeEstimator.HighestTargetTracked (FeeEstimateHorizon::LONG_HALFLIFE)) {
886
+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid nblocks" );
887
+ }
884
888
double threshold = 0.95 ;
885
889
if (!request.params [1 ].isNull ()) {
886
890
threshold = request.params [1 ].get_real ();
887
891
}
892
+ if (threshold < 0 || threshold > 1 ) {
893
+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid threshold" );
894
+ }
888
895
889
896
UniValue result (UniValue::VOBJ);
890
897
891
898
for (FeeEstimateHorizon horizon : {FeeEstimateHorizon::SHORT_HALFLIFE, FeeEstimateHorizon::MED_HALFLIFE, FeeEstimateHorizon::LONG_HALFLIFE}) {
892
899
CFeeRate feeRate;
893
900
EstimationResult buckets;
894
- feeRate = ::feeEstimator.estimateRawFee (nBlocks, threshold, horizon, &buckets);
895
901
902
+ // Only output results for horizons which track the target
903
+ if ((unsigned int )nBlocks > ::feeEstimator.HighestTargetTracked (horizon)) continue ;
904
+
905
+ feeRate = ::feeEstimator.estimateRawFee (nBlocks, threshold, horizon, &buckets);
896
906
UniValue horizon_result (UniValue::VOBJ);
897
- horizon_result.push_back (Pair (" feerate" , feeRate == CFeeRate (0 ) ? -1.0 : ValueFromAmount (feeRate.GetFeePerK ())));
898
- if (!(feeRate == CFeeRate (0 ))) {
907
+ UniValue errors (UniValue::VARR);
908
+ UniValue passbucket (UniValue::VOBJ);
909
+ passbucket.push_back (Pair (" startrange" , round (buckets.pass .start )));
910
+ passbucket.push_back (Pair (" endrange" , round (buckets.pass .end )));
911
+ passbucket.push_back (Pair (" withintarget" , round (buckets.pass .withinTarget * 100.0 ) / 100.0 ));
912
+ passbucket.push_back (Pair (" totalconfirmed" , round (buckets.pass .totalConfirmed * 100.0 ) / 100.0 ));
913
+ passbucket.push_back (Pair (" inmempool" , round (buckets.pass .inMempool * 100.0 ) / 100.0 ));
914
+ passbucket.push_back (Pair (" leftmempool" , round (buckets.pass .leftMempool * 100.0 ) / 100.0 ));
915
+ UniValue failbucket (UniValue::VOBJ);
916
+ failbucket.push_back (Pair (" startrange" , round (buckets.fail .start )));
917
+ failbucket.push_back (Pair (" endrange" , round (buckets.fail .end )));
918
+ failbucket.push_back (Pair (" withintarget" , round (buckets.fail .withinTarget * 100.0 ) / 100.0 ));
919
+ failbucket.push_back (Pair (" totalconfirmed" , round (buckets.fail .totalConfirmed * 100.0 ) / 100.0 ));
920
+ failbucket.push_back (Pair (" inmempool" , round (buckets.fail .inMempool * 100.0 ) / 100.0 ));
921
+ failbucket.push_back (Pair (" leftmempool" , round (buckets.fail .leftMempool * 100.0 ) / 100.0 ));
922
+
923
+ // CFeeRate(0) is used to indicate error as a return value from estimateRawFee
924
+ if (feeRate != CFeeRate (0 )) {
925
+ horizon_result.push_back (Pair (" feerate" , ValueFromAmount (feeRate.GetFeePerK ())));
899
926
horizon_result.push_back (Pair (" decay" , buckets.decay ));
900
927
horizon_result.push_back (Pair (" scale" , (int )buckets.scale ));
901
- UniValue passbucket (UniValue::VOBJ);
902
- passbucket.push_back (Pair (" startrange" , round (buckets.pass .start )));
903
- passbucket.push_back (Pair (" endrange" , round (buckets.pass .end )));
904
- passbucket.push_back (Pair (" withintarget" , round (buckets.pass .withinTarget * 100.0 ) / 100.0 ));
905
- passbucket.push_back (Pair (" totalconfirmed" , round (buckets.pass .totalConfirmed * 100.0 ) / 100.0 ));
906
- passbucket.push_back (Pair (" inmempool" , round (buckets.pass .inMempool * 100.0 ) / 100.0 ));
907
- passbucket.push_back (Pair (" leftmempool" , round (buckets.pass .leftMempool * 100.0 ) / 100.0 ));
908
928
horizon_result.push_back (Pair (" pass" , passbucket));
909
- UniValue failbucket (UniValue::VOBJ);
910
- failbucket.push_back (Pair (" startrange" , round (buckets.fail .start )));
911
- failbucket.push_back (Pair (" endrange" , round (buckets.fail .end )));
912
- failbucket.push_back (Pair (" withintarget" , round (buckets.fail .withinTarget * 100.0 ) / 100.0 ));
913
- failbucket.push_back (Pair (" totalconfirmed" , round (buckets.fail .totalConfirmed * 100.0 ) / 100.0 ));
914
- failbucket.push_back (Pair (" inmempool" , round (buckets.fail .inMempool * 100.0 ) / 100.0 ));
915
- failbucket.push_back (Pair (" leftmempool" , round (buckets.fail .leftMempool * 100.0 ) / 100.0 ));
929
+ // buckets.fail.start == -1 indicates that all buckets passed, there is no fail bucket to output
930
+ if (buckets.fail .start != -1 ) horizon_result.push_back (Pair (" fail" , failbucket));
931
+ } else {
932
+ // Output only information that is still meaningful in the event of error
933
+ horizon_result.push_back (Pair (" decay" , buckets.decay ));
934
+ horizon_result.push_back (Pair (" scale" , (int )buckets.scale ));
916
935
horizon_result.push_back (Pair (" fail" , failbucket));
936
+ errors.push_back (" Insufficient data or no feerate found which meets threshold" );
937
+ horizon_result.push_back (Pair (" errors" ,errors));
917
938
}
918
939
result.push_back (Pair (StringForFeeEstimateHorizon (horizon), horizon_result));
919
940
}
0 commit comments