change readasstring to readfromjson, deserialize into object,

This commit is contained in:
DavidGudEnough 2025-01-07 16:12:44 -05:00
parent f0f4c6970a
commit 20ed8e38f7
Signed by: david.nguyen
GPG Key ID: 0B95DC36355BEB37
15 changed files with 183 additions and 61 deletions

View File

@ -23,5 +23,14 @@
"ApiUrl": "",
"ApiKey": ""
},
"CoinGecko": {
"ApiUrl": "",
"ApiKey": ""
},
"HydroQuebec": {
"ApiUrl": ""
}
}

View File

@ -16,6 +16,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CH.Authority\CH.Authority.csproj" />
<ProjectReference Include="..\CH.CryptoStats.CoinMarketCap\CH.CryptoStats.CoinMarketCap.csproj" />
<ProjectReference Include="..\CH.CryptoStats\CH.CryptoStats.Abstractions.csproj" />
<ProjectReference Include="..\CH.Dal\CH.Dal.csproj" />
</ItemGroup>

View File

@ -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);
}
}

View File

@ -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<Abstractions.CryptoStats> GetCryptoStats(string cryptoName, string currency, CancellationToken cancellationToken)
//https://docs.coingecko.com/reference/coins-id
public Task<Abstractions.CryptoStats> GetCryptoStatsAsync(string cryptoName, string currency, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<Abstractions.CryptoStats> ParseCryptoStats(HttpResponseMessage result, string currency, CancellationToken cancellationToken)
public Task<Abstractions.CryptoStats> ParseCryptoStats(JsonDocument jsonDocument, string currency, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}

View File

@ -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<Abstractions.CryptoStats> GetCryptoStats(string cryptoName, string currency, CancellationToken cancellationToken)
{
var apiKey = configuration.GetValue<string>("CoinMarketCap:ApiKey");
var apiUrl = configuration.GetValue<string>("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<Abstractions.CryptoStats> 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);
}
}

View File

@ -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<string, CoinMarketCapEntity> 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; }
}

View File

@ -9,7 +9,7 @@ public class CoinMarketCapModule : IModule
{
public IServiceCollection ConfigureServices(IServiceCollection services)
{
services.AddScoped<CoinMarketCap>();
services.AddScoped<CoinMarketCapService>();
return services;
}
}

View File

@ -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<Abstractions.CryptoStats> GetCryptoStatsAsync(string cryptoName, string currency, CancellationToken cancellationToken)
{
var apiKey = configuration.GetValue<string>("CoinMarketCap:ApiKey");
var apiUrl = configuration.GetValue<string>("CoinMarketCap:ApiUrl");
var response = await httpClient.GetAsync($"{apiUrl}slug={cryptoName}&convert={currency}&CMC_PRO_API_KEY={apiKey}",cancellationToken);
var jsonResponse = await response.Content.ReadFromJsonAsync<ApiResponse>(cancellationToken);
return ParseCryptoStats(jsonResponse.Data["1"], currency, cancellationToken).Result;
}
private Task<Abstractions.CryptoStats> 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);
}
}

View File

@ -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; }

View File

@ -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<CryptoStats> GetCryptoStats(string cryptoName, string currency, CancellationToken cancellationToken);
public Task<CryptoStats> ParseCryptoStats(HttpResponseMessage result, string currency, CancellationToken cancellationToken);
public Task<CryptoStats> GetCryptoStatsAsync(string cryptoName, string currency, CancellationToken cancellationToken);
}

View File

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -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; }
}

View File

@ -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<EnergyPeak> GetEnergyPeak(CancellationToken cancellationToken);
}

View File

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -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