Decouple DefaultRates from BTCPayNetwork (#5974)

This commit is contained in:
Nicolas Dorier
2024-05-09 17:20:24 +09:00
committed by GitHub
parent 4c303d358b
commit adbe5977cd
17 changed files with 85 additions and 48 deletions

View File

@@ -356,13 +356,13 @@ retry:
{ {
var factory = FastTests.CreateBTCPayRateFactory(); var factory = FastTests.CreateBTCPayRateFactory();
var fetcher = new RateFetcher(factory); var fetcher = new RateFetcher(factory);
var provider = CreateNetworkProvider(ChainName.Mainnet); var provider = CreateDefaultRates(ChainName.Mainnet);
var b = new StoreBlob(); var b = new StoreBlob();
string[] temporarilyBroken = Array.Empty<string>(); string[] temporarilyBroken = Array.Empty<string>();
foreach (var k in StoreBlob.RecommendedExchanges) foreach (var k in StoreBlob.RecommendedExchanges)
{ {
b.DefaultCurrency = k.Key; b.DefaultCurrency = k.Key;
var rules = b.GetDefaultRateRules(provider); var rules = b.GetDefaultRateRules(provider.Select(p => p.DefaultRates));
var pairs = new[] { CurrencyPair.Parse($"BTC_{k.Key}") }.ToHashSet(); var pairs = new[] { CurrencyPair.Parse($"BTC_{k.Key}") }.ToHashSet();
var result = fetcher.FetchRates(pairs, rules, null, default); var result = fetcher.FetchRates(pairs, rules, null, default);
foreach ((CurrencyPair key, Task<RateResult> value) in result) foreach ((CurrencyPair key, Task<RateResult> value) in result)
@@ -389,11 +389,11 @@ retry:
public async Task CanGetRateCryptoCurrenciesByDefault() public async Task CanGetRateCryptoCurrenciesByDefault()
{ {
using var cts = new CancellationTokenSource(60_000); using var cts = new CancellationTokenSource(60_000);
var provider = CreateNetworkProvider(ChainName.Mainnet); var provider = CreateDefaultRates(ChainName.Mainnet);
var factory = FastTests.CreateBTCPayRateFactory(); var factory = FastTests.CreateBTCPayRateFactory();
var fetcher = new RateFetcher(factory); var fetcher = new RateFetcher(factory);
var pairs = var pairs =
provider.GetAll() provider
.Select(c => new CurrencyPair(c.CryptoCode, "USD")) .Select(c => new CurrencyPair(c.CryptoCode, "USD"))
.ToHashSet(); .ToHashSet();
@@ -408,7 +408,7 @@ retry:
} }
} }
var rules = new StoreBlob().GetDefaultRateRules(provider); var rules = new StoreBlob().GetDefaultRateRules(provider.Select(p => p.DefaultRates));
var result = fetcher.FetchRates(pairs, rules, null, cts.Token); var result = fetcher.FetchRates(pairs, rules, null, cts.Token);
foreach ((CurrencyPair key, Task<RateResult> value) in result) foreach ((CurrencyPair key, Task<RateResult> value) in result)
{ {
@@ -418,6 +418,17 @@ retry:
} }
} }
private IEnumerable<(string CryptoCode, DefaultRates DefaultRates)> CreateDefaultRates(ChainName chainName)
{
var results = new List<(string CryptoCode, DefaultRates DefaultRates)>();
var prov = CreateNetworkProvider(chainName);
foreach (var network in prov.GetAll())
{
results.Add((network.CryptoCode, new DefaultRates(network.DefaultRateRules)));
}
return results;
}
[Fact] [Fact]
[Trait("Fast", "Fast")] [Trait("Fast", "Fast")]
public async Task CheckJsContent() public async Task CheckJsContent()

View File

@@ -18,6 +18,8 @@ using BTCPayServer.Services.Wallets;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewComponents;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using NBitcoin; using NBitcoin;
using NBitcoin.Secp256k1; using NBitcoin.Secp256k1;
@@ -29,29 +31,31 @@ namespace BTCPayServer.Components.WalletNav
private readonly PaymentMethodHandlerDictionary _handlers; private readonly PaymentMethodHandlerDictionary _handlers;
private readonly UIWalletsController _walletsController; private readonly UIWalletsController _walletsController;
private readonly CurrencyNameTable _currencies; private readonly CurrencyNameTable _currencies;
private readonly BTCPayNetworkProvider _networkProvider; private readonly IEnumerable<DefaultRates> _defaultRates;
private readonly RateFetcher _rateFetcher; private readonly RateFetcher _rateFetcher;
public WalletNav( public WalletNav(
BTCPayWalletProvider walletProvider, BTCPayWalletProvider walletProvider,
PaymentMethodHandlerDictionary handlers, PaymentMethodHandlerDictionary handlers,
BTCPayNetworkProvider networkProvider,
UIWalletsController walletsController, UIWalletsController walletsController,
CurrencyNameTable currencies, CurrencyNameTable currencies,
IEnumerable<DefaultRates> defaultRates,
RateFetcher rateFetcher) RateFetcher rateFetcher)
{ {
_walletProvider = walletProvider; _walletProvider = walletProvider;
_handlers = handlers; _handlers = handlers;
_networkProvider = networkProvider;
_walletsController = walletsController; _walletsController = walletsController;
_currencies = currencies; _currencies = currencies;
_defaultRates = defaultRates;
_rateFetcher = rateFetcher; _rateFetcher = rateFetcher;
} }
public async Task<IViewComponentResult> InvokeAsync(WalletId walletId) public async Task<IViewComponentResult> InvokeAsync(WalletId walletId)
{ {
var store = ViewContext.HttpContext.GetStoreData(); var store = ViewContext.HttpContext.GetStoreData();
var network = _networkProvider.GetNetwork<BTCPayNetwork>(walletId.CryptoCode); var network = _handlers.TryGetNetwork(PaymentTypes.CHAIN.GetPaymentMethodId(walletId.CryptoCode));
if (network is null)
return new HtmlContentViewComponentResult(new StringHtmlContent(string.Empty));
var wallet = _walletProvider.GetWallet(network); var wallet = _walletProvider.GetWallet(network);
var defaultCurrency = store.GetStoreBlob().DefaultCurrency; var defaultCurrency = store.GetStoreBlob().DefaultCurrency;
var derivation = store.GetDerivationSchemeSettings(_handlers, walletId.CryptoCode); var derivation = store.GetDerivationSchemeSettings(_handlers, walletId.CryptoCode);
@@ -72,7 +76,7 @@ namespace BTCPayServer.Components.WalletNav
if (defaultCurrency != network.CryptoCode) if (defaultCurrency != network.CryptoCode)
{ {
var rule = store.GetStoreBlob().GetRateRules(_networkProvider)?.GetRuleFor(new Rating.CurrencyPair(network.CryptoCode, defaultCurrency)); var rule = store.GetStoreBlob().GetRateRules(_defaultRates)?.GetRuleFor(new Rating.CurrencyPair(network.CryptoCode, defaultCurrency));
var bid = rule is null ? null : (await _rateFetcher.FetchRate(rule, new StoreIdRateContext(walletId.StoreId), HttpContext.RequestAborted)).BidAsk?.Bid; var bid = rule is null ? null : (await _rateFetcher.FetchRate(rule, new StoreIdRateContext(walletId.StoreId), HttpContext.RequestAborted)).BidAsk?.Bid;
if (bid is decimal b) if (bid is decimal b)
{ {

View File

@@ -30,8 +30,8 @@ namespace BTCPayServer.Controllers
{ {
readonly RateFetcher _rateProviderFactory; readonly RateFetcher _rateProviderFactory;
readonly BTCPayNetworkProvider _networkProvider;
readonly CurrencyNameTable _currencyNameTable; readonly CurrencyNameTable _currencyNameTable;
private readonly IEnumerable<DefaultRates> _defaultRates;
private readonly PaymentMethodHandlerDictionary _handlers; private readonly PaymentMethodHandlerDictionary _handlers;
readonly StoreRepository _storeRepo; readonly StoreRepository _storeRepo;
private readonly InvoiceRepository _invoiceRepository; private readonly InvoiceRepository _invoiceRepository;
@@ -40,17 +40,17 @@ namespace BTCPayServer.Controllers
public BitpayRateController( public BitpayRateController(
RateFetcher rateProviderFactory, RateFetcher rateProviderFactory,
BTCPayNetworkProvider networkProvider,
StoreRepository storeRepo, StoreRepository storeRepo,
InvoiceRepository invoiceRepository, InvoiceRepository invoiceRepository,
CurrencyNameTable currencyNameTable, CurrencyNameTable currencyNameTable,
IEnumerable<DefaultRates> defaultRates,
PaymentMethodHandlerDictionary handlers) PaymentMethodHandlerDictionary handlers)
{ {
_rateProviderFactory = rateProviderFactory ?? throw new ArgumentNullException(nameof(rateProviderFactory)); _rateProviderFactory = rateProviderFactory ?? throw new ArgumentNullException(nameof(rateProviderFactory));
_networkProvider = networkProvider;
_storeRepo = storeRepo; _storeRepo = storeRepo;
_invoiceRepository = invoiceRepository; _invoiceRepository = invoiceRepository;
_currencyNameTable = currencyNameTable ?? throw new ArgumentNullException(nameof(currencyNameTable)); _currencyNameTable = currencyNameTable ?? throw new ArgumentNullException(nameof(currencyNameTable));
_defaultRates = defaultRates;
_handlers = handlers; _handlers = handlers;
} }
@@ -124,7 +124,7 @@ namespace BTCPayServer.Controllers
} }
} }
var rules = store.GetStoreBlob().GetRateRules(_networkProvider); var rules = store.GetStoreBlob().GetRateRules(_defaultRates);
var pairs = new HashSet<CurrencyPair>(); var pairs = new HashSet<CurrencyPair>();
foreach (var currency in currencyPairs.Split(',')) foreach (var currency in currencyPairs.Split(','))
{ {

View File

@@ -40,7 +40,6 @@ namespace BTCPayServer.Controllers.Greenfield
private readonly InvoiceRepository _invoiceRepository; private readonly InvoiceRepository _invoiceRepository;
private readonly LinkGenerator _linkGenerator; private readonly LinkGenerator _linkGenerator;
private readonly CurrencyNameTable _currencyNameTable; private readonly CurrencyNameTable _currencyNameTable;
private readonly BTCPayNetworkProvider _networkProvider;
private readonly PullPaymentHostedService _pullPaymentService; private readonly PullPaymentHostedService _pullPaymentService;
private readonly RateFetcher _rateProvider; private readonly RateFetcher _rateProvider;
private readonly InvoiceActivator _invoiceActivator; private readonly InvoiceActivator _invoiceActivator;
@@ -49,11 +48,12 @@ namespace BTCPayServer.Controllers.Greenfield
private readonly Dictionary<PaymentMethodId, IPaymentLinkExtension> _paymentLinkExtensions; private readonly Dictionary<PaymentMethodId, IPaymentLinkExtension> _paymentLinkExtensions;
private readonly PayoutMethodHandlerDictionary _payoutHandlers; private readonly PayoutMethodHandlerDictionary _payoutHandlers;
private readonly PaymentMethodHandlerDictionary _handlers; private readonly PaymentMethodHandlerDictionary _handlers;
private readonly IEnumerable<DefaultRates> _defaultRates;
public LanguageService LanguageService { get; } public LanguageService LanguageService { get; }
public GreenfieldInvoiceController(UIInvoiceController invoiceController, InvoiceRepository invoiceRepository, public GreenfieldInvoiceController(UIInvoiceController invoiceController, InvoiceRepository invoiceRepository,
LinkGenerator linkGenerator, LanguageService languageService, BTCPayNetworkProvider btcPayNetworkProvider, LinkGenerator linkGenerator, LanguageService languageService,
CurrencyNameTable currencyNameTable, RateFetcher rateProvider, CurrencyNameTable currencyNameTable, RateFetcher rateProvider,
InvoiceActivator invoiceActivator, InvoiceActivator invoiceActivator,
PullPaymentHostedService pullPaymentService, PullPaymentHostedService pullPaymentService,
@@ -61,13 +61,13 @@ namespace BTCPayServer.Controllers.Greenfield
IAuthorizationService authorizationService, IAuthorizationService authorizationService,
Dictionary<PaymentMethodId, IPaymentLinkExtension> paymentLinkExtensions, Dictionary<PaymentMethodId, IPaymentLinkExtension> paymentLinkExtensions,
PayoutMethodHandlerDictionary payoutHandlers, PayoutMethodHandlerDictionary payoutHandlers,
PaymentMethodHandlerDictionary handlers) PaymentMethodHandlerDictionary handlers,
IEnumerable<DefaultRates> defaultRates)
{ {
_invoiceController = invoiceController; _invoiceController = invoiceController;
_invoiceRepository = invoiceRepository; _invoiceRepository = invoiceRepository;
_linkGenerator = linkGenerator; _linkGenerator = linkGenerator;
_currencyNameTable = currencyNameTable; _currencyNameTable = currencyNameTable;
_networkProvider = btcPayNetworkProvider;
_rateProvider = rateProvider; _rateProvider = rateProvider;
_invoiceActivator = invoiceActivator; _invoiceActivator = invoiceActivator;
_pullPaymentService = pullPaymentService; _pullPaymentService = pullPaymentService;
@@ -76,6 +76,7 @@ namespace BTCPayServer.Controllers.Greenfield
_paymentLinkExtensions = paymentLinkExtensions; _paymentLinkExtensions = paymentLinkExtensions;
_payoutHandlers = payoutHandlers; _payoutHandlers = payoutHandlers;
_handlers = handlers; _handlers = handlers;
_defaultRates = defaultRates;
LanguageService = languageService; LanguageService = languageService;
} }
@@ -429,7 +430,7 @@ namespace BTCPayServer.Controllers.Greenfield
var paidCurrency = Math.Round(cryptoPaid * paymentPrompt.Rate, cdCurrency.Divisibility); var paidCurrency = Math.Round(cryptoPaid * paymentPrompt.Rate, cdCurrency.Divisibility);
var rateResult = await _rateProvider.FetchRate( var rateResult = await _rateProvider.FetchRate(
new CurrencyPair(paymentPrompt.Currency, invoice.Currency), new CurrencyPair(paymentPrompt.Currency, invoice.Currency),
store.GetStoreBlob().GetRateRules(_networkProvider), new StoreIdRateContext(storeId), store.GetStoreBlob().GetRateRules(_defaultRates), new StoreIdRateContext(storeId),
cancellationToken cancellationToken
); );

View File

@@ -10,6 +10,7 @@ using BTCPayServer.Client;
using BTCPayServer.Client.Models; using BTCPayServer.Client.Models;
using BTCPayServer.Data; using BTCPayServer.Data;
using BTCPayServer.Rating; using BTCPayServer.Rating;
using BTCPayServer.Services.Invoices;
using BTCPayServer.Services.Rates; using BTCPayServer.Services.Rates;
using BTCPayServer.Services.Stores; using BTCPayServer.Services.Stores;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
@@ -26,16 +27,16 @@ namespace BTCPayServer.Controllers.GreenField
public class GreenfieldStoreRateConfigurationController : ControllerBase public class GreenfieldStoreRateConfigurationController : ControllerBase
{ {
private readonly RateFetcher _rateProviderFactory; private readonly RateFetcher _rateProviderFactory;
private readonly BTCPayNetworkProvider _btcPayNetworkProvider; private readonly IEnumerable<DefaultRates> _defaultRates;
private readonly StoreRepository _storeRepository; private readonly StoreRepository _storeRepository;
public GreenfieldStoreRateConfigurationController( public GreenfieldStoreRateConfigurationController(
RateFetcher rateProviderFactory, RateFetcher rateProviderFactory,
BTCPayNetworkProvider btcPayNetworkProvider, IEnumerable<DefaultRates> defaultRates,
StoreRepository storeRepository) StoreRepository storeRepository)
{ {
_rateProviderFactory = rateProviderFactory; _rateProviderFactory = rateProviderFactory;
_btcPayNetworkProvider = btcPayNetworkProvider; _defaultRates = defaultRates;
_storeRepository = storeRepository; _storeRepository = storeRepository;
} }
@@ -48,7 +49,7 @@ namespace BTCPayServer.Controllers.GreenField
return Ok(new StoreRateConfiguration() return Ok(new StoreRateConfiguration()
{ {
EffectiveScript = blob.GetRateRules(_btcPayNetworkProvider, out var preferredExchange).ToString(), EffectiveScript = blob.GetRateRules(_defaultRates, out var preferredExchange).ToString(),
Spread = blob.Spread * 100.0m, Spread = blob.Spread * 100.0m,
IsCustomScript = blob.RateScripting, IsCustomScript = blob.RateScripting,
PreferredSource = preferredExchange ? blob.PreferredExchange : null PreferredSource = preferredExchange ? blob.PreferredExchange : null
@@ -117,7 +118,7 @@ namespace BTCPayServer.Controllers.GreenField
return this.CreateValidationError(ModelState); return this.CreateValidationError(ModelState);
PopulateBlob(configuration, blob); PopulateBlob(configuration, blob);
var rules = blob.GetRateRules(_btcPayNetworkProvider); var rules = blob.GetRateRules(_defaultRates);
var rateTasks = _rateProviderFactory.FetchRates(parsedCurrencyPairs, rules, new StoreIdRateContext(data.Id), CancellationToken.None); var rateTasks = _rateProviderFactory.FetchRates(parsedCurrencyPairs, rules, new StoreIdRateContext(data.Id), CancellationToken.None);
@@ -155,7 +156,7 @@ namespace BTCPayServer.Controllers.GreenField
{ {
if (string.IsNullOrEmpty(configuration.EffectiveScript)) if (string.IsNullOrEmpty(configuration.EffectiveScript))
{ {
configuration.EffectiveScript = storeBlob.GetDefaultRateRules(_btcPayNetworkProvider).ToString(); configuration.EffectiveScript = storeBlob.GetDefaultRateRules(_defaultRates).ToString();
} }
if (!RateRules.TryParse(configuration.EffectiveScript, out var r)) if (!RateRules.TryParse(configuration.EffectiveScript, out var r))

View File

@@ -9,6 +9,7 @@ using BTCPayServer.Client;
using BTCPayServer.Client.Models; using BTCPayServer.Client.Models;
using BTCPayServer.Data; using BTCPayServer.Data;
using BTCPayServer.Rating; using BTCPayServer.Rating;
using BTCPayServer.Services.Invoices;
using BTCPayServer.Services.Rates; using BTCPayServer.Services.Rates;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Cors;
@@ -23,14 +24,14 @@ namespace BTCPayServer.Controllers.GreenField
public class GreenfieldStoreRatesController : ControllerBase public class GreenfieldStoreRatesController : ControllerBase
{ {
private readonly RateFetcher _rateProviderFactory; private readonly RateFetcher _rateProviderFactory;
private readonly BTCPayNetworkProvider _btcPayNetworkProvider; private readonly IEnumerable<DefaultRates> _defaultRates;
public GreenfieldStoreRatesController( public GreenfieldStoreRatesController(
RateFetcher rateProviderFactory, RateFetcher rateProviderFactory,
BTCPayNetworkProvider btcPayNetworkProvider) IEnumerable<DefaultRates> defaultRates)
{ {
_rateProviderFactory = rateProviderFactory; _rateProviderFactory = rateProviderFactory;
_btcPayNetworkProvider = btcPayNetworkProvider; _defaultRates = defaultRates;
} }
[HttpGet("")] [HttpGet("")]
@@ -61,7 +62,7 @@ namespace BTCPayServer.Controllers.GreenField
} }
var rules = blob.GetRateRules(_btcPayNetworkProvider); var rules = blob.GetRateRules(_defaultRates);
var rateTasks = _rateProviderFactory.FetchRates(parsedCurrencyPairs, rules, new StoreIdRateContext(data.Id), CancellationToken.None); var rateTasks = _rateProviderFactory.FetchRates(parsedCurrencyPairs, rules, new StoreIdRateContext(data.Id), CancellationToken.None);

View File

@@ -382,7 +382,7 @@ namespace BTCPayServer.Controllers
var paidCurrency = Math.Round(cryptoPaid * paymentMethod.Rate, cdCurrency.Divisibility); var paidCurrency = Math.Round(cryptoPaid * paymentMethod.Rate, cdCurrency.Divisibility);
model.CryptoAmountThen = cryptoPaid.RoundToSignificant(paymentMethod.Divisibility); model.CryptoAmountThen = cryptoPaid.RoundToSignificant(paymentMethod.Divisibility);
model.RateThenText = _displayFormatter.Currency(model.CryptoAmountThen, paymentMethodCurrency); model.RateThenText = _displayFormatter.Currency(model.CryptoAmountThen, paymentMethodCurrency);
rules = store.GetStoreBlob().GetRateRules(_NetworkProvider); rules = store.GetStoreBlob().GetRateRules(_defaultRates);
rateResult = await _RateProvider.FetchRate( rateResult = await _RateProvider.FetchRate(
new CurrencyPair(paymentMethodCurrency, invoice.Currency), rules, new StoreIdRateContext(store.Id), new CurrencyPair(paymentMethodCurrency, invoice.Currency), rules, new StoreIdRateContext(store.Id),
cancellationToken); cancellationToken);
@@ -491,7 +491,7 @@ namespace BTCPayServer.Controllers
return View("_RefundModal", model); return View("_RefundModal", model);
} }
rules = store.GetStoreBlob().GetRateRules(_NetworkProvider); rules = store.GetStoreBlob().GetRateRules(_defaultRates);
rateResult = await _RateProvider.FetchRate( rateResult = await _RateProvider.FetchRate(
new CurrencyPair(paymentMethodCurrency, model.CustomCurrency), rules, new StoreIdRateContext(store.Id), new CurrencyPair(paymentMethodCurrency, model.CustomCurrency), rules, new StoreIdRateContext(store.Id),
cancellationToken); cancellationToken);

View File

@@ -52,6 +52,7 @@ namespace BTCPayServer.Controllers
readonly BTCPayNetworkProvider _NetworkProvider; readonly BTCPayNetworkProvider _NetworkProvider;
private readonly PayoutMethodHandlerDictionary _payoutHandlers; private readonly PayoutMethodHandlerDictionary _payoutHandlers;
private readonly PaymentMethodHandlerDictionary _handlers; private readonly PaymentMethodHandlerDictionary _handlers;
private readonly IEnumerable<DefaultRates> _defaultRates;
private readonly ApplicationDbContextFactory _dbContextFactory; private readonly ApplicationDbContextFactory _dbContextFactory;
private readonly PullPaymentHostedService _paymentHostedService; private readonly PullPaymentHostedService _paymentHostedService;
private readonly LanguageService _languageService; private readonly LanguageService _languageService;
@@ -93,6 +94,7 @@ namespace BTCPayServer.Controllers
AppService appService, AppService appService,
IFileService fileService, IFileService fileService,
UriResolver uriResolver, UriResolver uriResolver,
IEnumerable<DefaultRates> defaultRates,
IAuthorizationService authorizationService, IAuthorizationService authorizationService,
TransactionLinkProviders transactionLinkProviders, TransactionLinkProviders transactionLinkProviders,
Dictionary<PaymentMethodId, IPaymentModelExtension> paymentModelExtensions, Dictionary<PaymentMethodId, IPaymentModelExtension> paymentModelExtensions,
@@ -123,6 +125,7 @@ namespace BTCPayServer.Controllers
_viewProvider = viewProvider; _viewProvider = viewProvider;
_fileService = fileService; _fileService = fileService;
_uriResolver = uriResolver; _uriResolver = uriResolver;
_defaultRates = defaultRates;
_appService = appService; _appService = appService;
} }
@@ -294,7 +297,7 @@ namespace BTCPayServer.Controllers
private async Task FetchRates(InvoiceCreationContext context, CancellationToken cancellationToken) private async Task FetchRates(InvoiceCreationContext context, CancellationToken cancellationToken)
{ {
var rateRules = context.StoreBlob.GetRateRules(_NetworkProvider); var rateRules = context.StoreBlob.GetRateRules(_defaultRates);
await context.FetchingRates(_RateProvider, rateRules, cancellationToken); await context.FetchingRates(_RateProvider, rateRules, cancellationToken);
} }
} }

View File

@@ -28,8 +28,8 @@ public partial class UIStoresController
vm.SetExchangeRates(exchanges, storeBlob.PreferredExchange ?? storeBlob.GetRecommendedExchange()); vm.SetExchangeRates(exchanges, storeBlob.PreferredExchange ?? storeBlob.GetRecommendedExchange());
vm.Spread = (double)(storeBlob.Spread * 100m); vm.Spread = (double)(storeBlob.Spread * 100m);
vm.StoreId = CurrentStore.Id; vm.StoreId = CurrentStore.Id;
vm.Script = storeBlob.GetRateRules(_networkProvider).ToString(); vm.Script = storeBlob.GetRateRules(_defaultRates).ToString();
vm.DefaultScript = storeBlob.GetDefaultRateRules(_networkProvider).ToString(); vm.DefaultScript = storeBlob.GetDefaultRateRules(_defaultRates).ToString();
vm.AvailableExchanges = exchanges; vm.AvailableExchanges = exchanges;
vm.DefaultCurrencyPairs = storeBlob.GetDefaultCurrencyPairString(); vm.DefaultCurrencyPairs = storeBlob.GetDefaultCurrencyPairString();
vm.ShowScripting = storeBlob.RateScripting; vm.ShowScripting = storeBlob.RateScripting;
@@ -72,7 +72,7 @@ public partial class UIStoresController
model.PreferredExchange = model.PreferredExchange.Trim().ToLowerInvariant(); model.PreferredExchange = model.PreferredExchange.Trim().ToLowerInvariant();
var blob = CurrentStore.GetStoreBlob(); var blob = CurrentStore.GetStoreBlob();
model.DefaultScript = blob.GetDefaultRateRules(_networkProvider).ToString(); model.DefaultScript = blob.GetDefaultRateRules(_defaultRates).ToString();
model.AvailableExchanges = exchanges; model.AvailableExchanges = exchanges;
blob.PreferredExchange = model.PreferredExchange; blob.PreferredExchange = model.PreferredExchange;
@@ -103,7 +103,7 @@ public partial class UIStoresController
model.Script = blob.RateScript; model.Script = blob.RateScript;
} }
} }
rules = blob.GetRateRules(_networkProvider); rules = blob.GetRateRules(_defaultRates);
if (command == "Test") if (command == "Test")
{ {
@@ -175,7 +175,7 @@ public partial class UIStoresController
{ {
var blob = CurrentStore.GetStoreBlob(); var blob = CurrentStore.GetStoreBlob();
blob.RateScripting = scripting; blob.RateScripting = scripting;
blob.RateScript = blob.GetDefaultRateRules(_networkProvider).ToString(); blob.RateScript = blob.GetDefaultRateRules(_defaultRates).ToString();
CurrentStore.SetStoreBlob(blob); CurrentStore.SetStoreBlob(blob);
await _storeRepo.UpdateStore(CurrentStore); await _storeRepo.UpdateStore(CurrentStore);
TempData[WellKnownTempData.SuccessMessage] = "Rate rules scripting " + (scripting ? "activated" : "deactivated"); TempData[WellKnownTempData.SuccessMessage] = "Rate rules scripting " + (scripting ? "activated" : "deactivated");

View File

@@ -1,4 +1,5 @@
#nullable enable #nullable enable
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Abstractions.Constants; using BTCPayServer.Abstractions.Constants;
@@ -54,6 +55,7 @@ public partial class UIStoresController : Controller
IOptions<LightningNetworkOptions> lightningNetworkOptions, IOptions<LightningNetworkOptions> lightningNetworkOptions,
IOptions<ExternalServicesOptions> externalServiceOptions, IOptions<ExternalServicesOptions> externalServiceOptions,
IHtmlHelper html, IHtmlHelper html,
IEnumerable<DefaultRates> defaultRates,
EmailSenderFactory emailSenderFactory, EmailSenderFactory emailSenderFactory,
WalletFileParsers onChainWalletParsers, WalletFileParsers onChainWalletParsers,
UriResolver uriResolver, UriResolver uriResolver,
@@ -83,6 +85,7 @@ public partial class UIStoresController : Controller
_settingsRepository = settingsRepository; _settingsRepository = settingsRepository;
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
_html = html; _html = html;
_defaultRates = defaultRates;
_dataProtector = dataProtector.CreateProtector("ConfigProtector"); _dataProtector = dataProtector.CreateProtector("ConfigProtector");
_webhookNotificationManager = webhookNotificationManager; _webhookNotificationManager = webhookNotificationManager;
_lightningNetworkOptions = lightningNetworkOptions.Value; _lightningNetworkOptions = lightningNetworkOptions.Value;
@@ -101,6 +104,7 @@ public partial class UIStoresController : Controller
private readonly ExplorerClientProvider _explorerProvider; private readonly ExplorerClientProvider _explorerProvider;
private readonly LanguageService _langService; private readonly LanguageService _langService;
private readonly PaymentMethodHandlerDictionary _handlers; private readonly PaymentMethodHandlerDictionary _handlers;
private readonly IEnumerable<DefaultRates> _defaultRates;
private readonly PoliciesSettings _policiesSettings; private readonly PoliciesSettings _policiesSettings;
private readonly IAuthorizationService _authorizationService; private readonly IAuthorizationService _authorizationService;
private readonly AppService _appService; private readonly AppService _appService;

View File

@@ -73,6 +73,7 @@ namespace BTCPayServer.Controllers
private readonly PayjoinClient _payjoinClient; private readonly PayjoinClient _payjoinClient;
private readonly LabelService _labelService; private readonly LabelService _labelService;
private readonly PaymentMethodHandlerDictionary _handlers; private readonly PaymentMethodHandlerDictionary _handlers;
private readonly IEnumerable<DefaultRates> _defaultRates;
private readonly Dictionary<PaymentMethodId, IPaymentModelExtension> _paymentModelExtensions; private readonly Dictionary<PaymentMethodId, IPaymentModelExtension> _paymentModelExtensions;
private readonly TransactionLinkProviders _transactionLinkProviders; private readonly TransactionLinkProviders _transactionLinkProviders;
private readonly PullPaymentHostedService _pullPaymentHostedService; private readonly PullPaymentHostedService _pullPaymentHostedService;
@@ -99,12 +100,14 @@ namespace BTCPayServer.Controllers
IServiceProvider serviceProvider, IServiceProvider serviceProvider,
PullPaymentHostedService pullPaymentHostedService, PullPaymentHostedService pullPaymentHostedService,
LabelService labelService, LabelService labelService,
IEnumerable<DefaultRates> defaultRates,
PaymentMethodHandlerDictionary handlers, PaymentMethodHandlerDictionary handlers,
Dictionary<PaymentMethodId, IPaymentModelExtension> paymentModelExtensions, Dictionary<PaymentMethodId, IPaymentModelExtension> paymentModelExtensions,
TransactionLinkProviders transactionLinkProviders) TransactionLinkProviders transactionLinkProviders)
{ {
_currencyTable = currencyTable; _currencyTable = currencyTable;
_labelService = labelService; _labelService = labelService;
_defaultRates = defaultRates;
_handlers = handlers; _handlers = handlers;
_paymentModelExtensions = paymentModelExtensions; _paymentModelExtensions = paymentModelExtensions;
_transactionLinkProviders = transactionLinkProviders; _transactionLinkProviders = transactionLinkProviders;
@@ -456,7 +459,7 @@ namespace BTCPayServer.Controllers
if (network == null || network.ReadonlyWallet) if (network == null || network.ReadonlyWallet)
return NotFound(); return NotFound();
var storeData = store.GetStoreBlob(); var storeData = store.GetStoreBlob();
var rateRules = store.GetStoreBlob().GetRateRules(NetworkProvider); var rateRules = store.GetStoreBlob().GetRateRules(_defaultRates);
rateRules.Spread = 0.0m; rateRules.Spread = 0.0m;
var currencyPair = new Rating.CurrencyPair(walletId.CryptoCode, storeData.DefaultCurrency); var currencyPair = new Rating.CurrencyPair(walletId.CryptoCode, storeData.DefaultCurrency);
double.TryParse(defaultAmount, out var amount); double.TryParse(defaultAmount, out var amount);

View File

@@ -49,6 +49,7 @@ public class BitcoinLikePayoutHandler : IPayoutHandler, IHasNetwork
public PayoutMethodId PayoutMethodId { get; } public PayoutMethodId PayoutMethodId { get; }
public PaymentMethodId PaymentMethodId { get; } public PaymentMethodId PaymentMethodId { get; }
public BTCPayNetwork Network { get; } public BTCPayNetwork Network { get; }
public string[] DefaultRateRules => Network.DefaultRateRules;
public WalletRepository WalletRepository { get; } public WalletRepository WalletRepository { get; }
public BitcoinLikePayoutHandler(BTCPayNetworkProvider btcPayNetworkProvider, public BitcoinLikePayoutHandler(BTCPayNetworkProvider btcPayNetworkProvider,

View File

@@ -34,6 +34,7 @@ namespace BTCPayServer.Data.Payouts.LightningLike
private PaymentMethodHandlerDictionary _paymentHandlers; private PaymentMethodHandlerDictionary _paymentHandlers;
public BTCPayNetwork Network { get; } public BTCPayNetwork Network { get; }
public string[] DefaultRateRules => Network.DefaultRateRules;
public const string LightningLikePayoutHandlerOnionNamedClient = public const string LightningLikePayoutHandlerOnionNamedClient =
nameof(LightningLikePayoutHandlerOnionNamedClient); nameof(LightningLikePayoutHandlerOnionNamedClient);

View File

@@ -10,6 +10,7 @@ using BTCPayServer.Controllers;
using BTCPayServer.JsonConverters; using BTCPayServer.JsonConverters;
using BTCPayServer.Payments; using BTCPayServer.Payments;
using BTCPayServer.Rating; using BTCPayServer.Rating;
using BTCPayServer.Services.Invoices;
using BTCPayServer.Services.Mails; using BTCPayServer.Services.Mails;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
@@ -134,18 +135,18 @@ namespace BTCPayServer.Data
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public double PaymentTolerance { get; set; } public double PaymentTolerance { get; set; }
public BTCPayServer.Rating.RateRules GetRateRules(BTCPayNetworkProvider networkProvider) public BTCPayServer.Rating.RateRules GetRateRules(IEnumerable<DefaultRates> defaultRates)
{ {
return GetRateRules(networkProvider, out _); return GetRateRules(defaultRates, out _);
} }
public BTCPayServer.Rating.RateRules GetRateRules(BTCPayNetworkProvider networkProvider, out bool preferredSource) public BTCPayServer.Rating.RateRules GetRateRules(IEnumerable<DefaultRates> defaultRates, out bool preferredSource)
{ {
if (!RateScripting || if (!RateScripting ||
string.IsNullOrEmpty(RateScript) || string.IsNullOrEmpty(RateScript) ||
!BTCPayServer.Rating.RateRules.TryParse(RateScript, out var rules)) !BTCPayServer.Rating.RateRules.TryParse(RateScript, out var rules))
{ {
preferredSource = true; preferredSource = true;
return GetDefaultRateRules(networkProvider); return GetDefaultRateRules(defaultRates);
} }
else else
{ {
@@ -155,15 +156,14 @@ namespace BTCPayServer.Data
} }
} }
public RateRules GetDefaultRateRules(BTCPayNetworkProvider networkProvider) public RateRules GetDefaultRateRules(IEnumerable<DefaultRates> defaultRates)
{ {
var builder = new StringBuilder(); var builder = new StringBuilder();
foreach (var network in networkProvider.GetAll()) foreach (var rates in defaultRates)
{ {
if (network.DefaultRateRules.Length != 0) if (rates.Rates is { Length: > 0 } r)
{ {
builder.AppendLine(CultureInfo.InvariantCulture, $"// Default rate rules for {network.CryptoCode}"); foreach (var line in r)
foreach (var line in network.DefaultRateRules)
{ {
builder.AppendLine(line); builder.AppendLine(line);
} }

View File

@@ -0,0 +1,2 @@
namespace BTCPayServer;
public record DefaultRates(string[] Rates);

View File

@@ -279,6 +279,7 @@ namespace BTCPayServer.HostedServices
EventAggregator eventAggregator, EventAggregator eventAggregator,
BTCPayNetworkProvider networkProvider, BTCPayNetworkProvider networkProvider,
PayoutMethodHandlerDictionary handlers, PayoutMethodHandlerDictionary handlers,
IEnumerable<DefaultRates> defaultRates,
NotificationSender notificationSender, NotificationSender notificationSender,
RateFetcher rateFetcher, RateFetcher rateFetcher,
ILogger<PullPaymentHostedService> logger, ILogger<PullPaymentHostedService> logger,
@@ -291,6 +292,7 @@ namespace BTCPayServer.HostedServices
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
_networkProvider = networkProvider; _networkProvider = networkProvider;
_handlers = handlers; _handlers = handlers;
_defaultRates = defaultRates;
_notificationSender = notificationSender; _notificationSender = notificationSender;
_rateFetcher = rateFetcher; _rateFetcher = rateFetcher;
_logger = logger; _logger = logger;
@@ -304,6 +306,7 @@ namespace BTCPayServer.HostedServices
private readonly EventAggregator _eventAggregator; private readonly EventAggregator _eventAggregator;
private readonly BTCPayNetworkProvider _networkProvider; private readonly BTCPayNetworkProvider _networkProvider;
private readonly PayoutMethodHandlerDictionary _handlers; private readonly PayoutMethodHandlerDictionary _handlers;
private readonly IEnumerable<DefaultRates> _defaultRates;
private readonly NotificationSender _notificationSender; private readonly NotificationSender _notificationSender;
private readonly RateFetcher _rateFetcher; private readonly RateFetcher _rateFetcher;
private readonly ILogger<PullPaymentHostedService> _logger; private readonly ILogger<PullPaymentHostedService> _logger;
@@ -389,7 +392,7 @@ namespace BTCPayServer.HostedServices
if (explicitRateRule is null) if (explicitRateRule is null)
{ {
var storeBlob = payout.StoreData.GetStoreBlob(); var storeBlob = payout.StoreData.GetStoreBlob();
var rules = storeBlob.GetRateRules(_networkProvider); var rules = storeBlob.GetRateRules(_defaultRates);
rules.Spread = 0.0m; rules.Spread = 0.0m;
rule = rules.GetRuleFor(currencyPair); rule = rules.GetRuleFor(currencyPair);
} }

View File

@@ -563,11 +563,13 @@ o.GetRequiredService<IEnumerable<IPaymentLinkExtension>>().ToDictionary(o => o.P
} }
public static IServiceCollection AddBTCPayNetwork(this IServiceCollection services, BTCPayNetworkBase network) public static IServiceCollection AddBTCPayNetwork(this IServiceCollection services, BTCPayNetworkBase network)
{ {
services.AddSingleton(new DefaultRates(network.DefaultRateRules));
services.AddSingleton<BTCPayNetworkBase>(network); services.AddSingleton<BTCPayNetworkBase>(network);
return services; return services;
} }
public static IServiceCollection AddBTCPayNetwork(this IServiceCollection services, BTCPayNetwork network) public static IServiceCollection AddBTCPayNetwork(this IServiceCollection services, BTCPayNetwork network)
{ {
services.AddSingleton(new DefaultRates(network.DefaultRateRules));
// BTC // BTC
{ {
var pmi = PaymentTypes.CHAIN.GetPaymentMethodId(network.CryptoCode); var pmi = PaymentTypes.CHAIN.GetPaymentMethodId(network.CryptoCode);