Aggiunta Bootstrap 5.3.3 (CSS, JS, RTL, mappe) al progetto
Sono stati aggiunti tutti i file principali di Bootstrap 5.3.3, inclusi CSS, JavaScript (bundle, ESM, UMD, minificati), versioni RTL, utility, reboot, griglia e relative mappe delle sorgenti. Questi file abilitano un sistema di design moderno, responsive e accessibile, con supporto per layout LTR e RTL, debugging avanzato tramite source map e tutte le funzionalità di Bootstrap per lo sviluppo dell’interfaccia utente. Nessuna modifica ai file esistenti.
This commit is contained in:
101
TradingBot/Services/CoinGeckoMarketDataService.cs
Normal file
101
TradingBot/Services/CoinGeckoMarketDataService.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
using System.Text.Json;
|
||||
using TradingBot.Models;
|
||||
|
||||
namespace TradingBot.Services;
|
||||
|
||||
public class CoinGeckoMarketDataService : IMarketDataService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly Dictionary<string, string> _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<List<MarketPrice>> GetMarketPricesAsync(List<string> symbols)
|
||||
{
|
||||
var prices = new List<MarketPrice>();
|
||||
|
||||
// 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<Dictionary<string, JsonElement>>(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<MarketPrice?> GetPriceAsync(string symbol)
|
||||
{
|
||||
var prices = await GetMarketPricesAsync(new List<string> { symbol });
|
||||
return prices.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user