public Task <EstimateSmartFeeResponse> TryEstimateSmartFeeAsync(int confirmationTarget, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative) { return(Rpc.TryEstimateSmartFeeAsync(confirmationTarget, estimateMode: estimateMode)); }
public static async Task <EstimateSmartFeeResponse> EstimateSmartFeeAsync(this RPCClient 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)); }
public async Task <IActionResult> GetSynchronizeAsync([FromQuery] string bestKnownBlockHash, [FromQuery] int maxNumberOfFilters, [FromQuery] string estimateSmartFeeMode) { if (string.IsNullOrWhiteSpace(bestKnownBlockHash)) { return(BadRequest("Invalid block hash is provided.")); } if (maxNumberOfFilters <= 0) { return(BadRequest("Invalid maxNumberOfFilters is provided.")); } bool estimateSmartFee = !string.IsNullOrWhiteSpace(estimateSmartFeeMode); EstimateSmartFeeMode mode = EstimateSmartFeeMode.Conservative; if (estimateSmartFee) { if (!Enum.TryParse(estimateSmartFeeMode, ignoreCase: true, out mode)) { return(BadRequest("Invalid estimation mode is provided, possible values: ECONOMICAL/CONSERVATIVE.")); } } if (!ModelState.IsValid) { return(BadRequest("Wrong body is provided.")); } var knownHash = new uint256(bestKnownBlockHash); (Height bestHeight, IEnumerable <string> filters) = Global.IndexBuilderService.GetFilterLinesExcluding(knownHash, maxNumberOfFilters, out bool found); var response = new SynchronizeResponse(); response.Filters = new string[0]; response.BestHeight = bestHeight; if (!found) { response.FiltersResponseState = FiltersResponseState.BestKnownHashNotFound; } else if (!filters.Any()) { response.FiltersResponseState = FiltersResponseState.NoNewFilter; } else { response.FiltersResponseState = FiltersResponseState.NewFilters; response.Filters = filters; } response.CcjRoundStates = ChaumianCoinJoinController.GetStatesCollection(); if (estimateSmartFee) { response.AllFeeEstimate = await BlockchainController.GetAllFeeEstimateAsync(mode); } response.ExchangeRates = await OffchainController.GetExchangeRatesCollectionAsync(); return(Ok(response)); }
public override async Task <EstimateSmartFeeResponse> EstimateSmartFeeAsync(int confirmationTarget, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, CancellationToken cancellationToken = default) { string cacheKey = $"{nameof(EstimateSmartFeeAsync)}:{confirmationTarget}:{estimateMode}"; return(await Cache.AtomicGetOrCreateAsync( cacheKey, CacheOptions(1, 4, true), () => base.EstimateSmartFeeAsync(confirmationTarget, estimateMode, cancellationToken)).ConfigureAwait(false)); }
public static async Task <AllFeeEstimate> EstimateAllFeeAsync(this RPCClient rpc, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false, bool tolerateBitcoinCoreBrainfuck = true) { var rpcStatus = await rpc.GetRpcStatusAsync(CancellationToken.None).ConfigureAwait(false); var estimations = await rpc.EstimateHalfFeesAsync(new Dictionary <int, int>(), 2, 0, Constants.SevenDaysConfirmationTarget, 0, estimateMode, simulateIfRegTest, tolerateBitcoinCoreBrainfuck).ConfigureAwait(false); var allFeeEstimate = new AllFeeEstimate(estimateMode, estimations, rpcStatus.Synchronized); return(allFeeEstimate); }
private async Task <EstimateSmartFeeResponse> GetEstimateSmartFeeAsync(int target, EstimateSmartFeeMode mode) { var cacheKey = $"{nameof(GetEstimateSmartFeeAsync)}_{target}_{Enum.GetName(typeof(EstimateSmartFeeMode), mode)}"; if (!_cache.TryGetValue(cacheKey, out EstimateSmartFeeResponse feeResponse)) { feeResponse = await RpcClient.EstimateSmartFeeAsync(target, mode); var cacheEntryOptions = new MemoryCacheEntryOptions() .SetAbsoluteExpiration(TimeSpan.FromSeconds(20)); _cache.Set(cacheKey, feeResponse, cacheEntryOptions); } return(feeResponse); }
public Task <EstimateSmartFeeResponse> EstimateSmartFeeAsync(int confirmationTarget, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative) { throw new NotImplementedException(); }
public async Task <IActionResult> GetSynchronizeAsync([FromQuery, Required] string bestKnownBlockHash, [FromQuery, Required] int maxNumberOfFilters, [FromQuery] string?estimateSmartFeeMode = nameof(EstimateSmartFeeMode.Conservative)) { if (!ModelState.IsValid) { return(BadRequest("Wrong body is provided.")); } bool estimateSmartFee = !string.IsNullOrWhiteSpace(estimateSmartFeeMode); EstimateSmartFeeMode mode = EstimateSmartFeeMode.Conservative; if (estimateSmartFee) { if (!Enum.TryParse(estimateSmartFeeMode, ignoreCase: true, out mode)) { return(BadRequest("Invalid estimation mode is provided, possible values: ECONOMICAL/CONSERVATIVE.")); } } if (!uint256.TryParse(bestKnownBlockHash, out var knownHash)) { return(BadRequest($"Invalid {nameof(bestKnownBlockHash)}.")); } (Height bestHeight, IEnumerable <FilterModel> filters) = Global.IndexBuilderService.GetFilterLinesExcluding(knownHash, maxNumberOfFilters, out bool found); var response = new SynchronizeResponse { Filters = Enumerable.Empty <FilterModel>(), BestHeight = bestHeight }; if (!found) { response.FiltersResponseState = FiltersResponseState.BestKnownHashNotFound; } else if (!filters.Any()) { response.FiltersResponseState = FiltersResponseState.NoNewFilter; } else { response.FiltersResponseState = FiltersResponseState.NewFilters; response.Filters = filters; } response.CcjRoundStates = ChaumianCoinJoinController.GetStatesCollection(); if (estimateSmartFee) { try { response.AllFeeEstimate = await BlockchainController.GetAllFeeEstimateAsync(mode); } catch (Exception ex) { Logger.LogError(ex); } } response.ExchangeRates = await OffchainController.GetExchangeRatesCollectionAsync(); response.UnconfirmedCoinJoins = await ChaumianCoinJoinController.GetUnconfirmedCoinJoinCollectionAsync(); return(Ok(response)); }
private static EstimateSmartFeeResponse SimulateRegTestFeeEstimation(int confirmationTarget, EstimateSmartFeeMode estimateMode) { int satoshiPerBytes; if (estimateMode == EstimateSmartFeeMode.Conservative) { satoshiPerBytes = ((Constants.SevenDaysConfirmationTarget + 1 + 6) - confirmationTarget) / 7; } else // Economical { satoshiPerBytes = ((Constants.SevenDaysConfirmationTarget + 1 + 5) - confirmationTarget) / 7; } Money feePerK = new Money(satoshiPerBytes * 1000, MoneyUnit.Satoshi); FeeRate feeRate = new FeeRate(feePerK); var resp = new EstimateSmartFeeResponse { Blocks = confirmationTarget, FeeRate = feeRate }; return(resp); }
public static async Task <AllFeeEstimate> EstimateAllFeeAsync(this RPCClient rpc, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false, bool tolerateBitcoinCoreBrainfuck = true) { var estimations = await rpc.EstimateHalfFeesAsync(new Dictionary <int, int>(), 2, 0, 1008, 0, estimateMode, simulateIfRegTest, tolerateBitcoinCoreBrainfuck); var allFeeEstimate = new AllFeeEstimate(estimateMode, estimations); return(allFeeEstimate); }
private async Task <EstimateSmartFeeResponse> GetEstimateSmartFeeAsync(int target, EstimateSmartFeeMode mode) { var cacheKey = $"{nameof(GetEstimateSmartFeeAsync)}_{target}_{mode}"; var cacheOptions = new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(60) }; return(await Cache.AtomicGetOrCreateAsync( cacheKey, cacheOptions, () => RpcClient.EstimateSmartFeeAsync(target, mode, simulateIfRegTest: true, tryOtherFeeRates: true))); }
private static EstimateSmartFeeResponse SimulateRegTestFeeEstimation(int confirmationTarget, EstimateSmartFeeMode estimateMode) { int staoshiPerBytes; if (estimateMode == EstimateSmartFeeMode.Conservative) { staoshiPerBytes = 6 + confirmationTarget; } else // Economical { staoshiPerBytes = 5 + confirmationTarget; } var resp = new EstimateSmartFeeResponse { Blocks = confirmationTarget, FeeRate = new FeeRate(new Money(staoshiPerBytes * 1000, MoneyUnit.Satoshi)) }; return(resp); }
public static async Task <EstimateSmartFeeResponse> TryEstimateSmartFeeAsync(this IRPCClient rpc, int confirmationTarget, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false, bool tryOtherFeeRates = false) { if (simulateIfRegTest && rpc.Network == Network.RegTest) { return(SimulateRegTestFeeEstimation(confirmationTarget, estimateMode)); } if (tryOtherFeeRates) { EstimateSmartFeeResponse response = await rpc.TryEstimateSmartFeeAsync(confirmationTarget, estimateMode); if (response is { })
public static async Task <AllFeeEstimate> EstimateAllFeeAsync(this IRPCClient rpc, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false) { var rpcStatus = await rpc.GetRpcStatusAsync(CancellationToken.None).ConfigureAwait(false); var mempoolInfo = await rpc.GetMempoolInfoAsync().ConfigureAwait(false); var sanityFeeRate = mempoolInfo.GetSanityFeeRate(); var estimations = await rpc.EstimateHalfFeesAsync(new Dictionary <int, int>(), 2, 0, Constants.SevenDaysConfirmationTarget, 0, sanityFeeRate, estimateMode, simulateIfRegTest).ConfigureAwait(false); var allFeeEstimate = new AllFeeEstimate(estimateMode, estimations, rpcStatus.Synchronized); return(allFeeEstimate); }
public virtual async Task <EstimateSmartFeeResponse> EstimateSmartFeeAsync(int confirmationTarget, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative) { return(await Rpc.EstimateSmartFeeAsync(confirmationTarget, estimateMode).ConfigureAwait(false)); }
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 AllFeeEstimate(EstimateSmartFeeMode type, IDictionary <int, int> estimations, bool isAccurate) { Create(type, estimations, isAccurate); }
private static async Task <Dictionary <int, int> > EstimateHalfFeesAsync(this IRPCClient rpc, IDictionary <int, int> estimations, int smallTarget, int smallTargetFee, int largeTarget, int largeTargetFee, 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, estimateMode, simulateIfRegTest); smallTargetFee = (int)Math.Ceiling(smallTargetFeeResult.FeeRate.SatoshiPerByte); newEstimations.TryAdd(smallTarget, smallTargetFee); } if (largeTargetFee == 0) { var largeTargetFeeResult = await rpc.EstimateSmartFeeAsync(largeTarget, 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, 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, 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, estimateMode, simulateIfRegTest); foreach (var est in largeEstimations) { newEstimations.TryAdd(est.Key, est.Value); } } return(newEstimations); }
private async Task <EstimateSmartFeeResponse> GetEstimateSmartFeeAsync(int target, EstimateSmartFeeMode mode) { var cacheKey = $"{nameof(GetEstimateSmartFeeAsync)}_{target}_{mode}"; if (!Cache.TryGetValue(cacheKey, out EstimateSmartFeeResponse feeResponse)) { feeResponse = await RpcClient.EstimateSmartFeeAsync(target, mode, simulateIfRegTest : true, tryOtherFeeRates : true); var cacheEntryOptions = new MemoryCacheEntryOptions() .SetAbsoluteExpiration(TimeSpan.FromSeconds(300)); Cache.Set(cacheKey, feeResponse, cacheEntryOptions); } return(feeResponse); }
private static async Task <Dictionary <int, int> > GetFeeEstimationsAsync(IRPCClient rpc, EstimateSmartFeeMode estimateMode) { var batchClient = rpc.PrepareBatch(); var rpcFeeEstimationTasks = Constants.ConfirmationTargets .Select(target => batchClient.EstimateSmartFeeAsync(target, estimateMode)) .ToList(); await batchClient.SendBatchAsync().ConfigureAwait(false); try { await Task.WhenAll(rpcFeeEstimationTasks).ConfigureAwait(false); } catch { if (rpcFeeEstimationTasks.All(x => x.IsFaulted)) { throw rpcFeeEstimationTasks[0].Exception?.InnerExceptions[0] ?? new Exception($"{nameof(GetFeeEstimationsAsync)} failed to fetch fee estimations."); } } // EstimateSmartFeeAsync returns the block number where estimate was found - not always what the requested one. return(rpcFeeEstimationTasks .Zip(Constants.ConfirmationTargets, (task, target) => (task, target)) .Where(x => x.task.IsCompletedSuccessfully) .Select(x => (x.target, feeRate: x.task.Result.FeeRate)) .ToDictionary(x => x.target, x => (int)Math.Ceiling(x.feeRate.SatoshiPerByte))); }
public override async Task <EstimateSmartFeeResponse> EstimateSmartFeeAsync(int confirmationTarget, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative) { string cacheKey = $"{nameof(EstimateSmartFeeAsync)}:{confirmationTarget}:{estimateMode}"; var cacheOptions = new MemoryCacheEntryOptions { Size = 1, AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(4) }; cacheOptions.AddExpirationToken(new CancellationChangeToken(TipChangeCancellationTokenSource.Token)); return(await Cache.AtomicGetOrCreateAsync( cacheKey, cacheOptions, () => base.EstimateSmartFeeAsync(confirmationTarget, estimateMode)).ConfigureAwait(false)); }
public static async Task <EstimateSmartFeeResponse> EstimateSmartFeeAsync(this IRPCClient rpc, int confirmationTarget, 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); var mempoolInfo = await rpc.GetMempoolInfoAsync().ConfigureAwait(false); result.FeeRate = FeeRate.Max(mempoolInfo.GetSanityFeeRate(), result.FeeRate); } return(result); }
private static EstimateSmartFeeResponse SimulateRegTestFeeEstimation(int confirmationTarget, EstimateSmartFeeMode estimateMode) { int satoshiPerByte = estimateMode == EstimateSmartFeeMode.Conservative ? (Constants.SevenDaysConfirmationTarget + 1 + 6 - confirmationTarget) / 7 : (Constants.SevenDaysConfirmationTarget + 1 + 5 - confirmationTarget) / 7; // Economical Money feePerK = Money.Satoshis(satoshiPerByte * 1000); FeeRate feeRate = new FeeRate(feePerK); var resp = new EstimateSmartFeeResponse { Blocks = confirmationTarget, FeeRate = feeRate }; return(resp); }
private static Dictionary <int, int> SimulateRegTestFeeEstimation(EstimateSmartFeeMode estimateMode) => Constants.ConfirmationTargets .Select(target => SimulateRegTestFeeEstimation(target, estimateMode)) .ToDictionary(x => x.Blocks, x => (int)Math.Ceiling(x.FeeRate.SatoshiPerByte));
private static async Task <Dictionary <int, int> > EstimateHalfFeesAsync(this RPCClient 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); }
/// <summary> /// Estimates fees for 1w, 3d, 1d, 12h, 6h, 3h, 1h, 30m, 20m. /// </summary> public static async Task <AllFeeEstimate> EstimateAllFeeAsync(this IRPCClient rpc, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false) { var smartEstimations = (simulateIfRegTest && rpc.Network == Network.RegTest) ? SimulateRegTestFeeEstimation(estimateMode) : await GetFeeEstimationsAsync(rpc, estimateMode).ConfigureAwait(false); var mempoolInfo = await rpc.GetMempoolInfoAsync().ConfigureAwait(false); var sanityFeeRate = mempoolInfo.GetSanityFeeRate(); var rpcStatus = await rpc.GetRpcStatusAsync(CancellationToken.None).ConfigureAwait(false); var minEstimations = GetFeeEstimationsFromMempoolInfo(mempoolInfo); var fixedEstimations = smartEstimations .GroupJoin( minEstimations, outer => outer.Key, inner => inner.Key, (outer, inner) => new { Estimation = outer, MinimumFromMemPool = inner }) .SelectMany(x => x.MinimumFromMemPool.DefaultIfEmpty(), (a, b) => ( Target: a.Estimation.Key, FeeRate: Math.Max((int)sanityFeeRate.SatoshiPerByte, Math.Max(a.Estimation.Value, b.Value)))) .ToDictionary(x => x.Target, x => x.FeeRate); return(new AllFeeEstimate( estimateMode, fixedEstimations, rpcStatus.Synchronized)); }
public static async Task <EstimateSmartFeeResponse> TryEstimateSmartFeeAsync(this RPCClient rpc, int confirmationTarget, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false, bool tryOtherFeeRates = false) { if (simulateIfRegTest && rpc.Network == Network.RegTest) { return(SimulateRegTestFeeEstimation(confirmationTarget, estimateMode)); } if (tryOtherFeeRates) { EstimateSmartFeeResponse response = await rpc.TryEstimateSmartFeeAsync(confirmationTarget, estimateMode); if (response != null) { return(response); } else { // Hopefully Bitcoin Core brainfart: https://github.com/bitcoin/bitcoin/issues/14431 for (int i = 2; i <= Constants.SevenDaysConfirmationTarget; i++) { response = await rpc.TryEstimateSmartFeeAsync(i, estimateMode); if (response != null) { return(response); } } } // Let's try one more time, whatever. } return(await rpc.TryEstimateSmartFeeAsync(confirmationTarget, estimateMode)); }
/// <summary> /// Estimates fees for 1w, 3d, 1d, 12h, 6h, 3h, 1h, 30m, 20m. /// </summary> public static async Task <AllFeeEstimate> EstimateAllFeeAsync(this IRPCClient rpc, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false) { var estimations = (simulateIfRegTest && rpc.Network == Network.RegTest) ? SimulateRegTestFeeEstimation(estimateMode) : await GetFeeEstimationsAsync(rpc, estimateMode).ConfigureAwait(false); var rpcStatus = await rpc.GetRpcStatusAsync(CancellationToken.None).ConfigureAwait(false); var mempoolInfo = await rpc.GetMempoolInfoAsync().ConfigureAwait(false); var sanityFeeRate = mempoolInfo.GetSanityFeeRate(); return(new AllFeeEstimate( estimateMode, estimations.ToDictionary(x => x.Key, x => Math.Max(x.Value, (int)sanityFeeRate.SatoshiPerByte)), rpcStatus.Synchronized)); }