<commit_before>using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Rating;
using ExchangeSharp;

namespace BTCPayServer.Services.Rates
{
    public class ExchangeSharpRateProvider<T> : IRateProvider where T : ExchangeAPI
    {
        readonly HttpClient _httpClient;
        public ExchangeSharpRateProvider(HttpClient httpClient)
        {
            ArgumentNullException.ThrowIfNull(httpClient);
            _httpClient = httpClient;
        }

        public async Task<PairRate[]> GetRatesAsync(CancellationToken cancellationToken)
        {
            await new SynchronizationContextRemover();

            var exchangeAPI = (T) await ExchangeAPI.GetExchangeAPIAsync<T>();
            exchangeAPI.RequestMaker = new HttpClientRequestMaker(exchangeAPI, _httpClient, cancellationToken);
            var rates = await exchangeAPI.GetTickersAsync();

            var exchangeRateTasks = rates
                .Where(t => t.Value.Ask != 0m && t.Value.Bid != 0m)
                .Select(t => CreateExchangeRate(exchangeAPI, t));

            var exchangeRates = await Task.WhenAll(exchangeRateTasks);

            return exchangeRates
                .Where(t => t != null)
                .ToArray();
        }

        // ExchangeSymbolToGlobalSymbol throws exception which would kill perf
        readonly ConcurrentDictionary<string, string> notFoundSymbols = new ConcurrentDictionary<string, string>();
        private async Task<PairRate> CreateExchangeRate(T exchangeAPI, KeyValuePair<string, ExchangeTicker> ticker)
        {
            if (notFoundSymbols.TryGetValue(ticker.Key, out _))
                return null;
            if (ticker.Key.Contains("XMR"))
            {
            }
            try
            {
                CurrencyPair pair;
                if (ticker.Value.Volume.BaseCurrency is not null && ticker.Value.Volume.QuoteCurrency is not null)
                {
                    pair = new CurrencyPair(ticker.Value.Volume.BaseCurrency, ticker.Value.Volume.QuoteCurrency);
                }
                else
                {
                    var tickerName = await exchangeAPI.ExchangeMarketSymbolToGlobalMarketSymbolAsync(ticker.Key);
                    if (!CurrencyPair.TryParse(tickerName, out pair))
                    {
                        notFoundSymbols.TryAdd(ticker.Key, ticker.Key);
                        return null;
                    }
                }
                return new PairRate(pair, new BidAsk(ticker.Value.Bid, ticker.Value.Ask));
            }
            catch (ArgumentException)
            {
                notFoundSymbols.TryAdd(ticker.Key, ticker.Key);
                return null;
            }
        }
    }
}
<commit_msg>Remove some debug code<commit_after>using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Rating;
using ExchangeSharp;

namespace BTCPayServer.Services.Rates
{
    public class ExchangeSharpRateProvider<T> : IRateProvider where T : ExchangeAPI
    {
        readonly HttpClient _httpClient;
        public ExchangeSharpRateProvider(HttpClient httpClient)
        {
            ArgumentNullException.ThrowIfNull(httpClient);
            _httpClient = httpClient;
        }

        public async Task<PairRate[]> GetRatesAsync(CancellationToken cancellationToken)
        {
            await new SynchronizationContextRemover();

            var exchangeAPI = (T) await ExchangeAPI.GetExchangeAPIAsync<T>();
            exchangeAPI.RequestMaker = new HttpClientRequestMaker(exchangeAPI, _httpClient, cancellationToken);
            var rates = await exchangeAPI.GetTickersAsync();

            var exchangeRateTasks = rates
                .Where(t => t.Value.Ask != 0m && t.Value.Bid != 0m)
                .Select(t => CreateExchangeRate(exchangeAPI, t));

            var exchangeRates = await Task.WhenAll(exchangeRateTasks);

            return exchangeRates
                .Where(t => t != null)
                .ToArray();
        }

        // ExchangeSymbolToGlobalSymbol throws exception which would kill perf
        readonly ConcurrentDictionary<string, string> notFoundSymbols = new ConcurrentDictionary<string, string>();
        private async Task<PairRate> CreateExchangeRate(T exchangeAPI, KeyValuePair<string, ExchangeTicker> ticker)
        {
            if (notFoundSymbols.TryGetValue(ticker.Key, out _))
                return null;
            try
            {
                CurrencyPair pair;
                if (ticker.Value.Volume.BaseCurrency is not null && ticker.Value.Volume.QuoteCurrency is not null)
                {
                    pair = new CurrencyPair(ticker.Value.Volume.BaseCurrency, ticker.Value.Volume.QuoteCurrency);
                }
                else
                {
                    var tickerName = await exchangeAPI.ExchangeMarketSymbolToGlobalMarketSymbolAsync(ticker.Key);
                    if (!CurrencyPair.TryParse(tickerName, out pair))
                    {
                        notFoundSymbols.TryAdd(ticker.Key, ticker.Key);
                        return null;
                    }
                }
                return new PairRate(pair, new BidAsk(ticker.Value.Bid, ticker.Value.Ask));
            }
            catch (ArgumentException)
            {
                notFoundSymbols.TryAdd(ticker.Key, ticker.Key);
                return null;
            }
        }
    }
}

{'fraction_non_alphanumeric': 0.07964757709251101, 'fraction_numerical': 0.0007048458149779736, 'mean_word_length': 1.9531737773152966, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6717669', 'n_tokens_mistral': 1484, 'n_tokens_neox': 1405, 'n_words': 299}