diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj index 81b44be51..8fc598f96 100644 --- a/BTCPayServer/BTCPayServer.csproj +++ b/BTCPayServer/BTCPayServer.csproj @@ -22,7 +22,7 @@ - + diff --git a/BTCPayServer/Controllers/InvoiceController.cs b/BTCPayServer/Controllers/InvoiceController.cs index 80aabdd43..b3672de93 100644 --- a/BTCPayServer/Controllers/InvoiceController.cs +++ b/BTCPayServer/Controllers/InvoiceController.cs @@ -98,7 +98,8 @@ namespace BTCPayServer.Controllers entity.MonitoringExpiration = entity.ExpirationTime + TimeSpan.FromMinutes(storeBlob.MonitoringExpiration); entity.OrderId = invoice.OrderId; entity.ServerUrl = serverUrl; - entity.FullNotifications = invoice.FullNotifications; + entity.FullNotifications = invoice.FullNotifications || invoice.ExtendedNotifications; + entity.ExtendedNotifications = invoice.ExtendedNotifications; entity.NotificationURL = notificationUri?.AbsoluteUri; entity.BuyerInformation = Map(invoice); //Another way of passing buyer info to support diff --git a/BTCPayServer/HostedServices/InvoiceWatcher.cs b/BTCPayServer/HostedServices/InvoiceWatcher.cs index bbb574b78..d2bb68660 100644 --- a/BTCPayServer/HostedServices/InvoiceWatcher.cs +++ b/BTCPayServer/HostedServices/InvoiceWatcher.cs @@ -108,7 +108,7 @@ namespace BTCPayServer.HostedServices _EventAggregator.Publish(evt, evt.GetType()); } - foreach(var modifiedKnownState in updateContext.ModifiedKnownStates) + foreach (var modifiedKnownState in updateContext.ModifiedKnownStates) { changes.AddOrReplace(modifiedKnownState.Key, modifiedKnownState.Value); } @@ -223,10 +223,9 @@ namespace BTCPayServer.HostedServices if (invoice.Status == "paid") { var transactions = await GetPaymentsWithTransaction(network, invoice); - var chainConfirmedTransactions = transactions.Where(t => t.Confirmations >= 1); if (invoice.SpeedPolicy == SpeedPolicy.HighSpeed) { - transactions = transactions.Where(t => !t.Transaction.RBF); + transactions = transactions.Where(t => t.Confirmations >= 1 || !t.Transaction.RBF); } else if (invoice.SpeedPolicy == SpeedPolicy.MediumSpeed) { @@ -237,29 +236,25 @@ namespace BTCPayServer.HostedServices transactions = transactions.Where(t => t.Confirmations >= 6); } - var chainTotalConfirmed = chainConfirmedTransactions.Select(t => t.Payment.GetValue(cryptoDataAll, cryptoData.CryptoCode)).Sum(); + var totalConfirmed = transactions.Select(t => t.Payment.GetValue(cryptoDataAll, cryptoData.CryptoCode)).Sum(); if (// Is after the monitoring deadline (invoice.MonitoringExpiration < DateTimeOffset.UtcNow) && // And not enough amount confirmed - (chainTotalConfirmed < accounting.TotalDue)) + (totalConfirmed < accounting.TotalDue)) { await _InvoiceRepository.UnaffectAddress(invoice.Id); context.Events.Add(new InvoiceStatusChangedEvent(invoice, "invalid")); invoice.Status = "invalid"; context.MarkDirty(); } - else + else if (totalConfirmed >= accounting.TotalDue) { - var totalConfirmed = transactions.Select(t => t.Payment.GetValue(cryptoDataAll, cryptoData.CryptoCode)).Sum(); - if (totalConfirmed >= accounting.TotalDue) - { - await _InvoiceRepository.UnaffectAddress(invoice.Id); - context.Events.Add(new InvoiceStatusChangedEvent(invoice, "confirmed")); - invoice.Status = "confirmed"; - context.MarkDirty(); - } + await _InvoiceRepository.UnaffectAddress(invoice.Id); + context.Events.Add(new InvoiceStatusChangedEvent(invoice, "confirmed")); + invoice.Status = "confirmed"; + context.MarkDirty(); } } diff --git a/BTCPayServer/HostedServices/NBXplorerWaiter.cs b/BTCPayServer/HostedServices/NBXplorerWaiter.cs index 952be0f64..aa96e7c5c 100644 --- a/BTCPayServer/HostedServices/NBXplorerWaiter.cs +++ b/BTCPayServer/HostedServices/NBXplorerWaiter.cs @@ -20,14 +20,40 @@ namespace BTCPayServer.HostedServices Ready } + public class NBXplorerDashboard + { + public class NBXplorerSummary + { + public BTCPayNetwork Network { get; set; } + public NBXplorerState State { get; set; } + public StatusResult Status { get; set; } + } + ConcurrentDictionary _Summaries = new ConcurrentDictionary(); + public void Publish(BTCPayNetwork network, NBXplorerState state, StatusResult status) + { + var summary = new NBXplorerSummary() { Network = network, State = state, Status = status }; + _Summaries.AddOrUpdate(network.CryptoCode, summary, (k, v) => summary); + } + + public bool IsFullySynched() + { + return _Summaries.All(s => s.Value.Status != null && s.Value.Status.IsFullySynched); + } + + public IEnumerable GetAll() + { + return _Summaries.Values; + } + } + public class NBXplorerWaiters : IHostedService { List _Waiters = new List(); - public NBXplorerWaiters(ExplorerClientProvider explorerClientProvider, EventAggregator eventAggregator) + public NBXplorerWaiters(NBXplorerDashboard dashboard, ExplorerClientProvider explorerClientProvider, EventAggregator eventAggregator) { - foreach(var explorer in explorerClientProvider.GetAll()) + foreach (var explorer in explorerClientProvider.GetAll()) { - _Waiters.Add(new NBXplorerWaiter(explorer.Item1, explorer.Item2, eventAggregator)); + _Waiters.Add(new NBXplorerWaiter(dashboard, explorer.Item1, explorer.Item2, eventAggregator)); } } public Task StartAsync(CancellationToken cancellationToken) @@ -44,13 +70,15 @@ namespace BTCPayServer.HostedServices public class NBXplorerWaiter : IHostedService { - public NBXplorerWaiter(BTCPayNetwork network, ExplorerClient client, EventAggregator aggregator) + public NBXplorerWaiter(NBXplorerDashboard dashboard, BTCPayNetwork network, ExplorerClient client, EventAggregator aggregator) { _Network = network; _Client = client; _Aggregator = aggregator; + _Dashboard = dashboard; } + NBXplorerDashboard _Dashboard; BTCPayNetwork _Network; EventAggregator _Aggregator; ExplorerClient _Client; @@ -134,7 +162,6 @@ namespace BTCPayServer.HostedServices break; } - LastStatus = status; if (oldState != State) { if (State == NBXplorerState.Synching) @@ -147,6 +174,7 @@ namespace BTCPayServer.HostedServices } _Aggregator.Publish(new NBXplorerStateChangedEvent(_Network, oldState, State)); } + _Dashboard.Publish(_Network, State, status); return oldState != State; } @@ -181,8 +209,6 @@ namespace BTCPayServer.HostedServices public NBXplorerState State { get; private set; } - public StatusResult LastStatus { get; private set; } - public Task StopAsync(CancellationToken cancellationToken) { _Timer.Dispose(); diff --git a/BTCPayServer/Hosting/BTCPayServerServices.cs b/BTCPayServer/Hosting/BTCPayServerServices.cs index 017836305..bd7d3cdd2 100644 --- a/BTCPayServer/Hosting/BTCPayServerServices.cs +++ b/BTCPayServer/Hosting/BTCPayServerServices.cs @@ -132,6 +132,7 @@ namespace BTCPayServer.Hosting return new BTCPayNetworkProvider(opts.Network); }); + services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); diff --git a/BTCPayServer/Services/Invoices/InvoiceEntity.cs b/BTCPayServer/Services/Invoices/InvoiceEntity.cs index 54cd7ae7c..f1885062b 100644 --- a/BTCPayServer/Services/Invoices/InvoiceEntity.cs +++ b/BTCPayServer/Services/Invoices/InvoiceEntity.cs @@ -282,6 +282,7 @@ namespace BTCPayServer.Services.Invoices get; set; } + public bool ExtendedNotifications { get; set; } public bool IsExpired() { diff --git a/BTCPayServer/Views/Shared/_Layout.cshtml b/BTCPayServer/Views/Shared/_Layout.cshtml index a9a5c7971..99ebd095f 100644 --- a/BTCPayServer/Views/Shared/_Layout.cshtml +++ b/BTCPayServer/Views/Shared/_Layout.cshtml @@ -2,13 +2,7 @@ @inject UserManager UserManager @inject RoleManager RoleManager @inject BTCPayServer.Services.BTCPayServerEnvironment env -@inject BTCPayServer.NBXplorerWaiterAccessor waiter - -@{ - var waiterState = waiter.Instance.State; - var lastStatus = waiter.Instance.LastStatus; - var verificationProgress = waiter.Instance.LastStatus?.BitcoinStatus != null ? waiter.Instance.LastStatus.BitcoinStatus.VerificationProgress * 100 : 0.0; -} +@inject BTCPayServer.HostedServices.NBXplorerDashboard dashboard @@ -87,31 +81,7 @@ @RenderBody() - @if(waiterState == NBXplorerState.NotConnected) - { - - - } - - @if(waiterState == NBXplorerState.Synching && lastStatus.BitcoinStatus != null) + @if(!dashboard.IsFullySynched()) { - - } - else if(waiterState == NBXplorerState.Synching && lastStatus.BitcoinStatus == null) - { - -