diff --git a/BTCPayServer/Controllers/AppsPublicController.cs b/BTCPayServer/Controllers/AppsPublicController.cs index 13256ac6b..035f7c6a9 100644 --- a/BTCPayServer/Controllers/AppsPublicController.cs +++ b/BTCPayServer/Controllers/AppsPublicController.cs @@ -9,23 +9,21 @@ using System.Threading.Tasks; using BTCPayServer.Crowdfund; using BTCPayServer.Data; using BTCPayServer.Filters; -using BTCPayServer.Hubs; using BTCPayServer.Models; using BTCPayServer.Models.AppViewModels; +using BTCPayServer.Payments; using BTCPayServer.Rating; using BTCPayServer.Security; using BTCPayServer.Services.Apps; using BTCPayServer.Services.Invoices; using BTCPayServer.Services.Rates; using Ganss.XSS; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using NBitpayClient; -using Newtonsoft.Json.Linq; using YamlDotNet.RepresentationModel; using static BTCPayServer.Controllers.AppsController; @@ -126,35 +124,34 @@ namespace BTCPayServer.Controllers public async Task ContributeToCrowdfund(string appId, ContributeToCrowdfund request) { var app = await _AppsHelper.GetApp(appId, AppType.Crowdfund, true); - + if (app == null) return NotFound(); var settings = app.GetSettings(); - - + + var isAdmin = await _AppsHelper.GetAppDataIfOwner(GetUserId(), appId, AppType.Crowdfund) != null; - + if (!settings.Enabled) { - if(!isAdmin) + if (!isAdmin) return NotFound("Crowdfund is not currently active"); } var info = await _CrowdfundHubStreamer.GetCrowdfundInfo(appId); - - if(!isAdmin && - - ((settings.StartDate.HasValue && DateTime.Now < settings.StartDate) || - (settings.EndDate.HasValue && DateTime.Now > settings.EndDate) || - (settings.EnforceTargetAmount && - (info.Info.PendingProgressPercentage.GetValueOrDefault(0) + - info.Info.ProgressPercentage.GetValueOrDefault(0)) >= 100))) + + if (!isAdmin && + ((settings.StartDate.HasValue && DateTime.Now < settings.StartDate) || + (settings.EndDate.HasValue && DateTime.Now > settings.EndDate) || + (settings.EnforceTargetAmount && + (info.Info.PendingProgressPercentage.GetValueOrDefault(0) + + info.Info.ProgressPercentage.GetValueOrDefault(0)) >= 100))) { return NotFound("Crowdfund is not currently active"); } var store = await _AppsHelper.GetStore(app); - var title = settings.Title; + var title = settings.Title; var price = request.Amount; ViewPointOfSaleViewModel.Item choice = null; if (!string.IsNullOrEmpty(request.ChoiceKey)) @@ -170,11 +167,11 @@ namespace BTCPayServer.Controllers } if (!isAdmin && (settings.EnforceTargetAmount && info.TargetAmount.HasValue && price > - (info.TargetAmount - (info.Info.CurrentAmount + info.Info.CurrentPendingAmount)))) + (info.TargetAmount - (info.Info.CurrentAmount + info.Info.CurrentPendingAmount)))) { return NotFound("Contribution Amount is more than is currently allowed."); } - + store.AdditionalClaims.Add(new Claim(Policies.CanCreateInvoice.Key, store.Id)); try { @@ -189,9 +186,7 @@ namespace BTCPayServer.Controllers NotificationURL = settings.NotificationUrl, FullNotifications = true, ExtendedNotifications = true, - RedirectURL = request.RedirectUrl ?? Request.GetDisplayUrl(), - - + RedirectURL = request.RedirectUrl ?? Request.GetDisplayUrl() }, store, HttpContext.Request.GetAbsoluteRoot()); if (request.RedirectToCheckout) { @@ -286,7 +281,7 @@ namespace BTCPayServer.Controllers public class AppsHelper { ApplicationDbContextFactory _ContextFactory; - private CurrencyNameTable _Currencies; + CurrencyNameTable _Currencies; private readonly RateFetcher _RateFetcher; private readonly HtmlSanitizer _HtmlSanitizer; public CurrencyNameTable Currencies => _Currencies; @@ -395,6 +390,57 @@ namespace BTCPayServer.Controllers .ToArray(); } + public async Task GetCurrentContributionAmount(Dictionary stats, string primaryCurrency, RateRules rateRules) + { + var result = new List(); + + var ratesTask = _RateFetcher.FetchRates( + stats.Keys + .Select((x) => new CurrencyPair(primaryCurrency, PaymentMethodId.Parse(x).CryptoCode)) + .Distinct() + .ToHashSet(), + rateRules).Select(async rateTask => + { + var (key, value) = rateTask; + var tResult = await value; + var rate = tResult.BidAsk?.Bid; + if (rate == null) return; + + foreach (var stat in stats) + { + if (string.Equals(PaymentMethodId.Parse(stat.Key).CryptoCode, key.Right, + StringComparison.InvariantCultureIgnoreCase)) + { + result.Add((1m / rate.Value) * stat.Value); + } + } + }); + + await Task.WhenAll(ratesTask); + + return result.Sum(); + } + + public Dictionary GetCurrentContributionAmountStats(InvoiceEntity[] invoices, bool usePaymentData = true) + { + if(usePaymentData){ + var payments = invoices.SelectMany(entity => entity.GetPayments()); + + var groupedByMethod = payments.GroupBy(entity => entity.GetPaymentMethodId()); + + return groupedByMethod.ToDictionary(entities => entities.Key.ToString(), + entities => entities.Sum(entity => entity.GetCryptoPaymentData().GetValue())); + } + else + { + return invoices + .GroupBy(entity => entity.ProductInformation.Currency) + .ToDictionary( + entities => entities.Key, + entities => entities.Sum(entity => entity.ProductInformation.Price)); + } + } + private class PosHolder { public string Key { get; set; } diff --git a/BTCPayServer/Crowdfund/CrowdfundHubStreamer.cs b/BTCPayServer/Crowdfund/CrowdfundHubStreamer.cs index c2382dab5..79a8a59c1 100644 --- a/BTCPayServer/Crowdfund/CrowdfundHubStreamer.cs +++ b/BTCPayServer/Crowdfund/CrowdfundHubStreamer.cs @@ -184,62 +184,6 @@ namespace BTCPayServer.Crowdfund }, TaskScheduler.Current); } - - private async Task GetCurrentContributionAmount(Dictionary stats, string primaryCurrency, RateRules rateRules) - { - decimal result = 0; - - var ratesTask = _RateFetcher .FetchRates( - stats.Keys - .Select((x) => new CurrencyPair( primaryCurrency, PaymentMethodId.Parse(x).CryptoCode)) - .Distinct() - .ToHashSet(), - rateRules); - - var finalTasks = new List(); - foreach (var rateTask in ratesTask) - { - finalTasks.Add(Task.Run(async () => - { - var tResult = await rateTask.Value; - var rate = tResult.BidAsk?.Bid; - if (rate == null) return; - - foreach (var stat in stats) - { - if (string.Equals(PaymentMethodId.Parse(stat.Key).CryptoCode, rateTask.Key.Right, - StringComparison.InvariantCultureIgnoreCase)) - { - result += (1m / rate.Value) * stat.Value; - } - } - })); - } - - await Task.WhenAll(finalTasks); - - return result; - } - - private static Dictionary GetCurrentContributionAmountStats(InvoiceEntity[] invoices, bool usePaymentData = true) - { - if(usePaymentData){ - var payments = invoices.SelectMany(entity => entity.GetPayments()); - - var groupedByMethod = payments.GroupBy(entity => entity.GetPaymentMethodId()); - - return groupedByMethod.ToDictionary(entities => entities.Key.ToString(), - entities => entities.Sum(entity => entity.GetCryptoPaymentData().GetValue())); - } - else - { - return invoices - .GroupBy(entity => entity.ProductInformation.Currency) - .ToDictionary( - entities => entities.Key, - entities => entities.Sum(entity => entity.ProductInformation.Price)); - } - } private async Task GetInfo(AppData appData, string statusMessage= null) { var settings = appData.GetSettings(); @@ -280,13 +224,13 @@ namespace BTCPayServer.Crowdfund var rateRules = appData.StoreData.GetStoreBlob().GetRateRules(_BtcPayNetworkProvider); - var pendingPaymentStats = GetCurrentContributionAmountStats(pendingInvoices, !settings.UseInvoiceAmount); - var paymentStats = GetCurrentContributionAmountStats(completeInvoices, !settings.UseInvoiceAmount); + var pendingPaymentStats = _AppsHelper.GetCurrentContributionAmountStats(pendingInvoices, !settings.UseInvoiceAmount); + var paymentStats = _AppsHelper.GetCurrentContributionAmountStats(completeInvoices, !settings.UseInvoiceAmount); - var currentAmount = await GetCurrentContributionAmount( + var currentAmount = await _AppsHelper.GetCurrentContributionAmount( paymentStats, settings.TargetCurrency, rateRules); - var currentPendingAmount = await GetCurrentContributionAmount( + var currentPendingAmount = await _AppsHelper.GetCurrentContributionAmount( pendingPaymentStats, settings.TargetCurrency, rateRules);