Compare commits
4 Commits
main
...
feature/co
Author | SHA1 | Date | |
---|---|---|---|
caf6f3275c | |||
20ed8e38f7 | |||
f0f4c6970a | |||
46911ceaa1 |
@ -2,6 +2,9 @@
|
|||||||
using CH.CQRS;
|
using CH.CQRS;
|
||||||
using PoweredSoft.Module.Abstractions;
|
using PoweredSoft.Module.Abstractions;
|
||||||
using CH.Dal;
|
using CH.Dal;
|
||||||
|
using CH.CryptoStats.CoinMarketCap;
|
||||||
|
using CH.CryptoStats.CoinGecko;
|
||||||
|
|
||||||
|
|
||||||
namespace CH.Api;
|
namespace CH.Api;
|
||||||
|
|
||||||
@ -13,7 +16,8 @@ public class AppModule : IModule
|
|||||||
services.AddModule<SharedModule>();
|
services.AddModule<SharedModule>();
|
||||||
services.AddModule<CommandModule>();
|
services.AddModule<CommandModule>();
|
||||||
services.AddModule<QueryModule>();
|
services.AddModule<QueryModule>();
|
||||||
|
services.AddModule<CoinMarketCapModule>();
|
||||||
|
services.AddModule<CoinGeckoModule>();
|
||||||
services.AddModule<AuthorityModule>();
|
services.AddModule<AuthorityModule>();
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
|
@ -34,6 +34,8 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\CH.Authority\CH.Authority.csproj" />
|
<ProjectReference Include="..\CH.Authority\CH.Authority.csproj" />
|
||||||
<ProjectReference Include="..\CH.CQRS\CH.CQRS.csproj" />
|
<ProjectReference Include="..\CH.CQRS\CH.CQRS.csproj" />
|
||||||
|
<ProjectReference Include="..\CH.CryptoStats.CoinGecko\CH.CryptoStats.CoinGecko.csproj" />
|
||||||
|
<ProjectReference Include="..\CH.CryptoStats.CoinMarketCap\CH.CryptoStats.CoinMarketCap.csproj" />
|
||||||
<ProjectReference Include="..\CH.Dal\CH.Dal.csproj" />
|
<ProjectReference Include="..\CH.Dal\CH.Dal.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using CH.Api;
|
using CH.Api;
|
||||||
|
using CH.CryptoStats.Abstractions;
|
||||||
using CH.Dal;
|
using CH.Dal;
|
||||||
using FluentValidation.AspNetCore;
|
using FluentValidation.AspNetCore;
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
@ -39,10 +40,9 @@ builder.Services.AddDefaultCommandDiscovery();
|
|||||||
builder.Services.AddDefaultQueryDiscovery();
|
builder.Services.AddDefaultQueryDiscovery();
|
||||||
builder.Services.AddFluentValidation();
|
builder.Services.AddFluentValidation();
|
||||||
builder.Services.AddModule<AppModule>();
|
builder.Services.AddModule<AppModule>();
|
||||||
|
builder.Services.AddHttpClient();
|
||||||
builder.Services.AddDefaultCommandDiscovery();
|
builder.Services.AddDefaultCommandDiscovery();
|
||||||
builder.Services.AddDefaultQueryDiscovery();
|
builder.Services.AddDefaultQueryDiscovery();
|
||||||
|
|
||||||
if (builder.Configuration.GetValue<bool>("Swagger:Enable"))
|
if (builder.Configuration.GetValue<bool>("Swagger:Enable"))
|
||||||
{
|
{
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
@ -18,5 +18,19 @@
|
|||||||
"TokenUrl": "",
|
"TokenUrl": "",
|
||||||
"ClientId": "",
|
"ClientId": "",
|
||||||
"ClientSecret": ""
|
"ClientSecret": ""
|
||||||
|
},
|
||||||
|
"CoinMarketCap": {
|
||||||
|
"ApiUrl": "",
|
||||||
|
"ApiKey": ""
|
||||||
|
|
||||||
|
},
|
||||||
|
"CoinGecko": {
|
||||||
|
"ApiUrl": "",
|
||||||
|
"ApiKey": ""
|
||||||
|
|
||||||
|
},
|
||||||
|
"HydroQuebec": {
|
||||||
|
"ApiUrl": ""
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\CH.Authority\CH.Authority.csproj" />
|
<ProjectReference Include="..\CH.Authority\CH.Authority.csproj" />
|
||||||
|
<ProjectReference Include="..\CH.CryptoStats.CoinGecko\CH.CryptoStats.CoinGecko.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" />
|
<ProjectReference Include="..\CH.Dal\CH.Dal.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
28
CH.CQRS/Command/CryptoStats/GetCryptoStatsCommand.cs
Normal file
28
CH.CQRS/Command/CryptoStats/GetCryptoStatsCommand.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using CH.CQRS.Service.CryptoStats;
|
||||||
|
using CH.CQRS.Service.User;
|
||||||
|
using FluentValidation;
|
||||||
|
using OpenHarbor.CQRS.Abstractions;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CH.CQRS.Command.CryptoStats;
|
||||||
|
|
||||||
|
public class GetCryptoStatsCommand
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public class GetCryptoStatsCommandHandler(CryptoService cryptoService) : ICommandHandler<GetCryptoStatsCommand>
|
||||||
|
{
|
||||||
|
public Task HandleAsync(GetCryptoStatsCommand command, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return cryptoService.GetCryptoStatsAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class GetCryptoStatsCommandValidator : AbstractValidator<GetCryptoStatsCommand>
|
||||||
|
{
|
||||||
|
public GetCryptoStatsCommandValidator()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
13
CH.CQRS/Command/CryptoStats/ServiceCollectionExtension.cs
Normal file
13
CH.CQRS/Command/CryptoStats/ServiceCollectionExtension.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using OpenHarbor.CQRS.FluentValidation;
|
||||||
|
|
||||||
|
namespace CH.CQRS.Command.CryptoStats;
|
||||||
|
|
||||||
|
public static class ServiceCollectionExtension
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddCryptoCommand(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddCommand<GetCryptoStatsCommand, GetCryptoStatsCommandHandler, GetCryptoStatsCommandValidator>();
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using CH.CQRS.Command.User;
|
using CH.CQRS.Command.CryptoStats;
|
||||||
|
using CH.CQRS.Command.User;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using PoweredSoft.Module.Abstractions;
|
using PoweredSoft.Module.Abstractions;
|
||||||
using System;
|
using System;
|
||||||
@ -13,6 +14,7 @@ public class CommandModule : IModule
|
|||||||
public IServiceCollection ConfigureServices(IServiceCollection services)
|
public IServiceCollection ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddUserCommand();
|
services.AddUserCommand();
|
||||||
|
services.AddCryptoCommand();
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
13
CH.CQRS/Service/CryptoStats/CryptoService.cs
Normal file
13
CH.CQRS/Service/CryptoStats/CryptoService.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
using CH.CryptoStats.CoinGecko;
|
||||||
|
using CH.CryptoStats.CoinMarketCap;
|
||||||
|
|
||||||
|
namespace CH.CQRS.Service.CryptoStats;
|
||||||
|
|
||||||
|
public class CryptoService(CoinGeckoService coinGecko)
|
||||||
|
{
|
||||||
|
public async Task GetCryptoStatsAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var crypto = await coinGecko.GetCryptoStatsAsync("bitcoin", "cad", cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
using CH.CQRS.Service.User;
|
using CH.CQRS.Service.CryptoStats;
|
||||||
|
using CH.CQRS.Service.User;
|
||||||
|
using CH.CryptoStats.Abstractions;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using PoweredSoft.Module.Abstractions;
|
using PoweredSoft.Module.Abstractions;
|
||||||
|
|
||||||
@ -8,6 +10,7 @@ public class SharedModule : IModule
|
|||||||
public IServiceCollection ConfigureServices(IServiceCollection services)
|
public IServiceCollection ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddScoped<UserService>();
|
services.AddScoped<UserService>();
|
||||||
|
services.AddScoped<CryptoService>();
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
18
CH.CryptoStats.CoinGecko/CH.CryptoStats.CoinGecko.csproj
Normal file
18
CH.CryptoStats.CoinGecko/CH.CryptoStats.CoinGecko.csproj
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="FluentValidation" Version="10.4.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.2" />
|
||||||
|
<PackageReference Include="OpenHarbor.CQRS.DynamicQuery.Abstractions" Version="8.0.0-preview.6" />
|
||||||
|
<PackageReference Include="PoweredSoft.Data.Core" Version="3.0.0" />
|
||||||
|
<PackageReference Include="PoweredSoft.Module.Abstractions" Version="2.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\CH.CryptoStats\CH.CryptoStats.Abstractions.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
24
CH.CryptoStats.CoinGecko/CoinGeckoEntity.cs
Normal file
24
CH.CryptoStats.CoinGecko/CoinGeckoEntity.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
namespace CH.CryptoStats.CoinGecko;
|
||||||
|
public class CoinGeckoEntity
|
||||||
|
{
|
||||||
|
[JsonPropertyName("symbol")]
|
||||||
|
public required string Symbol { get; set; }
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public required string Name { get; set; }
|
||||||
|
[JsonPropertyName("current_price")]
|
||||||
|
public decimal Price { get; set; }
|
||||||
|
[JsonPropertyName("market_cap")]
|
||||||
|
public decimal MarketCap { get; set; }
|
||||||
|
[JsonPropertyName("fully_diluted_valuation")]
|
||||||
|
public decimal FullyDilutedValuation { get; set; }
|
||||||
|
[JsonPropertyName("circulating_supply")]
|
||||||
|
public decimal CirculatingSupply { get; set; }
|
||||||
|
[JsonPropertyName("total_supply")]
|
||||||
|
public decimal TotalSupply { get; set; }
|
||||||
|
[JsonPropertyName("max_supply")]
|
||||||
|
public decimal MaxSupply { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("last_updated")]
|
||||||
|
public DateTime LastUpdated { get; set; }
|
||||||
|
}
|
15
CH.CryptoStats.CoinGecko/CoinGeckoModule.cs
Normal file
15
CH.CryptoStats.CoinGecko/CoinGeckoModule.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using OpenHarbor.CQRS.DynamicQuery.Abstractions;
|
||||||
|
using PoweredSoft.Data.Core;
|
||||||
|
using PoweredSoft.Module.Abstractions;
|
||||||
|
|
||||||
|
namespace CH.CryptoStats.CoinGecko;
|
||||||
|
|
||||||
|
public class CoinGeckoModule : IModule
|
||||||
|
{
|
||||||
|
public IServiceCollection ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddScoped<CoinGeckoService>();
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
38
CH.CryptoStats.CoinGecko/CoinGeckoService.cs
Normal file
38
CH.CryptoStats.CoinGecko/CoinGeckoService.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using CH.CryptoStats.Abstractions;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Text.Json;
|
||||||
|
using CH.Energy.Abstractions.Enum;
|
||||||
|
|
||||||
|
namespace CH.CryptoStats.CoinGecko;
|
||||||
|
|
||||||
|
public class CoinGeckoService(IConfiguration configuration, HttpClient httpClient) : ICryptoStats
|
||||||
|
{
|
||||||
|
public async Task<Abstractions.CryptoStats> GetCryptoStatsAsync(string cryptoName, string currency, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var apiKey = configuration.GetValue<string>("CoinGecko:ApiKey");
|
||||||
|
var apiUrl = configuration.GetValue<string>("CoinGecko:ApiUrl");
|
||||||
|
var response = await httpClient.GetAsync($"{apiUrl}?ids={cryptoName}&vs_currency={currency}&x_cg_demo_api_key={apiKey}",cancellationToken);
|
||||||
|
var jsonResponse = await response.Content.ReadFromJsonAsync<List<CoinGeckoEntity>>(cancellationToken);
|
||||||
|
return ParseCryptoStats(jsonResponse.FirstOrDefault(), currency, cancellationToken).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task<Abstractions.CryptoStats> ParseCryptoStats(CoinGeckoEntity coinGeckoEntity, string currency, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
|
||||||
|
var cryptoStats = new Abstractions.CryptoStats
|
||||||
|
{
|
||||||
|
Name = coinGeckoEntity.Name,
|
||||||
|
Symbol = coinGeckoEntity.Symbol,
|
||||||
|
MaxSupply = coinGeckoEntity.MaxSupply,
|
||||||
|
CirculatingSupply = coinGeckoEntity.CirculatingSupply,
|
||||||
|
TotalSupply = coinGeckoEntity.TotalSupply,
|
||||||
|
Currency = (Currency)System.Enum.Parse(typeof(Currency), currency.ToUpper()),
|
||||||
|
UpdatedAt = coinGeckoEntity.LastUpdated,
|
||||||
|
Price = coinGeckoEntity.Price,
|
||||||
|
MarketCap = coinGeckoEntity.MarketCap,
|
||||||
|
FullyDilutedMarketCap = coinGeckoEntity.FullyDilutedValuation
|
||||||
|
};
|
||||||
|
return Task.FromResult(cryptoStats);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="FluentValidation" Version="10.4.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.2" />
|
||||||
|
<PackageReference Include="OpenHarbor.CQRS.DynamicQuery.Abstractions" Version="8.0.0-preview.6" />
|
||||||
|
<PackageReference Include="PoweredSoft.Data.Core" Version="3.0.0" />
|
||||||
|
<PackageReference Include="PoweredSoft.Module.Abstractions" Version="2.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\CH.CryptoStats\CH.CryptoStats.Abstractions.csproj" />
|
||||||
|
<ProjectReference Include="..\CH.Enum\CH.Enum.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
56
CH.CryptoStats.CoinMarketCap/CoinMarketCapEntity.cs
Normal file
56
CH.CryptoStats.CoinMarketCap/CoinMarketCapEntity.cs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
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 required string Name { get; set; }
|
||||||
|
[JsonPropertyName("symbol")]
|
||||||
|
public required 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
|
||||||
|
{
|
||||||
|
[JsonPropertyName("data")]
|
||||||
|
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; }
|
||||||
|
}
|
15
CH.CryptoStats.CoinMarketCap/CoinMarketCapModule.cs
Normal file
15
CH.CryptoStats.CoinMarketCap/CoinMarketCapModule.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using OpenHarbor.CQRS.DynamicQuery.Abstractions;
|
||||||
|
using PoweredSoft.Data.Core;
|
||||||
|
using PoweredSoft.Module.Abstractions;
|
||||||
|
|
||||||
|
namespace CH.CryptoStats.CoinMarketCap;
|
||||||
|
|
||||||
|
public class CoinMarketCapModule : IModule
|
||||||
|
{
|
||||||
|
public IServiceCollection ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddScoped<CoinMarketCapService>();
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
42
CH.CryptoStats.CoinMarketCap/CoinMarketCapService.cs
Normal file
42
CH.CryptoStats.CoinMarketCap/CoinMarketCapService.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
using CH.CryptoStats.Abstractions;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Text.Json;
|
||||||
|
using CH.Energy.Abstractions.Enum;
|
||||||
|
|
||||||
|
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 quoteData = coinMarketCapEntity.Quote.CAD ?? coinMarketCapEntity.Quote.USD;
|
||||||
|
var cryptoStats = new Abstractions.CryptoStats
|
||||||
|
{
|
||||||
|
Name = coinMarketCapEntity.Name,
|
||||||
|
Symbol = coinMarketCapEntity.Symbol,
|
||||||
|
MaxSupply = coinMarketCapEntity.MaxSupply,
|
||||||
|
CirculatingSupply = coinMarketCapEntity.CirculatingSupply,
|
||||||
|
TotalSupply = coinMarketCapEntity.TotalSupply,
|
||||||
|
Currency = (Currency)System.Enum.Parse(typeof(Currency), currency.ToUpper()),
|
||||||
|
UpdatedAt = DateTime.Parse(coinMarketCapEntity.LastUpdated),
|
||||||
|
Price = quoteData.Price,
|
||||||
|
Volume24H = quoteData.Volume24H,
|
||||||
|
VolumeChange24H = quoteData.VolumeChange24H,
|
||||||
|
MarketCap = quoteData.MarketCap,
|
||||||
|
MarketCapDominance = quoteData.MarketCapDominance,
|
||||||
|
FullyDilutedMarketCap = quoteData.FullyDilutedMarketCap
|
||||||
|
};
|
||||||
|
return Task.FromResult(cryptoStats);
|
||||||
|
}
|
||||||
|
}
|
18
CH.CryptoStats/CH.CryptoStats.Abstractions.csproj
Normal file
18
CH.CryptoStats/CH.CryptoStats.Abstractions.csproj
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="FluentValidation" Version="10.4.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.2" />
|
||||||
|
<PackageReference Include="OpenHarbor.CQRS.DynamicQuery.Abstractions" Version="8.0.0-preview.6" />
|
||||||
|
<PackageReference Include="PoweredSoft.Data.Core" Version="3.0.0" />
|
||||||
|
<PackageReference Include="PoweredSoft.Module.Abstractions" Version="2.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\CH.Enum\CH.Enum.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
25
CH.CryptoStats/CryptoStats.cs
Normal file
25
CH.CryptoStats/CryptoStats.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using CH.Energy.Abstractions.Enum;
|
||||||
|
|
||||||
|
namespace CH.CryptoStats.Abstractions;
|
||||||
|
|
||||||
|
public class CryptoStats
|
||||||
|
{
|
||||||
|
public required string Name { get; set; }
|
||||||
|
public required string Symbol { get; set; }
|
||||||
|
public decimal MaxSupply { get; set; }
|
||||||
|
public decimal CirculatingSupply { get; set; }
|
||||||
|
public decimal TotalSupply { get; set; }
|
||||||
|
public required Currency Currency { get; set; }
|
||||||
|
public DateTime UpdatedAt { get; set; }
|
||||||
|
public decimal Price { get; set; }
|
||||||
|
public decimal Volume24H { get; set; }
|
||||||
|
public decimal VolumeChange24H { get; set; }
|
||||||
|
public decimal MarketCap { get; set; }
|
||||||
|
public decimal MarketCapDominance { get; set; }
|
||||||
|
public decimal FullyDilutedMarketCap { get; set; }
|
||||||
|
}
|
13
CH.CryptoStats/ICryptoStats.cs
Normal file
13
CH.CryptoStats/ICryptoStats.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
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> GetCryptoStatsAsync(string cryptoName, string currency, CancellationToken cancellationToken);
|
||||||
|
}
|
9
CH.Energy.Abstractions/CH.Energy.Abstractions.csproj
Normal file
9
CH.Energy.Abstractions/CH.Energy.Abstractions.csproj
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
14
CH.Energy.Abstractions/EnergyPeak.cs
Normal file
14
CH.Energy.Abstractions/EnergyPeak.cs
Normal 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; }
|
||||||
|
}
|
12
CH.Energy.Abstractions/IEnergyStats.cs
Normal file
12
CH.Energy.Abstractions/IEnergyStats.cs
Normal 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);
|
||||||
|
}
|
9
CH.Energy.HydroQuebec/CH.Energy.HydroQuebec.csproj
Normal file
9
CH.Energy.HydroQuebec/CH.Energy.HydroQuebec.csproj
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
9
CH.Enum/CH.Enum.csproj
Normal file
9
CH.Enum/CH.Enum.csproj
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
7
CH.Enum/Currency.cs
Normal file
7
CH.Enum/Currency.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace CH.Energy.Abstractions.Enum;
|
||||||
|
|
||||||
|
public enum Currency
|
||||||
|
{
|
||||||
|
USD,
|
||||||
|
CAD,
|
||||||
|
}
|
@ -11,6 +11,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CH.CQRS", "CH.CQRS\CH.CQRS.
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CH.Authority", "CH.Authority\CH.Authority.csproj", "{2B26A5F6-B78D-418F-A28D-80E7E9CD5428}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CH.Authority", "CH.Authority\CH.Authority.csproj", "{2B26A5F6-B78D-418F-A28D-80E7E9CD5428}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CH.CryptoStats.Abstractions", "CH.CryptoStats\CH.CryptoStats.Abstractions.csproj", "{5AD75A8F-D4C5-4748-8624-FB65EA417E62}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CH.CryptoStats.CoinMarketCap", "CH.CryptoStats.CoinMarketCap\CH.CryptoStats.CoinMarketCap.csproj", "{E12AC021-8B7E-4451-BB41-59291230E224}"
|
||||||
|
EndProject
|
||||||
|
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
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CH.Enum", "CH.Enum\CH.Enum.csproj", "{45E17ADC-A1C9-4EE0-BA6E-A4B52F0621BD}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -33,6 +45,30 @@ Global
|
|||||||
{2B26A5F6-B78D-418F-A28D-80E7E9CD5428}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{2B26A5F6-B78D-418F-A28D-80E7E9CD5428}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{2B26A5F6-B78D-418F-A28D-80E7E9CD5428}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{2B26A5F6-B78D-418F-A28D-80E7E9CD5428}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{2B26A5F6-B78D-418F-A28D-80E7E9CD5428}.Release|Any CPU.Build.0 = Release|Any CPU
|
{2B26A5F6-B78D-418F-A28D-80E7E9CD5428}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{5AD75A8F-D4C5-4748-8624-FB65EA417E62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{5AD75A8F-D4C5-4748-8624-FB65EA417E62}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{5AD75A8F-D4C5-4748-8624-FB65EA417E62}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{5AD75A8F-D4C5-4748-8624-FB65EA417E62}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E12AC021-8B7E-4451-BB41-59291230E224}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E12AC021-8B7E-4451-BB41-59291230E224}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E12AC021-8B7E-4451-BB41-59291230E224}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E12AC021-8B7E-4451-BB41-59291230E224}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{AAF92179-CDA7-4711-89C0-E14445B5FFBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{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
|
||||||
|
{45E17ADC-A1C9-4EE0-BA6E-A4B52F0621BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{45E17ADC-A1C9-4EE0-BA6E-A4B52F0621BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{45E17ADC-A1C9-4EE0-BA6E-A4B52F0621BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{45E17ADC-A1C9-4EE0-BA6E-A4B52F0621BD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
Loading…
Reference in New Issue
Block a user