Can inject currency data in CurrencyNameTable (#6276)

This commit is contained in:
Nicolas Dorier
2024-10-04 22:24:44 +09:00
committed by GitHub
parent 206d222455
commit 64ba8248d2
13 changed files with 179 additions and 53 deletions

View File

@@ -1175,13 +1175,6 @@
"symbol":null, "symbol":null,
"crypto":true "crypto":true
}, },
{
"name":"USDt",
"code":"USDT",
"divisibility":8,
"symbol":null,
"crypto":true
},
{ {
"name":"LCAD", "name":"LCAD",
"code":"LCAD", "code":"LCAD",
@@ -1315,13 +1308,6 @@
"symbol": null, "symbol": null,
"crypto": true "crypto": true
}, },
{
"name":"USDt",
"code":"USDT20",
"divisibility":6,
"symbol":null,
"crypto":true
},
{ {
"name":"FaucetToken", "name":"FaucetToken",
"code":"FAU", "code":"FAU",

View File

@@ -5,6 +5,9 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using NBitcoin; using NBitcoin;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -18,14 +21,74 @@ namespace BTCPayServer.Services.Rates
public string Symbol { get; set; } public string Symbol { get; set; }
public bool Crypto { get; set; } public bool Crypto { get; set; }
} }
public class CurrencyNameTable public interface CurrencyDataProvider
{ {
public static CurrencyNameTable Instance = new(); Task<CurrencyData[]> LoadCurrencyData(CancellationToken cancellationToken);
public CurrencyNameTable() }
public class InMemoryCurrencyDataProvider : CurrencyDataProvider
{ {
_Currencies = LoadCurrency().ToDictionary(k => k.Code, StringComparer.InvariantCultureIgnoreCase); private readonly CurrencyData[] _currencyData;
public InMemoryCurrencyDataProvider(CurrencyData[] currencyData)
{
_currencyData = currencyData;
} }
public Task<CurrencyData[]> LoadCurrencyData(CancellationToken cancellationToken) => Task.FromResult(_currencyData);
}
public class AssemblyCurrencyDataProvider : CurrencyDataProvider
{
private readonly Assembly _assembly;
private readonly string _manifestResourceStream;
public AssemblyCurrencyDataProvider(Assembly assembly, string manifestResourceStream)
{
_assembly = assembly;
_manifestResourceStream = manifestResourceStream;
}
public Task<CurrencyData[]> LoadCurrencyData(CancellationToken cancellationToken)
{
var stream = _assembly.GetManifestResourceStream(_manifestResourceStream);
if (stream is null)
throw new InvalidOperationException("Unknown manifestResourceStream");
string content = null;
using (var reader = new StreamReader(stream, Encoding.UTF8))
{
content = reader.ReadToEnd();
}
var currencies = JsonConvert.DeserializeObject<CurrencyData[]>(content);
return Task.FromResult(currencies.ToArray());
}
}
public class CurrencyNameTable
{
public CurrencyNameTable(IEnumerable<CurrencyDataProvider> currencyDataProviders, ILogger<CurrencyNameTable> logger)
{
_currencyDataProviders = currencyDataProviders;
_logger = logger;
}
public async Task ReloadCurrencyData(CancellationToken cancellationToken)
{
var currencies = new Dictionary<string, CurrencyData>(StringComparer.InvariantCultureIgnoreCase);
var loadings = _currencyDataProviders.Select(c => (Task: c.LoadCurrencyData(cancellationToken), Prov: c)).ToList();
foreach (var loading in loadings)
{
try
{
foreach (var curr in await loading.Task)
{
currencies.TryAdd(curr.Code, curr);
}
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Error loading currency data for " + loading.Prov.GetType().FullName);
}
}
_Currencies = currencies;
}
static readonly Dictionary<string, IFormatProvider> _CurrencyProviders = new(); static readonly Dictionary<string, IFormatProvider> _CurrencyProviders = new();
public NumberFormatInfo GetNumberFormatInfo(string currency, bool useFallback) public NumberFormatInfo GetNumberFormatInfo(string currency, bool useFallback)
@@ -123,20 +186,9 @@ namespace BTCPayServer.Services.Rates
currencyProviders.TryAdd(code, number); currencyProviders.TryAdd(code, number);
} }
readonly Dictionary<string, CurrencyData> _Currencies; Dictionary<string, CurrencyData> _Currencies = new();
private readonly IEnumerable<CurrencyDataProvider> _currencyDataProviders;
static CurrencyData[] LoadCurrency() private readonly ILogger<CurrencyNameTable> _logger;
{
var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("BTCPayServer.Rating.Currencies.json");
string content = null;
using (var reader = new StreamReader(stream, Encoding.UTF8))
{
content = reader.ReadToEnd();
}
var currencies = JsonConvert.DeserializeObject<CurrencyData[]>(content);
return currencies;
}
public IEnumerable<CurrencyData> Currencies => _Currencies.Values; public IEnumerable<CurrencyData> Currencies => _Currencies.Values;

View File

@@ -1,11 +1,22 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using BTCPayServer.Services.Rates; using BTCPayServer.Services.Rates;
namespace BTCPayServer.Rating namespace BTCPayServer.Rating
{ {
public class CurrencyPair public class CurrencyPair
{ {
private static readonly HashSet<string> _knownCurrencies;
static CurrencyPair()
{
var prov = new AssemblyCurrencyDataProvider(typeof(BTCPayServer.Rating.BidAsk).Assembly, "BTCPayServer.Rating.Currencies.json");
// It's OK this is sync function
_knownCurrencies = prov.LoadCurrencyData(default).GetAwaiter().GetResult()
.Select(c => c.Code).ToHashSet(StringComparer.OrdinalIgnoreCase);
}
public CurrencyPair(string left, string right) public CurrencyPair(string left, string right)
{ {
ArgumentNullException.ThrowIfNull(right); ArgumentNullException.ThrowIfNull(right);
@@ -49,10 +60,9 @@ namespace BTCPayServer.Rating
for (int i = 3; i < 5; i++) for (int i = 3; i < 5; i++)
{ {
var potentialCryptoName = currencyPair.Substring(0, i); var potentialCryptoName = currencyPair.Substring(0, i);
var currency = CurrencyNameTable.Instance.GetCurrencyData(potentialCryptoName, false); if (_knownCurrencies.Contains(potentialCryptoName))
if (currency != null)
{ {
value = new CurrencyPair(currency.Code, currencyPair.Substring(i)); value = new CurrencyPair(potentialCryptoName, currencyPair.Substring(i));
return true; return true;
} }
} }

View File

@@ -40,6 +40,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Memory; using Microsoft.Extensions.Configuration.Memory;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using NBitcoin; using NBitcoin;
using NBitcoin.DataEncoders; using NBitcoin.DataEncoders;
@@ -681,7 +682,6 @@ namespace BTCPayServer.Tests
[Fact] [Fact]
public void CanAcceptInvoiceWithTolerance() public void CanAcceptInvoiceWithTolerance()
{ {
var networkProvider = CreateNetworkProvider(ChainName.Regtest);
var entity = new InvoiceEntity() { Currency = "USD" }; var entity = new InvoiceEntity() { Currency = "USD" };
#pragma warning disable CS0618 #pragma warning disable CS0618
entity.Payments = new List<PaymentEntity>(); entity.Payments = new List<PaymentEntity>();
@@ -738,10 +738,29 @@ namespace BTCPayServer.Tests
Assert.True(FileTypeDetector.IsAudio(new byte[] { 0xFF, 0xF3, 0xE4, 0x64, 0x00, 0x20, 0xAD, 0xBD, 0x04, 0x00 }, "music.mp3")); Assert.True(FileTypeDetector.IsAudio(new byte[] { 0xFF, 0xF3, 0xE4, 0x64, 0x00, 0x20, 0xAD, 0xBD, 0x04, 0x00 }, "music.mp3"));
} }
CurrencyNameTable GetCurrencyNameTable()
{
ServiceCollection services = new ServiceCollection();
services.AddLogging(o => o.AddProvider(this.TestLogProvider));
BTCPayServerServices.RegisterCurrencyData(services);
// One test fail without.
services.AddCurrencyData(new CurrencyData()
{
Code = "USDt",
Name = "USDt",
Divisibility = 8,
Symbol = null,
Crypto = true
});
var table = services.BuildServiceProvider().GetRequiredService<CurrencyNameTable>();
table.ReloadCurrencyData(default).GetAwaiter().GetResult();
return table;
}
[Fact] [Fact]
public void RoundupCurrenciesCorrectly() public void RoundupCurrenciesCorrectly()
{ {
DisplayFormatter displayFormatter = new(CurrencyNameTable.Instance); DisplayFormatter displayFormatter = new(GetCurrencyNameTable());
foreach (var test in new[] foreach (var test in new[]
{ {
(0.0005m, "0.0005 USD", "USD"), (0.001m, "0.001 USD", "USD"), (0.01m, "0.01 USD", "USD"), (0.0005m, "0.0005 USD", "USD"), (0.001m, "0.001 USD", "USD"), (0.01m, "0.01 USD", "USD"),
@@ -754,8 +773,8 @@ namespace BTCPayServer.Tests
actual = actual.Replace("¥", "¥"); // Hack so JPY test pass on linux as well actual = actual.Replace("¥", "¥"); // Hack so JPY test pass on linux as well
Assert.Equal(test.Item2, actual); Assert.Equal(test.Item2, actual);
} }
Assert.Equal(0, CurrencyNameTable.Instance.GetNumberFormatInfo("ARS").CurrencyDecimalDigits); Assert.Equal(0, GetCurrencyNameTable().GetNumberFormatInfo("ARS").CurrencyDecimalDigits);
Assert.Equal(0, CurrencyNameTable.Instance.GetNumberFormatInfo("COP").CurrencyDecimalDigits); Assert.Equal(0, GetCurrencyNameTable().GetNumberFormatInfo("COP").CurrencyDecimalDigits);
} }
[Fact] [Fact]
@@ -1377,7 +1396,7 @@ bc1qfzu57kgu5jthl934f9xrdzzx8mmemx7gn07tf0grnvz504j6kzusu2v0ku
var btcPayNetworkProvider = CreateNetworkProvider(ChainName.Regtest); var btcPayNetworkProvider = CreateNetworkProvider(ChainName.Regtest);
foreach (var network in btcPayNetworkProvider.GetAll()) foreach (var network in btcPayNetworkProvider.GetAll())
{ {
var cd = CurrencyNameTable.Instance.GetCurrencyData(network.CryptoCode, false); var cd = GetCurrencyNameTable().GetCurrencyData(network.CryptoCode, false);
Assert.NotNull(cd); Assert.NotNull(cd);
Assert.Equal(network.Divisibility, cd.Divisibility); Assert.Equal(network.Divisibility, cd.Divisibility);
Assert.True(cd.Crypto); Assert.True(cd.Crypto);
@@ -1445,8 +1464,8 @@ bc1qfzu57kgu5jthl934f9xrdzzx8mmemx7gn07tf0grnvz504j6kzusu2v0ku
Assert.True(CurrencyValue.TryParse("1usd", out result)); Assert.True(CurrencyValue.TryParse("1usd", out result));
Assert.Equal("1 USD", result.ToString()); Assert.Equal("1 USD", result.ToString());
Assert.True(CurrencyValue.TryParse("1.501 usd", out result)); Assert.True(CurrencyValue.TryParse("1.501 usd", out result));
Assert.Equal("1.50 USD", result.ToString()); Assert.Equal("1.501 USD", result.ToString());
Assert.False(CurrencyValue.TryParse("1.501 WTFF", out result)); Assert.True(CurrencyValue.TryParse("1.501 WTFF", out result));
Assert.False(CurrencyValue.TryParse("1,501 usd", out result)); Assert.False(CurrencyValue.TryParse("1,501 usd", out result));
Assert.False(CurrencyValue.TryParse("1.501", out result)); Assert.False(CurrencyValue.TryParse("1.501", out result));
} }

View File

@@ -1543,7 +1543,7 @@ namespace BTCPayServer.Tests
var vm = await user.GetController<UIStoresController>().CheckoutAppearance().AssertViewModelAsync<CheckoutAppearanceViewModel>(); var vm = await user.GetController<UIStoresController>().CheckoutAppearance().AssertViewModelAsync<CheckoutAppearanceViewModel>();
Assert.Equal(2, vm.PaymentMethodCriteria.Count); Assert.Equal(2, vm.PaymentMethodCriteria.Count);
var criteria = Assert.Single(vm.PaymentMethodCriteria.Where(m => m.PaymentMethod == btcMethod.ToString())); var criteria = Assert.Single(vm.PaymentMethodCriteria.Where(m => m.PaymentMethod == btcMethod.ToString()));
Assert.Equal(PaymentTypes.CHAIN.GetPaymentMethodId("BTC").ToString(), criteria.PaymentMethod); Assert.Equal(btcMethod.ToString(), criteria.PaymentMethod);
criteria.Value = "5 USD"; criteria.Value = "5 USD";
criteria.Type = PaymentMethodCriteriaViewModel.CriteriaType.GreaterThan; criteria.Type = PaymentMethodCriteriaViewModel.CriteriaType.GreaterThan;
Assert.IsType<RedirectToActionResult>(user.GetController<UIStoresController>().CheckoutAppearance(vm) Assert.IsType<RedirectToActionResult>(user.GetController<UIStoresController>().CheckoutAppearance(vm)

View File

@@ -27,17 +27,20 @@ namespace BTCPayServer.Controllers.Greenfield
public class GreenfieldStoresController : ControllerBase public class GreenfieldStoresController : ControllerBase
{ {
private readonly StoreRepository _storeRepository; private readonly StoreRepository _storeRepository;
private readonly CurrencyNameTable _currencyNameTable;
private readonly UserManager<ApplicationUser> _userManager; private readonly UserManager<ApplicationUser> _userManager;
private readonly IFileService _fileService; private readonly IFileService _fileService;
private readonly UriResolver _uriResolver; private readonly UriResolver _uriResolver;
public GreenfieldStoresController( public GreenfieldStoresController(
StoreRepository storeRepository, StoreRepository storeRepository,
CurrencyNameTable currencyNameTable,
UserManager<ApplicationUser> userManager, UserManager<ApplicationUser> userManager,
IFileService fileService, IFileService fileService,
UriResolver uriResolver) UriResolver uriResolver)
{ {
_storeRepository = storeRepository; _storeRepository = storeRepository;
_currencyNameTable = currencyNameTable;
_userManager = userManager; _userManager = userManager;
_fileService = fileService; _fileService = fileService;
_uriResolver = uriResolver; _uriResolver = uriResolver;
@@ -335,7 +338,7 @@ namespace BTCPayServer.Controllers.Greenfield
{ {
request.AddModelError(data => data.PaymentMethodCriteria[index].CurrencyCode, "CurrencyCode is required", this); request.AddModelError(data => data.PaymentMethodCriteria[index].CurrencyCode, "CurrencyCode is required", this);
} }
else if (CurrencyNameTable.Instance.GetCurrencyData(pmc.CurrencyCode, false) is null) else if (_currencyNameTable.GetCurrencyData(pmc.CurrencyCode, false) is null)
{ {
request.AddModelError(data => data.PaymentMethodCriteria[index].CurrencyCode, "CurrencyCode is invalid", this); request.AddModelError(data => data.PaymentMethodCriteria[index].CurrencyCode, "CurrencyCode is invalid", this);
} }

View File

@@ -875,9 +875,10 @@ namespace BTCPayServer.Controllers
return extension?.Image ?? ""; return extension?.Image ?? "";
} }
var cd = this._CurrencyNameTable.GetCurrencyData(prompt.Currency, false);
// Show the "Common divisibility" rather than the payment method disibility. // Show the "Common divisibility" rather than the payment method disibility.
// For example, BTC has commonly 8 digits, but on lightning it has 11. In this case, pick 8. // For example, BTC has commonly 8 digits, but on lightning it has 11. In this case, pick 8.
if (this._CurrencyNameTable.GetCurrencyData(prompt.Currency, false)?.Divisibility is not int divisibility) if (cd?.Divisibility is not int divisibility)
divisibility = prompt.Divisibility; divisibility = prompt.Divisibility;
string ShowMoney(decimal value) => MoneyExtensions.ShowMoney(value, divisibility); string ShowMoney(decimal value) => MoneyExtensions.ShowMoney(value, divisibility);

View File

@@ -368,7 +368,12 @@ public partial class UIStoresController
var existingCriteria = blob.PaymentMethodCriteria.FirstOrDefault(c => c.PaymentMethod == paymentMethodId); var existingCriteria = blob.PaymentMethodCriteria.FirstOrDefault(c => c.PaymentMethod == paymentMethodId);
if (existingCriteria != null) if (existingCriteria != null)
blob.PaymentMethodCriteria.Remove(existingCriteria); blob.PaymentMethodCriteria.Remove(existingCriteria);
CurrencyValue.TryParse(newCriteria.Value, out var cv); if (CurrencyValue.TryParse(newCriteria.Value, out var cv))
{
var currencyData = _currencyNameTable.GetCurrencyData(cv.Currency, false);
if (currencyData is not null)
cv = cv.Round(currencyData.Divisibility);
}
blob.PaymentMethodCriteria.Add(new PaymentMethodCriteria() blob.PaymentMethodCriteria.Add(new PaymentMethodCriteria()
{ {
Above = newCriteria.Type == PaymentMethodCriteriaViewModel.CriteriaType.GreaterThan, Above = newCriteria.Type == PaymentMethodCriteriaViewModel.CriteriaType.GreaterThan,

View File

@@ -60,6 +60,7 @@ public partial class UIStoresController : Controller
WalletFileParsers onChainWalletParsers, WalletFileParsers onChainWalletParsers,
UriResolver uriResolver, UriResolver uriResolver,
SettingsRepository settingsRepository, SettingsRepository settingsRepository,
CurrencyNameTable currencyNameTable,
EventAggregator eventAggregator) EventAggregator eventAggregator)
{ {
_rateFactory = rateFactory; _rateFactory = rateFactory;
@@ -83,6 +84,7 @@ public partial class UIStoresController : Controller
_onChainWalletParsers = onChainWalletParsers; _onChainWalletParsers = onChainWalletParsers;
_uriResolver = uriResolver; _uriResolver = uriResolver;
_settingsRepository = settingsRepository; _settingsRepository = settingsRepository;
_currencyNameTable = currencyNameTable;
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
_html = html; _html = html;
_defaultRules = defaultRules; _defaultRules = defaultRules;
@@ -101,6 +103,7 @@ public partial class UIStoresController : Controller
private readonly UserManager<ApplicationUser> _userManager; private readonly UserManager<ApplicationUser> _userManager;
private readonly RateFetcher _rateFactory; private readonly RateFetcher _rateFactory;
private readonly SettingsRepository _settingsRepository; private readonly SettingsRepository _settingsRepository;
private readonly CurrencyNameTable _currencyNameTable;
private readonly ExplorerClientProvider _explorerProvider; private readonly ExplorerClientProvider _explorerProvider;
private readonly LanguageService _langService; private readonly LanguageService _langService;
private readonly PaymentMethodHandlerDictionary _handlers; private readonly PaymentMethodHandlerDictionary _handlers;

View File

@@ -21,10 +21,6 @@ namespace BTCPayServer
return false; return false;
var currency = match.Groups[match.Groups.Count - 1].Value.ToUpperInvariant(); var currency = match.Groups[match.Groups.Count - 1].Value.ToUpperInvariant();
var currencyData = CurrencyNameTable.Instance.GetCurrencyData(currency, false);
if (currencyData == null)
return false;
v = Math.Round(v, currencyData.Divisibility);
value = new CurrencyValue() value = new CurrencyValue()
{ {
Value = v, Value = v,
@@ -40,5 +36,11 @@ namespace BTCPayServer
{ {
return Value.ToString(CultureInfo.InvariantCulture) + " " + Currency; return Value.ToString(CultureInfo.InvariantCulture) + " " + Currency;
} }
public CurrencyValue Round(int divisibility) => new()
{
Value = Math.Round(Value, divisibility),
Currency = Currency
};
} }
} }

View File

@@ -73,6 +73,7 @@ using BTCPayServer.Payouts;
using ExchangeSharp; using ExchangeSharp;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Microsoft.AspNetCore.Mvc.Localization; using Microsoft.AspNetCore.Mvc.Localization;
using System.Reflection;
namespace BTCPayServer.Hosting namespace BTCPayServer.Hosting
{ {
@@ -161,6 +162,7 @@ namespace BTCPayServer.Hosting
services.AddSingleton<IUIExtension>(new UIExtension("Lightning/ViewLightningLikePaymentData", "store-invoices-payments")); services.AddSingleton<IUIExtension>(new UIExtension("Lightning/ViewLightningLikePaymentData", "store-invoices-payments"));
services.AddStartupTask<BlockExplorerLinkStartupTask>(); services.AddStartupTask<BlockExplorerLinkStartupTask>();
services.AddStartupTask<LoadCurrencyNameTableStartupTask>();
services.AddStartupTask<LoadTranslationsStartupTask>(); services.AddStartupTask<LoadTranslationsStartupTask>();
services.TryAddSingleton<InvoiceRepository>(); services.TryAddSingleton<InvoiceRepository>();
services.AddSingleton<PaymentService>(); services.AddSingleton<PaymentService>();
@@ -352,7 +354,8 @@ namespace BTCPayServer.Hosting
services.TryAddSingleton<BTCPayWalletProvider>(); services.TryAddSingleton<BTCPayWalletProvider>();
services.TryAddSingleton<WalletReceiveService>(); services.TryAddSingleton<WalletReceiveService>();
services.AddSingleton<IHostedService>(provider => provider.GetService<WalletReceiveService>()); services.AddSingleton<IHostedService>(provider => provider.GetService<WalletReceiveService>());
services.TryAddSingleton<CurrencyNameTable>(CurrencyNameTable.Instance);
RegisterCurrencyData(services);
services.AddScheduledTask<FeeProviderFactory>(TimeSpan.FromMinutes(3.0)); services.AddScheduledTask<FeeProviderFactory>(TimeSpan.FromMinutes(3.0));
services.AddSingleton<IFeeProviderFactory, FeeProviderFactory>(f => f.GetRequiredService<FeeProviderFactory>()); services.AddSingleton<IFeeProviderFactory, FeeProviderFactory>(f => f.GetRequiredService<FeeProviderFactory>());
@@ -548,6 +551,12 @@ o.GetRequiredService<IEnumerable<IPaymentLinkExtension>>().ToDictionary(o => o.P
services.AddSingleton<IWalletFileParser, WasabiWalletFileParser>(); services.AddSingleton<IWalletFileParser, WasabiWalletFileParser>();
} }
internal static void RegisterCurrencyData(IServiceCollection services)
{
services.TryAddSingleton<CurrencyNameTable>();
services.AddSingleton<CurrencyDataProvider, AssemblyCurrencyDataProvider>(c => new AssemblyCurrencyDataProvider(typeof(BTCPayServer.Rating.BidAsk).Assembly, "BTCPayServer.Rating.Currencies.json"));
}
internal static void RegisterRateSources(IServiceCollection services) internal static void RegisterRateSources(IServiceCollection services)
{ {
// We need to be careful to only add exchanges which OnGetTickers implementation make only 1 request // We need to be careful to only add exchanges which OnGetTickers implementation make only 1 request
@@ -601,6 +610,12 @@ o.GetRequiredService<IEnumerable<IPaymentLinkExtension>>().ToDictionary(o => o.P
services.AddSingleton<BTCPayNetworkBase>(network); services.AddSingleton<BTCPayNetworkBase>(network);
return services; return services;
} }
public static IServiceCollection AddCurrencyData(this IServiceCollection services, params CurrencyData[] currencyData)
{
services.AddSingleton<CurrencyDataProvider, InMemoryCurrencyDataProvider>(c => new InMemoryCurrencyDataProvider(currencyData));
return services;
}
public static IServiceCollection AddBTCPayNetwork(this IServiceCollection services, BTCPayNetwork network) public static IServiceCollection AddBTCPayNetwork(this IServiceCollection services, BTCPayNetwork network)
{ {
services.AddSingleton(new DefaultRules(network.DefaultRateRules)); services.AddSingleton(new DefaultRules(network.DefaultRateRules));

View File

@@ -0,0 +1,21 @@
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Abstractions.Contracts;
using BTCPayServer.Services.Rates;
namespace BTCPayServer.Hosting
{
public class LoadCurrencyNameTableStartupTask : IStartupTask
{
private readonly CurrencyNameTable _currencyNameTable;
public LoadCurrencyNameTableStartupTask(CurrencyNameTable currencyNameTable)
{
_currencyNameTable = currencyNameTable;
}
public async Task ExecuteAsync(CancellationToken cancellationToken = default)
{
await _currencyNameTable.ReloadCurrencyData(cancellationToken);
}
}
}

View File

@@ -2,6 +2,7 @@ using System.Threading;
using BTCPayServer.Hosting; using BTCPayServer.Hosting;
using BTCPayServer.Payments; using BTCPayServer.Payments;
using BTCPayServer.Services; using BTCPayServer.Services;
using BTCPayServer.Services.Rates;
using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using NBitcoin; using NBitcoin;
@@ -33,6 +34,14 @@ public partial class AltcoinsPlugin
}.SetDefaultElectrumMapping(ChainName); }.SetDefaultElectrumMapping(ChainName);
services.AddBTCPayNetwork(network) services.AddBTCPayNetwork(network)
.AddTransactionLinkProvider(PaymentTypes.CHAIN.GetPaymentMethodId(nbxplorerNetwork.CryptoCode), new DefaultTransactionLinkProvider(LiquidBlockExplorer)); .AddTransactionLinkProvider(PaymentTypes.CHAIN.GetPaymentMethodId(nbxplorerNetwork.CryptoCode), new DefaultTransactionLinkProvider(LiquidBlockExplorer));
services.AddCurrencyData(new CurrencyData()
{
Code = "USDt",
Name = "USDt",
Divisibility = 8,
Symbol = null,
Crypto = true
});
selectedChains.Add("LBTC"); selectedChains.Add("LBTC");
} }