diff --git a/BTCPayServer/Controllers/WalletsController.cs b/BTCPayServer/Controllers/WalletsController.cs index 3d9b56098..ec93f8578 100644 --- a/BTCPayServer/Controllers/WalletsController.cs +++ b/BTCPayServer/Controllers/WalletsController.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.Net.Http; using System.Net.WebSockets; using System.Text; using System.Threading; @@ -417,38 +416,37 @@ namespace BTCPayServer.Controllers }, CryptoCode = walletId.CryptoCode }; - - - var feeProvider = _feeRateProvider.CreateFeeProvider(network); - var recommendedFees = new[] { - TimeSpan.FromMinutes(10.0), - TimeSpan.FromMinutes(60.0), - TimeSpan.FromHours(6.0), - TimeSpan.FromHours(24.0), - } - .Select(time => network.NBitcoinNetwork.Consensus.GetExpectedBlocksFor(time)) - .Select(blockCount => feeProvider.GetFeeRateAsync((int)blockCount)) - .ToArray(); + var feeProvider = _feeRateProvider.CreateFeeProvider(network); + var recommendedFees = + new[] + { + TimeSpan.FromMinutes(10.0), TimeSpan.FromMinutes(60.0), TimeSpan.FromHours(6.0), + TimeSpan.FromHours(24.0), + }.Select(async time => + { + try + { + var result = await feeProvider.GetFeeRateAsync( + (int)network.NBitcoinNetwork.Consensus.GetExpectedBlocksFor(time)); + return new WalletSendModel.FeeRateOption() {Target = time, FeeRate = result.SatoshiPerByte}; + } + catch (Exception) + { + return null; + } + }) + .ToArray(); var balance = _walletProvider.GetWallet(network).GetBalance(paymentMethod.AccountDerivation); model.NBXSeedAvailable = await CanUseHotWallet() && !string.IsNullOrEmpty(await ExplorerClientProvider.GetExplorerClient(network) .GetMetadataAsync(GetDerivationSchemeSettings(walletId).AccountDerivation, WellknownMetadataKeys.MasterHDKey)); model.CurrentBalance = await balance; - model.RecommendedSatoshiPerByte = new decimal?[recommendedFees.Length]; - for (int i = 0; i < model.RecommendedSatoshiPerByte.Length; i++) - { - decimal? feeRate = null; - try - { - feeRate = (await recommendedFees[i]).SatoshiPerByte; - } - catch - { + + await Task.WhenAll(recommendedFees); + model.RecommendedSatoshiPerByte = + recommendedFees.Select(tuple => tuple.Result).Where(option => option != null).ToList(); - } - model.RecommendedSatoshiPerByte[i] = feeRate; - } - model.FeeSatoshiPerByte = model.RecommendedSatoshiPerByte.Reverse().Where(r => r is decimal).FirstOrDefault(); + model.FeeSatoshiPerByte = model.RecommendedSatoshiPerByte.LastOrDefault()?.FeeRate; model.SupportRBF = network.SupportRBF; using (CancellationTokenSource cts = new CancellationTokenSource()) { diff --git a/BTCPayServer/Models/WalletViewModels/WalletSendModel.cs b/BTCPayServer/Models/WalletViewModels/WalletSendModel.cs index ec514a300..fd8dfce4a 100644 --- a/BTCPayServer/Models/WalletViewModels/WalletSendModel.cs +++ b/BTCPayServer/Models/WalletViewModels/WalletSendModel.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using BTCPayServer.Services.Labels; @@ -6,6 +7,11 @@ namespace BTCPayServer.Models.WalletViewModels { public class WalletSendModel { + public class FeeRateOption + { + public TimeSpan Target { get; set; } + public decimal FeeRate { get; set; } + } public List Outputs { get; set; } = new List(); public class TransactionOutput @@ -25,15 +31,8 @@ namespace BTCPayServer.Models.WalletViewModels public decimal CurrentBalance { get; set; } public string CryptoCode { get; set; } - - public string[] RecommendedSatoshiLabels = new string[] - { - "10 minutes", - "1 hour", - "6 hours", - "1 day" - }; - public decimal?[] RecommendedSatoshiPerByte { get; set; } + + public List RecommendedSatoshiPerByte { get; set; } [Display(Name = "Fee rate (satoshi per byte)")] [Required] diff --git a/BTCPayServer/Views/Wallets/WalletSend.cshtml b/BTCPayServer/Views/Wallets/WalletSend.cshtml index faf1d6c87..7d8308893 100644 --- a/BTCPayServer/Views/Wallets/WalletSend.cshtml +++ b/BTCPayServer/Views/Wallets/WalletSend.cshtml @@ -1,5 +1,6 @@ @addTagHelper *, BundlerMinifier.TagHelpers @using Microsoft.AspNetCore.Mvc.ModelBinding +@using BTCPayServer.Views @model WalletSendModel @{ Layout = "../Shared/_NavLayout.cshtml"; @@ -25,10 +26,6 @@ - @for (int i = 0; i < Model.RecommendedSatoshiPerByte.Length; i++) - { - - }
    @@ -135,15 +132,27 @@ -

    - Target confirmation in: - @for (int i = 0; i < Model.RecommendedSatoshiPerByte.Length; i++) - { - if (Model.RecommendedSatoshiPerByte[i] is null) - continue; - . - } -

    + @if (Model.RecommendedSatoshiPerByte.Any()) + { +
    + + Confirm in the next + +
    + + @for (var index = 0; index < Model.RecommendedSatoshiPerByte.Count; index++) + { + var feeRateOption = Model.RecommendedSatoshiPerByte[index]; + + } +
    +
    + } @if (Model.Outputs.Count == 1) { diff --git a/BTCPayServer/wwwroot/js/wallet/WalletSend.js b/BTCPayServer/wwwroot/js/wallet/WalletSend.js index 89c76dc01..a68044925 100644 --- a/BTCPayServer/wwwroot/js/wallet/WalletSend.js +++ b/BTCPayServer/wwwroot/js/wallet/WalletSend.js @@ -24,15 +24,24 @@ function updateFiatValueWithCurrentElement() { updateFiatValue($(this)) } +function selectCorrectFeeOption(){ + var val = $("#FeeSatoshiPerByte").val(); + $(".feerate-options").children(".crypto-fee-link").removeClass("active"); + $(".feerate-options").find("[value='"+val+"']").first().addClass("active"); +} + $(function () { $(".output-amount").on("input", updateFiatValueWithCurrentElement).each(updateFiatValueWithCurrentElement); $(".crypto-fee-link").on("click", function (elem) { - var val = $(this).attr("data-feerate").valueOf(); + $(this).parent().children().removeClass("active"); + var val = $(this).addClass("active").val(); $("#FeeSatoshiPerByte").val(val); return false; }); + $("#FeeSatoshiPerByte").on("change input", selectCorrectFeeOption); + selectCorrectFeeOption(); $(".crypto-balance-link").on("click", function (elem) { var val = $(this).text(); var parentContainer = $(this).parents(".form-group");