public static async Task <EstimateSmartFeeResponse> EstimateSmartFeeAsync(this IRPCClient rpc, int confirmationTarget, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false, bool tryOtherFeeRates = true) { if (simulateIfRegTest && rpc.Network == Network.RegTest) { return(SimulateRegTestFeeEstimation(confirmationTarget, estimateMode)); } if (tryOtherFeeRates) { try { return(await rpc.EstimateSmartFeeAsync(confirmationTarget, estimateMode)); } catch (Exception ex) when(ex is RPCException || ex is NoEstimationException) { Logger.LogTrace(ex); // Hopefully Bitcoin Core brainfart: https://github.com/bitcoin/bitcoin/issues/14431 for (int i = 2; i <= Constants.SevenDaysConfirmationTarget; i++) { try { return(await rpc.EstimateSmartFeeAsync(i, estimateMode)); } catch (Exception ex2) when(ex2 is RPCException || ex2 is NoEstimationException) { Logger.LogTrace(ex2); } } } // Let's try one more time, whatever. } return(await rpc.EstimateSmartFeeAsync(confirmationTarget, estimateMode)); }
private static async Task <Dictionary <int, int> > EstimateHalfFeesAsync(this IRPCClient rpc, IDictionary <int, int> estimations, int smallTarget, int smallFee, int largeTarget, int largeFee, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false, bool tolerateBitcoinCoreBrainfuck = true) { var newEstimations = new Dictionary <int, int>(); foreach (var est in estimations) { newEstimations.TryAdd(est.Key, est.Value); } if (Math.Abs(smallTarget - largeTarget) <= 1) { return(newEstimations); } if (smallFee == 0) { var smallFeeResult = await rpc.EstimateSmartFeeAsync(smallTarget, estimateMode, simulateIfRegTest, tolerateBitcoinCoreBrainfuck); smallFee = (int)Math.Ceiling(smallFeeResult.FeeRate.SatoshiPerByte); newEstimations.TryAdd(smallTarget, smallFee); } if (largeFee == 0) { var largeFeeResult = await rpc.EstimateSmartFeeAsync(largeTarget, estimateMode, simulateIfRegTest, tolerateBitcoinCoreBrainfuck); largeFee = (int)Math.Ceiling(largeFeeResult.FeeRate.SatoshiPerByte); largeTarget = largeFeeResult.Blocks; newEstimations.TryAdd(largeTarget, largeFee); } int halfTarget = (smallTarget + largeTarget) / 2; var halfFeeResult = await rpc.EstimateSmartFeeAsync(halfTarget, estimateMode, simulateIfRegTest, tolerateBitcoinCoreBrainfuck); int halfFee = (int)Math.Ceiling(halfFeeResult.FeeRate.SatoshiPerByte); halfTarget = halfFeeResult.Blocks; newEstimations.TryAdd(halfTarget, halfFee); if (smallFee != halfFee) { var smallEstimations = await rpc.EstimateHalfFeesAsync(newEstimations, smallTarget, smallFee, halfTarget, halfFee, estimateMode, simulateIfRegTest, tolerateBitcoinCoreBrainfuck); foreach (var est in smallEstimations) { newEstimations.TryAdd(est.Key, est.Value); } } if (largeFee != halfFee) { var largeEstimations = await rpc.EstimateHalfFeesAsync(newEstimations, halfTarget, halfFee, largeTarget, largeFee, estimateMode, simulateIfRegTest, tolerateBitcoinCoreBrainfuck); foreach (var est in largeEstimations) { newEstimations.TryAdd(est.Key, est.Value); } } return(newEstimations); }
public static async Task <EstimateSmartFeeResponse> EstimateSmartFeeAsync(this IRPCClient rpc, int confirmationTarget, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false) { if (simulateIfRegTest && rpc.Network == Network.RegTest) { return(SimulateRegTestFeeEstimation(confirmationTarget, estimateMode)); } return(await rpc.EstimateSmartFeeAsync(confirmationTarget, estimateMode)); }
public static async Task <EstimateSmartFeeResponse> EstimateSmartFeeAsync(this IRPCClient rpc, int confirmationTarget, FeeRate sanityFeeRate, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false) { EstimateSmartFeeResponse result; if (simulateIfRegTest && rpc.Network == Network.RegTest) { result = SimulateRegTestFeeEstimation(confirmationTarget, estimateMode); } else { result = await rpc.EstimateSmartFeeAsync(confirmationTarget, estimateMode).ConfigureAwait(false); } result.FeeRate = FeeRate.Max(sanityFeeRate, result.FeeRate); return(result); }
public static async Task <EstimateSmartFeeResponse> EstimateSmartFeeAsync(this IRPCClient rpc, int confirmationTarget, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false, CancellationToken cancellationToken = default) { EstimateSmartFeeResponse result; if (simulateIfRegTest && rpc.Network == Network.RegTest) { result = SimulateRegTestFeeEstimation(confirmationTarget, estimateMode); } else { result = await rpc.EstimateSmartFeeAsync(confirmationTarget, estimateMode, cancellationToken).ConfigureAwait(false); var mempoolInfo = await rpc.GetMempoolInfoAsync(cancellationToken).ConfigureAwait(false); result.FeeRate = FeeRate.Max(mempoolInfo.GetSanityFeeRate(), result.FeeRate); } return(result); }
private static async Task <Dictionary <int, int> > EstimateHalfFeesAsync(this IRPCClient rpc, IDictionary <int, int> estimations, int smallTarget, int smallTargetFee, int largeTarget, int largeTargetFee, FeeRate sanityFeeRate, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false) { var newEstimations = new Dictionary <int, int>(); foreach (var est in estimations) { newEstimations.TryAdd(est.Key, est.Value); } if (Math.Abs(smallTarget - largeTarget) <= 1) { return(newEstimations); } if (smallTargetFee == 0) { var smallTargetFeeResult = await rpc.EstimateSmartFeeAsync(smallTarget, sanityFeeRate, estimateMode, simulateIfRegTest); smallTargetFee = (int)Math.Ceiling(smallTargetFeeResult.FeeRate.SatoshiPerByte); newEstimations.TryAdd(smallTarget, smallTargetFee); } if (largeTargetFee == 0) { var largeTargetFeeResult = await rpc.EstimateSmartFeeAsync(largeTarget, sanityFeeRate, estimateMode, simulateIfRegTest); largeTargetFee = (int)Math.Ceiling(largeTargetFeeResult.FeeRate.SatoshiPerByte); // Blocks should never be larger than the target that we asked for, so it's just a sanity check. largeTarget = Math.Min(largeTarget, largeTargetFeeResult.Blocks); newEstimations.TryAdd(largeTarget, largeTargetFee); } int halfTarget = (smallTarget + largeTarget) / 2; var halfFeeResult = await rpc.EstimateSmartFeeAsync(halfTarget, sanityFeeRate, estimateMode, simulateIfRegTest); int halfTargetFee = (int)Math.Ceiling(halfFeeResult.FeeRate.SatoshiPerByte); // Blocks should never be larger than the target that we asked for, so it's just a sanity check. halfTarget = Math.Min(halfTarget, halfFeeResult.Blocks); newEstimations.TryAdd(halfTarget, halfTargetFee); if (smallTargetFee > halfTargetFee) { var smallEstimations = await rpc.EstimateHalfFeesAsync(newEstimations, smallTarget, smallTargetFee, halfTarget, halfTargetFee, sanityFeeRate, estimateMode, simulateIfRegTest); foreach (var est in smallEstimations) { newEstimations.TryAdd(est.Key, est.Value); } } if (largeTargetFee < halfTargetFee) { var largeEstimations = await rpc.EstimateHalfFeesAsync(newEstimations, halfTarget, halfTargetFee, largeTarget, largeTargetFee, sanityFeeRate, estimateMode, simulateIfRegTest); foreach (var est in largeEstimations) { newEstimations.TryAdd(est.Key, est.Value); } } return(newEstimations); }