From 20ed8e38f7c07b5df18af72a45232613a7dc956f Mon Sep 17 00:00:00 2001 From: DavidGudEnough Date: Tue, 7 Jan 2025 16:12:44 -0500 Subject: [PATCH] change readasstring to readfromjson, deserialize into object, --- CH.Api/appsettings.json | 9 +++ CH.CQRS/CH.CQRS.csproj | 1 + CH.CQRS/Service/CryptoStats/CryptoService.cs | 12 ++-- CH.CryptoStats.CoinGecko/CoinGecko.cs | 6 +- CH.CryptoStats.CoinMarketCap/CoinMarketCap.cs | 42 -------------- .../CoinMarketCapEntity.cs | 55 +++++++++++++++++++ .../CoinMarketCapModule.cs | 2 +- .../CoinMarketCapService.cs | 45 +++++++++++++++ CH.CryptoStats/CryptoStats.cs | 6 +- CH.CryptoStats/ICryptoStats.cs | 4 +- .../CH.Energy.Abstractions.csproj | 9 +++ CH.Energy.Abstractions/EnergyPeak.cs | 14 +++++ CH.Energy.Abstractions/IEnergyStats.cs | 12 ++++ .../CH.Energy.HydroQuebec.csproj | 9 +++ ConstellationHeating.sln | 18 +++++- 15 files changed, 183 insertions(+), 61 deletions(-) delete mode 100644 CH.CryptoStats.CoinMarketCap/CoinMarketCap.cs create mode 100644 CH.CryptoStats.CoinMarketCap/CoinMarketCapEntity.cs create mode 100644 CH.CryptoStats.CoinMarketCap/CoinMarketCapService.cs create mode 100644 CH.Energy.Abstractions/CH.Energy.Abstractions.csproj create mode 100644 CH.Energy.Abstractions/EnergyPeak.cs create mode 100644 CH.Energy.Abstractions/IEnergyStats.cs create mode 100644 CH.Energy.HydroQuebec/CH.Energy.HydroQuebec.csproj diff --git a/CH.Api/appsettings.json b/CH.Api/appsettings.json index f9c8192..ba3c323 100644 --- a/CH.Api/appsettings.json +++ b/CH.Api/appsettings.json @@ -23,5 +23,14 @@ "ApiUrl": "", "ApiKey": "" + }, + "CoinGecko": { + "ApiUrl": "", + "ApiKey": "" + + }, + "HydroQuebec": { + "ApiUrl": "" + } } diff --git a/CH.CQRS/CH.CQRS.csproj b/CH.CQRS/CH.CQRS.csproj index e293ada..11530f8 100644 --- a/CH.CQRS/CH.CQRS.csproj +++ b/CH.CQRS/CH.CQRS.csproj @@ -16,6 +16,7 @@ + diff --git a/CH.CQRS/Service/CryptoStats/CryptoService.cs b/CH.CQRS/Service/CryptoStats/CryptoService.cs index 31c6b44..880a486 100644 --- a/CH.CQRS/Service/CryptoStats/CryptoService.cs +++ b/CH.CQRS/Service/CryptoStats/CryptoService.cs @@ -1,16 +1,12 @@ -using CH.CryptoStats.Abstractions; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; + +using CH.CryptoStats.CoinMarketCap; namespace CH.CQRS.Service.CryptoStats; -public class CryptoService(CoinMarketCap coinMarketCap) +public class CryptoService(CoinMarketCapService coinMarketCap) { public async Task GetCryptoStatsAsync(CancellationToken cancellationToken) { - var crypto = await coinMarketCap.GetCryptoStats("bitcoin", "CAD", cancellationToken); + var crypto = await coinMarketCap.GetCryptoStatsAsync("bitcoin", "cad", cancellationToken); } } diff --git a/CH.CryptoStats.CoinGecko/CoinGecko.cs b/CH.CryptoStats.CoinGecko/CoinGecko.cs index 9554caf..11dfa4d 100644 --- a/CH.CryptoStats.CoinGecko/CoinGecko.cs +++ b/CH.CryptoStats.CoinGecko/CoinGecko.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Text.Json; using System.Threading.Tasks; using CH.CryptoStats.Abstractions; @@ -9,12 +10,13 @@ namespace CH.CryptoStats.CoinGecko; public class CoinGecko : ICryptoStats { - public Task GetCryptoStats(string cryptoName, string currency, CancellationToken cancellationToken) + //https://docs.coingecko.com/reference/coins-id + public Task GetCryptoStatsAsync(string cryptoName, string currency, CancellationToken cancellationToken) { throw new NotImplementedException(); } - public Task ParseCryptoStats(HttpResponseMessage result, string currency, CancellationToken cancellationToken) + public Task ParseCryptoStats(JsonDocument jsonDocument, string currency, CancellationToken cancellationToken) { throw new NotImplementedException(); } diff --git a/CH.CryptoStats.CoinMarketCap/CoinMarketCap.cs b/CH.CryptoStats.CoinMarketCap/CoinMarketCap.cs deleted file mode 100644 index 4a976ff..0000000 --- a/CH.CryptoStats.CoinMarketCap/CoinMarketCap.cs +++ /dev/null @@ -1,42 +0,0 @@ -using CH.CryptoStats.Abstractions; -using Microsoft.Extensions.Configuration; -using System.Text.Json; -namespace CH.CryptoStats.CoinMarketCap; - -public class CoinMarketCap(HttpClient httpClient, IConfiguration configuration) : ICryptoStats -{ - public Task GetCryptoStats(string cryptoName, string currency, CancellationToken cancellationToken) - { - var apiKey = configuration.GetValue("CoinMarketCap:ApiKey"); - var apiUrl = configuration.GetValue("CoinMarketCap:ApiUrl"); - var result = httpClient.GetAsync($"{apiUrl}slug={cryptoName}&convert={currency}&CMC_PRO_API_KEY={apiKey}",cancellationToken).Result; - return ParseCryptoStats(result, currency, cancellationToken); - - } - - public Task ParseCryptoStats(HttpResponseMessage result, string currency, CancellationToken cancellationToken) - { - var jsonResponse = result.Content.ReadAsStringAsync(cancellationToken); - var jsonDocument = JsonDocument.Parse(jsonResponse.Result); - var data = jsonDocument.RootElement.GetProperty("data"); - var cryptoElement = data.GetProperty("1"); - var quoteElement = cryptoElement.GetProperty("quote").GetProperty("CAD"); - var cryptoStats = new Abstractions.CryptoStats - { - Name = cryptoElement.GetProperty("name").GetString(), - Symbol = cryptoElement.GetProperty("symbol").GetString(), - MaxSupply = cryptoElement.GetProperty("max_supply").GetInt32(), - CirculatingSupply = cryptoElement.GetProperty("circulating_supply").GetInt32(), - TotalSupply = cryptoElement.GetProperty("total_supply").GetInt32(), - Currency = currency, - UpdatedAt = DateTime.Parse(quoteElement .GetProperty("last_updated").GetString()), - Price = quoteElement .GetProperty("price").GetDecimal(), - Volume24H = quoteElement .GetProperty("volume_24h").GetDecimal(), - VolumeChange24H = quoteElement .GetProperty("volume_change_24h").GetDecimal(), - MarketCap = quoteElement .GetProperty("market_cap").GetDecimal(), - MarketCapDominance = quoteElement .GetProperty("market_cap_dominance").GetDecimal(), - FullyDilutedMarketCap = quoteElement .GetProperty("fully_diluted_market_cap").GetDecimal() - }; - return Task.FromResult(cryptoStats); - } -} diff --git a/CH.CryptoStats.CoinMarketCap/CoinMarketCapEntity.cs b/CH.CryptoStats.CoinMarketCap/CoinMarketCapEntity.cs new file mode 100644 index 0000000..2752375 --- /dev/null +++ b/CH.CryptoStats.CoinMarketCap/CoinMarketCapEntity.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +namespace CH.CryptoStats.CoinMarketCap; +public class CoinMarketCapEntity +{ + [JsonPropertyName("id")] + public int Id { get; set; } + [JsonPropertyName("name")] + public string Name { get; set; } + [JsonPropertyName("symbol")] + public string Symbol { get; set; } + [JsonPropertyName("max_supply")] + public int MaxSupply { get; set; } + [JsonPropertyName("circulating_supply")] + public int CirculatingSupply { get; set; } + [JsonPropertyName("total_supply")] + public int TotalSupply { get; set; } + [JsonPropertyName("last_updated")] + public required string LastUpdated { get; set; } + [JsonPropertyName("quote")] + public required Quote Quote { get; set; } +} +public class ApiResponse +{ + public required Dictionary Data { get; set; } +} + +public class Quote +{ + [JsonPropertyName("CAD")] + public CurrencyValue? CAD { get; set; } + [JsonPropertyName("USD")] + public CurrencyValue? USD { get; set; } +} + +public class CurrencyValue +{ + [JsonPropertyName("price")] + public decimal Price { get; set; } + [JsonPropertyName("volume_24h")] + public decimal Volume24h { get; set; } + [JsonPropertyName("volume_change_24h")] + public decimal VolumeChange24h { get; set; } + [JsonPropertyName("market_cap")] + public decimal MarketCap { get; set; } + [JsonPropertyName("market_cap_dominance")] + public decimal MarketCapDominance { get; set; } + [JsonPropertyName("fully_diluted_market_cap")] + public decimal FullyDilutedMarketCap { get; set; } +} \ No newline at end of file diff --git a/CH.CryptoStats.CoinMarketCap/CoinMarketCapModule.cs b/CH.CryptoStats.CoinMarketCap/CoinMarketCapModule.cs index 6c03111..5e6204b 100644 --- a/CH.CryptoStats.CoinMarketCap/CoinMarketCapModule.cs +++ b/CH.CryptoStats.CoinMarketCap/CoinMarketCapModule.cs @@ -9,7 +9,7 @@ public class CoinMarketCapModule : IModule { public IServiceCollection ConfigureServices(IServiceCollection services) { - services.AddScoped(); + services.AddScoped(); return services; } } diff --git a/CH.CryptoStats.CoinMarketCap/CoinMarketCapService.cs b/CH.CryptoStats.CoinMarketCap/CoinMarketCapService.cs new file mode 100644 index 0000000..ab76ec6 --- /dev/null +++ b/CH.CryptoStats.CoinMarketCap/CoinMarketCapService.cs @@ -0,0 +1,45 @@ +using CH.CryptoStats.Abstractions; +using Microsoft.Extensions.Configuration; +using System.Net.Http.Json; +using System.Text.Json; +namespace CH.CryptoStats.CoinMarketCap; + +public class CoinMarketCapService(HttpClient httpClient, IConfiguration configuration) : ICryptoStats +{ + public async Task GetCryptoStatsAsync(string cryptoName, string currency, CancellationToken cancellationToken) + { + var apiKey = configuration.GetValue("CoinMarketCap:ApiKey"); + var apiUrl = configuration.GetValue("CoinMarketCap:ApiUrl"); + var response = await httpClient.GetAsync($"{apiUrl}slug={cryptoName}&convert={currency}&CMC_PRO_API_KEY={apiKey}",cancellationToken); + var jsonResponse = await response.Content.ReadFromJsonAsync(cancellationToken); + return ParseCryptoStats(jsonResponse.Data["1"], currency, cancellationToken).Result; + + } + + private Task ParseCryptoStats(CoinMarketCapEntity coinMarketCapEntity, string currency, CancellationToken cancellationToken) + { + var cryptoStats = new Abstractions.CryptoStats + { + Name = coinMarketCapEntity.Name, + Symbol = coinMarketCapEntity.Symbol, + MaxSupply = coinMarketCapEntity.MaxSupply, + CirculatingSupply = coinMarketCapEntity.CirculatingSupply, + TotalSupply = coinMarketCapEntity.TotalSupply, + Currency = currency.ToUpper(), + UpdatedAt = DateTime.Parse(coinMarketCapEntity.LastUpdated), + Price = coinMarketCapEntity.Quote.CAD == null ? + coinMarketCapEntity.Quote.USD.Price : coinMarketCapEntity.Quote.CAD.Price, + Volume24H = coinMarketCapEntity.Quote.CAD == null ? + coinMarketCapEntity.Quote.USD.Volume24h : coinMarketCapEntity.Quote.CAD.Volume24h, + VolumeChange24H = coinMarketCapEntity.Quote.CAD == null ? + coinMarketCapEntity.Quote.USD.VolumeChange24h : coinMarketCapEntity.Quote.CAD.VolumeChange24h, + MarketCap = coinMarketCapEntity.Quote.CAD == null ? + coinMarketCapEntity.Quote.USD.MarketCap : coinMarketCapEntity.Quote.CAD.MarketCap, + MarketCapDominance = coinMarketCapEntity.Quote.CAD == null ? + coinMarketCapEntity.Quote.USD.MarketCapDominance : coinMarketCapEntity.Quote.CAD.MarketCapDominance, + FullyDilutedMarketCap = coinMarketCapEntity.Quote.CAD == null ? + coinMarketCapEntity.Quote.USD.FullyDilutedMarketCap : coinMarketCapEntity.Quote.CAD.FullyDilutedMarketCap + }; + return Task.FromResult(cryptoStats); + } +} diff --git a/CH.CryptoStats/CryptoStats.cs b/CH.CryptoStats/CryptoStats.cs index c815e19..5c985c9 100644 --- a/CH.CryptoStats/CryptoStats.cs +++ b/CH.CryptoStats/CryptoStats.cs @@ -10,9 +10,9 @@ public class CryptoStats { public required string Name { get; set; } public required string Symbol { get; set; } - public int MaxSupply { get; set; } - public int CirculatingSupply { get; set; } - public int TotalSupply { get; set; } + public long MaxSupply { get; set; } + public long CirculatingSupply { get; set; } + public long TotalSupply { get; set; } public required string Currency { get; set; } public DateTime UpdatedAt { get; set; } public decimal Price { get; set; } diff --git a/CH.CryptoStats/ICryptoStats.cs b/CH.CryptoStats/ICryptoStats.cs index 6edce7e..79e037e 100644 --- a/CH.CryptoStats/ICryptoStats.cs +++ b/CH.CryptoStats/ICryptoStats.cs @@ -2,12 +2,12 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Text.Json; using System.Threading.Tasks; namespace CH.CryptoStats.Abstractions; public interface ICryptoStats { - public Task GetCryptoStats(string cryptoName, string currency, CancellationToken cancellationToken); - public Task ParseCryptoStats(HttpResponseMessage result, string currency, CancellationToken cancellationToken); + public Task GetCryptoStatsAsync(string cryptoName, string currency, CancellationToken cancellationToken); } diff --git a/CH.Energy.Abstractions/CH.Energy.Abstractions.csproj b/CH.Energy.Abstractions/CH.Energy.Abstractions.csproj new file mode 100644 index 0000000..fa71b7a --- /dev/null +++ b/CH.Energy.Abstractions/CH.Energy.Abstractions.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/CH.Energy.Abstractions/EnergyPeak.cs b/CH.Energy.Abstractions/EnergyPeak.cs new file mode 100644 index 0000000..5d761c7 --- /dev/null +++ b/CH.Energy.Abstractions/EnergyPeak.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CH.Energy.Abstractions; + +public class EnergyPeak +{ + public string? Sector { get; set; } + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } +} diff --git a/CH.Energy.Abstractions/IEnergyStats.cs b/CH.Energy.Abstractions/IEnergyStats.cs new file mode 100644 index 0000000..92b4936 --- /dev/null +++ b/CH.Energy.Abstractions/IEnergyStats.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CH.Energy.Abstractions; + +public interface IEnergyStats +{ + public Task GetEnergyPeak(CancellationToken cancellationToken); +} diff --git a/CH.Energy.HydroQuebec/CH.Energy.HydroQuebec.csproj b/CH.Energy.HydroQuebec/CH.Energy.HydroQuebec.csproj new file mode 100644 index 0000000..fa71b7a --- /dev/null +++ b/CH.Energy.HydroQuebec/CH.Energy.HydroQuebec.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/ConstellationHeating.sln b/ConstellationHeating.sln index 6f4ab72..0ef0fe0 100644 --- a/ConstellationHeating.sln +++ b/ConstellationHeating.sln @@ -11,11 +11,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CH.CQRS", "CH.CQRS\CH.CQRS. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CH.Authority", "CH.Authority\CH.Authority.csproj", "{2B26A5F6-B78D-418F-A28D-80E7E9CD5428}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CH.CryptoStats.Abstractions", "CH.CryptoStats\CH.CryptoStats.Abstractions.csproj", "{5AD75A8F-D4C5-4748-8624-FB65EA417E62}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CH.CryptoStats.Abstractions", "CH.CryptoStats\CH.CryptoStats.Abstractions.csproj", "{5AD75A8F-D4C5-4748-8624-FB65EA417E62}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CH.CryptoStats.CoinMarketCap", "CH.CryptoStats.CoinMarketCap\CH.CryptoStats.CoinMarketCap.csproj", "{E12AC021-8B7E-4451-BB41-59291230E224}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CH.CryptoStats.CoinMarketCap", "CH.CryptoStats.CoinMarketCap\CH.CryptoStats.CoinMarketCap.csproj", "{E12AC021-8B7E-4451-BB41-59291230E224}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CH.CryptoStats.CoinGecko", "CH.CryptoStats.CoinGecko\CH.CryptoStats.CoinGecko.csproj", "{AAF92179-CDA7-4711-89C0-E14445B5FFBE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CH.CryptoStats.CoinGecko", "CH.CryptoStats.CoinGecko\CH.CryptoStats.CoinGecko.csproj", "{AAF92179-CDA7-4711-89C0-E14445B5FFBE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CH.Energy.Abstractions", "CH.Energy.Abstractions\CH.Energy.Abstractions.csproj", "{ED45DC6D-75E8-449E-BB24-867C37439ADA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CH.Energy.HydroQuebec", "CH.Energy.HydroQuebec\CH.Energy.HydroQuebec.csproj", "{91BB50CF-87B6-40A0-BB70-B42B7208167A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -51,6 +55,14 @@ Global {AAF92179-CDA7-4711-89C0-E14445B5FFBE}.Debug|Any CPU.Build.0 = Debug|Any CPU {AAF92179-CDA7-4711-89C0-E14445B5FFBE}.Release|Any CPU.ActiveCfg = Release|Any CPU {AAF92179-CDA7-4711-89C0-E14445B5FFBE}.Release|Any CPU.Build.0 = Release|Any CPU + {ED45DC6D-75E8-449E-BB24-867C37439ADA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ED45DC6D-75E8-449E-BB24-867C37439ADA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED45DC6D-75E8-449E-BB24-867C37439ADA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ED45DC6D-75E8-449E-BB24-867C37439ADA}.Release|Any CPU.Build.0 = Release|Any CPU + {91BB50CF-87B6-40A0-BB70-B42B7208167A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {91BB50CF-87B6-40A0-BB70-B42B7208167A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {91BB50CF-87B6-40A0-BB70-B42B7208167A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {91BB50CF-87B6-40A0-BB70-B42B7208167A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE