using System.Text.Json; using TradingBot.Models; namespace TradingBot.Services; public class CoinGeckoMarketDataService : IMarketDataService { private readonly HttpClient _httpClient; private readonly Dictionary _symbolToId = new() { { "BTC", "bitcoin" }, { "ETH", "ethereum" }, { "BNB", "binancecoin" }, { "XRP", "ripple" }, { "ADA", "cardano" }, { "SOL", "solana" }, { "DOT", "polkadot" } }; public CoinGeckoMarketDataService(HttpClient httpClient) { _httpClient = httpClient; _httpClient.BaseAddress = new Uri("https://api.coingecko.com/api/v3/"); _httpClient.DefaultRequestHeaders.Add("User-Agent", "NovaTrader-Bot"); } public async Task> GetMarketPricesAsync(List symbols) { var prices = new List(); // Convert symbols to CoinGecko IDs var ids = string.Join(",", symbols.Select(s => _symbolToId.GetValueOrDefault(s.ToUpper(), s.ToLower()))); try { // CoinGecko API: /simple/price endpoint var response = await _httpClient.GetAsync( $"simple/price?ids={ids}&vs_currencies=usd&include_24hr_vol=true&include_24hr_change=true&include_last_updated_at=true"); if (response.IsSuccessStatusCode) { var json = await response.Content.ReadAsStringAsync(); var data = JsonSerializer.Deserialize>(json); if (data != null) { foreach (var symbol in symbols) { var coinId = _symbolToId.GetValueOrDefault(symbol.ToUpper(), symbol.ToLower()); if (data.TryGetValue(coinId, out var coinData)) { var price = new MarketPrice { Symbol = symbol.ToUpper(), Price = coinData.GetProperty("usd").GetDecimal(), Timestamp = DateTime.UtcNow }; // Safely get optional properties if (coinData.TryGetProperty("usd_24h_change", out var changeElement)) { price.Change24h = changeElement.GetDecimal(); } if (coinData.TryGetProperty("usd_24h_vol", out var volumeElement)) { price.Volume24h = volumeElement.GetDecimal(); } prices.Add(price); } } } } else { Console.WriteLine($"CoinGecko API error: {response.StatusCode} - {await response.Content.ReadAsStringAsync()}"); } } catch (HttpRequestException ex) { Console.WriteLine($"Network error fetching market data: {ex.Message}"); } catch (JsonException ex) { Console.WriteLine($"JSON parsing error: {ex.Message}"); } catch (Exception ex) { Console.WriteLine($"Unexpected error fetching market data: {ex.Message}"); } return prices; } public async Task GetPriceAsync(string symbol) { var prices = await GetMarketPricesAsync(new List { symbol }); return prices.FirstOrDefault(); } }