From fd3ecdf3f8f69eb6253a53489d01c0fb15c59689 Mon Sep 17 00:00:00 2001 From: itailiors <78041027+itailiors@users.noreply.github.com> Date: Thu, 29 Aug 2024 19:34:04 +0300 Subject: [PATCH] change CurrencyRate to its own service named CurrencyRateService.cs --- src/Angor/Client/Pages/Wallet.razor | 4 +- src/Angor/Client/Program.cs | 9 +-- .../Client/Services/CurrencyRateService.cs | 53 +++++++++++++++++ src/Angor/Client/Services/CurrencyService.cs | 57 +++---------------- .../Client/Services/ICurrencyRateService.cs | 4 ++ 5 files changed, 72 insertions(+), 55 deletions(-) create mode 100644 src/Angor/Client/Services/CurrencyRateService.cs create mode 100644 src/Angor/Client/Services/ICurrencyRateService.cs diff --git a/src/Angor/Client/Pages/Wallet.razor b/src/Angor/Client/Pages/Wallet.razor index c8da08f4..1e7248ec 100644 --- a/src/Angor/Client/Pages/Wallet.razor +++ b/src/Angor/Client/Pages/Wallet.razor @@ -1281,6 +1281,7 @@ else { return await _currencyService.GetBtcValueInPreferredCurrency(btcBalance); } + private async Task PrecomputeFiatValues() { @@ -1290,8 +1291,9 @@ else foreach (var addressInfo in addresses) { var total = Money.Satoshis(addressInfo.Balance).ToUnit(MoneyUnit.BTC); - var fiatValue = await _currencyService.GetBtcValueInPreferredCurrency(total); + var fiatValue = await _currencyService.GetBtcValueInPreferredCurrency(total); // Calls the method from ICurrencyService fiatValues[addressInfo.Address] = fiatValue; } } + } diff --git a/src/Angor/Client/Program.cs b/src/Angor/Client/Program.cs index 90da726f..7c9ec618 100644 --- a/src/Angor/Client/Program.cs +++ b/src/Angor/Client/Program.cs @@ -24,9 +24,9 @@ builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddTransient(); -builder.Services.AddTransient (); +builder.Services.AddTransient(); builder.Services.AddTransient(); -builder.Services.AddTransient (); +builder.Services.AddTransient(); builder.Services.AddScoped(); builder.Services.AddTransient(); builder.Services.AddScoped(); @@ -34,6 +34,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -51,10 +52,10 @@ builder.Services.AddTransient(); builder.Services.AddTransient(); -builder.Services.AddSingleton(); +builder.Services.AddSingleton(); builder.Services.AddScoped(); builder.Services.AddSingleton(); builder.Services.AddScoped(); -await builder.Build().RunAsync(); +await builder.Build().RunAsync(); \ No newline at end of file diff --git a/src/Angor/Client/Services/CurrencyRateService.cs b/src/Angor/Client/Services/CurrencyRateService.cs new file mode 100644 index 00000000..18cf99cf --- /dev/null +++ b/src/Angor/Client/Services/CurrencyRateService.cs @@ -0,0 +1,53 @@ +using System.Collections.Concurrent; +using System.Text.Json; + +public class CurrencyRateService : ICurrencyRateService +{ + private readonly TimeSpan _cacheDuration = TimeSpan.FromMinutes(10); // Cache duration of 10 minutes + private readonly HttpClient _httpClient; + private readonly ILogger _logger; + private readonly ConcurrentDictionary _rateCache = new(); + + public CurrencyRateService(HttpClient httpClient, ILogger logger) + { + _httpClient = httpClient; + _logger = logger; + } + + public async Task GetBtcToCurrencyRate(string currencyCode) + { + // Normalize currency code + var preferredCurrency = currencyCode.ToUpper(); + + // Check if we have a recent rate in the cache + if (_rateCache.ContainsKey(preferredCurrency) && + DateTime.UtcNow - _rateCache[preferredCurrency].timestamp < _cacheDuration) + { + _logger.LogInformation($"Using cached rate for {preferredCurrency}"); + return _rateCache[preferredCurrency].rate; + } + + // Fetch new rate if not cached or cache is stale + var apiUrl = "https://mempool.space/api/v1/prices"; + var response = await _httpClient.GetAsync(apiUrl); + if (response.IsSuccessStatusCode) + { + var jsonString = await response.Content.ReadAsStringAsync(); + _logger.LogInformation($"API Response: {jsonString}"); + + var data = JsonSerializer.Deserialize>(jsonString); + + if (data != null && data.ContainsKey(preferredCurrency)) + { + var rate = data[preferredCurrency]; + // Update the cache + _rateCache[preferredCurrency] = (rate, DateTime.UtcNow); + return rate; + } + + throw new Exception($"Currency '{preferredCurrency}' not found in the API response."); + } + + throw new Exception("Failed to fetch BTC rate from the API."); + } +} \ No newline at end of file diff --git a/src/Angor/Client/Services/CurrencyService.cs b/src/Angor/Client/Services/CurrencyService.cs index 77f017a8..dc7ca02f 100644 --- a/src/Angor/Client/Services/CurrencyService.cs +++ b/src/Angor/Client/Services/CurrencyService.cs @@ -1,24 +1,16 @@ -using System; using System.Globalization; -using System.Net.Http; -using System.Threading.Tasks; using Angor.Client.Storage; -using System.Text.Json; -using System.Collections.Generic; public class CurrencyService : ICurrencyService { - private readonly HttpClient _httpClient; - private readonly IClientStorage _storage; + private readonly ICurrencyRateService _currencyRateService; private readonly ILogger _logger; + private readonly IClientStorage _storage; - // Cache fields - does it work or need of redis cache/storage? - private Dictionary _rateCache = new(); - private readonly TimeSpan _cacheDuration = TimeSpan.FromMinutes(10); // Cache duration of 10 minutes - - public CurrencyService(HttpClient httpClient, IClientStorage storage, ILogger logger) + public CurrencyService(ICurrencyRateService currencyRateService, IClientStorage storage, + ILogger logger) { - _httpClient = httpClient; + _currencyRateService = currencyRateService; _storage = storage; _logger = logger; } @@ -27,8 +19,8 @@ public async Task GetBtcValueInPreferredCurrency(decimal btcBalance) { try { - var rate = await GetBtcToPreferredCurrencyRate(); var currencyCode = _storage.GetCurrencyDisplaySetting(); + var rate = await _currencyRateService.GetBtcToCurrencyRate(currencyCode); var currencySymbol = GetCurrencySymbol(currencyCode); var cultureInfo = new CultureInfo(GetCultureCode(currencyCode)); var value = btcBalance * rate; @@ -41,41 +33,6 @@ public async Task GetBtcValueInPreferredCurrency(decimal btcBalance) } } - private async Task GetBtcToPreferredCurrencyRate() - { - string preferredCurrency = _storage.GetCurrencyDisplaySetting().ToUpper(); - - // Check if we have a recent rate in the cache - if (_rateCache.ContainsKey(preferredCurrency) && - DateTime.UtcNow - _rateCache[preferredCurrency].timestamp < _cacheDuration) - { - _logger.LogInformation($"Using cached rate for {preferredCurrency}"); - return _rateCache[preferredCurrency].rate; - } - - // Fetch new rate if not cached or cache is stale - string apiUrl = "https://mempool.space/api/v1/prices"; - var response = await _httpClient.GetAsync(apiUrl); - if (response.IsSuccessStatusCode) - { - var jsonString = await response.Content.ReadAsStringAsync(); - _logger.LogInformation($"API Response: {jsonString}"); - - var data = JsonSerializer.Deserialize>(jsonString); - - if (data != null && data.ContainsKey(preferredCurrency)) - { - var rate = data[preferredCurrency]; - // Update the cache - _rateCache[preferredCurrency] = (rate, DateTime.UtcNow); - return rate; - } - throw new Exception($"Currency '{preferredCurrency}' not found in the API response."); - } - - throw new Exception("Failed to fetch BTC rate from the API."); - } - public string GetCurrencySymbol(string currencyCode) { return currencyCode.ToUpper() switch @@ -105,4 +62,4 @@ private static string GetCultureCode(string currencyCode) _ => "en-US" }; } -} +} \ No newline at end of file diff --git a/src/Angor/Client/Services/ICurrencyRateService.cs b/src/Angor/Client/Services/ICurrencyRateService.cs new file mode 100644 index 00000000..b3db8da1 --- /dev/null +++ b/src/Angor/Client/Services/ICurrencyRateService.cs @@ -0,0 +1,4 @@ +public interface ICurrencyRateService +{ + Task GetBtcToCurrencyRate(string currencyCode); +} \ No newline at end of file